comparison sat/plugins/plugin_xep_0060.py @ 3308:384283adcce1

plugins XEP-0059, XEP-0060, XEP-0277, XEP-0313: better serialisation: `data_format.serialise` is now used for `mbGet`, and RSM/MAM values are not transtyped to strings anymore. A serialised dict is now used, items are put in the `items` key. Comments handling has been refactored to use a list for the potentially multiple comments nodes. `rsm` data are now in a `rsm` key of the dict, and `mam` data are merged with other metadata.
author Goffi <goffi@goffi.org>
date Thu, 16 Jul 2020 09:07:20 +0200
parents 4c98f4972db5
children 77177b13ff54
comparison
equal deleted inserted replaced
3307:9f0e28137cd0 3308:384283adcce1
715 metadata = { 715 metadata = {
716 "service": service_jid, 716 "service": service_jid,
717 "node": node, 717 "node": node,
718 "uri": self.getNodeURI(service_jid, node), 718 "uri": self.getNodeURI(service_jid, node),
719 } 719 }
720 if mam_response is not None:
721 # mam_response is a dict with "complete" and "stable" keys
722 # we can put them directly in metadata
723 metadata.update(mam_response)
720 if rsm_request is not None and rsm_response is not None: 724 if rsm_request is not None and rsm_response is not None:
721 metadata.update( 725 metadata['rsm'] = rsm_response.toDict()
722 { 726 if mam_response is None:
723 "rsm_" + key: value 727 index = rsm_response.index
724 for key, value in rsm_response.toDict().items() 728 count = rsm_response.count
725 } 729 if index is None or count is None:
726 ) 730 # we don't have enough information to know if the data is complete
727 if mam_response is not None: 731 # or not
728 for key, value in mam_response.items(): 732 metadata["complete"] = None
729 metadata["mam_" + key] = value 733 else:
734 # normally we have a strict equality here but XEP-0059 states
735 # that index MAY be approximative, so just in caseā€¦
736 metadata["complete"] = index + len(items) >= count
737
730 return (items, metadata) 738 return (items, metadata)
731 739
732 d.addCallback(addMetadata) 740 d.addCallback(addMetadata)
733 return d 741 return d
734 742
1105 1113
1106 @param service(jid.JID): PubSub service 1114 @param service(jid.JID): PubSub service
1107 @param node(unicode): node 1115 @param node(unicode): node
1108 @return (unicode): URI of the node 1116 @return (unicode): URI of the node
1109 """ 1117 """
1118 # FIXME: deprecated, use sat.tools.common.uri instead
1110 assert service is not None 1119 assert service is not None
1111 # XXX: urllib.urlencode use "&" to separate value, while XMPP URL (cf. RFC 5122) 1120 # XXX: urllib.urlencode use "&" to separate value, while XMPP URL (cf. RFC 5122)
1112 # use ";" as a separator. So if more than one value is used in query_data, 1121 # use ";" as a separator. So if more than one value is used in query_data,
1113 # urlencode MUST NOT BE USED. 1122 # urlencode MUST NOT BE USED.
1114 query_data = [("node", node.encode("utf-8"))] 1123 query_data = [("node", node.encode("utf-8"))]
1125 def getRTResults( 1134 def getRTResults(
1126 self, session_id, on_success=None, on_error=None, profile=C.PROF_KEY_NONE 1135 self, session_id, on_success=None, on_error=None, profile=C.PROF_KEY_NONE
1127 ): 1136 ):
1128 return self.rt_sessions.getResults(session_id, on_success, on_error, profile) 1137 return self.rt_sessions.getResults(session_id, on_success, on_error, profile)
1129 1138
1130 def transItemsData(self, items_data, item_cb=lambda item: item.toXml(), 1139 def transItemsData(self, items_data, item_cb=lambda item: item.toXml()):
1131 serialise=False):
1132 """Helper method to transform result from [getItems] 1140 """Helper method to transform result from [getItems]
1141
1142 the items_data must be a tuple(list[domish.Element], dict[unicode, unicode])
1143 as returned by [getItems].
1144 @param items_data(tuple): tuple returned by [getItems]
1145 @param item_cb(callable): method to transform each item
1146 @return (tuple): a serialised form ready to go throught bridge
1147 """
1148 items, metadata = items_data
1149 items = [item_cb(item) for item in items]
1150
1151 return (items, metadata)
1152
1153 def transItemsDataD(self, items_data, item_cb):
1154 """Helper method to transform result from [getItems], deferred version
1133 1155
1134 the items_data must be a tuple(list[domish.Element], dict[unicode, unicode]) 1156 the items_data must be a tuple(list[domish.Element], dict[unicode, unicode])
1135 as returned by [getItems]. metadata values are then casted to unicode and 1157 as returned by [getItems]. metadata values are then casted to unicode and
1136 each item is passed to items_cb then optionally serialised with 1158 each item is passed to items_cb.
1137 data_format.serialise.
1138 @param items_data(tuple): tuple returned by [getItems]
1139 @param item_cb(callable): method to transform each item
1140 @param serialise(bool): if True do a data_format.serialise
1141 after applying item_cb
1142 @return (tuple): a serialised form ready to go throught bridge
1143 """
1144 items, metadata = items_data
1145 if serialise:
1146 items = [data_format.serialise(item_cb(item)) for item in items]
1147 else:
1148 items = [item_cb(item) for item in items]
1149
1150 return (
1151 items,
1152 {key: str(value) for key, value in metadata.items()},
1153 )
1154
1155 def transItemsDataD(self, items_data, item_cb, serialise=False):
1156 """Helper method to transform result from [getItems], deferred version
1157
1158 the items_data must be a tuple(list[domish.Element], dict[unicode, unicode])
1159 as returned by [getItems]. metadata values are then casted to unicode and
1160 each item is passed to items_cb then optionally serialised with
1161 data_format.serialise.
1162 An errback is added to item_cb, and when it is fired the value is filtered from 1159 An errback is added to item_cb, and when it is fired the value is filtered from
1163 final items 1160 final items
1164 @param items_data(tuple): tuple returned by [getItems] 1161 @param items_data(tuple): tuple returned by [getItems]
1165 @param item_cb(callable): method to transform each item (must return a deferred) 1162 @param item_cb(callable): method to transform each item (must return a deferred)
1166 @param serialise(bool): if True do a data_format.serialise 1163 @return (tuple): a deferred which fire a dict which can be serialised to go
1167 after applying item_cb 1164 throught bridge
1168 @return (tuple): a deferred which fire a serialised form ready to go throught
1169 bridge
1170 """ 1165 """
1171 items, metadata = items_data 1166 items, metadata = items_data
1172 1167
1173 def eb(failure_): 1168 def eb(failure_):
1174 log.warning(f"Error while serialising/parsing item: {failure_.value}") 1169 log.warning(f"Error while parsing item: {failure_.value}")
1175 1170
1176 d = defer.gatherResults([item_cb(item).addErrback(eb) for item in items]) 1171 d = defer.gatherResults([item_cb(item).addErrback(eb) for item in items])
1177 1172 d.addCallback(lambda parsed_items: (parsed_items, metadata))
1178 def finishSerialisation(parsed_items):
1179 if serialise:
1180 items = [data_format.serialise(i) for i in parsed_items if i is not None]
1181 else:
1182 items = [i for i in parsed_items if i is not None]
1183
1184 return (
1185 items,
1186 {key: str(value) for key, value in metadata.items()},
1187 )
1188
1189 d.addCallback(finishSerialisation)
1190 return d 1173 return d
1191 1174
1192 def serDList(self, results, failure_result=None): 1175 def serDList(self, results, failure_result=None):
1193 """Serialise a DeferredList result 1176 """Serialise a DeferredList result
1194 1177