From 7a5edccb982a9aa3d1d1557d5928d03046bda29e Mon Sep 17 00:00:00 2001 From: jesopo Date: Tue, 8 Oct 2019 13:49:43 +0100 Subject: [PATCH] transient timers shouldn't use the event system --- modules/coins.py | 14 ++++++-------- modules/database_backup.py | 7 +++---- modules/kick-rejoin.py | 10 +++++----- modules/nick_regain.py | 16 ++++++++-------- modules/rss.py | 10 ++++------ src/IRCBot.py | 19 +++++++++---------- src/Timers.py | 32 +++++++++++++++++++++----------- 7 files changed, 56 insertions(+), 52 deletions(-) diff --git a/modules/coins.py b/modules/coins.py index 3bdf6fff..413714d2 100644 --- a/modules/coins.py +++ b/modules/coins.py @@ -41,9 +41,9 @@ class CoinParseException(Exception): class Module(ModuleManager.BaseModule): def on_load(self): - self.timers.add("coin-interest", INTEREST_INTERVAL, + self.timers.add("coin-interest", self._interest, INTEREST_INTERVAL, time.time()+self._until_next_hour()) - self.timers.add("coin-lottery", LOTTERY_INTERVAL, + self.timers.add("coin-lottery", self._lottery, LOTTERY_INTERVAL, time.time()+self._until_next_6_hour()) def _until_next_hour(self, now=None): @@ -440,8 +440,7 @@ class Module(ModuleManager.BaseModule): "%s loses %s" % (choice, event["user"].nickname, str(coin_losses))) - @utils.hook("timer.coin-interest") - def interest(self, event): + def _interest(self, timer): for server in self.bot.servers.values(): if not server.get_setting("coin-interest", False): continue @@ -456,7 +455,7 @@ class Module(ModuleManager.BaseModule): interest = round(coins*interest_rate, 2) server.set_user_setting(nickname, "coins", self._coin_str(coins+interest)) - event["timer"].redo() + timer.redo() @utils.hook("received.command.lotterybuy", authenticated=True) def lottery_buy(self, event): @@ -539,8 +538,7 @@ class Module(ModuleManager.BaseModule): else: event["stderr"].write("There have been no lottery winners!") - @utils.hook("timer.coin-lottery") - def lottery(self, event): + def _lottery(self, timer): for server in self.bot.servers.values(): lottery = server.get_setting("lottery", {}) if lottery: @@ -561,4 +559,4 @@ class Module(ModuleManager.BaseModule): server.set_setting("lottery-winner", user.nickname) user.send_notice("You won %s in the lottery! you now have %s coins" % (self._coin_str(winnings), self._coin_str(new_coins))) - event["timer"].redo() + timer.redo() diff --git a/modules/database_backup.py b/modules/database_backup.py index 55f18a13..2166be1d 100644 --- a/modules/database_backup.py +++ b/modules/database_backup.py @@ -10,11 +10,10 @@ class Module(ModuleManager.BaseModule): until_next_hour = 60-now.second until_next_hour += ((60-(now.minute+1))*60) - self.timers.add("database-backup", BACKUP_INTERVAL, + self.timers.add("database-backup", self._backup, BACKUP_INTERVAL, time.time()+until_next_hour) - @utils.hook("timer.database-backup") - def backup(self, event): + def _backup(self, timer): location = self.bot.database.location files = glob.glob("%s.*" % location) files = sorted(files) @@ -26,4 +25,4 @@ class Module(ModuleManager.BaseModule): backup_file = "%s.%s" % (location, suffix) shutil.copy2(location, backup_file) - event["timer"].redo() + timer.repo() diff --git a/modules/kick-rejoin.py b/modules/kick-rejoin.py index 1082f79f..b2d3d234 100644 --- a/modules/kick-rejoin.py +++ b/modules/kick-rejoin.py @@ -28,12 +28,12 @@ class Module(ModuleManager.BaseModule): if delay == 0: self._rejoin(event["server"], event["channel"].name) else: - self.timers.add("kick-rejoin", delay, server=event["server"], - channel_name=event["channel"].name) + self.timers.add("kick-rejoin", + self._timer(event["server"], event["channel"].name), + delay) - @utils.hook("timer.kick-rejoin") - def timer(self, event): - self._rejoin(event["server"], event["channel_name"]) + def _timer(self, server, channel_name): + return lambda timer: self._rejoin(server, channel_name) def _rejoin(self, server, channel_name): server.send_join(channel_name) diff --git a/modules/nick_regain.py b/modules/nick_regain.py index 20602dbb..cf1dfa48 100644 --- a/modules/nick_regain.py +++ b/modules/nick_regain.py @@ -7,7 +7,8 @@ class Module(ModuleManager.BaseModule): if "MONITOR" in server.isupport: server.send_raw("MONITOR + %s" % target_nick) else: - self.timers.add("ison-check", 30, server=server) + self.timers.add("ison-check", self._ison_check, 30, + server=server) @utils.hook("received.376") def end_of_motd(self, event): @@ -31,13 +32,12 @@ class Module(ModuleManager.BaseModule): if event["server"].irc_lower(target_nick) in nicks: event["server"].send_nick(target_nick) - @utils.hook("timer.ison-check") - def ison_check(self, event): - target_nick = event["server"].connection_params.nickname - if not event["server"].irc_equals( - event["server"].nickname, target_nick): - event["server"].send_raw("ISON %s" % target_nick) - event["timer"].redo() + def _ison_check(self, timer): + server = timer.kwargs["server"] + target_nick = server.connection_params.nickname + if not server.irc_equals(server.nickname, target_nick): + server.send_raw("ISON %s" % target_nick) + timer.redo() @utils.hook("received.303") def ison_response(self, event): diff --git a/modules/rss.py b/modules/rss.py index 235d8bb3..e8e237da 100644 --- a/modules/rss.py +++ b/modules/rss.py @@ -14,8 +14,8 @@ RSS_INTERVAL = 60 # 1 minute class Module(ModuleManager.BaseModule): _name = "RSS" def on_load(self): - self.timers.add("rss", self.bot.get_setting("rss-interval", - RSS_INTERVAL)) + self.timers.add("rss-feeds", self._timer, + self.bot.get_setting("rss-interval", RSS_INTERVAL)) def _format_entry(self, server, feed_title, entry, shorten): title = entry["title"] @@ -32,13 +32,11 @@ class Module(ModuleManager.BaseModule): return "%s%s%s%s" % (feed_title_str, title, author, link) - - @utils.hook("timer.rss") - def timer(self, event): + def _timer(self, timer): start_time = time.monotonic() self.log.trace("Polling RSS feeds") - event["timer"].redo() + timer.redo() hook_settings = self.bot.database.channel_settings.find_by_setting( "rss-hooks") hooks = {} diff --git a/src/IRCBot.py b/src/IRCBot.py index b03f2037..5e843054 100644 --- a/src/IRCBot.py +++ b/src/IRCBot.py @@ -1,7 +1,7 @@ import enum, queue, os, queue, select, socket, sys, threading, time, traceback import typing, uuid from src import EventManager, Exports, IRCServer, Logging, ModuleManager -from src import PollHook, Socket, utils +from src import PollHook, Socket, Timers, utils VERSION = "v1.11.1" SOURCE = "https://git.io/bitbot" @@ -83,8 +83,6 @@ class Bot(object): self._poll_timeouts.append(ListLambdaPollHook( lambda: self.servers.values(), self._throttle_timeout)) - self._events.on("timer.reconnect").hook(self._timed_reconnect) - def _throttle_timeout(self, server: IRCServer.Server): if server.socket.waiting_throttled_send(): return server.socket.send_throttle_timeout() @@ -216,12 +214,13 @@ class Bot(object): del self.servers[server.fileno()] self._trigger_both() - def _timed_reconnect(self, event: EventManager.Event): - if not self.reconnect(event["server_id"], - event.get("connection_params", None)): - event["timer"].redo() + def _timed_reconnect(self, timer: Timers.Timer): + server_id = timer.kwargs["server_id"] + params = timer.kwargs.get("connection_params", None) + if not self.reconnect(server_id, params): + timer.redo() else: - del self.reconnections[event["server_id"]] + del self.reconnections[server_id] def reconnect(self, server_id: int, connection_params: typing.Optional[ utils.irc.IRCConnectionParameters]=None) -> bool: args = {} # type: typing.Dict[str, str] @@ -395,8 +394,8 @@ class Bot(object): if not self.get_server_by_id(server.id): reconnect_delay = self.config.get("reconnect-delay", 10) - timer = self._timers.add("reconnect", reconnect_delay, - server_id=server.id) + self.timers.add("timed-reconnect", self._timed_reconnect, + reconnect_delay, server_id=server.id) self.reconnections[server.id] = timer self.log.warn( diff --git a/src/Timers.py b/src/Timers.py index e74d4a53..f913b781 100644 --- a/src/Timers.py +++ b/src/Timers.py @@ -1,9 +1,12 @@ import time, typing, uuid from src import Database, EventManager, Logging, PollHook +T_CALLBACK = typing.Callable[["Timer"], None] + class Timer(object): def __init__(self, id: str, context: typing.Optional[str], name: str, - delay: float, next_due: typing.Optional[float], kwargs: dict): + delay: float, next_due: typing.Optional[float], kwargs: dict, + callback: T_CALLBACK): self.id = id self.context = context self.name = name @@ -13,6 +16,7 @@ class Timer(object): else: self.set_next_due() self.kwargs = kwargs + self.callback = callback self._done = False def set_next_due(self): @@ -64,17 +68,24 @@ class Timers(PollHook.PollHook): self.timers.remove(timer) self.database.bot_settings.delete("timer-%s" % timer.id) - def add(self, name: str, delay: float, next_due: float=None, **kwargs - ) -> Timer: - return self._add(None, name, delay, next_due, None, False, kwargs) + def add(self, name: str, callback: T_CALLBACK, delay: float, + next_due: float=None, **kwargs) -> Timer: + return self._add(None, name, delay, next_due, None, False, kwargs, + callback=callback) def add_persistent(self, name: str, delay: float, next_due: float=None, **kwargs) -> Timer: return self._add(None, name, delay, next_due, None, True, kwargs) def _add(self, context: typing.Optional[str], name: str, delay: float, next_due: typing.Optional[float], id: typing.Optional[str], - persist: bool, kwargs: dict) -> Timer: + persist: bool, kwargs: dict, callback: T_CALLBACK=None) -> Timer: id = id or str(uuid.uuid4()) - timer = Timer(id, context, name, delay, next_due, kwargs) + + if not callback: + callback = lambda timer: self.events.on("timer.%s" % name).call( + timer=timer, **kwargs) + + timer = Timer(id, context, name, delay, next_due, kwargs, + callback=callback) if persist: self._persist(timer) @@ -110,8 +121,7 @@ class Timers(PollHook.PollHook): for timer in self.get_timers(): if timer.due(): timer.finish() - self.events.on("timer.%s" % timer.name).call(timer=timer, - **timer.kwargs) + timer.callback(timer) if timer.done(): self._remove(timer) @@ -123,10 +133,10 @@ class TimersContext(object): def __init__(self, parent: Timers, context: str): self._parent = parent self.context = context - def add(self, name: str, delay: float, next_due: float=None, - **kwargs) -> Timer: + def add(self, name: str, callback: T_CALLBACK, delay: float, + next_due: float=None, **kwargs) -> Timer: return self._parent._add(self.context, name, delay, next_due, None, - False, kwargs) + False, kwargs, callback=callback) def add_persistent(self, name: str, delay: float, next_due: float=None, **kwargs) -> Timer: return self._parent._add(None, name, delay, next_due, None, True,