Implement 'list' ad-hoc command
darcs-hash:20070627060637-86b55-c56b45c11cfd4d264ae5c5f351e1f201c222dff1.gz
This commit is contained in:
@@ -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"""
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user