# HG changeset patch # User Goffi # Date 1340575696 -7200 # Node ID 031b0e0aaab8817d394c9446bb031d5189a58e13 # Parent b9fd32b46306aca2d07308e70e2999d3b1dd4e36 plugin groupblog: subscriptions/notifications diff -r b9fd32b46306 -r 031b0e0aaab8 frontends/src/bridge/DBus.py --- a/frontends/src/bridge/DBus.py Thu May 31 00:26:39 2012 +0200 +++ b/frontends/src/bridge/DBus.py Mon Jun 25 00:08:16 2012 +0200 @@ -252,6 +252,12 @@ def getMassiveLastGroupBlogs(self, publishers_type, publishers, max_items=10, profile_key='@DEFAULT@', callback=None, errback=None): return self.db_plugin_iface.getMassiveLastGroupBlogs(publishers_type, publishers, max_items, profile_key, reply_handler=callback, error_handler=errback) + def subscribeGroupBlog(self, jid, profile_key='@DEFAULT@', callback=None, errback=None): + return self.db_plugin_iface.subscribeGroupBlog(jid, profile_key, reply_handler=callback, error_handler=errback) + + def massiveSubscribeGroupBlogs(self, publishers_type, publishers, profile_key='@DEFAULT@', callback=None, errback=None): + return self.db_plugin_iface.massiveSubscribeGroupBlogs(publishers_type, publishers, profile_key, reply_handler=callback, error_handler=errback) + def sendPersonalEvent(self, event_type, data, profile_key): return self.db_plugin_iface.sendPersonalEvent(event_type, data, profile_key) diff -r b9fd32b46306 -r 031b0e0aaab8 src/bridge/DBus.py --- a/src/bridge/DBus.py Thu May 31 00:26:39 2012 +0200 +++ b/src/bridge/DBus.py Mon Jun 25 00:08:16 2012 +0200 @@ -34,6 +34,9 @@ const_CORE_SUFFIX = ".core" const_PLUGIN_SUFFIX = ".plugin" +class ParseError(Exception): + pass + class MethodNotRegistered(dbus.DBusException): _dbus_error_name = const_ERROR_PREFIX + ".MethodNotRegistered" @@ -50,7 +53,7 @@ def __init__(self, twisted_error): super(GenericException,self).__init__() mess = twisted_error.getErrorMessage() - self._dbus_error_name = const_ERROR_PREFIX+"."+ (mess or str(err.__class__)) + self._dbus_error_name = const_ERROR_PREFIX+"."+ (mess or str(twisted_error.__class__)) class DbusObject(dbus.service.Object): diff -r b9fd32b46306 -r 031b0e0aaab8 src/bridge/bridge_constructor/dbus_core_template.py --- a/src/bridge/bridge_constructor/dbus_core_template.py Thu May 31 00:26:39 2012 +0200 +++ b/src/bridge/bridge_constructor/dbus_core_template.py Mon Jun 25 00:08:16 2012 +0200 @@ -34,6 +34,9 @@ const_CORE_SUFFIX = ".core" const_PLUGIN_SUFFIX = ".plugin" +class ParseError(Exception): + pass + class MethodNotRegistered(dbus.DBusException): _dbus_error_name = const_ERROR_PREFIX + ".MethodNotRegistered" @@ -50,7 +53,7 @@ def __init__(self, twisted_error): super(GenericException,self).__init__() mess = twisted_error.getErrorMessage() - self._dbus_error_name = const_ERROR_PREFIX+"."+ (mess or str(err.__class__)) + self._dbus_error_name = const_ERROR_PREFIX+"."+ (mess or str(twisted_error.__class__)) class DbusObject(dbus.service.Object): diff -r b9fd32b46306 -r 031b0e0aaab8 src/bridge/bridge_constructor/dbus_frontend_template.py --- a/src/bridge/bridge_constructor/dbus_frontend_template.py Thu May 31 00:26:39 2012 +0200 +++ b/src/bridge/bridge_constructor/dbus_frontend_template.py Mon Jun 25 00:08:16 2012 +0200 @@ -145,6 +145,12 @@ def getMassiveLastGroupBlogs(self, publishers_type, publishers, max_items=10, profile_key='@DEFAULT@', callback=None, errback=None): return self.db_plugin_iface.getMassiveLastGroupBlogs(publishers_type, publishers, max_items, profile_key, reply_handler=callback, error_handler=errback) + def subscribeGroupBlog(self, jid, profile_key='@DEFAULT@', callback=None, errback=None): + return self.db_plugin_iface.subscribeGroupBlog(jid, profile_key, reply_handler=callback, error_handler=errback) + + def massiveSubscribeGroupBlogs(self, publishers_type, publishers, profile_key='@DEFAULT@', callback=None, errback=None): + return self.db_plugin_iface.massiveSubscribeGroupBlogs(publishers_type, publishers, profile_key, reply_handler=callback, error_handler=errback) + def sendPersonalEvent(self, event_type, data, profile_key): return self.db_plugin_iface.sendPersonalEvent(event_type, data, profile_key) diff -r b9fd32b46306 -r 031b0e0aaab8 src/plugins/plugin_misc_groupblog.py --- a/src/plugins/plugin_misc_groupblog.py Thu May 31 00:26:39 2012 +0200 +++ b/src/plugins/plugin_misc_groupblog.py Mon Jun 25 00:08:16 2012 +0200 @@ -34,6 +34,7 @@ NS_PUBSUB = 'http://jabber.org/protocol/pubsub' NS_GROUPBLOG = 'http://goffi.org/protocol/groupblog' +NS_NODE_PREFIX = 'urn:xmpp:groupblog:' #NS_PUBSUB_EXP = 'http://goffi.org/protocol/pubsub' #for non official features NS_PUBSUB_EXP = NS_PUBSUB #XXX: we can't use custom namespace as Wokkel's PubSubService use official NS NS_PUBSUB_ITEM_ACCESS = NS_PUBSUB_EXP + "#item-access" @@ -88,6 +89,17 @@ in_sign='sasis', out_sign='a{saa{ss}}', method=self.getMassiveLastGroupBlogs, async = True) + + host.bridge.addMethod("subscribeGroupBlog", ".plugin", in_sign='ss', out_sign='', + method=self.subscribeGroupBlog, + async = True) + + host.bridge.addMethod("massiveSubscribeGroupBlogs", ".plugin", in_sign='sass', out_sign='', + method=self.massiveSubscribeGroupBlogs, + async = True) + + host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger) + def getHandler(self, profile): return GroupBlog_handler() @@ -115,7 +127,8 @@ client.item_access_pubsub = None for entity in self.host.memory.getServerServiceEntities("pubsub", "service", profile): _disco = yield client.disco.requestInfo(entity) - if set([NS_PUBSUB_ITEM_ACCESS, NS_PUBSUB_AUTO_CREATE, NS_PUBSUB_CREATOR_JID_CHECK]).issubset(_disco.features): + #if set([NS_PUBSUB_ITEM_ACCESS, NS_PUBSUB_AUTO_CREATE, NS_PUBSUB_CREATOR_JID_CHECK]).issubset(_disco.features): + if set([NS_PUBSUB_AUTO_CREATE, NS_PUBSUB_CREATOR_JID_CHECK]).issubset(_disco.features): info(_("item-access powered pubsub service found: [%s]") % entity.full()) client.item_access_pubsub = entity @@ -125,6 +138,24 @@ defer.returnValue((profile, client)) + def pubSubItemsReceivedTrigger(self, event, profile): + """"Trigger which catch groupblogs events""" + if event.nodeIdentifier.startswith(NS_NODE_PREFIX): + for item in event.items: + microblog_data = self.host.plugins["XEP-0277"].item2mbdata(item) + self.host.bridge.personalEvent(event.sender.full(), "MICROBLOG", microblog_data, profile) + return False + return True + + + + def getNodeName(self, publisher): + """Retrieve the name of publisher's node + @param publisher: publisher's jid + @return: node's name (string)""" + return NS_NODE_PREFIX + publisher.userhost() + + def _publishMblog(self, service, client, access_type, access_list, message): """Actually publish the message on the group blog @@ -152,7 +183,7 @@ else: error(_("Unknown access_type")) raise BadAccessTypeError - defer_blog = self.host.plugins["XEP-0060"].publish(service, client.jid.userhost(), items=[mblog_item], profile_key=client.profile) + defer_blog = self.host.plugins["XEP-0060"].publish(service, self.getNodeName(client.jid), items=[mblog_item], profile_key=client.profile) defer_blog.addErrback(self._mblogPublicationFailed) def _mblogPublicationFailed(self, failure): @@ -199,7 +230,7 @@ def initialised(result): profile, client = result - d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, jid.JID(pub_jid).userhost(), + d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)), max_items=max_items, profile_key=profile_key) d.addCallback(lambda items: map(self.host.plugins["XEP-0277"].item2mbdata, items)) d.addErrback(lambda ignore: {}) #TODO: more complete error management (log !) @@ -235,7 +266,7 @@ jids = [contact.jid.userhost() for contact in contacts] mblogs = [] for _jid in jids: - d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, jid.JID(_jid).userhost(), + d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid.JID(_jid)), max_items=max_items, profile_key=profile_key) d.addCallback(lambda items, source_jid: (source_jid, map(self.host.plugins["XEP-0277"].item2mbdata, items)), _jid) mblogs.append(d) @@ -254,6 +285,50 @@ return self.initialise(profile_key).addCallback(initialised) #TODO: we need to use the server corresponding the the host of the jid + def subscribeGroupBlog(self, pub_jid, profile_key='@DEFAULT'): + def initialised(result): + profile, client = result + d = self.host.plugins["XEP-0060"].subscribe(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)), + profile_key=profile_key) + return d + + #TODO: we need to use the server corresponding the the host of the jid + return self.initialise(profile_key).addCallback(initialised) + + + def massiveSubscribeGroupBlogs(self, publishers_type, publishers, profile_key='@DEFAULT@'): + """Subscribe microblogs for a list of groups or jids + @param publishers_type: type of the list of publishers (one of "GROUP" or "JID" or "ALL") + @param publishers: list of publishers, according to "publishers_type" (list of groups or list of jids) + @param profile_key: profile key + """ + def initialised(result): + profile, client = result + + if publishers_type == "ALL": + contacts = client.roster.getItems() + jids = [contact.jid.userhost() for contact in contacts] + mblogs = [] + for _jid in jids: + d = self.host.plugins["XEP-0060"].subscribe(client.item_access_pubsub, self.getNodeName(jid.JID(_jid)), + profile_key=profile_key) + mblogs.append(d) + dlist = defer.DeferredList(mblogs) + return dlist + + return defer.fail("Unknown type") + + + #TODO: custom exception + if publishers_type not in ["GROUP", "JID", "ALL"]: + raise Exception("Bad call, unknown publishers_type") + if publishers_type=="ALL" and publishers: + raise Exception("Publishers list must be empty when getting microblogs for all contacts") + return self.initialise(profile_key).addCallback(initialised) + #TODO: we need to use the server corresponding the the host of the jid + + + class GroupBlog_handler(XMPPHandler): implements(iwokkel.IDisco) diff -r b9fd32b46306 -r 031b0e0aaab8 src/plugins/plugin_xep_0060.py --- a/src/plugins/plugin_xep_0060.py Thu May 31 00:26:39 2012 +0200 +++ b/src/plugins/plugin_xep_0060.py Mon Jun 25 00:08:16 2012 +0200 @@ -131,6 +131,8 @@ pubsub.PubSubClient.connectionInitialized(self) def itemsReceived(self, event): + if not self.host.trigger.point("PubSubItemsReceived", event, self.parent.profile): + return for node in self.parent_plugin.managedNodes: if event.nodeIdentifier == node[0]: return node[1](event, self.parent.profile)