comparison sat/plugins/plugin_xep_0277.py @ 3328:d49607e3a066

plugin XEP-0277: set "uri" in item2mbdata
author Goffi <goffi@goffi.org>
date Mon, 03 Aug 2020 08:45:49 +0200
parents 384283adcce1
children 13b91b7280bc
comparison
equal deleted inserted replaced
3327:ddc10f76fb7e 3328:d49607e3a066
14 # GNU Affero General Public License for more details. 14 # GNU Affero General Public License for more details.
15 15
16 # You should have received a copy of the GNU Affero General Public License 16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 18
19 from sat.core.i18n import _ 19 import shortuuid
20 from sat.core.constants import Const as C 20 import time
21 from sat.core.log import getLogger 21 import dateutil
22 import calendar
23 import urllib.parse
24 from typing import Optional
25 from functools import partial
22 26
23 from twisted.words.protocols.jabber import jid, error 27 from twisted.words.protocols.jabber import jid, error
24 from twisted.words.protocols.jabber.xmlstream import XMPPHandler 28 from twisted.words.protocols.jabber.xmlstream import XMPPHandler
25 from twisted.words.xish import domish 29 from twisted.words.xish import domish
26 from twisted.internet import defer 30 from twisted.internet import defer
27 from twisted.python import failure 31 from twisted.python import failure
32
33 # XXX: sat_tmp.wokkel.pubsub is actually used instead of wokkel version
34 from wokkel import pubsub
35 from wokkel import disco, iwokkel
36 from zope.interface import implementer
37
38 from sat.core.i18n import _
39 from sat.core.constants import Const as C
40 from sat.core.log import getLogger
28 from sat.core import exceptions 41 from sat.core import exceptions
42 from sat.core.xmpp import SatXMPPEntity
29 from sat.tools import xml_tools 43 from sat.tools import xml_tools
30 from sat.tools import sat_defer 44 from sat.tools import sat_defer
31 from sat.tools import utils 45 from sat.tools import utils
32 from sat.tools.common import data_format 46 from sat.tools.common import data_format
33 from sat.tools.common import uri as xmpp_uri 47 from sat.tools.common import uri as xmpp_uri
34 48
35 # XXX: sat_tmp.wokkel.pubsub is actually used instead of wokkel version
36 from wokkel import pubsub
37 from wokkel import disco, iwokkel
38 from zope.interface import implementer
39 import shortuuid
40 import time
41 import dateutil
42 import calendar
43 import urllib.parse
44 49
45 log = getLogger(__name__) 50 log = getLogger(__name__)
46 51
47 52
48 NS_MICROBLOG = "urn:xmpp:microblog:0" 53 NS_MICROBLOG = "urn:xmpp:microblog:0"
183 client.profile, 188 client.profile,
184 ) 189 )
185 190
186 for item in itemsEvent.items: 191 for item in itemsEvent.items:
187 if item.name == C.PS_ITEM: 192 if item.name == C.PS_ITEM:
188 self.item2mbdata(item).addCallbacks( 193 # FIXME: service and node should be used here
194 self.item2mbdata(client, item).addCallbacks(
189 manageItem, lambda failure: None, (C.PS_PUBLISH,) 195 manageItem, lambda failure: None, (C.PS_PUBLISH,)
190 ) 196 )
191 elif item.name == C.PS_RETRACT: 197 elif item.name == C.PS_RETRACT:
192 manageItem({"id": item["id"]}, C.PS_RETRACT) 198 manageItem({"id": item["id"]}, C.PS_RETRACT)
193 else: 199 else:
194 raise exceptions.InternalError("Invalid event value") 200 raise exceptions.InternalError("Invalid event value")
195 201
196 ## data/item transformation ## 202 ## data/item transformation ##
197 203
198 @defer.inlineCallbacks 204 @defer.inlineCallbacks
199 def item2mbdata(self, item_elt): 205 def item2mbdata(
206 self,
207 client: SatXMPPEntity,
208 item_elt: domish.Element,
209 service: Optional[jid.JID],
210 # FIXME: node is Optional until all calls to item2mbdata set properly service
211 # and node. Once done, the Optional must be removed here
212 node: Optional[str]
213 ) -> dict:
200 """Convert an XML Item to microblog data 214 """Convert an XML Item to microblog data
201 215
202 @param item_elt: domish.Element of microblog item 216 @param item_elt: microblog item element
203 @return: microblog data (dictionary) 217 @param service: PubSub service where the item has been retrieved
218 profile's PEP is used when service is None
219 @param node: PubSub node where the item has been retrieved
220 if None, "uri" won't be set
221 @return: microblog data
204 """ 222 """
205 microblog_data = {} 223 microblog_data = {}
206 224
207 def check_conflict(key, increment=False): 225 def check_conflict(key, increment=False):
208 """Check if key is already in microblog data 226 """Check if key is already in microblog data
270 try: 288 try:
271 entry_elt = next(item_elt.elements(NS_ATOM, "entry")) 289 entry_elt = next(item_elt.elements(NS_ATOM, "entry"))
272 except StopIteration: 290 except StopIteration:
273 msg = "No atom entry found in the pubsub item {}".format(id_) 291 msg = "No atom entry found in the pubsub item {}".format(id_)
274 raise failure.Failure(exceptions.DataError(msg)) 292 raise failure.Failure(exceptions.DataError(msg))
293
294 # uri
295 # FIXME: node should alway be set in the future, check FIXME in method signature
296 if node is not None:
297 microblog_data['uri'] = xmpp_uri.buildXMPPUri(
298 "pubsub",
299 path=service.full() if service is not None else client.jid.userhost(),
300 node=node,
301 item=id_,
302 )
275 303
276 # language 304 # language
277 try: 305 try:
278 microblog_data["language"] = entry_elt[(C.NS_XML, "lang")].strip() 306 microblog_data["language"] = entry_elt[(C.NS_XML, "lang")].strip()
279 except KeyError: 307 except KeyError:
855 item_ids=item_ids, 883 item_ids=item_ids,
856 rsm_request=rsm_request, 884 rsm_request=rsm_request,
857 extra=extra, 885 extra=extra,
858 ) 886 )
859 mb_data = yield self._p.transItemsDataD( 887 mb_data = yield self._p.transItemsDataD(
860 items_data, self.item2mbdata) 888 items_data, partial(self.item2mbdata, client, service=service, node=node))
861 defer.returnValue(mb_data) 889 defer.returnValue(mb_data)
862 890
863 def parseCommentUrl(self, node_url): 891 def parseCommentUrl(self, node_url):
864 """Parse a XMPP URI 892 """Parse a XMPP URI
865 893
1039 - items_data(list): data as returned by [mbGet] 1067 - items_data(list): data as returned by [mbGet]
1040 - items_metadata(dict): metadata as returned by [mbGet] 1068 - items_metadata(dict): metadata as returned by [mbGet]
1041 @param profile_key: %(doc_profile_key)s 1069 @param profile_key: %(doc_profile_key)s
1042 """ 1070 """
1043 1071
1072 client = self.host.getClient(profile_key)
1073
1044 def onSuccess(items_data): 1074 def onSuccess(items_data):
1045 """convert items elements to list of microblog data in items_data""" 1075 """convert items elements to list of microblog data in items_data"""
1046 d = self._p.transItemsDataD(items_data, self.item2mbdata, serialise=True) 1076 d = self._p.transItemsDataD(
1077 items_data,
1078 # FIXME: service and node should be used here
1079 partial(self.item2mbdata, client),
1080 serialise=True
1081 )
1047 d.addCallback(lambda serialised: ("", serialised)) 1082 d.addCallback(lambda serialised: ("", serialised))
1048 return d 1083 return d
1049 1084
1050 profile = self.host.getClient(profile_key).profile
1051 d = self._p.getRTResults( 1085 d = self._p.getRTResults(
1052 session_id, 1086 session_id,
1053 on_success=onSuccess, 1087 on_success=onSuccess,
1054 on_error=lambda failure: (str(failure.value), ([], {})), 1088 on_error=lambda failure: (str(failure.value), ([], {})),
1055 profile=profile, 1089 profile=client.profile,
1056 ) 1090 )
1057 d.addCallback( 1091 d.addCallback(
1058 lambda ret: ( 1092 lambda ret: (
1059 ret[0], 1093 ret[0],
1060 [ 1094 [
1224 for key, value in item.items(): 1258 for key, value in item.items():
1225 # we look for comments 1259 # we look for comments
1226 if key.startswith("comments") and key.endswith("_service"): 1260 if key.startswith("comments") and key.endswith("_service"):
1227 prefix = key[: key.find("_")] 1261 prefix = key[: key.find("_")]
1228 service_s = value 1262 service_s = value
1263 service = jid.JID(service_s)
1229 node = item["{}{}".format(prefix, "_node")] 1264 node = item["{}{}".format(prefix, "_node")]
1230 # time to get the comments 1265 # time to get the comments
1231 d = self._p.getItems( 1266 d = self._p.getItems(
1232 client, 1267 client,
1233 jid.JID(service_s), 1268 service,
1234 node, 1269 node,
1235 max_comments, 1270 max_comments,
1236 rsm_request=rsm_comments, 1271 rsm_request=rsm_comments,
1237 extra=extra_comments, 1272 extra=extra_comments,
1238 ) 1273 )
1239 # then serialise 1274 # then serialise
1240 d.addCallback( 1275 d.addCallback(
1241 lambda items_data: self._p.transItemsDataD( 1276 lambda items_data: self._p.transItemsDataD(
1242 items_data, self.item2mbdata, serialise=True 1277 items_data,
1278 partial(
1279 self.item2mbdata, client, service=service, node=node
1280 ),
1281 serialise=True
1243 ) 1282 )
1244 ) 1283 )
1245 # with failure handling 1284 # with failure handling
1246 d.addCallback( 1285 d.addCallback(
1247 lambda serialised_items_data: ("",) + serialised_items_data 1286 lambda serialised_items_data: ("",) + serialised_items_data
1275 d = deferreds[(service, node)] = self._p.getItems( 1314 d = deferreds[(service, node)] = self._p.getItems(
1276 client, service, node, max_items, rsm_request=rsm_request, extra=extra 1315 client, service, node, max_items, rsm_request=rsm_request, extra=extra
1277 ) 1316 )
1278 d.addCallback( 1317 d.addCallback(
1279 lambda items_data: self._p.transItemsDataD( 1318 lambda items_data: self._p.transItemsDataD(
1280 items_data, self.item2mbdata) 1319 items_data,
1320 partial(self.item2mbdata, client, service=service, node=node),
1321 )
1281 ) 1322 )
1282 d.addCallback(getComments) 1323 d.addCallback(getComments)
1283 d.addCallback(lambda items_comments_data: ("", items_comments_data)) 1324 d.addCallback(lambda items_comments_data: ("", items_comments_data))
1284 d.addErrback(lambda failure: (str(failure.value), ([], {}))) 1325 d.addErrback(lambda failure: (str(failure.value), ([], {})))
1285 1326