Generic support for exposing commands (untested).

This commit is contained in:
Tomasz Melcer 2006-07-15 13:27:57 +00:00
parent 76c7831c49
commit 477f33b6b9

View file

@ -655,6 +655,10 @@ class ConnectionDisco:
feature = common.xmpp.Node('feature')
feature.setAttr('var', common.xmpp.NS_FILE)
query.addChild(node=feature)
# exposing adhoc commands
feature = common.xmpp.Node('feature')
feature.setAttr('var', common.xmpp.NS_COMMANDS)
query.addChild(node=feature)
self.connection.send(iq)
raise common.xmpp.NodeProcessed
@ -692,19 +696,33 @@ class ConnectionDisco:
else:
self.dispatch('AGENT_INFO_ITEMS', (jid, node, items))
def _DiscoverItemsGetCB(self, con, iq_obj):
gajim.log.debug('DiscoverItemsGetCB')
node = iq_obj.getTagAttr('query', 'node')
if node==common.xmpp.NS_COMMANDS:
self.commandListQuery(con, iq_obj)
raise common.xmpp.NodeProcessed
def _DiscoverInfoGetCB(self, con, iq_obj):
gajim.log.debug('DiscoverInfoGetCB')
iq = iq_obj.buildReply('result')
q = iq.getTag('query')
q.addChild('identity', attrs = {'type': 'pc',
'category': 'client',
'name': 'Gajim'})
q.addChild('feature', attrs = {'var': common.xmpp.NS_BYTESTREAM})
q.addChild('feature', attrs = {'var': common.xmpp.NS_SI})
q.addChild('feature', attrs = {'var': common.xmpp.NS_FILE})
q.addChild('feature', attrs = {'var': common.xmpp.NS_MUC})
self.connection.send(iq)
raise common.xmpp.NodeProcessed
q = iq_obj.getTag('query')
node = q.getAttr('node')
if self.commandQuery(con, iq_obj):
raise NodeProcessed
elif node is None:
iq = iq_obj.buildReply('result')
q = iq.getTag('query')
q.addChild('identity', attrs = {'type': 'pc',
'category': 'client',
'name': 'Gajim'})
q.addChild('feature', attrs = {'var': common.xmpp.NS_BYTESTREAM})
q.addChild('feature', attrs = {'var': common.xmpp.NS_SI})
q.addChild('feature', attrs = {'var': common.xmpp.NS_FILE})
q.addChild('feature', attrs = {'var': common.xmpp.NS_MUC})
self.connection.send(iq)
raise common.xmpp.NodeProcessed
def _DiscoverInfoErrorCB(self, con, iq_obj):
gajim.log.debug('DiscoverInfoErrorCB')
@ -1036,11 +1054,124 @@ class ConnectionVcard:
else:
self.dispatch('VCARD', vcard)
class AdHocCommand:
commandnode = 'command'
commandname = 'The Command'
commandfeatures = (common.xmpp.NS_DATA,)
class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco):
@staticmethod
def isVisibleFor(jid): return True
class ChangeStatusCommand(AdHocCommand):
commandnode = 'change-status'
commandname = 'Change status information'
def __init__(self, sessiondata):
pass
class ConnectionCommands:
def __init__(self):
# a list of all commands exposed
self.__commands = {}
for cmdobj in (ChangeStatusCommand,):
self.__commands[cmdobj.commandnode] = cmdobj
# a list of sessions; keys are tuples (jid, sessionid, node)
self.__sessions = {}
def commandListQuery(self, con, iq_obj):
iq = iq_obj.buildReply('result')
jid = helpers.get_full_jid_from_iq(iq_obj)
q = iq.getTag('query')
for node, cmd in self.__commands.iter_items():
if cmd.isVisibleFor(jid):
q.addChild('item', {
'jid': 'our-jid',
'node': node,
'name': cmd.commandname})
self.connection.send(iq)
def commandQuery(self, con, iq_obj):
''' Send disco result for query for command (JEP-0050, example 6.).
Return True if the result was sent, False if not. '''
jid = helpers.get_full_jid_from_iq(iq_obj)
node = iq_obj.getTagAttr('query', 'node')
if node not in self.__commands: return False
cmd = self.__commands[node]
if cmd.isVisibleFor(jid):
iq = iq_obj.buildReply('result')
q = iq.getTag('query')
q.addChild('identity', attrs = {'type': 'command-node',
'category': 'automation',
'name': cmd.commandname})
q.addChild('feature', attrs = {'var': common.xmpp.NS_COMMANDS})
for feature in cmd.commandfeatures:
q.addChild('feature', attrs = {'var': feature})
self.connection.send(iq)
return True
return False
def _CommandExecuteCB(self, con, iq_obj):
jid = helpers.get_full_jid_from_iq(iq_obj)
cmd = iq_obj.getTag('command')
if cmd is None: return
node = cmd.getAttr('node')
if node is None: return
sessionid = cmd.getAttr('sessionid')
if sessionid is None:
# we start a new command session... only if we are visible for the jid
newcmd = self.__commands[node]
if not newcmd.isVisibleFor(jid):
return
# generate new sessionid
sessionid = self.connection.getAnID()
# create new instance and run it
obj = newcmd(jid=jid, sessionid=sessionid)
rc = obj.execute()
if rc:
self.__sessions[(jid, sessionid, node)] = obj
raise NodeProcessed
else:
# the command is already running, check for it
magictuple = (jid, sessionid, node)
if magictuple not in self.__sessions:
# we don't have this session... ha!
return
action = cmd.getAttr('action')
obj = self.__sessions[magictuple]
if action == 'cancel': rc = obj.cancel(iq_obj)
elif action == 'prev': rc = obj.prev(iq_obj)
elif action == 'next': rc = obj.next(iq_obj)
elif action == 'execute': rc = obj.execute(iq_obj)
elif action == 'complete': rc = obj.complete(iq_obj)
else:
# action is wrong. stop the session, send error
del self.__sessions[magictuple]
return
# delete the session if rc is False
if not rc:
del self.__sessions[magictuple]
raise NodeProcessed
class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ConnectionCommands):
def __init__(self):
ConnectionVcard.__init__(self)
ConnectionBytestream.__init__(self)
ConnectionCommands.__init__(self)
# List of IDs we are waiting answers for {id: (type_of_request, data), }
self.awaiting_answers = {}
# List of IDs that will produce a timeout is answer doesn't arrive
@ -1785,12 +1916,16 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco)
common.xmpp.NS_PRIVATE)
con.RegisterHandler('iq', self._HttpAuthCB, 'get',
common.xmpp.NS_HTTP_AUTH)
con.RegisterHandler('iq', self._CommandExecuteCB, 'set',
common.xmpp.NS_COMMANDS)
con.RegisterHandler('iq', self._gMailNewMailCB, 'set',
common.xmpp.NS_GMAILNOTIFY)
con.RegisterHandler('iq', self._gMailQueryCB, 'result',
common.xmpp.NS_GMAILNOTIFY)
con.RegisterHandler('iq', self._DiscoverInfoGetCB, 'get',
common.xmpp.NS_DISCO_INFO)
con.RegisterHandler('iq', self._DiscoverItemsGetCB, 'get',
common.xmpp.NS_DISCO_ITEMS)
con.RegisterHandler('iq', self._ErrorCB, 'error')
con.RegisterHandler('iq', self._IqCB)
con.RegisterHandler('iq', self._StanzaArrivedCB)