changeset 1267:ea692d51a0ee

plugins XEP-0059, XEP-0060: leave internal wokkel extensions to sat.tmp.wokkel
author souliane <souliane@mailoo.org>
date Mon, 15 Dec 2014 14:03:13 +0100
parents 9141bde7ff31
children bb30bf3ae932
files src/plugins/plugin_xep_0059.py src/plugins/plugin_xep_0060.py
diffstat 2 files changed, 13 insertions(+), 222 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0059.py	Mon Dec 15 12:46:58 2014 +0100
+++ b/src/plugins/plugin_xep_0059.py	Mon Dec 15 14:03:13 2014 +0100
@@ -22,7 +22,6 @@
 from sat.core.log import getLogger
 log = getLogger(__name__)
 
-from twisted.words.xish import domish
 from wokkel import disco, iwokkel
 try:
     from twisted.words.protocols.xmlstream import XMPPHandler
@@ -45,93 +44,10 @@
 
 
 class XEP_0059(object):
+    # XXX: RSM management is done directly in Wokkel.
 
     def __init__(self, host):
         log.info(_("Result Set Management plugin initialization"))
-        self.host = host
-
-    def requestPage(self, stanza, limit=10, index=None, after=None, before=None):
-        """Embed a RSM page request in the given stanza.
-
-        @param stanza (domish.Element): any stanza to which RSM applies
-        @param limit (int): the maximum number of items in the page
-        @param index (int): the starting index of the requested page
-        @param after (str, int): the element immediately preceding the page
-        @param before (str, int): the element immediately following the page
-        """
-        main_elt = None
-        try:
-            main_elt = domish.generateElementsNamed(stanza.elements(), name="query").next()
-        except StopIteration:
-            try:
-                main_elt = domish.generateElementsNamed(stanza.elements(), name="pubsub").next()
-            except StopIteration:
-                log.warning("Injection of a RSM element only applies to query or pubsub stanzas")
-                return
-        limit = str(int(limit))
-
-        # in case the service doesn't support RSM, do this at least
-        main_elt.items.attributes['max_items'] = limit
-
-        set_elt = main_elt.addElement('set', NS_RSM)
-        set_elt.addElement('max').addContent(limit)
-        if index:
-            assert(after is None and before is None)
-            set_elt.addElement('index').addContent(str(int(index)))
-        if after:
-            assert(before is None)  # could not specify both at the same time
-            set_elt.addElement('after').addContent(str(after))
-        if before is not None:
-            if before == '':  # request the last page, according to http://xmpp.org/extensions/xep-0059.html#last
-                set_elt.addElement('before')
-            else:
-                set_elt.addElement('before').addContent(str(before))
-
-    def countItems(self, stanza):
-        """Count the items without retrieving any of them.
-
-        @param stanza (domish.Element): any stanza to which RSM applies
-        """
-        self.requestPage(stanza, limit=0)
-
-    def extractMetadata(self, stanza):
-        """Extract the RSM metadata from the given stanza.
-
-        @param stanza (domish.Element, wokkel.pubsub.PubSubRequest):
-           any stanza to which RSM applies. When used by XEP-0060,
-           wokkel's PubSubRequest instance is also accepted.
-        @return: dict containing the page metadata
-        """
-        try:
-            main_elt = domish.generateElementsNamed(stanza.elements(), name="query").next()
-        except StopIteration:
-            try:
-                main_elt = domish.generateElementsNamed(stanza.elements(), name="pubsub").next()
-            except StopIteration:
-                log.warning("Extracting data from a RSM element only applies to query or pubsub stanzas")
-                return {}
-        try:
-            set_elt = domish.generateElementsQNamed(main_elt.elements(), name="set", uri=NS_RSM).next()
-        except StopIteration:
-            log.debug("There's no RSM element in the stanza")
-            return {}
-
-        data = {}
-        elts = set_elt.elements()
-        try:
-            elt = elts.next()
-            if elt.name == "first":
-                data["first"] = "".join(elt.children)
-                data["first_index"] = int(elt.getAttribute("index"))
-            elif elt.name == "last":
-                data["last"] = "".join(elt.children)
-            elif elt.name == "count":
-                data["count"] = int("".join(elt.children))
-        except StopIteration:
-            pass
-        if "count" not in data:
-            log.warning("There's no 'count' element in the RSM element!")
-        return data
 
 
 class XEP_0059_handler(XMPPHandler):
--- a/src/plugins/plugin_xep_0060.py	Mon Dec 15 12:46:58 2014 +0100
+++ b/src/plugins/plugin_xep_0060.py	Mon Dec 15 14:03:13 2014 +0100
@@ -23,8 +23,7 @@
 log = getLogger(__name__)
 from sat.memory.memory import Sessions
 
-from wokkel.compat import IQ
-from wokkel import disco, pubsub
+from wokkel import disco, pubsub, rsm
 from zope.interface import implements
 from twisted.internet import defer
 
@@ -232,82 +231,16 @@
         return client.subscriptions(service, nodeIdentifier)
 
 
-class SatPubSubClient(pubsub.PubSubClient):
+class SatPubSubClient(rsm.PubSubClient):
     implements(disco.IDisco)
 
     def __init__(self, host, parent_plugin):
         self.host = host
         self.parent_plugin = parent_plugin
-        pubsub.PubSubClient.__init__(self)
+        rsm.PubSubClient.__init__(self)
 
     def connectionInitialized(self):
-        pubsub.PubSubClient.connectionInitialized(self)
-
-    # FIXME: we have to temporary override this method here just
-    # to set the attributes itemIdentifiers which is not used
-    # in pubsub.PubSubClient.items + use the XEP-0059
-    def items(self, service, nodeIdentifier, maxItems=None, itemIdentifiers=None,
-              subscriptionIdentifier=None, sender=None):
-        """
-        Retrieve previously published items from a publish subscribe node.
-
-        @param service: The publish subscribe service that keeps the node.
-        @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
-
-        @param nodeIdentifier: The identifier of the node.
-        @type nodeIdentifier: C{unicode}
-
-        @param maxItems: Optional limit on the number of retrieved items.
-        @type maxItems: C{int}
-
-        @param itemIdentifiers: Identifiers of the items to be retrieved.
-        @type itemIdentifiers: C{set}
-
-        @param subscriptionIdentifier: Optional subscription identifier. In
-            case the node has been subscribed to multiple times, this narrows
-            the results to the specific subscription.
-        @type subscriptionIdentifier: C{unicode}
-        """
-        # TODO: add method attributes for RSM: before, after, index
-        request = PubSubRequest('items', self.host, {'limit': maxItems} if maxItems else {})
-        request.recipient = service
-        request.nodeIdentifier = nodeIdentifier
-        if maxItems:
-            request.maxItems = str(int(maxItems))
-        request.subscriptionIdentifier = subscriptionIdentifier
-        request.sender = sender
-        request.itemIdentifiers = itemIdentifiers  # XXX: this line has been added
-
-        def cb(iq):
-            items = []
-            for element in iq.pubsub.items.elements():
-                if element.uri == pubsub.NS_PUBSUB and element.name == 'item':
-                    items.append(element)
-            # TODO: return (items, self.host.plugins['XEP-0059'].extractMetadata(iq)) ??
-            return items
-
-        d = request.send(self.xmlstream)
-        d.addCallback(cb)
-        return d
-
-    # FIXME: this should be done in wokkel
-    def retractItems(self, service, nodeIdentifier, itemIdentifiers, sender=None):
-        """
-        Retract items from a publish subscribe node.
-
-        @param service: The publish subscribe service to delete the node from.
-        @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
-        @param nodeIdentifier: The identifier of the node.
-        @type nodeIdentifier: C{unicode}
-        @param itemIdentifiers: Identifiers of the items to be retracted.
-        @type itemIdentifiers: C{set}
-        """
-        request = PubSubRequest('retract')
-        request.recipient = service
-        request.nodeIdentifier = nodeIdentifier
-        request.itemIdentifiers = itemIdentifiers
-        request.sender = sender
-        return request.send(self.xmlstream)
+        rsm.PubSubClient.connectionInitialized(self)
 
     def itemsReceived(self, event):
         if not self.host.trigger.point("PubSubItemsReceived", event, self.parent.profile):
@@ -322,7 +255,6 @@
 
     # def purgeReceived(self, event):
 
-    @defer.inlineCallbacks
     def subscriptions(self, service, nodeIdentifier, sender=None):
         """Return the list of subscriptions to the given service and node.
 
@@ -331,13 +263,17 @@
         @param nodeIdentifier: The identifier of the node (leave empty to retrieve all subscriptions).
         @type nodeIdentifier: C{unicode}
         """
-        request = PubSubRequest('subscriptions')
+        request = pubsub.PubSubRequest('subscriptions')
         request.recipient = service
         request.nodeIdentifier = nodeIdentifier
         request.sender = sender
-        iq = yield request.send(self.xmlstream)
-        defer.returnValue([sub for sub in iq.pubsub.subscriptions.elements() if
-                           (sub.uri == pubsub.NS_PUBSUB and sub.name == 'subscription')])
+        d = request.send(self.xmlstream)
+
+        def cb(iq):
+            return [sub for sub in iq.pubsub.subscriptions.elements() if
+                    (sub.uri == pubsub.NS_PUBSUB and sub.name == 'subscription')]
+
+        return d.addCallback(cb)
 
     def getDiscoInfo(self, requestor, service, nodeIdentifier=''):
         disco_info = []
@@ -346,64 +282,3 @@
 
     def getDiscoItems(self, requestor, service, nodeIdentifier=''):
         return []
-
-
-class PubSubRequest(pubsub.PubSubRequest):
-
-    def __init__(self, verb=None, host=None, page_attrs=None):
-        """
-        @param verb (str): the type of pubsub request
-        @param host (SAT): the SAT instance
-        @param page_attrs (dict): options for RSM paging:
-            - limit (int): the maximum number of items in the page
-            - index (int): the starting index of the requested page
-            - after (str, int): the element immediately preceding the page
-            - before (str, int): the element immediately following the page
-        """
-        self.verb = verb
-        self.host = host
-        self.page_attrs = page_attrs
-
-    # FIXME: the redefinition of this wokkel method is the easiest way I found
-    # to handle RSM. We should find a proper solution, maybe just add in wokkel an
-    # empty method postProcessMessage, call it before sending and overwrite it here
-    # instead of overwriting the whole send method.
-    def send(self, xs):
-        """
-        Send this request to its recipient.
-
-        This renders all of the relevant parameters for this specific
-        requests into an L{IQ}, and invoke its C{send} method.
-        This returns a deferred that fires upon reception of a response. See
-        L{IQ} for details.
-
-        @param xs: The XML stream to send the request on.
-        @type xs: L{twisted.words.protocols.jabber.xmlstream.XmlStream}
-        @rtype: L{defer.Deferred}.
-        """
-
-        try:
-            (self.stanzaType,
-             childURI,
-             childName) = self._verbRequestMap[self.verb]
-        except KeyError:
-            raise NotImplementedError()
-
-        iq = IQ(xs, self.stanzaType)
-        iq.addElement((childURI, 'pubsub'))
-        verbElement = iq.pubsub.addElement(childName)
-
-        if self.sender:
-            iq['from'] = self.sender.full()
-        if self.recipient:
-            iq['to'] = self.recipient.full()
-
-        for parameter in self._parameters[self.verb]:
-            getattr(self, '_render_%s' % parameter)(verbElement)
-
-        # This lines have been added for RSM
-        if self.host and 'XEP-0059' in self.host.plugins and self.page_attrs:
-            self.page_attrs['stanza'] = iq
-            self.host.plugins['XEP-0059'].requestPage(**self.page_attrs)
-
-        return iq.send()