comparison sat/plugins/plugin_exp_events.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 1cc88adb5142
children 378188abe941
comparison
equal deleted inserted replaced
2623:49533de4540b 2624:56f94936df1e
19 19
20 from sat.core.i18n import _ 20 from sat.core.i18n import _
21 from sat.core import exceptions 21 from sat.core import exceptions
22 from sat.core.constants import Const as C 22 from sat.core.constants import Const as C
23 from sat.core.log import getLogger 23 from sat.core.log import getLogger
24
24 log = getLogger(__name__) 25 log = getLogger(__name__)
25 from sat.tools import utils 26 from sat.tools import utils
26 from sat.tools.common import uri as xmpp_uri 27 from sat.tools.common import uri as xmpp_uri
27 from sat.tools.common import date_utils 28 from sat.tools.common import date_utils
28 from twisted.internet import defer 29 from twisted.internet import defer
43 C.PI_PROTOCOLS: [], 44 C.PI_PROTOCOLS: [],
44 C.PI_DEPENDENCIES: ["XEP-0060"], 45 C.PI_DEPENDENCIES: ["XEP-0060"],
45 C.PI_RECOMMENDATIONS: ["INVITATIONS", "XEP-0277"], 46 C.PI_RECOMMENDATIONS: ["INVITATIONS", "XEP-0277"],
46 C.PI_MAIN: "Events", 47 C.PI_MAIN: "Events",
47 C.PI_HANDLER: "yes", 48 C.PI_HANDLER: "yes",
48 C.PI_DESCRIPTION: _("""Experimental implementation of XMPP events management""") 49 C.PI_DESCRIPTION: _("""Experimental implementation of XMPP events management"""),
49 } 50 }
50 51
51 NS_EVENT = 'org.salut-a-toi.event:0' 52 NS_EVENT = "org.salut-a-toi.event:0"
52 NS_EVENT_LIST = NS_EVENT + '#list' 53 NS_EVENT_LIST = NS_EVENT + "#list"
53 NS_EVENT_INVIT = NS_EVENT + '#invitation' 54 NS_EVENT_INVIT = NS_EVENT + "#invitation"
54 INVITATION = '/message[@type="chat"]/invitation[@xmlns="{ns_invit}"]'.format( 55 INVITATION = '/message[@type="chat"]/invitation[@xmlns="{ns_invit}"]'.format(
55 ns_invit=NS_EVENT_INVIT) 56 ns_invit=NS_EVENT_INVIT
57 )
56 58
57 59
58 class Events(object): 60 class Events(object):
59 """Q&D module to handle event attendance answer, experimentation only""" 61 """Q&D module to handle event attendance answer, experimentation only"""
60 62
62 log.info(_(u"Event plugin initialization")) 64 log.info(_(u"Event plugin initialization"))
63 self.host = host 65 self.host = host
64 self._p = self.host.plugins["XEP-0060"] 66 self._p = self.host.plugins["XEP-0060"]
65 self._i = self.host.plugins.get("INVITATIONS") 67 self._i = self.host.plugins.get("INVITATIONS")
66 self._b = self.host.plugins.get("XEP-0277") 68 self._b = self.host.plugins.get("XEP-0277")
67 host.bridge.addMethod("eventGet", ".plugin", 69 host.bridge.addMethod(
68 in_sign='ssss', out_sign='(ia{ss})', 70 "eventGet",
69 method=self._eventGet, 71 ".plugin",
70 async=True) 72 in_sign="ssss",
71 host.bridge.addMethod("eventCreate", ".plugin", 73 out_sign="(ia{ss})",
72 in_sign='ia{ss}ssss', out_sign='s', 74 method=self._eventGet,
73 method=self._eventCreate, 75 async=True,
74 async=True) 76 )
75 host.bridge.addMethod("eventModify", ".plugin", 77 host.bridge.addMethod(
76 in_sign='sssia{ss}s', out_sign='', 78 "eventCreate",
77 method=self._eventModify, 79 ".plugin",
78 async=True) 80 in_sign="ia{ss}ssss",
79 host.bridge.addMethod("eventsList", ".plugin", 81 out_sign="s",
80 in_sign='sss', out_sign='aa{ss}', 82 method=self._eventCreate,
81 method=self._eventsList, 83 async=True,
82 async=True) 84 )
83 host.bridge.addMethod("eventInviteeGet", ".plugin", 85 host.bridge.addMethod(
84 in_sign='sss', out_sign='a{ss}', 86 "eventModify",
85 method=self._eventInviteeGet, 87 ".plugin",
86 async=True) 88 in_sign="sssia{ss}s",
87 host.bridge.addMethod("eventInviteeSet", ".plugin", 89 out_sign="",
88 in_sign='ssa{ss}s', out_sign='', 90 method=self._eventModify,
89 method=self._eventInviteeSet, 91 async=True,
90 async=True) 92 )
91 host.bridge.addMethod("eventInviteesList", ".plugin", 93 host.bridge.addMethod(
92 in_sign='sss', out_sign='a{sa{ss}}', 94 "eventsList",
93 method=self._eventInviteesList, 95 ".plugin",
94 async=True), 96 in_sign="sss",
95 host.bridge.addMethod("eventInvite", ".plugin", in_sign='sssss', out_sign='', 97 out_sign="aa{ss}",
96 method=self._invite, 98 method=self._eventsList,
97 async=True) 99 async=True,
98 host.bridge.addMethod("eventInviteByEmail", ".plugin", in_sign='ssssassssssss', out_sign='', 100 )
99 method=self._inviteByEmail, 101 host.bridge.addMethod(
100 async=True) 102 "eventInviteeGet",
103 ".plugin",
104 in_sign="sss",
105 out_sign="a{ss}",
106 method=self._eventInviteeGet,
107 async=True,
108 )
109 host.bridge.addMethod(
110 "eventInviteeSet",
111 ".plugin",
112 in_sign="ssa{ss}s",
113 out_sign="",
114 method=self._eventInviteeSet,
115 async=True,
116 )
117 host.bridge.addMethod(
118 "eventInviteesList",
119 ".plugin",
120 in_sign="sss",
121 out_sign="a{sa{ss}}",
122 method=self._eventInviteesList,
123 async=True,
124 ),
125 host.bridge.addMethod(
126 "eventInvite",
127 ".plugin",
128 in_sign="sssss",
129 out_sign="",
130 method=self._invite,
131 async=True,
132 )
133 host.bridge.addMethod(
134 "eventInviteByEmail",
135 ".plugin",
136 in_sign="ssssassssssss",
137 out_sign="",
138 method=self._inviteByEmail,
139 async=True,
140 )
101 141
102 def getHandler(self, client): 142 def getHandler(self, client):
103 return EventsHandler(self) 143 return EventsHandler(self)
104 144
105 def _parseEventElt(self, event_elt): 145 def _parseEventElt(self, event_elt):
113 except StopIteration: 153 except StopIteration:
114 timestamp = -1 154 timestamp = -1
115 155
116 data = {} 156 data = {}
117 157
118 for key in (u'name',): 158 for key in (u"name",):
119 try: 159 try:
120 data[key] = event_elt[key] 160 data[key] = event_elt[key]
121 except KeyError: 161 except KeyError:
122 continue 162 continue
123 163
124 for elt_name in (u'description',): 164 for elt_name in (u"description",):
125 try: 165 try:
126 elt = next(event_elt.elements(NS_EVENT, elt_name)) 166 elt = next(event_elt.elements(NS_EVENT, elt_name))
127 except StopIteration: 167 except StopIteration:
128 continue 168 continue
129 else: 169 else:
130 data[elt_name] = unicode(elt) 170 data[elt_name] = unicode(elt)
131 171
132 for elt_name in (u'image', 'background-image'): 172 for elt_name in (u"image", "background-image"):
133 try: 173 try:
134 image_elt = next(event_elt.elements(NS_EVENT, elt_name)) 174 image_elt = next(event_elt.elements(NS_EVENT, elt_name))
135 data[elt_name] = image_elt['src'] 175 data[elt_name] = image_elt["src"]
136 except StopIteration: 176 except StopIteration:
137 continue 177 continue
138 except KeyError: 178 except KeyError:
139 log.warning(_(u'no src found for image')) 179 log.warning(_(u"no src found for image"))
140 180
141 for uri_type in (u'invitees', u'blog'): 181 for uri_type in (u"invitees", u"blog"):
142 try: 182 try:
143 elt = next(event_elt.elements(NS_EVENT, uri_type)) 183 elt = next(event_elt.elements(NS_EVENT, uri_type))
144 uri = data[uri_type + u'_uri'] = elt['uri'] 184 uri = data[uri_type + u"_uri"] = elt["uri"]
145 uri_data = xmpp_uri.parseXMPPUri(uri) 185 uri_data = xmpp_uri.parseXMPPUri(uri)
146 if uri_data[u'type'] != u'pubsub': 186 if uri_data[u"type"] != u"pubsub":
147 raise ValueError 187 raise ValueError
148 except StopIteration: 188 except StopIteration:
149 log.warning(_(u"no {uri_type} element found!").format(uri_type=uri_type)) 189 log.warning(_(u"no {uri_type} element found!").format(uri_type=uri_type))
150 except KeyError: 190 except KeyError:
151 log.warning(_(u"incomplete {uri_type} element").format(uri_type=uri_type)) 191 log.warning(_(u"incomplete {uri_type} element").format(uri_type=uri_type))
152 except ValueError: 192 except ValueError:
153 log.warning(_(u"bad {uri_type} element").format(uri_type=uri_type)) 193 log.warning(_(u"bad {uri_type} element").format(uri_type=uri_type))
154 else: 194 else:
155 data[uri_type + u'_service'] = uri_data[u'path'] 195 data[uri_type + u"_service"] = uri_data[u"path"]
156 data[uri_type + u'_node'] = uri_data[u'node'] 196 data[uri_type + u"_node"] = uri_data[u"node"]
157 197
158 for meta_elt in event_elt.elements(NS_EVENT, 'meta'): 198 for meta_elt in event_elt.elements(NS_EVENT, "meta"):
159 key = meta_elt[u'name'] 199 key = meta_elt[u"name"]
160 if key in data: 200 if key in data:
161 log.warning(u'Ignoring conflicting meta element: {xml}'.format(xml=meta_elt.toXml())) 201 log.warning(
202 u"Ignoring conflicting meta element: {xml}".format(
203 xml=meta_elt.toXml()
204 )
205 )
162 continue 206 continue
163 data[key] = unicode(meta_elt) 207 data[key] = unicode(meta_elt)
164 if event_elt.link: 208 if event_elt.link:
165 link_elt = event_elt.link 209 link_elt = event_elt.link
166 data['service'] = link_elt['service'] 210 data["service"] = link_elt["service"]
167 data['node'] = link_elt['node'] 211 data["node"] = link_elt["node"]
168 data['item'] = link_elt['item'] 212 data["item"] = link_elt["item"]
169 if event_elt.getAttribute('creator') == 'true': 213 if event_elt.getAttribute("creator") == "true":
170 data['creator'] = True 214 data["creator"] = True
171 return timestamp, data 215 return timestamp, data
172 216
173 @defer.inlineCallbacks 217 @defer.inlineCallbacks
174 def getEventElement(self, client, service, node, id_): 218 def getEventElement(self, client, service, node, id_):
175 """Retrieve event element 219 """Retrieve event element
182 """ 226 """
183 if not id_: 227 if not id_:
184 id_ = NS_EVENT 228 id_ = NS_EVENT
185 items, metadata = yield self._p.getItems(client, service, node, item_ids=[id_]) 229 items, metadata = yield self._p.getItems(client, service, node, item_ids=[id_])
186 try: 230 try:
187 event_elt = next(items[0].elements(NS_EVENT, u'event')) 231 event_elt = next(items[0].elements(NS_EVENT, u"event"))
188 except IndexError: 232 except IndexError:
189 raise exceptions.NotFound(_(u"No event with this id has been found")) 233 raise exceptions.NotFound(_(u"No event with this id has been found"))
190 defer.returnValue(event_elt) 234 defer.returnValue(event_elt)
191 235
192 @defer.inlineCallbacks 236 @defer.inlineCallbacks
202 """ 246 """
203 # we save a link to the event in our local list 247 # we save a link to the event in our local list
204 try: 248 try:
205 # TODO: check auto-create, no need to create node first if available 249 # TODO: check auto-create, no need to create node first if available
206 options = {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_WHITELIST} 250 options = {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_WHITELIST}
207 yield self._p.createNode(client, 251 yield self._p.createNode(
208 client.jid.userhostJID(), 252 client,
209 nodeIdentifier=NS_EVENT_LIST, 253 client.jid.userhostJID(),
210 options=options) 254 nodeIdentifier=NS_EVENT_LIST,
255 options=options,
256 )
211 except error.StanzaError as e: 257 except error.StanzaError as e:
212 if e.condition == u'conflict': 258 if e.condition == u"conflict":
213 log.debug(_(u"requested node already exists")) 259 log.debug(_(u"requested node already exists"))
214 link_elt = event_elt.addElement((NS_EVENT_LIST, 'link')) 260 link_elt = event_elt.addElement((NS_EVENT_LIST, "link"))
215 link_elt["service"] = service.full() 261 link_elt["service"] = service.full()
216 link_elt["node"] = node 262 link_elt["node"] = node
217 link_elt["item"] = event_id 263 link_elt["item"] = event_id
218 item_id = xmpp_uri.buildXMPPUri(u'pubsub', 264 item_id = xmpp_uri.buildXMPPUri(
219 path=service.full(), 265 u"pubsub", path=service.full(), node=node, item=event_id
220 node=node, 266 )
221 item=event_id)
222 if creator: 267 if creator:
223 event_elt['creator'] = 'true' 268 event_elt["creator"] = "true"
224 item_elt = pubsub.Item(id=item_id, payload=event_elt) 269 item_elt = pubsub.Item(id=item_id, payload=event_elt)
225 yield self._p.publish(client, 270 yield self._p.publish(
226 client.jid.userhostJID(), 271 client, client.jid.userhostJID(), NS_EVENT_LIST, items=[item_elt]
227 NS_EVENT_LIST, 272 )
228 items=[item_elt]) 273
229 274 def _eventGet(self, service, node, id_=u"", profile_key=C.PROF_KEY_NONE):
230 def _eventGet(self, service, node, id_=u'', profile_key=C.PROF_KEY_NONE):
231 service = jid.JID(service) if service else None 275 service = jid.JID(service) if service else None
232 node = node if node else NS_EVENT 276 node = node if node else NS_EVENT
233 client = self.host.getClient(profile_key) 277 client = self.host.getClient(profile_key)
234 return self.eventGet(client, service, node, id_) 278 return self.eventGet(client, service, node, id_)
235 279
249 """ 293 """
250 event_elt = yield self.getEventElement(client, service, node, id_) 294 event_elt = yield self.getEventElement(client, service, node, id_)
251 295
252 defer.returnValue(self._parseEventElt(event_elt)) 296 defer.returnValue(self._parseEventElt(event_elt))
253 297
254 def _eventCreate(self, timestamp, data, service, node, id_=u'', profile_key=C.PROF_KEY_NONE): 298 def _eventCreate(
299 self, timestamp, data, service, node, id_=u"", profile_key=C.PROF_KEY_NONE
300 ):
255 service = jid.JID(service) if service else None 301 service = jid.JID(service) if service else None
256 node = node or None 302 node = node or None
257 client = self.host.getClient(profile_key) 303 client = self.host.getClient(profile_key)
258 data[u'register'] = C.bool(data.get(u'register', C.BOOL_FALSE)) 304 data[u"register"] = C.bool(data.get(u"register", C.BOOL_FALSE))
259 return self.eventCreate(client, timestamp, data, service, node, id_ or NS_EVENT) 305 return self.eventCreate(client, timestamp, data, service, node, id_ or NS_EVENT)
260 306
261 @defer.inlineCallbacks 307 @defer.inlineCallbacks
262 def eventCreate(self, client, timestamp, data, service, node=None, event_id=NS_EVENT): 308 def eventCreate(self, client, timestamp, data, service, node=None, event_id=NS_EVENT):
263 """Create or replace an event 309 """Create or replace an event
280 if not event_id: 326 if not event_id:
281 raise ValueError(_(u"event_id must be set")) 327 raise ValueError(_(u"event_id must be set"))
282 if not service: 328 if not service:
283 service = client.jid.userhostJID() 329 service = client.jid.userhostJID()
284 if not node: 330 if not node:
285 node = NS_EVENT + u'__' + shortuuid.uuid() 331 node = NS_EVENT + u"__" + shortuuid.uuid()
286 event_elt = domish.Element((NS_EVENT, 'event')) 332 event_elt = domish.Element((NS_EVENT, "event"))
287 if timestamp is not None and timestamp != -1: 333 if timestamp is not None and timestamp != -1:
288 formatted_date = utils.xmpp_date(timestamp) 334 formatted_date = utils.xmpp_date(timestamp)
289 event_elt.addElement((NS_EVENT, 'date'), content=formatted_date) 335 event_elt.addElement((NS_EVENT, "date"), content=formatted_date)
290 register = data.pop('register', False) 336 register = data.pop("register", False)
291 for key in (u'name',): 337 for key in (u"name",):
292 if key in data: 338 if key in data:
293 event_elt[key] = data.pop(key) 339 event_elt[key] = data.pop(key)
294 for key in (u'description',): 340 for key in (u"description",):
295 if key in data: 341 if key in data:
296 event_elt.addElement((NS_EVENT, key), content=data.pop(key)) 342 event_elt.addElement((NS_EVENT, key), content=data.pop(key))
297 for key in (u'image', u'background-image'): 343 for key in (u"image", u"background-image"):
298 if key in data: 344 if key in data:
299 elt = event_elt.addElement((NS_EVENT, key)) 345 elt = event_elt.addElement((NS_EVENT, key))
300 elt['src'] = data.pop(key) 346 elt["src"] = data.pop(key)
301 347
302 # we first create the invitees and blog nodes (if not specified in data) 348 # we first create the invitees and blog nodes (if not specified in data)
303 for uri_type in (u'invitees', u'blog'): 349 for uri_type in (u"invitees", u"blog"):
304 key = uri_type + u'_uri' 350 key = uri_type + u"_uri"
305 for to_delete in (u'service', u'node'): 351 for to_delete in (u"service", u"node"):
306 k = uri_type + u'_' + to_delete 352 k = uri_type + u"_" + to_delete
307 if k in data: 353 if k in data:
308 del data[k] 354 del data[k]
309 if key not in data: 355 if key not in data:
310 # FIXME: affiliate invitees 356 # FIXME: affiliate invitees
311 uri_node = yield self._p.createNode(client, service) 357 uri_node = yield self._p.createNode(client, service)
312 yield self._p.setConfiguration(client, service, uri_node, {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_WHITELIST}) 358 yield self._p.setConfiguration(
359 client,
360 service,
361 uri_node,
362 {self._p.OPT_ACCESS_MODEL: self._p.ACCESS_WHITELIST},
363 )
313 uri_service = service 364 uri_service = service
314 else: 365 else:
315 uri = data.pop(key) 366 uri = data.pop(key)
316 uri_data = xmpp_uri.parseXMPPUri(uri) 367 uri_data = xmpp_uri.parseXMPPUri(uri)
317 if uri_data[u'type'] != u'pubsub': 368 if uri_data[u"type"] != u"pubsub":
318 raise ValueError(_(u'The given URI is not valid: {uri}').format(uri=uri)) 369 raise ValueError(
319 uri_service = jid.JID(uri_data[u'path']) 370 _(u"The given URI is not valid: {uri}").format(uri=uri)
320 uri_node = uri_data[u'node'] 371 )
372 uri_service = jid.JID(uri_data[u"path"])
373 uri_node = uri_data[u"node"]
321 374
322 elt = event_elt.addElement((NS_EVENT, uri_type)) 375 elt = event_elt.addElement((NS_EVENT, uri_type))
323 elt['uri'] = xmpp_uri.buildXMPPUri('pubsub', path=uri_service.full(), node=uri_node) 376 elt["uri"] = xmpp_uri.buildXMPPUri(
377 "pubsub", path=uri_service.full(), node=uri_node
378 )
324 379
325 # remaining data are put in <meta> elements 380 # remaining data are put in <meta> elements
326 for key in data.keys(): 381 for key in data.keys():
327 elt = event_elt.addElement((NS_EVENT, 'meta'), content = data.pop(key)) 382 elt = event_elt.addElement((NS_EVENT, "meta"), content=data.pop(key))
328 elt['name'] = key 383 elt["name"] = key
329 384
330 item_elt = pubsub.Item(id=event_id, payload=event_elt) 385 item_elt = pubsub.Item(id=event_id, payload=event_elt)
331 try: 386 try:
332 # TODO: check auto-create, no need to create node first if available 387 # TODO: check auto-create, no need to create node first if available
333 node = yield self._p.createNode(client, service, nodeIdentifier=node) 388 node = yield self._p.createNode(client, service, nodeIdentifier=node)
334 except error.StanzaError as e: 389 except error.StanzaError as e:
335 if e.condition == u'conflict': 390 if e.condition == u"conflict":
336 log.debug(_(u"requested node already exists")) 391 log.debug(_(u"requested node already exists"))
337 392
338 yield self._p.publish(client, service, node, items=[item_elt]) 393 yield self._p.publish(client, service, node, items=[item_elt])
339 394
340 if register: 395 if register:
341 yield self.register(client, service, node, event_id, event_elt, creator=True) 396 yield self.register(client, service, node, event_id, event_elt, creator=True)
342 defer.returnValue(node) 397 defer.returnValue(node)
343 398
344 def _eventModify(self, service, node, id_, timestamp_update, data_update, profile_key=C.PROF_KEY_NONE): 399 def _eventModify(
400 self,
401 service,
402 node,
403 id_,
404 timestamp_update,
405 data_update,
406 profile_key=C.PROF_KEY_NONE,
407 ):
345 service = jid.JID(service) if service else None 408 service = jid.JID(service) if service else None
346 node = node if node else NS_EVENT 409 node = node if node else NS_EVENT
347 client = self.host.getClient(profile_key) 410 client = self.host.getClient(profile_key)
348 return self.eventModify(client, service, node, id_ or NS_EVENT, timestamp_update or None, data_update) 411 return self.eventModify(
349 412 client, service, node, id_ or NS_EVENT, timestamp_update or None, data_update
350 @defer.inlineCallbacks 413 )
351 def eventModify(self, client, service, node, id_=NS_EVENT, timestamp_update=None, data_update=None): 414
415 @defer.inlineCallbacks
416 def eventModify(
417 self, client, service, node, id_=NS_EVENT, timestamp_update=None, data_update=None
418 ):
352 """Update an event 419 """Update an event
353 420
354 Similar as create instead that it update existing item instead of 421 Similar as create instead that it update existing item instead of
355 creating or replacing it. Params are the same as for [eventCreate]. 422 creating or replacing it. Params are the same as for [eventCreate].
356 """ 423 """
362 new_data[k] = v 429 new_data[k] = v
363 yield self.eventCreate(client, new_timestamp, new_data, service, node, id_) 430 yield self.eventCreate(client, new_timestamp, new_data, service, node, id_)
364 431
365 def _eventsListSerialise(self, events): 432 def _eventsListSerialise(self, events):
366 for timestamp, data in events: 433 for timestamp, data in events:
367 data['date'] = unicode(timestamp) 434 data["date"] = unicode(timestamp)
368 data['creator'] = C.boolConst(data.get('creator', False)) 435 data["creator"] = C.boolConst(data.get("creator", False))
369 return [e[1] for e in events] 436 return [e[1] for e in events]
370 437
371 def _eventsList(self, service, node, profile): 438 def _eventsList(self, service, node, profile):
372 service = jid.JID(service) if service else None 439 service = jid.JID(service) if service else None
373 node = node or None 440 node = node or None
386 node = NS_EVENT_LIST 453 node = NS_EVENT_LIST
387 items = yield self._p.getItems(client, service, node) 454 items = yield self._p.getItems(client, service, node)
388 events = [] 455 events = []
389 for item in items[0]: 456 for item in items[0]:
390 try: 457 try:
391 event_elt = next(item.elements(NS_EVENT, u'event')) 458 event_elt = next(item.elements(NS_EVENT, u"event"))
392 except IndexError: 459 except IndexError:
393 log.error(_(u"No event found in item {item_id}").format( 460 log.error(
394 item_id = item['id'])) 461 _(u"No event found in item {item_id}").format(item_id=item["id"])
462 )
395 timestamp, data = self._parseEventElt(event_elt) 463 timestamp, data = self._parseEventElt(event_elt)
396 events.append((timestamp, data)) 464 events.append((timestamp, data))
397 defer.returnValue(events) 465 defer.returnValue(events)
398 466
399 def _eventInviteeGet(self, service, node, profile_key): 467 def _eventInviteeGet(self, service, node, profile_key):
409 @param service(unicode, None): PubSub service 477 @param service(unicode, None): PubSub service
410 @param node(unicode): PubSub node of the event 478 @param node(unicode): PubSub node of the event
411 @return (dict): a dict with current attendance status, 479 @return (dict): a dict with current attendance status,
412 an empty dict is returned if nothing has been answered yed 480 an empty dict is returned if nothing has been answered yed
413 """ 481 """
414 items, metadata = yield self._p.getItems(client, service, node, item_ids=[client.jid.userhost()]) 482 items, metadata = yield self._p.getItems(
483 client, service, node, item_ids=[client.jid.userhost()]
484 )
415 try: 485 try:
416 event_elt = next(items[0].elements(NS_EVENT, u'invitee')) 486 event_elt = next(items[0].elements(NS_EVENT, u"invitee"))
417 except IndexError: 487 except IndexError:
418 # no item found, event data are not set yet 488 # no item found, event data are not set yet
419 defer.returnValue({}) 489 defer.returnValue({})
420 data = {} 490 data = {}
421 for key in (u'attend', u'guests'): 491 for key in (u"attend", u"guests"):
422 try: 492 try:
423 data[key] = event_elt[key] 493 data[key] = event_elt[key]
424 except KeyError: 494 except KeyError:
425 continue 495 continue
426 defer.returnValue(data) 496 defer.returnValue(data)
427 497
428 def _eventInviteeSet(self, service, node, event_data, profile_key): 498 def _eventInviteeSet(self, service, node, event_data, profile_key):
429 service = jid.JID(service) if service else None 499 service = jid.JID(service) if service else None
430 node = node if node else NS_EVENT 500 node = node if node else NS_EVENT
431 client = self.host.getClient(profile_key) 501 client = self.host.getClient(profile_key)
432 return self.eventInviteeSet(client, service, node, event_data) 502 return self.eventInviteeSet(client, service, node, event_data)
433 503
439 @param data(dict[unicode, unicode]): data to update 509 @param data(dict[unicode, unicode]): data to update
440 key can be: 510 key can be:
441 attend: one of "yes", "no", "maybe" 511 attend: one of "yes", "no", "maybe"
442 guests: an int 512 guests: an int
443 """ 513 """
444 event_elt = domish.Element((NS_EVENT, 'invitee')) 514 event_elt = domish.Element((NS_EVENT, "invitee"))
445 for key in (u'attend', u'guests'): 515 for key in (u"attend", u"guests"):
446 try: 516 try:
447 event_elt[key] = data.pop(key) 517 event_elt[key] = data.pop(key)
448 except KeyError: 518 except KeyError:
449 pass 519 pass
450 item_elt = pubsub.Item(id=client.jid.userhost(), payload=event_elt) 520 item_elt = pubsub.Item(id=client.jid.userhost(), payload=event_elt)
467 """ 537 """
468 items, metadata = yield self._p.getItems(client, service, node) 538 items, metadata = yield self._p.getItems(client, service, node)
469 invitees = {} 539 invitees = {}
470 for item in items: 540 for item in items:
471 try: 541 try:
472 event_elt = next(item.elements(NS_EVENT, u'invitee')) 542 event_elt = next(item.elements(NS_EVENT, u"invitee"))
473 except StopIteration: 543 except StopIteration:
474 # no item found, event data are not set yet 544 # no item found, event data are not set yet
475 log.warning(_(u"no data found for {item_id} (service: {service}, node: {node})".format( 545 log.warning(
476 item_id=item['id'], 546 _(
477 service=service, 547 u"no data found for {item_id} (service: {service}, node: {node})".format(
478 node=node 548 item_id=item["id"], service=service, node=node
479 ))) 549 )
550 )
551 )
480 else: 552 else:
481 data = {} 553 data = {}
482 for key in (u'attend', u'guests'): 554 for key in (u"attend", u"guests"):
483 try: 555 try:
484 data[key] = event_elt[key] 556 data[key] = event_elt[key]
485 except KeyError: 557 except KeyError:
486 continue 558 continue
487 invitees[item['id']] = data 559 invitees[item["id"]] = data
488 defer.returnValue(invitees) 560 defer.returnValue(invitees)
489 561
490 def sendMessageInvitation(self, client, invitee_jid, service, node, item_id): 562 def sendMessageInvitation(self, client, invitee_jid, service, node, item_id):
491 """Send an invitation in a <message> stanza 563 """Send an invitation in a <message> stanza
492 564
494 @param service(jid.JID): pubsub service of the event 566 @param service(jid.JID): pubsub service of the event
495 @param node(unicode): node of the event 567 @param node(unicode): node of the event
496 @param item_id(unicode): id of the event 568 @param item_id(unicode): id of the event
497 """ 569 """
498 mess_data = { 570 mess_data = {
499 'from': client.jid, 571 "from": client.jid,
500 'to': invitee_jid, 572 "to": invitee_jid,
501 'uid': '', 573 "uid": "",
502 'message': {}, 574 "message": {},
503 'type': C.MESS_TYPE_CHAT, 575 "type": C.MESS_TYPE_CHAT,
504 'subject': {}, 576 "subject": {},
505 'extra': {}, 577 "extra": {},
506 } 578 }
507 client.generateMessageXML(mess_data) 579 client.generateMessageXML(mess_data)
508 event_elt = mess_data['xml'].addElement('invitation', NS_EVENT_INVIT) 580 event_elt = mess_data["xml"].addElement("invitation", NS_EVENT_INVIT)
509 event_elt['service'] = service.full() 581 event_elt["service"] = service.full()
510 event_elt['node'] = node 582 event_elt["node"] = node
511 event_elt['item'] = item_id 583 event_elt["item"] = item_id
512 client.send(mess_data['xml']) 584 client.send(mess_data["xml"])
513 585
514 def _invite(self, invitee_jid, service, node, item_id, profile): 586 def _invite(self, invitee_jid, service, node, item_id, profile):
515 client = self.host.getClient(profile) 587 client = self.host.getClient(profile)
516 service = jid.JID(service) if service else None 588 service = jid.JID(service) if service else None
517 node = node or None 589 node = node or None
529 None to use client's PEP 601 None to use client's PEP
530 @param node(unicode): event node 602 @param node(unicode): event node
531 @param item_id(unicode): event id 603 @param item_id(unicode): event id
532 """ 604 """
533 if self._b is None: 605 if self._b is None:
534 raise exceptions.FeatureNotFound(_(u'"XEP-0277" (blog) plugin is needed for this feature')) 606 raise exceptions.FeatureNotFound(
607 _(u'"XEP-0277" (blog) plugin is needed for this feature')
608 )
535 if item_id is None: 609 if item_id is None:
536 item_id = NS_EVENT 610 item_id = NS_EVENT
537 611
538 # first we authorize our invitee to see the nodes of interest 612 # first we authorize our invitee to see the nodes of interest
539 yield self._p.setNodeAffiliations(client, service, node, {invitee_jid: u'member'}) 613 yield self._p.setNodeAffiliations(client, service, node, {invitee_jid: u"member"})
540 log.debug(_(u'affiliation set on event node')) 614 log.debug(_(u"affiliation set on event node"))
541 dummy, event_data = yield self.eventGet(client, service, node, item_id) 615 dummy, event_data = yield self.eventGet(client, service, node, item_id)
542 log.debug(_(u'got event data')) 616 log.debug(_(u"got event data"))
543 invitees_service = jid.JID(event_data['invitees_service']) 617 invitees_service = jid.JID(event_data["invitees_service"])
544 invitees_node = event_data['invitees_node'] 618 invitees_node = event_data["invitees_node"]
545 blog_service = jid.JID(event_data['blog_service']) 619 blog_service = jid.JID(event_data["blog_service"])
546 blog_node = event_data['blog_node'] 620 blog_node = event_data["blog_node"]
547 yield self._p.setNodeAffiliations(client, invitees_service, invitees_node, {invitee_jid: u'publisher'}) 621 yield self._p.setNodeAffiliations(
548 log.debug(_(u'affiliation set on invitee node')) 622 client, invitees_service, invitees_node, {invitee_jid: u"publisher"}
549 yield self._p.setNodeAffiliations(client, blog_service, blog_node, {invitee_jid: u'member'}) 623 )
624 log.debug(_(u"affiliation set on invitee node"))
625 yield self._p.setNodeAffiliations(
626 client, blog_service, blog_node, {invitee_jid: u"member"}
627 )
550 blog_items, dummy = yield self._b.mbGet(client, blog_service, blog_node, None) 628 blog_items, dummy = yield self._b.mbGet(client, blog_service, blog_node, None)
551 629
552 for item in blog_items: 630 for item in blog_items:
553 try: 631 try:
554 comments_service = jid.JID(item['comments_service']) 632 comments_service = jid.JID(item["comments_service"])
555 comments_node = item['comments_node'] 633 comments_node = item["comments_node"]
556 except KeyError: 634 except KeyError:
557 log.debug(u"no comment service set for itemĀ {item_id}".format(item_id=item['id'])) 635 log.debug(
636 u"no comment service set for itemĀ {item_id}".format(
637 item_id=item["id"]
638 )
639 )
558 else: 640 else:
559 yield self._p.setNodeAffiliations(client, comments_service, comments_node, {invitee_jid: u'publisher'}) 641 yield self._p.setNodeAffiliations(
560 log.debug(_(u'affiliation set on blog and comments nodes')) 642 client, comments_service, comments_node, {invitee_jid: u"publisher"}
643 )
644 log.debug(_(u"affiliation set on blog and comments nodes"))
561 645
562 # now we send the invitation 646 # now we send the invitation
563 self.sendMessageInvitation(client, invitee_jid, service, node, item_id) 647 self.sendMessageInvitation(client, invitee_jid, service, node, item_id)
564 648
565 def _inviteByEmail(self, service, node, id_=NS_EVENT, email=u'', emails_extra=None, name=u'', host_name=u'', language=u'', url_template=u'', 649 def _inviteByEmail(
566 message_subject=u'', message_body=u'', profile_key=C.PROF_KEY_NONE): 650 self,
651 service,
652 node,
653 id_=NS_EVENT,
654 email=u"",
655 emails_extra=None,
656 name=u"",
657 host_name=u"",
658 language=u"",
659 url_template=u"",
660 message_subject=u"",
661 message_body=u"",
662 profile_key=C.PROF_KEY_NONE,
663 ):
567 client = self.host.getClient(profile_key) 664 client = self.host.getClient(profile_key)
568 kwargs = {u'profile': client.profile, 665 kwargs = {
569 u'emails_extra': [unicode(e) for e in emails_extra] 666 u"profile": client.profile,
570 } 667 u"emails_extra": [unicode(e) for e in emails_extra],
571 for key in ("email", "name", "host_name", "language", "url_template", "message_subject", "message_body"): 668 }
669 for key in (
670 "email",
671 "name",
672 "host_name",
673 "language",
674 "url_template",
675 "message_subject",
676 "message_body",
677 ):
572 value = locals()[key] 678 value = locals()[key]
573 kwargs[key] = unicode(value) 679 kwargs[key] = unicode(value)
574 return self.inviteByEmail(client, 680 return self.inviteByEmail(
575 jid.JID(service) if service else None, 681 client, jid.JID(service) if service else None, node, id_ or NS_EVENT, **kwargs
576 node, 682 )
577 id_ or NS_EVENT,
578 **kwargs)
579 683
580 @defer.inlineCallbacks 684 @defer.inlineCallbacks
581 def inviteByEmail(self, client, service, node, id_=NS_EVENT, **kwargs): 685 def inviteByEmail(self, client, service, node, id_=NS_EVENT, **kwargs):
582 """High level method to create an email invitation to an event 686 """High level method to create an email invitation to an event
583 687
584 @param service(unicode, None): PubSub service 688 @param service(unicode, None): PubSub service
585 @param node(unicode): PubSub node of the event 689 @param node(unicode): PubSub node of the event
586 @param id_(unicode): id_ with even data 690 @param id_(unicode): id_ with even data
587 """ 691 """
588 if self._i is None: 692 if self._i is None:
589 raise exceptions.FeatureNotFound(_(u'"Invitations" plugin is needed for this feature')) 693 raise exceptions.FeatureNotFound(
694 _(u'"Invitations" plugin is needed for this feature')
695 )
590 if self._b is None: 696 if self._b is None:
591 raise exceptions.FeatureNotFound(_(u'"XEP-0277" (blog) plugin is needed for this feature')) 697 raise exceptions.FeatureNotFound(
698 _(u'"XEP-0277" (blog) plugin is needed for this feature')
699 )
592 service = service or client.jid.userhostJID() 700 service = service or client.jid.userhostJID()
593 event_uri = xmpp_uri.buildXMPPUri('pubsub', 701 event_uri = xmpp_uri.buildXMPPUri(
594 path=service.full(), 702 "pubsub", path=service.full(), node=node, item=id_
595 node=node, 703 )
596 item=id_) 704 kwargs["extra"] = {u"event_uri": event_uri}
597 kwargs['extra'] = {u'event_uri': event_uri}
598 invitation_data = yield self._i.create(**kwargs) 705 invitation_data = yield self._i.create(**kwargs)
599 invitee_jid = invitation_data[u'jid'] 706 invitee_jid = invitation_data[u"jid"]
600 log.debug(_(u'invitation created')) 707 log.debug(_(u"invitation created"))
601 # now that we have a jid, we can send normal invitation 708 # now that we have a jid, we can send normal invitation
602 yield self.invite(client, invitee_jid, service, node, id_) 709 yield self.invite(client, invitee_jid, service, node, id_)
603 710
604 @defer.inlineCallbacks 711 @defer.inlineCallbacks
605 def onInvitation(self, message_elt, client): 712 def onInvitation(self, message_elt, client):
606 invitation_elt = message_elt.invitation 713 invitation_elt = message_elt.invitation
607 try: 714 try:
608 service = jid.JID(invitation_elt['service']) 715 service = jid.JID(invitation_elt["service"])
609 node = invitation_elt['node'] 716 node = invitation_elt["node"]
610 event_id = invitation_elt['item'] 717 event_id = invitation_elt["item"]
611 except (RuntimeError, KeyError): 718 except (RuntimeError, KeyError):
612 log.warning(_(u"Bad invitation: {xml}").format(xml=message_elt.toXml())) 719 log.warning(_(u"Bad invitation: {xml}").format(xml=message_elt.toXml()))
613 720
614 event_elt = yield self.getEventElement(client, service, node, event_id) 721 event_elt = yield self.getEventElement(client, service, node, event_id)
615 yield self.register(client, service, node, event_id, event_elt, creator=False) 722 yield self.register(client, service, node, event_id, event_elt, creator=False)
624 @property 731 @property
625 def host(self): 732 def host(self):
626 return self.plugin_parent.host 733 return self.plugin_parent.host
627 734
628 def connectionInitialized(self): 735 def connectionInitialized(self):
629 self.xmlstream.addObserver(INVITATION, 736 self.xmlstream.addObserver(
630 self.plugin_parent.onInvitation, 737 INVITATION, self.plugin_parent.onInvitation, client=self.parent
631 client=self.parent) 738 )
632 739
633 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): 740 def getDiscoInfo(self, requestor, target, nodeIdentifier=""):
634 return [disco.DiscoFeature(NS_EVENT), 741 return [
635 disco.DiscoFeature(NS_EVENT_LIST), 742 disco.DiscoFeature(NS_EVENT),
636 disco.DiscoFeature(NS_EVENT_INVIT)] 743 disco.DiscoFeature(NS_EVENT_LIST),
637 744 disco.DiscoFeature(NS_EVENT_INVIT),
638 def getDiscoItems(self, requestor, target, nodeIdentifier=''): 745 ]
746
747 def getDiscoItems(self, requestor, target, nodeIdentifier=""):
639 return [] 748 return []