Mercurial > libervia-pubsub
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. |