diff --git a/bot.py b/bot.py
index a57b341..5eb8d85 100644
--- a/bot.py
+++ b/bot.py
@@ -16,6 +16,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+from datetime import datetime
+import threading
+
import event
import hooks
from server import Server
@@ -33,6 +36,46 @@ class Bot:
self.hooks = hooks.MessagesHook()
self.events = list()
+ self.event_timer = None
+
+
+ def add_event(self, evt):
+ # Add the event in place
+ t = evt.current
+ i = 0
+ for i in range(0, len(self.events)):
+ if self.events[i].current > t:
+ break
+ self.events.insert(i, evt)
+ if i == 0:
+ self.update_timer()
+
+ def update_timer(self):
+ # Reset the timer if this is the first item
+ if self.event_timer is not None:
+ self.event_timer.cancel()
+ if len(self.events) > 0:
+ #print ("Update timer, next in", self.events[0].time_left.seconds,
+ # "seconds")
+ if datetime.now() >= self.events[0].current:
+ self.end_timer()
+ else:
+ self.event_timer = threading.Timer(
+ self.events[0].time_left.seconds + 1, self.end_timer)
+ self.event_timer.start()
+ #else:
+ # print ("Update timer: no timer left")
+
+
+ def end_timer(self):
+ #print ("end timer")
+ while len(self.events)>0 and datetime.now() >= self.events[0].current:
+ #print ("end timer: while")
+ evt = self.events.pop(0)
+ evt.launch_check()
+ if evt.next is not None:
+ self.add_event(evt)
+ self.update_timer()
def addServer(self, node, nick, owner, realname):
diff --git a/event.py b/event.py
index ccba1d1..f1137d4 100644
--- a/event.py
+++ b/event.py
@@ -16,11 +16,12 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-import threading
+from datetime import datetime
+from datetime import timedelta
class ModuleEvent:
- def __init__(self, func, func_data, check, cmp_data, intervalle=60,
- call=None, call_data=None, times=1):
+ def __init__(self, func=None, func_data=None, check=None, cmp_data=None,
+ intervalle=60, call=None, call_data=None, times=1):
# What have we to check?
self.func = func
self.func_data = func_data
@@ -29,10 +30,16 @@ class ModuleEvent:
self.check = check
if cmp_data is not None:
self.cmp_data = cmp_data
- else:
- self.cmp_data = self.func(self.func_data)
+ elif self.func is not None:
+ if self.func_data is None:
+ self.cmp_data = self.func()
+ elif isinstance(self.func_data, dict):
+ self.cmp_data = self.func(**self.func_data)
+ else:
+ self.cmp_data = self.func(self.func_data)
- self.intervalle = intervalle
+ self.intervalle = timedelta(seconds=intervalle)
+ self.end = None
# What should we call when
self.call = call
@@ -45,21 +52,58 @@ class ModuleEvent:
self.times = times
- def launch_check(self):
- d = self.func(self.func_data)
- #print ("do test with", d, self.cmp_data)
- if self.check(d, self.cmp_data):
- self.call(self.call_data)
- self.times -= 1
- self.run()
-
- def run(self):
+ @property
+ def next(self):
+ """Return the date of the next check"""
if self.times != 0:
- #print ("run timer")
- self.timer = threading.Timer(self.intervalle, self.launch_check)
- self.timer.start()
- #else:
- #print ("no more times")
+ if self.end is None:
+ self.end = datetime.now() + self.intervalle
+ elif self.end < datetime.now():
+ self.end += self.intervalle
+ return self.end
+ return None
- def stop(self):
- self.timer.cancel()
+ @property
+ def current(self):
+ """Return the date of the near check"""
+ if self.times != 0:
+ if self.end is None:
+ self.end = datetime.now() + self.intervalle
+ 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
+
+ def launch_check(self):
+ if self.func is None:
+ d = self.func_data
+ elif self.func_data is None:
+ d = self.func()
+ elif isinstance(self.func_data, dict):
+ d = self.func(**self.func_data)
+ else:
+ d = self.func(self.func_data)
+ #print ("do test with", d, self.cmp_data)
+
+ if self.check is None:
+ r = True
+ elif self.cmp_data is None:
+ r = self.check(d)
+ elif isinstance(self.cmp_data, dict):
+ r = self.check(d, **self.cmp_data)
+ else:
+ r = self.check(d, self.cmp_data)
+
+ if r:
+ self.times -= 1
+ if self.call_data is None:
+ self.call()
+ elif isinstance(self.call_data, dict):
+ self.call(**self.call_data)
+ else:
+ self.call(self.call_data)
diff --git a/modules/velib.py b/modules/velib.py
index ca9915f..51e3540 100644
--- a/modules/velib.py
+++ b/modules/velib.py
@@ -16,8 +16,7 @@ def load(context):
evt = ModuleEvent(station_available, "42706",
(lambda a, b: a != b), None, 60,
station_status)
- context.events.append(evt)
- evt.run()
+ context.add_event(evt)
def help_tiny ():
"""Line inserted in the response to the command !help"""