Mercurial > libervia-backend
comparison src/plugins/plugin_misc_groupblog.py @ 594:e629371a28d3
Fix pep8 support in src/plugins.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Fri, 18 Jan 2013 17:55:35 +0100 |
parents | beaf6bec2fcd |
children | 84a6e83157c2 |
comparison
equal
deleted
inserted
replaced
593:70bae685d05c | 594:e629371a28d3 |
---|---|
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_NODE_PREFIX = 'urn:xmpp:groupblog:' |
38 #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 |
39 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 |
40 NS_PUBSUB_ITEM_ACCESS = NS_PUBSUB_EXP + "#item-access" | 40 NS_PUBSUB_ITEM_ACCESS = NS_PUBSUB_EXP + "#item-access" |
41 NS_PUBSUB_CREATOR_JID_CHECK = NS_PUBSUB_EXP + "#creator-jid-check" | 41 NS_PUBSUB_CREATOR_JID_CHECK = NS_PUBSUB_EXP + "#creator-jid-check" |
42 NS_PUBSUB_ITEM_CONFIG = NS_PUBSUB_EXP + "#item-config" | 42 NS_PUBSUB_ITEM_CONFIG = NS_PUBSUB_EXP + "#item-config" |
43 NS_PUBSUB_AUTO_CREATE = NS_PUBSUB + "#auto-create" | 43 NS_PUBSUB_AUTO_CREATE = NS_PUBSUB + "#auto-create" |
44 OPT_ROSTER_GROUPS_ALLOWED = 'pubsub#roster_groups_allowed' | 44 OPT_ROSTER_GROUPS_ALLOWED = 'pubsub#roster_groups_allowed' |
49 OPT_SUBSCRIPTION_TYPE = 'pubsub#subscription_type' | 49 OPT_SUBSCRIPTION_TYPE = 'pubsub#subscription_type' |
50 OPT_SUBSCRIPTION_DEPTH = 'pubsub#subscription_depth' | 50 OPT_SUBSCRIPTION_DEPTH = 'pubsub#subscription_depth' |
51 TYPE_COLLECTION = 'collection' | 51 TYPE_COLLECTION = 'collection' |
52 | 52 |
53 PLUGIN_INFO = { | 53 PLUGIN_INFO = { |
54 "name": "Group blogging throught collections", | 54 "name": "Group blogging throught collections", |
55 "import_name": "groupblog", | 55 "import_name": "groupblog", |
56 "type": "MISC", | 56 "type": "MISC", |
57 "protocols": [], | 57 "protocols": [], |
58 "dependencies": ["XEP-0277"], | 58 "dependencies": ["XEP-0277"], |
59 "main": "GroupBlog", | 59 "main": "GroupBlog", |
60 "handler": "yes", | 60 "handler": "yes", |
61 "description": _("""Implementation of microblogging with roster access""") | 61 "description": _("""Implementation of microblogging with roster access""") |
62 } | 62 } |
63 | |
63 | 64 |
64 class NoCompatiblePubSubServerFound(Exception): | 65 class NoCompatiblePubSubServerFound(Exception): |
65 pass | 66 pass |
66 | 67 |
68 | |
67 class BadAccessTypeError(Exception): | 69 class BadAccessTypeError(Exception): |
68 pass | 70 pass |
69 | 71 |
72 | |
70 class BadAccessListError(Exception): | 73 class BadAccessListError(Exception): |
71 pass | 74 pass |
72 | 75 |
76 | |
73 class UnknownType(Exception): | 77 class UnknownType(Exception): |
74 pass | 78 pass |
79 | |
75 | 80 |
76 class GroupBlog(object): | 81 class GroupBlog(object): |
77 """This class use a SàT PubSub Service to manage access on microblog""" | 82 """This class use a SàT PubSub Service to manage access on microblog""" |
78 | 83 |
79 def __init__(self, host): | 84 def __init__(self, host): |
80 info(_("Group blog plugin initialization")) | 85 info(_("Group blog plugin initialization")) |
81 self.host = host | 86 self.host = host |
82 | 87 |
83 host.bridge.addMethod("sendGroupBlog", ".plugin", in_sign='sasss', out_sign='', | 88 host.bridge.addMethod("sendGroupBlog", ".plugin", in_sign='sasss', out_sign='', |
84 method=self.sendGroupBlog) | 89 method=self.sendGroupBlog) |
85 | 90 |
86 host.bridge.addMethod("getLastGroupBlogs", ".plugin", | 91 host.bridge.addMethod("getLastGroupBlogs", ".plugin", |
87 in_sign='sis', out_sign='aa{ss}', | 92 in_sign='sis', out_sign='aa{ss}', |
88 method=self.getLastGroupBlogs, | 93 method=self.getLastGroupBlogs, |
89 async = True) | 94 async=True) |
90 | 95 |
91 host.bridge.addMethod("getMassiveLastGroupBlogs", ".plugin", | 96 host.bridge.addMethod("getMassiveLastGroupBlogs", ".plugin", |
92 in_sign='sasis', out_sign='a{saa{ss}}', | 97 in_sign='sasis', out_sign='a{saa{ss}}', |
93 method=self.getMassiveLastGroupBlogs, | 98 method=self.getMassiveLastGroupBlogs, |
94 async = True) | 99 async=True) |
95 | 100 |
96 host.bridge.addMethod("subscribeGroupBlog", ".plugin", in_sign='ss', out_sign='', | 101 host.bridge.addMethod("subscribeGroupBlog", ".plugin", in_sign='ss', out_sign='', |
97 method=self.subscribeGroupBlog, | 102 method=self.subscribeGroupBlog, |
98 async = True) | 103 async=True) |
99 | 104 |
100 host.bridge.addMethod("massiveSubscribeGroupBlogs", ".plugin", in_sign='sass', out_sign='', | 105 host.bridge.addMethod("massiveSubscribeGroupBlogs", ".plugin", in_sign='sass', out_sign='', |
101 method=self.massiveSubscribeGroupBlogs, | 106 method=self.massiveSubscribeGroupBlogs, |
102 async = True) | 107 async=True) |
103 | 108 |
104 host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger) | 109 host.trigger.add("PubSubItemsReceived", self.pubSubItemsReceivedTrigger) |
105 | |
106 | 110 |
107 def getHandler(self, profile): | 111 def getHandler(self, profile): |
108 return GroupBlog_handler() | 112 return GroupBlog_handler() |
109 | 113 |
110 @defer.inlineCallbacks | 114 @defer.inlineCallbacks |
119 | 123 |
120 client = self.host.getClient(profile) | 124 client = self.host.getClient(profile) |
121 if not client: | 125 if not client: |
122 error(_('No client for this profile key: %s') % profile_key) | 126 error(_('No client for this profile key: %s') % profile_key) |
123 raise Exception("Unknown profile") | 127 raise Exception("Unknown profile") |
124 yield client.client_initialized #we want to be sure that the client is initialized | 128 yield client.client_initialized # we want to be sure that the client is initialized |
125 | 129 |
126 #we first check that we have a item-access pubsub server | 130 #we first check that we have a item-access pubsub server |
127 if not hasattr(client,"item_access_pubsub"): | 131 if not hasattr(client, "item_access_pubsub"): |
128 debug(_('Looking for item-access power pubsub server')) | 132 debug(_('Looking for item-access power pubsub server')) |
129 #we don't have any pubsub server featuring item access yet | 133 #we don't have any pubsub server featuring item access yet |
130 client.item_access_pubsub = None | 134 client.item_access_pubsub = None |
131 client._item_access_pubsub_pending = defer.Deferred() | 135 client._item_access_pubsub_pending = defer.Deferred() |
132 for entity in self.host.memory.getServerServiceEntities("pubsub", "service", profile): | 136 for entity in self.host.memory.getServerServiceEntities("pubsub", "service", profile): |
135 if set([NS_PUBSUB_AUTO_CREATE, NS_PUBSUB_CREATOR_JID_CHECK]).issubset(_disco.features): | 139 if set([NS_PUBSUB_AUTO_CREATE, NS_PUBSUB_CREATOR_JID_CHECK]).issubset(_disco.features): |
136 info(_("item-access powered pubsub service found: [%s]") % entity.full()) | 140 info(_("item-access powered pubsub service found: [%s]") % entity.full()) |
137 client.item_access_pubsub = entity | 141 client.item_access_pubsub = entity |
138 client._item_access_pubsub_pending.callback(None) | 142 client._item_access_pubsub_pending.callback(None) |
139 | 143 |
140 if hasattr(client,"_item_access_pubsub_pending"): | 144 if hasattr(client, "_item_access_pubsub_pending"): |
141 #XXX: we need to wait for item access pubsub service check | 145 #XXX: we need to wait for item access pubsub service check |
142 yield client._item_access_pubsub_pending | 146 yield client._item_access_pubsub_pending |
143 del client._item_access_pubsub_pending | 147 del client._item_access_pubsub_pending |
144 | 148 |
145 if not client.item_access_pubsub: | 149 if not client.item_access_pubsub: |
155 origin_host = publisher.host.split('.') | 159 origin_host = publisher.host.split('.') |
156 event_host = event.sender.host.split('.') | 160 event_host = event.sender.host.split('.') |
157 #FIXME: basic origin check, must be improved | 161 #FIXME: basic origin check, must be improved |
158 #TODO: automatic security test | 162 #TODO: automatic security test |
159 if (not (origin_host) | 163 if (not (origin_host) |
160 or len(event_host) < len(origin_host) | 164 or len(event_host) < len(origin_host) |
161 or event_host[-len(origin_host):] != origin_host): | 165 or event_host[-len(origin_host):] != origin_host): |
162 warning("Host incoherence between %s and %s (hack attempt ?)" % (unicode(event.sender), | 166 warning("Host incoherence between %s and %s (hack attempt ?)" % (unicode(event.sender), |
163 unicode(publisher))) | 167 unicode(publisher))) |
164 return | 168 return |
165 for item in event.items: | 169 for item in event.items: |
166 microblog_data = self.item2gbdata(item) | 170 microblog_data = self.item2gbdata(item) |
167 | 171 |
168 self.host.bridge.personalEvent(publisher.full(), "MICROBLOG", microblog_data, profile) | 172 self.host.bridge.personalEvent(publisher.full(), "MICROBLOG", microblog_data, profile) |
169 return False | 173 return False |
170 return True | 174 return True |
171 | |
172 | 175 |
173 def _parseAccessData(self, microblog_data, item): | 176 def _parseAccessData(self, microblog_data, item): |
174 form_elts = filter(lambda elt: elt.name == "x", item.children) | 177 form_elts = filter(lambda elt: elt.name == "x", item.children) |
175 for form_elt in form_elts: | 178 for form_elt in form_elts: |
176 form = data_form.Form.fromElement(form_elt) | 179 form = data_form.Form.fromElement(form_elt) |
190 """ Convert item to microblog data dictionary + add access data """ | 193 """ Convert item to microblog data dictionary + add access data """ |
191 microblog_data = self.host.plugins["XEP-0277"].item2mbdata(item) | 194 microblog_data = self.host.plugins["XEP-0277"].item2mbdata(item) |
192 self._parseAccessData(microblog_data, item) | 195 self._parseAccessData(microblog_data, item) |
193 return microblog_data | 196 return microblog_data |
194 | 197 |
195 | |
196 def getNodeName(self, publisher): | 198 def getNodeName(self, publisher): |
197 """Retrieve the name of publisher's node | 199 """Retrieve the name of publisher's node |
198 @param publisher: publisher's jid | 200 @param publisher: publisher's jid |
199 @return: node's name (string)""" | 201 @return: node's name (string)""" |
200 return NS_NODE_PREFIX + publisher.userhost() | 202 return NS_NODE_PREFIX + publisher.userhost() |
201 | |
202 | |
203 | 203 |
204 def _publishMblog(self, service, client, access_type, access_list, message): | 204 def _publishMblog(self, service, client, access_type, access_list, message): |
205 """Actually publish the message on the group blog | 205 """Actually publish the message on the group blog |
206 @param service: jid of the item-access pubsub service | 206 @param service: jid of the item-access pubsub service |
207 @param client: SatXMPPClient of the published | 207 @param client: SatXMPPClient of the published |
208 @param access_type: one of "PUBLIC", "GROUP", "JID" | 208 @param access_type: one of "PUBLIC", "GROUP", "JID" |
209 @param access_list: set of entities (empty list for all, groups or jids) allowed to see the item | 209 @param access_list: set of entities (empty list for all, groups or jids) allowed to see the item |
210 @param message: message to publish | 210 @param message: message to publish |
211 """ | 211 """ |
212 mblog_item = self.host.plugins["XEP-0277"].data2entry({'content':message}, client.profile) | 212 mblog_item = self.host.plugins["XEP-0277"].data2entry({'content': message}, client.profile) |
213 form = data_form.Form('submit', formNamespace=NS_PUBSUB_ITEM_CONFIG) | 213 form = data_form.Form('submit', formNamespace=NS_PUBSUB_ITEM_CONFIG) |
214 if access_type == "PUBLIC": | 214 if access_type == "PUBLIC": |
215 if access_list: | 215 if access_list: |
216 raise BadAccessListError("access_list must be empty for PUBLIC access") | 216 raise BadAccessListError("access_list must be empty for PUBLIC access") |
217 access = data_form.Field(None, OPT_ACCESS_MODEL, value="open") | 217 access = data_form.Field(None, OPT_ACCESS_MODEL, value="open") |
241 list of groups or list of jids) for this item | 241 list of groups or list of jids) for this item |
242 @param message: microblog | 242 @param message: microblog |
243 @profile_key: %(doc_profile)s | 243 @profile_key: %(doc_profile)s |
244 """ | 244 """ |
245 print "sendGroupBlog" | 245 print "sendGroupBlog" |
246 | |
246 def initialised(result): | 247 def initialised(result): |
247 profile, client = result | 248 profile, client = result |
248 if access_type == "PUBLIC": | 249 if access_type == "PUBLIC": |
249 if access_list: | 250 if access_list: |
250 raise Exception("Publishers list must be empty when getting microblogs for all contacts") | 251 raise Exception("Publishers list must be empty when getting microblogs for all contacts") |
251 self._publishMblog(client.item_access_pubsub, client, "PUBLIC", [], message) | 252 self._publishMblog(client.item_access_pubsub, client, "PUBLIC", [], message) |
252 elif access_type == "GROUP": | 253 elif access_type == "GROUP": |
253 _groups = set(access_list).intersection(client.roster.getGroups()) #We only keep group which actually exist | 254 _groups = set(access_list).intersection(client.roster.getGroups()) # We only keep group which actually exist |
254 if not _groups: | 255 if not _groups: |
255 raise BadAccessListError("No valid group") | 256 raise BadAccessListError("No valid group") |
256 self._publishMblog(client.item_access_pubsub, client, "GROUP", _groups, message) | 257 self._publishMblog(client.item_access_pubsub, client, "GROUP", _groups, message) |
257 elif access_type == "JID": | 258 elif access_type == "JID": |
258 raise NotImplementedError | 259 raise NotImplementedError |
260 error(_("Unknown access type")) | 261 error(_("Unknown access type")) |
261 raise BadAccessTypeError | 262 raise BadAccessTypeError |
262 | 263 |
263 self.initialise(profile_key).addCallback(initialised) | 264 self.initialise(profile_key).addCallback(initialised) |
264 | 265 |
265 | |
266 | |
267 def getLastGroupBlogs(self, pub_jid, max_items=10, profile_key='@DEFAULT@'): | 266 def getLastGroupBlogs(self, pub_jid, max_items=10, profile_key='@DEFAULT@'): |
268 """Get the last published microblogs | 267 """Get the last published microblogs |
269 @param pub_jid: jid of the publisher | 268 @param pub_jid: jid of the publisher |
270 @param max_items: how many microblogs we want to get (see XEP-0060 #6.5.7) | 269 @param max_items: how many microblogs we want to get (see XEP-0060 #6.5.7) |
271 @param profile_key: profile key | 270 @param profile_key: profile key |
275 def initialised(result): | 274 def initialised(result): |
276 profile, client = result | 275 profile, client = result |
277 d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)), | 276 d = self.host.plugins["XEP-0060"].getItems(client.item_access_pubsub, self.getNodeName(jid.JID(pub_jid)), |
278 max_items=max_items, profile_key=profile_key) | 277 max_items=max_items, profile_key=profile_key) |
279 d.addCallback(lambda items: map(self.item2gbdata, items)) | 278 d.addCallback(lambda items: map(self.item2gbdata, items)) |
280 d.addErrback(lambda ignore: {}) #TODO: more complete error management (log !) | 279 d.addErrback(lambda ignore: {}) # TODO: more complete error management (log !) |
281 return d | 280 return d |
282 | 281 |
283 #TODO: we need to use the server corresponding the the host of the jid | 282 #TODO: we need to use the server corresponding the the host of the jid |
284 return self.initialise(profile_key).addCallback(initialised) | 283 return self.initialise(profile_key).addCallback(initialised) |
285 | 284 |
288 @param publishers_type: type of the list of publishers (one of "GROUP" or "JID" or "ALL") | 287 @param publishers_type: type of the list of publishers (one of "GROUP" or "JID" or "ALL") |
289 @param publishers: list of publishers, according to "publishers_type" (list of groups or list of jids) | 288 @param publishers: list of publishers, according to "publishers_type" (list of groups or list of jids) |
290 @param max_items: how many microblogs we want to get | 289 @param max_items: how many microblogs we want to get |
291 @param profile_key: profile key | 290 @param profile_key: profile key |
292 """ | 291 """ |
292 | |
293 def sendResult(result): | 293 def sendResult(result): |
294 """send result of DeferredList (list of microblogs to the calling method""" | 294 """send result of DeferredList (list of microblogs to the calling method""" |
295 | 295 |
296 ret = {} | 296 ret = {} |
297 | 297 |
327 dlist = defer.DeferredList(mblogs) | 327 dlist = defer.DeferredList(mblogs) |
328 dlist.addCallback(sendResult) | 328 dlist.addCallback(sendResult) |
329 | 329 |
330 return dlist | 330 return dlist |
331 | 331 |
332 | |
333 #TODO: custom exception | 332 #TODO: custom exception |
334 if publishers_type not in ["GROUP", "JID", "ALL"]: | 333 if publishers_type not in ["GROUP", "JID", "ALL"]: |
335 raise Exception("Bad call, unknown publishers_type") | 334 raise Exception("Bad call, unknown publishers_type") |
336 if publishers_type=="ALL" and publishers: | 335 if publishers_type == "ALL" and publishers: |
337 raise Exception("Publishers list must be empty when getting microblogs for all contacts") | 336 raise Exception("Publishers list must be empty when getting microblogs for all contacts") |
338 return self.initialise(profile_key).addCallback(initialised) | 337 return self.initialise(profile_key).addCallback(initialised) |
339 #TODO: we need to use the server corresponding the the host of the jid | 338 #TODO: we need to use the server corresponding the the host of the jid |
340 | 339 |
341 def subscribeGroupBlog(self, pub_jid, profile_key='@DEFAULT'): | 340 def subscribeGroupBlog(self, pub_jid, profile_key='@DEFAULT'): |
345 profile_key=profile_key) | 344 profile_key=profile_key) |
346 return d | 345 return d |
347 | 346 |
348 #TODO: we need to use the server corresponding the the host of the jid | 347 #TODO: we need to use the server corresponding the the host of the jid |
349 return self.initialise(profile_key).addCallback(initialised) | 348 return self.initialise(profile_key).addCallback(initialised) |
350 | |
351 | 349 |
352 def massiveSubscribeGroupBlogs(self, publishers_type, publishers, profile_key='@DEFAULT@'): | 350 def massiveSubscribeGroupBlogs(self, publishers_type, publishers, profile_key='@DEFAULT@'): |
353 """Subscribe microblogs for a list of groups or jids | 351 """Subscribe microblogs for a list of groups or jids |
354 @param publishers_type: type of the list of publishers (one of "GROUP" or "JID" or "ALL") | 352 @param publishers_type: type of the list of publishers (one of "GROUP" or "JID" or "ALL") |
355 @param publishers: list of publishers, according to "publishers_type" (list of groups or list of jids) | 353 @param publishers: list of publishers, according to "publishers_type" (list of groups or list of jids) |
356 @param profile_key: profile key | 354 @param profile_key: profile key |
357 """ | 355 """ |
356 | |
358 def initialised(result): | 357 def initialised(result): |
359 profile, client = result | 358 profile, client = result |
360 | 359 |
361 if publishers_type == "ALL": | 360 if publishers_type == "ALL": |
362 contacts = client.roster.getItems() | 361 contacts = client.roster.getItems() |
376 profile_key=profile_key) | 375 profile_key=profile_key) |
377 mblogs.append(d) | 376 mblogs.append(d) |
378 dlist = defer.DeferredList(mblogs) | 377 dlist = defer.DeferredList(mblogs) |
379 return dlist | 378 return dlist |
380 | 379 |
381 | |
382 #TODO: custom exception | 380 #TODO: custom exception |
383 if publishers_type not in ["GROUP", "JID", "ALL"]: | 381 if publishers_type not in ["GROUP", "JID", "ALL"]: |
384 raise Exception("Bad call, unknown publishers_type") | 382 raise Exception("Bad call, unknown publishers_type") |
385 if publishers_type=="ALL" and publishers: | 383 if publishers_type == "ALL" and publishers: |
386 raise Exception("Publishers list must be empty when getting microblogs for all contacts") | 384 raise Exception("Publishers list must be empty when getting microblogs for all contacts") |
387 return self.initialise(profile_key).addCallback(initialised) | 385 return self.initialise(profile_key).addCallback(initialised) |
388 #TODO: we need to use the server corresponding the the host of the jid | 386 #TODO: we need to use the server corresponding the the host of the jid |
389 | 387 |
390 | 388 |
391 | |
392 class GroupBlog_handler(XMPPHandler): | 389 class GroupBlog_handler(XMPPHandler): |
393 implements(iwokkel.IDisco) | 390 implements(iwokkel.IDisco) |
394 | 391 |
395 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): | 392 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): |
396 return [disco.DiscoFeature(NS_GROUPBLOG)] | 393 return [disco.DiscoFeature(NS_GROUPBLOG)] |
397 | 394 |
398 def getDiscoItems(self, requestor, target, nodeIdentifier=''): | 395 def getDiscoItems(self, requestor, target, nodeIdentifier=''): |
399 return [] | 396 return [] |
400 |