changeset 3842:943901372eba

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
author Goffi <goffi@goffi.org>
date Thu, 14 Jul 2022 12:55:30 +0200
parents b337d7da72e5
children 17c757bd74bc
files sat/plugins/plugin_comp_ap_gateway/__init__.py
diffstat 1 files changed, 49 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/sat/plugins/plugin_comp_ap_gateway/__init__.py	Thu Jul 14 12:55:19 2022 +0200
+++ b/sat/plugins/plugin_comp_ap_gateway/__init__.py	Thu Jul 14 12:55:30 2022 +0200
@@ -348,12 +348,55 @@
         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 @@
         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 @@
         @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: