diff --git a/plugins/figlet.py b/plugins/figlet.py new file mode 100644 index 00000000..ccff687a --- /dev/null +++ b/plugins/figlet.py @@ -0,0 +1,11 @@ +from plugin import BasePlugin +import subprocess + +class Plugin(BasePlugin): + def init(self): + self.add_poezio_event_handler('muc_say', self.figletize) + + def figletize(self, msg): + process = subprocess.Popen(['figlet', msg['body']], stdout=subprocess.PIPE) + result = process.communicate()[0].decode('utf-8') + msg['body'] = result diff --git a/src/core.py b/src/core.py index aab82768..10e114e0 100644 --- a/src/core.py +++ b/src/core.py @@ -33,6 +33,7 @@ import multiuserchat as muc import tabs import xhtml +import events import pubsub import windows import connection @@ -80,12 +81,6 @@ class Core(object): User interface using ncurses """ - # dict containing the name of the internal events - # used with the plugins, the key is the name of the event - # and the value is the number of arguments the handler must take - internal_events = { - 'enter': 2, - } def __init__(self): # All uncaught exception are given to this callback, instead # of being displayed on the screen and exiting the program. @@ -93,6 +88,7 @@ class Core(object): self.status = Status(show=None, message='') sys.excepthook = self.on_exception self.running = True + self.events = events.EventHandler() self.xmpp = singleton.Singleton(connection.Connection) self.remote_fifo = None # a unique buffer used to store global informations @@ -180,6 +176,7 @@ class Core(object): self.timed_events = set() self.connected_events = {} + self.autoload_plugins() def autoload_plugins(self): @@ -213,57 +210,6 @@ class Core(object): )) self.refresh_window() - def connect(self, event, handler): - """ - Connect an handler to an internal event of poezio - (eg "enter pressed in a chattab") - """ - # Fail if the method doesn’t take at least the good number of arguments - # or if the event is unknown - if not event in self.internal_events \ - or len(getargspec(handler).args) < self.internal_events[event]: - return False - - module_name = handler.__module__ - if not event in self.connected_events: - self.connected_events[event] = {} - if not module_name in self.connected_events[event]: - self.connected_events[event][module_name] = [] - - self.connected_events[event][module_name].append(handler) - return True - - def run_event(self, event, **kwargs): - """ - Call the handlers associated with an event - """ - if event in self.connected_events: - for module in self.connected_events[event]: - for handler in self.connected_events[event][module]: - try: - handler(**kwargs) - except: - import traceback - tp = traceback.format_exc() - module_name = handler.__name__ - log.debug('ERROR: in plugin %s, \n%s' % (module_name, tp)) - - def disconnect(self, event, handler): - """ - Disconnect a handler from an event - """ - if not event in self.internal_events: - return False - - module_name = getmodule(handler).__name__ - if not event in self.connected_events: - return False - if not module_name in self.connected_events[event]: - return False - - self.connected_events[event][module_name].remove(handler) - return True - def resize_global_information_win(self): """ Resize the global_information_win only once at each resize. diff --git a/src/plugin.py b/src/plugin.py index a8eb5934..0b4f3f3a 100644 --- a/src/plugin.py +++ b/src/plugin.py @@ -84,3 +84,9 @@ class BasePlugin(object, metaclass=SafetyMetaclass): def del_event_handler(self, event_name, handler): return self.plugin_manager.del_event_handler(self.__module__, event_name, handler) + + def add_poezio_event_handler(self, event_name, handler, first=True, last=False, position=None): + return self.plugin_manager.add_poezio_event_handler(self.__module__, event_name, handler, first, last, position) + + def del_poezio_event_handler(self, event_name, handler): + return self.plugin_manager.del_poezio_event_handler(self.__module__, event_name, handler) diff --git a/src/plugin_manager.py b/src/plugin_manager.py index 5bd6d75b..37db3d13 100644 --- a/src/plugin_manager.py +++ b/src/plugin_manager.py @@ -34,6 +34,7 @@ class PluginManager(object): self.plugins = {} # module name -> plugin object self.commands = {} # module name -> dict of commands loaded for the module self.event_handlers = {} # module name -> list of event_name/handler pairs loaded for the module + self.poezio_event_handlers = {} def load(self, name): if name in self.plugins: @@ -60,6 +61,7 @@ class PluginManager(object): self.modules[name] = module self.commands[name] = {} self.event_handlers[name] = [] + self.poezio_event_handlers[name] = [] self.plugins[name] = module.Plugin(self, self.core, plugins_conf_dir) def unload(self, name): @@ -69,14 +71,14 @@ class PluginManager(object): del self.core.commands[command] for event_name, handler in self.event_handlers[name]: self.core.xmpp.del_event_handler(event_name, handler) - for event_name in self.core.internal_events: - if name in event_name: - del event_name[name] + for handler in self.poezio_event_handlers[name]: + self.core.events.del_event_handler(None, handler) self.plugins[name].unload() del self.plugins[name] del self.commands[name] del self.event_handlers[name] + del self.poezio_event_handlers[name] except Exception as e: import traceback self.core.information(_("Could not unload plugin (may not be safe to try again): ") + traceback.format_exc()) @@ -105,6 +107,16 @@ class PluginManager(object): eh = self.event_handlers[module_name] eh = list(filter(lambda e : e != (event_name, handler), eh)) + def add_poezio_event_handler(self, module_name, event_name, handler, first, last, position): + eh = self.poezio_event_handlers[module_name] + eh.append(handler) + self.core.events.add_event_handler(event_name, handler, first, last, position) + + def del_poezio_event_handler(self, module_name, event_name, handler): + self.core.events.del_event_handler(None, handler) + eh = self.poezio_event_handlers[module_name] + eh = list(filter(lambda e : e != handler, eh)) + def completion_load(self, the_input): """ completion function that completes the name of the plugins, from diff --git a/src/tabs.py b/src/tabs.py index 78f56bdb..cae188ae 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -323,8 +323,7 @@ class ChatTab(Tab): if not self.execute_command(clean_text): if txt.startswith('//'): txt = txt[1:] - self.core.run_event('enter', line=txt) - self.command_say(txt) + self.command_say(xhtml.convert_simple_to_full_colors(txt)) self.cancel_paused_delay() def send_chat_state(self, state, always_send=False): @@ -602,7 +601,7 @@ class MucTab(ChatTab): r = self.core.open_private_window(self.name, user.nick) if r and len(args) > 1: msg = arg[len(nick)+1:] - self.core.current_tab().command_say(msg) + self.core.current_tab().command_say(xhtml.convert_simple_to_full_colors(msg)) if not r: self.core.information(_("Cannot find user: %s" % nick), 'Error') @@ -719,10 +718,11 @@ class MucTab(ChatTab): if line.find('\x19') == -1: msg['body'] = line else: - msg['body'] = xhtml.clean_text_simple(line) + msg['body'] = xhtml.clean_text(line) msg['xhtml_im'] = xhtml.poezio_colors_to_html(line) if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: msg['chat_state'] = needed + self.core.events.trigger('muc_say', msg) self.cancel_paused_delay() msg.send() self.chat_state = needed @@ -1211,11 +1211,12 @@ class PrivateTab(ChatTab): if line.find('\x19') == -1: msg['body'] = line else: - msg['body'] = xhtml.clean_text_simple(line) + msg['body'] = xhtml.clean_text(line) msg['xhtml_im'] = xhtml.poezio_colors_to_html(line) if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active' msg['chat_state'] = needed + self.core.events.trigger('private_say', msg) msg.send() self.core.add_message_to_text_buffer(self._text_buffer, xhtml.convert_simple_to_full_colors(line), None, self.core.own_nick or self.own_nick) self.cancel_paused_delay() @@ -1874,11 +1875,12 @@ class ConversationTab(ChatTab): if line.find('\x19') == -1: msg['body'] = line else: - msg['body'] = xhtml.clean_text_simple(line) + msg['body'] = xhtml.clean_text(line) msg['xhtml_im'] = xhtml.poezio_colors_to_html(line) if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active' msg['chat_state'] = needed + self.core.events.trigger('conversation_say', msg) msg.send() self.core.add_message_to_text_buffer(self._text_buffer, xhtml.convert_simple_to_full_colors(line), None, self.core.own_nick) logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)