comparison src/plugins/plugin_misc_groupblog.py @ 1420:7c0acb966fd6

plugins groupblog, xep-0060: first pass of simplification
author Goffi <goffi@goffi.org>
date Wed, 22 Apr 2015 20:21:55 +0200
parents be2df1ddea8e
children 882e5fabf68c
comparison
equal deleted inserted replaced
1419:be2df1ddea8e 1420:7c0acb966fd6
141 method=self._massiveSubscribeGroupBlogs, 141 method=self._massiveSubscribeGroupBlogs,
142 async=True) 142 async=True)
143 143
144 host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger) 144 host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger)
145 145
146 ## plugin management methods ##
147
146 def getHandler(self, profile): 148 def getHandler(self, profile):
147 return GroupBlog_handler() 149 return GroupBlog_handler()
148 150
149 @defer.inlineCallbacks 151 @defer.inlineCallbacks
150 def _initialise(self, profile_key): 152 def _initialise(self, profile_key):
210 d = self._handleCommentsItems(event.items, event.sender, event.nodeIdentifier) 212 d = self._handleCommentsItems(event.items, event.sender, event.nodeIdentifier)
211 d.addCallback(gbdataManagementComments) 213 d.addCallback(gbdataManagementComments)
212 return False 214 return False
213 return True 215 return True
214 216
217 ## internal helping methodes ##
218
215 def _handleCommentsItems(self, items, service, node_identifier): 219 def _handleCommentsItems(self, items, service, node_identifier):
216 """ Convert comments items to groupblog data, and send them as signals 220 """ Convert comments items to groupblog data, and send them as signals
217 221
218 @param items: comments items 222 @param items: comments items
219 @param service: jid of the PubSub service used 223 @param service: jid of the PubSub service used
266 @param publisher: publisher's jid 270 @param publisher: publisher's jid
267 @return: node's name (string) 271 @return: node's name (string)
268 """ 272 """
269 return NS_NODE_PREFIX + publisher.userhost() 273 return NS_NODE_PREFIX + publisher.userhost()
270 274
275 ## publish ##
276
271 def _publishMblog(self, service, client, access_type, access_list, message, extra): 277 def _publishMblog(self, service, client, access_type, access_list, message, extra):
272 """Actually publish the message on the group blog 278 """Actually publish the message on the group blog
273 279
274 @param service: jid of the item-access pubsub service 280 @param service: jid of the item-access pubsub service
275 @param client: SatXMPPClient of the publisher 281 @param client: SatXMPPClient of the publisher
289 P = self.host.plugins["XEP-0060"] 295 P = self.host.plugins["XEP-0060"]
290 access_model_value = ACCESS_TYPE_MAP[access_type] 296 access_model_value = ACCESS_TYPE_MAP[access_type]
291 297
292 if extra.get('allow_comments', 'False').lower() == 'true': 298 if extra.get('allow_comments', 'False').lower() == 'true':
293 # XXX: use the item identifier? http://bugs.goffi.org/show_bug.cgi?id=63 299 # XXX: use the item identifier? http://bugs.goffi.org/show_bug.cgi?id=63
294 comments_node = self.__fillCommentsElement(mblog_data, None, node_name, service) 300 comments_node = self._fillCommentsElement(mblog_data, None, node_name, service)
295 _options = {P.OPT_ACCESS_MODEL: access_model_value, 301 _options = {P.OPT_ACCESS_MODEL: access_model_value,
296 P.OPT_PERSIST_ITEMS: 1, 302 P.OPT_PERSIST_ITEMS: 1,
297 P.OPT_MAX_ITEMS: -1, 303 P.OPT_MAX_ITEMS: -1,
298 P.OPT_DELIVER_PAYLOADS: 1, 304 P.OPT_DELIVER_PAYLOADS: 1,
299 P.OPT_SEND_ITEM_SUBSCRIBE: 1, 305 P.OPT_SEND_ITEM_SUBSCRIBE: 1,
333 339
334 entry_d = self.host.plugins["XEP-0277"].data2entry(mblog_data, client.profile) 340 entry_d = self.host.plugins["XEP-0277"].data2entry(mblog_data, client.profile)
335 entry_d.addCallback(itemCreated) 341 entry_d.addCallback(itemCreated)
336 return entry_d 342 return entry_d
337 343
338 def __fillCommentsElement(self, mblog_data, entry_id, node_name, service_jid): 344 def _fillCommentsElement(self, mblog_data, entry_id, node_name, service_jid):
339 """ 345 """
340 @param mblog_data: dict containing the microblog data 346 @param mblog_data: dict containing the microblog data
341 @param entry_id: unique identifier of the entry 347 @param entry_id: unique identifier of the entry
342 @param node_name: the pubsub node name 348 @param node_name: the pubsub node name
343 @param service_jid: the JID of the pubsub service 349 @param service_jid: the JID of the pubsub service
354 #TODO 360 #TODO
355 return failure 361 return failure
356 362
357 def sendGroupBlog(self, access_type, access_list, message, extra, profile_key=C.PROF_KEY_NONE): 363 def sendGroupBlog(self, access_type, access_list, message, extra, profile_key=C.PROF_KEY_NONE):
358 """Publish a microblog with given item access 364 """Publish a microblog with given item access
365
359 @param access_type: one of "PUBLIC", "GROUP", "JID" 366 @param access_type: one of "PUBLIC", "GROUP", "JID"
360 @param access_list: list of authorized entity (empty list for PUBLIC ACCESS, 367 @param access_list: list of authorized entity (empty list for PUBLIC ACCESS,
361 list of groups or list of jids) for this item 368 list of groups or list of jids) for this item
362 @param message: microblog 369 @param message: microblog
363 @param extra: dict which option name as key, which can be: 370 @param extra: dict which option name as key, which can be:
380 elif access_type == "JID": 387 elif access_type == "JID":
381 raise NotImplementedError 388 raise NotImplementedError
382 else: 389 else:
383 log.error(_("Unknown access type")) 390 log.error(_("Unknown access type"))
384 raise BadAccessTypeError 391 raise BadAccessTypeError
385
386 return self._initialise(profile_key).addCallback(initialised)
387
388 def deleteGroupBlog(self, pub_data, comments, profile_key=C.PROF_KEY_NONE):
389 """Delete a microblog item from a node.
390 @param pub_data: a tuple (service, node identifier, item identifier)
391 @param comments: comments node identifier (for main item) or empty string
392 @param profile_key: %(doc_profile_key)s
393 """
394
395 def initialised(result):
396 profile, client = result
397 service, node, item_id = pub_data
398 service_jid = jid.JID(service) if service else client.item_access_pubsub
399 if comments or not node: # main item
400 node = self.getNodeName(client.jid)
401 if comments:
402 # remove the associated comments node
403 comments_service, comments_node = self.host.plugins["XEP-0277"].parseCommentUrl(comments)
404 d = self.host.plugins["XEP-0060"].deleteNode(comments_service, comments_node, profile_key=profile)
405 d.addErrback(lambda failure: log.error(u"Deletion of node %s failed: %s" % (comments_node, failure.getErrorMessage())))
406 # remove the item itself
407 d = self.host.plugins["XEP-0060"].retractItems(service_jid, node, [item_id], profile_key=profile)
408 d.addErrback(lambda failure: log.error(u"Deletion of item %s from %s failed: %s" % (item_id, node, failure.getErrorMessage())))
409 return d
410
411 def notify(d):
412 # TODO: this works only on the same host, and notifications for item deletion should be
413 # implemented according to http://xmpp.org/extensions/xep-0060.html#publisher-delete-success-notify
414 # instead. The notification mechanism implemented in sat_pubsub and wokkel have apriori
415 # a problem with retrieving the subscriptions, or something else.
416 service, node, item_id = pub_data
417 publisher = self.host.getJidNStream(profile_key)[0]
418 profile = self.host.memory.getProfileName(profile_key)
419 gbdatum = {'id': item_id, 'type': 'main_item' if (comments or not node) else 'comment'}
420 self.host.bridge.personalEvent(publisher.full(), "MICROBLOG_DELETE", gbdatum, profile)
421 return d
422
423 return self._initialise(profile_key).addCallback(initialised).addCallback(notify)
424
425 def updateGroupBlog(self, pub_data, comments, message, extra, profile_key=C.PROF_KEY_NONE):
426 """Modify a microblog node
427 @param pub_data: a tuple (service, node identifier, item identifier)
428 @param comments: comments node identifier (for main item) or empty string
429 @param message: new message
430 @param extra: dict which option name as key, which can be:
431 - allow_comments: True to accept an other level of comments, False else (default: False)
432 - rich: if present, contain rich text in currently selected syntax
433 @param profile_key: %(doc_profile)
434 """
435
436 def initialised(result):
437 profile, client = result
438 mblog_data = {'content': message}
439 for attr in ['content_rich', 'title', 'title_rich']:
440 if attr in extra and extra[attr]:
441 mblog_data[attr] = extra[attr]
442 service, node, item_id = pub_data
443 service_jid = jid.JID(service) if service else client.item_access_pubsub
444 if comments or not node: # main item
445 node = self.getNodeName(client.jid)
446 mblog_data['id'] = unicode(item_id)
447 if 'published' in extra:
448 mblog_data['published'] = extra['published']
449 if extra.get('allow_comments', 'False').lower() == 'true':
450 comments_service, comments_node = self.host.plugins["XEP-0277"].parseCommentUrl(comments)
451 # we could use comments_node directly but it's safer to rebuild it
452 # XXX: use the item identifier? http://bugs.goffi.org/show_bug.cgi?id=63
453 entry_id = comments_node.split('_')[1].split('__')[0]
454 self.__fillCommentsElement(mblog_data, entry_id, node, service_jid)
455 entry_d = self.host.plugins["XEP-0277"].data2entry(mblog_data, profile)
456 entry_d.addCallback(lambda mblog_item: self.host.plugins["XEP-0060"].publish(service_jid, node, items=[mblog_item], profile_key=profile))
457 entry_d.addErrback(lambda failure: log.error(u"Modification of %s failed: %s" % (pub_data, failure.getErrorMessage())))
458 return entry_d
459 392
460 return self._initialise(profile_key).addCallback(initialised) 393 return self._initialise(profile_key).addCallback(initialised)
461 394
462 def sendGroupBlogComment(self, node_url, message, extra, profile_key=C.PROF_KEY_NONE): 395 def sendGroupBlogComment(self, node_url, message, extra, profile_key=C.PROF_KEY_NONE):
463 """Publish a comment in the given node 396 """Publish a comment in the given node
517 450
518 for item in items: 451 for item in items:
519 d_list.append(self.item2gbdata(item).addCallback(cb)) 452 d_list.append(self.item2gbdata(item).addCallback(cb))
520 return defer.DeferredList(d_list, consumeErrors=True).addCallback(lambda result: [value for (success, value) in result if success]) 453 return defer.DeferredList(d_list, consumeErrors=True).addCallback(lambda result: [value for (success, value) in result if success])
521 454
455 ## modify ##
456
457 def updateGroupBlog(self, pub_data, comments, message, extra, profile_key=C.PROF_KEY_NONE):
458 """Modify a microblog node
459
460 @param pub_data: a tuple (service, node identifier, item identifier)
461 @param comments: comments node identifier (for main item) or empty string
462 @param message: new message
463 @param extra: dict which option name as key, which can be:
464 - allow_comments: True to accept an other level of comments, False else (default: False)
465 - rich: if present, contain rich text in currently selected syntax
466 @param profile_key: %(doc_profile)
467 """
468
469 def initialised(result):
470 profile, client = result
471 mblog_data = {'content': message}
472 for attr in ['content_rich', 'title', 'title_rich']:
473 if attr in extra and extra[attr]:
474 mblog_data[attr] = extra[attr]
475 service, node, item_id = pub_data
476 service_jid = jid.JID(service) if service else client.item_access_pubsub
477 if comments or not node: # main item
478 node = self.getNodeName(client.jid)
479 mblog_data['id'] = unicode(item_id)
480 if 'published' in extra:
481 mblog_data['published'] = extra['published']
482 if extra.get('allow_comments', 'False').lower() == 'true':
483 comments_service, comments_node = self.host.plugins["XEP-0277"].parseCommentUrl(comments)
484 # we could use comments_node directly but it's safer to rebuild it
485 # XXX: use the item identifier? http://bugs.goffi.org/show_bug.cgi?id=63
486 entry_id = comments_node.split('_')[1].split('__')[0]
487 self._fillCommentsElement(mblog_data, entry_id, node, service_jid)
488 entry_d = self.host.plugins["XEP-0277"].data2entry(mblog_data, profile)
489 entry_d.addCallback(lambda mblog_item: self.host.plugins["XEP-0060"].publish(service_jid, node, items=[mblog_item], profile_key=profile))
490 entry_d.addErrback(lambda failure: log.error(u"Modification of %s failed: %s" % (pub_data, failure.getErrorMessage())))
491 return entry_d
492
493 return self._initialise(profile_key).addCallback(initialised)
494
495 ## get ##
496
522 def _getOrCountComments(self, items, max=0, profile_key=C.PROF_KEY_NONE): 497 def _getOrCountComments(self, items, max=0, profile_key=C.PROF_KEY_NONE):
523 """Get and/or count the comments of the given items. 498 """Get and/or count the comments of the given items.
524 499
525 @param items (list): items to consider. 500 @param items (list): items to consider.
526 @param max (int): maximum number of comments to get, if 0 only count 501 @param max (int): maximum number of comments to get, if 0 only count
551 d_list.append(defer.succeed(entry)) 526 d_list.append(defer.succeed(entry))
552 deferred_list = defer.DeferredList(d_list) 527 deferred_list = defer.DeferredList(d_list)
553 deferred_list.addCallback(lambda result: [value for (success, value) in result if success]) 528 deferred_list.addCallback(lambda result: [value for (success, value) in result if success])
554 return deferred_list 529 return deferred_list
555 530
556 def __getGroupBlogs(self, pub_jid_s, item_ids=None, rsm=None, max_comments=0, profile_key=C.PROF_KEY_NONE): 531 def _getGroupBlogs(self, pub_jid_s, item_ids=None, rsm=None, max_comments=0, profile_key=C.PROF_KEY_NONE):
557 """Retrieve previously published items from a publish subscribe node. 532 """Retrieve previously published items from a publish subscribe node.
558 533
559 @param pub_jid_s: jid of the publisher 534 @param pub_jid_s: jid of the publisher
560 @param item_ids: list of microblogs items IDs 535 @param item_ids: list of microblogs items IDs
561 @param rsm (dict): RSM request data 536 @param rsm (dict): RSM request data
592 @return: a deferred couple (list, dict) containing: 567 @return: a deferred couple (list, dict) containing:
593 - list of microblog data 568 - list of microblog data
594 - RSM response data 569 - RSM response data
595 """ 570 """
596 max_comments = 0 if count_comments else DO_NOT_COUNT_COMMENTS 571 max_comments = 0 if count_comments else DO_NOT_COUNT_COMMENTS
597 return self.__getGroupBlogs(pub_jid_s, item_ids=item_ids, rsm=rsm, max_comments=max_comments, profile_key=profile_key) 572 return self._getGroupBlogs(pub_jid_s, item_ids=item_ids, rsm=rsm, max_comments=max_comments, profile_key=profile_key)
598 573
599 def getGroupBlogsWithComments(self, pub_jid_s, item_ids=None, rsm=None, max_comments=None, profile_key=C.PROF_KEY_NONE): 574 def getGroupBlogsWithComments(self, pub_jid_s, item_ids=None, rsm=None, max_comments=None, profile_key=C.PROF_KEY_NONE):
600 """Get the published microblogs of the specified IDs and their comments. If 575 """Get the published microblogs of the specified IDs and their comments. If
601 item_ids is None, returns the last published microblogs and their comments. 576 item_ids is None, returns the last published microblogs and their comments.
602 577
612 - RSM response data 587 - RSM response data
613 """ 588 """
614 if max_comments is None: 589 if max_comments is None:
615 max_comments = MAX_COMMENTS 590 max_comments = MAX_COMMENTS
616 assert(max_comments > 0) # otherwise the return signature is not the same 591 assert(max_comments > 0) # otherwise the return signature is not the same
617 return self.__getGroupBlogs(pub_jid_s, item_ids=item_ids, rsm=rsm, max_comments=max_comments, profile_key=profile_key) 592 return self._getGroupBlogs(pub_jid_s, item_ids=item_ids, rsm=rsm, max_comments=max_comments, profile_key=profile_key)
618 593
619 def getGroupBlogsAtom(self, pub_jid_s, rsm=None, profile_key=C.PROF_KEY_NONE): 594 def getGroupBlogsAtom(self, pub_jid_s, rsm=None, profile_key=C.PROF_KEY_NONE):
620 """Get the atom feed of the last published microblogs 595 """Get the atom feed of the last published microblogs
621 @param pub_jid: jid of the publisher 596 @param pub_jid: jid of the publisher
622 @param profile_key: profile key 597 @param profile_key: profile key
717 return d.addCallback(self._getOrCountComments, False, profile_key) 692 return d.addCallback(self._getOrCountComments, False, profile_key)
718 693
719 #TODO: we need to use the server corresponding to the host of the jid 694 #TODO: we need to use the server corresponding to the host of the jid
720 return DeferredItemsFromMany(self, cb, profile_key).get(publishers_type, publishers, rsm=rsm) 695 return DeferredItemsFromMany(self, cb, profile_key).get(publishers_type, publishers, rsm=rsm)
721 696
697 ## subscribe ##
698
722 def subscribeGroupBlog(self, pub_jid, profile_key=C.PROF_KEY_NONE): 699 def subscribeGroupBlog(self, pub_jid, profile_key=C.PROF_KEY_NONE):
723 def initialised(result): 700 def initialised(result):
724 profile, client = result 701 profile, client = result
725 d = self.host.plugins["XEP-0060"].subscribe(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)), 702 d = self.host.plugins["XEP-0060"].subscribe(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)),
726 profile_key=profile_key) 703 profile_key=profile_key)
749 jids = self._getPublishersJIDs(publishers_type, publishers, client) 726 jids = self._getPublishersJIDs(publishers_type, publishers, client)
750 node_ids = [self.getNodeName(publisher) for publisher in jids] 727 node_ids = [self.getNodeName(publisher) for publisher in jids]
751 d_list = yield self.host.plugins["XEP-0060"].subscribeToMany(client.item_access_pubsub, node_ids, profile_key=profile_key) 728 d_list = yield self.host.plugins["XEP-0060"].subscribeToMany(client.item_access_pubsub, node_ids, profile_key=profile_key)
752 yield defer.DeferredList(d_list, consumeErrors=False) 729 yield defer.DeferredList(d_list, consumeErrors=False)
753 defer.returnValue(None) 730 defer.returnValue(None)
731
732 ## delete ##
733
734 def deleteGroupBlog(self, pub_data, comments, profile_key=C.PROF_KEY_NONE):
735 """Delete a microblog item from a node.
736
737 @param pub_data: a tuple (service, node identifier, item identifier)
738 @param comments: comments node identifier (for main item) or empty string
739 @param profile_key: %(doc_profile_key)s
740 """
741
742 def initialised(result):
743 profile, client = result
744 service, node, item_id = pub_data
745 service_jid = jid.JID(service) if service else client.item_access_pubsub
746 if comments or not node: # main item
747 node = self.getNodeName(client.jid)
748 if comments:
749 # remove the associated comments node
750 comments_service, comments_node = self.host.plugins["XEP-0277"].parseCommentUrl(comments)
751 d = self.host.plugins["XEP-0060"].deleteNode(comments_service, comments_node, profile_key=profile)
752 d.addErrback(lambda failure: log.error(u"Deletion of node %s failed: %s" % (comments_node, failure.getErrorMessage())))
753 # remove the item itself
754 d = self.host.plugins["XEP-0060"].retractItems(service_jid, node, [item_id], profile_key=profile)
755 d.addErrback(lambda failure: log.error(u"Deletion of item %s from %s failed: %s" % (item_id, node, failure.getErrorMessage())))
756 return d
757
758 def notify(d):
759 # TODO: this works only on the same host, and notifications for item deletion should be
760 # implemented according to http://xmpp.org/extensions/xep-0060.html#publisher-delete-success-notify
761 # instead. The notification mechanism implemented in sat_pubsub and wokkel have apriori
762 # a problem with retrieving the subscriptions, or something else.
763 service, node, item_id = pub_data
764 publisher = self.host.getJidNStream(profile_key)[0]
765 profile = self.host.memory.getProfileName(profile_key)
766 gbdatum = {'id': item_id, 'type': 'main_item' if (comments or not node) else 'comment'}
767 self.host.bridge.personalEvent(publisher.full(), "MICROBLOG_DELETE", gbdatum, profile)
768 return d
769
770 return self._initialise(profile_key).addCallback(initialised).addCallback(notify)
754 771
755 def deleteAllGroupBlogsAndComments(self, profile_key=C.PROF_KEY_NONE): 772 def deleteAllGroupBlogsAndComments(self, profile_key=C.PROF_KEY_NONE):
756 """Delete absolutely all the microblog data that the user has posted""" 773 """Delete absolutely all the microblog data that the user has posted"""
757 calls = [self.deleteAllGroupBlogs(profile_key), self.deleteAllGroupBlogsComments(profile_key)] 774 calls = [self.deleteAllGroupBlogs(profile_key), self.deleteAllGroupBlogsComments(profile_key)]
758 return defer.DeferredList(calls) 775 return defer.DeferredList(calls)
863 deletions.append(d) 880 deletions.append(d)
864 return defer.DeferredList(deletions) 881 return defer.DeferredList(deletions)
865 882
866 return self._initialise(profile_key).addCallback(initialised) 883 return self._initialise(profile_key).addCallback(initialised)
867 884
885 ## helper classes to manipulate items ##
868 886
869 class DeferredItems(): 887 class DeferredItems():
870 """Helper class to retrieve items using XEP-0060""" 888 """Retrieve items using XEP-0060"""
871 889
872 def __init__(self, parent, cb, eb=None, profile_key=C.PROF_KEY_NONE): 890 def __init__(self, parent, cb, eb=None, profile_key=C.PROF_KEY_NONE):
873 """ 891 """
874 @param parent (GroupBlog): GroupBlog instance 892 @param parent (GroupBlog): GroupBlog instance
875 @param cb (callable): callback method to be applied on items 893 @param cb (callable): callback method to be applied on items
881 self.eb = (lambda dummy: ([], {})) if eb is None else eb 899 self.eb = (lambda dummy: ([], {})) if eb is None else eb
882 self.profile_key = profile_key 900 self.profile_key = profile_key
883 901
884 def get(self, node, item_ids=None, sub_id=None, rsm=None): 902 def get(self, node, item_ids=None, sub_id=None, rsm=None):
885 """ 903 """
904
886 @param node (str): node identifier. 905 @param node (str): node identifier.
887 @param item_ids (list[str]): list of items identifiers. 906 @param item_ids (list[str]): list of items identifiers.
888 @param sub_id (str): optional subscription identifier. 907 @param sub_id (str): optional subscription identifier.
889 @param rsm (dict): RSM request data 908 @param rsm (dict): RSM request data
890 @return: a deferred couple (list, dict) containing: 909 @return: a deferred couple (list, dict) containing:
896 915
897 def initialised(result): 916 def initialised(result):
898 profile, client = result 917 profile, client = result
899 rsm_ = wokkel_rsm.RSMRequest(**rsm) 918 rsm_ = wokkel_rsm.RSMRequest(**rsm)
900 d = self.parent.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, 919 d = self.parent.host.plugins["XEP-0060"].getItems(client.item_access_pubsub,
901 node, rsm_.max, 920 node, rsm_.max_,
902 item_ids, sub_id, rsm_, 921 item_ids, sub_id, rsm_,
903 profile_key=profile) 922 profile_key=profile)
904 923
905 def cb(result): 924 def cb(result):
906 d = defer.maybeDeferred(self.cb, result[0], client) 925 d = defer.maybeDeferred(self.cb, result[0], client)
922 """ 941 """
923 self.parent = parent 942 self.parent = parent
924 self.cb = cb 943 self.cb = cb
925 self.profile_key = profile_key 944 self.profile_key = profile_key
926 945
927 def __buildData(self, publishers_type, publishers, client): 946 def _buildData(self, publishers_type, publishers, client):
928 jids = self.parent._getPublishersJIDs(publishers_type, publishers, client) 947 jids = self.parent._getPublishersJIDs(publishers_type, publishers, client)
929 return {publisher: self.parent.getNodeName(publisher) for publisher in jids} 948 return {publisher: self.parent.getNodeName(publisher) for publisher in jids}
930 949
931 def get(self, publishers_type, publishers, sub_id=None, rsm=None): 950 def get(self, publishers_type, publishers, sub_id=None, rsm=None):
932 """ 951 """
944 rsm = {'max': MAX_ITEMS} 963 rsm = {'max': MAX_ITEMS}
945 964
946 def initialised(result): 965 def initialised(result):
947 profile, client = result 966 profile, client = result
948 967
949 data = self.__buildData(publishers_type, publishers, client) 968 data = self._buildData(publishers_type, publishers, client)
950 rsm_ = wokkel_rsm.RSMRequest(**rsm) 969 rsm_ = wokkel_rsm.RSMRequest(**rsm)
951 d = self.parent.host.plugins["XEP-0060"].getItemsFromMany(client.item_access_pubsub, 970 d = self.parent.host.plugins["XEP-0060"].getItemsFromMany(client.item_access_pubsub,
952 data, rsm_.max, sub_id, 971 data, rsm_.max, sub_id,
953 rsm_, profile_key=profile) 972 rsm_, profile_key=profile)
954 973