diff src/plugins/plugin_xep_0060.py @ 2338:b1bbd2994ceb

plugin XEP-0060: implemented subscriptions management method for node owner: added getNodeSubscriptions and setNodeSubscriptions and their bridge method (psNodeSubscriptionsGet and psNodeSubscriptionsSet)
author Goffi <goffi@goffi.org>
date Sun, 20 Aug 2017 10:31:53 +0200
parents e715a29c4f9b
children 6c26f435a02d
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0060.py	Sun Aug 20 10:29:26 2017 +0200
+++ b/src/plugins/plugin_xep_0060.py	Sun Aug 20 10:31:53 2017 +0200
@@ -88,9 +88,11 @@
         host.bridge.addMethod("psNodeCreate", ".plugin", in_sign='ssa{ss}s', out_sign='s', method=self._createNode, async=True)
         host.bridge.addMethod("psNodeConfigurationGet", ".plugin", in_sign='sss', out_sign='a{ss}', method=self._getNodeConfiguration, async=True)
         host.bridge.addMethod("psNodeConfigurationSet", ".plugin", in_sign='ssa{ss}s', out_sign='', method=self._setNodeConfiguration, async=True)
-        host.bridge.addMethod("psAffiliationsGet", ".plugin", in_sign='sss', out_sign='a{ss}', method=self._getAffiliations, async=True)
         host.bridge.addMethod("psNodeAffiliationsGet", ".plugin", in_sign='sss', out_sign='a{ss}', method=self._getNodeAffiliations, async=True)
         host.bridge.addMethod("psNodeAffiliationsSet", ".plugin", in_sign='ssa{ss}s', out_sign='', method=self._setNodeAffiliations, async=True)
+        host.bridge.addMethod("psNodeSubscriptionsGet", ".plugin", in_sign='sss', out_sign='a{ss}', method=self._getNodeSubscriptions, async=True)
+        host.bridge.addMethod("psNodeSubscriptionsSet", ".plugin", in_sign='ssa{ss}s', out_sign='', method=self._setNodeSubscriptions, async=True)
+        host.bridge.addMethod("psAffiliationsGet", ".plugin", in_sign='sss', out_sign='a{ss}', method=self._getAffiliations, async=True)
         host.bridge.addMethod("psNodeDelete", ".plugin", in_sign='sss', out_sign='', method=self._deleteNode, async=True)
         host.bridge.addMethod("psItemsGet", ".plugin", in_sign='ssiassa{ss}s', out_sign='(asa{ss})', method=self._getItems, async=True)
         host.bridge.addMethod("psItemSend", ".plugin", in_sign='ssssa{ss}s', out_sign='s', method=self._sendItem, async=True)
@@ -663,6 +665,58 @@
 
     # subscribe #
 
+    def _getNodeSubscriptions(self, service_s, nodeIdentifier, profile_key):
+        client = self.host.getClient(profile_key)
+        d = self.getNodeSubscriptions(client, jid.JID(service_s) if service_s else None, nodeIdentifier)
+        d.addCallback(lambda subscriptions: {j.full(): a for j, a in subscriptions.iteritems()})
+        return d
+
+    def getNodeSubscriptions(self, client, service, nodeIdentifier):
+        """Retrieve subscriptions to a node
+
+        @param nodeIdentifier(unicode): node to get subscriptions from
+        """
+        if not nodeIdentifier:
+            raise exceptions.DataError("node identifier can't be empty")
+        request = pubsub.PubSubRequest('subscriptionsGet')
+        request.recipient = service
+        request.nodeIdentifier = nodeIdentifier
+
+        def cb(iq_elt):
+            try:
+                subscriptions_elt = next(iq_elt.pubsub.elements((pubsub.NS_PUBSUB, 'subscriptions')))
+            except StopIteration:
+                raise ValueError(_(u"Invalid result: missing <subscriptions> element: {}").format(iq_elt.toXml))
+            except AttributeError as e:
+                raise ValueError(_(u"Invalid result: {}").format(e))
+            try:
+                return {jid.JID(s['jid']): s['subscription'] for s in subscriptions_elt.elements((pubsub.NS_PUBSUB, 'subscription'))}
+            except KeyError:
+                raise ValueError(_(u"Invalid result: bad <subscription> element: {}").format(iq_elt.toXml))
+
+        d = request.send(client.xmlstream)
+        d.addCallback(cb)
+        return d
+
+    def _setNodeSubscriptions(self, service_s, nodeIdentifier, subscriptions, profile_key=C.PROF_KEY_NONE):
+        client = self.host.getClient(profile_key)
+        subscriptions = {jid.JID(jid_): subscription for jid_, subscription in subscriptions.iteritems()}
+        d = self.setNodeSubscriptions(client, jid.JID(service_s) if service_s else None, nodeIdentifier, subscriptions)
+        return d
+
+    def setNodeSubscriptions(self, client, service, nodeIdentifier, subscriptions):
+        """Set or update subscriptions of a node owned by profile
+
+        @param subscriptions(dict[jid.JID, unicode]): subscriptions to set
+            check https://xmpp.org/extensions/xep-0060.html#substates for a list of possible subscriptions
+        """
+        request = pubsub.PubSubRequest('subscriptionsSet')
+        request.recipient = service
+        request.nodeIdentifier = nodeIdentifier
+        request.subscriptions = {pubsub.Subscription(nodeIdentifier, jid_, state) for jid_, state in subscriptions.iteritems()}
+        d = request.send(client.xmlstream)
+        return d
+
     def _manySubscribeRTResult(self, session_id, profile_key=C.PROF_KEY_DEFAULT):
         """Get real-time results for subcribeToManu session