Mercurial > libervia-backend
diff sat/plugins/plugin_pubsub_attachments.py @ 3869:c0bcbcf5b4b7
component AP gateway: handle `Like` and `Undo`/`Like` activities:
rel 370
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 21 Jul 2022 18:07:35 +0200 |
parents | ac255a0fbd4c |
children |
line wrap: on
line diff
--- a/sat/plugins/plugin_pubsub_attachments.py Thu Jul 21 18:05:20 2022 +0200 +++ b/sat/plugins/plugin_pubsub_attachments.py Thu Jul 21 18:07:35 2022 +0200 @@ -61,7 +61,7 @@ host.registerNamespace("pubsub-attachments", NS_PUBSUB_ATTACHMENTS) self.host = host self._p = host.plugins["XEP-0060"] - self.handlers = {} + self.handlers: Dict[Tuple[str, str], dict[str, Any]] = {} host.trigger.add("XEP-0277_send", self.onMBSend) self.registerAttachmentHandler( "noticed", NS_PUBSUB_ATTACHMENTS, self.noticedGet, self.noticedSet @@ -270,12 +270,73 @@ ) -> None: client = self.host.getClient(profile_key) attachments = data_format.deserialise(attachments_s) or {} - return defer.ensureDeferred(self.setAttachments( client, attachments)) + return defer.ensureDeferred(self.setAttachments(client, attachments)) + + def applySetHandler( + self, + client: SatXMPPEntity, + attachments_data: dict, + item_elt: Optional[domish.Element], + handlers: Optional[List[Tuple[str, str]]] = None, + from_jid: Optional[jid.JID] = None, + ) -> domish.Element: + """Apply all ``set`` callbacks to an attachments item + + @param attachments_data: data describing the attachments + ``extra`` key will be used, and created if not found + @param from_jid: jid of the author of the attachments + ``client.jid.userhostJID()`` will be used if not specified + @param item_elt: item containing an <attachments> element + will be modified in place + if None, a new element will be created + @param handlers: list of (name, namespace) of handlers to use. + if None, all registered handlers will be used. + @return: updated item_elt if given, otherwise a new item_elt + """ + attachments_data.setdefault("extra", {}) + if item_elt is None: + item_id = client.jid.userhost() if from_jid is None else from_jid.userhost() + item_elt = pubsub.Item(item_id) + item_elt.addElement((NS_PUBSUB_ATTACHMENTS, "attachments")) + + try: + attachments_elt = next( + item_elt.elements(NS_PUBSUB_ATTACHMENTS, "attachments") + ) + except StopIteration: + log.warning( + f"no <attachments> element found, creating a new one: {item_elt.toXml()}" + ) + attachments_elt = item_elt.addElement((NS_PUBSUB_ATTACHMENTS, "attachments")) + + if handlers is None: + handlers = list(self.handlers.keys()) + + for name, namespace in handlers: + try: + handler = self.handlers[(name, namespace)] + except KeyError: + log.error( + f"unregistered handler ({name!r}, {namespace!r}) is requested, " + "ignoring" + ) + continue + try: + former_elt = next(attachments_elt.elements(namespace, name)) + except StopIteration: + former_elt = None + new_elt = handler["set"](client, attachments_data, former_elt) + if new_elt != former_elt: + if former_elt is not None: + attachments_elt.children.remove(former_elt) + if new_elt is not None: + attachments_elt.addChild(new_elt) + return item_elt async def setAttachments( self, client: SatXMPPEntity, - data: Dict[str, Any] + attachments_data: Dict[str, Any] ) -> None: """Set or update attachments @@ -287,51 +348,39 @@ used in attachments where "update" makes sense (e.g. it's used for "reactions" but not for "noticed"). - @param data: microblog data data. Various keys (usually stored in - data["extra"]) may be used depending on the attachments handlers - registered. The keys "service", "node" and "id" MUST be set. + @param attachments_data: data describing attachments. Various keys (usually stored + in attachments_data["extra"]) may be used depending on the attachments + handlers registered. The keys "service", "node" and "id" MUST be set. + ``attachments_data`` is thought to be compatible with microblog data. + """ - data.setdefault("extra", {}) try: - service = jid.JID(data["service"]) - node = data["node"] - item = data["id"] + service = jid.JID(attachments_data["service"]) + node = attachments_data["node"] + item = attachments_data["id"] except (KeyError, RuntimeError): raise ValueError( 'data must have "service", "node" and "id" set' ) attachment_node = self.getAttachmentNodeName(service, node, item) - items, __ = await self._p.getItems( - client, service, attachment_node, item_ids=[client.jid.userhost()] - ) - if not items: - # the item doesn't exist, we create a new one - item_elt = pubsub.Item(client.jid.userhost()) - item_elt.addElement((NS_PUBSUB_ATTACHMENTS, "attachments")) - else: - item_elt = items[0] - try: - attachments_elt = next( - item_elt.elements(NS_PUBSUB_ATTACHMENTS, "attachments") + items, __ = await self._p.getItems( + client, service, attachment_node, item_ids=[client.jid.userhost()] ) - except StopIteration: - log.warning( - f"no <attachments> element found, creating a new one: {item_elt.toXml()}" - ) - attachments_elt = item_elt.addElement((NS_PUBSUB_ATTACHMENTS, "attachments")) + except exceptions.NotFound: + item_elt = None + else: + if not items: + item_elt = None + else: + item_elt = items[0] - for (name, namespace), handler in self.handlers.items(): - try: - former_elt = next(attachments_elt.elements(namespace, name)) - except StopIteration: - former_elt = None - new_elt = handler["set"](client, data, former_elt) - if new_elt != former_elt: - if former_elt is not None: - attachments_elt.children.remove(former_elt) - if new_elt is not None: - attachments_elt.addChild(new_elt) + item_elt = self.applySetHandler( + client, + attachments_data, + item_elt=item_elt, + ) + try: await self._p.sendItems(client, service, attachment_node, [item_elt]) except error.StanzaError as e: