From 12b03085728be65ff42ed4a01db148eceeefd710 Mon Sep 17 00:00:00 2001 From: David Rousselie Date: Mon, 14 Aug 2006 18:16:54 +0200 Subject: [PATCH] First JCLComponent implementation darcs-hash:20060814161654-86b55-e6f2553e9ebae6bb8b057795ddc4f53e449a5c68.gz --- run_tests.py | 12 +- src/jcl/jabber/component.py | 347 ++++++++++++++++++++++++++--- src/jcl/jabber/feeder.py | 70 ++++++ src/jcl/lang.py | 247 ++++++++++++++++++++ src/jcl/model/account.py | 2 +- tests/jcl/jabber/test_component.py | 161 +++++++++++++ tests/jcl/jabber/test_feeder.py | 29 ++- 7 files changed, 836 insertions(+), 32 deletions(-) create mode 100644 src/jcl/jabber/feeder.py create mode 100644 src/jcl/lang.py create mode 100644 tests/jcl/jabber/test_component.py diff --git a/run_tests.py b/run_tests.py index 70f44d1..1debef5 100644 --- a/run_tests.py +++ b/run_tests.py @@ -35,6 +35,7 @@ sys.setdefaultencoding('utf8') del sys.setdefaultencoding import tests +from tests.jcl.jabber.test_component import * from tests.jcl.jabber.test_feeder import * import jcl @@ -44,12 +45,19 @@ if __name__ == '__main__': logger.addHandler(logging.StreamHandler()) logger.setLevel(logging.INFO) + component_suite = unittest.makeSuite(JCLComponent_TestCase, "test") + feeder_component_suite = unittest.makeSuite(FeederComponent_TestCase, "test") feeder_suite = unittest.makeSuite(Feeder_TestCase, "test") + sender_suite = unittest.makeSuite(Sender_TestCase, "test") - jcl_suite = unittest.TestSuite((feeder_suite)) + jcl_suite = unittest.TestSuite((component_suite, + feeder_component_suite, + feeder_suite, + sender_suite)) test_support.run_suite(jcl_suite) coverage.stop() coverage.analysis(jcl.jabber.component) -coverage.report([jcl.jabber.component]) +coverage.analysis(jcl.jabber.feeder) +coverage.report([jcl.jabber.component, jcl.jabber.feeder]) diff --git a/src/jcl/jabber/component.py b/src/jcl/jabber/component.py index 3278294..ddbc803 100644 --- a/src/jcl/jabber/component.py +++ b/src/jcl/jabber/component.py @@ -21,30 +21,16 @@ ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## -from jcl.model.account import * +import logging +import signal from pyxmpp.jid import JID from pyxmpp.jabberd.component import Component +from pyxmpp.presence import Presence -class JabberComponent(object): - def __init__(self): - pass - -class Feeder(object): - def __init__(self): - pass - - def feed(self, account): - pass - -class Sender(object): - def __init__(self): - pass - - def send(self, to_account, message): - pass - +from jcl.model.account import Account +VERSION = "0.1" ############################################################################### # JCL implementation @@ -55,20 +41,327 @@ class JCLComponent(Component): secret, server, port, - check_interval, - spool_dir, - storage, - name, + name = "Jabber Component Library generic component", disco_category = "gateway", - disco_type = "headline"): + disco_type = "headline", + spool_dir = ".", + check_interval = 1, + account_class = Account): Component.__init__(self, \ JID(jid), \ secret, \ port, \ disco_category, \ disco_type) + self.__logger = logging.getLogger("jcl.jabber.JCLComponent") + # TODO : self.__lang = Lang(default_lang) + self.__name = name + self.__disco_category = disco_category + self.__disco_type = disco_type + self.__interval = check_interval + self.running = False + + self.__shutdown = 0 + + signal.signal(signal.SIGINT, self.signal_handler) + signal.signal(signal.SIGTERM, self.signal_handler) + spool_dir += "/" + jid + self.__account_class = account_class + self.__account_class.createTable(ifNotExists = True) + self.version = VERSION + + def authenticated(self): + Component.authenticated(self) + self.__logger.debug("AUTHENTICATED") + # Send probe for transport + current_jid = None + for account in self.__account_class.select(orderBy = "user_jid"): + if account.user_jid != current_jid: + p = Presence(from_jid = unicode(self.jid), \ + to_jid = account.user_jid, \ + stanza_type = "probe") + self.stream.send(p) + current_jid = account.user_jid + p = Presence(from_jid = self.get_jid(account), \ + to_jid = account.user_jid, \ + stanza_type = "probe") + self.stream.send(p) + + self.stream.set_iq_get_handler("query", "jabber:iq:version", \ + self.handle_get_version) + self.stream.set_iq_get_handler("query", "jabber:iq:register", \ + self.handle_get_register) + self.stream.set_iq_set_handler("query", "jabber:iq:register", \ + self.handle_set_register) + + self.stream.set_presence_handler("available", \ + self.handle_presence_available) + + self.stream.set_presence_handler("probe", \ + self.handle_presence_available) + + self.stream.set_presence_handler("unavailable", \ + self.handle_presence_unavailable) + + self.stream.set_presence_handler("unsubscribe", \ + self.handle_presence_unsubscribe) + self.stream.set_presence_handler("unsubscribed", \ + self.handle_presence_unsubscribed) + self.stream.set_presence_handler("subscribe", \ + self.handle_presence_subscribe) + self.stream.set_presence_handler("subscribed", \ + self.handle_presence_subscribed) + + self.stream.set_message_handler("normal", \ + self.handle_message) + + def run(self): + self.connect() + self.running = True + thread.start_new_thread(self.time_handler, ()) + try: + while (not self.__shutdown and self.stream + and not self.stream.eof and self.stream.socket is not None): + try: + self.stream.loop_iter(timeout) + except (KeyboardInterrupt, SystemExit, FatalStreamError, \ + StreamError): + raise + except: + self.__logger.exception("Exception cought:") + finally: + self.running = False + if self.stream: + # TODO : send unavailble from transport and all account to users + pass +# for jid in self.__storage.keys(()): +# p = Presence(from_jid = unicode(self.jid), to_jid = jid, \ +# stanza_type = "unavailable") +# self.stream.send(p) +# for jid, name in self.__storage.keys(): +# if self.__storage[(jid, name)].status != "offline": +# p = Presence(from_jid = name + "@" + unicode(self.jid), \ +# to_jid = jid, \ +# stanza_type = "unavailable") +# self.stream.send(p) + threads = threading.enumerate() + for th in threads: + try: + th.join(10 * timeout) + except: + pass + for th in threads: + try: + th.join(timeout) + except: + pass + self.disconnect() + # TODO : terminate SQLObject + self.__logger.debug("Exitting normally") + + def get_reg_form(self, lang_class, account_class): + pass + + def get_reg_form_init(self, lang_class, account): + pass + + def _ask_password(self, lang_class, account): + if not account.waiting_password_reply \ + and account.status != "offline": + account.waiting_password_reply = True + msg = Message(from_jid = account.jid, \ + to_jid = from_jid, \ + stanza_type = "normal", \ + subject = u"[PASSWORD] " + lang_class.ask_password_subject, \ + body = lang_class.ask_password_body % \ + (account.host, account.login)) + self.stream.send(msg) + + def get_jid(self, account): + return account.name + u"@" + unicode(self.jid) + + ## Handlers + + """ Stop method handler """ + def signal_handler(self, signum, frame): + self.__logger.debug("Signal %i received, shutting down..." % (signum,)) + self.__shutdown = 1 + + + def stream_state_changed(self,state,arg): + self.__logger.debug("*** State changed: %s %r ***" % (state,arg)) + + """ Discovery get info handler """ + def disco_get_info(self, node, iq): + self.__logger.debug("DISCO_GET_INFO") + di = DiscoInfo() + if node is None: + di.add_feature("jabber:iq:version") + di.add_feature("jabber:iq:register") + DiscoIdentity(di, self.__name, \ + self.__disco_category, \ + self.__disco_type) + else: + di.add_feature("jabber:iq:register") + return di + + """ Discovery get nested nodes handler """ + def disco_get_items(self, node, iq): + self.__logger.debug("DISCO_GET_ITEMS") +# lang_class = self.__lang.get_lang_class_from_node(iq.get_node()) + base_from_jid = unicode(iq.get_from().bare()) + di = DiscoItems() + if not node: + # TODO : list accounts + for account in self.__accounts: + pass +# DiscoItem(di, JID(name + "@" + unicode(self.jid)), \ +# name, str_name) + return di + + """ Get Version handler """ + def handle_get_version(self, iq): + self.__logger.debug("GET_VERSION") + iq = iq.make_result_response() + q = iq.new_query("jabber:iq:version") + q.newTextChild(q.ns(), "name", self.__name) + q.newTextChild(q.ns(), "version", self.version) + self.stream.send(iq) + return 1 + + """ Send back register form to user """ + def handle_get_register(self, iq): + self.__logger.debug("GET_REGISTER") +# lang_class = self.__lang.get_lang_class_from_node(iq.get_node()) + base_from_jid = unicode(iq.get_from().bare()) + to = iq.get_to() + iq = iq.make_result_response() + q = iq.new_query("jabber:iq:register") + if to and to != self.jid: + self.get_reg_form_init(lang_class, \ + self.__accounts.select() # TODO + ).attach_xml(q) + else: + self.get_reg_form(lang_class).attach_xml(q) + self.stream.send(iq) + return 1 + + """ Handle user registration response """ + def handle_set_register(self, iq): + self.__logger.debug("SET_REGISTER") + lang_class = self.__lang.get_lang_class_from_node(iq.get_node()) + to = iq.get_to() + from_jid = iq.get_from() + base_from_jid = unicode(from_jid.bare()) + remove = iq.xpath_eval("r:query/r:remove", \ + {"r" : "jabber:iq:register"}) + if remove: + for name in self.__storage.keys((base_from_jid,)): + self.__logger.debug("Deleting " + name + " for " + base_from_jid) + p = Presence(from_jid = name + "@" + unicode(self.jid), \ + to_jid = from_jid, \ + stanza_type = "unsubscribe") + self.stream.send(p) + p = Presence(from_jid = name + "@" + unicode(self.jid), \ + to_jid = from_jid, \ + stanza_type = "unsubscribed") + self.stream.send(p) + del self.__storage[(base_from_jid, name)] + p = Presence(from_jid = self.jid, to_jid = from_jid, \ + stanza_type = "unsubscribe") + self.stream.send(p) + p = Presence(from_jid = self.jid, to_jid = from_jid, \ + stanza_type = "unsubscribed") + self.stream.send(p) + return 1 + + query = iq.get_query() + x = X() + x.from_xml(query.children) + # TODO : get info from Xdata + + + """ Handle presence availability """ + def handle_presence_available(self, stanza): + self.__logger.debug("PRESENCE_AVAILABLE") + from_jid = stanza.get_from() + base_from_jid = unicode(from_jid.bare()) + name = stanza.get_to().node + lang_class = self.__lang.get_lang_class_from_node(stanza.get_node()) + show = stanza.get_show() + self.__logger.debug("SHOW : " + str(show)) + if name: + self.__logger.debug("TO : " + name + " " + base_from_jid) + # TODO : if to transport send back available to all user's account + # else send available presence + return 1 + + """ handle presence unavailability """ + def handle_presence_unavailable(self, stanza): + self.__logger.debug("PRESENCE_UNAVAILABLE") + from_jid = stanza.get_from() + base_from_jid = unicode(from_jid.bare()) + # TODO : send unavailable to all user's account if target is transport + # else send unavailable back + return 1 + + """ handle subscribe presence from user """ + def handle_presence_subscribe(self, stanza): + self.__logger.debug("PRESENCE_SUBSCRIBE") + p = stanza.make_accept_response() + self.stream.send(p) + return 1 + + """ handle subscribed presence from user """ + def handle_presence_subscribed(self, stanza): + self.__logger.debug("PRESENCE_SUBSCRIBED") + name = stanza.get_to().node + from_jid = stanza.get_from() + base_from_jid = unicode(from_jid.bare()) + # TODO : send presence available to subscribed user + return 1 + + """ handle unsubscribe presence from user """ + def handle_presence_unsubscribe(self, stanza): + self.__logger.debug("PRESENCE_UNSUBSCRIBE") + name = stanza.get_to().node + from_jid = stanza.get_from() + base_from_jid = unicode(from_jid.bare()) + # TODO : delete from account base + p = Presence(from_jid = stanza.get_to(), to_jid = from_jid, \ + stanza_type = "unsubscribe") + self.stream.send(p) + p = stanza.make_accept_response() + self.stream.send(p) + return 1 + + """ handle unsubscribed presence from user """ + def handle_presence_unsubscribed(self, stanza): + self.__logger.debug("PRESENCE_UNSUBSCRIBED") + p = Presence(from_jid = stanza.get_to(), \ + to_jid = stanza.get_from(), \ + stanza_type = "unavailable") + self.stream.send(p) + return 1 + + """ Handle new message """ + def handle_message(self, message): + self.__logger.debug("MESSAGE: " + message.get_body()) + lang_class = self.__lang.get_lang_class_from_node(message.get_node()) + name = message.get_to().node + base_from_jid = unicode(message.get_from().bare()) + if re.compile("\[PASSWORD\]").search(message.get_subject()) is not None: +# TODO and self.__storage.has_key((base_from_jid, name)): +# account = self.__storage[(base_from_jid, name)] + 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) + return 1 def handle_tick(self): - for account in Account.select("*"): - for message in self.__jabber_component.feeder.feed(account): - self.__jabber_component.sender.send(account, message) + pass diff --git a/src/jcl/jabber/feeder.py b/src/jcl/jabber/feeder.py new file mode 100644 index 0000000..f48ab48 --- /dev/null +++ b/src/jcl/jabber/feeder.py @@ -0,0 +1,70 @@ +# -*- coding: UTF-8 -*- +## +## component.py +## Login : David Rousselie +## Started on Wed Aug 9 21:04:42 2006 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 jcl.jabber.component import JCLComponent +from jcl.model.account import * + +class FeederComponent(JCLComponent): + def __init__(self, + jid, + secret, + server, + port, + name = "Generic Feeder Component", + disco_category = "gateway", + disco_type = "headline", + spool_dir = ".", + check_interval = 1): + JCLComponent.__init__(self, \ + jid, \ + secret, \ + server, \ + port, \ + name, \ + disco_category, \ + disco_type, \ + spool_dir, \ + check_interval) + + def handle_tick(self): + for account in Account.select("*"): + for message in self.__jabber_component.feeder.feed(account): + self.__jabber_component.sender.send(account, message) + + + +class Feeder(object): + def __init__(self): + pass + + def feed(self, account): + pass + + +class Sender(object): + def __init__(self): + pass + + def send(self, to_account, message): + pass + diff --git a/src/jcl/lang.py b/src/jcl/lang.py new file mode 100644 index 0000000..5aeb025 --- /dev/null +++ b/src/jcl/lang.py @@ -0,0 +1,247 @@ +# -*- coding: utf-8 -*- +## +## lang.py +## Login : David Rousselie +## Started on Sat Jan 28 16:37:11 2006 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 +## + +# TODO delete not JCL translation +class Lang: + def __init__(self, default_lang = "en"): + self.default_lang = default_lang + + def get_lang_from_node(self, node): + lang = node.getLang() + if lang is None: + print "Using default lang " + self.default_lang + lang = self.default_lang + return lang + + def get_lang_class(self, lang): + return getattr(Lang, lang) + + def get_lang_class_from_node(self, node): + return self.get_lang_class(self.get_lang_from_node(node)) + + class en: + register_title = u"Jabber Mail connection registration" + register_instructions = u"Enter connection parameters" + account_name = u"Connection name" + account_login = u"Login" + account_password = u"Password" + account_password_store = u"Store password on Jabber server?" + account_host = u"Host" + account_port = u"Port" + account_type = u"Mail server type" + account_mailbox = u"Mailbox path (IMAP)" + account_ffc_action = u"Action when state is 'Free For Chat'" + account_online_action = u"Action when state is 'Online'" + account_away_action = u"Action when state is 'Away'" + account_xa_action = u"Action when state is 'Not Available'" + account_dnd_action = u"Action when state is 'Do not Disturb'" + account_offline_action = u"Action when state is 'Offline'" + account_check_interval = u"Mail check interval (in minutes)" + account_live_email_only = u"Reports only emails received while connected to Jabber" + action_nothing = u"Do nothing" + action_retrieve = u"Retrieve mail" + action_digest = u"Send mail digest" + update_title = u"Jabber mail connection update" + update_instructions = u"Modifying connection '%s'" + connection_label = u"%s connection '%s'" + update_account_message_subject = u"Updated %s connection '%s'" + update_account_message_body = u"Registered with username '%s' and " \ + "password '%s' on '%s'" + new_account_message_subject = u"New %s connection '%s' created" + new_account_message_body = u"Registered with " \ + "username '%s' and password '%s' on '%s'" + ask_password_subject = u"Password request" + ask_password_body = u"Reply to this message with the password " \ + "for the following account: \n" \ + "\thost = %s\n" \ + "\tlogin = %s\n" + password_saved_for_session = u"Password will be kept during your Jabber session" + check_error_subject = u"Error while checking emails." + check_error_body = u"An error appears while checking emails:\n\t%s" + new_mail_subject = u"New email from %s" + new_digest_subject = u"%i new email(s)" + + class fr: + register_title = u"Enregistrement d'une nouvelle connexion à un serveur email." + register_instructions = u"Entrer les paramètres de connexion" + account_name = u"Nom de la connexion" + account_login = u"Nom d'utilisateur" + account_password = u"Mot de passe" + account_password_store = u"Sauvegarder le mot de passe sur le serveur Jabber ?" + account_host = u"Adresse du serveur email" + account_port = u"Port du serveur email" + account_type = u"Type du serveur email" + account_mailbox = u"Chemin de la boîte email (IMAP)" + account_ffc_action = u"Action lorsque l'état est 'Free For Chat'" + account_online_action = u"Action lorsque l'état est 'Online'" + account_away_action = u"Action lorsque l'état est 'Away'" + account_xa_action = u"Action lorsque l'état est 'Not Available'" + account_dnd_action = u"Action lorsque l'état est 'Do not Disturb'" + account_offline_action = u"Action lorsque l'état est 'Offline'" + account_check_interval = u"Interval de vérification de nouveaux emails (en minutes)" + account_live_email_only = u"Vérifier les nouveaux emails seulement " \ + "lorsqu'une session Jabber est ouverte" + action_nothing = u"Ne rien faire" + action_retrieve = u"Récupérer l'email" + action_digest = u"Envoyer un résumé" + update_title = u"Mise à jour du compte JMC" + update_instructions = u"Modification de la connexion '%s'" + connection_label = u"Connexion %s '%s'" + update_account_message_subject = u"La connexion %s '%s' a été mise à jour" + update_account_message_body = u"Nom d'utilisateur : '%s'\nMot de passe : '%s'\nsur : '%s'" + new_account_message_subject = u"La connexion %s '%s' a été créée" + new_account_message_body = u"Nom d'utilisateur : '%s'\nMot de passe : '%s'\nsur : '%s'" + ask_password_subject = u"Demande de mot de passe" + ask_password_body = u"Répondre à ce message avec le mot de passe du " \ + "compte suivant : \n" \ + "\thost = %s\n" \ + "\tlogin = %s\n" + password_saved_for_session = u"Le mot de passe sera garder tout au " \ + "long de la session Jabber." + check_error_subject = u"Erreur lors de la vérification des emails." + check_error_body = u"Une erreur est survenue lors de la vérification " \ + "des emails :\n\t%s" + new_mail_subject = u"Nouvel email de %s" + new_digest_subject = u"%i nouveau(x) email(s)" + + class nl: + register_title = u"Registratie van verbindingen voor Jabber Mail" + register_instructions = u"Instellingen voor verbinding" + account_name = u"Accountnaam" + account_login = u"Gebruikersnaam" + account_password = u"Wachtwoord" + account_password_store = u"Wachtwoord opslaan op Jabber-server?" + account_host = u"Server" + account_port = u"Poort" + account_type = u"Soort account" + account_mailbox = u"Pad naar mailbox (IMAP)" + account_ffc_action = u"Actie bij aanwezigheid 'Chat'" + account_online_action = u"Actie bij aanwezigheid 'Beschikbaar'" + account_away_action = u"Actie bij aanwezigheid 'Afwezig'" + account_xa_action = u"Actie bij aanwezigheid 'Langdurig afwezig'" + account_dnd_action = u"Actie bij aanwezigheid 'Niet storen'" + account_offline_action = u"Actie bij aanwezigheid 'Niet beschikbaar'" + account_check_interval = u"Controle-interval (in minuten)" + account_live_email_only = u"Enkel controleren op e-mails als er een" \ + "verbinding is met Jabber" + action_nothing = u"Niets doen" + action_retrieve = u"E-mail ophalen" + action_digest = u"Samenvatting verzenden" + update_title = u"Bijwerken van JMC" + update_instructions = u"Verbinding '%s' aanpassen" + connection_label = u"%s verbinding '%s'" + update_account_message_subject = u"Verbinding %s '%s' werd bijgewerkt" + update_account_message_body = u"Geregistreerd met gebruikersnaam '%s'"\ + "en wachtwoord '%s' op '%s'" + new_account_message_subject = u"Nieuwe %s verbinding '%s' aangemaakt" + new_account_message_body = u"Geregistreerd met " \ + "gebruikersnaam '%s' en wachtwoord '%s' op '%s'" + ask_password_subject = u"Wachtwoordaanvraag" + ask_password_body = u"Antwoord dit bericht met het volgende wachtwoord" \ + "voor de volgende account: \n" \ + "\thost = %s\n" \ + "\tlogin = %s\n" + password_saved_for_session = u"Het wachtwoord zal worden bewaard tijdens uw Jabber-sessie" + check_error_subject = u"Fout tijdens controle op e-mails." + check_error_body = u"Fout tijdens controle op e-mails:\n\t%s" + new_mail_subject = u"Nieuwe e-mail van %s" + new_digest_subject = u"%i nieuwe e-mail(s)" + + class es: + register_title = u"Registro de nueva cuenta de email" + register_instructions = u"Inserta los datos para la nueva cuenta" + account_name = u"Nombre para la cuenta" + account_login = u"Usuario (login)" + account_password = u"Contraseña" + account_password_store = u"¿Guardar la contraseña en el servidor Jabber?" + account_host = u"Host" + account_port = u"Puerto" + account_type = u"Tipo de servidor Mail" + account_mailbox = u"Ruta del mailbox (solo para IMAP)" + account_ffc_action = u"Acción para cuando tu estado sea 'Listopara hablar'" + account_online_action = u"Acción para cuando tu estado sea 'Conectado'" + account_away_action = u"Acción para cuando tu estado sea 'Ausente'" + account_xa_action = u"Acción para cuando tu estado sea 'No disponible'" + account_dnd_action = u"Acción para cuando tu estado sea 'No molestar'" + account_offline_action = u"Acción para cuando tu estado sea 'Desconectado'" + account_check_interval = u"Intervalo para comprobar emails nuevos (en minutos)" + account_live_email_only = u"Avisarme de emails nuevos solo cuando esté conectado" + action_nothing = u"No hacer nada" + action_retrieve = u"Mostrarme el email" + action_digest = u"Enviar resúmen" + update_title = u"Actualización de cuenta de email" + update_instructions = u"Modifica los datos de la cuenta '%s'" + connection_label = u"%s conexión '%s'" + update_account_message_subject = u"Actualizada %s conexión '%s'" + update_account_message_body = u"Registrado con el usuario '%s' y contraseña '%s' en '%s'" + new_account_message_subject = u"Nueva %s conexión '%s' creada" + new_account_message_body = u"Registrado con usuario '%s' y contraseña '%s' en '%s'" + ask_password_subject = u"Petición de contraseña" + ask_password_body = u"Para avisarte de emails nuevos, contesta a este mensaje con la contraseña " \ + "de la cuenta: \n" \ + "\tHost = %s\n" \ + "\tUsuario = %s\n" + password_saved_for_session = u"La contraseña será guardada para esta sesión únicamente." + check_error_subject = u"Error al revisar los emails." + check_error_body = u"Un error apareció al revisar los emails:\n\t%s" + new_mail_subject = u"Nuevo email en %s" + new_digest_subject = u"%i email(s) nuevo(s)" + + class pl: + register_title = u"Rejestracja w komponencie E-Mail" + register_instructions = u"Wprowadź parametry połączenia" + account_name = u"Nazwa połączenia" + account_login = u"Nazwa użytkownika" + account_password = u"Hasło" + account_password_store = u"Zachować hasło na serwerze Jabbera? " + account_host = u"Nazwa hosta" + account_port = u"Port" + account_type = u"Typ serwera email" + account_mailbox = u"Ścieżka do skrzynki odbiorczej (IMAP)" + account_ffc_action = u"Akcja gdy status to 'Chętny do rozmowy'" + account_online_action = u"Akcja gdy status to 'Dostępny'" + account_away_action = u"Akcja gdy status to 'Zaraz wracam'" + account_xa_action = u"Akcja gdy status to 'Niedostępny'" + account_dnd_action = u"Akcja gdy status to 'Nie przeszkadzać'" + account_offline_action = u"Akcja gdy status to 'Rozłączony'" + account_check_interval = u"Sprawdzaj email co (w minutach)" + account_live_email_only = u"Raportuj otrzymane emaile tylko\n gdy podłączony do Jabbera" + action_nothing = u"Nic nie rób" + action_retrieve = u"Pobierz emaila" + action_digest = u"Wyślij zarys emaila" + update_title = u"Modyfikacja połączenia z komponentem mailowym" + update_instructions = u"Modyfikacja połączenia '%s'" + connection_label = u"%s połączenie '%s'" + update_account_message_subject = u"Zmodyfikowane %s połączenie '%s'" + update_account_message_body = u"Zarejestrowany z nazwą użytkownika '%s' i hasłem '%s' na '%s'" + new_account_message_subject = u"Nowe %s połączenie '%s' utworzone" + new_account_message_body = u"Zarejestrowany z nazwą użytkownika '%s' i hasłem '%s' na '%s'" + ask_password_subject = u"Żądanie hasła" + ask_password_body = u"Odpowiedz na ta wiadomosc z hasłem dla podanego konta: \n" \ + "\tnazwa hosta = %s\n" \ + "\tnazwa uzytkownika = %s\n" + password_saved_for_session = u"Hasło będzie przechowywane podczas Twojej sesji Jabbera" + check_error_subject = u"Błąd podczas sprawdzania emaili." + check_error_body = u"Pojawił się błąd podczas sprawdzania emaili:\n\t%s" + new_mail_subject = u"Nowy email od %s" + new_digest_subject = u"%i nowy(ch) email(i)" diff --git a/src/jcl/model/account.py b/src/jcl/model/account.py index 80bb4ec..02953c5 100644 --- a/src/jcl/model/account.py +++ b/src/jcl/model/account.py @@ -24,7 +24,7 @@ from sqlobject import * class Account(SQLObject): - jid = StringCol() + user_jid = StringCol() name = StringCol() diff --git a/tests/jcl/jabber/test_component.py b/tests/jcl/jabber/test_component.py new file mode 100644 index 0000000..0caa8f5 --- /dev/null +++ b/tests/jcl/jabber/test_component.py @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- +## +## test_component.py +## Login : David Rousselie +## Started on Wed Aug 9 21:34:26 2006 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 +## + +import unittest +from sqlobject import * + +from jcl.jabber.component import JCLComponent +from jcl.model.account import Account +from jcl.lang import Lang + +class MockStream(object): + def __init__(self): + self.sended = [] + + def send(self, iq): + self.sended.append(iq) + + def set_iq_set_handler(self, iq_type, ns, handler): + if not iq_type in ["query"]: + raise Exception("IQ type unknown: " + iq_type) + if not ns in ["jabber:iq:version", \ + "jabber:iq:register", \ + "http://jabber.org/protocol/disco#items", \ + "http://jabber.org/protocol/disco#info"]: + raise Exception("Unknown namespace: " + ns) + if handler is None: + raise Exception("Handler must not be None") + + set_iq_get_handler = set_iq_set_handler + + def set_presence_handler(self, status, handler): + if not status in ["available", \ + "unavailable", \ + "probe", \ + "subscribe", \ + "subscribed", \ + "unsubscribe", \ + "unsubscribed"]: + raise Exception("Status unknown: " + status) + if handler is None: + raise Exception("Handler must not be None") + + def set_message_handler(self, msg_type, handler): + if not msg_type in ["normal"]: + raise Exception("Message type unknown: " + msg_type) + if handler is None: + raise Exception("Handler must not be None") + +class JCLComponent_TestCase(unittest.TestCase): + def setUp(self): + connection = sqlhub.processConnection = connectionForURI('sqlite:/:memory:') + self.comp = JCLComponent("jcl.test.com", + "password", + "localhost", + "5347") + + def tearDown(self): + Account.dropTable(ifExists = True) + + def test_constructor(self): + self.assertTrue(Account._connection.tableExists("account")) + + def test_authenticated_handler(self): + self.comp.stream = MockStream() + self.comp.authenticated() + self.assertTrue(True) + + def test_authenticated_send_probe(self): + account11 = Account(user_jid = "test1@test.com", \ + name = "test11") + account12 = Account(user_jid = "test1@test.com", \ + name = "test12") + account2 = Account(user_jid = "test2@test.com", \ + name = "test2") + self.comp.stream = stream = MockStream() + self.comp.authenticated() + + presence_sended = stream.sended + self.assertEqual(len(presence_sended), 5) + self.assertEqual(len([presence \ + for presence in presence_sended \ + if presence.get_from_jid() == "jcl.test.com"]), \ + 2) + self.assertEqual(len([presence \ + for presence in presence_sended \ + if presence.get_to_jid() == "test1@test.com"]), \ + 3) + self.assertEqual(len([presence \ + for presence in presence_sended \ + if presence.get_to_jid() == "test2@test.com"]), \ + 2) + + def test_get_reg_form(self): + self.comp.get_reg_form(Lang.en, Account) + self.assertTrue(True) + + def test_get_reg_form_init(self): + account = Account(user_jid = "", name = "") + self.comp.get_reg_form_init(Lang.en, account) + self.assertTrue(True) + + def test_disco_get_info(self): + pass + + def test_disco_get_items(self): + pass + + def test_handle_get_version(self): + pass + + def test_handle_get_register(self): + pass + + def test_handle_set_register(self): + pass + + def test_handle_presence_available(self): + pass + + def test_handle_presence_unavailable(self): + pass + + def test_handle_presence_subscribe(self): + pass + + def test_handle_presence_subscribed(self): + pass + + def test_handle_presence_unsubscribe(self): + pass + + def test_handle_presence_unsubscribed(self): + pass + + def test_handle_message(self): + pass + + def test_handle_tick(self): + self.comp.handle_tick() + self.assertTrue(True) + diff --git a/tests/jcl/jabber/test_feeder.py b/tests/jcl/jabber/test_feeder.py index e26f751..52005c9 100644 --- a/tests/jcl/jabber/test_feeder.py +++ b/tests/jcl/jabber/test_feeder.py @@ -24,15 +24,40 @@ import unittest from sqlobject import * -from jcl.jabber.component import Feeder +from tests.jcl.jabber.test_component import JCLComponent_TestCase + +from jcl.jabber.feeder import Feeder, Sender from jcl.model.account import Account +class FeederComponent_TestCase(JCLComponent_TestCase): + pass + class Feeder_TestCase(unittest.TestCase): def setUp(self): connection = sqlhub.processConnection = connectionForURI('sqlite:/:memory:') Account.createTable() + + def tearDown(self): + Account.dropTable(ifExists = True) def test_feed_exist(self): feeder = Feeder() - feeder.feed(Account(jid="test@jid.com", name="test")) + feeder.feed(Account(user_jid = "test@test.com", \ + name = "test")) + self.assertTrue(True) + +class Sender_TestCase(unittest.TestCase): + def setUp(self): + connection = sqlhub.processConnection = connectionForURI('sqlite:/:memory:') + Account.createTable() + + def tearDown(self): + Account.dropTable(ifExists = True) + + def test_send_exist(self): + sender = Sender() + account = Account(user_jid = "test@test.com", \ + name = "test") + sender.send(to_account = account, \ + message = "Hello World") self.assertTrue(True)