diff sat/plugins/plugin_xep_0060.py @ 2800:3b68293a60d4

plugin XEP-0060: added sendItems/psItemsSend method to publish several items at once
author Goffi <goffi@goffi.org>
date Fri, 15 Feb 2019 22:13:20 +0100
parents 838f53730ce4
children ae127e14b040
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0060.py	Wed Feb 06 09:10:31 2019 +0100
+++ b/sat/plugins/plugin_xep_0060.py	Fri Feb 15 22:13:20 2019 +0100
@@ -29,6 +29,7 @@
 from twisted.internet import reactor, defer
 from wokkel import disco
 from wokkel import data_form
+from wokkel import generic
 from zope.interface import implements
 from collections import namedtuple
 import urllib
@@ -191,6 +192,14 @@
             async=True,
         )
         host.bridge.addMethod(
+            "psItemsSend",
+            ".plugin",
+            in_sign="ssasa{ss}s",
+            out_sign="as",
+            method=self._sendItems,
+            async=True,
+        )
+        host.bridge.addMethod(
             "psRetractItem",
             ".plugin",
             in_sign="sssbs",
@@ -439,10 +448,25 @@
         d.addCallback(lambda ret: ret or u"")
         return d
 
+    def _sendItems(self, service, nodeIdentifier, items, extra=None,
+                  profile_key=C.PROF_KEY_NONE):
+        client = self.host.getClient(profile_key)
+        service = None if not service else jid.JID(service)
+        try:
+            items = [generic.parseXml(item.encode('utf-8')) for item in items]
+        except Exception as e:
+            raise exceptions.DataError(_(u"Can't parse items: {msg}").format(
+                msg=e))
+        d = self.sendItems(
+            client, service, nodeIdentifier, items, extra
+        )
+        return d
+
     def _getPublishedItemId(self, iq_elt, original_id):
         """return item of published id if found in answer
 
-        if not found original_id is returned, or empty string if it is None or empty string
+        if not found original_id is returned, or empty string if it is None or empty
+            string
         """
         try:
             item_id = iq_elt.pubsub.publish.item["id"]
@@ -450,16 +474,15 @@
             item_id = None
         return item_id or original_id
 
-    def sendItem(
-        self, client, service, nodeIdentifier, payload, item_id=None, extra=None
-    ):
-        """high level method to send one item
+    def sendItem(self, client, service, nodeIdentifier, payload, item_id=None,
+                 extra=None):
+        """High level method to send one item
 
         @param service(jid.JID, None): service to send the item to
             None to use PEP
         @param NodeIdentifier(unicode): PubSub node to use
+        @param payload(domish.Element, unicode): payload of the item to send
         @param item_id(unicode, None): id to use or None to create one
-        @param payload(domish.Element, unicode): payload of the item to send
         @param extra(dict, None): extra option, not used yet
         @return (unicode, None): id of the created item
         """
@@ -468,6 +491,36 @@
         d.addCallback(self._getPublishedItemId, item_id)
         return d
 
+    def _publishCb(self, iq_result):
+        """Parse publish result, and return ids given by pubsub service"""
+        try:
+            item_ids = [item['id']
+                for item in iq_result.pubsub.publish.elements(pubsub.NS_PUBSUB, u'item')]
+        except AttributeError:
+            return []
+        return item_ids
+
+    def sendItems(self, client, service, nodeIdentifier, items, extra=None):
+        """High level method to send several items at once
+
+        @param service(jid.JID, None): service to send the item to
+            None to use PEP
+        @param NodeIdentifier(unicode): PubSub node to use
+        @param items(list[domish.Element]): whole item elements to send,
+            "id" will be used if set
+        @param extra(dict, None): extra option, not used yet
+        @return (list[unicode]): ids of the created items
+        """
+        parsed_items = []
+        for item in items:
+            if item.name != u'item':
+                raise exceptions.DataError(_(u"Invalid item: {xml}").format(item.toXml()))
+            item_id = item.getAttribute(u"id")
+            parsed_items.append(pubsub.Item(id=item_id, payload=item.firstChildElement()))
+        d = self.publish(client, service, nodeIdentifier, parsed_items)
+        d.addCallback(self._publishCb)
+        return d
+
     def publish(self, client, service, nodeIdentifier, items=None):
         return client.pubsub_client.publish(
             service, nodeIdentifier, items, client.pubsub_client.parent.jid