From fe4dc35f5cdd03e4b3bc62e49bb75cc52802723a Mon Sep 17 00:00:00 2001 From: Goffi Date: Thu, 14 Jul 2022 12:55:30 +0200 Subject: [PATCH] component AP gateway: `apGetObject` and `apGetList` now work with local object: When a local item is linked, it is found from database instead of doing an HTTP request. rel 370 --- .../plugin_comp_ap_gateway/__init__.py | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/sat/plugins/plugin_comp_ap_gateway/__init__.py b/sat/plugins/plugin_comp_ap_gateway/__init__.py index 6ff45ba3..fbfc9cd7 100644 --- a/sat/plugins/plugin_comp_ap_gateway/__init__.py +++ b/sat/plugins/plugin_comp_ap_gateway/__init__.py @@ -348,12 +348,55 @@ class APGateway: elif isinstance(value, dict): return value elif isinstance(value, str): - return await self.apGet(value) + if self.isLocalURL(value): + return await self.apGetLocalObject(value) + else: + return await self.apGet(value) else: raise NotImplementedError( "was expecting a string or a dict, got {type(value)}: {value!r}}" ) + async def apGetLocalObject( + self, + url: str + ) -> dict: + """Retrieve or generate local object + + for now, only handle XMPP items to convert to AP + """ + url_type, url_args = self.parseAPURL(url) + if url_type == TYPE_ITEM: + try: + account, item_id = url_args + except ValueError: + raise ValueError(f"invalid URL: {url}") + author_jid, node = await self.getJIDAndNode(account) + if node is None: + node = self._m.namespace + cached_node = await self.host.memory.storage.getPubsubNode( + self.client, author_jid, node + ) + if not cached_node: + raise exceptions.NotFound + cached_items, __ = await self.host.memory.storage.getItems( + cached_node, item_ids=[item_id] + ) + if not cached_items: + raise exceptions.NotFound( + f"item {item_id!r} is not found in cache" + ) + mb_data = await self._m.item2mbdata( + self.client, cached_items[0].data, author_jid, node + ) + ap_item = await self.mbdata2APitem(self.client, mb_data) + # the URL must return the object and not the activity + return ap_item["object"] + else: + raise NotImplementedError( + 'only object from "item" URLs can be retrieved for now' + ) + async def apGetList( self, data: dict, @@ -374,7 +417,10 @@ class APGateway: if value is None: return None elif isinstance(value, str): - value = await self.apGet(value) + if self.isLocalURL(value): + value = await self.apGetLocalObject(value) + else: + value = await self.apGet(value) if isinstance(value, dict): return [value] if not isinstance(value, list): @@ -680,7 +726,7 @@ class APGateway: @return: endpoint type and extra arguments """ path = parse.urlparse(url).path.lstrip("/") - type_, *extra_args = path[len(self.ap_path):].lstrip("/").split("/", 1) + type_, *extra_args = path[len(self.ap_path):].lstrip("/").split("/") return type_, [parse.unquote(a) for a in extra_args] def buildAPURL(self, type_:str , *args: str) -> str: