From acded35e1a74caff0dc0ecafa2c3a5c7bd7fd389 Mon Sep 17 00:00:00 2001 From: nemunaire Date: Tue, 23 Sep 2014 22:27:53 +0200 Subject: [PATCH] Pick events class from v4 --- consumer.py | 10 ++- event.py | 103 +++++++++++++++++++------------ modules/bonneannee.py | 2 +- modules/events.py | 10 +-- modules/watchWebsite/__init__.py | 2 +- modules/worldcup.py | 4 +- 6 files changed, 82 insertions(+), 49 deletions(-) diff --git a/consumer.py b/consumer.py index 26904c6..f5274ce 100644 --- a/consumer.py +++ b/consumer.py @@ -205,11 +205,17 @@ class EventConsumer: def run(self, context): try: - self.evt.launch_check() + self.evt.check() except: logger.exception("Error during event end") + + # Reappend the event in the queue if it has next iteration if self.evt.next is not None: - context.add_event(self.evt, self.evt.id) + context.add_event(self.evt, eid=self.evt.id) + + # Or remove reference of this event + elif hasattr(self.evt, "module_src") and self.evt.module_src is not None: + self.evt.module_src.REGISTERED_EVENTS.remove(self.evt.id) diff --git a/event.py b/event.py index 89b10f3..fc90785 100644 --- a/event.py +++ b/event.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -# Nemubot is a modulable IRC bot, built around XML configuration files. -# Copyright (C) 2012 Mercier Pierre-Olivier +# Nemubot is a smart and modulable IM bot. +# Copyright (C) 2012-2014 nemunaire # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -16,18 +16,36 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from datetime import datetime -from datetime import timedelta +from datetime import datetime, timedelta class ModuleEvent: - def __init__(self, func=None, func_data=None, check=None, cmp_data=None, - intervalle=60, offset=0, call=None, call_data=None, times=1): + + """Representation of a event initiated by a bot module""" + + def __init__(self, call=None, call_data=None, func=None, func_data=None, + cmp=None, cmp_data=None, interval=60, offset=0, times=1): + + """Initialize the event + + Keyword arguments: + call -- Function to call when the event is realized + call_data -- Argument(s) (single or dict) to pass as argument + func -- Function called to check + func_data -- Argument(s) (single or dict) to pass as argument OR if no func, initial data to watch + cmp -- Boolean function called to check changes + cmp_data -- Argument(s) (single or dict) to pass as argument OR if no cmp, data compared to previous + interval -- Time in seconds between each check (default: 60) + offset -- Time in seconds added to interval before the first check (default: 0) + times -- Number of times the event has to be realized before being removed; -1 for no limit (default: 1) + """ + # What have we to check? self.func = func self.func_data = func_data # How detect a change? - self.check = check + self.cmp = cmp + self.cmp_data = None if cmp_data is not None: self.cmp_data = cmp_data elif self.func is not None: @@ -37,20 +55,19 @@ class ModuleEvent: self.cmp_data = self.func(**self.func_data) else: self.cmp_data = self.func(self.func_data) - else: - self.cmp_data = None - self.offset = timedelta(seconds=offset) # Time to wait before the first check - self.intervalle = timedelta(seconds=intervalle) - self.end = None - - # What should we call when + # What should we call when? self.call = call if call_data is not None: self.call_data = call_data else: self.call_data = func_data + # Store times + self.offset = timedelta(seconds=offset) # Time to wait before the first check + self.interval = timedelta(seconds=interval) + self._end = None # Cache + # How many times do this event? self.times = times @@ -59,60 +76,68 @@ class ModuleEvent: def current(self): """Return the date of the near check""" if self.times != 0: - if self.end is None: - self.end = datetime.now() + self.offset + self.intervalle - return self.end + if self._end is None: + self._end = datetime.now() + self.offset + self.interval + return self._end return None + @property def next(self): """Return the date of the next check""" if self.times != 0: - if self.end is None: + if self._end is None: return self.current - elif self.end < datetime.now(): - self.end += self.intervalle - return self.end + elif self._end < datetime.now(): + self._end += self.interval + return self._end return None + @property def time_left(self): """Return the time left before/after the near check""" if self.current is not None: return self.current - datetime.now() - return 99999 + return 99999 #TODO: 99999 is not a valid time to return - def launch_check(self): + + def check(self): + """Run a check and realized the event if this is time""" + + # Get initial data if self.func is None: - d = self.func_data + d_init = self.func_data elif self.func_data is None: - d = self.func() + d_init = self.func() elif isinstance(self.func_data, dict): - d = self.func(**self.func_data) + d_init = self.func(**self.func_data) else: - d = self.func(self.func_data) - #print ("do test with", d, self.cmp_data) + d_init = self.func(self.func_data) - if self.check is None: + # then compare with current data + if self.cmp is None: if self.cmp_data is None: - r = True + rlz = True else: - r = d != self.cmp_data + rlz = (d_init != self.cmp_data) elif self.cmp_data is None: - r = self.check(d) + rlz = self.cmp(d_init) elif isinstance(self.cmp_data, dict): - r = self.check(d, **self.cmp_data) + rlz = self.cmp(d_init, **self.cmp_data) else: - r = self.check(d, self.cmp_data) + rlz = self.cmp(d_init, self.cmp_data) - if r: + if rlz: self.times -= 1 + + # Call attended function if self.call_data is None: - if d is None: + if d_init is None: self.call() else: - self.call(d) + self.call(d_init) elif isinstance(self.call_data, dict): - self.call(d, **self.call_data) + self.call(d_init, **self.call_data) else: - self.call(d, self.call_data) + self.call(d_init, self.call_data) diff --git a/modules/bonneannee.py b/modules/bonneannee.py index 0d8f180..c5bff46 100644 --- a/modules/bonneannee.py +++ b/modules/bonneannee.py @@ -14,7 +14,7 @@ yrn = datetime.today().year + 1 def load(context): d = datetime(yrn, 1, 1, 0, 0, 0) - datetime.now() - add_event(ModuleEvent(intervalle=0, offset=d.total_seconds(), call=bonneannee)) + add_event(ModuleEvent(interval=0, offset=d.total_seconds(), call=bonneannee)) def bonneannee(): txt = "Bonne année %d !" % datetime.today().year diff --git a/modules/events.py b/modules/events.py index 12cbb36..78a1236 100644 --- a/modules/events.py +++ b/modules/events.py @@ -29,7 +29,7 @@ def load(context): for evt in DATAS.index.keys(): if DATAS.index[evt].hasAttribute("end"): event = ModuleEvent(call=fini, call_data=dict(strend=DATAS.index[evt])) - event.end = DATAS.index[evt].getDate("end") + event._end = DATAS.index[evt].getDate("end") idt = context.add_event(event) if idt is not None: DATAS.index[evt]["id"] = idt @@ -101,7 +101,7 @@ def start_countdown(msg): strnd["end"] = datetime(now.year, now.month, now.day, hou, minu, sec) else: strnd["end"] = datetime(now.year, now.month, now.day + 1, hou, minu, sec) - evt.end = strnd.getDate("end") + evt._end = strnd.getDate("end") strnd["id"] = add_event(evt) except: DATAS.delChild(strnd) @@ -122,8 +122,10 @@ def start_countdown(msg): strnd["end"] += timedelta(days=int(t)*365) else: strnd["end"] += timedelta(seconds=int(t)) - evt.end = strnd.getDate("end") - strnd["id"] = add_event(evt) + evt._end = strnd.getDate("end") + eid = add_event(evt) + if eid is not None: + strnd["id"] = eid save() if "end" in strnd: diff --git a/modules/watchWebsite/__init__.py b/modules/watchWebsite/__init__.py index 1da0ff8..efbcf52 100644 --- a/modules/watchWebsite/__init__.py +++ b/modules/watchWebsite/__init__.py @@ -38,7 +38,7 @@ def start_watching(site, offset=0): print_debug("Add event for site: %s" % o.netloc) evt = ModuleEvent(func=lambda url: w3m(url), cmp_data=site["lastcontent"], func_data=site["url"], offset=offset, - intervalle=site.getInt("time"), + interval=site.getInt("time"), call=alert_change, call_data=site) site["_evt_id"] = add_event(evt) diff --git a/modules/worldcup.py b/modules/worldcup.py index fc65daa..b4f42a8 100644 --- a/modules/worldcup.py +++ b/modules/worldcup.py @@ -16,7 +16,7 @@ API_URL="http://worldcup.sfg.io/%s" def load(context): from event import ModuleEvent - add_event(ModuleEvent(func=lambda url: urlopen(url, timeout=10).read().decode(), func_data=API_URL % "matches/current?by_date=DESC", call=current_match_new_action, intervalle=30)) + add_event(ModuleEvent(func=lambda url: urlopen(url, timeout=10).read().decode(), func_data=API_URL % "matches/current?by_date=DESC", call=current_match_new_action, interval=30)) def help_full (): @@ -66,7 +66,7 @@ def cmd_watch(msg): def current_match_new_action(match_str, osef): global DATAS - add_event(ModuleEvent(func=lambda url: urlopen(url).read().decode(), func_data=API_URL % "matches/current?by_date=DESC", call=current_match_new_action, intervalle=30)) + add_event(ModuleEvent(func=lambda url: urlopen(url).read().decode(), func_data=API_URL % "matches/current?by_date=DESC", call=current_match_new_action, interval=30)) matches = json.loads(match_str)