changeset 1821:d6062afdd54f

plugin XEP-0277: comments handling improvments: - if comments*, comments*_node or comments*_service are provided, they are used instead of generated values - moved node and service generation to getCommentNode and getCommentService, so they can be used by an external plugin
author Goffi <>
date Fri, 22 Jan 2016 20:24:17 +0100
parents 3c8cf120a0fd
children aaf034bc6f7a
files src/plugins/
diffstat 1 files changed, 53 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/	Fri Jan 22 20:24:17 2016 +0100
+++ b/src/plugins/	Fri Jan 22 20:24:17 2016 +0100
@@ -455,18 +455,40 @@
     ## publish ##
+    def getCommentNode(self, item_id):
+        """Generate comment node
+        @param item_id(unicode): id of the parent item
+        @return (unicode): comment node to use
+        """
+        return u"{}{}".format(NS_COMMENT_PREFIX, item_id)
+    def getCommentService(self, client, parent_service=None):
+        """Get prefered PubSub service to create comment node
+        @param pubsub_service(jid.JID, None): PubSub service of the parent item
+        @param return(jid.JID, None): PubSub service to use
+        """
+        return client.pubsub_service if client.pubsub_service is not None else parent_service
     def _manageComments(self, access, mb_data, service, node, item_id, profile):
         """Check comments keys in mb_data and create comments node if necessary
+        if mb_data['comments'] exists, it is used (or mb_data['comments_service'] and/or mb_data['comments_node']),
+        else it is generated (if allow_comments is True).
         @param access(unicode): access model
         @param mb_data(dict): microblog mb_data
-        @param service(jid.JID): Pubsub service of the parent item
+        @param service(jid.JID, None): PubSub service of the parent item
         @param node(unicode): node of the parent item
         @param item_id(unicoe): id of the parent item
+        # FIXME: if 'comments' already exists in mb_data, it is not used to create the Node
         allow_comments = C.bool(mb_data.pop("allow_comments", "false"))
         if not allow_comments:
+            if 'comments' in mb_data:
+                log.warning(u"comments are not allowed but there is already a comments node, it may be lost: {uri}".format(uri=mb_data['comments']))
+                del mb_data['comments']
         client =
@@ -482,9 +504,18 @@
         # if other plugins need to change the options
         yield"XEP-0277_comments", client, mb_data, options)
-        comments_node_base = u"{}{}".format(NS_COMMENT_PREFIX, item_id)
-        comments_node = comments_node_base
-        comments_service = client.pubsub_service if client.pubsub_service is not None else service
+        try:
+            comments_node = mb_data['comments_node']
+        except KeyError:
+            comments_node = self.getCommentNode(item_id)
+        else:
+            if not comments_node:
+                raise exceptions.DataError(u"if comments_node is present, it must not be empty")
+        try:
+            comments_service = mb_data['comments_service']
+        except KeyError:
+            comments_service = self.getCommentService(client, service)
             yield self._p.createNode(comments_service, comments_node, options, profile_key=profile)
@@ -497,31 +528,40 @@
         if comments_service is None:
             comments_service = client.jid.userhostJID()
-        mb_data['comments'] = "xmpp:%(service)s?%(query)s" % {
-            'service': comments_service.userhost(),
-            'query': urllib.urlencode([('node', comments_node.encode('utf-8'))])
-            }
+        if 'comments' in mb_data:
+            if not mb_data['comments']:
+                raise exceptions.DataError(u"if comments is present, it must not be empty")
+            if 'comments_node' in mb_data or 'comments_service' in mb_data:
+                raise exceptions.DataError(u"You can't use comments_service/comments_node and comments at the same time")
+        else:
+            mb_data['comments'] = u"xmpp:%(service)s?%(query)s" % {
+                'service': comments_service.userhost(),
+                'query': urllib.urlencode([('node', comments_node.encode('utf-8'))])
+                }
     def _mbSend(self, service, node, data, profile_key):
         service = jid.JID(service) if service else None
         node = node if node else NS_MICROBLOG
         profile =
-        return self.send(service, node, data, profile)
+        return self.send(data, service, node, profile)
-    def send(self, service=None, node=NS_MICROBLOG, data=None, profile=None):
+    def send(self, data, service=None, node=NS_MICROBLOG, profile=None):
         """Send XEP-0277's microblog data
+        @param data(dict): microblog data (must include at least a "content" or a "title" key).
+            see for details
         @param service(jid.JID, None): PubSub service where the microblog must be published
             None to publish on profile's PEP
-        @param node(unicode): PubSub node to use (defaut to microblog NS)
-        @param data(dict): microblog data (must include at least a "content" or a "title" key).
-            see for details
+        @param node(unicode, None): PubSub node to use (defaut to microblog NS)
+            None is equivalend as using default value
         @param profile: %(doc_profile)s
         # TODO: check that all data keys are used, this would avoid sending publicly a private message
         #       by accident (e.g. if group pluging is not loaded, and "grou*" key are not used)
         assert profile is not None
+        if node is None:
+            node = NS_MICROBLOG
         item_id = data.get('id') or unicode(uuid.uuid4())