comparison src/plugins/plugin_misc_groupblog.py @ 477:031b0e0aaab8

plugin groupblog: subscriptions/notifications
author Goffi <goffi@goffi.org>
date Mon, 25 Jun 2012 00:08:16 +0200
parents b9fd32b46306
children f856575a62a6
comparison
equal deleted inserted replaced
476:b9fd32b46306 477:031b0e0aaab8
32 except ImportError: 32 except ImportError:
33 from wokkel.subprotocols import XMPPHandler 33 from wokkel.subprotocols import XMPPHandler
34 34
35 NS_PUBSUB = 'http://jabber.org/protocol/pubsub' 35 NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
36 NS_GROUPBLOG = 'http://goffi.org/protocol/groupblog' 36 NS_GROUPBLOG = 'http://goffi.org/protocol/groupblog'
37 NS_NODE_PREFIX = 'urn:xmpp:groupblog:'
37 #NS_PUBSUB_EXP = 'http://goffi.org/protocol/pubsub' #for non official features 38 #NS_PUBSUB_EXP = 'http://goffi.org/protocol/pubsub' #for non official features
38 NS_PUBSUB_EXP = NS_PUBSUB #XXX: we can't use custom namespace as Wokkel's PubSubService use official NS 39 NS_PUBSUB_EXP = NS_PUBSUB #XXX: we can't use custom namespace as Wokkel's PubSubService use official NS
39 NS_PUBSUB_ITEM_ACCESS = NS_PUBSUB_EXP + "#item-access" 40 NS_PUBSUB_ITEM_ACCESS = NS_PUBSUB_EXP + "#item-access"
40 NS_PUBSUB_CREATOR_JID_CHECK = NS_PUBSUB_EXP + "#creator-jid-check" 41 NS_PUBSUB_CREATOR_JID_CHECK = NS_PUBSUB_EXP + "#creator-jid-check"
41 NS_PUBSUB_ITEM_CONFIG = NS_PUBSUB_EXP + "#item-config" 42 NS_PUBSUB_ITEM_CONFIG = NS_PUBSUB_EXP + "#item-config"
86 87
87 host.bridge.addMethod("getMassiveLastGroupBlogs", ".plugin", 88 host.bridge.addMethod("getMassiveLastGroupBlogs", ".plugin",
88 in_sign='sasis', out_sign='a{saa{ss}}', 89 in_sign='sasis', out_sign='a{saa{ss}}',
89 method=self.getMassiveLastGroupBlogs, 90 method=self.getMassiveLastGroupBlogs,
90 async = True) 91 async = True)
92
93 host.bridge.addMethod("subscribeGroupBlog", ".plugin", in_sign='ss', out_sign='',
94 method=self.subscribeGroupBlog,
95 async = True)
96
97 host.bridge.addMethod("massiveSubscribeGroupBlogs", ".plugin", in_sign='sass', out_sign='',
98 method=self.massiveSubscribeGroupBlogs,
99 async = True)
100
101 host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger)
102
91 103
92 def getHandler(self, profile): 104 def getHandler(self, profile):
93 return GroupBlog_handler() 105 return GroupBlog_handler()
94 106
95 @defer.inlineCallbacks 107 @defer.inlineCallbacks
113 debug(_('Looking for item-access power pubsub server')) 125 debug(_('Looking for item-access power pubsub server'))
114 #we don't have any pubsub server featuring item access yet 126 #we don't have any pubsub server featuring item access yet
115 client.item_access_pubsub = None 127 client.item_access_pubsub = None
116 for entity in self.host.memory.getServerServiceEntities("pubsub", "service", profile): 128 for entity in self.host.memory.getServerServiceEntities("pubsub", "service", profile):
117 _disco = yield client.disco.requestInfo(entity) 129 _disco = yield client.disco.requestInfo(entity)
118 if set([NS_PUBSUB_ITEM_ACCESS, NS_PUBSUB_AUTO_CREATE, NS_PUBSUB_CREATOR_JID_CHECK]).issubset(_disco.features): 130 #if set([NS_PUBSUB_ITEM_ACCESS, NS_PUBSUB_AUTO_CREATE, NS_PUBSUB_CREATOR_JID_CHECK]).issubset(_disco.features):
131 if set([NS_PUBSUB_AUTO_CREATE, NS_PUBSUB_CREATOR_JID_CHECK]).issubset(_disco.features):
119 info(_("item-access powered pubsub service found: [%s]") % entity.full()) 132 info(_("item-access powered pubsub service found: [%s]") % entity.full())
120 client.item_access_pubsub = entity 133 client.item_access_pubsub = entity
121 134
122 if not client.item_access_pubsub: 135 if not client.item_access_pubsub:
123 error(_("No item-access powered pubsub server found, can't use group blog")) 136 error(_("No item-access powered pubsub server found, can't use group blog"))
124 raise NoCompatiblePubSubServerFound 137 raise NoCompatiblePubSubServerFound
125 138
126 defer.returnValue((profile, client)) 139 defer.returnValue((profile, client))
140
141 def pubSubItemsReceivedTrigger(self, event, profile):
142 """"Trigger which catch groupblogs events"""
143 if event.nodeIdentifier.startswith(NS_NODE_PREFIX):
144 for item in event.items:
145 microblog_data = self.host.plugins["XEP-0277"].item2mbdata(item)
146 self.host.bridge.personalEvent(event.sender.full(), "MICROBLOG", microblog_data, profile)
147 return False
148 return True
149
150
151
152 def getNodeName(self, publisher):
153 """Retrieve the name of publisher's node
154 @param publisher: publisher's jid
155 @return: node's name (string)"""
156 return NS_NODE_PREFIX + publisher.userhost()
157
127 158
128 159
129 def _publishMblog(self, service, client, access_type, access_list, message): 160 def _publishMblog(self, service, client, access_type, access_list, message):
130 """Actually publish the message on the group blog 161 """Actually publish the message on the group blog
131 @param service: jid of the item-access pubsub service 162 @param service: jid of the item-access pubsub service
150 elif access_type == "JID": 181 elif access_type == "JID":
151 raise NotImplementedError 182 raise NotImplementedError
152 else: 183 else:
153 error(_("Unknown access_type")) 184 error(_("Unknown access_type"))
154 raise BadAccessTypeError 185 raise BadAccessTypeError
155 defer_blog = self.host.plugins["XEP-0060"].publish(service, client.jid.userhost(), items=[mblog_item], profile_key=client.profile) 186 defer_blog = self.host.plugins["XEP-0060"].publish(service, self.getNodeName(client.jid), items=[mblog_item], profile_key=client.profile)
156 defer_blog.addErrback(self._mblogPublicationFailed) 187 defer_blog.addErrback(self._mblogPublicationFailed)
157 188
158 def _mblogPublicationFailed(self, failure): 189 def _mblogPublicationFailed(self, failure):
159 #TODO 190 #TODO
160 return failure 191 return failure
197 @return: list of microblog data (dict) 228 @return: list of microblog data (dict)
198 """ 229 """
199 230
200 def initialised(result): 231 def initialised(result):
201 profile, client = result 232 profile, client = result
202 d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, jid.JID(pub_jid).userhost(), 233 d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)),
203 max_items=max_items, profile_key=profile_key) 234 max_items=max_items, profile_key=profile_key)
204 d.addCallback(lambda items: map(self.host.plugins["XEP-0277"].item2mbdata, items)) 235 d.addCallback(lambda items: map(self.host.plugins["XEP-0277"].item2mbdata, items))
205 d.addErrback(lambda ignore: {}) #TODO: more complete error management (log !) 236 d.addErrback(lambda ignore: {}) #TODO: more complete error management (log !)
206 return d 237 return d
207 238
233 if publishers_type == "ALL": 264 if publishers_type == "ALL":
234 contacts = client.roster.getItems() 265 contacts = client.roster.getItems()
235 jids = [contact.jid.userhost() for contact in contacts] 266 jids = [contact.jid.userhost() for contact in contacts]
236 mblogs = [] 267 mblogs = []
237 for _jid in jids: 268 for _jid in jids:
238 d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, jid.JID(_jid).userhost(), 269 d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid.JID(_jid)),
239 max_items=max_items, profile_key=profile_key) 270 max_items=max_items, profile_key=profile_key)
240 d.addCallback(lambda items, source_jid: (source_jid, map(self.host.plugins["XEP-0277"].item2mbdata, items)), _jid) 271 d.addCallback(lambda items, source_jid: (source_jid, map(self.host.plugins["XEP-0277"].item2mbdata, items)), _jid)
241 mblogs.append(d) 272 mblogs.append(d)
242 dlist = defer.DeferredList(mblogs) 273 dlist = defer.DeferredList(mblogs)
243 dlist.addCallback(sendResult) 274 dlist.addCallback(sendResult)
252 if publishers_type=="ALL" and publishers: 283 if publishers_type=="ALL" and publishers:
253 raise Exception("Publishers list must be empty when getting microblogs for all contacts") 284 raise Exception("Publishers list must be empty when getting microblogs for all contacts")
254 return self.initialise(profile_key).addCallback(initialised) 285 return self.initialise(profile_key).addCallback(initialised)
255 #TODO: we need to use the server corresponding the the host of the jid 286 #TODO: we need to use the server corresponding the the host of the jid
256 287
288 def subscribeGroupBlog(self, pub_jid, profile_key='@DEFAULT'):
289 def initialised(result):
290 profile, client = result
291 d = self.host.plugins["XEP-0060"].subscribe(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)),
292 profile_key=profile_key)
293 return d
294
295 #TODO: we need to use the server corresponding the the host of the jid
296 return self.initialise(profile_key).addCallback(initialised)
297
298
299 def massiveSubscribeGroupBlogs(self, publishers_type, publishers, profile_key='@DEFAULT@'):
300 """Subscribe microblogs for a list of groups or jids
301 @param publishers_type: type of the list of publishers (one of "GROUP" or "JID" or "ALL")
302 @param publishers: list of publishers, according to "publishers_type" (list of groups or list of jids)
303 @param profile_key: profile key
304 """
305 def initialised(result):
306 profile, client = result
307
308 if publishers_type == "ALL":
309 contacts = client.roster.getItems()
310 jids = [contact.jid.userhost() for contact in contacts]
311 mblogs = []
312 for _jid in jids:
313 d = self.host.plugins["XEP-0060"].subscribe(client.item_access_pubsub, self.getNodeName(jid.JID(_jid)),
314 profile_key=profile_key)
315 mblogs.append(d)
316 dlist = defer.DeferredList(mblogs)
317 return dlist
318
319 return defer.fail("Unknown type")
320
321
322 #TODO: custom exception
323 if publishers_type not in ["GROUP", "JID", "ALL"]:
324 raise Exception("Bad call, unknown publishers_type")
325 if publishers_type=="ALL" and publishers:
326 raise Exception("Publishers list must be empty when getting microblogs for all contacts")
327 return self.initialise(profile_key).addCallback(initialised)
328 #TODO: we need to use the server corresponding the the host of the jid
329
330
331
257 class GroupBlog_handler(XMPPHandler): 332 class GroupBlog_handler(XMPPHandler):
258 implements(iwokkel.IDisco) 333 implements(iwokkel.IDisco)
259 334
260 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): 335 def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
261 return [disco.DiscoFeature(NS_GROUPBLOG)] 336 return [disco.DiscoFeature(NS_GROUPBLOG)]