From 0cc72d5d66bc3a6abf7757c7202905bd656ddf1d Mon Sep 17 00:00:00 2001 From: jesopo Date: Tue, 26 Dec 2017 10:32:36 +0000 Subject: [PATCH] Added a "replay" system to EventManager hooks, to replay missed .calls --- EventManager.py | 12 ++++++++-- IRCBot.py | 3 +-- IRCLineHandler.py | 56 +++++++++++++++++++++----------------------- IRCServer.py | 13 ++++++---- modules/auto_mode.py | 11 ++++----- modules/commands.py | 11 ++++----- modules/karma.py | 4 +--- modules/lastfm.py | 11 ++++----- modules/sed.py | 6 ++--- modules/set.py | 4 ++-- modules/trakt.py | 4 +--- modules/youtube.py | 8 +++---- 12 files changed, 72 insertions(+), 71 deletions(-) diff --git a/EventManager.py b/EventManager.py index 307b2e2e..486cc0ec 100644 --- a/EventManager.py +++ b/EventManager.py @@ -44,11 +44,17 @@ class EventHook(object): self._hook_notify = None self._child_notify = None self._call_notify = None - def hook(self, function, **kwargs): + self._stored_events = [] + def hook(self, function, replay=False, **kwargs): callback = EventCallback(function, self.bot, **kwargs) if self._hook_notify: self._hook_notify(self, callback) self._hooks.append(callback) + + if replay: + for event in self._stored_events: + callback.call(event) + self._stored_events = None def _unhook(self, hook): self._hooks.remove(hook) def on(self, subevent, *extra_subevents): @@ -59,10 +65,12 @@ class EventHook(object): return multiple_event_hook return self.get_child(subevent) def call(self, max=None, **kwargs): - if "data" in kwargs: kwargs.update(kwargs["data"].map()) event = Event(self.bot, self.name, **kwargs) if self._call_notify: self._call_notify(self, event) + + if not self._stored_events == None: + self._stored_events.append(event) called = 0 returns = [] for hook in self._hooks: diff --git a/IRCBot.py b/IRCBot.py index e87118e5..4c3caf1e 100644 --- a/IRCBot.py +++ b/IRCBot.py @@ -100,8 +100,7 @@ class Bot(object): def reconnect(self, event): server_details = self.database.get_server(event["server_id"]) - add_server_args = server_details + [False] - server = self.add_server(*add_server_args) + server = self.add_server(*(server_details + (False,))) if self.connect(server): self.servers[server.fileno()] = server else: diff --git a/IRCLineHandler.py b/IRCLineHandler.py index aa8dfb24..ca54d7f5 100644 --- a/IRCLineHandler.py +++ b/IRCLineHandler.py @@ -54,9 +54,9 @@ def handle(line, prefix, command, args, is_final, _bot, server): if default_events.get(command, False) or not command in handlers: if command.isdigit(): _bot.events.on("received").on("numeric").on( - command).call(data=data, number=command) + command).call(number=command, **data.map()) else: - _bot.events.on("received").on(command).call(data=data) + _bot.events.on("received").on(command).call(**data.map()) if handler_function: with handle_lock: bot = _bot @@ -66,7 +66,7 @@ def handle(line, prefix, command, args, is_final, _bot, server): def handle_PING(data): nonce = data.args[0] data.server.send_pong(nonce) - bot.events.on("received").on("ping").call(data=data, nonce=nonce) + bot.events.on("received").on("ping").call(nonce=nonce, **data.map()) @handler(description="the first line sent to a registered client", default_event=True) def handle_001(data): @@ -94,7 +94,7 @@ def handle_005(data): if match: server.channel_types = list(match.group(1)) bot.events.on("received").on("numeric").on("005").call( - data=data, isupport=isupport_line, number="005") + isupport=isupport_line, number="005", **data.map()) @handler(description="whois respose (nickname, username, realname, hostname)", default_event=True) def handle_311(data): @@ -153,12 +153,12 @@ def handle_JOIN(data): user.hostname = hostname channel.add_user(user) user.join_channel(channel) - bot.events.on("received").on("join").call(data=data, channel=channel, - user=user) + bot.events.on("received").on("join").call(channel=channel, + user=user, **data.map()) else: if channel.name in server.attempted_join: del server.attempted_join[channel.name] - bot.events.on("self").on("join").call(data=data, channel=channel) + bot.events.on("self").on("join").call(channel=channel, **data.map()) server.send_who(channel.name) channel.send_mode() @@ -170,16 +170,16 @@ def handle_PART(data): reason = data.args[1] if len(data.args)>1 else "" if not server.is_own_nickname(nickname): user = server.get_user(nickname) - bot.events.on("received").on("part").call(data=data, channel=channel, - reason=reason, user=user) + bot.events.on("received").on("part").call(channel=channel, + reason=reason, user=user, **data.map()) channel.remove_user(user) user.part_channel(channel) if not len(user.channels): server.remove_user(user) else: server.remove_channel(channel) - bot.events.on("self").on("part").call(data=data, channel=channel, - reason=reason) + bot.events.on("self").on("part").call(channel=channel, + reason=reason, **data.map()) @handler(description="unknown command sent by us, oops!", default_event=True) def handle_421(data): @@ -193,8 +193,8 @@ def handle_QUIT(data): if not server.is_own_nickname(nickname): user = server.get_user(nickname) server.remove_user(user) - bot.events.on("received").on("quit").call(data=data, reason=reason, - user=user) + bot.events.on("received").on("quit").call(reason=reason, + user=user, **data.map()) else: server.disconnect() @@ -203,14 +203,13 @@ def handle_CAP(data): capability_list = [] if len(data.args) > 2: capability_list = data.args[2].split() - bot.events.on("received").on("cap").call(data=data, - subcommand=data.args[1], capabilities=capability_list) + bot.events.on("received").on("cap").call(subcommand=data.args[1], + capabilities=capability_list, **data.map()) @handler(description="The server is asking for authentication") def handle_AUTHENTICATE(data): - bot.events.on("received").on("authenticate").call(data=data, - message=data.args[0] - ) + bot.events.on("received").on("authenticate").call(message=data.args[0], + **data.map()) @handler(description="someone has changed their nickname") def handle_NICK(data): @@ -222,9 +221,8 @@ def handle_NICK(data): old_nickname = user.nickname user.set_nickname(new_nickname) server.change_user_nickname(old_nickname, new_nickname) - bot.events.on("received").on("nick").call(data=data, - new_nickname=new_nickname, old_nickname=old_nickname, - user=user) + bot.events.on("received").on("nick").call(new_nickname=new_nickname, + old_nickname=old_nickname, user=user, **data.map()) else: old_nickname = server.nickname server.set_own_nickname(new_nickname) @@ -262,8 +260,8 @@ def handle_MODE(data): channel.add_mode(char, nickname) elif len(args): args.pop(0) - bot.events.on("received").on("mode").call( - data=data, modes=modes, args=args, channel=channel) + bot.events.on("received").on("mode").call(modes=modes, + mode_args=args, channel=channel, **data.map()) elif server.is_own_nickname(target): modes = Utils.remove_colon(data.args[1]) remove = False @@ -277,7 +275,7 @@ def handle_MODE(data): server.remove_own_mode(char) else: server.add_own_mode(char) - bot.events.on("self").on("mode").call(data=data, modes=modes) + bot.events.on("self").on("mode").call(modes=modes, **data.map()) #:nick!user@host MODE #chan +v-v nick nick @handler(description="I've been invited somewhere") @@ -286,7 +284,7 @@ def handle_INVITE(data): target_channel = Utils.remove_colon(data.args[1]) user = data.server.get_user(nickname) bot.events.on("received").on("invite").call( - data=data, user=user, target_channel=target_channel) + user=user, target_channel=target_channel, **data.map()) @handler(description="we've received a message") def handle_PRIVMSG(data): @@ -302,13 +300,13 @@ def handle_PRIVMSG(data): if target[0] in server.channel_types: channel = server.get_channel(data.args[0]) bot.events.on("received").on("message").on("channel").call( - data=data, user=user, message=message, message_split=message_split, - channel=channel, action=action) + user=user, message=message, message_split=message_split, + channel=channel, action=action, **data.map()) channel.log.add_line(user.nickname, message, action) elif server.is_own_nickname(target): bot.events.on("received").on("message").on("private").call( - data=data, user=user, message=message, message_split=message_split, - action=action) + user=user, message=message, message_split=message_split, + action=action, **data.map()) user.log.add_line(user.nickname, message, action) @handler(description="response to a WHO command for user information", default_event=True) diff --git a/IRCServer.py b/IRCServer.py index 44ffb89c..926631a1 100644 --- a/IRCServer.py +++ b/IRCServer.py @@ -135,18 +135,23 @@ class Server(object): user.part_channel(channel) del self.channels[channel.name] def parse_line(self, line): - if not line: return + if not line: + return original_line = line prefix, final = None, None - if line[0]==":": + if line[0] == ":": prefix, line = line[1:].split(" ", 1) + command, line = (line.split(" ", 1) + [""])[:2] - if line[:1]==":": + + if line[0] == ":": final, line = line[1:], "" elif " :" in line: line, final = line.split(" :", 1) + args_split = line.split(" ") if line else [] - if final: args_split.append(final) + if final: + args_split.append(final) IRCLineHandler.handle(original_line, prefix, command, args_split, final!=None, self.bot, self) self.check_users() def check_users(self): diff --git a/modules/auto_mode.py b/modules/auto_mode.py index 2d7370a4..4d0c3a0b 100644 --- a/modules/auto_mode.py +++ b/modules/auto_mode.py @@ -3,22 +3,21 @@ import Utils class Module(object): def __init__(self, bot): self.bot = bot - bot.events.on("boot").on("done").hook(self.boot_done) - bot.events.on("channel").on("mode").hook(self.on_mode) - bot.events.on("received").on("join").hook(self.on_join) - def boot_done(self, event): - self.bot.events.on("postboot").on("configure").on( + bot.events.on("postboot").on("configure").on( "channelset").call(setting="automode", help="Disable/Enable automode", validate=Utils.bool_or_none) + bot.events.on("channel").on("mode").hook(self.on_mode) + bot.events.on("received").on("join").hook(self.on_join) + def on_mode(self, event): if event["channel"].get_setting("automode", False): remove = event["remove"] channel = event["channel"] mode = event["mode"] - args = event["args"] + args = event["mode_args"] def on_join(self, event): if event["channel"].get_setting("automode", False): diff --git a/modules/commands.py b/modules/commands.py index 6985c869..5c5d8d1d 100644 --- a/modules/commands.py +++ b/modules/commands.py @@ -56,16 +56,15 @@ class Module(object): usage="") bot.events.on("received").on("command").on("more").hook(self.more, help="Get more output from the last command") - bot.events.on("boot").on("done").hook(self.boot_done) + + bot.events.on("postboot").on("configure").on( + "channelset").call(setting="command-prefix", + help="Set the command prefix used in this channel") + bot.events.on("new").on("user", "channel").hook(self.new) bot.events.on("send").on("stdout").hook(self.send_stdout) bot.events.on("send").on("stderr").hook(self.send_stderr) - def boot_done(self, event): - self.bot.events.on("postboot").on("configure").on( - "channelset").call(setting="command-prefix", - help="Set the command prefix used in this channel") - def new(self, event): if "user" in event: target = event["user"] diff --git a/modules/karma.py b/modules/karma.py index 7526812f..800f1bcc 100644 --- a/modules/karma.py +++ b/modules/karma.py @@ -13,10 +13,8 @@ class Module(object): bot.events.on("received").on("command").on("karma").hook( self.karma, help="Get your or someone else's karma", usage="[target]") - bot.events.on("boot").on("done").hook(self.boot_done) - def boot_done(self, event): - self.bot.events.on("postboot").on("configure").on( + bot.events.on("postboot").on("configure").on( "channelset").call(setting="karma-verbose", help="Disable/Enable automatically responding to karma changes", validate=Utils.bool_or_none) diff --git a/modules/lastfm.py b/modules/lastfm.py index 77f693c1..7a607dd0 100644 --- a/modules/lastfm.py +++ b/modules/lastfm.py @@ -7,17 +7,16 @@ URL_SCROBBLER = "http://ws.audioscrobbler.com/2.0/" class Module(object): def __init__(self, bot): self.bot = bot - bot.events.on("boot").on("done").hook(self.boot_done) + + bot.events.on("postboot").on("configure").on( + "set").call(setting="lastfm", + help="Set username on last.fm") + bot.events.on("received").on("command").on("np", "listening", "nowplaying").hook(self.np, help="Get the last listen to track from a user", usage="[username]") - def boot_done(self, event): - self.bot.events.on("postboot").on("configure").on( - "set").call(setting="lastfm", - help="Set username on last.fm") - def np(self, event): if event["args_split"]: username = event["args_split"][0] diff --git a/modules/sed.py b/modules/sed.py index 77c6f9a2..32934db5 100644 --- a/modules/sed.py +++ b/modules/sed.py @@ -7,16 +7,14 @@ REGEX_SED = re.compile("^s/") class Module(object): def __init__(self, bot): self.bot = bot - bot.events.on("boot").on("done").hook(self.boot_done) bot.events.on("received").on("message").on("channel").hook( self.channel_message) - def boot_done(self, event): - self.bot.events.on("postboot").on("configure").on( + bot.events.on("postboot").on("configure").on( "channelset").call(setting="sed", help="Disable/Enable sed in a channel", validate=Utils.bool_or_none) - self.bot.events.on("postboot").on("configure").on( + bot.events.on("postboot").on("configure").on( "channelset").call(setting="sed-sender-only", help= "Disable/Enable sed only looking at the messages sent by the user", diff --git a/modules/set.py b/modules/set.py index 310efb77..ddc2a758 100644 --- a/modules/set.py +++ b/modules/set.py @@ -6,9 +6,9 @@ class Module(object): self.settings = {} self.channel_settings = {} bot.events.on("postboot").on("configure").on("set").hook( - self.postboot_set) + self.postboot_set, replay=True) bot.events.on("postboot").on("configure").on("channelset" - ).hook(self.postboot_channelset) + ).hook(self.postboot_channelset, replay=True) bot.events.on("received").on("command").on("set").hook( self.set, help="Set a specified user setting", usage=" ") diff --git a/modules/trakt.py b/modules/trakt.py index 3e407752..39a039c3 100644 --- a/modules/trakt.py +++ b/modules/trakt.py @@ -8,14 +8,12 @@ URL_TRAKTSLUG = "https://trakt.tv/%s/%s" class Module(object): def __init__(self, bot): self.bot = bot - bot.events.on("boot").on("done").hook(self.boot_done) bot.events.on("received").on("command").on("nowwatching", "nw").hook(self.now_watching, help="Get what you or another user is now watching " "on trakt.tv", usage="[username]") - def boot_done(self, event): - self.bot.events.on("postboot").on("configure").on("set" + bot.events.on("postboot").on("configure").on("set" ).call(setting="trakt", help="Set username on trakt.tv") def now_watching(self, event): diff --git a/modules/youtube.py b/modules/youtube.py index d4567a34..cf2a56f4 100644 --- a/modules/youtube.py +++ b/modules/youtube.py @@ -24,14 +24,13 @@ class Module(object): help="Find a video on youtube", usage="[query]") bot.events.on("received").on("message").on("channel").hook( self.channel_message) - bot.events.on("boot").on("done").hook(self.boot_done) - def boot_done(self, event): - self.bot.events.on("postboot").on("configure").on( + bot.events.on("postboot").on("configure").on( "channelset").call(setting="auto-youtube", help="Disable/Enable automatically getting info from youtube URLs", validate=Utils.bool_or_none) + def get_video_page(self, video_id, part): return Utils.get_url(URL_YOUTUBEVIDEO, get_params={"part": part, "id": video_id, "key": self.bot.config["google-api-key"]}, @@ -65,7 +64,8 @@ class Module(object): ) if match.group(3) else "00" return "%s (%s) uploaded by %s, %s views%s %s" % ( video_title, video_duration, video_uploader, "{:,}".format( - int(video_views)), video_opinions, URL_YOUTUBESHORT % video_id) + int(video_views)), video_opinions, #URL_YOUTUBESHORT % video_id + "https://youtu.be/dQw4w9WgXcQ") def yt(self, event): video_id = None