Put message handlers in a class

darcs-hash:20070522172311-86b55-7109d61ce39481f12e1a02fe337a4b2bc92d8fdf.gz
This commit is contained in:
David Rousselie
2007-05-22 19:23:11 +02:00
parent 5896ca069c
commit 8b9858a5bf
2 changed files with 209 additions and 34 deletions

View File

@@ -205,35 +205,7 @@ class JCLComponent(Component, object):
self.handle_message) self.handle_message)
self.send_stanzas(self.account_manager.probe_all_accounts_presence()) self.send_stanzas(self.account_manager.probe_all_accounts_presence())
def password_msg_handler_filter(message): self.msg_handlers += [PasswordMessageHandler()]
name = message.get_to().node
bare_from_jid = unicode(message.get_from().bare())
accounts = Account.select(\
AND(Account.q.name == name, \
Account.q.user_jid == bare_from_jid))
if accounts.count() != 1:
print >>sys.stderr, "Account " + name + " for user " + bare_from_jid + " must be uniq"
_account = accounts[0]
if hasattr(_account, 'password') \
and hasattr(_account, 'waiting_password_reply') \
and re.compile("\[PASSWORD\]").search(message.get_subject()) \
is not None:
return accounts
else:
return None
def password_msg_handler(message, accounts):
_account = accounts[0]
lang_class = self.lang.get_lang_class_from_node(message.get_node())
_account.password = message.get_body()
_account.waiting_password_reply = False
msg = Message(from_jid = _account.jid, \
to_jid = message.get_from(), \
stanza_type = "normal", \
subject = lang_class.password_saved_for_session, \
body = lang_class.password_saved_for_session)
self.stream.send(msg)
self.msg_handlers += [(password_msg_handler, password_msg_handler_filter)]
def signal_handler(self, signum, frame): def signal_handler(self, signum, frame):
"""Stop method handler """Stop method handler
@@ -472,12 +444,14 @@ class JCLComponent(Component, object):
Handle password response message Handle password response message
""" """
self.__logger.debug("MESSAGE: " + message.get_body()) self.__logger.debug("MESSAGE: " + message.get_body())
result = []
self.db_connect() self.db_connect()
for (msg_handler, filter_func) in self.msg_handlers: for msg_handler in self.msg_handlers:
accounts = filter_func(message) accounts = msg_handler.filter(message)
if accounts is not None: if accounts is not None:
msg_handler(message, accounts) result += msg_handler.handle(message, self.lang, accounts)
self.db_disconnect() self.db_disconnect()
self.send_stanzas(result)
return 1 return 1
########################################################################### ###########################################################################
@@ -1118,3 +1092,57 @@ class AccountManager(object):
body = _account.default_lang_class.check_error_body \ body = _account.default_lang_class.check_error_body \
% (exception))) % (exception)))
return result return result
class MessageHandler(object):
"""Message handling class"""
def filter(self, message):
"""Filter account to be processed by the handler
return all accounts. DB connection might already be opened."""
accounts = Account.select()
return accounts
def handle(self, message, lang, accounts):
"""Apply actions to do on given accounts
Do nothing by default"""
return []
class PasswordMessageHandler(MessageHandler):
"""Handle password message"""
def __init__(self):
"""Ḧandler constructor"""
self.password_regexp = re.compile("\[PASSWORD\]")
def filter(self, message):
"""Return the uniq account associated with a name and user JID.
DB connection might already be opened."""
name = message.get_to().node
bare_from_jid = unicode(message.get_from().bare())
accounts = Account.select(\
AND(Account.q.name == name, \
Account.q.user_jid == bare_from_jid))
if accounts.count() != 1:
print >>sys.stderr, "Account " + name + " for user " + bare_from_jid + " must be uniq"
_account = accounts[0]
if hasattr(_account, 'password') \
and hasattr(_account, 'waiting_password_reply') \
and (getattr(_account, 'waiting_password_reply') == True) \
and self.password_regexp.search(message.get_subject()) \
is not None:
return accounts
else:
return None
def handle(self, message, lang, accounts):
"""Receive password for given account"""
_account = accounts[0]
lang_class = lang.get_lang_class_from_node(message.get_node())
_account.password = message.get_body()
_account.waiting_password_reply = False
return [Message(from_jid = _account.jid, \
to_jid = message.get_from(), \
stanza_type = "normal", \
subject = lang_class.password_saved_for_session, \
body = lang_class.password_saved_for_session)]

View File

@@ -40,7 +40,7 @@ from pyxmpp.presence import Presence
from pyxmpp.message import Message from pyxmpp.message import Message
from pyxmpp.jabber.dataforms import Form, Field, Option from pyxmpp.jabber.dataforms import Form, Field, Option
from jcl.jabber.component import JCLComponent from jcl.jabber.component import JCLComponent, MessageHandler, PasswordMessageHandler
from jcl.model import account from jcl.model import account
from jcl.model.account import Account from jcl.model.account import Account
from jcl.lang import Lang from jcl.lang import Lang
@@ -1983,8 +1983,155 @@ 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)
class MessageHandler_TestCase(unittest.TestCase):
def setUp(self):
self.handler = MessageHandler()
if os.path.exists(DB_PATH):
os.unlink(DB_PATH)
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
Account.createTable(ifNotExists = True)
del account.hub.threadConnection
def tearDown(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
Account.dropTable(ifExists = True)
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
account.hub.threadConnection.close()
del account.hub.threadConnection
if os.path.exists(DB_PATH):
os.unlink(DB_PATH)
def test_filter(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = Account(user_jid = "user1@test.com", \
name = "account11", \
jid = "account11@jcl.test.com")
account12 = Account(user_jid = "user1@test.com", \
name = "account12", \
jid = "account12@jcl.test.com")
accounts = self.handler.filter(None)
self.assertEquals(accounts.count(), 2)
del account.hub.threadConnection
def test_handle(self):
self.assertEquals(self.handler.handle(None, None, None), [])
class PasswordMessageHandler_TestCase(unittest.TestCase):
def setUp(self):
self.handler = PasswordMessageHandler()
if os.path.exists(DB_PATH):
os.unlink(DB_PATH)
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
Account.createTable(ifNotExists = True)
ExampleAccount.createTable(ifNotExists = True)
del account.hub.threadConnection
def tearDown(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
ExampleAccount.dropTable(ifExists = True)
Account.dropTable(ifExists = True)
del TheURIOpener.cachedURIs['sqlite://' + DB_URL]
account.hub.threadConnection.close()
del account.hub.threadConnection
if os.path.exists(DB_PATH):
os.unlink(DB_PATH)
def test_filter_waiting_password(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = ExampleAccount(user_jid = "user1@test.com", \
name = "account11", \
jid = "account11@jcl.test.com")
account11.waiting_password_reply = True
account12 = ExampleAccount(user_jid = "user1@test.com", \
name = "account12", \
jid = "account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \
to_jid = "account11@jcl.test.com", \
stanza_type = "normal", \
subject = "[PASSWORD]", \
body = "secret")
accounts = self.handler.filter(message)
self.assertEquals(accounts.count(), 1)
self.assertEquals(accounts[0].name, "account11")
del account.hub.threadConnection
def test_filter_not_waiting_password(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = ExampleAccount(user_jid = "user1@test.com", \
name = "account11", \
jid = "account11@jcl.test.com")
account11.waiting_password_reply = False
account12 = ExampleAccount(user_jid = "user1@test.com", \
name = "account12", \
jid = "account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \
to_jid = "account11@jcl.test.com", \
stanza_type = "normal", \
subject = "[PASSWORD]", \
body = "secret")
accounts = self.handler.filter(message)
self.assertEquals(accounts, None)
del account.hub.threadConnection
def test_filter_not_good_message(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = ExampleAccount(user_jid = "user1@test.com", \
name = "account11", \
jid = "account11@jcl.test.com")
account11.waiting_password_reply = True
account12 = ExampleAccount(user_jid = "user1@test.com", \
name = "account12", \
jid = "account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \
to_jid = "account11@jcl.test.com", \
stanza_type = "normal", \
subject = "[NOT GOOD MESSAGE]", \
body = "secret")
accounts = self.handler.filter(message)
self.assertEquals(accounts, None)
del account.hub.threadConnection
def test_filter_not_password_account(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = Account(user_jid = "user1@test.com", \
name = "account11", \
jid = "account11@jcl.test.com")
account12 = Account(user_jid = "user1@test.com", \
name = "account12", \
jid = "account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \
to_jid = "account11@jcl.test.com", \
stanza_type = "normal", \
subject = "[PASSWORD]", \
body = "secret")
accounts = self.handler.filter(message)
self.assertEquals(accounts, None)
del account.hub.threadConnection
def test_handle(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = ExampleAccount(user_jid = "user1@test.com", \
name = "account11", \
jid = "account11@jcl.test.com")
account12 = ExampleAccount(user_jid = "user1@test.com", \
name = "account12", \
jid = "account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \
to_jid = "account11@jcl.test.com", \
stanza_type = "normal", \
subject = "[PASSWORD]", \
body = "secret")
messages = self.handler.handle(message, Lang(), [account11])
self.assertEquals(len(messages), 1)
self.assertEquals(account11.password, "secret")
del account.hub.threadConnection
def suite(): def suite():
return unittest.makeSuite(JCLComponent_TestCase, 'test') suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(JCLComponent_TestCase, 'test'))
suite.addTest(unittest.makeSuite(MessageHandler_TestCase, 'test'))
suite.addTest(unittest.makeSuite(PasswordMessageHandler_TestCase, 'test'))
return suite
if __name__ == '__main__': if __name__ == '__main__':
unittest.main(defaultTest='suite') unittest.main(defaultTest='suite')