[misc & I] add adhoc command: ability to leave a room. see #1910

This commit is contained in:
Yann Leboulanger 2007-01-14 21:38:34 +00:00
parent bb306163a6
commit b21e2882c8
1 changed files with 143 additions and 41 deletions

View File

@ -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