Modules refactoring

darcs-hash:20070627195955-86b55-e43dd68a84f08386389049c9e36bdbd9d46ea11d.gz
This commit is contained in:
David Rousselie
2007-06-27 21:59:55 +02:00
parent 9809356f36
commit a9534ee40f
6 changed files with 189 additions and 116 deletions

View File

@@ -7,14 +7,18 @@ class Handler(object):
"""handling class""" """handling class"""
def filter(self, stanza, lang_class): def filter(self, stanza, lang_class):
"""Filter account to be processed by the handler """
return all accounts. DB connection might already be opened.""" Filter account to be processed by the handler
return all accounts. DB connection might already be opened.
"""
accounts = Account.select() accounts = Account.select()
return accounts return accounts
def handle(self, stanza, lang_class, accounts): def handle(self, stanza, lang_class, data):
"""Apply actions to do on given accounts """
Do nothing by default""" Apply actions to do on given accounts
Do nothing by default.
"""
return [] return []
class DiscoHandler(object): class DiscoHandler(object):
@@ -24,6 +28,6 @@ class DiscoHandler(object):
"""Filter requests to be handled""" """Filter requests to be handled"""
return False return False
def handle(self, disco_items, node, info_query, data, lang_class): def handle(self, node, info_query, lang_class, disco_items, data):
"""Handle disco get items request""" """Handle disco get items request"""
return None return None

View File

@@ -21,7 +21,8 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## ##
"""JCL base component """
JCL base component
""" """
__revision__ = "$Id: component.py,v 1.3 2005/09/18 20:24:07 dax Exp $" __revision__ = "$Id: component.py,v 1.3 2005/09/18 20:24:07 dax Exp $"
@@ -50,8 +51,9 @@ from pyxmpp.presence import Presence
from pyxmpp.jabber.dataforms import Form, Field, Option from pyxmpp.jabber.dataforms import Form, Field, Option
import jcl import jcl
from jcl.jabber import Handler
from jcl.error import FieldError from jcl.error import FieldError
from jcl.jabber import Handler
from jcl.jabber.message import PasswordMessageHandler
import jcl.jabber.command as command import jcl.jabber.command as command
from jcl.jabber.command import CommandDiscoGetItemsHandler, \ from jcl.jabber.command import CommandDiscoGetItemsHandler, \
CommandDiscoGetInfoHandler, CommandManager, JCLCommandManager CommandDiscoGetInfoHandler, CommandManager, JCLCommandManager
@@ -283,10 +285,10 @@ class JCLComponent(Component, object):
for handler in handlers: for handler in handlers:
try: try:
self.__logger.debug("Applying filter " + repr(handler)) self.__logger.debug("Applying filter " + repr(handler))
accounts = handler.filter(stanza, lang) data = handler.filter(stanza, lang)
if accounts is not None: if data:
self.__logger.debug("Applying handler " + repr(handler)) self.__logger.debug("Applying handler " + repr(handler))
result += handler.handle(stanza, lang, accounts) result += handler.handle(stanza, lang, data)
if not apply_all: if not apply_all:
break break
except Exception, e: except Exception, e:
@@ -1276,82 +1278,3 @@ class AccountManager(object):
body=_account.default_lang_class.error_body \ body=_account.default_lang_class.error_body \
% (exception))) % (exception)))
return result return result
class DefaultPresenceHandler(Handler):
"""Handle presence"""
def handle(self, presence, lang_class, accounts):
"""Return same presence as receive one"""
to_jid = presence.get_to()
from_jid = presence.get_from()
presence.set_to(from_jid)
presence.set_from(to_jid)
return [presence]
class DefaultSubscribeHandler(Handler):
"""Return default response to subscribe queries"""
def handle(self, stanza, lang_class, accounts):
"""Create subscribe response"""
result = []
result.append(Presence(from_jid=stanza.get_to(),
to_jid=stanza.get_from(),
stanza_type="subscribe"))
result.append(Presence(from_jid=stanza.get_to(),
to_jid=stanza.get_from(),
stanza_type="subscribed"))
return result
class DefaultUnsubscribeHandler(Handler):
"""Return default response to subscribe queries"""
def handle(self, stanza, lang_class, accounts):
"""Create subscribe response"""
result = []
result.append(Presence(from_jid=stanza.get_to(),
to_jid=stanza.get_from(),
stanza_type="unsubscribe"))
result.append(Presence(from_jid=stanza.get_to(),
to_jid=stanza.get_from(),
stanza_type="unsubscribed"))
return result
class PasswordMessageHandler(Handler):
"""Handle password message"""
def __init__(self):
"""handler constructor"""
self.password_regexp = re.compile("\[PASSWORD\]")
def filter(self, stanza, lang_class):
"""Return the uniq account associated with a name and user JID.
DB connection might already be opened."""
name = stanza.get_to().node
bare_from_jid = unicode(stanza.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"
elif accounts.count() == 0:
return None
_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(stanza.get_subject()) \
is not None:
return accounts
else:
return None
def handle(self, stanza, lang_class, accounts):
"""Receive password in stanza (must be a Message) for given account"""
_account = accounts[0]
_account.password = stanza.get_body()
_account.waiting_password_reply = False
return [Message(from_jid=_account.jid,
to_jid=stanza.get_from(),
subject=lang_class.password_saved_for_session,
body=lang_class.password_saved_for_session)]

View File

@@ -36,10 +36,13 @@ from jcl.model.account import Account
from pyxmpp.message import Message from pyxmpp.message import Message
class FeederComponent(JCLComponent): class FeederComponent(JCLComponent):
"""Implement a feeder sender behavior based on the """
Implement a feeder sender behavior based on the
regular interval behavior of JCLComponent regular interval behavior of JCLComponent
feed data from given Feeder and send it to user feed data from given Feeder and send it to user
through the given Sender.""" through the given Sender.
"""
def __init__(self, def __init__(self,
jid, jid,
secret, secret,
@@ -121,7 +124,8 @@ class HeadlineSender(MessageSender):
body=body) body=body)
class FeederHandler(Handler): class FeederHandler(Handler):
"""Filter (nothing by default) and call sender for each message from """
Filter (nothing by default) and call sender for each message from
Feeder. Feeder.
""" """
@@ -131,18 +135,20 @@ class FeederHandler(Handler):
self.sender = sender self.sender = sender
def filter(self, stanza, lang_class): def filter(self, stanza, lang_class):
"""Filter account to be processed by the handler """
Filter account to be processed by the handler
return all accounts. return all accounts.
""" """
accounts = Account.select(clauseTables=["account"], accounts = Account.select(clauseTables=["account"],
orderBy="user_jid") orderBy="user_jid")
return accounts return accounts
def handle(self, stanza, lang_class, accounts): def handle(self, stanza, lang_class, data):
"""Apply actions to do on given accounts """
Apply actions to do on given accounts
Do nothing by default. Do nothing by default.
""" """
for _account in accounts: for _account in data:
for data in self.feeder.feed(_account): for data in self.feeder.feed(_account):
self.sender.send(_account, data) self.sender.send(_account, data)
return [] return []

72
src/jcl/jabber/message.py Normal file
View File

@@ -0,0 +1,72 @@
##
## message.py
## Login : David Rousselie <dax@happycoders.org>
## Started on Wed Jun 27 21:43:57 2007 David Rousselie
## $Id$
##
## Copyright (C) 2007 David Rousselie
## This program 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.
##
## This program 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 this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
import re
from pyxmpp.message import Message
from jcl.jabber import Handler
from jcl.model.account import Account
class PasswordMessageHandler(Handler):
"""Handle password message"""
def __init__(self):
"""handler constructor"""
self.password_regexp = re.compile("\[PASSWORD\]")
def filter(self, stanza, lang_class):
"""
Return the uniq account associated with a name and user JID.
DB connection might already be opened.
"""
name = stanza.get_to().node
bare_from_jid = unicode(stanza.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"
elif accounts.count() == 0:
return None
_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(stanza.get_subject()) \
is not None:
return accounts
else:
return None
def handle(self, stanza, lang_class, data):
"""
Receive password in stanza (must be a Message) for given account.
"""
_account = data[0]
_account.password = stanza.get_body()
_account.waiting_password_reply = False
return [Message(from_jid=_account.jid,
to_jid=stanza.get_from(),
subject=lang_class.password_saved_for_session,
body=lang_class.password_saved_for_session)]

View File

@@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
##
## component.py
## Login : David Rousselie <dax@happycoders.org>
## Started on Wed Jun 27 21:42:47 2007 David Rousselie
## $Id$
##
## Copyright (C) 2006 David Rousselie
## This program 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.
##
## This program 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 this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
from pyxmpp.presence import Presence
from jcl.jabber import Handler
class DefaultPresenceHandler(Handler):
"""Handle presence"""
def handle(self, presence, lang_class, data):
"""Return same presence as receive one"""
to_jid = presence.get_to()
from_jid = presence.get_from()
presence.set_to(from_jid)
presence.set_from(to_jid)
return [presence]
class DefaultSubscribeHandler(Handler):
"""Return default response to subscribe queries"""
def handle(self, stanza, lang_class, data):
"""Create subscribe response"""
result = []
result.append(Presence(from_jid=stanza.get_to(),
to_jid=stanza.get_from(),
stanza_type="subscribe"))
result.append(Presence(from_jid=stanza.get_to(),
to_jid=stanza.get_from(),
stanza_type="subscribed"))
return result
class DefaultUnsubscribeHandler(Handler):
"""Return default response to subscribe queries"""
def handle(self, stanza, lang_class, data):
"""Create subscribe response"""
result = []
result.append(Presence(from_jid=stanza.get_to(),
to_jid=stanza.get_from(),
stanza_type="unsubscribe"))
result.append(Presence(from_jid=stanza.get_to(),
to_jid=stanza.get_from(),
stanza_type="unsubscribed"))
return result

View File

@@ -41,8 +41,9 @@ 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, Handler, \ from jcl.jabber.component import JCLComponent, Handler
PasswordMessageHandler, DefaultSubscribeHandler, \ from jcl.jabber.message import PasswordMessageHandler
from jcl.jabber.presence import DefaultSubscribeHandler, \
DefaultUnsubscribeHandler, DefaultPresenceHandler DefaultUnsubscribeHandler, DefaultPresenceHandler
from jcl.model import account from jcl.model import account
from jcl.model.account import Account, LegacyJID from jcl.model.account import Account, LegacyJID
@@ -154,12 +155,12 @@ class HandlerMock(object):
def __init__(self): def __init__(self):
self.handled = [] self.handled = []
def filter(self, message, lang_class): def filter(self, stanza, lang_class):
return [] return []
def handle(self, stanza, lang_class, accounts): def handle(self, stanza, lang_class, data):
self.handled.append((stanza, lang_class, accounts)) self.handled.append((stanza, lang_class, data))
return [(stanza, lang_class, accounts)] return [(stanza, lang_class, data)]
class JCLComponent_TestCase(unittest.TestCase): class JCLComponent_TestCase(unittest.TestCase):
########################################################################### ###########################################################################
@@ -1688,24 +1689,25 @@ class JCLComponent_TestCase(unittest.TestCase):
self.comp.stream_class = MockStream self.comp.stream_class = MockStream
self.comp.available_handlers += [DefaultPresenceHandler()] self.comp.available_handlers += [DefaultPresenceHandler()]
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = Account(user_jid = "user1@test.com", \ account11 = Account(user_jid="user1@test.com",
name = "account11", \ name="account11",
jid = "account11@jcl.test.com") jid="account11@jcl.test.com")
account12 = Account(user_jid = "user1@test.com", \ account12 = Account(user_jid="user1@test.com",
name = "account12", \ name="account12",
jid = "account12@jcl.test.com") jid="account12@jcl.test.com")
account2 = Account(user_jid = "user2@test.com", \ account2 = Account(user_jid="user2@test.com",
name = "account2", \ name="account2",
jid = "account2@jcl.test.com") jid="account2@jcl.test.com")
del account.hub.threadConnection del account.hub.threadConnection
self.comp.handle_presence_available(Presence(\ self.comp.handle_presence_available(Presence(\
stanza_type = "available", \ stanza_type="available",
from_jid = "user1@test.com",\ from_jid="user1@test.com",
to_jid = "user1%test.com@jcl.test.com")) to_jid="user1%test.com@jcl.test.com"))
presence_sent = self.comp.stream.sent presence_sent = self.comp.stream.sent
self.assertEqual(len(presence_sent), 1) self.assertEqual(len(presence_sent), 1)
self.assertEqual(presence_sent[0].get_to(), "user1@test.com") self.assertEqual(presence_sent[0].get_to(), "user1@test.com")
self.assertEqual(presence_sent[0].get_from(), "user1%test.com@jcl.test.com") self.assertEqual(presence_sent[0].get_from(),
"user1%test.com@jcl.test.com")
self.assertTrue(isinstance(presence_sent[0], Presence)) self.assertTrue(isinstance(presence_sent[0], Presence))
self.assertEqual(presence_sent[0].get_type(), None) self.assertEqual(presence_sent[0].get_type(), None)