comparison 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
comparison
equal deleted inserted replaced
321:c7fe09894952 322:54d90c73b8b5
26 26
27 27
28 from zope.interface import implements 28 from zope.interface import implements
29 29
30 from twisted.words.xish import domish 30 from twisted.words.xish import domish
31 from twisted.python import log
32 from twisted.words.protocols.jabber import error
31 33
32 from sat_pubsub import const 34 from sat_pubsub import const
33 from sat_pubsub.backend import PubSubResourceFromBackend 35 from sat_pubsub import backend
34 from wokkel.pubsub import NS_PUBSUB_EVENT 36 from wokkel import pubsub
35 37
36 from dateutil import parser 38 from wokkel import rsm
37 39 from wokkel import mam
38 # TODO: change this when RSM and MAM are in wokkel 40 from wokkel import delay
39 from sat.tmp.wokkel import rsm
40 from sat.tmp.wokkel import mam
41
42 NS_CLIENT = 'jabber:client'
43 41
44 42
45 class MAMResource(object): 43 class MAMResource(object):
44 implements(mam.IMAMResource)
45 _errorMap = backend.PubSubResourceFromBackend._errorMap
46 46
47 implements(mam.IMAMResource) 47 def __init__(self, backend_):
48 self.backend = backend_
48 49
49 def __init__(self, backend): 50 def _mapErrors(self, failure):
50 self.backend = backend 51 # XXX: come from backend.PubsubResourceFromBackend
52 e = failure.trap(*self._errorMap.keys())
51 53
52 def onArchiveRequest(self, mam, requestor): 54 condition, pubsubCondition, feature = self._errorMap[e]
55 msg = failure.value.msg
56
57 if pubsubCondition:
58 exc = pubsub.PubSubError(condition, pubsubCondition, feature, msg)
59 else:
60 exc = error.StanzaError(condition, text=msg)
61
62 raise exc
63
64 def onArchiveRequest(self, mam_request, requestor):
53 """ 65 """
54 66
55 @param mam: The MAM <query/> request. 67 @param mam_request: The MAM archive request.
56 @type mam: L{MAMQueryReques<wokkel.mam.MAMQueryRequest>} 68 @type mam_request: L{MAMQueryReques<wokkel.mam.MAMRequest>}
57 69
58 @param requestor: JID of the requestor. 70 @param requestor: JID of the requestor.
59 @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>} 71 @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>}
60 72
61 @return: A tuple with list of message data (id, element, data) and RSM element 73 @return: A tuple with list of message data (id, element, data) and RSM element
62 @rtype: C{tuple} 74 @rtype: C{tuple}
63 """ 75 """
64 # FIXME: bad result ordering 76 # FIXME: bad result ordering
65 ext_data = {} 77 try:
66 if mam.form: 78 pep = mam_request.delegated
67 ext_data['filters'] = mam.form.fields.values() 79 except AttributeError:
68 if mam.rsm is None: 80 pep = False
69 mam.rsm = rsm.RSMRequest(const.VAL_RSM_MAX_DEFAULT) 81 ext_data = {'pep': pep}
70 ext_data['rsm'] = mam.rsm 82 if mam_request.form:
83 ext_data['filters'] = mam_request.form.fields.values()
84 if mam_request.rsm is None:
85 if const.VAL_RSM_MAX_DEFAULT != None:
86 log.msg("MAM request without RSM limited to {}".format(const.VAL_RSM_MAX_DEFAULT))
87 ext_data['rsm'] = rsm.RSMRequest(const.VAL_RSM_MAX_DEFAULT)
88 else:
89 ext_data['rsm'] = mam_request.rsm
71 90
72 d = self.backend.getItems(mam.node, requestor, mam.rsm.max, None, ext_data) 91 d = self.backend.getItemsData(mam_request.node, requestor, None, None, ext_data)
73 92
74 def make_message(elt): 93 def make_message(elt):
75 # XXX: http://xmpp.org/extensions/xep-0297.html#sect-idp629952 (rule 3) 94 # XXX: http://xmpp.org/extensions/xep-0297.html#sect-idp629952 (rule 3)
76 message = domish.Element((NS_CLIENT, "message")) 95 message = domish.Element((const.NS_CLIENT, "message"))
77 event = message.addElement((NS_PUBSUB_EVENT, "event")) 96 event = message.addElement((pubsub.NS_PUBSUB_EVENT, "event"))
78 items = event.addElement('items') 97 items = event.addElement('items')
79 items["node"] = mam.node 98 items["node"] = mam_request.node
80 items.addChild(elt) 99 items.addChild(elt)
81 return message 100 return message
82 101
83 def cb(elts): 102 def cb(items_data):
84 msg_data = [] 103 msg_data = []
85 rsm_elt = None 104 rsm_elt = None
86 for elt in elts: 105 for item_data in items_data:
87 if elt.name == 'set' and elt.uri == rsm.NS_RSM: 106 if item_data.item.name == 'set' and item_data.item.uri == rsm.NS_RSM:
88 assert rsm_elt is None 107 assert rsm_elt is None
89 rsm_elt = elt 108 rsm_elt = item_data.item
90 elif elt.name == 'item': 109 elif item_data.item.name == 'item':
91 # FIXME: this is not good as it is dependant on payload 110 msg_data.append([item_data.item['id'], make_message(item_data.item), item_data.date])
92 # TODO: remove this and use date field in database 111 else:
93 date = parser.parse(''.join(elt.entry.published.children)) 112 log.msg("WARNING: unknown element: {}".format(item_data.item.name))
94 msg_data.append([elt['id'], make_message(elt), date]) 113 if pep:
114 # we need to send privileged message
115 # so me manage the sending ourself, and return
116 # an empty msg_data list to avoid double sending
117 for data in msg_data:
118 self.forwardPEPMessage(mam_request, requestor, *data)
119 msg_data = []
95 return (msg_data, rsm_elt) 120 return (msg_data, rsm_elt)
96 121
97 d.addErrback(PubSubResourceFromBackend._mapErrors) 122 d.addErrback(self._mapErrors)
98 d.addCallback(cb) 123 d.addCallback(cb)
99 return d 124 return d
125
126 def forwardPEPMessage(self, mam_request, requestor, id_, elt, date):
127 msg = domish.Element((None, 'message'))
128 msg['from'] = self.backend.privilege.server_jid.full()
129 msg['to'] = requestor.full()
130 result = msg.addElement((mam.NS_MAM, 'result'))
131 if mam_request.query_id is not None:
132 result['queryid'] = mam_request.query_id
133 result['id'] = id_
134 forward = result.addElement((const.NS_FORWARD, 'forwarded'))
135 forward.addChild(delay.Delay(date).toElement())
136 forward.addChild(elt)
137 self.backend.privilege.sendMessage(msg)
100 138
101 def onPrefsGetRequest(self, requestor): 139 def onPrefsGetRequest(self, requestor):
102 """ 140 """
103 141
104 @param requestor: JID of the requestor. 142 @param requestor: JID of the requestor.