Generic support for exposing commands (untested).
This commit is contained in:
parent
76c7831c49
commit
477f33b6b9
1 changed files with 147 additions and 12 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue