2009-06-03 22:56:51 +00:00
|
|
|
"""
|
|
|
|
SleekXMPP: The Sleek XMPP Library
|
|
|
|
Copyright (C) 2007 Nathanael C. Fritz
|
|
|
|
This file is part of SleekXMPP.
|
|
|
|
|
|
|
|
SleekXMPP is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
SleekXMPP is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with SleekXMPP; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
"""
|
|
|
|
from __future__ import with_statement
|
2009-08-31 22:46:31 +00:00
|
|
|
from . import base
|
2009-06-03 22:56:51 +00:00
|
|
|
import logging
|
|
|
|
from xml.etree import cElementTree as ET
|
|
|
|
import traceback
|
|
|
|
import time
|
|
|
|
|
|
|
|
class xep_0050(base.base_plugin):
|
|
|
|
"""
|
|
|
|
XEP-0050 Ad-Hoc Commands
|
|
|
|
"""
|
|
|
|
|
|
|
|
def plugin_init(self):
|
|
|
|
self.xep = '0050'
|
|
|
|
self.description = 'Ad-Hoc Commands'
|
|
|
|
self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='__None__'/></iq>" % self.xmpp.default_ns, self.handler_command)
|
|
|
|
self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='execute'/></iq>" % self.xmpp.default_ns, self.handler_command)
|
|
|
|
self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='next'/></iq>" % self.xmpp.default_ns, self.handler_command_next, threaded=True)
|
|
|
|
self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='cancel'/></iq>" % self.xmpp.default_ns, self.handler_command_cancel)
|
|
|
|
self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='complete'/></iq>" % self.xmpp.default_ns, self.handler_command_complete)
|
|
|
|
self.commands = {}
|
|
|
|
self.sessions = {}
|
2009-10-29 02:34:23 +00:00
|
|
|
self.sd = self.xmpp.plugin['xep_0030']
|
2009-06-03 22:56:51 +00:00
|
|
|
|
|
|
|
def post_init(self):
|
2009-10-29 02:34:23 +00:00
|
|
|
self.sd.add_feature('http://jabber.org/protocol/commands')
|
2009-06-03 22:56:51 +00:00
|
|
|
|
|
|
|
def addCommand(self, node, name, form, pointer=None, multi=False):
|
2009-10-29 02:34:23 +00:00
|
|
|
self.sd.add_item(None, name, 'http://jabber.org/protocol/commands', node)
|
|
|
|
self.sd.add_identity('automation', 'command-node', name, node)
|
|
|
|
self.sd.add_feature('http://jabber.org/protocol/commands', node)
|
|
|
|
self.sd.add_feature('jabber:x:data', node)
|
2009-06-03 22:56:51 +00:00
|
|
|
self.commands[node] = (name, form, pointer, multi)
|
|
|
|
|
|
|
|
def getNewSession(self):
|
|
|
|
return str(time.time()) + '-' + self.xmpp.getNewId()
|
|
|
|
|
|
|
|
def handler_command(self, xml):
|
|
|
|
in_command = xml.find('{http://jabber.org/protocol/commands}command')
|
|
|
|
sessionid = in_command.get('sessionid', None)
|
|
|
|
node = in_command.get('node')
|
|
|
|
sessionid = self.getNewSession()
|
|
|
|
name, form, pointer, multi = self.commands[node]
|
|
|
|
self.sessions[sessionid] = {}
|
|
|
|
self.sessions[sessionid]['jid'] = xml.get('from')
|
|
|
|
self.sessions[sessionid]['past'] = [(form, None)]
|
|
|
|
self.sessions[sessionid]['next'] = pointer
|
|
|
|
npointer = pointer
|
|
|
|
if multi:
|
|
|
|
actions = ['next']
|
|
|
|
status = 'executing'
|
|
|
|
else:
|
|
|
|
if pointer is None:
|
|
|
|
status = 'completed'
|
|
|
|
actions = []
|
|
|
|
else:
|
|
|
|
status = 'executing'
|
|
|
|
actions = ['complete']
|
|
|
|
self.xmpp.send(self.makeCommand(xml.attrib['from'], in_command.attrib['node'], form=form, id=xml.attrib['id'], sessionid=sessionid, status=status, actions=actions))
|
|
|
|
|
|
|
|
def handler_command_complete(self, xml):
|
|
|
|
in_command = xml.find('{http://jabber.org/protocol/commands}command')
|
|
|
|
sessionid = in_command.get('sessionid', None)
|
|
|
|
pointer = self.sessions[sessionid]['next']
|
2009-10-29 02:34:23 +00:00
|
|
|
results = self.xmpp.plugin['xep_0004'].makeForm('result')
|
2009-06-03 22:56:51 +00:00
|
|
|
results.fromXML(in_command.find('{jabber:x:data}x'))
|
2009-10-05 18:18:37 +00:00
|
|
|
pointer(results,sessionid)
|
2009-06-03 22:56:51 +00:00
|
|
|
self.xmpp.send(self.makeCommand(xml.attrib['from'], in_command.attrib['node'], form=None, id=xml.attrib['id'], sessionid=sessionid, status='completed', actions=[]))
|
2009-07-11 18:20:47 +00:00
|
|
|
del self.sessions[in_command.get('sessionid')]
|
2009-06-03 22:56:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
def handler_command_next(self, xml):
|
|
|
|
in_command = xml.find('{http://jabber.org/protocol/commands}command')
|
|
|
|
sessionid = in_command.get('sessionid', None)
|
|
|
|
pointer = self.sessions[sessionid]['next']
|
2009-10-29 02:34:23 +00:00
|
|
|
results = self.xmpp.plugin['xep_0004'].makeForm('result')
|
2009-06-03 22:56:51 +00:00
|
|
|
results.fromXML(in_command.find('{jabber:x:data}x'))
|
2009-10-05 17:44:59 +00:00
|
|
|
form, npointer, next = pointer(results,sessionid)
|
2009-06-03 22:56:51 +00:00
|
|
|
self.sessions[sessionid]['next'] = npointer
|
|
|
|
self.sessions[sessionid]['past'].append((form, pointer))
|
|
|
|
actions = []
|
|
|
|
actions.append('prev')
|
|
|
|
if npointer is None:
|
|
|
|
status = 'completed'
|
|
|
|
else:
|
|
|
|
status = 'executing'
|
|
|
|
if next:
|
|
|
|
actions.append('next')
|
|
|
|
else:
|
|
|
|
actions.append('complete')
|
|
|
|
self.xmpp.send(self.makeCommand(xml.attrib['from'], in_command.attrib['node'], form=form, id=xml.attrib['id'], sessionid=sessionid, status=status, actions=actions))
|
|
|
|
|
|
|
|
def handler_command_cancel(self, xml):
|
|
|
|
command = xml.find('{http://jabber.org/protocol/commands}command')
|
|
|
|
try:
|
|
|
|
del self.sessions[command.get('sessionid')]
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
self.xmpp.send(self.makeCommand(xml.attrib['from'], command.attrib['node'], id=xml.attrib['id'], sessionid=command.attrib['sessionid'], status='canceled'))
|
|
|
|
|
|
|
|
def makeCommand(self, to, node, id=None, form=None, sessionid=None, status='executing', actions=[]):
|
|
|
|
if not id:
|
|
|
|
id = self.xmpp.getNewId()
|
|
|
|
iq = self.xmpp.makeIqResult(id)
|
|
|
|
iq.attrib['from'] = self.xmpp.fulljid
|
|
|
|
iq.attrib['to'] = to
|
|
|
|
command = ET.Element('{http://jabber.org/protocol/commands}command')
|
|
|
|
command.attrib['node'] = node
|
|
|
|
command.attrib['status'] = status
|
|
|
|
xmlactions = ET.Element('actions')
|
|
|
|
for action in actions:
|
|
|
|
xmlactions.append(ET.Element(action))
|
|
|
|
if xmlactions:
|
|
|
|
command.append(xmlactions)
|
|
|
|
if not sessionid:
|
|
|
|
sessionid = self.getNewSession()
|
|
|
|
command.attrib['sessionid'] = sessionid
|
|
|
|
if form is not None:
|
|
|
|
if hasattr(form,'getXML'):
|
|
|
|
form = form.getXML()
|
|
|
|
command.append(form)
|
|
|
|
iq.append(command)
|
|
|
|
return iq
|