diff sat/plugins/plugin_xep_0060.py @ 3519:02eec2a5b5f9

plugin XEP-0060, XEP-0277: new rename methods (`psItemRename`, `mbRename`): Those methods recreate an item to given new ID, and if successful, delete the former one.
author Goffi <goffi@goffi.org>
date Sat, 01 May 2021 18:37:57 +0200
parents fa796612adad
children edc79cefe968
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0060.py	Sat May 01 18:36:13 2021 +0200
+++ b/sat/plugins/plugin_xep_0060.py	Sat May 01 18:37:57 2021 +0200
@@ -17,6 +17,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+from typing import Optional
 from collections import namedtuple
 import urllib.request, urllib.parse, urllib.error
 from functools import reduce
@@ -34,6 +35,7 @@
 from sat.core.i18n import _
 from sat.core.constants import Const as C
 from sat.core.log import getLogger
+from sat.core.xmpp import SatXMPPEntity
 from sat.core import exceptions
 from sat.tools import sat_defer
 from sat.tools import xml_tools
@@ -233,6 +235,14 @@
             async_=True,
         )
         host.bridge.addMethod(
+            "psItemRename",
+            ".plugin",
+            in_sign="sssss",
+            out_sign="",
+            method=self._renameItem,
+            async_=True,
+        )
+        host.bridge.addMethod(
             "psSubscribe",
             ".plugin",
             in_sign="ssa{ss}s",
@@ -1031,26 +1041,61 @@
     def _retractItems(
         self, service_s, nodeIdentifier, itemIdentifiers, notify, profile_key
     ):
+        client = self.host.getClient(profile_key)
         return self.retractItems(
+            client,
             jid.JID(service_s) if service_s else None,
             nodeIdentifier,
             itemIdentifiers,
             notify,
-            profile_key,
         )
 
     def retractItems(
         self,
+        client,
         service,
         nodeIdentifier,
         itemIdentifiers,
         notify=True,
+    ):
+        return client.pubsub_client.retractItems(
+            service, nodeIdentifier, itemIdentifiers, notify=True
+        )
+
+    def _renameItem(
+        self,
+        service,
+        node,
+        item_id,
+        new_id,
         profile_key=C.PROF_KEY_NONE,
     ):
         client = self.host.getClient(profile_key)
-        return client.pubsub_client.retractItems(
-            service, nodeIdentifier, itemIdentifiers, notify=True
-        )
+        service = jid.JID(service) if service else None
+        return defer.ensureDeferred(self.renameItem(
+            client, service, node, item_id, new_id
+        ))
+
+    async def renameItem(
+        self,
+        client: SatXMPPEntity,
+        service: Optional[jid.JID],
+        node: str,
+        item_id: str,
+        new_id: str
+    ) -> None:
+        """Rename an item by recreating it then deleting it
+
+        we have to recreate then delete because there is currently no rename operation
+        with PubSub
+        """
+        if not item_id or not new_id:
+            raise ValueError("item_id and new_id must not be empty")
+        # retract must be done last, so if something goes wrong, the exception will stop
+        # the workflow and no accidental delete should happen
+        item_elt = (await self.getItems(client, service, node, item_ids=[item_id]))[0][0]
+        await self.sendItem(client, service, node, item_elt.firstChildElement(), new_id)
+        await self.retractItems(client, service, node, [item_id])
 
     def _subscribe(self, service, nodeIdentifier, options, profile_key=C.PROF_KEY_NONE):
         client = self.host.getClient(profile_key)