comparison sat/plugins/plugin_xep_0060.py @ 2800:3b68293a60d4

plugin XEP-0060: added sendItems/psItemsSend method to publish several items at once
author Goffi <goffi@goffi.org>
date Fri, 15 Feb 2019 22:13:20 +0100
parents 838f53730ce4
children ae127e14b040
comparison
equal deleted inserted replaced
2799:202e2d8e3d7b 2800:3b68293a60d4
27 27
28 from twisted.words.protocols.jabber import jid, error 28 from twisted.words.protocols.jabber import jid, error
29 from twisted.internet import reactor, defer 29 from twisted.internet import reactor, defer
30 from wokkel import disco 30 from wokkel import disco
31 from wokkel import data_form 31 from wokkel import data_form
32 from wokkel import generic
32 from zope.interface import implements 33 from zope.interface import implements
33 from collections import namedtuple 34 from collections import namedtuple
34 import urllib 35 import urllib
35 36
36 # XXX: sat_tmp.wokkel.pubsub is actually use instead of wokkel version 37 # XXX: sat_tmp.wokkel.pubsub is actually use instead of wokkel version
186 "psItemSend", 187 "psItemSend",
187 ".plugin", 188 ".plugin",
188 in_sign="ssssa{ss}s", 189 in_sign="ssssa{ss}s",
189 out_sign="s", 190 out_sign="s",
190 method=self._sendItem, 191 method=self._sendItem,
192 async=True,
193 )
194 host.bridge.addMethod(
195 "psItemsSend",
196 ".plugin",
197 in_sign="ssasa{ss}s",
198 out_sign="as",
199 method=self._sendItems,
191 async=True, 200 async=True,
192 ) 201 )
193 host.bridge.addMethod( 202 host.bridge.addMethod(
194 "psRetractItem", 203 "psRetractItem",
195 ".plugin", 204 ".plugin",
437 client, service, nodeIdentifier, payload, item_id or None, extra 446 client, service, nodeIdentifier, payload, item_id or None, extra
438 ) 447 )
439 d.addCallback(lambda ret: ret or u"") 448 d.addCallback(lambda ret: ret or u"")
440 return d 449 return d
441 450
451 def _sendItems(self, service, nodeIdentifier, items, extra=None,
452 profile_key=C.PROF_KEY_NONE):
453 client = self.host.getClient(profile_key)
454 service = None if not service else jid.JID(service)
455 try:
456 items = [generic.parseXml(item.encode('utf-8')) for item in items]
457 except Exception as e:
458 raise exceptions.DataError(_(u"Can't parse items: {msg}").format(
459 msg=e))
460 d = self.sendItems(
461 client, service, nodeIdentifier, items, extra
462 )
463 return d
464
442 def _getPublishedItemId(self, iq_elt, original_id): 465 def _getPublishedItemId(self, iq_elt, original_id):
443 """return item of published id if found in answer 466 """return item of published id if found in answer
444 467
445 if not found original_id is returned, or empty string if it is None or empty string 468 if not found original_id is returned, or empty string if it is None or empty
469 string
446 """ 470 """
447 try: 471 try:
448 item_id = iq_elt.pubsub.publish.item["id"] 472 item_id = iq_elt.pubsub.publish.item["id"]
449 except (AttributeError, KeyError): 473 except (AttributeError, KeyError):
450 item_id = None 474 item_id = None
451 return item_id or original_id 475 return item_id or original_id
452 476
453 def sendItem( 477 def sendItem(self, client, service, nodeIdentifier, payload, item_id=None,
454 self, client, service, nodeIdentifier, payload, item_id=None, extra=None 478 extra=None):
455 ): 479 """High level method to send one item
456 """high level method to send one item
457 480
458 @param service(jid.JID, None): service to send the item to 481 @param service(jid.JID, None): service to send the item to
459 None to use PEP 482 None to use PEP
460 @param NodeIdentifier(unicode): PubSub node to use 483 @param NodeIdentifier(unicode): PubSub node to use
484 @param payload(domish.Element, unicode): payload of the item to send
461 @param item_id(unicode, None): id to use or None to create one 485 @param item_id(unicode, None): id to use or None to create one
462 @param payload(domish.Element, unicode): payload of the item to send
463 @param extra(dict, None): extra option, not used yet 486 @param extra(dict, None): extra option, not used yet
464 @return (unicode, None): id of the created item 487 @return (unicode, None): id of the created item
465 """ 488 """
466 item_elt = pubsub.Item(id=item_id, payload=payload) 489 item_elt = pubsub.Item(id=item_id, payload=payload)
467 d = self.publish(client, service, nodeIdentifier, [item_elt]) 490 d = self.publish(client, service, nodeIdentifier, [item_elt])
468 d.addCallback(self._getPublishedItemId, item_id) 491 d.addCallback(self._getPublishedItemId, item_id)
492 return d
493
494 def _publishCb(self, iq_result):
495 """Parse publish result, and return ids given by pubsub service"""
496 try:
497 item_ids = [item['id']
498 for item in iq_result.pubsub.publish.elements(pubsub.NS_PUBSUB, u'item')]
499 except AttributeError:
500 return []
501 return item_ids
502
503 def sendItems(self, client, service, nodeIdentifier, items, extra=None):
504 """High level method to send several items at once
505
506 @param service(jid.JID, None): service to send the item to
507 None to use PEP
508 @param NodeIdentifier(unicode): PubSub node to use
509 @param items(list[domish.Element]): whole item elements to send,
510 "id" will be used if set
511 @param extra(dict, None): extra option, not used yet
512 @return (list[unicode]): ids of the created items
513 """
514 parsed_items = []
515 for item in items:
516 if item.name != u'item':
517 raise exceptions.DataError(_(u"Invalid item: {xml}").format(item.toXml()))
518 item_id = item.getAttribute(u"id")
519 parsed_items.append(pubsub.Item(id=item_id, payload=item.firstChildElement()))
520 d = self.publish(client, service, nodeIdentifier, parsed_items)
521 d.addCallback(self._publishCb)
469 return d 522 return d
470 523
471 def publish(self, client, service, nodeIdentifier, items=None): 524 def publish(self, client, service, nodeIdentifier, items=None):
472 return client.pubsub_client.publish( 525 return client.pubsub_client.publish(
473 service, nodeIdentifier, items, client.pubsub_client.parent.jid 526 service, nodeIdentifier, items, client.pubsub_client.parent.jid