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.dataforms import Form, Field
import jcl
from jcl.jabber import DiscoHandler
from jcl.model.account import Account
COMMAND_NS = "http://jabber.org/protocol/commands"
class CommandManager(object):
"""Handle Ad-Hoc commands"""
@@ -62,6 +66,14 @@ class CommandManager(object):
else:
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()
class JCLCommandManager(CommandManager):
@@ -74,13 +86,37 @@ class JCLCommandManager(CommandManager):
def get_list_info(self, disco_info, lang_class):
"""Return infos for 'list' command"""
disco_info.add_feature("http://jabber.org/protocol/commands")
disco_info.add_feature(COMMAND_NS)
DiscoIdentity(disco_info,
self.get_command_desc("list", lang_class),
"automation",
"command-node")
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):
"""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.handle_set_gateway)
self.stream.set_iq_set_handler("command", command.COMMAND_NS,
self.handle_command)
self.stream.set_presence_handler("available",
self.handle_presence_available)
@@ -568,6 +571,23 @@ class JCLComponent(Component, object):
self.apply_registered_behavior(self.msg_handlers, message, False)
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
###########################################################################
@@ -575,7 +595,6 @@ class JCLComponent(Component, object):
""" """
self.send_stanzas(self.account_manager.send_error(_account, exception))
type, value, stack = sys.exc_info()
# TODO : not checking email here
self.__logger.debug("Error: %s\n%s"
% (exception, "".join(traceback.format_exception
(type, value, stack, 5))))
@@ -641,7 +660,7 @@ class AccountManager(object):
if not node:
disco_info = DiscoInfo()
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:
disco_info.add_feature("jabber:iq:register")
DiscoIdentity(disco_info, name,

View File

@@ -73,13 +73,14 @@ class MockStream(object):
self.sent.append(iq)
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)
if not ns in ["jabber:iq:version",
"jabber:iq:register",
"jabber:iq:gateway",
"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)
if handler is None:
raise Exception("Handler must not be None")
@@ -744,7 +745,7 @@ class JCLComponent_TestCase(unittest.TestCase):
item = disco_items.get_items()[0]
self.assertEquals(item.get_node(), "list")
self.assertEquals(item.get_name(), Lang.en.command_list)
###########################################################################
# 'handle_get_version' tests
###########################################################################
@@ -2485,6 +2486,45 @@ class JCLComponent_TestCase(unittest.TestCase):
self.comp.send_stanzas(None)
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):
def setUp(self):
self.handler = Handler()