changeset 3100:cea52c9ddfd9

plugin XEP-0060, jp (pubsub/set): publish-options implementation: - publishing options (XEP-0060 §7.1.5) implementation. - jp pubsub/set can specify publish-options using `-f` and `-F` - doc has been updated to explain that - psItemSend and psItemsSend now use serialisation for "extra" - publish-options can be specified in extra['publish-options'] with those methods
author Goffi <goffi@goffi.org>
date Sat, 28 Dec 2019 20:02:18 +0100
parents 0b6d56a8f7e3
children ab7e8ade848a
files doc/jp/pubsub.rst doc/jp/pubsub_node.rst doc/overview.rst sat/plugins/plugin_xep_0060.py sat_frontends/jp/cmd_pubsub.py
diffstat 5 files changed, 56 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/doc/jp/pubsub.rst	Fri Dec 27 13:30:20 2019 +0100
+++ b/doc/jp/pubsub.rst	Sat Dec 28 20:02:18 2019 +0100
@@ -17,6 +17,15 @@
 
 ``stdin`` is used to get the raw XML of the payload of the item to publish.
 
+``-f KEY VALUE, --field KEY VALUE`` can be used to specify publish options, i.e. option
+which must be set if the node already exists, or used if the node is to be created, see
+`XEP-0060 §7.1.5`_ for details.
+
+In the same way as for :ref:`jp-pubsub_node_create`, ``-F, --full-prefix`` can be used if
+you need to specify the full option name.
+
+.. _XEP-0060 §7.1.5: https://xmpp.org/extensions/xep-0060.html#publisher-publish-options
+
 example
 -------
 
--- a/doc/jp/pubsub_node.rst	Fri Dec 27 13:30:20 2019 +0100
+++ b/doc/jp/pubsub_node.rst	Sat Dec 28 20:02:18 2019 +0100
@@ -23,6 +23,8 @@
 
   $ jp pubsub node info -n urn:xmpp:microblog:0 -k access_model -k publish_model
 
+.. _jp-pubsub_node_create:
+
 create
 ======
 
--- a/doc/overview.rst	Fri Dec 27 13:30:20 2019 +0100
+++ b/doc/overview.rst	Sat Dec 28 20:02:18 2019 +0100
@@ -66,7 +66,7 @@
 -----
 
 Cagou is the desktop/mobile frontend. It's probably the main interface for most users. It
-is based on the `Kivy`_ framework and should run of most platforms (for now it is
+is based on the `Kivy`_ framework and should run on most platforms (for now it is
 officially tested only on GNU/Linux and Android phones and tablets).
 
 .. _Kivy: https://kivy.org
--- a/sat/plugins/plugin_xep_0060.py	Fri Dec 27 13:30:20 2019 +0100
+++ b/sat/plugins/plugin_xep_0060.py	Sat Dec 28 20:02:18 2019 +0100
@@ -201,7 +201,7 @@
         host.bridge.addMethod(
             "psItemSend",
             ".plugin",
-            in_sign="ssssa{ss}s",
+            in_sign="ssssss",
             out_sign="s",
             method=self._sendItem,
             async_=True,
@@ -209,7 +209,7 @@
         host.bridge.addMethod(
             "psItemsSend",
             ".plugin",
-            in_sign="ssasa{ss}s",
+            in_sign="ssasss",
             out_sign="as",
             method=self._sendItems,
             async_=True,
@@ -453,17 +453,18 @@
     #     d.addCallback(lambda subs: [sub.getAttribute('node') for sub in subs if sub.getAttribute('subscription') == filter_])
     #     return d
 
-    def _sendItem(self, service, nodeIdentifier, payload, item_id=None, extra=None,
+    def _sendItem(self, service, nodeIdentifier, payload, item_id=None, extra_ser="",
                   profile_key=C.PROF_KEY_NONE):
         client = self.host.getClient(profile_key)
         service = None if not service else jid.JID(service)
+        extra = data_format.deserialise(extra_ser)
         d = self.sendItem(
             client, service, nodeIdentifier, payload, item_id or None, extra
         )
         d.addCallback(lambda ret: ret or "")
         return d
 
-    def _sendItems(self, service, nodeIdentifier, items, extra=None,
+    def _sendItems(self, service, nodeIdentifier, items, extra_ser=None,
                   profile_key=C.PROF_KEY_NONE):
         client = self.host.getClient(profile_key)
         service = None if not service else jid.JID(service)
@@ -472,6 +473,7 @@
         except Exception as e:
             raise exceptions.DataError(_("Can't parse items: {msg}").format(
                 msg=e))
+        extra = data_format.deserialise(extra_ser)
         d = self.sendItems(
             client, service, nodeIdentifier, items, extra
         )
@@ -501,8 +503,12 @@
         @param extra(dict, None): extra option, not used yet
         @return (unicode, None): id of the created item
         """
+        if extra is None:
+            extra = {}
+        publish_options = extra.get('publish_options')
         item_elt = pubsub.Item(id=item_id, payload=payload)
-        d = self.publish(client, service, nodeIdentifier, [item_elt])
+        d = self.publish(
+            client, service, nodeIdentifier, [item_elt], options=publish_options)
         d.addCallback(self._getPublishedItemId, item_id)
         return d
 
@@ -523,22 +529,28 @@
         @param NodeIdentifier(unicode): PubSub node to use
         @param items(list[domish.Element]): whole item elements to send,
             "id" will be used if set
-        @param extra(dict, None): extra option, not used yet
+        @param extra(dict, None): extra options. Key can be:
+            - publish_options: dict of publish-options
         @return (list[unicode]): ids of the created items
         """
+        if extra is None:
+            extra = {}
         parsed_items = []
         for item in items:
             if item.name != 'item':
                 raise exceptions.DataError(_("Invalid item: {xml}").format(item.toXml()))
             item_id = item.getAttribute("id")
             parsed_items.append(pubsub.Item(id=item_id, payload=item.firstChildElement()))
-        d = self.publish(client, service, nodeIdentifier, parsed_items)
+        publish_options = extra.get('publish_options')
+        d = self.publish(
+            client, service, nodeIdentifier, parsed_items, options=publish_options)
         d.addCallback(self._publishCb)
         return d
 
-    def publish(self, client, service, nodeIdentifier, items=None):
+    def publish(self, client, service, nodeIdentifier, items=None, options=None):
         return client.pubsub_client.publish(
-            service, nodeIdentifier, items, client.pubsub_client.parent.jid
+            service, nodeIdentifier, items, client.pubsub_client.parent.jid,
+            options=options
         )
 
     def _unwrapMAMMessage(self, message_elt):
--- a/sat_frontends/jp/cmd_pubsub.py	Fri Dec 27 13:30:20 2019 +0100
+++ b/sat_frontends/jp/cmd_pubsub.py	Sat Dec 28 20:02:18 2019 +0100
@@ -32,6 +32,7 @@
 from sat_frontends.jp import arg_tools
 from sat_frontends.jp import xml_tools
 from functools import partial
+from sat.tools.common import data_format
 from sat.tools.common import uri
 from sat.tools.common.ansi import ANSI as A
 from sat_frontends.tools import jid, strings
@@ -104,8 +105,9 @@
             help=_("create a node"),
         )
 
-    def add_parser_options(self):
-        self.parser.add_argument(
+    @staticmethod
+    def add_node_config_options(parser):
+        parser.add_argument(
             "-f",
             "--field",
             action="append",
@@ -115,18 +117,25 @@
             metavar=("KEY", "VALUE"),
             help=_("configuration field to set"),
         )
-        self.parser.add_argument(
+        parser.add_argument(
             "-F",
             "--full-prefix",
             action="store_true",
             help=_('don\'t prepend "pubsub#" prefix to field names'),
         )
 
+    def add_parser_options(self):
+        self.add_node_config_options(self.parser)
+
+    @staticmethod
+    def get_config_options(args):
+        if not args.full_prefix:
+            return {"pubsub#" + k: v for k, v in args.fields}
+        else:
+            return dict(args.fields)
+
     async def start(self):
-        if not self.args.full_prefix:
-            options = {"pubsub#" + k: v for k, v in self.args.fields}
-        else:
-            options = dict(self.args.fields)
+        options = self.get_config_options(self.args)
         try:
             node_id = await self.host.bridge.psNodeCreate(
                 self.args.service,
@@ -730,6 +739,7 @@
         )
 
     def add_parser_options(self):
+        NodeCreate.add_node_config_options(self.parser)
         self.parser.add_argument(
             "item",
             nargs="?",
@@ -741,6 +751,10 @@
         element, etree = xml_tools.etreeParse(self, sys.stdin)
         element = xml_tools.getPayload(self, element)
         payload = etree.tostring(element, encoding="unicode")
+        extra = {}
+        publish_options = NodeCreate.get_config_options(self.args)
+        if publish_options:
+            extra['publish_options'] = publish_options
 
         try:
             published_id = await self.host.bridge.psItemSend(
@@ -748,7 +762,7 @@
                 self.args.node,
                 payload,
                 self.args.item,
-                {},
+                data_format.serialise(extra),
                 self.profile,
             )
         except Exception as e:
@@ -869,7 +883,7 @@
             self.pubsub_node,
             content,
             self.pubsub_item or "",
-            {},
+            "",
             self.profile,
         )
         if published_id: