1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import xmpp
26 import helpers
27 import dataforms
28 import gajim
31 commandnode = 'command'
32 commandname = 'The Command'
33 commandfeatures = (xmpp.NS_DATA,)
34
35 @staticmethod
37 """
38 This returns True if that command should be visible and invokable for
39 others
40
41 samejid - True when command is invoked by an entity with the same bare
42 jid.
43 """
44 return True
45
46 - def __init__(self, conn, jid, sessionid):
47 self.connection = conn
48 self.jid = jid
49 self.sessionid = sessionid
50
51 - def buildResponse(self, request, status = 'executing', defaultaction = None,
52 actions = None):
53 assert status in ('executing', 'completed', 'canceled')
54
55 response = request.buildReply('result')
56 cmd = response.addChild('command', namespace=xmpp.NS_COMMANDS, attrs={
57 'sessionid': self.sessionid,
58 'node': self.commandnode,
59 'status': status})
60 if defaultaction is not None or actions is not None:
61 if defaultaction is not None:
62 assert defaultaction in ('cancel', 'execute', 'prev', 'next',
63 'complete')
64 attrs = {'action': defaultaction}
65 else:
66 attrs = {}
67
68 cmd.addChild('actions', attrs, actions)
69 return response, cmd
70
74
79
81 commandnode = 'change-status'
82 commandname = _('Change status information')
83
84 @staticmethod
86 """
87 Change status is visible only if the entity has the same bare jid
88 """
89 return samejid
90
92
93 response, cmd = self.buildResponse(request, defaultaction = 'execute',
94 actions = ['execute'])
95
96 cmd.addChild(node = dataforms.SimpleDataForm(
97 title = _('Change status'),
98 instructions = _('Set the presence type and description'),
99 fields = [
100 dataforms.Field('list-single',
101 var = 'presence-type',
102 label = 'Type of presence:',
103 options = [
104 (u'chat', _('Free for chat')),
105 (u'online', _('Online')),
106 (u'away', _('Away')),
107 (u'xa', _('Extended away')),
108 (u'dnd', _('Do not disturb')),
109 (u'offline', _('Offline - disconnect'))],
110 value = 'online',
111 required = True),
112 dataforms.Field('text-multi',
113 var = 'presence-desc',
114 label = _('Presence description:'))]))
115
116 self.connection.connection.send(response)
117
118
119 self.execute = self.changestatus
120
121 return True
122
124
125 try:
126 form = dataforms.SimpleDataForm(extend = request.getTag('command').\
127 getTag('x'))
128 except Exception:
129 self.badRequest(request)
130 return False
131
132 try:
133 presencetype = form['presence-type'].value
134 if not presencetype in \
135 ('chat', 'online', 'away', 'xa', 'dnd', 'offline'):
136 self.badRequest(request)
137 return False
138 except Exception:
139
140 self.badRequest(request)
141 return False
142
143 try:
144 presencedesc = form['presence-desc'].value
145 except Exception:
146 presencedesc = u''
147
148 response, cmd = self.buildResponse(request, status = 'completed')
149 cmd.addChild('note', {}, _('The status has been changed.'))
150
151
152
153 self.connection.connection.send(response, now = presencetype == 'offline')
154
155
156 gajim.interface.roster.send_status(self.connection.name, presencetype,
157 presencedesc)
158
159 return False
160
177
180 commandnode = 'leave-groupchats'
181 commandname = _('Leave Groupchats')
182
183 @staticmethod
185 """
186 Change status is visible only if the entity has the same bare jid
187 """
188 return samejid
189
191
192 response, cmd = self.buildResponse(request, defaultaction = 'execute',
193 actions=['execute'])
194 options = []
195 account = self.connection.name
196 for gc in find_current_groupchats(account):
197 options.append((u'%s' %(gc[0]), _('%(nickname)s on %(room_jid)s') % \
198 {'nickname': gc[1], 'room_jid': gc[0]}))
199 if not len(options):
200 response, cmd = self.buildResponse(request, status = 'completed')
201 cmd.addChild('note', {}, _('You have not joined a groupchat.'))
202
203 self.connection.connection.send(response)
204 return False
205
206 cmd.addChild(node=dataforms.SimpleDataForm(
207 title = _('Leave Groupchats'),
208 instructions = _('Choose the groupchats you want to leave'),
209 fields=[
210 dataforms.Field('list-multi',
211 var = 'groupchats',
212 label = _('Groupchats'),
213 options = options,
214 required = True)]))
215
216 self.connection.connection.send(response)
217
218
219 self.execute = self.leavegroupchats
220
221 return True
222
260
263
264 commandnode = 'forward-messages'
265 commandname = _('Forward unread messages')
266
267 @staticmethod
269 """
270 Change status is visible only if the entity has the same bare jid
271 """
272 return samejid
273
275 account = self.connection.name
276
277 events = gajim.events.get_events(account, types=['chat', 'normal'])
278 j, resource = gajim.get_room_and_nick_from_fjid(self.jid)
279 for jid in events:
280 for event in events[jid]:
281 self.connection.send_message(j, event.parameters[0], '',
282 type_=event.type_, subject=event.parameters[1],
283 resource=resource, forward_from=jid, delayed=event.time_)
284
285
286 response, cmd = self.buildResponse(request, status = 'completed')
287 cmd.addChild('note', {}, _('All unread messages have been forwarded.'))
288
289 self.connection.connection.send(response)
290
291 return False
292
294 commandnode = 'fwd-msd-disconnect'
295 commandname = _('Forward unread message then disconnect')
296
297 @staticmethod
299 """
300 Change status is visible only if the entity has the same bare jid
301 """
302 return samejid
303
305 account = self.connection.name
306
307 events = gajim.events.get_events(account, types=['chat', 'normal'])
308 j, resource = gajim.get_room_and_nick_from_fjid(self.jid)
309 for jid in events:
310 for event in events[jid]:
311 self.connection.send_message(j, event.parameters[0], '',
312 type_=event.type_, subject=event.parameters[1],
313 resource=resource, forward_from=jid, delayed=event.time_,
314 now=True)
315
316 response, cmd = self.buildResponse(request, status = 'completed')
317 cmd.addChild('note', {}, _('The status has been changed.'))
318
319
320
321 self.connection.connection.send(response, now = True)
322
323
324 gajim.interface.roster.send_status(self.connection.name, 'offline', '')
325
326 return False
327
329 """
330 This class depends on that it is a part of Connection() class
331 """
332
342
345
351
368
370 """
371 Send disco#info result for query for command (JEP-0050, example 6.).
372 Return True if the result was sent, False if not
373 """
374 jid = helpers.get_full_jid_from_iq(iq_obj)
375 node = iq_obj.getTagAttr('query', 'node')
376
377 if node not in self.__commands: return False
378
379 cmd = self.__commands[node]
380 if cmd.isVisibleFor(self.isSameJID(jid)):
381 iq = iq_obj.buildReply('result')
382 q = iq.getTag('query')
383 q.addChild('identity', attrs = {'type': 'command-node',
384 'category': 'automation',
385 'name': cmd.commandname})
386 q.addChild('feature', attrs = {'var': xmpp.NS_COMMANDS})
387 for feature in cmd.commandfeatures:
388 q.addChild('feature', attrs = {'var': feature})
389
390 self.connection.send(iq)
391 return True
392
393 return False
394
396 """
397 Send disco#items result for query for command. Return True if the result
398 was sent, False if not.
399 """
400 jid = helpers.get_full_jid_from_iq(iq_obj)
401 node = iq_obj.getTagAttr('query', 'node')
402
403 if node not in self.__commands: return False
404
405 cmd = self.__commands[node]
406 if cmd.isVisibleFor(self.isSameJID(jid)):
407 iq = iq_obj.buildReply('result')
408 self.connection.send(iq)
409 return True
410
411 return False
412
414 jid = helpers.get_full_jid_from_iq(iq_obj)
415
416 cmd = iq_obj.getTag('command')
417 if cmd is None: return
418
419 node = cmd.getAttr('node')
420 if node is None: return
421
422 sessionid = cmd.getAttr('sessionid')
423 if sessionid is None:
424
425
426 if node not in self.__commands.keys():
427 self.connection.send(
428 xmpp.Error(iq_obj, xmpp.NS_STANZAS + ' item-not-found'))
429 raise xmpp.NodeProcessed
430
431 newcmd = self.__commands[node]
432 if not newcmd.isVisibleFor(self.isSameJID(jid)):
433 return
434
435
436 sessionid = self.connection.getAnID()
437
438
439 obj = newcmd(conn = self, jid = jid, sessionid = sessionid)
440 rc = obj.execute(iq_obj)
441 if rc:
442 self.__sessions[(jid, sessionid, node)] = obj
443 raise xmpp.NodeProcessed
444 else:
445
446 magictuple = (jid, sessionid, node)
447 if magictuple not in self.__sessions:
448
449 return
450
451 action = cmd.getAttr('action')
452 obj = self.__sessions[magictuple]
453
454 try:
455 if action == 'cancel':
456 rc = obj.cancel(iq_obj)
457 elif action == 'prev':
458 rc = obj.prev(iq_obj)
459 elif action == 'next':
460 rc = obj.next(iq_obj)
461 elif action == 'execute' or action is None:
462 rc = obj.execute(iq_obj)
463 elif action == 'complete':
464 rc = obj.complete(iq_obj)
465 else:
466
467 raise AttributeError
468 except AttributeError:
469
470
471 del self.__sessions[magictuple]
472 return
473
474
475 if not rc:
476 del self.__sessions[magictuple]
477
478 raise xmpp.NodeProcessed
479