[misc & I] add adhoc command: ability to leave a room. see #1910
This commit is contained in:
parent
bb306163a6
commit
b21e2882c8
|
@ -25,8 +25,8 @@ class AdHocCommand:
|
||||||
def isVisibleFor(samejid):
|
def isVisibleFor(samejid):
|
||||||
''' This returns True if that command should be visible and invokable
|
''' This returns True if that command should be visible and invokable
|
||||||
for others.
|
for others.
|
||||||
samejid - True when command is invoked by an entity with the same bare jid.
|
samejid - True when command is invoked by an entity with the same bare
|
||||||
'''
|
jid.'''
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __init__(self, conn, jid, sessionid):
|
def __init__(self, conn, jid, sessionid):
|
||||||
|
@ -34,7 +34,8 @@ class AdHocCommand:
|
||||||
self.jid = jid
|
self.jid = jid
|
||||||
self.sessionid = sessionid
|
self.sessionid = sessionid
|
||||||
|
|
||||||
def buildResponse(self, request, status='executing', defaultaction=None, actions=None):
|
def buildResponse(self, request, status = 'executing', defaultaction = None,
|
||||||
|
actions = None):
|
||||||
assert status in ('executing', 'completed', 'canceled')
|
assert status in ('executing', 'completed', 'canceled')
|
||||||
|
|
||||||
response = request.buildReply('result')
|
response = request.buildReply('result')
|
||||||
|
@ -45,7 +46,8 @@ class AdHocCommand:
|
||||||
'status': status})
|
'status': status})
|
||||||
if defaultaction is not None or actions is not None:
|
if defaultaction is not None or actions is not None:
|
||||||
if defaultaction is not None:
|
if defaultaction is not None:
|
||||||
assert defaultaction in ('cancel', 'execute', 'prev', 'next', 'complete')
|
assert defaultaction in ('cancel', 'execute', 'prev', 'next',
|
||||||
|
'complete')
|
||||||
attrs = {'action': defaultaction}
|
attrs = {'action': defaultaction}
|
||||||
else:
|
else:
|
||||||
attrs = {}
|
attrs = {}
|
||||||
|
@ -54,16 +56,17 @@ class AdHocCommand:
|
||||||
return response, cmd
|
return response, cmd
|
||||||
|
|
||||||
def badRequest(self, stanza):
|
def badRequest(self, stanza):
|
||||||
self.connection.connection.send(xmpp.Error(stanza, xmpp.NS_STANZAS+' bad-request'))
|
self.connection.connection.send(xmpp.Error(stanza, xmpp.NS_STANZAS + \
|
||||||
|
' bad-request'))
|
||||||
|
|
||||||
def cancel(self, request):
|
def cancel(self, request):
|
||||||
response, cmd = self.buildResponse(request, status='canceled')
|
response, cmd = self.buildResponse(request, status = 'canceled')
|
||||||
self.connection.connection.send(response)
|
self.connection.connection.send(response)
|
||||||
return False # finish the session
|
return False # finish the session
|
||||||
|
|
||||||
class ChangeStatusCommand(AdHocCommand):
|
class ChangeStatusCommand(AdHocCommand):
|
||||||
commandnode = 'change-status'
|
commandnode = 'change-status'
|
||||||
commandname = 'Change status information'
|
commandname = _('Change status information')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isVisibleFor(samejid):
|
def isVisibleFor(samejid):
|
||||||
|
@ -72,27 +75,28 @@ class ChangeStatusCommand(AdHocCommand):
|
||||||
|
|
||||||
def execute(self, request):
|
def execute(self, request):
|
||||||
# first query...
|
# first query...
|
||||||
response, cmd = self.buildResponse(request, defaultaction='execute', actions=['execute'])
|
response, cmd = self.buildResponse(request, defaultaction = 'execute',
|
||||||
|
actions = ['execute'])
|
||||||
|
|
||||||
cmd.addChild(node=dataforms.SimpleDataForm(
|
cmd.addChild(node = dataforms.SimpleDataForm(
|
||||||
title='Change status',
|
title = _('Change status'),
|
||||||
instructions='Set the presence type and description',
|
instructions = _('Set the presence type and description'),
|
||||||
fields=[
|
fields = [
|
||||||
dataforms.Field('list-single',
|
dataforms.Field('list-single',
|
||||||
var='presence-type',
|
var = 'presence-type',
|
||||||
label='Type of presence:',
|
label = 'Type of presence:',
|
||||||
options=[
|
options = [
|
||||||
(u'free-for-chat', u'Free for chat'),
|
(u'free-for-chat', _('Free for chat')),
|
||||||
(u'online', u'Online'),
|
(u'online', _('Online')),
|
||||||
(u'away', u'Away'),
|
(u'away', _('Away')),
|
||||||
(u'xa', u'Extended away'),
|
(u'xa', _('Extended away')),
|
||||||
(u'dnd', u'Do not disturb'),
|
(u'dnd', _('Do not disturb')),
|
||||||
(u'offline', u'Offline - disconnect')],
|
(u'offline', _('Offline - disconnect'))],
|
||||||
value='online',
|
value = 'online',
|
||||||
required=True),
|
required = True),
|
||||||
dataforms.Field('text-multi',
|
dataforms.Field('text-multi',
|
||||||
var='presence-desc',
|
var = 'presence-desc',
|
||||||
label='Presence description:')]))
|
label = _('Presence description:'))]))
|
||||||
|
|
||||||
self.connection.connection.send(response)
|
self.connection.connection.send(response)
|
||||||
|
|
||||||
|
@ -104,7 +108,8 @@ class ChangeStatusCommand(AdHocCommand):
|
||||||
def changestatus(self, request):
|
def changestatus(self, request):
|
||||||
# check if the data is correct
|
# check if the data is correct
|
||||||
try:
|
try:
|
||||||
form=dataforms.SimpleDataForm(extend=request.getTag('command').getTag('x'))
|
form = dataforms.SimpleDataForm(extend = request.getTag('command').\
|
||||||
|
getTag('x'))
|
||||||
except:
|
except:
|
||||||
self.badRequest(request)
|
self.badRequest(request)
|
||||||
return False
|
return False
|
||||||
|
@ -125,24 +130,118 @@ class ChangeStatusCommand(AdHocCommand):
|
||||||
except: # same exceptions as in last comment
|
except: # same exceptions as in last comment
|
||||||
presencedesc = u''
|
presencedesc = u''
|
||||||
|
|
||||||
response, cmd = self.buildResponse(request, status='completed')
|
response, cmd = self.buildResponse(request, status = 'completed')
|
||||||
cmd.addChild('note', {}, 'The status has been changed.')
|
cmd.addChild('note', {}, _('The status has been changed.'))
|
||||||
|
|
||||||
# if going offline, we need to push response so it won't go into
|
# if going offline, we need to push response so it won't go into
|
||||||
# queue and disappear
|
# queue and disappear
|
||||||
self.connection.connection.send(response, presencetype=='offline')
|
self.connection.connection.send(response, presencetype == 'offline')
|
||||||
|
|
||||||
# send new status
|
# send new status
|
||||||
gajim.interface.roster.send_status(self.connection.name, presencetype, presencedesc)
|
gajim.interface.roster.send_status(self.connection.name, presencetype,
|
||||||
|
presencedesc)
|
||||||
|
|
||||||
return False # finish the session
|
return False # finish the session
|
||||||
|
|
||||||
|
def find_current_groupchats(account):
|
||||||
|
import message_control
|
||||||
|
rooms = []
|
||||||
|
for gc_control in gajim.interface.msg_win_mgr.get_controls(
|
||||||
|
message_control.TYPE_GC):
|
||||||
|
acct = gc_control.account
|
||||||
|
# check if account is the good one
|
||||||
|
if acct != account:
|
||||||
|
continue
|
||||||
|
room_jid = gc_control.room_jid
|
||||||
|
nick = gc_control.nick
|
||||||
|
if gajim.gc_connected[acct].has_key(room_jid) and \
|
||||||
|
gajim.gc_connected[acct][room_jid]:
|
||||||
|
rooms.append((room_jid, nick,))
|
||||||
|
return rooms
|
||||||
|
|
||||||
|
|
||||||
|
class LeaveGroupchatsCommand(AdHocCommand):
|
||||||
|
commandnode = 'leave-groupchats'
|
||||||
|
commandname = 'Leave Groupchats'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def isVisibleFor(samejid):
|
||||||
|
''' Change status is visible only if the entity has the same bare jid. '''
|
||||||
|
return samejid
|
||||||
|
|
||||||
|
def execute(self, request):
|
||||||
|
# first query...
|
||||||
|
response, cmd = self.buildResponse(request, defaultaction = 'execute',
|
||||||
|
actions=['execute'])
|
||||||
|
options = []
|
||||||
|
account = self.connection.name
|
||||||
|
for gc in find_current_groupchats(account):
|
||||||
|
options.append((u'%s' %(gc[0]), _('%(nickname)s on %(room_jid)s') % \
|
||||||
|
{'nickname': gc[1], 'room_jid': gc[0]}))
|
||||||
|
if not len(options):
|
||||||
|
response, cmd = self.buildResponse(request, status = 'completed')
|
||||||
|
cmd.addChild('note', {}, _('You have not joined a groupchat.'))
|
||||||
|
|
||||||
|
self.connection.connection.send(response)
|
||||||
|
return False
|
||||||
|
|
||||||
|
cmd.addChild(node=dataforms.SimpleDataForm(
|
||||||
|
title = _('Leave Groupchats'),
|
||||||
|
instructions = _('Choose the groupchats you want to leave'),
|
||||||
|
fields=[
|
||||||
|
dataforms.Field('list-multi',
|
||||||
|
var = 'groupchats',
|
||||||
|
label = _('Groupchats'),
|
||||||
|
options = options,
|
||||||
|
required = True)]))
|
||||||
|
|
||||||
|
self.connection.connection.send(response)
|
||||||
|
|
||||||
|
# for next invocation
|
||||||
|
self.execute = self.leavegroupchats
|
||||||
|
|
||||||
|
return True # keep the session
|
||||||
|
|
||||||
|
def leavegroupchats(self, request):
|
||||||
|
# check if the data is correct
|
||||||
|
try:
|
||||||
|
form = dataforms.SimpleDataForm(extend = request.getTag('command').\
|
||||||
|
getTag('x'))
|
||||||
|
except:
|
||||||
|
self.badRequest(request)
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
gc = form['groupchats'].values
|
||||||
|
except: # KeyError if there's no presence-type field in form or
|
||||||
|
# AttributeError if that field is of wrong type
|
||||||
|
self.badRequest(request)
|
||||||
|
return False
|
||||||
|
account = self.connection.name
|
||||||
|
try:
|
||||||
|
for room_jid in gc:
|
||||||
|
gc_control = gajim.interface.msg_win_mgr.get_control(room_jid,
|
||||||
|
account)
|
||||||
|
gc_control.parent_win.remove_tab(gc_control, None, force = True)
|
||||||
|
except: # KeyError if there's no presence-type field in form or
|
||||||
|
self.badRequest(request)
|
||||||
|
return False
|
||||||
|
response, cmd = self.buildResponse(request, status = 'completed')
|
||||||
|
note = _('You leaved the following groupchats:')
|
||||||
|
for room_jid in gc:
|
||||||
|
note += '\n\t' + room_jid
|
||||||
|
cmd.addChild('note', {}, note)
|
||||||
|
|
||||||
|
self.connection.connection.send(response)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class ConnectionCommands:
|
class ConnectionCommands:
|
||||||
''' This class depends on that it is a part of Connection() class. '''
|
''' This class depends on that it is a part of Connection() class. '''
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# a list of all commands exposed: node -> command class
|
# a list of all commands exposed: node -> command class
|
||||||
self.__commands = {}
|
self.__commands = {}
|
||||||
for cmdobj in (ChangeStatusCommand,):
|
for cmdobj in (ChangeStatusCommand, LeaveGroupchatsCommand):
|
||||||
self.__commands[cmdobj.commandnode] = cmdobj
|
self.__commands[cmdobj.commandnode] = cmdobj
|
||||||
|
|
||||||
# a list of sessions; keys are tuples (jid, sessionid, node)
|
# a list of sessions; keys are tuples (jid, sessionid, node)
|
||||||
|
@ -164,7 +263,7 @@ class ConnectionCommands:
|
||||||
if cmd.isVisibleFor(self.isSameJID(jid)):
|
if cmd.isVisibleFor(self.isSameJID(jid)):
|
||||||
q.addChild('item', {
|
q.addChild('item', {
|
||||||
# TODO: find the jid
|
# TODO: find the jid
|
||||||
'jid': self.getOurBareJID()+u'/'+self.server_resource,
|
'jid': self.getOurBareJID() + u'/' + self.server_resource,
|
||||||
'node': node,
|
'node': node,
|
||||||
'name': cmd.commandname})
|
'name': cmd.commandname})
|
||||||
|
|
||||||
|
@ -209,7 +308,7 @@ class ConnectionCommands:
|
||||||
# and command exist
|
# and command exist
|
||||||
if node not in self.__commands.keys():
|
if node not in self.__commands.keys():
|
||||||
self.connection.send(
|
self.connection.send(
|
||||||
xmpp.Error(iq_obj, xmpp.NS_STANZAS+' item-not-found'))
|
xmpp.Error(iq_obj, xmpp.NS_STANZAS + ' item-not-found'))
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
newcmd = self.__commands[node]
|
newcmd = self.__commands[node]
|
||||||
|
@ -220,7 +319,7 @@ class ConnectionCommands:
|
||||||
sessionid = self.connection.getAnID()
|
sessionid = self.connection.getAnID()
|
||||||
|
|
||||||
# create new instance and run it
|
# create new instance and run it
|
||||||
obj = newcmd(conn=self, jid=jid, sessionid=sessionid)
|
obj = newcmd(conn = self, jid = jid, sessionid = sessionid)
|
||||||
rc = obj.execute(iq_obj)
|
rc = obj.execute(iq_obj)
|
||||||
if rc:
|
if rc:
|
||||||
self.__sessions[(jid, sessionid, node)] = obj
|
self.__sessions[(jid, sessionid, node)] = obj
|
||||||
|
@ -236,12 +335,16 @@ class ConnectionCommands:
|
||||||
obj = self.__sessions[magictuple]
|
obj = self.__sessions[magictuple]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if action == 'cancel': rc = obj.cancel(iq_obj)
|
if action == 'cancel':
|
||||||
elif action == 'prev': rc = obj.prev(iq_obj)
|
rc = obj.cancel(iq_obj)
|
||||||
elif action == 'next': rc = obj.next(iq_obj)
|
elif action == 'prev':
|
||||||
|
rc = obj.prev(iq_obj)
|
||||||
|
elif action == 'next':
|
||||||
|
rc = obj.next(iq_obj)
|
||||||
elif action == 'execute' or action is None:
|
elif action == 'execute' or action is None:
|
||||||
rc = obj.execute(iq_obj)
|
rc = obj.execute(iq_obj)
|
||||||
elif action == 'complete': rc = obj.complete(iq_obj)
|
elif action == 'complete':
|
||||||
|
rc = obj.complete(iq_obj)
|
||||||
else:
|
else:
|
||||||
# action is wrong. stop the session, send error
|
# action is wrong. stop the session, send error
|
||||||
raise AttributeError
|
raise AttributeError
|
||||||
|
@ -256,4 +359,3 @@ class ConnectionCommands:
|
||||||
del self.__sessions[magictuple]
|
del self.__sessions[magictuple]
|
||||||
|
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue