Implement 'list' ad-hoc command

darcs-hash:20070627060637-86b55-c56b45c11cfd4d264ae5c5f351e1f201c222dff1.gz
This commit is contained in:
David Rousselie
2007-06-27 08:06:37 +02:00
parent 04a0292285
commit db47f17ea9
3 changed files with 101 additions and 6 deletions

View File

@@ -21,9 +21,13 @@
## ##
from pyxmpp.jabber.disco import DiscoInfo, DiscoItems, DiscoItem, DiscoIdentity from pyxmpp.jabber.disco import DiscoInfo, DiscoItems, DiscoItem, DiscoIdentity
from pyxmpp.jabber.dataforms import Form, Field
import jcl import jcl
from jcl.jabber import DiscoHandler from jcl.jabber import DiscoHandler
from jcl.model.account import Account
COMMAND_NS = "http://jabber.org/protocol/commands"
class CommandManager(object): class CommandManager(object):
"""Handle Ad-Hoc commands""" """Handle Ad-Hoc commands"""
@@ -62,6 +66,14 @@ class CommandManager(object):
else: else:
return disco_info return disco_info
def apply_command_action(self, info_query, command, action):
"""Apply action on command"""
action_command_method = action + "_" + command
if hasattr(self, action_command_method):
return getattr(self, action_command_method)(info_query)
else:
return None
command_manager = CommandManager() command_manager = CommandManager()
class JCLCommandManager(CommandManager): class JCLCommandManager(CommandManager):
@@ -74,13 +86,37 @@ class JCLCommandManager(CommandManager):
def get_list_info(self, disco_info, lang_class): def get_list_info(self, disco_info, lang_class):
"""Return infos for 'list' command""" """Return infos for 'list' command"""
disco_info.add_feature("http://jabber.org/protocol/commands") disco_info.add_feature(COMMAND_NS)
DiscoIdentity(disco_info, DiscoIdentity(disco_info,
self.get_command_desc("list", lang_class), self.get_command_desc("list", lang_class),
"automation", "automation",
"command-node") "command-node")
return disco_info return disco_info
def execute_list(self, info_query):
"""Execute command 'list'. List accounts"""
response = info_query.make_result_response()
command_node = response.set_new_content(COMMAND_NS, "command")
command_node.setProp("node", "list")
command_node.setProp("status", "completed")
#command_node.setProp("sessionid", "????") # TODO
result_form = Form(xmlnode_or_type="result",
title="Registered account") # TODO : add to Lang
result_form.reported_fields.append(Field(name="name",
field_type="fixed",
label="Account name")) # TODO: add to Lang
bare_from_jid = unicode(info_query.get_from().bare())
self.account_manager.db_connect()
accounts = Account.select(Account.q.user_jid == bare_from_jid)
for _account in accounts:
fields = [Field(name="name",
field_type="fixed",
value=_account.name)]
result_form.add_item(fields)
self.account_manager.db_disconnect()
result_form.as_xml(command_node)
return [response]
class CommandDiscoGetInfoHandler(DiscoHandler): class CommandDiscoGetInfoHandler(DiscoHandler):
"""Handle Ad-Hoc command disco get info requests""" """Handle Ad-Hoc command disco get info requests"""

View File

@@ -200,6 +200,9 @@ class JCLComponent(Component, object):
self.stream.set_iq_set_handler("query", "jabber:iq:gateway", self.stream.set_iq_set_handler("query", "jabber:iq:gateway",
self.handle_set_gateway) self.handle_set_gateway)
self.stream.set_iq_set_handler("command", command.COMMAND_NS,
self.handle_command)
self.stream.set_presence_handler("available", self.stream.set_presence_handler("available",
self.handle_presence_available) self.handle_presence_available)
@@ -568,6 +571,23 @@ class JCLComponent(Component, object):
self.apply_registered_behavior(self.msg_handlers, message, False) self.apply_registered_behavior(self.msg_handlers, message, False)
return 1 return 1
def handle_command(self, info_query):
"""
Handle command IQ
"""
self.__logger.debug("COMMAND")
_command = info_query.xpath_eval("c:command",
{"c": command.COMMAND_NS})[0]
command_node = _command.prop("node")
action = _command.prop("action")
if action is None:
action = "execute"
result = command.command_manager.apply_command_action(info_query,
command_node,
action)
self.send_stanzas(result)
return 1
########################################################################### ###########################################################################
# Utils # Utils
########################################################################### ###########################################################################
@@ -575,7 +595,6 @@ class JCLComponent(Component, object):
""" """ """ """
self.send_stanzas(self.account_manager.send_error(_account, exception)) self.send_stanzas(self.account_manager.send_error(_account, exception))
type, value, stack = sys.exc_info() type, value, stack = sys.exc_info()
# TODO : not checking email here
self.__logger.debug("Error: %s\n%s" self.__logger.debug("Error: %s\n%s"
% (exception, "".join(traceback.format_exception % (exception, "".join(traceback.format_exception
(type, value, stack, 5)))) (type, value, stack, 5))))
@@ -641,7 +660,7 @@ class AccountManager(object):
if not node: if not node:
disco_info = DiscoInfo() disco_info = DiscoInfo()
disco_info.add_feature("jabber:iq:version") disco_info.add_feature("jabber:iq:version")
disco_info.add_feature("http://jabber.org/protocol/commands") disco_info.add_feature(command.COMMAND_NS)
if not self.has_multiple_account_type: if not self.has_multiple_account_type:
disco_info.add_feature("jabber:iq:register") disco_info.add_feature("jabber:iq:register")
DiscoIdentity(disco_info, name, DiscoIdentity(disco_info, name,

View File

@@ -73,13 +73,14 @@ class MockStream(object):
self.sent.append(iq) self.sent.append(iq)
def set_iq_set_handler(self, iq_type, ns, handler): def set_iq_set_handler(self, iq_type, ns, handler):
if not iq_type in ["query"]: if not iq_type in ["query", "command"]:
raise Exception("IQ type unknown: " + iq_type) raise Exception("IQ type unknown: " + iq_type)
if not ns in ["jabber:iq:version", if not ns in ["jabber:iq:version",
"jabber:iq:register", "jabber:iq:register",
"jabber:iq:gateway", "jabber:iq:gateway",
"http://jabber.org/protocol/disco#items", "http://jabber.org/protocol/disco#items",
"http://jabber.org/protocol/disco#info"]: "http://jabber.org/protocol/disco#info",
"http://jabber.org/protocol/commands"]:
raise Exception("Unknown namespace: " + ns) raise Exception("Unknown namespace: " + ns)
if handler is None: if handler is None:
raise Exception("Handler must not be None") raise Exception("Handler must not be None")
@@ -744,7 +745,7 @@ class JCLComponent_TestCase(unittest.TestCase):
item = disco_items.get_items()[0] item = disco_items.get_items()[0]
self.assertEquals(item.get_node(), "list") self.assertEquals(item.get_node(), "list")
self.assertEquals(item.get_name(), Lang.en.command_list) self.assertEquals(item.get_name(), Lang.en.command_list)
########################################################################### ###########################################################################
# 'handle_get_version' tests # 'handle_get_version' tests
########################################################################### ###########################################################################
@@ -2485,6 +2486,45 @@ class JCLComponent_TestCase(unittest.TestCase):
self.comp.send_stanzas(None) self.comp.send_stanzas(None)
self.assertEquals(len(self.comp.stream.sent), 0) self.assertEquals(len(self.comp.stream.sent), 0)
###########################################################################
# 'handle_command' tests
###########################################################################
def test_handle_command_execute_list(self):
self.comp.stream = MockStream()
self.comp.stream_class = MockStream
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = ExampleAccount(user_jid="user1@test.com",
name="account11",
jid="account11@jcl.test.com")
account12 = Example2Account(user_jid="user1@test.com",
name="account12",
jid="account12@jcl.test.com")
account2 = ExampleAccount(user_jid="user2@test.com",
name="account2",
jid="account2@jcl.test.com")
del account.hub.threadConnection
info_query = Iq(stanza_type="set",
from_jid="user1@test.com",
to_jid="jcl.test.com")
command_node = info_query.set_new_content("http://jabber.org/protocol/commands",
"command")
command_node.setProp("node", "list")
command_node.setProp("action", "execute")
self.comp.handle_command(info_query)
result = self.comp.stream.sent
self.assertNotEquals(result, None)
self.assertEquals(len(result), 1)
command_result = result[0].xpath_eval("c:command",
{"c": "http://jabber.org/protocol/commands"})
self.assertEquals(len(command_result), 1)
self.assertEquals(command_result[0].prop("status"), "completed")
# TODO : test sessionid prop, usage (cf XEP) ?
items = result[0].xpath_eval("c:command/data:x/data:item",
{"c": "http://jabber.org/protocol/commands",
"data": "jabber:x:data"})
self.assertEquals(len(items), 2)
class Handler_TestCase(unittest.TestCase): class Handler_TestCase(unittest.TestCase):
def setUp(self): def setUp(self):
self.handler = Handler() self.handler = Handler()