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 = common.xmpp.Node('feature')
|
||||||
feature.setAttr('var', common.xmpp.NS_FILE)
|
feature.setAttr('var', common.xmpp.NS_FILE)
|
||||||
query.addChild(node=feature)
|
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)
|
self.connection.send(iq)
|
||||||
raise common.xmpp.NodeProcessed
|
raise common.xmpp.NodeProcessed
|
||||||
|
@ -692,8 +696,22 @@ class ConnectionDisco:
|
||||||
else:
|
else:
|
||||||
self.dispatch('AGENT_INFO_ITEMS', (jid, node, items))
|
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):
|
def _DiscoverInfoGetCB(self, con, iq_obj):
|
||||||
gajim.log.debug('DiscoverInfoGetCB')
|
gajim.log.debug('DiscoverInfoGetCB')
|
||||||
|
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')
|
iq = iq_obj.buildReply('result')
|
||||||
q = iq.getTag('query')
|
q = iq.getTag('query')
|
||||||
q.addChild('identity', attrs = {'type': 'pc',
|
q.addChild('identity', attrs = {'type': 'pc',
|
||||||
|
@ -1036,11 +1054,124 @@ class ConnectionVcard:
|
||||||
else:
|
else:
|
||||||
self.dispatch('VCARD', vcard)
|
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):
|
def __init__(self):
|
||||||
ConnectionVcard.__init__(self)
|
ConnectionVcard.__init__(self)
|
||||||
ConnectionBytestream.__init__(self)
|
ConnectionBytestream.__init__(self)
|
||||||
|
ConnectionCommands.__init__(self)
|
||||||
# List of IDs we are waiting answers for {id: (type_of_request, data), }
|
# List of IDs we are waiting answers for {id: (type_of_request, data), }
|
||||||
self.awaiting_answers = {}
|
self.awaiting_answers = {}
|
||||||
# List of IDs that will produce a timeout is answer doesn't arrive
|
# 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)
|
common.xmpp.NS_PRIVATE)
|
||||||
con.RegisterHandler('iq', self._HttpAuthCB, 'get',
|
con.RegisterHandler('iq', self._HttpAuthCB, 'get',
|
||||||
common.xmpp.NS_HTTP_AUTH)
|
common.xmpp.NS_HTTP_AUTH)
|
||||||
|
con.RegisterHandler('iq', self._CommandExecuteCB, 'set',
|
||||||
|
common.xmpp.NS_COMMANDS)
|
||||||
con.RegisterHandler('iq', self._gMailNewMailCB, 'set',
|
con.RegisterHandler('iq', self._gMailNewMailCB, 'set',
|
||||||
common.xmpp.NS_GMAILNOTIFY)
|
common.xmpp.NS_GMAILNOTIFY)
|
||||||
con.RegisterHandler('iq', self._gMailQueryCB, 'result',
|
con.RegisterHandler('iq', self._gMailQueryCB, 'result',
|
||||||
common.xmpp.NS_GMAILNOTIFY)
|
common.xmpp.NS_GMAILNOTIFY)
|
||||||
con.RegisterHandler('iq', self._DiscoverInfoGetCB, 'get',
|
con.RegisterHandler('iq', self._DiscoverInfoGetCB, 'get',
|
||||||
common.xmpp.NS_DISCO_INFO)
|
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._ErrorCB, 'error')
|
||||||
con.RegisterHandler('iq', self._IqCB)
|
con.RegisterHandler('iq', self._IqCB)
|
||||||
con.RegisterHandler('iq', self._StanzaArrivedCB)
|
con.RegisterHandler('iq', self._StanzaArrivedCB)
|
||||||
|
|
Loading…
Add table
Reference in a new issue