Pylint checking
darcs-hash:20061001204010-86b55-2b2b3997794d11e2257effc502563ef32eac4560.gz
This commit is contained in:
@@ -0,0 +1 @@
|
||||
__revision__ = "$Id: __init__.py dax $"
|
||||
|
||||
@@ -21,13 +21,26 @@
|
||||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##
|
||||
|
||||
"""JCL base component
|
||||
"""
|
||||
|
||||
__revision__ = ""
|
||||
|
||||
import thread
|
||||
import threading
|
||||
import time
|
||||
import logging
|
||||
import signal
|
||||
import re
|
||||
|
||||
from pyxmpp.jid import JID
|
||||
from pyxmpp.jabberd.component import Component
|
||||
from pyxmpp.jabber.disco import DiscoInfo, DiscoItems
|
||||
from pyxmpp.message import Message
|
||||
from pyxmpp.presence import Presence
|
||||
from pyxmpp.streambase import StreamError, FatalStreamError
|
||||
|
||||
from jcl.jabber.x import X
|
||||
from jcl.model.account import Account
|
||||
|
||||
VERSION = "0.1"
|
||||
@@ -35,58 +48,128 @@ VERSION = "0.1"
|
||||
###############################################################################
|
||||
# JCL implementation
|
||||
###############################################################################
|
||||
class JCLComponent(Component):
|
||||
class JCLComponent(Component):
|
||||
"""Implement default JCL component behavior:
|
||||
- regular interval behavior
|
||||
- Jabber register process (add, delete, update accounts)
|
||||
- Jabber presence handling
|
||||
- passwork request at login
|
||||
"""
|
||||
|
||||
timeout = 1
|
||||
|
||||
def __init__(self,
|
||||
jid,
|
||||
secret,
|
||||
server,
|
||||
port,
|
||||
name = "Jabber Component Library generic component",
|
||||
disco_category = "gateway",
|
||||
disco_type = "headline",
|
||||
spool_dir = ".",
|
||||
check_interval = 1,
|
||||
account_class = Account):
|
||||
disco_type = "headline"):
|
||||
Component.__init__(self, \
|
||||
JID(jid), \
|
||||
secret, \
|
||||
server, \
|
||||
port, \
|
||||
disco_category, \
|
||||
disco_type)
|
||||
# default values
|
||||
self.name = "Jabber Component Library generic component"
|
||||
self.spool_dir = "."
|
||||
self.__account_class = None
|
||||
self.account_class = Account
|
||||
self.version = VERSION
|
||||
self.accounts = []
|
||||
|
||||
self.disco_info.add_feature("jabber:iq:version")
|
||||
self.disco_info.add_feature("jabber:iq:register")
|
||||
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.__lang = None
|
||||
self.running = False
|
||||
|
||||
self.__shutdown = 0
|
||||
|
||||
signal.signal(signal.SIGINT, self.signal_handler)
|
||||
signal.signal(signal.SIGTERM, self.signal_handler)
|
||||
spool_dir += "/" + jid
|
||||
|
||||
def set_account_class(self, account_class):
|
||||
self.__account_class = account_class
|
||||
self.__account_class.createTable(ifNotExists = True)
|
||||
self.version = VERSION
|
||||
|
||||
|
||||
def get_account_class(self):
|
||||
return self.__account_class
|
||||
|
||||
account_class = property(get_account_class, set_account_class)
|
||||
|
||||
def run(self):
|
||||
"""Main loop
|
||||
Connect to Jabber server
|
||||
Start timer thread
|
||||
Call Component main loop
|
||||
Clean up when shutting down JCLcomponent
|
||||
"""
|
||||
self.spool_dir += "/" + str(self.jid)
|
||||
self.running = True
|
||||
self.connect()
|
||||
thread.start_new_thread(self.time_handler, ())
|
||||
try:
|
||||
while (self.running and self.stream
|
||||
and not self.stream.eof and self.stream.socket is not None):
|
||||
try:
|
||||
self.stream.loop_iter(JCLComponent.timeout)
|
||||
except (KeyboardInterrupt, SystemExit, FatalStreamError, \
|
||||
StreamError):
|
||||
raise
|
||||
except:
|
||||
self.__logger.exception("Exception cought:")
|
||||
finally:
|
||||
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 _thread in threads:
|
||||
try:
|
||||
_thread.join(10 * JCLComponent.timeout)
|
||||
except:
|
||||
pass
|
||||
for _thread in threads:
|
||||
try:
|
||||
_thread.join(JCLComponent.timeout)
|
||||
except:
|
||||
pass
|
||||
self.disconnect()
|
||||
# TODO : terminate SQLObject
|
||||
self.__logger.debug("Exitting normally")
|
||||
|
||||
|
||||
|
||||
###########################################################################
|
||||
# Handlers
|
||||
###########################################################################
|
||||
def time_handler(self):
|
||||
"""Timer thread handler
|
||||
"""
|
||||
self.__logger.info("Timer thread started...")
|
||||
while self.running:
|
||||
self.handle_tick()
|
||||
self.__logger.debug("Resetting alarm signal")
|
||||
time.sleep(60)
|
||||
|
||||
def authenticated(self):
|
||||
Component.authenticated(self)
|
||||
"""Override authenticated Component event handler
|
||||
Register event handlers
|
||||
Probe for every accounts registered
|
||||
"""
|
||||
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)
|
||||
|
||||
Component.authenticated(self)
|
||||
self.stream.set_iq_get_handler("query", "jabber:iq:version", \
|
||||
self.handle_get_version)
|
||||
self.stream.set_iq_get_handler("query", "jabber:iq:register", \
|
||||
@@ -114,180 +197,128 @@ class JCLComponent(Component):
|
||||
|
||||
self.stream.set_message_handler("normal", \
|
||||
self.handle_message)
|
||||
current_jid = None
|
||||
for account in self.account_class.select(orderBy = "user_jid"):
|
||||
if account.user_jid != current_jid:
|
||||
presence = Presence(from_jid = unicode(self.jid), \
|
||||
to_jid = account.user_jid, \
|
||||
stanza_type = "probe")
|
||||
self.stream.send(presence)
|
||||
current_jid = account.user_jid
|
||||
presence = Presence(from_jid = self.get_jid(account), \
|
||||
to_jid = account.user_jid, \
|
||||
stanza_type = "probe")
|
||||
self.stream.send(presence)
|
||||
|
||||
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):
|
||||
"""Stop method handler
|
||||
"""
|
||||
self.__logger.debug("Signal %i received, shutting down..." % (signum,))
|
||||
self.__shutdown = 1
|
||||
self.running = False
|
||||
|
||||
|
||||
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):
|
||||
def disco_get_info(self, node, input_query):
|
||||
"""Discovery get info handler
|
||||
"""
|
||||
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)
|
||||
if node is not None:
|
||||
disco_info = DiscoInfo()
|
||||
disco_info.add_feature("jabber:iq:register")
|
||||
return disco_info
|
||||
else:
|
||||
di.add_feature("jabber:iq:register")
|
||||
return di
|
||||
return self.disco_info
|
||||
|
||||
""" Discovery get nested nodes handler """
|
||||
def disco_get_items(self, node, iq):
|
||||
def disco_get_items(self, node, input_query):
|
||||
"""Discovery get nested nodes handler
|
||||
"""
|
||||
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()
|
||||
## TODO Lang
|
||||
## lang_class = self.__lang.get_lang_class_from_node(input_query.get_node())
|
||||
## base_from_jid = unicode(input_query.get_from().bare())
|
||||
disco_items = 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
|
||||
## TODO : list accounts
|
||||
for account in self.accounts:
|
||||
self.__logger.debug(str(account))
|
||||
## DiscoItem(di, JID(name + "@" + unicode(self.jid)), \
|
||||
## name, str_name)
|
||||
return disco_items
|
||||
|
||||
""" Get Version handler """
|
||||
def handle_get_version(self, iq):
|
||||
def handle_get_version(self, input_query):
|
||||
"""Get Version handler
|
||||
"""
|
||||
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)
|
||||
input_query = input_query.make_result_response()
|
||||
query = input_query.new_query("jabber:iq:version")
|
||||
query.newTextChild(query.ns(), "name", self.name)
|
||||
query.newTextChild(query.ns(), "version", self.version)
|
||||
self.stream.send(input_query)
|
||||
return 1
|
||||
|
||||
""" Send back register form to user """
|
||||
def handle_get_register(self, iq):
|
||||
def handle_get_register(self, input_query):
|
||||
"""Send back register form to user
|
||||
"""
|
||||
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:
|
||||
## TODO Lang
|
||||
## lang_class = self.__lang.get_lang_class_from_node(input_query.get_node())
|
||||
lang_class = None
|
||||
## base_from_jid = unicode(input_query.get_from().bare())
|
||||
to_jid = input_query.get_to()
|
||||
input_query = input_query.make_result_response()
|
||||
query = input_query.new_query("jabber:iq:register")
|
||||
if to_jid and to_jid != self.jid:
|
||||
self.get_reg_form_init(lang_class, \
|
||||
self.__accounts.select() # TODO
|
||||
).attach_xml(q)
|
||||
self.accounts.select() # TODO
|
||||
).attach_xml(query)
|
||||
else:
|
||||
self.get_reg_form(lang_class).attach_xml(q)
|
||||
self.stream.send(iq)
|
||||
self.get_reg_form(lang_class).attach_xml(query)
|
||||
self.stream.send(input_query)
|
||||
return 1
|
||||
|
||||
""" Handle user registration response """
|
||||
def handle_set_register(self, iq):
|
||||
def handle_set_register(self, input_query):
|
||||
"""Handle user registration response
|
||||
"""
|
||||
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"})
|
||||
## lang_class = \
|
||||
## self.__lang.get_lang_class_from_node(input_query.get_node())
|
||||
from_jid = input_query.get_from()
|
||||
## base_from_jid = unicode(from_jid.bare())
|
||||
remove = input_query.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)
|
||||
# for name in self.__storage.keys((base_from_jid,)):
|
||||
# self.__logger.debug("Deleting " + name \
|
||||
# + " for " + base_from_jid)
|
||||
# presence = Presence(from_jid = name + "@" + unicode(self.jid), \
|
||||
# to_jid = from_jid, \
|
||||
# stanza_type = "unsubscribe")
|
||||
# self.stream.send(presence)
|
||||
# presence = Presence(from_jid = name + "@" + unicode(self.jid), \
|
||||
# to_jid = from_jid, \
|
||||
# stanza_type = "unsubscribed")
|
||||
# self.stream.send(presence)
|
||||
# del self.__storage[(base_from_jid, name)]
|
||||
presence = Presence(from_jid = self.jid, to_jid = from_jid, \
|
||||
stanza_type = "unsubscribe")
|
||||
self.stream.send(presence)
|
||||
presence = Presence(from_jid = self.jid, to_jid = from_jid, \
|
||||
stanza_type = "unsubscribed")
|
||||
self.stream.send(presence)
|
||||
return 1
|
||||
|
||||
query = iq.get_query()
|
||||
x = X()
|
||||
x.from_xml(query.children)
|
||||
query = input_query.get_query()
|
||||
x_data = X()
|
||||
x_data.from_xml(query.children)
|
||||
# TODO : get info from Xdata
|
||||
|
||||
|
||||
""" Handle presence availability """
|
||||
def handle_presence_available(self, stanza):
|
||||
"""Handle presence availability
|
||||
"""
|
||||
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())
|
||||
## lang_class = self.__lang.get_lang_class_from_node(stanza.get_node())
|
||||
show = stanza.get_show()
|
||||
self.__logger.debug("SHOW : " + str(show))
|
||||
if name:
|
||||
@@ -296,63 +327,71 @@ class JCLComponent(Component):
|
||||
# else send available presence
|
||||
return 1
|
||||
|
||||
""" handle presence unavailability """
|
||||
def handle_presence_unavailable(self, stanza):
|
||||
"""Handle presence unavailability
|
||||
"""
|
||||
self.__logger.debug("PRESENCE_UNAVAILABLE")
|
||||
from_jid = stanza.get_from()
|
||||
base_from_jid = unicode(from_jid.bare())
|
||||
## 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):
|
||||
"""Handle subscribe presence from user
|
||||
"""
|
||||
self.__logger.debug("PRESENCE_SUBSCRIBE")
|
||||
p = stanza.make_accept_response()
|
||||
self.stream.send(p)
|
||||
presence = stanza.make_accept_response()
|
||||
self.stream.send(presence)
|
||||
return 1
|
||||
|
||||
""" handle subscribed presence from user """
|
||||
def handle_presence_subscribed(self, stanza):
|
||||
"""Handle subscribed presence from user
|
||||
"""
|
||||
self.__logger.debug("PRESENCE_SUBSCRIBED")
|
||||
name = stanza.get_to().node
|
||||
from_jid = stanza.get_from()
|
||||
base_from_jid = unicode(from_jid.bare())
|
||||
## 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):
|
||||
"""Handle unsubscribe presence from user
|
||||
"""
|
||||
self.__logger.debug("PRESENCE_UNSUBSCRIBE")
|
||||
name = stanza.get_to().node
|
||||
from_jid = stanza.get_from()
|
||||
base_from_jid = unicode(from_jid.bare())
|
||||
## 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)
|
||||
presence = Presence(from_jid = stanza.get_to(), to_jid = from_jid, \
|
||||
stanza_type = "unsubscribe")
|
||||
self.stream.send(presence)
|
||||
presence = stanza.make_accept_response()
|
||||
self.stream.send(presence)
|
||||
return 1
|
||||
|
||||
""" handle unsubscribed presence from user """
|
||||
def handle_presence_unsubscribed(self, stanza):
|
||||
"""Handle unsubscribed presence from user
|
||||
"""
|
||||
self.__logger.debug("PRESENCE_UNSUBSCRIBED")
|
||||
p = Presence(from_jid = stanza.get_to(), \
|
||||
to_jid = stanza.get_from(), \
|
||||
stanza_type = "unavailable")
|
||||
self.stream.send(p)
|
||||
presence = Presence(from_jid = stanza.get_to(), \
|
||||
to_jid = stanza.get_from(), \
|
||||
stanza_type = "unavailable")
|
||||
self.stream.send(presence)
|
||||
return 1
|
||||
|
||||
""" Handle new message """
|
||||
def handle_message(self, message):
|
||||
"""Handle new 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)]
|
||||
## 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 = Account()
|
||||
account.password = message.get_body()
|
||||
account.waiting_password_reply = False
|
||||
msg = Message(from_jid = account.jid, \
|
||||
@@ -363,5 +402,47 @@ class JCLComponent(Component):
|
||||
self.stream.send(msg)
|
||||
return 1
|
||||
|
||||
###########################################################################
|
||||
# Utils
|
||||
###########################################################################
|
||||
def _ask_password(self, from_jid, lang_class, account):
|
||||
"""Send a Jabber message to ask for account password
|
||||
"""
|
||||
#TODO be JMC independant
|
||||
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 jid based on account instance and component jid
|
||||
"""
|
||||
return account.name + u"@" + unicode(self.jid)
|
||||
|
||||
###########################################################################
|
||||
# Virtual methods
|
||||
###########################################################################
|
||||
def handle_tick(self):
|
||||
"""Virtual method
|
||||
Called regularly
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_reg_form(self, lang_class, account_class):
|
||||
"""Virtual method
|
||||
Return register form based on language and account class
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_reg_form_init(self, lang_class, account):
|
||||
"""Virtual method
|
||||
Return register form for an existing account (update)
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -21,50 +21,70 @@
|
||||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##
|
||||
|
||||
"""FeederComponent with default Feeder and Sender
|
||||
implementation
|
||||
"""
|
||||
|
||||
__revision__ = "$Id: feeder.py dax $"
|
||||
|
||||
import logging
|
||||
|
||||
from jcl.jabber.component import JCLComponent
|
||||
from jcl.model.account import *
|
||||
from jcl.model.account import Account
|
||||
|
||||
class FeederComponent(JCLComponent):
|
||||
"""Implement a feeder sender behavior based on the
|
||||
regular interval behavior of JCLComponent
|
||||
feed data from given Feeder and send it to user
|
||||
through the given Sender.
|
||||
"""
|
||||
def __init__(self,
|
||||
jid,
|
||||
secret,
|
||||
server,
|
||||
port,
|
||||
name = "Generic Feeder Component",
|
||||
disco_category = "gateway",
|
||||
disco_type = "headline",
|
||||
spool_dir = ".",
|
||||
check_interval = 1):
|
||||
port):
|
||||
JCLComponent.__init__(self, \
|
||||
jid, \
|
||||
secret, \
|
||||
server, \
|
||||
port, \
|
||||
name, \
|
||||
disco_category, \
|
||||
disco_type, \
|
||||
spool_dir, \
|
||||
check_interval)
|
||||
port)
|
||||
self.name = "Generic Feeder Component"
|
||||
# Define default feeder and sender, can be override
|
||||
self.feeder = Feeder()
|
||||
self.sender = Sender()
|
||||
self.check_interval = 1
|
||||
|
||||
self.__logger = logging.getLogger("jcl.jabber.JCLComponent")
|
||||
|
||||
def handle_tick(self):
|
||||
"""Implement main feed/send behavior
|
||||
"""
|
||||
for account in Account.select("*"):
|
||||
for message in self.__jabber_component.feeder.feed(account):
|
||||
self.__jabber_component.sender.send(account, message)
|
||||
for data in self.feeder.feed(account):
|
||||
self.sender.send(account, data)
|
||||
|
||||
|
||||
|
||||
class Feeder(object):
|
||||
"""Abstract feeder class
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def feed(self, account):
|
||||
"""Feed data for given account
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Sender(object):
|
||||
"""Abstract sender class
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def send(self, to_account, message):
|
||||
def send(self, to_account, data):
|
||||
"""Send data to given account
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -20,110 +20,134 @@
|
||||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##
|
||||
|
||||
import sys
|
||||
"""X -- X data handling
|
||||
"""
|
||||
|
||||
__revision__ = ""
|
||||
|
||||
from pyxmpp.stanza import common_doc
|
||||
|
||||
class Option(object):
|
||||
"""Option value for list field
|
||||
"""
|
||||
def __init__(self, label, value):
|
||||
self.__label = label
|
||||
self.__value = value
|
||||
|
||||
self.__label = label
|
||||
self.__value = value
|
||||
|
||||
def get_xml(self, parent):
|
||||
if parent is None:
|
||||
option = common_doc.newChild(None, "option", None)
|
||||
else:
|
||||
option = parent.newChild(None, "option", None)
|
||||
option.setProp("label", self.__label)
|
||||
option.newChild(None, "value", self.__value)
|
||||
return option
|
||||
"""Return XML Option representation from
|
||||
self.__label and self.__value and attach it to parent
|
||||
"""
|
||||
if parent is None:
|
||||
option = common_doc.newChild(None, "option", None)
|
||||
else:
|
||||
option = parent.newChild(None, "option", None)
|
||||
option.setProp("label", self.__label)
|
||||
option.newChild(None, "value", self.__value)
|
||||
return option
|
||||
|
||||
class Field(object):
|
||||
def __init__(self, type, label, var, value):
|
||||
self.__type = type
|
||||
self.__label = label
|
||||
self.__var = var
|
||||
self.value = value
|
||||
self.__options = []
|
||||
"""Jabber Xdata form Field
|
||||
"""
|
||||
def __init__(self, field_type, label, var, value):
|
||||
self.__type = field_type
|
||||
self.__label = label
|
||||
self.__var = var
|
||||
self.value = value
|
||||
self.__options = []
|
||||
|
||||
def add_option(self, label, value):
|
||||
option = Option(label, value)
|
||||
self.__options.append(option)
|
||||
return option
|
||||
"""Add an Option to this field
|
||||
"""
|
||||
option = Option(label, value)
|
||||
self.__options.append(option)
|
||||
return option
|
||||
|
||||
def get_xml(self, parent):
|
||||
if parent is None:
|
||||
raise Exception, "parent field should not be None"
|
||||
else:
|
||||
field = parent.newChild(None, "field", None)
|
||||
field.setProp("type", self.__type)
|
||||
if not self.__label is None:
|
||||
field.setProp("label", self.__label)
|
||||
if not self.__var is None:
|
||||
field.setProp("var", self.__var)
|
||||
if self.value:
|
||||
field.newChild(None, "value", self.value)
|
||||
for option in self.__options:
|
||||
option.get_xml(field)
|
||||
return field
|
||||
"""Return XML Field representation
|
||||
and attach it to parent
|
||||
"""
|
||||
if parent is None:
|
||||
raise Exception, "parent field should not be None"
|
||||
else:
|
||||
field = parent.newChild(None, "field", None)
|
||||
field.setProp("type", self.__type)
|
||||
if not self.__label is None:
|
||||
field.setProp("label", self.__label)
|
||||
if not self.__var is None:
|
||||
field.setProp("var", self.__var)
|
||||
if self.value:
|
||||
field.newChild(None, "value", self.value)
|
||||
for option in self.__options:
|
||||
option.get_xml(field)
|
||||
return field
|
||||
|
||||
class X(object):
|
||||
"""Jabber Xdata form
|
||||
"""
|
||||
def __init__(self):
|
||||
self.fields = {}
|
||||
self.fields_tab = []
|
||||
self.title = None
|
||||
self.instructions = None
|
||||
self.type = None
|
||||
self.fields = {}
|
||||
self.fields_tab = []
|
||||
self.title = None
|
||||
self.instructions = None
|
||||
self.x_type = None
|
||||
self.xmlns = None
|
||||
|
||||
def add_field(self, type = "fixed", label = None, var = None, value = ""):
|
||||
field = Field(type, label, var, value)
|
||||
self.fields[var] = field
|
||||
# fields_tab exist to keep added fields order
|
||||
self.fields_tab.append(field)
|
||||
return field
|
||||
def add_field(self, field_type = "fixed", label = None, var = None, value = ""):
|
||||
"""Add a Field to this Xdata form
|
||||
"""
|
||||
field = Field(field_type, label, var, value)
|
||||
self.fields[var] = field
|
||||
# fields_tab exist to keep added fields order
|
||||
self.fields_tab.append(field)
|
||||
return field
|
||||
|
||||
def attach_xml(self, iq):
|
||||
node = iq.newChild(None, "x", None)
|
||||
_ns = node.newNs(self.xmlns, None)
|
||||
node.setNs(_ns)
|
||||
if not self.title is None:
|
||||
node.newTextChild(None, "title", self.title)
|
||||
if not self.instructions is None:
|
||||
node.newTextChild(None, "instructions", self.instructions)
|
||||
for field in self.fields_tab:
|
||||
field.get_xml(node)
|
||||
return node
|
||||
"""Attach this Xdata form to iq node
|
||||
"""
|
||||
node = iq.newChild(None, "x", None)
|
||||
_ns = node.newNs(self.xmlns, None)
|
||||
node.setNs(_ns)
|
||||
if not self.title is None:
|
||||
node.newTextChild(None, "title", self.title)
|
||||
if not self.instructions is None:
|
||||
node.newTextChild(None, "instructions", self.instructions)
|
||||
for field in self.fields_tab:
|
||||
field.get_xml(node)
|
||||
return node
|
||||
|
||||
def from_xml(self, node):
|
||||
## TODO : test node type and ns and clean that loop !!!!
|
||||
while node and node.type != "element":
|
||||
node = node.next
|
||||
child = node.children
|
||||
while child:
|
||||
## TODO : test child type (element) and ns (jabber:x:data)
|
||||
if child.type == "element" and child.name == "field":
|
||||
if child.hasProp("type"):
|
||||
type = child.prop("type")
|
||||
else:
|
||||
type = ""
|
||||
"""Populate this X object from an XML representation
|
||||
"""
|
||||
## TODO : test node type and ns and clean that loop !!!!
|
||||
while node and node.type != "element":
|
||||
node = node.next
|
||||
child = node.children
|
||||
while child:
|
||||
## TODO : test child type (element) and ns (jabber:x:data)
|
||||
if child.type == "element" and child.name == "field":
|
||||
if child.hasProp("type"):
|
||||
field_type = child.prop("type")
|
||||
else:
|
||||
field_type = ""
|
||||
|
||||
if child.hasProp("label"):
|
||||
label = child.prop("label")
|
||||
else:
|
||||
label = ""
|
||||
if child.hasProp("label"):
|
||||
label = child.prop("label")
|
||||
else:
|
||||
label = ""
|
||||
|
||||
if child.hasProp("var"):
|
||||
var = child.prop("var")
|
||||
else:
|
||||
var = ""
|
||||
|
||||
xval = child.children
|
||||
while xval and xval.name != "value":
|
||||
xval = xval.next
|
||||
if xval:
|
||||
value = xval.getContent()
|
||||
else:
|
||||
value = ""
|
||||
field = Field(type, label, var, value)
|
||||
self.fields[var] = field
|
||||
child = child.next
|
||||
if child.hasProp("var"):
|
||||
var = child.prop("var")
|
||||
else:
|
||||
var = ""
|
||||
|
||||
xval = child.children
|
||||
while xval and xval.name != "value":
|
||||
xval = xval.next
|
||||
if xval:
|
||||
value = xval.getContent()
|
||||
else:
|
||||
value = ""
|
||||
field = Field(field_type, label, var, value)
|
||||
self.fields[var] = field
|
||||
child = child.next
|
||||
|
||||
140
src/jcl/lang.py
140
src/jcl/lang.py
@@ -21,12 +21,27 @@
|
||||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##
|
||||
|
||||
# TODO delete not JCL translation
|
||||
"""lang -- contains translations
|
||||
"""
|
||||
|
||||
# TODO get help to generate revision
|
||||
__revision__ = "$Id: lang.py dax $"
|
||||
|
||||
# TODO delete JMC translation
|
||||
class Lang:
|
||||
"""Lang.
|
||||
"""
|
||||
# TODO get help on docstring
|
||||
# pylint: disable-msg=W0232, R0903, C0103, C0111
|
||||
def __init__(self, default_lang = "en"):
|
||||
self.default_lang = default_lang
|
||||
|
||||
def get_lang_from_node(self, node):
|
||||
"""Extract lang contain in a XML node.
|
||||
|
||||
:Parameters:
|
||||
- `node`: XML node.
|
||||
"""
|
||||
lang = node.getLang()
|
||||
if lang is None:
|
||||
print "Using default lang " + self.default_lang
|
||||
@@ -34,9 +49,19 @@ class Lang:
|
||||
return lang
|
||||
|
||||
def get_lang_class(self, lang):
|
||||
return getattr(Lang, lang)
|
||||
"""Return lang class from lang code.
|
||||
|
||||
:Parameters:
|
||||
- `lang`: lang code.
|
||||
"""
|
||||
return getattr(self, lang)
|
||||
|
||||
def get_lang_class_from_node(self, node):
|
||||
"""Return lang class from XML node.
|
||||
|
||||
:Parameters:
|
||||
- `node`: XML node.
|
||||
"""
|
||||
return self.get_lang_class(self.get_lang_from_node(node))
|
||||
|
||||
class en:
|
||||
@@ -57,7 +82,8 @@ class Lang:
|
||||
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"
|
||||
account_live_email_only = u"Reports only emails received while " \
|
||||
u"connected to Jabber"
|
||||
action_nothing = u"Do nothing"
|
||||
action_retrieve = u"Retrieve mail"
|
||||
action_digest = u"Send mail digest"
|
||||
@@ -66,7 +92,7 @@ class Lang:
|
||||
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'"
|
||||
u"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'"
|
||||
@@ -75,19 +101,22 @@ class Lang:
|
||||
"for the following account: \n" \
|
||||
"\thost = %s\n" \
|
||||
"\tlogin = %s\n"
|
||||
password_saved_for_session = u"Password will be kept during your Jabber session"
|
||||
password_saved_for_session = u"Password will be kept during your " \
|
||||
u"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_title = u"Enregistrement d'une nouvelle connexion à un " \
|
||||
u"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_password_store = u"Sauvegarder le mot de passe sur le " \
|
||||
u"serveur Jabber ?"
|
||||
account_host = u"Adresse du serveur email"
|
||||
account_port = u"Port du serveur email"
|
||||
account_type = u"Type du serveur email"
|
||||
@@ -98,7 +127,8 @@ class Lang:
|
||||
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_check_interval = u"Interval de vérification de nouveaux " \
|
||||
u"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"
|
||||
@@ -107,20 +137,23 @@ class Lang:
|
||||
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'"
|
||||
update_account_message_subject = u"La connexion %s '%s' a été mise " \
|
||||
u"à jour"
|
||||
update_account_message_body = u"Nom d'utilisateur : '%s'\nMot de " \
|
||||
u"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'"
|
||||
new_account_message_body = u"Nom d'utilisateur : '%s'\nMot de passe " \
|
||||
u": '%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"
|
||||
ask_password_body = u"Répondre à ce message avec le mot de passe " \
|
||||
u"du compte suivant : \n" \
|
||||
u"\thost = %s\n" \
|
||||
u"\tlogin = %s\n"
|
||||
password_saved_for_session = u"Le mot de passe sera garder tout au " \
|
||||
"long de la session Jabber."
|
||||
u"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"
|
||||
check_error_body = u"Une erreur est survenue lors de la " \
|
||||
u"vérification des emails :\n\t%s"
|
||||
new_mail_subject = u"Nouvel email de %s"
|
||||
new_digest_subject = u"%i nouveau(x) email(s)"
|
||||
|
||||
@@ -152,16 +185,18 @@ class Lang:
|
||||
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'"
|
||||
u"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'"
|
||||
u"gebruikersnaam '%s' en wachtwoord " \
|
||||
u"'%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"
|
||||
ask_password_body = u"Antwoord dit bericht met het volgende " \
|
||||
u"wachtwoord voor de volgende account: \n" \
|
||||
u"\thost = %s\n" \
|
||||
u"\tlogin = %s\n"
|
||||
password_saved_for_session = u"Het wachtwoord zal worden bewaard " \
|
||||
u"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"
|
||||
@@ -173,19 +208,24 @@ class Lang:
|
||||
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_password_store = u"¿Guardar la contraseña en el servidor " \
|
||||
u"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_ffc_action = u"Acción para cuando tu estado sea " \
|
||||
u"'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"
|
||||
account_offline_action = u"Acción para cuando tu estado sea " \
|
||||
u"'Desconectado'"
|
||||
account_check_interval = u"Intervalo para comprobar emails nuevos " \
|
||||
u"(en minutos)"
|
||||
account_live_email_only = u"Avisarme de emails nuevos solo cuando " \
|
||||
u"esté conectado"
|
||||
action_nothing = u"No hacer nada"
|
||||
action_retrieve = u"Mostrarme el email"
|
||||
action_digest = u"Enviar resúmen"
|
||||
@@ -193,15 +233,19 @@ class Lang:
|
||||
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'"
|
||||
update_account_message_body = u"Registrado con el usuario '%s' y " \
|
||||
u"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'"
|
||||
new_account_message_body = u"Registrado con usuario '%s' y " \
|
||||
u"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."
|
||||
ask_password_body = u"Para avisarte de emails nuevos, contesta a " \
|
||||
u"este mensaje con la contraseña " \
|
||||
u"de la cuenta: \n" \
|
||||
u"\tHost = %s\n" \
|
||||
u"\tUsuario = %s\n"
|
||||
password_saved_for_session = u"La contraseña será guardada para " \
|
||||
u"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"
|
||||
@@ -225,7 +269,8 @@ class Lang:
|
||||
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"
|
||||
account_live_email_only = u"Raportuj otrzymane emaile tylko\n gdy " \
|
||||
u"podłączony do Jabbera"
|
||||
action_nothing = u"Nic nie rób"
|
||||
action_retrieve = u"Pobierz emaila"
|
||||
action_digest = u"Wyślij zarys emaila"
|
||||
@@ -233,15 +278,20 @@ class Lang:
|
||||
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'"
|
||||
update_account_message_body = u"Zarejestrowany z nazwą użytkownika " \
|
||||
u"'%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'"
|
||||
new_account_message_body = u"Zarejestrowany z nazwą użytkownika " \
|
||||
u"'%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"
|
||||
ask_password_body = u"Odpowiedz na ta wiadomosc z hasłem dla " \
|
||||
u"podanego konta: \n" \
|
||||
u"\tnazwa hosta = %s\n" \
|
||||
u"\tnazwa uzytkownika = %s\n"
|
||||
password_saved_for_session = u"Hasło będzie przechowywane podczas " \
|
||||
u"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"
|
||||
check_error_body = u"Pojawił się błąd podczas sprawdzania " \
|
||||
u"emaili:\n\t%s"
|
||||
new_mail_subject = u"Nowy email od %s"
|
||||
new_digest_subject = u"%i nowy(ch) email(i)"
|
||||
|
||||
@@ -26,5 +26,7 @@ from sqlobject import *
|
||||
class Account(SQLObject):
|
||||
user_jid = StringCol()
|
||||
name = StringCol()
|
||||
jid = StringCol()
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user