comparison sat/plugins/plugin_xep_0277.py @ 2807:0b7ce5daee9b

plugin XEP-0277: blog items data are now entirely serialised before going to bridge: So far, and for historical reasons, blog items data where serialised using a unicode: unicode dict, which was causing trouble for many types of values (timestamps, booleans, lists). This patch changes it by serialising the whole items before going to bridge, and deserialising it when going back. This way, complex data can be used easily in items. This impact psEvent and serItemsData* methods which are renamed transItemsData* because there are not always serialising anymore (a new argument "serialise" allows to specify it). When editing a blog post in jp, metadata are now more easy to manipulate, specially lists like tags.
author Goffi <goffi@goffi.org>
date Sat, 23 Feb 2019 18:59:00 +0100
parents 85d3240a400f
children ab2696e34d29
comparison
equal deleted inserted replaced
2806:2400cad2dace 2807:0b7ce5daee9b
83 ) 83 )
84 84
85 host.bridge.addMethod( 85 host.bridge.addMethod(
86 "mbSend", 86 "mbSend",
87 ".plugin", 87 ".plugin",
88 in_sign="ssa{ss}s", 88 in_sign="ssss",
89 out_sign="", 89 out_sign="",
90 method=self._mbSend, 90 method=self._mbSend,
91 async=True, 91 async=True,
92 ) 92 )
93 host.bridge.addMethod( 93 host.bridge.addMethod(
100 ) 100 )
101 host.bridge.addMethod( 101 host.bridge.addMethod(
102 "mbGet", 102 "mbGet",
103 ".plugin", 103 ".plugin",
104 in_sign="ssiasa{ss}s", 104 in_sign="ssiasa{ss}s",
105 out_sign="(aa{ss}a{ss})", 105 out_sign="(asa{ss})",
106 method=self._mbGet, 106 method=self._mbGet,
107 async=True, 107 async=True,
108 ) 108 )
109 host.bridge.addMethod( 109 host.bridge.addMethod(
110 "mbSetAccess", 110 "mbSetAccess",
123 ) 123 )
124 host.bridge.addMethod( 124 host.bridge.addMethod(
125 "mbGetFromManyRTResult", 125 "mbGetFromManyRTResult",
126 ".plugin", 126 ".plugin",
127 in_sign="ss", 127 in_sign="ss",
128 out_sign="(ua(sssaa{ss}a{ss}))", 128 out_sign="(ua(sssasa{ss}))",
129 method=self._mbGetFromManyRTResult, 129 method=self._mbGetFromManyRTResult,
130 async=True, 130 async=True,
131 ) 131 )
132 host.bridge.addMethod( 132 host.bridge.addMethod(
133 "mbGetFromMany", 133 "mbGetFromMany",
138 ) 138 )
139 host.bridge.addMethod( 139 host.bridge.addMethod(
140 "mbGetFromManyWithCommentsRTResult", 140 "mbGetFromManyWithCommentsRTResult",
141 ".plugin", 141 ".plugin",
142 in_sign="ss", 142 in_sign="ss",
143 out_sign="(ua(sssa(a{ss}a(sssaa{ss}a{ss}))a{ss}))", 143 out_sign="(ua(sssa(sa(sssasa{ss}))a{ss}))",
144 method=self._mbGetFromManyWithCommentsRTResult, 144 method=self._mbGetFromManyWithCommentsRTResult,
145 async=True, 145 async=True,
146 ) 146 )
147 host.bridge.addMethod( 147 host.bridge.addMethod(
148 "mbGetFromManyWithComments", 148 "mbGetFromManyWithComments",
176 self.host.bridge.psEvent( 176 self.host.bridge.psEvent(
177 C.PS_MICROBLOG, 177 C.PS_MICROBLOG,
178 itemsEvent.sender.full(), 178 itemsEvent.sender.full(),
179 itemsEvent.nodeIdentifier, 179 itemsEvent.nodeIdentifier,
180 event, 180 event,
181 data, 181 data_format.serialise(data),
182 client.profile, 182 client.profile,
183 ) 183 )
184 184
185 for item in itemsEvent.items: 185 for item in itemsEvent.items:
186 if item.name == C.PS_ITEM: 186 if item.name == C.PS_ITEM:
194 194
195 ## data/item transformation ## 195 ## data/item transformation ##
196 196
197 @defer.inlineCallbacks 197 @defer.inlineCallbacks
198 def item2mbdata(self, item_elt): 198 def item2mbdata(self, item_elt):
199 """Convert an XML Item to microblog data used in bridge API 199 """Convert an XML Item to microblog data
200 200
201 @param item_elt: domish.Element of microblog item 201 @param item_elt: domish.Element of microblog item
202 @return: microblog data (dictionary) 202 @return: microblog data (dictionary)
203 """ 203 """
204 microblog_data = {} 204 microblog_data = {}
236 if type_ == "xhtml": 236 if type_ == "xhtml":
237 data_elt = elem.firstChildElement() 237 data_elt = elem.firstChildElement()
238 if data_elt is None: 238 if data_elt is None:
239 raise failure.Failure( 239 raise failure.Failure(
240 exceptions.DataError( 240 exceptions.DataError(
241 u"XHML content not wrapped in a <div/> element, this is not standard !" 241 u"XHML content not wrapped in a <div/> element, this is not "
242 u"standard !"
242 ) 243 )
243 ) 244 )
244 if data_elt.uri != C.NS_XHTML: 245 if data_elt.uri != C.NS_XHTML:
245 raise failure.Failure( 246 raise failure.Failure(
246 exceptions.DataError( 247 exceptions.DataError(
279 280
280 # atom:id 281 # atom:id
281 try: 282 try:
282 id_elt = entry_elt.elements(NS_ATOM, "id").next() 283 id_elt = entry_elt.elements(NS_ATOM, "id").next()
283 except StopIteration: 284 except StopIteration:
284 msg = u"No atom id found in the pubsub item {}, this is not standard !".format( 285 msg = (u"No atom id found in the pubsub item {}, this is not standard !"
285 id_ 286 .format(id_))
286 )
287 log.warning(msg) 287 log.warning(msg)
288 microblog_data[u"atom_id"] = "" 288 microblog_data[u"atom_id"] = ""
289 else: 289 else:
290 microblog_data[u"atom_id"] = unicode(id_elt) 290 microblog_data[u"atom_id"] = unicode(id_elt)
291 291
341 try: 341 try:
342 updated_elt = entry_elt.elements(NS_ATOM, "updated").next() 342 updated_elt = entry_elt.elements(NS_ATOM, "updated").next()
343 except StopIteration: 343 except StopIteration:
344 msg = u"No atom updated element found in the pubsub item {}".format(id_) 344 msg = u"No atom updated element found in the pubsub item {}".format(id_)
345 raise failure.Failure(exceptions.DataError(msg)) 345 raise failure.Failure(exceptions.DataError(msg))
346 microblog_data[u"updated"] = unicode( 346 microblog_data[u"updated"] = calendar.timegm(
347 calendar.timegm(dateutil.parser.parse(unicode(updated_elt)).utctimetuple()) 347 dateutil.parser.parse(unicode(updated_elt)).utctimetuple()
348 ) 348 )
349 try: 349 try:
350 published_elt = entry_elt.elements(NS_ATOM, "published").next() 350 published_elt = entry_elt.elements(NS_ATOM, "published").next()
351 except StopIteration: 351 except StopIteration:
352 microblog_data[u"published"] = microblog_data[u"updated"] 352 microblog_data[u"published"] = microblog_data[u"updated"]
353 else: 353 else:
354 microblog_data[u"published"] = unicode( 354 microblog_data[u"published"] = calendar.timegm(
355 calendar.timegm( 355 dateutil.parser.parse(unicode(published_elt)).utctimetuple()
356 dateutil.parser.parse(unicode(published_elt)).utctimetuple()
357 )
358 ) 356 )
359 357
360 # links 358 # links
361 for link_elt in entry_elt.elements(NS_ATOM, "link"): 359 for link_elt in entry_elt.elements(NS_ATOM, "link"):
362 if ( 360 if (
418 item_elt.getAttribute(u"publisher") or "" 416 item_elt.getAttribute(u"publisher") or ""
419 ) 417 )
420 418
421 if not publisher: 419 if not publisher:
422 log.debug(u"No publisher attribute, we can't verify author jid") 420 log.debug(u"No publisher attribute, we can't verify author jid")
423 microblog_data[u"author_jid_verified"] = C.BOOL_FALSE 421 microblog_data[u"author_jid_verified"] = False
424 elif jid.JID(publisher).userhostJID() == jid.JID(uri).userhostJID(): 422 elif jid.JID(publisher).userhostJID() == jid.JID(uri).userhostJID():
425 microblog_data[u"author_jid_verified"] = C.BOOL_TRUE 423 microblog_data[u"author_jid_verified"] = True
426 else: 424 else:
427 log.warning( 425 log.warning(
428 u"item atom:uri differ from publisher attribute, spoofing attempt ? atom:uri = {} publisher = {}".format( 426 u"item atom:uri differ from publisher attribute, spoofing "
427 u"attempt ? atom:uri = {} publisher = {}".format(
429 uri, item_elt.getAttribute("publisher") 428 uri, item_elt.getAttribute("publisher")
430 ) 429 )
431 ) 430 )
432 microblog_data[u"author_jid_verified"] = C.BOOL_FALSE 431 microblog_data[u"author_jid_verified"] = False
433 # email 432 # email
434 try: 433 try:
435 email_elt = author_elt.elements(NS_ATOM, "email").next() 434 email_elt = author_elt.elements(NS_ATOM, "email").next()
436 except StopIteration: 435 except StopIteration:
437 pass 436 pass
438 else: 437 else:
439 microblog_data[u"author_email"] = unicode(email_elt) 438 microblog_data[u"author_email"] = unicode(email_elt)
440 439
441 # categories 440 # categories
442 categories = ( 441 categories = [
443 category_elt.getAttribute("term", "") 442 category_elt.getAttribute("term", "")
444 for category_elt in entry_elt.elements(NS_ATOM, "category") 443 for category_elt in entry_elt.elements(NS_ATOM, "category")
445 ) 444 ]
446 data_format.iter2dict("tag", categories, microblog_data) 445 microblog_data[u"tags"] = categories
447 446
448 ## the trigger ## 447 ## the trigger ##
449 # if other plugins have things to add or change 448 # if other plugins have things to add or change
450 yield self.host.trigger.point( 449 yield self.host.trigger.point(
451 "XEP-0277_item2data", item_elt, entry_elt, microblog_data 450 "XEP-0277_item2data", item_elt, entry_elt, microblog_data
570 "published", 569 "published",
571 content=utils.xmpp_date(float(data.get("published", current_time))), 570 content=utils.xmpp_date(float(data.get("published", current_time))),
572 ) 571 )
573 572
574 ## categories ## 573 ## categories ##
575 for tag in data_format.dict2iter("tag", data): 574 for tag in data.get('tags', []):
576 category_elt = entry_elt.addElement("category") 575 category_elt = entry_elt.addElement("category")
577 category_elt["term"] = tag 576 category_elt["term"] = tag
578 577
579 ## id ## 578 ## id ##
580 entry_id = data.get( 579 entry_id = data.get(
653 @param node(unicode): node of the parent item 652 @param node(unicode): node of the parent item
654 @param item_id(unicode): id of the parent item 653 @param item_id(unicode): id of the parent item
655 @param access(unicode, None): access model 654 @param access(unicode, None): access model
656 None to use same access model as parent item 655 None to use same access model as parent item
657 """ 656 """
658 # FIXME: if 'comments' already exists in mb_data, it is not used to create the Node 657 # FIXME: if 'comments' already exists in mb_data,
659 allow_comments = C.bool(mb_data.pop("allow_comments", "false")) 658 # it is not used to create the Node
660 if not allow_comments: 659 allow_comments = mb_data.pop("allow_comments", None)
660 if allow_comments is None:
661 return
662 elif allow_comments == False:
661 if "comments" in mb_data: 663 if "comments" in mb_data:
662 log.warning( 664 log.warning(
663 u"comments are not allowed but there is already a comments node, it may be lost: {uri}".format( 665 u"comments are not allowed but there is already a comments node, "
666 u"it may be lost: {uri}".format(
664 uri=mb_data["comments"] 667 uri=mb_data["comments"]
665 ) 668 )
666 ) 669 )
667 del mb_data["comments"] 670 del mb_data["comments"]
668 return 671 return
735 raise exceptions.DataError( 738 raise exceptions.DataError(
736 u"if comments is present, it must not be empty" 739 u"if comments is present, it must not be empty"
737 ) 740 )
738 if "comments_node" in mb_data or "comments_service" in mb_data: 741 if "comments_node" in mb_data or "comments_service" in mb_data:
739 raise exceptions.DataError( 742 raise exceptions.DataError(
740 u"You can't use comments_service/comments_node and comments at the same time" 743 u"You can't use comments_service/comments_node and comments at the "
744 u"same time"
741 ) 745 )
742 else: 746 else:
743 mb_data["comments"] = self._p.getNodeURI(comments_service, comments_node) 747 mb_data["comments"] = self._p.getNodeURI(comments_service, comments_node)
744 748
745 def _mbSend(self, service, node, data, profile_key): 749 def _mbSend(self, service, node, data, profile_key):
746 service = jid.JID(service) if service else None 750 service = jid.JID(service) if service else None
747 node = node if node else NS_MICROBLOG 751 node = node if node else NS_MICROBLOG
748 client = self.host.getClient(profile_key) 752 client = self.host.getClient(profile_key)
753 data = data_format.deserialise(data)
749 return self.send(client, data, service, node) 754 return self.send(client, data, service, node)
750 755
751 @defer.inlineCallbacks 756 @defer.inlineCallbacks
752 def send(self, client, data, service=None, node=NS_MICROBLOG): 757 def send(self, client, data, service=None, node=NS_MICROBLOG):
753 """Send XEP-0277's microblog data 758 """Send XEP-0277's microblog data
758 None to publish on profile's PEP 763 None to publish on profile's PEP
759 @param node(unicode, None): PubSub node to use (defaut to microblog NS) 764 @param node(unicode, None): PubSub node to use (defaut to microblog NS)
760 None is equivalend as using default value 765 None is equivalend as using default value
761 """ 766 """
762 # TODO: check that all data keys are used, this would avoid sending publicly a private message 767 # TODO: check that all data keys are used, this would avoid sending publicly a private message
763 # by accident (e.g. if group pluging is not loaded, and "grou*" key are not used) 768 # by accident (e.g. if group plugin is not loaded, and "group*" key are not used)
764 if node is None: 769 if node is None:
765 node = NS_MICROBLOG 770 node = NS_MICROBLOG
766 771
767 item_id = data.get("id") or unicode(shortuuid.uuid()) 772 item_id = data.get("id") or unicode(shortuuid.uuid())
768 773
786 profile_key, 791 profile_key,
787 ) 792 )
788 793
789 ## get ## 794 ## get ##
790 795
796 def _mbGetSerialise(self, data):
797 items, metadata = data
798 items = [data_format.serialise(item) for item in items]
799 return items, metadata
800
791 def _mbGet(self, service="", node="", max_items=10, item_ids=None, extra_dict=None, 801 def _mbGet(self, service="", node="", max_items=10, item_ids=None, extra_dict=None,
792 profile_key=C.PROF_KEY_NONE): 802 profile_key=C.PROF_KEY_NONE):
793 """ 803 """
794 @param max_items(int): maximum number of item to get, C.NO_LIMIT for no limit 804 @param max_items(int): maximum number of item to get, C.NO_LIMIT for no limit
795 @param item_ids (list[unicode]): list of item IDs 805 @param item_ids (list[unicode]): list of item IDs
796 """ 806 """
797 client = self.host.getClient(profile_key) 807 client = self.host.getClient(profile_key)
798 service = jid.JID(service) if service else None 808 service = jid.JID(service) if service else None
799 max_items = None if max_items == C.NO_LIMIT else max_items 809 max_items = None if max_items == C.NO_LIMIT else max_items
800 extra = self._p.parseExtra(extra_dict) 810 extra = self._p.parseExtra(extra_dict)
801 return self.mbGet( 811 d = self.mbGet(client, service, node or None, max_items, item_ids,
802 client, 812 extra.rsm_request, extra.extra)
803 service, 813 d.addCallback(self._mbGetSerialise)
804 node or None, 814 return d
805 max_items,
806 item_ids,
807 extra.rsm_request,
808 extra.extra,
809 )
810 815
811 @defer.inlineCallbacks 816 @defer.inlineCallbacks
812 def mbGet(self, client, service=None, node=None, max_items=10, item_ids=None, 817 def mbGet(self, client, service=None, node=None, max_items=10, item_ids=None,
813 rsm_request=None, extra=None): 818 rsm_request=None, extra=None):
814 """Get some microblogs 819 """Get some microblogs
832 max_items=max_items, 837 max_items=max_items,
833 item_ids=item_ids, 838 item_ids=item_ids,
834 rsm_request=rsm_request, 839 rsm_request=rsm_request,
835 extra=extra, 840 extra=extra,
836 ) 841 )
837 serialised = yield self._p.serItemsDataD(items_data, self.item2mbdata) 842 mb_data = yield self._p.transItemsDataD(items_data, self.item2mbdata)
838 defer.returnValue(serialised) 843 defer.returnValue(mb_data)
839 844
840 def parseCommentUrl(self, node_url): 845 def parseCommentUrl(self, node_url):
841 """Parse a XMPP URI 846 """Parse a XMPP URI
842 847
843 Determine the fields comments_service and comments_node of a microblog data 848 Determine the fields comments_service and comments_node of a microblog data
920 925
921 @param publishers_type: type of the list of publishers, one of: 926 @param publishers_type: type of the list of publishers, one of:
922 C.ALL: get all jids from roster, publishers is not used 927 C.ALL: get all jids from roster, publishers is not used
923 C.GROUP: get jids from groups 928 C.GROUP: get jids from groups
924 C.JID: use publishers directly as list of jids 929 C.JID: use publishers directly as list of jids
925 @param publishers: list of publishers, according to "publishers_type" (None, list of groups or list of jids) 930 @param publishers: list of publishers, according to "publishers_type" (None,
931 list of groups or list of jids)
926 @param profile_key: %(doc_profile_key)s 932 @param profile_key: %(doc_profile_key)s
927 """ 933 """
928 client = self.host.getClient(profile_key) 934 client = self.host.getClient(profile_key)
929 if publishers_type == C.JID: 935 if publishers_type == C.JID:
930 jids_set = set(publishers) 936 jids_set = set(publishers)
931 else: 937 else:
932 jids_set = client.roster.getJidsSet(publishers_type, publishers) 938 jids_set = client.roster.getJidsSet(publishers_type, publishers)
933 if publishers_type == C.ALL: 939 if publishers_type == C.ALL:
934 try: # display messages from salut-a-toi@libervia.org or other PEP services 940 try:
941 # display messages from salut-a-toi@libervia.org or other PEP services
935 services = self.host.plugins["EXTRA-PEP"].getFollowedEntities( 942 services = self.host.plugins["EXTRA-PEP"].getFollowedEntities(
936 profile_key 943 profile_key
937 ) 944 )
938 except KeyError: 945 except KeyError:
939 pass # plugin is not loaded 946 pass # plugin is not loaded
985 992
986 @param publishers_type: type of the list of publishers, one of: 993 @param publishers_type: type of the list of publishers, one of:
987 C.ALL: get all jids from roster, publishers is not used 994 C.ALL: get all jids from roster, publishers is not used
988 C.GROUP: get jids from groups 995 C.GROUP: get jids from groups
989 C.JID: use publishers directly as list of jids 996 C.JID: use publishers directly as list of jids
990 @param publishers: list of publishers, according to "publishers_type" (None, list of groups or list of jids) 997 @param publishers: list of publishers, according to "publishers_type" (None, list
998 of groups or list of jids)
991 @param profile: %(doc_profile)s 999 @param profile: %(doc_profile)s
992 @return (str): session id 1000 @return (str): session id
993 """ 1001 """
994 client, node_data = self._getClientAndNodeData( 1002 client, node_data = self._getClientAndNodeData(
995 publishers_type, publishers, profile_key 1003 publishers_type, publishers, profile_key
1015 @param profile_key: %(doc_profile_key)s 1023 @param profile_key: %(doc_profile_key)s
1016 """ 1024 """
1017 1025
1018 def onSuccess(items_data): 1026 def onSuccess(items_data):
1019 """convert items elements to list of microblog data in items_data""" 1027 """convert items elements to list of microblog data in items_data"""
1020 d = self._p.serItemsDataD(items_data, self.item2mbdata) 1028 d = self._p.transItemsDataD(items_data, self.item2mbdata, serialise=True)
1021 d.addCallback(lambda serialised: ("", serialised)) 1029 d.addCallback(lambda serialised: ("", serialised))
1022 return d 1030 return d
1023 1031
1024 profile = self.host.getClient(profile_key).profile 1032 profile = self.host.getClient(profile_key).profile
1025 d = self._p.getRTResults( 1033 d = self._p.getRTResults(
1039 ], 1047 ],
1040 ) 1048 )
1041 ) 1049 )
1042 return d 1050 return d
1043 1051
1044 def _mbGetFromMany( 1052 def _mbGetFromMany(self, publishers_type, publishers, max_items=10, extra_dict=None,
1045 self, 1053 profile_key=C.PROF_KEY_NONE):
1046 publishers_type,
1047 publishers,
1048 max_items=10,
1049 extra_dict=None,
1050 profile_key=C.PROF_KEY_NONE,
1051 ):
1052 """ 1054 """
1053 @param max_items(int): maximum number of item to get, C.NO_LIMIT for no limit 1055 @param max_items(int): maximum number of item to get, C.NO_LIMIT for no limit
1054 """ 1056 """
1055 max_items = None if max_items == C.NO_LIMIT else max_items 1057 max_items = None if max_items == C.NO_LIMIT else max_items
1056 publishers_type, publishers = self._checkPublishers(publishers_type, publishers) 1058 publishers_type, publishers = self._checkPublishers(publishers_type, publishers)
1062 extra.rsm_request, 1064 extra.rsm_request,
1063 extra.extra, 1065 extra.extra,
1064 profile_key, 1066 profile_key,
1065 ) 1067 )
1066 1068
1067 def mbGetFromMany( 1069 def mbGetFromMany(self, publishers_type, publishers, max_items=None, rsm_request=None,
1068 self, 1070 extra=None, profile_key=C.PROF_KEY_NONE):
1069 publishers_type,
1070 publishers,
1071 max_items=None,
1072 rsm_request=None,
1073 extra=None,
1074 profile_key=C.PROF_KEY_NONE,
1075 ):
1076 """Get the published microblogs for a list of groups or jids 1071 """Get the published microblogs for a list of groups or jids
1077 1072
1078 @param publishers_type (str): type of the list of publishers (one of "GROUP" or "JID" or "ALL") 1073 @param publishers_type (str): type of the list of publishers (one of "GROUP" or
1079 @param publishers (list): list of publishers, according to publishers_type (list of groups or list of jids) 1074 "JID" or "ALL")
1075 @param publishers (list): list of publishers, according to publishers_type (list
1076 of groups or list of jids)
1080 @param max_items (int): optional limit on the number of retrieved items. 1077 @param max_items (int): optional limit on the number of retrieved items.
1081 @param rsm_request (rsm.RSMRequest): RSM request data, common to all publishers 1078 @param rsm_request (rsm.RSMRequest): RSM request data, common to all publishers
1082 @param extra (dict): Extra data 1079 @param extra (dict): Extra data
1083 @param profile_key: profile key 1080 @param profile_key: profile key
1084 @return (str): RT Deferred session id 1081 @return (str): RT Deferred session id
1091 node_data, max_items, rsm_request, profile_key=profile_key 1088 node_data, max_items, rsm_request, profile_key=profile_key
1092 ) 1089 )
1093 1090
1094 # comments # 1091 # comments #
1095 1092
1096 def _mbGetFromManyWithCommentsRTResult( 1093 def _mbGetFromManyWithCommentsRTResultSerialise(self, data):
1097 self, session_id, profile_key=C.PROF_KEY_DEFAULT 1094 """Serialisation of result
1098 ): 1095
1096 This is probably the longest method name of whole SàT ecosystem ^^
1097 @param data(dict): data as received by rt_sessions
1098 @return (tuple): see [_mbGetFromManyWithCommentsRTResult]
1099 """
1100 ret = []
1101 data_iter = data[1].iteritems()
1102 for (service, node), (success, (failure_, (items_data, metadata))) in data_iter:
1103 items = []
1104 for item, item_metadata in items_data:
1105 item = data_format.serialise(item)
1106 items.append((item, item_metadata))
1107 ret.append((
1108 service.full(),
1109 node,
1110 failure_,
1111 items,
1112 metadata))
1113
1114 return data[0], ret
1115
1116 def _mbGetFromManyWithCommentsRTResult(self, session_id,
1117 profile_key=C.PROF_KEY_DEFAULT):
1099 """Get real-time results for [mbGetFromManyWithComments] session 1118 """Get real-time results for [mbGetFromManyWithComments] session
1100 1119
1101 @param session_id: id of the real-time deferred session 1120 @param session_id: id of the real-time deferred session
1102 @param return (tuple): (remaining, results) where: 1121 @param return (tuple): (remaining, results) where:
1103 - remaining is the number of still expected results 1122 - remaining is the number of still expected results
1116 - metadata(dict): original node metadata 1135 - metadata(dict): original node metadata
1117 @param profile_key: %(doc_profile_key)s 1136 @param profile_key: %(doc_profile_key)s
1118 """ 1137 """
1119 profile = self.host.getClient(profile_key).profile 1138 profile = self.host.getClient(profile_key).profile
1120 d = self.rt_sessions.getResults(session_id, profile=profile) 1139 d = self.rt_sessions.getResults(session_id, profile=profile)
1121 d.addCallback( 1140 d.addCallback(self._mbGetFromManyWithCommentsRTResultSerialise)
1122 lambda ret: (
1123 ret[0],
1124 [
1125 (service.full(), node, failure, items, metadata)
1126 for (service, node), (success, (failure, (items, metadata))) in ret[
1127 1
1128 ].iteritems()
1129 ],
1130 )
1131 )
1132 return d 1141 return d
1133 1142
1134 def _mbGetFromManyWithComments( 1143 def _mbGetFromManyWithComments(self, publishers_type, publishers, max_items=10,
1135 self, 1144 max_comments=C.NO_LIMIT, extra_dict=None,
1136 publishers_type, 1145 extra_comments_dict=None, profile_key=C.PROF_KEY_NONE):
1137 publishers,
1138 max_items=10,
1139 max_comments=C.NO_LIMIT,
1140 extra_dict=None,
1141 extra_comments_dict=None,
1142 profile_key=C.PROF_KEY_NONE,
1143 ):
1144 """ 1146 """
1145 @param max_items(int): maximum number of item to get, C.NO_LIMIT for no limit 1147 @param max_items(int): maximum number of item to get, C.NO_LIMIT for no limit
1146 @param max_comments(int): maximum number of comments to get, C.NO_LIMIT for no limit 1148 @param max_comments(int): maximum number of comments to get, C.NO_LIMIT for no
1149 limit
1147 """ 1150 """
1148 max_items = None if max_items == C.NO_LIMIT else max_items 1151 max_items = None if max_items == C.NO_LIMIT else max_items
1149 max_comments = None if max_comments == C.NO_LIMIT else max_comments 1152 max_comments = None if max_comments == C.NO_LIMIT else max_comments
1150 publishers_type, publishers = self._checkPublishers(publishers_type, publishers) 1153 publishers_type, publishers = self._checkPublishers(publishers_type, publishers)
1151 extra = self._p.parseExtra(extra_dict) 1154 extra = self._p.parseExtra(extra_dict)
1160 extra_comments.rsm_request, 1163 extra_comments.rsm_request,
1161 extra_comments.extra, 1164 extra_comments.extra,
1162 profile_key, 1165 profile_key,
1163 ) 1166 )
1164 1167
1165 def mbGetFromManyWithComments( 1168 def mbGetFromManyWithComments(self, publishers_type, publishers, max_items=None,
1166 self, 1169 max_comments=None, rsm_request=None, extra=None,
1167 publishers_type, 1170 rsm_comments=None, extra_comments=None,
1168 publishers, 1171 profile_key=C.PROF_KEY_NONE):
1169 max_items=None,
1170 max_comments=None,
1171 rsm_request=None,
1172 extra=None,
1173 rsm_comments=None,
1174 extra_comments=None,
1175 profile_key=C.PROF_KEY_NONE,
1176 ):
1177 """Helper method to get the microblogs and their comments in one shot 1172 """Helper method to get the microblogs and their comments in one shot
1178 1173
1179 @param publishers_type (str): type of the list of publishers (one of "GROUP" or "JID" or "ALL") 1174 @param publishers_type (str): type of the list of publishers (one of "GROUP" or
1180 @param publishers (list): list of publishers, according to publishers_type (list of groups or list of jids) 1175 "JID" or "ALL")
1176 @param publishers (list): list of publishers, according to publishers_type (list
1177 of groups or list of jids)
1181 @param max_items (int): optional limit on the number of retrieved items. 1178 @param max_items (int): optional limit on the number of retrieved items.
1182 @param max_comments (int): maximum number of comments to retrieve 1179 @param max_comments (int): maximum number of comments to retrieve
1183 @param rsm_request (rsm.RSMRequest): RSM request for initial items only 1180 @param rsm_request (rsm.RSMRequest): RSM request for initial items only
1184 @param extra (dict): extra configuration for initial items only 1181 @param extra (dict): extra configuration for initial items only
1185 @param rsm_comments (rsm.RSMRequest): RSM request for comments only 1182 @param rsm_comments (rsm.RSMRequest): RSM request for comments only
1221 rsm_request=rsm_comments, 1218 rsm_request=rsm_comments,
1222 extra=extra_comments, 1219 extra=extra_comments,
1223 ) 1220 )
1224 # then serialise 1221 # then serialise
1225 d.addCallback( 1222 d.addCallback(
1226 lambda items_data: self._p.serItemsDataD( 1223 lambda items_data: self._p.transItemsDataD(
1227 items_data, self.item2mbdata 1224 items_data, self.item2mbdata, serialise=True
1228 ) 1225 )
1229 ) 1226 )
1230 # with failure handling 1227 # with failure handling
1231 d.addCallback( 1228 d.addCallback(
1232 lambda serialised_items_data: ("",) + serialised_items_data 1229 lambda serialised_items_data: ("",) + serialised_items_data
1233 ) 1230 )
1234 d.addErrback(lambda failure: (unicode(failure.value), [], {})) 1231 d.addErrback(lambda failure: (unicode(failure.value), [], {}))
1235 # and associate with service/node (needed if there are several comments nodes) 1232 # and associate with service/node (needed if there are several
1233 # comments nodes)
1236 d.addCallback( 1234 d.addCallback(
1237 lambda serialised, service_s=service_s, node=node: ( 1235 lambda serialised, service_s=service_s, node=node: (
1238 service_s, 1236 service_s,
1239 node, 1237 node,
1240 ) 1238 )
1258 for service, node in node_data: 1256 for service, node in node_data:
1259 d = deferreds[(service, node)] = self._p.getItems( 1257 d = deferreds[(service, node)] = self._p.getItems(
1260 client, service, node, max_items, rsm_request=rsm_request, extra=extra 1258 client, service, node, max_items, rsm_request=rsm_request, extra=extra
1261 ) 1259 )
1262 d.addCallback( 1260 d.addCallback(
1263 lambda items_data: self._p.serItemsDataD(items_data, self.item2mbdata) 1261 lambda items_data: self._p.transItemsDataD(items_data, self.item2mbdata)
1264 ) 1262 )
1265 d.addCallback(getComments) 1263 d.addCallback(getComments)
1266 d.addCallback(lambda items_comments_data: ("", items_comments_data)) 1264 d.addCallback(lambda items_comments_data: ("", items_comments_data))
1267 d.addErrback(lambda failure: (unicode(failure.value), ([], {}))) 1265 d.addErrback(lambda failure: (unicode(failure.value), ([], {})))
1268 1266