From 7e40a4bddbb9415884af72cd75c3a1259f0a7328 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Fri, 31 Aug 2012 13:54:45 +0200 Subject: [PATCH] Listener: Use the Supybot registry instead of hardcoded values & allow multiple listeners. --- Listener/config.py | 7 +++ Listener/plugin.py | 110 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 104 insertions(+), 13 deletions(-) diff --git a/Listener/config.py b/Listener/config.py index ab95a9e..b556a46 100644 --- a/Listener/config.py +++ b/Listener/config.py @@ -31,6 +31,10 @@ import supybot.conf as conf import supybot.registry as registry +from supybot.i18n import PluginInternationalization +from supybot.i18n import internationalizeDocstring +_ = PluginInternationalization('Listener') + def configure(advanced): # This will be called by supybot to configure this module. advanced is # a bool that specifies whether the user identified himself as an advanced @@ -45,5 +49,8 @@ Listener = conf.registerPlugin('Listener') # conf.registerGlobalValue(Listener, 'someConfigVariableName', # registry.Boolean(False, """Help for someConfigVariableName.""")) +conf.registerGlobalValue(Listener, 'relays', + registry.String('[]', _("""JSON-formatted relays. Do not edit this + configuration variable unless you know what you are doing."""))) # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: diff --git a/Listener/plugin.py b/Listener/plugin.py index f18e782..3ee6fa7 100644 --- a/Listener/plugin.py +++ b/Listener/plugin.py @@ -1,5 +1,6 @@ ### # Copyright (c) 2010, quantumlemur +# Copyright (c) 2012, Valentin Lorentz # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -28,17 +29,29 @@ ### +import json import time import socket import threading +import traceback +import supybot.log as log +import supybot.conf as conf import supybot.utils as utils import supybot.world as world from supybot.commands import * import supybot.plugins as plugins import supybot.ircmsgs as ircmsgs import supybot.ircutils as ircutils +import supybot.registry as registry import supybot.callbacks as callbacks +from supybot.i18n import PluginInternationalization +from supybot.i18n import internationalizeDocstring +_ = PluginInternationalization('Listener') + +def serialize_relay(relay): + format_ = _('from %(host)s:%(port)s to %(channel)s@%(network)s') + return format_ % relay class Listener(callbacks.Plugin): """Add the help for "@plugin help Listener" here @@ -48,13 +61,33 @@ class Listener(callbacks.Plugin): def __init__(self, irc): self.__parent = super(Listener, self) self.__parent.__init__(irc) - self.buffer = '' - self.channel = '#supybot-bots' # set this - self.network = 'freenode' # ...and this - self.host = 'localhost' # ...and this - self.port = 56789 # ...and this. - self.listenerThread = self.ListeningThread(self.network, self.channel, self.host, self.port) - self.listenerThread.start() + self.listenerThreads = [] + try: + conf.supybot.plugins.Listener.relays.addCallback( + self._loadFromConfig) + except registry.NonExistentRegistryEntry: + log.error("Your version of Supybot is not compatible with " + "configuration hooks. So, Listener won't be able " + "to reload the configuration if you use the Config " + "plugin.") + self._loadFromConfig() + + def _loadFromConfig(self, name=None): + relays = json.loads(self.registryValue('relays')) + for thread in self.listenerThreads: + thread.active = False + thread.listener.close() + time.sleep(2) + self.listenerThreads = [] + for relay in relays: + try: + log.debug('Starting listener thread: %s' % + serialize_relay(relay)) + thread = self.ListeningThread(**relay) + thread.start() + self.listenerThreads.append(thread) + except TypeError: + irc.error('Cannot load relay: %s' % serialize_relay(relay)) class ListeningThread(threading.Thread): @@ -83,23 +116,74 @@ class Listener(callbacks.Plugin): if self.buffer: for IRC in world.ircs: if IRC.network == self.network: - IRC.queueMsg(ircmsgs.privmsg(self.channel, self.buffer)) + try: + IRC.queueMsg(ircmsgs.privmsg(self.channel, self.buffer)) + except Exception as e: + traceback.print_exc(e) self.buffer = '' self.listener.close() + def add(self, irc, msg, args, channel, network, host, port): + """[] [] + + Start listening on : and relays messages to @ + . + and default to the current ones.""" + relays = json.loads(self.registryValue('relays')) + relay = {'channel': channel, 'network': network.network, + 'host': host, 'port': port} + if relay in relays: + irc.error(_('This relay already exists.'), Raise=True) + relays.append(relay) + self.setRegistryValue('relays', value=json.dumps(relays)) + self._loadFromConfig() + irc.replySuccess() + add = wrap(add, ['channel', 'networkIrc', 'somethingWithoutSpaces', + ('int', 'port', lambda x: (x<65536))]) + + def remove(self, irc, msg, args, channel, network, host, port): + """[] [] + + Start listening on : and relays messages to @ + . + and default to the current ones.""" + relays = json.loads(self.registryValue('relays')) + relay = {'channel': channel, 'network': network.network, + 'host': host, 'port': port} + try: + relays.remove(relay) + except ValueError: + irc.error(_('This relay does not exist.'), Raise=True) + self.setRegistryValue('relays', value=json.dumps(relays)) + self._loadFromConfig() + irc.replySuccess() + remove = wrap(remove, ['channel', 'networkIrc', 'somethingWithoutSpaces', + ('int', 'port', lambda x: (x<65536))]) + + def list(self, irc, msg, args): + """takes no arguments + + Return a list of all relays.""" + relays = json.loads(self.registryValue('relays')) + irc.replies([serialize_relay(x) for x in relays]) + list = wrap(list) def stop(self, irc, msg, args): """takes no arguments - Tries to close the listening socket""" - self.listenerThread.active = False - self.listenerThread.listener.close() + Tries to close all listening sockets""" + for thread in self.listenerThreads: + thread.active = False + thread.listener.close() + self.listenerThreads = [] irc.replySuccess() stop = wrap(stop) def die(self): - self.listenerThread.active = False - self.listenerThread.listener.close() + for thread in self.listenerThreads: + thread.active = False + thread.listener.close() + self.listenerThreads = [] time.sleep(2) Class = Listener