Mercurial > libervia-backend
comparison src/plugins/plugin_misc_groupblog.py @ 858:660b3f5b6c78
plugins groupblog, XEP-0277: attempt to clarify the code for the comments handling:
- add or update some methods docstrings
- add GroupBlog.__fillCommentsElement to factorize the code responsible to build the comments link
- do not mix up attributes names between the item own service/node and the comments service/node
author | souliane <souliane@mailoo.org> |
---|---|
date | Fri, 14 Feb 2014 21:24:31 +0100 |
parents | 071524bfcc7d |
children | 2b98f5631fba |
comparison
equal
deleted
inserted
replaced
857:3c270d691e56 | 858:660b3f5b6c78 |
---|---|
134 def getHandler(self, profile): | 134 def getHandler(self, profile): |
135 return GroupBlog_handler() | 135 return GroupBlog_handler() |
136 | 136 |
137 @defer.inlineCallbacks | 137 @defer.inlineCallbacks |
138 def _initialise(self, profile_key): | 138 def _initialise(self, profile_key): |
139 """Check that this data for this profile are initialised, and do it else | 139 """Check that the data for this profile are initialised, and do it else |
140 @param client: client of the profile | 140 @param profile_key: %(doc_profile)s""" |
141 @profile_key: %(doc_profile)s""" | |
142 profile = self.host.memory.getProfileName(profile_key) | 141 profile = self.host.memory.getProfileName(profile_key) |
143 if not profile: | 142 if not profile: |
144 raise exceptions.ProfileUnknownError | 143 raise exceptions.ProfileUnknownError |
145 | 144 |
146 client = self.host.getClient(profile) | 145 client = self.host.getClient(profile) |
264 return NS_NODE_PREFIX + publisher.userhost() | 263 return NS_NODE_PREFIX + publisher.userhost() |
265 | 264 |
266 def _publishMblog(self, service, client, access_type, access_list, message, extra): | 265 def _publishMblog(self, service, client, access_type, access_list, message, extra): |
267 """Actually publish the message on the group blog | 266 """Actually publish the message on the group blog |
268 @param service: jid of the item-access pubsub service | 267 @param service: jid of the item-access pubsub service |
269 @param client: SatXMPPClient of the published | 268 @param client: SatXMPPClient of the publisher |
270 @param access_type: one of "PUBLIC", "GROUP", "JID" | 269 @param access_type: one of "PUBLIC", "GROUP", "JID" |
271 @param access_list: set of entities (empty list for all, groups or jids) allowed to see the item | 270 @param access_list: set of entities (empty list for all, groups or jids) allowed to see the item |
272 @param message: message to publish | 271 @param message: message to publish |
273 @param extra: dict which option name as key, which can be: | 272 @param extra: dict which option name as key, which can be: |
274 - allow_comments: True to accept comments, False else (default: False) | 273 - allow_comments: True to accept comments, False else (default: False) |
283 P = self.host.plugins["XEP-0060"] | 282 P = self.host.plugins["XEP-0060"] |
284 access_model_value = ACCESS_TYPE_MAP[access_type] | 283 access_model_value = ACCESS_TYPE_MAP[access_type] |
285 | 284 |
286 if extra.get('allow_comments', 'False').lower() == 'true': | 285 if extra.get('allow_comments', 'False').lower() == 'true': |
287 # XXX: use the item identifier? http://bugs.goffi.org/show_bug.cgi?id=63 | 286 # XXX: use the item identifier? http://bugs.goffi.org/show_bug.cgi?id=63 |
288 comments_node = "%s_%s__%s" % (NS_COMMENT_PREFIX, str(uuid.uuid4()), node_name) | 287 comments_node = self.__fillCommentsElement(mblog_data, None, node_name, service) |
289 mblog_data['comments'] = "xmpp:%(service)s?%(query)s" % {'service': service.userhost(), | |
290 'query': urllib.urlencode([('node', comments_node.encode('utf-8'))])} | |
291 _options = {P.OPT_ACCESS_MODEL: access_model_value, | 288 _options = {P.OPT_ACCESS_MODEL: access_model_value, |
292 P.OPT_PERSIST_ITEMS: 1, | 289 P.OPT_PERSIST_ITEMS: 1, |
293 P.OPT_MAX_ITEMS: -1, | 290 P.OPT_MAX_ITEMS: -1, |
294 P.OPT_DELIVER_PAYLOADS: 1, | 291 P.OPT_DELIVER_PAYLOADS: 1, |
295 P.OPT_SEND_ITEM_SUBSCRIBE: 1, | 292 P.OPT_SEND_ITEM_SUBSCRIBE: 1, |
329 | 326 |
330 entry_d = self.host.plugins["XEP-0277"].data2entry(mblog_data, client.profile) | 327 entry_d = self.host.plugins["XEP-0277"].data2entry(mblog_data, client.profile) |
331 entry_d.addCallback(itemCreated) | 328 entry_d.addCallback(itemCreated) |
332 return entry_d | 329 return entry_d |
333 | 330 |
331 def __fillCommentsElement(self, mblog_data, entry_id, node_name, service_jid): | |
332 """ | |
333 @param mblog_data: dict containing the microblog data | |
334 @param entry_id: unique identifier of the entry | |
335 @param node_name: the pubsub node name | |
336 @param service_jid: the JID of the pubsub service | |
337 @return: the comments node string | |
338 """ | |
339 if entry_id is None: | |
340 entry_id = unicode(uuid.uuid4()) | |
341 comments_node = "%s_%s__%s" % (NS_COMMENT_PREFIX, entry_id, node_name) | |
342 mblog_data['comments'] = "xmpp:%(service)s?%(query)s" % {'service': service_jid.userhost(), | |
343 'query': urllib.urlencode([('node', comments_node.encode('utf-8'))])} | |
344 return comments_node | |
345 | |
334 def _mblogPublicationFailed(self, failure): | 346 def _mblogPublicationFailed(self, failure): |
335 #TODO | 347 #TODO |
336 return failure | 348 return failure |
337 | 349 |
338 def sendGroupBlog(self, access_type, access_list, message, extra, profile_key='@NONE@'): | 350 def sendGroupBlog(self, access_type, access_list, message, extra, profile_key='@NONE@'): |
366 | 378 |
367 return self._initialise(profile_key).addCallback(initialised) | 379 return self._initialise(profile_key).addCallback(initialised) |
368 | 380 |
369 def deleteGroupBlog(self, pub_data, comments, profile_key='@NONE@'): | 381 def deleteGroupBlog(self, pub_data, comments, profile_key='@NONE@'): |
370 """Delete a microblog item from a node. | 382 """Delete a microblog item from a node. |
371 @param pub_data: a tuple (service, comment node identifier, item identifier) | 383 @param pub_data: a tuple (service, node identifier, item identifier) |
372 @param comments: comments node identifier (for main item) or empty string | 384 @param comments: comments node identifier (for main item) or empty string |
373 @param profile_key: %(doc_profile_key)s | 385 @param profile_key: %(doc_profile_key)s |
374 """ | 386 """ |
375 | 387 |
376 def initialised(result): | 388 def initialised(result): |
377 profile, client = result | 389 profile, client = result |
378 service, node, item_id = pub_data | 390 service, node, item_id = pub_data |
391 service_jid = jid.JID(service) if service else client.item_access_pubsub | |
392 if comments or not node: # main item | |
393 node = self.getNodeName(client.jid) | |
379 if comments: | 394 if comments: |
380 # remove the associated comments node | 395 # remove the associated comments node |
381 d = self.host.plugins["XEP-0060"].deleteNode(jid.JID(service), node, profile_key=profile) | 396 comments_service, comments_node = self.host.plugins["XEP-0277"].parseCommentUrl(comments) |
382 d.addErrback(lambda failure: error("Deletion of node %s failed: %s" % (node, failure.getErrorMessage()))) | 397 d = self.host.plugins["XEP-0060"].deleteNode(comments_service, comments_node, profile_key=profile) |
383 node = self.getNodeName(client.jid) | 398 d.addErrback(lambda failure: error("Deletion of node %s failed: %s" % (comments_node, failure.getErrorMessage()))) |
384 # remove the item itself | 399 # remove the item itself |
385 d = self.host.plugins["XEP-0060"].retractItems(jid.JID(service), node, [item_id], profile_key=profile) | 400 d = self.host.plugins["XEP-0060"].retractItems(service_jid, node, [item_id], profile_key=profile) |
386 d.addErrback(lambda failure: error("Deletion of item %s from %s failed: %s" % (item_id, node, failure.getErrorMessage()))) | 401 d.addErrback(lambda failure: error("Deletion of item %s from %s failed: %s" % (item_id, node, failure.getErrorMessage()))) |
387 return d | 402 return d |
388 | 403 |
389 def notify(d): | 404 def notify(d): |
390 # TODO: this works only on the same host, and notifications for item deletion should be | 405 # TODO: this works only on the same host, and notifications for item deletion should be |
392 # instead. The notification mechanisms implemented in sat_pubsub and wokkel seem not compatible, | 407 # instead. The notification mechanisms implemented in sat_pubsub and wokkel seem not compatible, |
393 # see wokkel.pubsub.PubSubClient._onEvent_items and sat_pubsub.backend._doNotifyRetraction | 408 # see wokkel.pubsub.PubSubClient._onEvent_items and sat_pubsub.backend._doNotifyRetraction |
394 service, node, item_id = pub_data | 409 service, node, item_id = pub_data |
395 publisher = self.host.getJidNStream(profile_key)[0] | 410 publisher = self.host.getJidNStream(profile_key)[0] |
396 profile = self.host.memory.getProfileName(profile_key) | 411 profile = self.host.memory.getProfileName(profile_key) |
397 gbdatum = {'id': item_id, 'type': 'main_item' if comments else 'comment'} | 412 gbdatum = {'id': item_id, 'type': 'main_item' if (comments or not node) else 'comment'} |
398 self.host.bridge.personalEvent(publisher.full(), "MICROBLOG_DELETE", gbdatum, profile) | 413 self.host.bridge.personalEvent(publisher.full(), "MICROBLOG_DELETE", gbdatum, profile) |
399 return d | 414 return d |
400 | 415 |
401 return self._initialise(profile_key).addCallback(initialised).addCallback(notify) | 416 return self._initialise(profile_key).addCallback(initialised).addCallback(notify) |
402 | 417 |
403 def updateGroupBlog(self, pub_data, comments, message, extra, profile_key='@NONE@'): | 418 def updateGroupBlog(self, pub_data, comments, message, extra, profile_key='@NONE@'): |
404 """Modify a microblog node | 419 """Modify a microblog node |
405 @param pub_data: a tuple (service, comment node identifier, item identifier) | 420 @param pub_data: a tuple (service, node identifier, item identifier) |
406 @param comments: comments node identifier (for main item) or empty string | 421 @param comments: comments node identifier (for main item) or empty string |
407 @param message: new message | 422 @param message: new message |
408 @param extra: dict which option name as key, which can be: | 423 @param extra: dict which option name as key, which can be: |
409 - allow_comments: True to accept an other level of comments, False else (default: False) | 424 - allow_comments: True to accept an other level of comments, False else (default: False) |
410 - rich: if present, contain rich text in currently selected syntax | 425 - rich: if present, contain rich text in currently selected syntax |
416 mblog_data = {'content': message} | 431 mblog_data = {'content': message} |
417 for attr in ['content_rich', 'title', 'title_rich']: | 432 for attr in ['content_rich', 'title', 'title_rich']: |
418 if attr in extra and extra[attr]: | 433 if attr in extra and extra[attr]: |
419 mblog_data[attr] = extra[attr] | 434 mblog_data[attr] = extra[attr] |
420 service, node, item_id = pub_data | 435 service, node, item_id = pub_data |
421 if comments: | 436 service_jid = jid.JID(service) if service else client.item_access_pubsub |
437 if comments or not node: # main item | |
422 node = self.getNodeName(client.jid) | 438 node = self.getNodeName(client.jid) |
423 mblog_data['id'] = str(item_id) | 439 mblog_data['id'] = unicode(item_id) |
424 if 'published' in extra: | 440 if 'published' in extra: |
425 mblog_data['published'] = extra['published'] | 441 mblog_data['published'] = extra['published'] |
426 if extra.get('allow_comments', 'False').lower() == 'true': | 442 if extra.get('allow_comments', 'False').lower() == 'true': |
427 comments_node = self.host.plugins["XEP-0277"].parseCommentUrl(comments)[1] | 443 comments_service, comments_node = self.host.plugins["XEP-0277"].parseCommentUrl(comments) |
428 # we could use comments_node directly but it's safer to rebuild it | 444 # we could use comments_node directly but it's safer to rebuild it |
429 # XXX: use the item identifier? http://bugs.goffi.org/show_bug.cgi?id=63 | 445 # XXX: use the item identifier? http://bugs.goffi.org/show_bug.cgi?id=63 |
430 hash_ = comments_node.split('_')[1].split('__')[0] | 446 entry_id = comments_node.split('_')[1].split('__')[0] |
431 comments_node = "%s_%s__%s" % (NS_COMMENT_PREFIX, hash_, node) | 447 self.__fillCommentsElement(mblog_data, entry_id, node, service_jid) |
432 mblog_data['comments'] = "xmpp:%(service)s?%(query)s" % {'service': jid.JID(service).userhost(), | |
433 'query': urllib.urlencode([('node', comments_node.encode('utf-8'))])} | |
434 entry_d = self.host.plugins["XEP-0277"].data2entry(mblog_data, profile) | 448 entry_d = self.host.plugins["XEP-0277"].data2entry(mblog_data, profile) |
435 entry_d.addCallback(lambda mblog_item: self.host.plugins["XEP-0060"].publish(jid.JID(service), node, items=[mblog_item], profile_key=profile)) | 449 entry_d.addCallback(lambda mblog_item: self.host.plugins["XEP-0060"].publish(service_jid, node, items=[mblog_item], profile_key=profile)) |
436 entry_d.addErrback(lambda failure: error("Modification of %s failed: %s" % (pub_data, failure.getErrorMessage()))) | 450 entry_d.addErrback(lambda failure: error("Modification of %s failed: %s" % (pub_data, failure.getErrorMessage()))) |
437 return entry_d | 451 return entry_d |
438 | 452 |
439 return self._initialise(profile_key).addCallback(initialised) | 453 return self._initialise(profile_key).addCallback(initialised) |
440 | 454 |
472 @return: deferred which fire list of group blog data """ | 486 @return: deferred which fire list of group blog data """ |
473 # TODO: use items data when pub_jid is None | 487 # TODO: use items data when pub_jid is None |
474 ret = [] | 488 ret = [] |
475 for item in items: | 489 for item in items: |
476 gbdata = yield self.item2gbdata(item) | 490 gbdata = yield self.item2gbdata(item) |
491 try: | |
492 gbdata['service'] = client.item_access_pubsub.full() | |
493 except AttributeError: | |
494 pass | |
477 ret.append(gbdata) | 495 ret.append(gbdata) |
478 # if there is a comments node, we subscribe to it | 496 # if there is a comments node, we subscribe to it |
479 if "comments_node" in gbdata: | 497 if "comments_node" in gbdata: |
480 try: | 498 try: |
481 # every comments node must be subscribed, except if we are the publisher (we are already subscribed in this case) | 499 # every comments node must be subscribed, except if we are the publisher (we are already subscribed in this case) |