diff sat_pubsub/mam.py @ 322:54d90c73b8b5

mam: various improvments: - put common namespaces ton const - VAL_RSM_MAX_DEFAULT can be None if default limit is not wanted - ItemDate now has a 'date' attribute - MAMService is MonkeyPatched the same way as PubSubService to handle PEP - fixed error mapping in mam module - PEP is handled - properly manage date in a payload independent way - when PEP is used, send privileged messages
author Goffi <goffi@goffi.org>
date Tue, 05 Jan 2016 23:13:13 +0100
parents cca47e9977a5
children 8d939378f023
line wrap: on
line diff
--- a/sat_pubsub/mam.py	Tue Jan 05 22:16:37 2016 +0100
+++ b/sat_pubsub/mam.py	Tue Jan 05 23:13:13 2016 +0100
@@ -28,32 +28,44 @@
 from zope.interface import implements
 
 from twisted.words.xish import domish
+from twisted.python import log
+from twisted.words.protocols.jabber import error
 
 from sat_pubsub import const
-from sat_pubsub.backend import PubSubResourceFromBackend
-from wokkel.pubsub import NS_PUBSUB_EVENT
-
-from dateutil import parser
+from sat_pubsub import backend
+from wokkel import pubsub
 
-# TODO: change this when RSM and MAM are in wokkel
-from sat.tmp.wokkel import rsm
-from sat.tmp.wokkel import mam
-
-NS_CLIENT = 'jabber:client'
+from wokkel import rsm
+from wokkel import mam
+from wokkel import delay
 
 
 class MAMResource(object):
+    implements(mam.IMAMResource)
+    _errorMap = backend.PubSubResourceFromBackend._errorMap
 
-    implements(mam.IMAMResource)
+    def __init__(self, backend_):
+        self.backend = backend_
+
+    def _mapErrors(self, failure):
+        # XXX: come from backend.PubsubResourceFromBackend
+        e = failure.trap(*self._errorMap.keys())
 
-    def __init__(self, backend):
-        self.backend = backend
+        condition, pubsubCondition, feature = self._errorMap[e]
+        msg = failure.value.msg
 
-    def onArchiveRequest(self, mam, requestor):
+        if pubsubCondition:
+            exc = pubsub.PubSubError(condition, pubsubCondition, feature, msg)
+        else:
+            exc = error.StanzaError(condition, text=msg)
+
+        raise exc
+
+    def onArchiveRequest(self, mam_request, requestor):
         """
 
-        @param mam: The MAM <query/> request.
-        @type mam: L{MAMQueryReques<wokkel.mam.MAMQueryRequest>}
+        @param mam_request: The MAM archive request.
+        @type mam_request: L{MAMQueryReques<wokkel.mam.MAMRequest>}
 
         @param requestor: JID of the requestor.
         @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>}
@@ -62,42 +74,68 @@
         @rtype: C{tuple}
         """
         # FIXME: bad result ordering
-        ext_data = {}
-        if mam.form:
-            ext_data['filters'] = mam.form.fields.values()
-        if mam.rsm is None:
-            mam.rsm = rsm.RSMRequest(const.VAL_RSM_MAX_DEFAULT)
-        ext_data['rsm'] = mam.rsm
+        try:
+            pep = mam_request.delegated
+        except AttributeError:
+            pep = False
+        ext_data = {'pep': pep}
+        if mam_request.form:
+            ext_data['filters'] = mam_request.form.fields.values()
+        if mam_request.rsm is None:
+            if const.VAL_RSM_MAX_DEFAULT != None:
+                log.msg("MAM request without RSM limited to {}".format(const.VAL_RSM_MAX_DEFAULT))
+                ext_data['rsm'] = rsm.RSMRequest(const.VAL_RSM_MAX_DEFAULT)
+        else:
+            ext_data['rsm'] = mam_request.rsm
 
-        d = self.backend.getItems(mam.node, requestor, mam.rsm.max, None, ext_data)
+        d = self.backend.getItemsData(mam_request.node, requestor, None, None, ext_data)
 
         def make_message(elt):
             # XXX: http://xmpp.org/extensions/xep-0297.html#sect-idp629952 (rule 3)
-            message = domish.Element((NS_CLIENT, "message"))
-            event = message.addElement((NS_PUBSUB_EVENT, "event"))
+            message = domish.Element((const.NS_CLIENT, "message"))
+            event = message.addElement((pubsub.NS_PUBSUB_EVENT, "event"))
             items = event.addElement('items')
-            items["node"] = mam.node
+            items["node"] = mam_request.node
             items.addChild(elt)
             return message
 
-        def cb(elts):
+        def cb(items_data):
             msg_data = []
             rsm_elt = None
-            for elt in elts:
-                if elt.name == 'set' and elt.uri == rsm.NS_RSM:
+            for item_data in items_data:
+                if item_data.item.name == 'set' and item_data.item.uri == rsm.NS_RSM:
                     assert rsm_elt is None
-                    rsm_elt = elt
-                elif elt.name == 'item':
-                    # FIXME: this is not good as it is dependant on payload
-                    # TODO: remove this and use date field in database
-                    date = parser.parse(''.join(elt.entry.published.children))
-                    msg_data.append([elt['id'], make_message(elt), date])
+                    rsm_elt = item_data.item
+                elif item_data.item.name == 'item':
+                    msg_data.append([item_data.item['id'], make_message(item_data.item), item_data.date])
+                else:
+                    log.msg("WARNING: unknown element: {}".format(item_data.item.name))
+            if pep:
+                # we need to send privileged message
+                # so me manage the sending ourself, and return
+                # an empty msg_data list to avoid double sending
+                for data in msg_data:
+                    self.forwardPEPMessage(mam_request, requestor, *data)
+                msg_data = []
             return (msg_data, rsm_elt)
 
-        d.addErrback(PubSubResourceFromBackend._mapErrors)
+        d.addErrback(self._mapErrors)
         d.addCallback(cb)
         return d
 
+    def forwardPEPMessage(self, mam_request, requestor, id_, elt, date):
+        msg = domish.Element((None, 'message'))
+        msg['from'] = self.backend.privilege.server_jid.full()
+        msg['to'] = requestor.full()
+        result = msg.addElement((mam.NS_MAM, 'result'))
+        if mam_request.query_id is not None:
+            result['queryid'] = mam_request.query_id
+        result['id'] = id_
+        forward = result.addElement((const.NS_FORWARD, 'forwarded'))
+        forward.addChild(delay.Delay(date).toElement())
+        forward.addChild(elt)
+        self.backend.privilege.sendMessage(msg)
+
     def onPrefsGetRequest(self, requestor):
         """