Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0313.py @ 3028:ab2696e34d29
Python 3 port:
/!\ this is a huge commit
/!\ starting from this commit, SàT is needs Python 3.6+
/!\ SàT maybe be instable or some feature may not work anymore, this will improve with time
This patch port backend, bridge and frontends to Python 3.
Roughly this has been done this way:
- 2to3 tools has been applied (with python 3.7)
- all references to python2 have been replaced with python3 (notably shebangs)
- fixed files not handled by 2to3 (notably the shell script)
- several manual fixes
- fixed issues reported by Python 3 that where not handled in Python 2
- replaced "async" with "async_" when needed (it's a reserved word from Python 3.7)
- replaced zope's "implements" with @implementer decorator
- temporary hack to handle data pickled in database, as str or bytes may be returned,
to be checked later
- fixed hash comparison for password
- removed some code which is not needed anymore with Python 3
- deactivated some code which needs to be checked (notably certificate validation)
- tested with jp, fixed reported issues until some basic commands worked
- ported Primitivus (after porting dependencies like urwid satext)
- more manual fixes
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 13 Aug 2019 19:08:41 +0200 |
parents | 1f74cd0f22c3 |
children | 9d0df638c8b4 |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # SAT plugin for Message Archive Management (XEP-0313) | 4 # SAT plugin for Message Archive Management (XEP-0313) |
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
6 # Copyright (C) 2013-2016 Adrien Cossa (souliane@mailoo.org) | 6 # Copyright (C) 2013-2016 Adrien Cossa (souliane@mailoo.org) |
23 from sat.core.log import getLogger | 23 from sat.core.log import getLogger |
24 from sat.core import exceptions | 24 from sat.core import exceptions |
25 from sat.tools.common import data_format | 25 from sat.tools.common import data_format |
26 from twisted.words.protocols.jabber import jid | 26 from twisted.words.protocols.jabber import jid |
27 from twisted.internet import defer | 27 from twisted.internet import defer |
28 from zope.interface import implements | 28 from zope.interface import implementer |
29 from datetime import datetime | 29 from datetime import datetime |
30 from dateutil import tz | 30 from dateutil import tz |
31 from wokkel import disco | 31 from wokkel import disco |
32 from wokkel import data_form | 32 from wokkel import data_form |
33 import uuid | 33 import uuid |
38 | 38 |
39 | 39 |
40 log = getLogger(__name__) | 40 log = getLogger(__name__) |
41 | 41 |
42 PLUGIN_INFO = { | 42 PLUGIN_INFO = { |
43 C.PI_NAME: u"Message Archive Management", | 43 C.PI_NAME: "Message Archive Management", |
44 C.PI_IMPORT_NAME: u"XEP-0313", | 44 C.PI_IMPORT_NAME: "XEP-0313", |
45 C.PI_TYPE: u"XEP", | 45 C.PI_TYPE: "XEP", |
46 C.PI_PROTOCOLS: [u"XEP-0313"], | 46 C.PI_PROTOCOLS: ["XEP-0313"], |
47 C.PI_DEPENDENCIES: [u"XEP-0059", u"XEP-0359"], | 47 C.PI_DEPENDENCIES: ["XEP-0059", "XEP-0359"], |
48 C.PI_MAIN: u"XEP_0313", | 48 C.PI_MAIN: "XEP_0313", |
49 C.PI_HANDLER: u"yes", | 49 C.PI_HANDLER: "yes", |
50 C.PI_DESCRIPTION: _(u"""Implementation of Message Archive Management"""), | 50 C.PI_DESCRIPTION: _("""Implementation of Message Archive Management"""), |
51 } | 51 } |
52 | 52 |
53 MAM_PREFIX = u"mam_" | 53 MAM_PREFIX = "mam_" |
54 FILTER_PREFIX = MAM_PREFIX + "filter_" | 54 FILTER_PREFIX = MAM_PREFIX + "filter_" |
55 KEY_LAST_STANZA_ID = u"last_stanza_id" | 55 KEY_LAST_STANZA_ID = "last_stanza_id" |
56 MESSAGE_RESULT = "/message/result[@xmlns='{mam_ns}' and @queryid='{query_id}']" | 56 MESSAGE_RESULT = "/message/result[@xmlns='{mam_ns}' and @queryid='{query_id}']" |
57 MESSAGE_STANZA_ID = '/message/stanza-id[@xmlns="{ns_stanza_id}"]' | 57 MESSAGE_STANZA_ID = '/message/stanza-id[@xmlns="{ns_stanza_id}"]' |
58 | 58 |
59 | 59 |
60 class XEP_0313(object): | 60 class XEP_0313(object): |
61 def __init__(self, host): | 61 def __init__(self, host): |
62 log.info(_("Message Archive Management plugin initialization")) | 62 log.info(_("Message Archive Management plugin initialization")) |
63 self.host = host | 63 self.host = host |
64 self.host.registerNamespace(u"mam", mam.NS_MAM) | 64 self.host.registerNamespace("mam", mam.NS_MAM) |
65 self._rsm = host.plugins[u"XEP-0059"] | 65 self._rsm = host.plugins["XEP-0059"] |
66 self._sid = host.plugins[u"XEP-0359"] | 66 self._sid = host.plugins["XEP-0359"] |
67 # Deferred used to store last stanza id in order of reception | 67 # Deferred used to store last stanza id in order of reception |
68 self._last_stanza_id_d = defer.Deferred() | 68 self._last_stanza_id_d = defer.Deferred() |
69 self._last_stanza_id_d.callback(None) | 69 self._last_stanza_id_d.callback(None) |
70 host.bridge.addMethod( | 70 host.bridge.addMethod( |
71 "MAMGet", ".plugin", in_sign='sss', | 71 "MAMGet", ".plugin", in_sign='sss', |
72 out_sign='(a(sdssa{ss}a{ss}sa{ss})a{ss}s)', method=self._getArchives, | 72 out_sign='(a(sdssa{ss}a{ss}sa{ss})a{ss}s)', method=self._getArchives, |
73 async=True) | 73 async_=True) |
74 | 74 |
75 @defer.inlineCallbacks | 75 @defer.inlineCallbacks |
76 def resume(self, client): | 76 def resume(self, client): |
77 """Retrieve one2one messages received since the last we have in local storage""" | 77 """Retrieve one2one messages received since the last we have in local storage""" |
78 stanza_id_data = yield self.host.memory.storage.getPrivates( | 78 stanza_id_data = yield self.host.memory.storage.getPrivates( |
79 mam.NS_MAM, [KEY_LAST_STANZA_ID], profile=client.profile) | 79 mam.NS_MAM, [KEY_LAST_STANZA_ID], profile=client.profile) |
80 stanza_id = stanza_id_data.get(KEY_LAST_STANZA_ID) | 80 stanza_id = stanza_id_data.get(KEY_LAST_STANZA_ID) |
81 if stanza_id is None: | 81 if stanza_id is None: |
82 log.info(u"can't retrieve last stanza ID, checking history") | 82 log.info("can't retrieve last stanza ID, checking history") |
83 last_mess = yield self.host.memory.historyGet( | 83 last_mess = yield self.host.memory.historyGet( |
84 None, None, limit=1, filters={u'not_types': C.MESS_TYPE_GROUPCHAT, | 84 None, None, limit=1, filters={'not_types': C.MESS_TYPE_GROUPCHAT, |
85 u'last_stanza_id': True}, | 85 'last_stanza_id': True}, |
86 profile=client.profile) | 86 profile=client.profile) |
87 if not last_mess: | 87 if not last_mess: |
88 log.info(_(u"It seems that we have no MAM history yet")) | 88 log.info(_("It seems that we have no MAM history yet")) |
89 return | 89 return |
90 stanza_id = last_mess[0][-1][u'stanza_id'] | 90 stanza_id = last_mess[0][-1]['stanza_id'] |
91 rsm_req = rsm.RSMRequest(max_=100, after=stanza_id) | 91 rsm_req = rsm.RSMRequest(max_=100, after=stanza_id) |
92 mam_req = mam.MAMRequest(rsm_=rsm_req) | 92 mam_req = mam.MAMRequest(rsm_=rsm_req) |
93 complete = False | 93 complete = False |
94 count = 0 | 94 count = 0 |
95 while not complete: | 95 while not complete: |
96 mam_data = yield self.getArchives(client, mam_req, | 96 mam_data = yield self.getArchives(client, mam_req, |
97 service=client.jid.userhostJID()) | 97 service=client.jid.userhostJID()) |
98 elt_list, rsm_response, mam_response = mam_data | 98 elt_list, rsm_response, mam_response = mam_data |
99 complete = mam_response[u"complete"] | 99 complete = mam_response["complete"] |
100 # we update MAM request for next iteration | 100 # we update MAM request for next iteration |
101 mam_req.rsm.after = rsm_response.last | 101 mam_req.rsm.after = rsm_response.last |
102 if not elt_list: | 102 if not elt_list: |
103 break | 103 break |
104 else: | 104 else: |
112 continue | 112 continue |
113 | 113 |
114 try: | 114 try: |
115 destinee = jid.JID(fwd_message_elt['to']) | 115 destinee = jid.JID(fwd_message_elt['to']) |
116 except KeyError: | 116 except KeyError: |
117 log.warning(_(u'missing "to" attribute in forwarded message')) | 117 log.warning(_('missing "to" attribute in forwarded message')) |
118 destinee = client.jid | 118 destinee = client.jid |
119 if destinee.userhostJID() == client.jid.userhostJID(): | 119 if destinee.userhostJID() == client.jid.userhostJID(): |
120 # message to use, we insert the forwarded message in the normal | 120 # message to use, we insert the forwarded message in the normal |
121 # workflow | 121 # workflow |
122 client.xmlstream.dispatch(fwd_message_elt) | 122 client.xmlstream.dispatch(fwd_message_elt) |
123 else: | 123 else: |
124 # this message should be from us, we just add it to history | 124 # this message should be from us, we just add it to history |
125 try: | 125 try: |
126 from_jid = jid.JID(fwd_message_elt['from']) | 126 from_jid = jid.JID(fwd_message_elt['from']) |
127 except KeyError: | 127 except KeyError: |
128 log.warning(_(u'missing "from" attribute in forwarded message')) | 128 log.warning(_('missing "from" attribute in forwarded message')) |
129 from_jid = client.jid | 129 from_jid = client.jid |
130 if from_jid.userhostJID() != client.jid.userhostJID(): | 130 if from_jid.userhostJID() != client.jid.userhostJID(): |
131 log.warning(_( | 131 log.warning(_( |
132 u'was expecting a message sent by our jid, but this one if ' | 132 'was expecting a message sent by our jid, but this one if ' |
133 u'from {from_jid}, ignoring\n{xml}').format( | 133 'from {from_jid}, ignoring\n{xml}').format( |
134 from_jid=from_jid.full(), xml=mess_elt.toXml())) | 134 from_jid=from_jid.full(), xml=mess_elt.toXml())) |
135 continue | 135 continue |
136 # adding message to history | 136 # adding message to history |
137 mess_data = client.messageProt.parseMessage(fwd_message_elt) | 137 mess_data = client.messageProt.parseMessage(fwd_message_elt) |
138 try: | 138 try: |
139 yield client.messageProt.addToHistory(mess_data) | 139 yield client.messageProt.addToHistory(mess_data) |
140 except exceptions.CancelError as e: | 140 except exceptions.CancelError as e: |
141 log.warning( | 141 log.warning( |
142 u"message has not been added to history: {e}".format(e=e)) | 142 "message has not been added to history: {e}".format(e=e)) |
143 except Exception as e: | 143 except Exception as e: |
144 log.error( | 144 log.error( |
145 u"can't add message to history: {e}\n{xml}" | 145 "can't add message to history: {e}\n{xml}" |
146 .format(e=e, xml=mess_elt.toXml())) | 146 .format(e=e, xml=mess_elt.toXml())) |
147 | 147 |
148 if not count: | 148 if not count: |
149 log.info(_(u"We have received no message while offline")) | 149 log.info(_("We have received no message while offline")) |
150 else: | 150 else: |
151 log.info(_(u"We have received {num_mess} message(s) while offline.") | 151 log.info(_("We have received {num_mess} message(s) while offline.") |
152 .format(num_mess=count)) | 152 .format(num_mess=count)) |
153 | 153 |
154 def profileConnected(self, client): | 154 def profileConnected(self, client): |
155 return self.resume(client) | 155 return self.resume(client) |
156 | 156 |
166 @return (data_form, None): request with parsed arguments | 166 @return (data_form, None): request with parsed arguments |
167 or None if no MAM arguments have been found | 167 or None if no MAM arguments have been found |
168 """ | 168 """ |
169 mam_args = {} | 169 mam_args = {} |
170 form_args = {} | 170 form_args = {} |
171 for arg in (u"start", u"end"): | 171 for arg in ("start", "end"): |
172 try: | 172 try: |
173 value = extra.pop(MAM_PREFIX + arg) | 173 value = extra.pop(MAM_PREFIX + arg) |
174 form_args[arg] = datetime.fromtimestamp(float(value), tz.tzutc()) | 174 form_args[arg] = datetime.fromtimestamp(float(value), tz.tzutc()) |
175 except (TypeError, ValueError): | 175 except (TypeError, ValueError): |
176 log.warning(u"Bad value for {arg} filter ({value}), ignoring".format( | 176 log.warning("Bad value for {arg} filter ({value}), ignoring".format( |
177 arg=arg, value=value)) | 177 arg=arg, value=value)) |
178 except KeyError: | 178 except KeyError: |
179 continue | 179 continue |
180 | 180 |
181 try: | 181 try: |
182 form_args[u"with_jid"] = jid.JID(extra.pop( | 182 form_args["with_jid"] = jid.JID(extra.pop( |
183 MAM_PREFIX + u"with")) | 183 MAM_PREFIX + "with")) |
184 except (jid.InvalidFormat): | 184 except (jid.InvalidFormat): |
185 log.warning(u"Bad value for jid filter") | 185 log.warning("Bad value for jid filter") |
186 except KeyError: | 186 except KeyError: |
187 pass | 187 pass |
188 | 188 |
189 for name, value in extra.iteritems(): | 189 for name, value in extra.items(): |
190 if name.startswith(FILTER_PREFIX): | 190 if name.startswith(FILTER_PREFIX): |
191 var = name[len(FILTER_PREFIX):] | 191 var = name[len(FILTER_PREFIX):] |
192 extra_fields = form_args.setdefault(u"extra_fields", []) | 192 extra_fields = form_args.setdefault("extra_fields", []) |
193 extra_fields.append(data_form.Field(var=var, value=value)) | 193 extra_fields.append(data_form.Field(var=var, value=value)) |
194 | 194 |
195 for arg in (u"node", u"query_id"): | 195 for arg in ("node", "query_id"): |
196 try: | 196 try: |
197 value = extra.pop(MAM_PREFIX + arg) | 197 value = extra.pop(MAM_PREFIX + arg) |
198 mam_args[arg] = value | 198 mam_args[arg] = value |
199 except KeyError: | 199 except KeyError: |
200 continue | 200 continue |
207 if form_args: | 207 if form_args: |
208 mam_args["form"] = mam.buildForm(**form_args) | 208 mam_args["form"] = mam.buildForm(**form_args) |
209 | 209 |
210 # we only set orderBy if we have other MAM args | 210 # we only set orderBy if we have other MAM args |
211 # else we would make a MAM query while it's not expected | 211 # else we would make a MAM query while it's not expected |
212 if u"order_by" in extra and mam_args: | 212 if "order_by" in extra and mam_args: |
213 order_by = extra.pop(u"order_by") | 213 order_by = extra.pop("order_by") |
214 assert isinstance(order_by, list) | 214 assert isinstance(order_by, list) |
215 mam_args["orderBy"] = order_by | 215 mam_args["orderBy"] = order_by |
216 | 216 |
217 return mam.MAMRequest(**mam_args) if mam_args else None | 217 return mam.MAMRequest(**mam_args) if mam_args else None |
218 | 218 |
228 If None, a new dict is created | 228 If None, a new dict is created |
229 @return (dict): data dict | 229 @return (dict): data dict |
230 """ | 230 """ |
231 if data is None: | 231 if data is None: |
232 data = {} | 232 data = {} |
233 data[u"mam_complete"] = C.boolConst(mam_response[u'complete']) | 233 data["mam_complete"] = C.boolConst(mam_response['complete']) |
234 data[u"mam_stable"] = C.boolConst(mam_response[u'stable']) | 234 data["mam_stable"] = C.boolConst(mam_response['stable']) |
235 return data | 235 return data |
236 | 236 |
237 def getMessageFromResult(self, client, mess_elt, mam_req, service=None): | 237 def getMessageFromResult(self, client, mess_elt, mam_req, service=None): |
238 """Extract usable <message/> from MAM query result | 238 """Extract usable <message/> from MAM query result |
239 | 239 |
243 @param mam_req(mam.MAMRequest): request used (needed to get query_id) | 243 @param mam_req(mam.MAMRequest): request used (needed to get query_id) |
244 @param service(jid.JID, None): MAM service where the request has been sent | 244 @param service(jid.JID, None): MAM service where the request has been sent |
245 None if it's user server | 245 None if it's user server |
246 @return domish.Element): <message/> that can be used directly with onMessage | 246 @return domish.Element): <message/> that can be used directly with onMessage |
247 """ | 247 """ |
248 if mess_elt.name != u"message": | 248 if mess_elt.name != "message": |
249 log.warning(u"unexpected stanza in archive: {xml}".format( | 249 log.warning("unexpected stanza in archive: {xml}".format( |
250 xml=mess_elt.toXml())) | 250 xml=mess_elt.toXml())) |
251 raise exceptions.DataError(u"Invalid element") | 251 raise exceptions.DataError("Invalid element") |
252 service_jid = client.jid.userhostJID() if service is None else service | 252 service_jid = client.jid.userhostJID() if service is None else service |
253 mess_from = mess_elt[u"from"] | 253 mess_from = mess_elt["from"] |
254 # we check that the message has been sent by the right service | 254 # we check that the message has been sent by the right service |
255 # if service is None (i.e. message expected from our own server) | 255 # if service is None (i.e. message expected from our own server) |
256 # from can be server jid or user's bare jid | 256 # from can be server jid or user's bare jid |
257 if (mess_from != service_jid.full() | 257 if (mess_from != service_jid.full() |
258 and not (service is None and mess_from == client.jid.host)): | 258 and not (service is None and mess_from == client.jid.host)): |
259 log.error(u"Message is not from our server, something went wrong: " | 259 log.error("Message is not from our server, something went wrong: " |
260 u"{xml}".format(xml=mess_elt.toXml())) | 260 "{xml}".format(xml=mess_elt.toXml())) |
261 raise exceptions.DataError(u"Invalid element") | 261 raise exceptions.DataError("Invalid element") |
262 try: | 262 try: |
263 result_elt = next(mess_elt.elements(mam.NS_MAM, u"result")) | 263 result_elt = next(mess_elt.elements(mam.NS_MAM, "result")) |
264 forwarded_elt = next(result_elt.elements(C.NS_FORWARD, u"forwarded")) | 264 forwarded_elt = next(result_elt.elements(C.NS_FORWARD, "forwarded")) |
265 try: | 265 try: |
266 delay_elt = next(forwarded_elt.elements(C.NS_DELAY, u"delay")) | 266 delay_elt = next(forwarded_elt.elements(C.NS_DELAY, "delay")) |
267 except StopIteration: | 267 except StopIteration: |
268 # delay_elt is not mandatory | 268 # delay_elt is not mandatory |
269 delay_elt = None | 269 delay_elt = None |
270 fwd_message_elt = next(forwarded_elt.elements(C.NS_CLIENT, u"message")) | 270 fwd_message_elt = next(forwarded_elt.elements(C.NS_CLIENT, "message")) |
271 except StopIteration: | 271 except StopIteration: |
272 log.warning(u"Invalid message received from MAM: {xml}".format( | 272 log.warning("Invalid message received from MAM: {xml}".format( |
273 xml=mess_elt.toXml())) | 273 xml=mess_elt.toXml())) |
274 raise exceptions.DataError(u"Invalid element") | 274 raise exceptions.DataError("Invalid element") |
275 else: | 275 else: |
276 if not result_elt[u"queryid"] == mam_req.query_id: | 276 if not result_elt["queryid"] == mam_req.query_id: |
277 log.error(u"Unexpected query id (was expecting {query_id}): {xml}" | 277 log.error("Unexpected query id (was expecting {query_id}): {xml}" |
278 .format(query_id=mam.query_id, xml=mess_elt.toXml())) | 278 .format(query_id=mam.query_id, xml=mess_elt.toXml())) |
279 raise exceptions.DataError(u"Invalid element") | 279 raise exceptions.DataError("Invalid element") |
280 stanza_id = self._sid.getStanzaId(fwd_message_elt, | 280 stanza_id = self._sid.getStanzaId(fwd_message_elt, |
281 service_jid) | 281 service_jid) |
282 if stanza_id is None: | 282 if stanza_id is None: |
283 # not stanza-id element is present, we add one so message | 283 # not stanza-id element is present, we add one so message |
284 # will be archived with it, and we won't request several times | 284 # will be archived with it, and we won't request several times |
285 # the same MAM achive | 285 # the same MAM achive |
286 try: | 286 try: |
287 stanza_id = result_elt[u"id"] | 287 stanza_id = result_elt["id"] |
288 except AttributeError: | 288 except AttributeError: |
289 log.warning(u'Invalid MAM result: missing "id" attribute: {xml}' | 289 log.warning('Invalid MAM result: missing "id" attribute: {xml}' |
290 .format(xml=result_elt.toXml())) | 290 .format(xml=result_elt.toXml())) |
291 raise exceptions.DataError(u"Invalid element") | 291 raise exceptions.DataError("Invalid element") |
292 self._sid.addStanzaId(client, fwd_message_elt, stanza_id, by=service_jid) | 292 self._sid.addStanzaId(client, fwd_message_elt, stanza_id, by=service_jid) |
293 | 293 |
294 if delay_elt is not None: | 294 if delay_elt is not None: |
295 fwd_message_elt.addChild(delay_elt) | 295 fwd_message_elt.addChild(delay_elt) |
296 | 296 |
321 elt_list.append(message_elt) | 321 elt_list.append(message_elt) |
322 | 322 |
323 def _queryFinished(self, iq_result, client, elt_list, event): | 323 def _queryFinished(self, iq_result, client, elt_list, event): |
324 client.xmlstream.removeObserver(event, self._appendMessage) | 324 client.xmlstream.removeObserver(event, self._appendMessage) |
325 try: | 325 try: |
326 fin_elt = iq_result.elements(mam.NS_MAM, "fin").next() | 326 fin_elt = next(iq_result.elements(mam.NS_MAM, "fin")) |
327 except StopIteration: | 327 except StopIteration: |
328 raise exceptions.DataError(u"Invalid MAM result") | 328 raise exceptions.DataError("Invalid MAM result") |
329 | 329 |
330 mam_response = {u"complete": C.bool(fin_elt.getAttribute(u"complete", C.BOOL_FALSE)), | 330 mam_response = {"complete": C.bool(fin_elt.getAttribute("complete", C.BOOL_FALSE)), |
331 u"stable": C.bool(fin_elt.getAttribute(u"stable", C.BOOL_TRUE))} | 331 "stable": C.bool(fin_elt.getAttribute("stable", C.BOOL_TRUE))} |
332 | 332 |
333 try: | 333 try: |
334 rsm_response = rsm.RSMResponse.fromElement(fin_elt) | 334 rsm_response = rsm.RSMResponse.fromElement(fin_elt) |
335 except rsm.RSMNotFoundError: | 335 except rsm.RSMNotFoundError: |
336 rsm_response = None | 336 rsm_response = None |
381 - MAM response, which is a dict with following value: | 381 - MAM response, which is a dict with following value: |
382 - complete: a boolean which is True if all items have been received | 382 - complete: a boolean which is True if all items have been received |
383 - stable: a boolean which is False if items order may be changed | 383 - stable: a boolean which is False if items order may be changed |
384 """ | 384 """ |
385 if query.query_id is None: | 385 if query.query_id is None: |
386 query.query_id = unicode(uuid.uuid4()) | 386 query.query_id = str(uuid.uuid4()) |
387 elt_list = [] | 387 elt_list = [] |
388 event = MESSAGE_RESULT.format(mam_ns=mam.NS_MAM, query_id=query.query_id) | 388 event = MESSAGE_RESULT.format(mam_ns=mam.NS_MAM, query_id=query.query_id) |
389 client.xmlstream.addObserver(event, self._appendMessage, 0, elt_list, message_cb) | 389 client.xmlstream.addObserver(event, self._appendMessage, 0, elt_list, message_cb) |
390 d = self.queryArchive(client, query, service) | 390 d = self.queryArchive(client, query, service) |
391 d.addCallback(self._queryFinished, client, elt_list, event) | 391 d.addCallback(self._queryFinished, client, elt_list, event) |
429 @param message_elt(domish.Element): <message> with a stanza-id | 429 @param message_elt(domish.Element): <message> with a stanza-id |
430 """ | 430 """ |
431 service_jid = client.jid.userhostJID() | 431 service_jid = client.jid.userhostJID() |
432 stanza_id = self._sid.getStanzaId(message_elt, service_jid) | 432 stanza_id = self._sid.getStanzaId(message_elt, service_jid) |
433 if stanza_id is None: | 433 if stanza_id is None: |
434 log.debug(u"Ignoring <message>, stanza id is not from our server") | 434 log.debug("Ignoring <message>, stanza id is not from our server") |
435 else: | 435 else: |
436 # we use self._last_stanza_id_d do be sure that last_stanza_id is stored in | 436 # we use self._last_stanza_id_d do be sure that last_stanza_id is stored in |
437 # the order of reception | 437 # the order of reception |
438 self._last_stanza_id_d.addCallback( | 438 self._last_stanza_id_d.addCallback( |
439 lambda __: self.host.memory.storage.setPrivateValue( | 439 lambda __: self.host.memory.storage.setPrivateValue( |
441 key=KEY_LAST_STANZA_ID, | 441 key=KEY_LAST_STANZA_ID, |
442 value=stanza_id, | 442 value=stanza_id, |
443 profile=client.profile)) | 443 profile=client.profile)) |
444 | 444 |
445 | 445 |
446 @implementer(disco.IDisco) | |
446 class SatMAMClient(mam.MAMClient): | 447 class SatMAMClient(mam.MAMClient): |
447 implements(disco.IDisco) | |
448 | 448 |
449 def __init__(self, plugin_parent): | 449 def __init__(self, plugin_parent): |
450 self.plugin_parent = plugin_parent | 450 self.plugin_parent = plugin_parent |
451 | 451 |
452 @property | 452 @property |
453 def host(self): | 453 def host(self): |
454 return self.parent.host_app | 454 return self.parent.host_app |
455 | 455 |
456 def connectionInitialized(self): | 456 def connectionInitialized(self): |
457 observer_xpath = MESSAGE_STANZA_ID.format( | 457 observer_xpath = MESSAGE_STANZA_ID.format( |
458 ns_stanza_id=self.host.ns_map[u'stanza_id']) | 458 ns_stanza_id=self.host.ns_map['stanza_id']) |
459 self.xmlstream.addObserver( | 459 self.xmlstream.addObserver( |
460 observer_xpath, self.plugin_parent.onMessageStanzaId, client=self.parent | 460 observer_xpath, self.plugin_parent.onMessageStanzaId, client=self.parent |
461 ) | 461 ) |
462 | 462 |
463 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): | 463 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): |