comparison sat/plugins/plugin_xep_0470.py @ 3956:3cb9ade2ab84

plugin pubsub signing: pubsub items signature implementation: - this is based on a protoXEP, not yet an official XEP: https://github.com/xsf/xeps/pull/1228 - XEP-0470: `set` attachment handler can now be async rel 381
author Goffi <goffi@goffi.org>
date Fri, 28 Oct 2022 18:47:17 +0200
parents 2b2856ae5eeb
children 722c25818778
comparison
equal deleted inserted replaced
3955:323017a4e4d2 3956:3cb9ade2ab84
28 from sat.core.i18n import _ 28 from sat.core.i18n import _
29 from sat.core.log import getLogger 29 from sat.core.log import getLogger
30 from sat.core.core_types import SatXMPPEntity 30 from sat.core.core_types import SatXMPPEntity
31 from sat.core import exceptions 31 from sat.core import exceptions
32 from sat.tools.common import uri, data_format, date_utils 32 from sat.tools.common import uri, data_format, date_utils
33 from sat.tools.utils import xmpp_date 33 from sat.tools.utils import asDeferred, xmpp_date
34 34
35 35
36 log = getLogger(__name__) 36 log = getLogger(__name__)
37 37
38 IMPORT_NAME = "XEP-0470" 38 IMPORT_NAME = "XEP-0470"
61 host.registerNamespace("pubsub-attachments", NS_PUBSUB_ATTACHMENTS) 61 host.registerNamespace("pubsub-attachments", NS_PUBSUB_ATTACHMENTS)
62 self.host = host 62 self.host = host
63 self._p = host.plugins["XEP-0060"] 63 self._p = host.plugins["XEP-0060"]
64 self.handlers: Dict[Tuple[str, str], dict[str, Any]] = {} 64 self.handlers: Dict[Tuple[str, str], dict[str, Any]] = {}
65 host.trigger.add("XEP-0277_send", self.onMBSend) 65 host.trigger.add("XEP-0277_send", self.onMBSend)
66 self.registerAttachmentHandler( 66 self.register_attachment_handler(
67 "noticed", NS_PUBSUB_ATTACHMENTS, self.noticedGet, self.noticedSet 67 "noticed", NS_PUBSUB_ATTACHMENTS, self.noticedGet, self.noticedSet
68 ) 68 )
69 self.registerAttachmentHandler( 69 self.register_attachment_handler(
70 "reactions", NS_PUBSUB_ATTACHMENTS, self.reactionsGet, self.reactionsSet 70 "reactions", NS_PUBSUB_ATTACHMENTS, self.reactionsGet, self.reactionsSet
71 ) 71 )
72 host.bridge.addMethod( 72 host.bridge.addMethod(
73 "psAttachmentsGet", 73 "psAttachmentsGet",
74 ".plugin", 74 ".plugin",
87 ) 87 )
88 88
89 def getHandler(self, client): 89 def getHandler(self, client):
90 return PubsubAttachments_Handler() 90 return PubsubAttachments_Handler()
91 91
92 def registerAttachmentHandler( 92 def register_attachment_handler(
93 self, 93 self,
94 name: str, 94 name: str,
95 namespace: str, 95 namespace: str,
96 get_cb: Callable[ 96 get_cb: Callable[
97 [SatXMPPEntity, domish.Element, Dict[str, Any]], 97 [SatXMPPEntity, domish.Element, Dict[str, Any]],
111 parsed data 111 parsed data
112 @param set: method to call when the attachment need to be set or udpated 112 @param set: method to call when the attachment need to be set or udpated
113 it will be called with (client, data, former_elt of None if there was no 113 it will be called with (client, data, former_elt of None if there was no
114 former element). When suitable, ``operation`` should be used to check if we 114 former element). When suitable, ``operation`` should be used to check if we
115 request an ``update`` or a ``replace``. 115 request an ``update`` or a ``replace``.
116 The callback can be either a blocking method, a Deferred or a coroutine
116 """ 117 """
117 key = (name, namespace) 118 key = (name, namespace)
118 if key in self.handlers: 119 if key in self.handlers:
119 raise exceptions.ConflictError( 120 raise exceptions.ConflictError(
120 f"({name}, {namespace}) attachment handlers are already registered" 121 f"({name}, {namespace}) attachment handlers are already registered"
297 @param extra: extra data, will be used as ``extra`` argument when doing 298 @param extra: extra data, will be used as ``extra`` argument when doing
298 ``getItems`` call. 299 ``getItems`` call.
299 @return: A tuple with: 300 @return: A tuple with:
300 - the list of attachments data, one item per found sender. The attachments 301 - the list of attachments data, one item per found sender. The attachments
301 data are dict containing attachment, no ``extra`` field is used here 302 data are dict containing attachment, no ``extra`` field is used here
302 (contrarily to attachments data used with ``setAttachments``). 303 (contrarily to attachments data used with ``set_attachements``).
303 - metadata returned by the call to ``getItems`` 304 - metadata returned by the call to ``getItems``
304 """ 305 """
305 if extra is None: 306 if extra is None:
306 extra = {} 307 extra = {}
307 attachment_node = self.getAttachmentNodeName(service, node, item) 308 attachment_node = self.getAttachmentNodeName(service, node, item)
318 attachments_s: str, 319 attachments_s: str,
319 profile_key: str 320 profile_key: str
320 ) -> None: 321 ) -> None:
321 client = self.host.getClient(profile_key) 322 client = self.host.getClient(profile_key)
322 attachments = data_format.deserialise(attachments_s) or {} 323 attachments = data_format.deserialise(attachments_s) or {}
323 return defer.ensureDeferred(self.setAttachments(client, attachments)) 324 return defer.ensureDeferred(self.set_attachements(client, attachments))
324 325
325 def applySetHandler( 326 async def apply_set_handler(
326 self, 327 self,
327 client: SatXMPPEntity, 328 client: SatXMPPEntity,
328 attachments_data: dict, 329 attachments_data: dict,
329 item_elt: Optional[domish.Element], 330 item_elt: Optional[domish.Element],
330 handlers: Optional[List[Tuple[str, str]]] = None, 331 handlers: Optional[List[Tuple[str, str]]] = None,
373 continue 374 continue
374 try: 375 try:
375 former_elt = next(attachments_elt.elements(namespace, name)) 376 former_elt = next(attachments_elt.elements(namespace, name))
376 except StopIteration: 377 except StopIteration:
377 former_elt = None 378 former_elt = None
378 new_elt = handler["set"](client, attachments_data, former_elt) 379 new_elt = await asDeferred(
380 handler["set"], client, attachments_data, former_elt
381 )
379 if new_elt != former_elt: 382 if new_elt != former_elt:
380 if former_elt is not None: 383 if former_elt is not None:
381 attachments_elt.children.remove(former_elt) 384 attachments_elt.children.remove(former_elt)
382 if new_elt is not None: 385 if new_elt is not None:
383 attachments_elt.addChild(new_elt) 386 attachments_elt.addChild(new_elt)
384 return item_elt 387 return item_elt
385 388
386 async def setAttachments( 389 async def set_attachements(
387 self, 390 self,
388 client: SatXMPPEntity, 391 client: SatXMPPEntity,
389 attachments_data: Dict[str, Any] 392 attachments_data: Dict[str, Any]
390 ) -> None: 393 ) -> None:
391 """Set or update attachments 394 """Set or update attachments
423 if not items: 426 if not items:
424 item_elt = None 427 item_elt = None
425 else: 428 else:
426 item_elt = items[0] 429 item_elt = items[0]
427 430
428 item_elt = self.applySetHandler( 431 item_elt = await self.apply_set_handler(
429 client, 432 client,
430 attachments_data, 433 attachments_data,
431 item_elt=item_elt, 434 item_elt=item_elt,
432 ) 435 )
433 436