comparison src/plugins/plugin_misc_groupblog.py @ 938:fc7e0828b18e

plugin account, groupblog: user can erase all their microblogs at once
author souliane <souliane@mailoo.org>
date Thu, 27 Mar 2014 02:24:20 +0100
parents 1a759096ccbd
children c6d8fc63b1db
comparison
equal deleted inserted replaced
937:255e6953b2c3 938:fc7e0828b18e
20 from sat.core.i18n import _ 20 from sat.core.i18n import _
21 from sat.core.constants import Const as C 21 from sat.core.constants import Const as C
22 from logging import debug, info, warning, error 22 from logging import debug, info, warning, error
23 from twisted.internet import defer 23 from twisted.internet import defer
24 from twisted.words.protocols.jabber import jid 24 from twisted.words.protocols.jabber import jid
25 from twisted.words.xish.domish import Element 25 from twisted.words.xish.domish import Element, generateElementsNamed
26 from sat.core import exceptions 26 from sat.core import exceptions
27 from wokkel import disco, data_form, iwokkel 27 from wokkel import disco, data_form, iwokkel
28 from zope.interface import implements 28 from zope.interface import implements
29 from feed import date 29 from feed import date
30 import uuid 30 import uuid
51 'JID': None, #JID is not yet managed 51 'JID': None, #JID is not yet managed
52 } 52 }
53 53
54 PLUGIN_INFO = { 54 PLUGIN_INFO = {
55 "name": "Group blogging throught collections", 55 "name": "Group blogging throught collections",
56 "import_name": "groupblog", 56 "import_name": "GROUPBLOG",
57 "type": "MISC", 57 "type": "MISC",
58 "protocols": [], 58 "protocols": [],
59 "dependencies": ["XEP-0277"], 59 "dependencies": ["XEP-0277"],
60 "main": "GroupBlog", 60 "main": "GroupBlog",
61 "handler": "yes", 61 "handler": "yes",
413 return d 413 return d
414 414
415 def notify(d): 415 def notify(d):
416 # TODO: this works only on the same host, and notifications for item deletion should be 416 # TODO: this works only on the same host, and notifications for item deletion should be
417 # implemented according to http://xmpp.org/extensions/xep-0060.html#publisher-delete-success-notify 417 # implemented according to http://xmpp.org/extensions/xep-0060.html#publisher-delete-success-notify
418 # instead. The notification mechanisms implemented in sat_pubsub and wokkel seem not compatible, 418 # instead. The notification mechanism implemented in sat_pubsub and wokkel have apriori
419 # see wokkel.pubsub.PubSubClient._onEvent_items and sat_pubsub.backend._doNotifyRetraction 419 # a problem with retrieving the subscriptions, or something else.
420 service, node, item_id = pub_data 420 service, node, item_id = pub_data
421 publisher = self.host.getJidNStream(profile_key)[0] 421 publisher = self.host.getJidNStream(profile_key)[0]
422 profile = self.host.memory.getProfileName(profile_key) 422 profile = self.host.memory.getProfileName(profile_key)
423 gbdatum = {'id': item_id, 'type': 'main_item' if (comments or not node) else 'comment'} 423 gbdatum = {'id': item_id, 'type': 'main_item' if (comments or not node) else 'comment'}
424 self.host.bridge.personalEvent(publisher.full(), "MICROBLOG_DELETE", gbdatum, profile) 424 self.host.bridge.personalEvent(publisher.full(), "MICROBLOG_DELETE", gbdatum, profile)
570 570
571 d = self.__getGroupBlogs(pub_jid_s, item_ids=item_ids, profile_key=profile_key) 571 d = self.__getGroupBlogs(pub_jid_s, item_ids=item_ids, profile_key=profile_key)
572 d.addCallback(get_comments) 572 d.addCallback(get_comments)
573 return d 573 return d
574 574
575
576 def getLastGroupBlogs(self, pub_jid_s, max_items=10, profile_key=C.PROF_KEY_NONE): 575 def getLastGroupBlogs(self, pub_jid_s, max_items=10, profile_key=C.PROF_KEY_NONE):
577 """Get the last published microblogs 576 """Get the last published microblogs
578 @param pub_jid_s: jid of the publisher 577 @param pub_jid_s: jid of the publisher
579 @param max_items: how many microblogs we want to get (see XEP-0060 #6.5.7) 578 @param max_items: how many microblogs we want to get (see XEP-0060 #6.5.7)
580 @param profile_key: profile key 579 @param profile_key: profile key
663 @param max_items: how many microblogs we want to get 662 @param max_items: how many microblogs we want to get
664 @param profile_key: profile key 663 @param profile_key: profile key
665 """ 664 """
666 665
667 def sendResult(result): 666 def sendResult(result):
668 """send result of DeferredList (list of microblogs to the calling method""" 667 """send result of DeferredList (dict of jid => microblogs) to the calling method"""
669 668
670 ret = {} 669 ret = {}
671 670
672 for (success, value) in result: 671 for (success, value) in result:
673 if success: 672 if success:
691 else: 690 else:
692 raise UnknownType 691 raise UnknownType
693 692
694 mblogs = [] 693 mblogs = []
695 694
696
697 for jid_ in jids: 695 for jid_ in jids:
698 d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid_), 696 d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid_),
699 max_items=max_items, profile_key=profile_key) 697 max_items=max_items, profile_key=profile_key)
700 d.addCallback(self._itemsConstruction, jid_, client) 698 d.addCallback(self._itemsConstruction, jid_, client)
701 d.addCallback(lambda gbdata, source_jid: (source_jid, gbdata), jid_.full()) 699 d.addCallback(lambda gbdata, source_jid: (source_jid, gbdata), jid_.full())
771 if publishers_type == "ALL" and publishers: 769 if publishers_type == "ALL" and publishers:
772 raise Exception("Publishers list must be empty when getting microblogs for all contacts") 770 raise Exception("Publishers list must be empty when getting microblogs for all contacts")
773 return self._initialise(profile_key).addCallback(initialised) 771 return self._initialise(profile_key).addCallback(initialised)
774 #TODO: we need to use the server corresponding the the host of the jid 772 #TODO: we need to use the server corresponding the the host of the jid
775 773
774 def deleteAllGroupBlogsAndComments(self, profile_key=C.PROF_KEY_NONE):
775 """Delete absolutely all the microblog data that the user has posted"""
776 calls = [self.deleteAllGroupBlogs(profile_key), self.deleteAllGroupBlogsComments(profile_key)]
777 return defer.DeferredList(calls)
778
779 def deleteAllGroupBlogs(self, profile_key=C.PROF_KEY_NONE):
780 """Delete all the main items and their comments that the user has posted
781 """
782 def initialised(result):
783 profile, client = result
784 service = client.item_access_pubsub
785 jid_ = client.jid
786
787 main_node = self.getNodeName(jid_)
788 d = self.host.plugins["XEP-0060"].deleteNode(service, main_node, profile_key=profile)
789 d.addCallback(lambda dummy: info(_("All microblog's main items from %s have been deleted!") % jid_.userhost()))
790 d.addErrback(lambda failure: error(_("Deletion of node %(node)s failed: %(message)s") %
791 {'node': main_node, 'message': failure.getErrorMessage()}))
792 return d
793
794 return self._initialise(profile_key).addCallback(initialised)
795
796 def deleteAllGroupBlogsComments(self, profile_key=C.PROF_KEY_NONE):
797 """Delete all the comments that the user posted on other's main items.
798 We avoid the conversions from item to microblog data as we only need
799 to retrieve some attributes, no need to convert text syntax...
800 """
801 def initialised(result):
802 """Get all the main items from our contact list
803 @return: a DeferredList
804 """
805 profile, client = result
806 service = client.item_access_pubsub
807 jids = [contact.jid.userhostJID() for contact in client.roster.getItems()]
808 blogs = []
809 for jid_ in jids:
810 main_node = self.getNodeName(jid_)
811 d = self.host.plugins["XEP-0060"].getItems(service, main_node, profile_key=profile)
812 d.addCallback(getComments, client)
813 d.addErrback(lambda failure, main_node: error(_("Retrieval of items for node %(node)s failed: %(message)s") %
814 {'node': main_node, 'message': failure.getErrorMessage()}), main_node)
815 blogs.append(d)
816
817 return defer.DeferredList(blogs)
818
819 def getComments(items, client):
820 """Get all the comments for a list of items
821 @param items: a list of main items for one user
822 @param client: the client of the user
823 @return: a DeferredList
824 """
825 comments = []
826 for item in items:
827 try:
828 entry = generateElementsNamed(item.elements(), 'entry').next()
829 link = generateElementsNamed(entry.elements(), 'link').next()
830 except StopIteration:
831 continue
832 href = link.getAttribute('href')
833 service, node = self.host.plugins['XEP-0277'].parseCommentUrl(href)
834 d = self.host.plugins["XEP-0060"].getItems(service, node, profile_key=profile_key)
835 d.addCallback(lambda items, service, node: (service, node, items), service, node)
836 d.addErrback(lambda failure, node: error(_("Retrieval of comments for node %(node)s failed: %(message)s") %
837 {'node': node, 'message': failure.getErrorMessage()}), node)
838 comments.append(d)
839 dlist = defer.DeferredList(comments)
840 dlist.addCallback(deleteComments, client)
841 return dlist
842
843 def deleteComments(result, client):
844 """Delete all the comments of the user that are found in result
845 @param result: a list of couple (success, value) with success a
846 boolean and value a tuple (service as JID, node_id, comment_items)
847 @param client: the client of the user
848 @return: a DeferredList with the deletions result
849 """
850 user_jid_s = client.jid.userhost()
851 for (success, value) in result:
852 if not success:
853 continue
854 service, node_id, comment_items = value
855 item_ids = []
856 for comment_item in comment_items: # for all the comments on one post
857 try:
858 entry = generateElementsNamed(comment_item.elements(), 'entry').next()
859 author = generateElementsNamed(entry.elements(), 'author').next()
860 name = generateElementsNamed(author.elements(), 'name').next()
861 except StopIteration:
862 continue
863 if name.children[0] == user_jid_s:
864 item_ids.append(comment_item.getAttribute('id'))
865 deletions = []
866 if item_ids: # remove the comments of the user on the given post
867 d = self.host.plugins['XEP-0060'].retractItems(service, node_id, item_ids, profile_key=profile_key)
868 d.addCallback(lambda dummy, node_id: debug(_('Comments of user %(user)s in node %(node)s have been retracted') %
869 {'user': user_jid_s, 'node': node_id}), node_id)
870 d.addErrback(lambda failure, node_id: error(_("Retraction of comments from %(user)s in node %(node)s failed: %(message)s") %
871 {'user': user_jid_s, 'node': node_id, 'message': failure.getErrorMessage()}), node_id)
872 deletions.append(d)
873 return defer.DeferredList(deletions)
874
875 return self._initialise(profile_key).addCallback(initialised)
876
776 877
777 class GroupBlog_handler(XMPPHandler): 878 class GroupBlog_handler(XMPPHandler):
778 implements(iwokkel.IDisco) 879 implements(iwokkel.IDisco)
779 880
780 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): 881 def getDiscoInfo(self, requestor, target, nodeIdentifier=''):