component AP gateway: handle Like and Undo/Like activities:

rel 370
This commit is contained in:
Goffi 2022-07-21 18:07:35 +02:00
commit 9089a6494e

View file

@ -61,7 +61,7 @@ class PubsubAttachments:
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,46 +270,34 @@ class PubsubAttachments:
) -> 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))
async def setAttachments(
def applySetHandler(
self,
client: SatXMPPEntity,
data: Dict[str, Any]
) -> None:
"""Set or update attachments
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
Former <attachments> element will be retrieved and updated. Individual
attachments replace or update their elements individually, according to the
"operation" key.
"operation" key may be "update" or "replace", and defaults to update, it is only
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 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
"""
data.setdefault("extra", {})
try:
service = jid.JID(data["service"])
node = data["node"]
item = 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())
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"))
else:
item_elt = items[0]
try:
attachments_elt = next(
@ -321,17 +309,78 @@ class PubsubAttachments:
)
attachments_elt = item_elt.addElement((NS_PUBSUB_ATTACHMENTS, "attachments"))
for (name, namespace), handler in self.handlers.items():
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, data, former_elt)
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,
attachments_data: Dict[str, Any]
) -> None:
"""Set or update attachments
Former <attachments> element will be retrieved and updated. Individual
attachments replace or update their elements individually, according to the
"operation" key.
"operation" key may be "update" or "replace", and defaults to update, it is only
used in attachments where "update" makes sense (e.g. it's used for "reactions"
but not for "noticed").
@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.
"""
try:
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)
try:
items, __ = await self._p.getItems(
client, service, attachment_node, item_ids=[client.jid.userhost()]
)
except exceptions.NotFound:
item_elt = None
else:
if not items:
item_elt = None
else:
item_elt = items[0]
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: