comparison src/plugins/plugin_xep_0060.py @ 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 b1bbd2994ceb
children 72cbb6478f97
comparison
equal deleted inserted replaced
2351:3c0a3fae1862 2352:6c26f435a02d
96 host.bridge.addMethod("psNodeDelete", ".plugin", in_sign='sss', out_sign='', method=self._deleteNode, async=True) 96 host.bridge.addMethod("psNodeDelete", ".plugin", in_sign='sss', out_sign='', method=self._deleteNode, async=True)
97 host.bridge.addMethod("psItemsGet", ".plugin", in_sign='ssiassa{ss}s', out_sign='(asa{ss})', method=self._getItems, async=True) 97 host.bridge.addMethod("psItemsGet", ".plugin", in_sign='ssiassa{ss}s', out_sign='(asa{ss})', method=self._getItems, async=True)
98 host.bridge.addMethod("psItemSend", ".plugin", in_sign='ssssa{ss}s', out_sign='s', method=self._sendItem, async=True) 98 host.bridge.addMethod("psItemSend", ".plugin", in_sign='ssssa{ss}s', out_sign='s', method=self._sendItem, async=True)
99 host.bridge.addMethod("psRetractItem", ".plugin", in_sign='sssbs', out_sign='', method=self._retractItem, async=True) 99 host.bridge.addMethod("psRetractItem", ".plugin", in_sign='sssbs', out_sign='', method=self._retractItem, async=True)
100 host.bridge.addMethod("psRetractItems", ".plugin", in_sign='ssasbs', out_sign='', method=self._retractItems, async=True) 100 host.bridge.addMethod("psRetractItems", ".plugin", in_sign='ssasbs', out_sign='', method=self._retractItems, async=True)
101 host.bridge.addMethod("psSubscribe", ".plugin", in_sign='sss', out_sign='', method=self._subscribe, async=True)
102 host.bridge.addMethod("psUnsubscribe", ".plugin", in_sign='sss', out_sign='', method=self._unsubscribe, async=True)
103 host.bridge.addMethod("psSubscriptionsGet", ".plugin", in_sign='sss', out_sign='aa{ss}', method=self._subscriptions, async=True)
101 host.bridge.addMethod("psSubscribeToMany", ".plugin", in_sign='a(ss)sa{ss}s', out_sign='s', method=self._subscribeToMany) 104 host.bridge.addMethod("psSubscribeToMany", ".plugin", in_sign='a(ss)sa{ss}s', out_sign='s', method=self._subscribeToMany)
102 host.bridge.addMethod("psGetSubscribeRTResult", ".plugin", in_sign='ss', out_sign='(ua(sss))', method=self._manySubscribeRTResult, async=True) 105 host.bridge.addMethod("psGetSubscribeRTResult", ".plugin", in_sign='ss', out_sign='(ua(sss))', method=self._manySubscribeRTResult, async=True)
103 host.bridge.addMethod("psGetFromMany", ".plugin", in_sign='a(ss)ia{ss}s', out_sign='s', method=self._getFromMany) 106 host.bridge.addMethod("psGetFromMany", ".plugin", in_sign='a(ss)ia{ss}s', out_sign='s', method=self._getFromMany)
104 host.bridge.addMethod("psGetFromManyRTResult", ".plugin", in_sign='ss', out_sign='(ua(sssasa{ss}))', method=self._getFromManyRTResult, async=True) 107 host.bridge.addMethod("psGetFromManyRTResult", ".plugin", in_sign='ss', out_sign='(ua(sssasa{ss}))', method=self._getFromManyRTResult, async=True)
105 host.bridge.addSignal("psEvent", ".plugin", signature='ssssa{ss}s') # args: category, service(jid), node, type (C.PS_ITEMS, C.PS_DELETE), data, profile 108 host.bridge.addSignal("psEvent", ".plugin", signature='ssssa{ss}s') # args: category, service(jid), node, type (C.PS_ITEMS, C.PS_DELETE), data, profile
577 580
578 def retractItems(self, service, nodeIdentifier, itemIdentifiers, notify=True, profile_key=C.PROF_KEY_NONE): 581 def retractItems(self, service, nodeIdentifier, itemIdentifiers, notify=True, profile_key=C.PROF_KEY_NONE):
579 client = self.host.getClient(profile_key) 582 client = self.host.getClient(profile_key)
580 return client.pubsub_client.retractItems(service, nodeIdentifier, itemIdentifiers, notify=True) 583 return client.pubsub_client.retractItems(service, nodeIdentifier, itemIdentifiers, notify=True)
581 584
582 def subscribe(self, service, nodeIdentifier, sub_jid=None, options=None, profile_key=C.PROF_KEY_NONE): 585 def _subscribe(self, service, nodeIdentifier, profile_key=C.PROF_KEY_NONE):
586 client = self.host.getClient(profile_key)
587 service = None if not service else jid.JID(service)
588 return self.subscribe(client, service, nodeIdentifier)
589
590 def subscribe(self, client, service, nodeIdentifier, sub_jid=None, options=None):
583 # TODO: reimplement a subscribtion cache, checking that we have not subscription before trying to subscribe 591 # TODO: reimplement a subscribtion cache, checking that we have not subscription before trying to subscribe
584 client = self.host.getClient(profile_key) 592 return client.pubsub_client.subscribe(service, nodeIdentifier, sub_jid or client.jid.userhostJID(), options=options)
585 return client.pubsub_client.subscribe(service, nodeIdentifier, sub_jid or client.pubsub_client.parent.jid.userhostJID(), options=options) 593
586 594 def _unsubscribe(self, service, nodeIdentifier, profile_key=C.PROF_KEY_NONE):
587 def subscriptions(self, service, nodeIdentifier='', profile_key=C.PROF_KEY_NONE): 595 client = self.host.getClient(profile_key)
588 client = self.host.getClient(profile_key) 596 service = None if not service else jid.JID(service)
597 return self.unsubscribe(client, service, nodeIdentifier)
598
599 def unsubscribe(self, client, service, nodeIdentifier, sub_jid=None, subscriptionIdentifier=None, sender=None):
600 return client.pubsub_client.unsubscribe(service, nodeIdentifier, sub_jid or client.jid.userhostJID(), subscriptionIdentifier, sender)
601
602 def _subscriptions(self, service, nodeIdentifier='', profile_key=C.PROF_KEY_NONE):
603 client = self.host.getClient(profile_key)
604 service = None if not service else jid.JID(service)
605
606 def gotSubscriptions(subscriptions):
607 # we replace pubsub.Subscription instance by dict that we can serialize
608 for idx, sub in enumerate(subscriptions):
609 sub_dict = {'node': sub.nodeIdentifier,
610 'subscriber': sub.subscriber.full(),
611 'state': sub.state
612 }
613 if sub.subscriptionIdentifier is not None:
614 sub_dict['id'] = sub.subscriptionIdentifier
615 subscriptions[idx] = sub_dict
616
617 return subscriptions
618
619 d = self.subscriptions(client, service, nodeIdentifier or None)
620 d.addCallback(gotSubscriptions)
621 return d
622
623 def subscriptions(self, client, service, nodeIdentifier=None):
624 """retrieve subscriptions from a service
625
626 @param service(jid.JID): PubSub service
627 @param nodeIdentifier(unicode, None): node to check
628 None to get all subscriptions
629 """
589 return client.pubsub_client.subscriptions(service, nodeIdentifier) 630 return client.pubsub_client.subscriptions(service, nodeIdentifier)
590 631
591 ## misc tools ## 632 ## misc tools ##
592 633
593 def getNodeURI(self, service, node, item=None): 634 def getNodeURI(self, service, node, item=None):
594 """Return XMPP URI of a PubSub node 635 """Return XMPP URI of a PubSub node
595 636
596 @param service(jid.JID): PubSub service, 637 @param service(jid.JID): PubSub service
597 @param node(unicode): node 638 @param node(unicode): node
598 @return (unicode): URI of the node 639 @return (unicode): URI of the node
599 """ 640 """
600 assert service is not None 641 assert service is not None
601 # XXX: urllib.urlencode use "&" to separate value, while XMPP URL (cf. RFC 5122) 642 # XXX: urllib.urlencode use "&" to separate value, while XMPP URL (cf. RFC 5122)
860 901
861 @param service: The publish subscribe service to retrieve the subscriptions from. 902 @param service: The publish subscribe service to retrieve the subscriptions from.
862 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} 903 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
863 @param nodeIdentifier: The identifier of the node (leave empty to retrieve all subscriptions). 904 @param nodeIdentifier: The identifier of the node (leave empty to retrieve all subscriptions).
864 @type nodeIdentifier: C{unicode} 905 @type nodeIdentifier: C{unicode}
906 @return (list[pubsub.Subscription]): list of subscriptions
865 """ 907 """
866 request = pubsub.PubSubRequest('subscriptions') 908 request = pubsub.PubSubRequest('subscriptions')
867 request.recipient = service 909 request.recipient = service
868 request.nodeIdentifier = nodeIdentifier 910 request.nodeIdentifier = nodeIdentifier
869 request.sender = sender 911 request.sender = sender
870 d = request.send(self.xmlstream) 912 d = request.send(self.xmlstream)
871 913
872 def cb(iq): 914 def cb(iq):
873 # FIXME: to be checked 915 subs = []
874 return [sub for sub in iq.pubsub.subscriptions.elements() if 916 for subscription_elt in iq.pubsub.subscriptions.elements(pubsub.NS_PUBSUB, 'subscription'):
875 (sub.uri == pubsub.NS_PUBSUB and sub.name == 'subscription')] 917 subscription = pubsub.Subscription(subscription_elt['node'],
918 jid.JID(subscription_elt['jid']),
919 subscription_elt['subscription'],
920 subscriptionIdentifier=subscription_elt.getAttribute('subid'))
921 subs.append(subscription)
922 return subs
876 923
877 return d.addCallback(cb) 924 return d.addCallback(cb)
878 925
879 def getDiscoInfo(self, requestor, service, nodeIdentifier=''): 926 def getDiscoInfo(self, requestor, service, nodeIdentifier=''):
880 disco_info = [] 927 disco_info = []