import collections import configparser import logging import re import slixmpp logger = logging.getLogger('forwardxmpp.config') Forward = collections.namedtuple('Forward', ('from_re', 'to_jid', 'body_fmt')) class Config(configparser.ConfigParser): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) bot_section = self.setdefault('Bot', {}) bot_section.setdefault('loglevel', 'warning') def read_paths(self, paths_seq, encoding=None): for path in paths_seq: try: with path.open(encoding=encoding) as source: self.read_file(source) except OSError as error: logger.error("error reading %s: %s", path, error.strerror) else: yield path def ready(self): retval = True if not self['Bot'].get('jid'): logger.error("Bot configuration missing jid") retval = False if self['Bot'].get('password') is None: logger.error("Bot configuration missing password") retval = False if not any(self._forward_sections()): logger.error("no forwarding sections found in configuration") retval = False if self.get_loglevel(-1) == -1: logger.error("invalid loglevel setting %r", self['Bot']['loglevel']) retval = False return retval def bot_jid(self): retval = slixmpp.JID(self['Bot']['jid']) if not retval.resource: retval.resource = 'ForwardXMPP' return retval def bot_password(self): return self['Bot']['password'] def bot_nick(self): try: return self['Bot']['nickname'] except KeyError: return self.bot_jid().user def _forward_sections(self): for skey in self.sections(): if skey.startswith('Forward '): yield skey, self[skey] def forwards(self): re_cache = {} for key, section in self._forward_sections(): try: from_re = re_cache[section['from']] except KeyError: from_re = re.compile(section['from']) re_cache[section['from']] = from_re value = Forward( from_re, slixmpp.JID(section['to']), section.get('format', "Forwarded message from {from.full}: {body}"), ) yield (key, value) def get_loglevel(self, fallback=None): loglevel_s = self['Bot'].get('loglevel', 'warning') try: retval = getattr(logging, loglevel_s.upper()) except (AttributeError, TypeError, ValueError): if fallback is None: raise else: return fallback else: return retval