Mercurial > libervia-backend
comparison src/tmp/wokkel/mam.py @ 1286:d9939b476526
tmp: update wokkel MAM implementation
author | souliane <souliane@mailoo.org> |
---|---|
date | Thu, 15 Jan 2015 21:02:41 +0100 |
parents | ed2c718bfe03 |
children | e5393b12dd0f |
comparison
equal
deleted
inserted
replaced
1285:ed2c718bfe03 | 1286:d9939b476526 |
---|---|
9 This protocol is specified in | 9 This protocol is specified in |
10 U{XEP-0313<http://xmpp.org/extensions/xep-0313.html>}. | 10 U{XEP-0313<http://xmpp.org/extensions/xep-0313.html>}. |
11 """ | 11 """ |
12 | 12 |
13 from dateutil.tz import tzutc | 13 from dateutil.tz import tzutc |
14 | |
14 from zope.interface import Interface, implements | 15 from zope.interface import Interface, implements |
16 | |
15 from twisted.words.protocols.jabber.xmlstream import IQ, toResponse | 17 from twisted.words.protocols.jabber.xmlstream import IQ, toResponse |
16 from twisted.words.xish import domish | 18 from twisted.words.xish import domish |
17 from twisted.words.protocols.jabber import jid | 19 from twisted.words.protocols.jabber import jid |
20 from twisted.python import log | |
21 | |
18 from wokkel.subprotocols import IQHandlerMixin, XMPPHandler | 22 from wokkel.subprotocols import IQHandlerMixin, XMPPHandler |
19 from wokkel import disco, data_form | 23 from wokkel import disco, data_form, delay |
24 | |
20 import rsm | 25 import rsm |
21 | 26 |
22 NS_MAM = 'urn:xmpp:mam:0' | 27 NS_MAM = 'urn:xmpp:mam:0' |
28 NS_FORWARD = 'urn:xmpp:forward:0' | |
23 | 29 |
24 FIELDS_REQUEST = "/iq[@type='get']/query[@xmlns='%s']" % NS_MAM | 30 FIELDS_REQUEST = "/iq[@type='get']/query[@xmlns='%s']" % NS_MAM |
25 ARCHIVE_REQUEST = "/iq[@type='set']/query[@xmlns='%s']" % NS_MAM | 31 ARCHIVE_REQUEST = "/iq[@type='set']/query[@xmlns='%s']" % NS_MAM |
26 PREFS_GET_REQUEST = "/iq[@type='get']/prefs[@xmlns='%s']" % NS_MAM | 32 PREFS_GET_REQUEST = "/iq[@type='get']/prefs[@xmlns='%s']" % NS_MAM |
27 PREFS_SET_REQUEST = "/iq[@type='set']/prefs[@xmlns='%s']" % NS_MAM | 33 PREFS_SET_REQUEST = "/iq[@type='set']/prefs[@xmlns='%s']" % NS_MAM |
66 form = None | 72 form = None |
67 rsm = None | 73 rsm = None |
68 node = None | 74 node = None |
69 | 75 |
70 def __init__(self, form=None, rsm=None, node=None): | 76 def __init__(self, form=None, rsm=None, node=None): |
77 if form is not None: | |
78 assert(form.formType == 'submit') | |
71 self.form = form | 79 self.form = form |
72 self.rsm = rsm | 80 self.rsm = rsm |
73 self.node = node | 81 self.node = node |
74 | 82 |
75 @classmethod | 83 @classmethod |
313 return iq.send(to=service.full() if service else None) | 321 return iq.send(to=service.full() if service else None) |
314 | 322 |
315 | 323 |
316 class IMAMResource(Interface): | 324 class IMAMResource(Interface): |
317 | 325 |
318 def onArchiveRequest(self, mam, rsm, requestor): | 326 def onArchiveRequest(self, mam, requestor): |
319 """ | 327 """ |
320 | 328 |
321 @param mam: The MAM <query/> request. | 329 @param mam: The MAM <query/> request. |
322 @type mam: L{MAMQueryReques<wokkel.mam.MAMQueryRequest>} | 330 @type mam: L{MAMQueryReques<wokkel.mam.MAMQueryRequest>} |
323 | |
324 @param rsm: The RSM request. | |
325 @type rsm: L{RSMRequest<wokkel.rsm.RSMRequest>} | |
326 | 331 |
327 @param requestor: JID of the requestor. | 332 @param requestor: JID of the requestor. |
328 @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>} | 333 @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>} |
329 | 334 |
330 @return: The RSM answer. | 335 @return: The RSM answer. |
385 'label': 'Entity', | 390 'label': 'Entity', |
386 'desc': 'Entity against which to match message.', | 391 'desc': 'Entity against which to match message.', |
387 }, | 392 }, |
388 } | 393 } |
389 | 394 |
390 extra_filters = [] | 395 extra_filters = {} |
391 | 396 |
392 def __init__(self, resource): | 397 def __init__(self, resource): |
393 """ | 398 """ |
394 @param resource: instance implementing IMAMResource | 399 @param resource: instance implementing IMAMResource |
395 @type resource: L{object} | 400 @type resource: L{object} |
413 | 418 |
414 @param field: dictionary specifying the attributes to build a | 419 @param field: dictionary specifying the attributes to build a |
415 wokkel.data_form.Field. | 420 wokkel.data_form.Field. |
416 @type field: C{dict} | 421 @type field: C{dict} |
417 """ | 422 """ |
418 self.extra_filters.append(field) | 423 self.extra_filters[field.var] = field |
419 | 424 |
420 def _onFieldsRequest(self, iq): | 425 def _onFieldsRequest(self, iq): |
421 """ | 426 """ |
422 Called when a fields request has been received. | 427 Called when a fields request has been received. |
423 | 428 |
438 """ | 443 """ |
439 response = toResponse(iq, 'result') | 444 response = toResponse(iq, 'result') |
440 self.xmlstream.send(response) | 445 self.xmlstream.send(response) |
441 | 446 |
442 mam_ = MAMQueryRequest.parse(iq.query) | 447 mam_ = MAMQueryRequest.parse(iq.query) |
443 try: | |
444 rsm_ = rsm.RSMRequest.parse(iq.query) | |
445 except rsm.RSMNotFoundError: | |
446 rsm_ = None | |
447 requestor = jid.JID(iq['from']) | 448 requestor = jid.JID(iq['from']) |
448 rsm_response = self.resource.onArchiveRequest(mam_, rsm_, requestor) | 449 |
449 | 450 # remove unsupported filters |
450 msg = domish.Element((None, 'message')) | 451 unsupported_fields = [] |
451 fin = msg.addElement('fin', NS_MAM) | 452 if mam_.form: |
452 if iq.hasAttribute('queryid'): | 453 for key, field in mam_.form.fields.iteritems(): |
453 fin['queryid'] = iq.query['queryid'] | 454 if key not in self._legacyFilters and key not in self.extra_filters: |
454 if rsm_response is not None: | 455 log.msg('Ignored unsupported MAM filter: %s' % field) |
455 fin.addChild(rsm_response.toElement()) | 456 unsupported_fields.append(key) |
456 self.xmlstream.send(msg) | 457 for key in unsupported_fields: |
457 | 458 del mam_.form.fields[key] |
459 | |
460 def forward_message(id_, elt, date): | |
461 msg = domish.Element((None, 'message')) | |
462 msg['to'] = iq['from'] | |
463 result = msg.addElement('result', NS_MAM) | |
464 if iq.hasAttribute('queryid'): | |
465 result['queryid'] = iq.query['queryid'] | |
466 result['id'] = id_ | |
467 forward = result.addElement('forwarded', NS_FORWARD) | |
468 forward.addChild(delay.Delay(date).toElement()) | |
469 forward.addChild(elt) | |
470 self.xmlstream.send(msg) | |
471 | |
472 def cb(result): | |
473 msg_data, rsm_elt = result | |
474 for data in msg_data: | |
475 forward_message(*data) | |
476 msg = domish.Element((None, 'message')) | |
477 msg['to'] = iq['from'] | |
478 fin = msg.addElement('fin', NS_MAM) | |
479 if iq.hasAttribute('queryid'): | |
480 fin['queryid'] = iq.query['queryid'] | |
481 if rsm_elt is not None: | |
482 fin.addChild(rsm_elt) | |
483 self.xmlstream.send(msg) | |
484 | |
485 self.resource.onArchiveRequest(mam_, requestor).addCallback(cb) | |
458 iq.handled = True | 486 iq.handled = True |
459 | 487 |
460 def _onPrefsGetRequest(self, iq): | 488 def _onPrefsGetRequest(self, iq): |
461 """ | 489 """ |
462 Called when a prefs get request has been received. | 490 Called when a prefs get request has been received. |
464 This immediately replies with a result response. | 492 This immediately replies with a result response. |
465 """ | 493 """ |
466 response = toResponse(iq, 'result') | 494 response = toResponse(iq, 'result') |
467 | 495 |
468 requestor = jid.JID(iq['from']) | 496 requestor = jid.JID(iq['from']) |
469 prefs = self.resource.onPrefsGetRequest(requestor) | 497 |
470 | 498 def cb(prefs): |
471 response.addChild(prefs.toElement()) | 499 response.addChild(prefs.toElement()) |
472 self.xmlstream.send(response) | 500 self.xmlstream.send(response) |
501 | |
502 self.resource.onPrefsGetRequest(requestor).addCallback(cb) | |
473 iq.handled = True | 503 iq.handled = True |
474 | 504 |
475 def _onPrefsSetRequest(self, iq): | 505 def _onPrefsSetRequest(self, iq): |
476 """ | 506 """ |
477 Called when a prefs get request has been received. | 507 Called when a prefs get request has been received. |
480 """ | 510 """ |
481 response = toResponse(iq, 'result') | 511 response = toResponse(iq, 'result') |
482 | 512 |
483 prefs = MAMPrefs.parse(iq.prefs) | 513 prefs = MAMPrefs.parse(iq.prefs) |
484 requestor = jid.JID(iq['from']) | 514 requestor = jid.JID(iq['from']) |
485 prefs = self.resource.onPrefsSetRequest(prefs, requestor) | 515 |
486 | 516 def cb(prefs): |
487 response.addChild(prefs.toElement()) | 517 response.addChild(prefs.toElement()) |
488 self.xmlstream.send(response) | 518 self.xmlstream.send(response) |
519 | |
520 self.resource.onPrefsSetRequest(prefs, requestor).addCallback(cb) | |
489 iq.handled = True | 521 iq.handled = True |
490 | 522 |
491 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): | 523 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): |
492 return [disco.DiscoFeature(NS_MAM)] | 524 return [disco.DiscoFeature(NS_MAM)] |
493 | 525 |