diff --git a/hooks.py b/hooks.py index 0bc6d0e..76f50c2 100644 --- a/hooks.py +++ b/hooks.py @@ -18,6 +18,10 @@ class MessagesHook: def __init__(self): + # Store specials hook + self.all_pre = list() # Treated before any parse + #self.all_post = list() # Treated before send message to user + # Store direct hook self.cmd_hook = dict() self.ask_hook = dict() @@ -28,6 +32,11 @@ class MessagesHook: self.ask_rgxp = list() self.msg_rgxp = list() + # Store default hooks (after other hooks if no match) + self.cmd_default = list() + self.ask_default = list() + self.msg_default = list() + def add_hook(self, store, hook): """Insert in the right place a hook into the given store""" @@ -40,42 +49,29 @@ class MessagesHook: else: print ("Warning: unrecognized hook store type") + def register_hook_attributes(self, store, module, node): + if node.hasAttribute("name"): + self.add_hook(getattr(self, store + "_hook"), Hook(getattr(module, + node["call"]), + node["name"])) + elif node.hasAttribute("regexp"): + self.add_hook(getattr(self, store + "_rgxp"), Hook(getattr(module, + node["call"]), + None, None, + node["regexp"])) + def register_hook(self, module, node): """Create a hook from configuration node""" if node.name == "message" and node.hasAttribute("type"): if node["type"] == "cmd" or node["type"] == "all": - if node.hasAttribute("name"): - self.add_hook(self.cmd_hook, Hook(getattr(module, - node["call"]), - node["name"])) - elif node.hasAttribute("regexp"): - self.add_hook(self.cmd_rgxp, Hook(getattr(module, - node["call"]), - None, None, - node["regexp"])) + self.register_hook_attributes("cmd", module, node) if node["type"] == "ask" or node["type"] == "all": - if node.hasAttribute("name"): - self.add_hook(self.ask_hook, Hook(getattr(module, - node["call"]), - node["name"])) - elif node.hasAttribute("regexp"): - self.add_hook(self.ask_rgxp, Hook(getattr(module, - node["call"]), - None, None, - node["regexp"])) - - if node["type"] == "answer" or node["type"] == "all": - if node.hasAttribute("name"): - self.add_hook(self.msg_hook, Hook(getattr(module, - node["call"]), - node["name"])) - elif node.hasAttribute("regexp"): - self.add_hook(self.msg_rgxp, Hook(getattr(module, - node["call"]), - None, None, - node["regexp"])) + self.register_hook_attributes("ask", module, node) + if (node["type"] == "msg" or node["type"] == "answer" or + node["type"] == "all"): + self.register_hook_attributes("answer", module, node) def check_rest_times(self, store, hook): """Remove from store the hook if it has been executed given time""" @@ -87,65 +83,105 @@ class MessagesHook: elif isinstance(store, list): store.remove(hook) + def treat_pre(self, msg): + """Treat a message before all other treatment""" + for h in self.all_pre: + h.run(msg) + self.check_rest_times(self.all_pre, h) + + def treat_cmd(self, msg): """Treat a command message""" + treated = False # First, treat simple hook if msg.cmd[0] in self.cmd_hook: for h in self.cmd_hook[msg.cmd[0]]: - h.run(msg) + treated |= h.run(msg) self.check_rest_times(self.cmd_hook, h) # Then, treat regexp based hook for hook in self.cmd_rgxp: - if hook.is_matching(msg): - hook.run(msg) + if hook.is_matching(msg.cmd[0], msg.channel): + treated |= hook.run(msg) self.check_rest_times(self.cmd_rgxp, hook) + # Finally, treat default hooks if not catched before + for hook in self.cmd_default: + if treated: + break + treated |= hook.run(msg) + self.check_rest_times(self.cmd_default, hook) + + def treat_ask(self, msg): """Treat an ask message""" + treated = False # First, treat simple hook if msg.content in self.ask_hook: for h in self.ask_hook[msg.content]: - h.run(msg) + treated |= h.run(msg) self.check_rest_times(self.ask_hook, h) # Then, treat regexp based hook for hook in self.ask_rgxp: - if hook.is_matching(msg): - hook.run(msg) + if hook.is_matching(msg.content, msg.channel): + treated |= hook.run(msg) self.check_rest_times(self.ask_rgxp, hook) + # Finally, treat default hooks if not catched before + for hook in self.ask_default: + if treated: + break + treated |= hook.run(msg) + self.check_rest_times(self.ask_default, hook) + + def treat_answer(self, msg): """Treat a normal message""" # First, treat simple hook if msg.content in self.msg_hook: - for h in self.msg_hook[msg.cmd[0]]: + for h in self.msg_hook[msg.content]: h.run(msg) self.check_rest_times(self.msg_hook, h) # Then, treat regexp based hook for hook in self.msg_rgxp: - if hook.is_matching(msg): + if hook.is_matching(msg.content, msg.channel): hook.run(msg) self.check_rest_times(self.msg_rgxp, hook) + # Finally, treat default hooks if not catched before + for hook in self.msg_default: + if treated: + break + treated |= hook.run(msg) + self.check_rest_times(self.msg_default, hook) + class Hook: """Class storing hook informations""" - def __init__(self, call, name=None, data=None, regexp=None): + def __init__(self, call, name=None, data=None, regexp=None, channels=list()): self.name = name self.call = call self.regexp = regexp self.data = data self.times = -1 + self.channels = channels - def is_matching(self, strcmp): + def is_matching(self, strcmp, channel): """Test if the current hook correspond to the message""" - return (self.name is not None and strcmp == self.name) or ( - self.regexp is not None and re.match(self.regexp, strcmp)) + return (len(self.channel) <= 0 or channel in self.channels) and ( + (self.name is not None and strcmp == self.name) or ( + self.regexp is not None and re.match(self.regexp, strcmp))) def run(self, msg): """Run the hook""" - if self.times > 0: + if self.times != 0: self.times -= 1 - return self.call(self.data, msg) + + if self.data is None: + return self.call(msg) + elif isinstance(self.data, dict): + return self.call(msg, **self.data) + else: + return self.call(msg, self.data) diff --git a/importer.py b/importer.py index 9288eb4..4277763 100644 --- a/importer.py +++ b/importer.py @@ -21,6 +21,8 @@ from importlib.abc import SourceLoader import imp import os import sys + +from hooks import Hook import xmlparser class ModuleFinder(Finder): @@ -206,6 +208,14 @@ def register_hooks(module, context, prompt): for msg in module.CONF.getNodes("message"): context.hooks.register_hook(module, msg) + # Register legacy hooks + if hasattr(module, "parseanswer"): + context.hooks.add_hook(context.hooks.cmd_default, Hook(module.parseanswer)) + if hasattr(module, "parseask"): + context.hooks.add_hook(context.hooks.ask_default, Hook(module.parseask)) + if hasattr(module, "parselisten"): + context.hooks.add_hook(context.hooks.ask_default, Hook(module.parselisten)) + ########################## # # # Module functions # diff --git a/modules/events/__init__.py b/modules/events/__init__.py index 10152bf..0106491 100644 --- a/modules/events/__init__.py +++ b/modules/events/__init__.py @@ -47,7 +47,7 @@ def fini(strend): DATAS.delChild(DATAS.index[strend["name"]]) save() -def cmd_we(data, msg): +def cmd_we(msg): ndate = datetime.today() + timedelta(5 - datetime.today().weekday()) ndate = datetime(ndate.year, ndate.month, ndate.day, 0, 0, 1) msg.send_chn ( @@ -55,19 +55,19 @@ def cmd_we(data, msg): "Il reste %s avant le week-end, courage ;)", "Youhou, on est en week-end depuis %s.")) -def cmd_newyear(data, msg): +def cmd_newyear(msg): msg.send_chn ( msg.countdown_format (datetime(datetime.today().year + 1, 1, 1, 0, 0, 1), "Il reste %s avant la nouvelle année.", "Nous faisons déjà la fête depuis %s !")) -def cmd_vacances(data, msg): +def cmd_vacances(msg): msg.send_chn ( msg.countdown_format (datetime(2012, 7, 30, 18, 0, 1), "Il reste %s avant les vacances :)", "Profitons, c'est les vacances depuis %s.")) -def start_countdown(data, msg): +def start_countdown(msg): if msg.cmd[1] not in DATAS: strnd = ModuleState("strend") diff --git a/modules/qd/__init__.py b/modules/qd/__init__.py index f18494a..871512b 100644 --- a/modules/qd/__init__.py +++ b/modules/qd/__init__.py @@ -16,19 +16,19 @@ temps = dict () SCORES = None -def load(): - global DATAS, SCORES, CONF - DATAS.setIndex("name", "player") - SCORES = QDWrapper.QDWrapper(DATAS) - GameUpdater.SCORES = SCORES - GameUpdater.CONF = CONF - GameUpdater.save = save - GameUpdater.getUser = getUser +def load(context): + global DATAS, SCORES, CONF + DATAS.setIndex("name", "player") + SCORES = QDWrapper.QDWrapper(DATAS) + GameUpdater.SCORES = SCORES + GameUpdater.CONF = CONF + GameUpdater.save = save + GameUpdater.getUser = getUser def reload(): - imp.reload(GameUpdater) - imp.reload(QDWrapper) - imp.reload(Score) + imp.reload(GameUpdater) + imp.reload(QDWrapper) + imp.reload(Score) def help_tiny (): diff --git a/modules/sleepytime.py b/modules/sleepytime.py index 71c84db..890f974 100644 --- a/modules/sleepytime.py +++ b/modules/sleepytime.py @@ -20,7 +20,7 @@ def load(context): context.hooks.add_hook(context.hooks.cmd_hook, Hook(cmd_sleep, "sleepytime")) -def cmd_sleep(data, msg): +def cmd_sleep(msg): if len (msg.cmd) > 1 and re.match("[0-9]{1,2}[h':.,-]([0-9]{1,2})?[m'\":.,-]?", msg.cmd[1]) is not None: # First, parse the hour diff --git a/modules/syno.py b/modules/syno.py index 579004a..2d230b9 100644 --- a/modules/syno.py +++ b/modules/syno.py @@ -19,7 +19,7 @@ def load(context): context.hooks.add_hook(context.hooks.cmd_hook, Hook(cmd_syno, "synonyme")) -def cmd_syno(data, msg): +def cmd_syno(msg): if 1 < len(msg.cmd) < 6: for word in msg.cmd[1:]: synos = get_synos(word) diff --git a/modules/translate.py b/modules/translate.py index 055408b..605bfde 100644 --- a/modules/translate.py +++ b/modules/translate.py @@ -8,7 +8,7 @@ from urllib.parse import quote nemubotversion = 3.2 -import module_states_file as xmlparser +import xmlparser LANG = ["ar", "zh", "cz", "en", "fr", "gr", "it", "ja", "ko", "pl", "pt", "ro", "es", "tr"] @@ -25,7 +25,7 @@ def load(context): Hook(cmd_translate, "traduire")) -def cmd_translate(data, msg): +def cmd_translate(msg): global LANG startWord = 1 if msg.cmd[startWord] in LANG: diff --git a/modules/velib.py b/modules/velib.py index 51e3540..5c79fb3 100644 --- a/modules/velib.py +++ b/modules/velib.py @@ -78,7 +78,7 @@ def print_station_status(msg, station): else: msg.send_chn("%s: station %s inconnue." % (msg.nick, station)) -def ask_stations(data, msg): +def ask_stations(msg): """Hook entry from !velib""" global DATAS if len(msg.cmd) > 5: