From 31807233c4b0a7cad61beba9c93d0df502e64f90 Mon Sep 17 00:00:00 2001 From: Thomas Sileo Date: Sat, 23 Jul 2022 23:06:30 +0200 Subject: [PATCH] Improvements on polls support --- app/admin.py | 13 +++++----- app/ap_object.py | 15 +++++++++++ app/boxes.py | 54 ++++++++++++++++++++++------------------ app/templates/utils.html | 36 +++++++++++++++++++-------- 4 files changed, 77 insertions(+), 41 deletions(-) diff --git a/app/admin.py b/app/admin.py index 706ac5b..91e5069 100644 --- a/app/admin.py +++ b/app/admin.py @@ -281,7 +281,7 @@ async def admin_inbox( ) -> templates.TemplateResponse: where = [ models.InboxObject.ap_type.not_in( - ["Accept", "Delete", "Create", "Update", "Undo", "Read"] + ["Accept", "Delete", "Create", "Update", "Undo", "Read", "Add", "Remove"] ), models.InboxObject.is_deleted.is_(False), ] @@ -695,12 +695,11 @@ async def admin_actions_vote( form_data = await request.form() names = form_data.getlist("name") logger.info(f"{names=}") - for name in names: - await boxes.send_vote( - db_session, - in_reply_to=in_reply_to, - name=name, - ) + await boxes.send_vote( + db_session, + in_reply_to=in_reply_to, + names=names, + ) return RedirectResponse(redirect_url, status_code=302) diff --git a/app/ap_object.py b/app/ap_object.py index bbcefc4..32584bd 100644 --- a/app/ap_object.py +++ b/app/ap_object.py @@ -11,6 +11,7 @@ from app.actor import LOCAL_ACTOR from app.actor import Actor from app.actor import RemoteActor from app.media import proxied_media_url +from app.utils.datetime import now from app.utils.datetime import parse_isoformat @@ -190,6 +191,20 @@ class Object: def has_ld_signature(self) -> bool: return bool(self.ap_object.get("signature")) + @property + def is_poll_ended(self) -> bool: + if "endTime" in self.ap_object: + return now() > parse_isoformat(self.ap_object["endTime"]) + return False + + @cached_property + def poll_items(self) -> list[ap.RawObject] | None: + return self.ap_object.get("oneOf") or self.ap_object.get("anyOf") + + @cached_property + def is_one_of_poll(self) -> bool: + return bool(self.ap_object.get("oneOf")) + def _to_camel(string: str) -> str: cased = "".join(word.capitalize() for word in string.split("_")) diff --git a/app/boxes.py b/app/boxes.py index b9ee147..1168a65 100644 --- a/app/boxes.py +++ b/app/boxes.py @@ -401,42 +401,48 @@ async def send_create( async def send_vote( db_session: AsyncSession, in_reply_to: str, - name: str, + names: list[str], ) -> str: - logger.info(f"Send vote {name}") - vote_id = allocate_outbox_id() + logger.info(f"Send vote {names}") published = now().replace(microsecond=0).isoformat().replace("+00:00", "Z") - in_reply_to_object = await get_anybox_object_by_ap_id(db_session, in_reply_to) + in_reply_to_object = await get_inbox_object_by_ap_id(db_session, in_reply_to) if not in_reply_to_object: raise ValueError(f"Invalid in reply to {in_reply_to=}") if not in_reply_to_object.ap_context: raise ValueError("Object has no context") context = in_reply_to_object.ap_context + # TODO: ensure the name are valid? + + # Save the answers + in_reply_to_object.voted_for_answers = names + to = [in_reply_to_object.actor.ap_id] - note = { - "@context": ap.AS_EXTENDED_CTX, - "type": "Note", - "id": outbox_object_id(vote_id), - "attributedTo": ID, - "name": name, - "to": to, - "cc": [], - "published": published, - "context": context, - "conversation": context, - "url": outbox_object_id(vote_id), - "inReplyTo": in_reply_to, - } - outbox_object = await save_outbox_object(db_session, vote_id, note) - if not outbox_object.id: - raise ValueError("Should never happen") + for name in names: + vote_id = allocate_outbox_id() + note = { + "@context": ap.AS_EXTENDED_CTX, + "type": "Note", + "id": outbox_object_id(vote_id), + "attributedTo": ID, + "name": name, + "to": to, + "cc": [], + "published": published, + "context": context, + "conversation": context, + "url": outbox_object_id(vote_id), + "inReplyTo": in_reply_to, + } + outbox_object = await save_outbox_object(db_session, vote_id, note) + if not outbox_object.id: + raise ValueError("Should never happen") - recipients = await _compute_recipients(db_session, note) - for rcp in recipients: - await new_outgoing_activity(db_session, rcp, outbox_object.id) + recipients = await _compute_recipients(db_session, note) + for rcp in recipients: + await new_outgoing_activity(db_session, rcp, outbox_object.id) await db_session.commit() return vote_id diff --git a/app/templates/utils.html b/app/templates/utils.html index a58636b..38058cc 100644 --- a/app/templates/utils.html +++ b/app/templates/utils.html @@ -292,24 +292,36 @@ {% endif %} {% if object.ap_type == "Question" %} - {% if object.is_from_inbox %} + {% if is_admin and object.is_from_inbox and not object.is_poll_ended and not object.voted_for_answers %}
{{ embed_csrf_token() }} {{ embed_redirect_url(object.permalink_id) }} {% endif %} - {% if object.ap_object.oneOf %} + {% if object.poll_items %} {% endif %} - {% if object.is_from_inbox %} + {% if can_vote %}

@@ -345,8 +357,12 @@ {% if object.ap_type == "Question" %} {% set endAt = object.ap_object.endTime | parse_datetime %} -
  • ends
  • -
  • {{ object.ap_object.votersCount }} voters
  • +
  • + {% if object.is_poll_ended %}ended{% else %}ends{% endif %} +
  • +
  • + {{ object.ap_object.votersCount }} voters +
  • {% endif %} {% if is_admin %}