# HG changeset patch # User Goffi # Date 1504850277 -7200 # Node ID 6c26f435a02d01b4fbc98b5c31fe0a35048be825 # Parent 3c0a3fae18622febd3958ab0782c9099a1c119f0 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) diff -r 3c0a3fae1862 -r 6c26f435a02d src/plugins/plugin_xep_0060.py --- 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} @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)