changeset 2352:6c26f435a02d

plugin XEP-0060: added/fixed subscribe/unsubscribe and subscriptions methods/bridge methods: subscriptions now returns Subscription instances, and psSubscriptionsGet return dict with subscription data (node, subscriber, state)
author Goffi <goffi@goffi.org>
date Fri, 08 Sep 2017 07:57:57 +0200
parents 3c0a3fae1862
children ebc0dfe9c0ca
files src/plugins/plugin_xep_0060.py
diffstat 1 files changed, 55 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0060.py	Wed Sep 06 07:39:10 2017 +0200
+++ b/src/plugins/plugin_xep_0060.py	Fri Sep 08 07:57:57 2017 +0200
@@ -98,6 +98,9 @@
         host.bridge.addMethod("psItemSend", ".plugin", in_sign='ssssa{ss}s', out_sign='s', method=self._sendItem, async=True)
         host.bridge.addMethod("psRetractItem", ".plugin", in_sign='sssbs', out_sign='', method=self._retractItem, async=True)
         host.bridge.addMethod("psRetractItems", ".plugin", in_sign='ssasbs', out_sign='', method=self._retractItems, async=True)
+        host.bridge.addMethod("psSubscribe", ".plugin", in_sign='sss', out_sign='', method=self._subscribe, async=True)
+        host.bridge.addMethod("psUnsubscribe", ".plugin", in_sign='sss', out_sign='', method=self._unsubscribe, async=True)
+        host.bridge.addMethod("psSubscriptionsGet", ".plugin", in_sign='sss', out_sign='aa{ss}', method=self._subscriptions, async=True)
         host.bridge.addMethod("psSubscribeToMany", ".plugin", in_sign='a(ss)sa{ss}s', out_sign='s', method=self._subscribeToMany)
         host.bridge.addMethod("psGetSubscribeRTResult", ".plugin", in_sign='ss', out_sign='(ua(sss))', method=self._manySubscribeRTResult, async=True)
         host.bridge.addMethod("psGetFromMany", ".plugin", in_sign='a(ss)ia{ss}s', out_sign='s', method=self._getFromMany)
@@ -579,13 +582,51 @@
         client = self.host.getClient(profile_key)
         return client.pubsub_client.retractItems(service, nodeIdentifier, itemIdentifiers, notify=True)
 
-    def subscribe(self, service, nodeIdentifier, sub_jid=None, options=None, profile_key=C.PROF_KEY_NONE):
+    def _subscribe(self, service, nodeIdentifier, profile_key=C.PROF_KEY_NONE):
+        client = self.host.getClient(profile_key)
+        service = None if not service else jid.JID(service)
+        return self.subscribe(client, service, nodeIdentifier)
+
+    def subscribe(self, client, service, nodeIdentifier, sub_jid=None, options=None):
         # TODO: reimplement a subscribtion cache, checking that we have not subscription before trying to subscribe
+        return client.pubsub_client.subscribe(service, nodeIdentifier, sub_jid or client.jid.userhostJID(), options=options)
+
+    def _unsubscribe(self, service, nodeIdentifier, profile_key=C.PROF_KEY_NONE):
+        client = self.host.getClient(profile_key)
+        service = None if not service else jid.JID(service)
+        return self.unsubscribe(client, service, nodeIdentifier)
+
+    def unsubscribe(self, client, service, nodeIdentifier, sub_jid=None, subscriptionIdentifier=None, sender=None):
+        return client.pubsub_client.unsubscribe(service, nodeIdentifier, sub_jid or client.jid.userhostJID(), subscriptionIdentifier, sender)
+
+    def _subscriptions(self, service, nodeIdentifier='', profile_key=C.PROF_KEY_NONE):
         client = self.host.getClient(profile_key)
-        return client.pubsub_client.subscribe(service, nodeIdentifier, sub_jid or client.pubsub_client.parent.jid.userhostJID(), options=options)
+        service = None if not service else jid.JID(service)
+
+        def gotSubscriptions(subscriptions):
+            # we replace pubsub.Subscription instance by dict that we can serialize
+            for idx, sub in enumerate(subscriptions):
+                sub_dict = {'node': sub.nodeIdentifier,
+                            'subscriber': sub.subscriber.full(),
+                            'state': sub.state
+                           }
+                if sub.subscriptionIdentifier is not None:
+                    sub_dict['id'] = sub.subscriptionIdentifier
+                subscriptions[idx] = sub_dict
 
-    def subscriptions(self, service, nodeIdentifier='', profile_key=C.PROF_KEY_NONE):
-        client = self.host.getClient(profile_key)
+            return subscriptions
+
+        d = self.subscriptions(client, service, nodeIdentifier or None)
+        d.addCallback(gotSubscriptions)
+        return d
+
+    def subscriptions(self, client, service, nodeIdentifier=None):
+        """retrieve subscriptions from a service
+
+        @param service(jid.JID): PubSub service
+        @param nodeIdentifier(unicode, None): node to check
+            None to get all subscriptions
+        """
         return client.pubsub_client.subscriptions(service, nodeIdentifier)
 
     ## misc tools ##
@@ -593,7 +634,7 @@
     def getNodeURI(self, service, node, item=None):
         """Return XMPP URI of a PubSub node
 
-        @param service(jid.JID): PubSub service,
+        @param service(jid.JID): PubSub service
         @param node(unicode): node
         @return (unicode): URI of the node
         """
@@ -862,6 +903,7 @@
         @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
         @param nodeIdentifier: The identifier of the node (leave empty to retrieve all subscriptions).
         @type nodeIdentifier: C{unicode}
+        @return (list[pubsub.Subscription]): list of subscriptions
         """
         request = pubsub.PubSubRequest('subscriptions')
         request.recipient = service
@@ -870,9 +912,14 @@
         d = request.send(self.xmlstream)
 
         def cb(iq):
-            # FIXME: to be checked
-            return [sub for sub in iq.pubsub.subscriptions.elements() if
-                    (sub.uri == pubsub.NS_PUBSUB and sub.name == 'subscription')]
+            subs = []
+            for subscription_elt in iq.pubsub.subscriptions.elements(pubsub.NS_PUBSUB, 'subscription'):
+                subscription = pubsub.Subscription(subscription_elt['node'],
+                                                   jid.JID(subscription_elt['jid']),
+                                                   subscription_elt['subscription'],
+                                                   subscriptionIdentifier=subscription_elt.getAttribute('subid'))
+                subs.append(subscription)
+            return subs
 
         return d.addCallback(cb)