Added a "replay" system to EventManager hooks, to replay missed .calls

This commit is contained in:
jesopo 2017-12-26 10:32:36 +00:00
parent 62ac516d1f
commit 0cc72d5d66
12 changed files with 72 additions and 71 deletions

View file

@ -44,11 +44,17 @@ class EventHook(object):
self._hook_notify = None self._hook_notify = None
self._child_notify = None self._child_notify = None
self._call_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) callback = EventCallback(function, self.bot, **kwargs)
if self._hook_notify: if self._hook_notify:
self._hook_notify(self, callback) self._hook_notify(self, callback)
self._hooks.append(callback) self._hooks.append(callback)
if replay:
for event in self._stored_events:
callback.call(event)
self._stored_events = None
def _unhook(self, hook): def _unhook(self, hook):
self._hooks.remove(hook) self._hooks.remove(hook)
def on(self, subevent, *extra_subevents): def on(self, subevent, *extra_subevents):
@ -59,10 +65,12 @@ class EventHook(object):
return multiple_event_hook return multiple_event_hook
return self.get_child(subevent) return self.get_child(subevent)
def call(self, max=None, **kwargs): def call(self, max=None, **kwargs):
if "data" in kwargs: kwargs.update(kwargs["data"].map())
event = Event(self.bot, self.name, **kwargs) event = Event(self.bot, self.name, **kwargs)
if self._call_notify: if self._call_notify:
self._call_notify(self, event) self._call_notify(self, event)
if not self._stored_events == None:
self._stored_events.append(event)
called = 0 called = 0
returns = [] returns = []
for hook in self._hooks: for hook in self._hooks:

View file

@ -100,8 +100,7 @@ class Bot(object):
def reconnect(self, event): def reconnect(self, event):
server_details = self.database.get_server(event["server_id"]) server_details = self.database.get_server(event["server_id"])
add_server_args = server_details + [False] server = self.add_server(*(server_details + (False,)))
server = self.add_server(*add_server_args)
if self.connect(server): if self.connect(server):
self.servers[server.fileno()] = server self.servers[server.fileno()] = server
else: else:

View file

@ -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 default_events.get(command, False) or not command in handlers:
if command.isdigit(): if command.isdigit():
_bot.events.on("received").on("numeric").on( _bot.events.on("received").on("numeric").on(
command).call(data=data, number=command) command).call(number=command, **data.map())
else: else:
_bot.events.on("received").on(command).call(data=data) _bot.events.on("received").on(command).call(**data.map())
if handler_function: if handler_function:
with handle_lock: with handle_lock:
bot = _bot bot = _bot
@ -66,7 +66,7 @@ def handle(line, prefix, command, args, is_final, _bot, server):
def handle_PING(data): def handle_PING(data):
nonce = data.args[0] nonce = data.args[0]
data.server.send_pong(nonce) 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) @handler(description="the first line sent to a registered client", default_event=True)
def handle_001(data): def handle_001(data):
@ -94,7 +94,7 @@ def handle_005(data):
if match: if match:
server.channel_types = list(match.group(1)) server.channel_types = list(match.group(1))
bot.events.on("received").on("numeric").on("005").call( 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) @handler(description="whois respose (nickname, username, realname, hostname)", default_event=True)
def handle_311(data): def handle_311(data):
@ -153,12 +153,12 @@ def handle_JOIN(data):
user.hostname = hostname user.hostname = hostname
channel.add_user(user) channel.add_user(user)
user.join_channel(channel) user.join_channel(channel)
bot.events.on("received").on("join").call(data=data, channel=channel, bot.events.on("received").on("join").call(channel=channel,
user=user) user=user, **data.map())
else: else:
if channel.name in server.attempted_join: if channel.name in server.attempted_join:
del server.attempted_join[channel.name] 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) server.send_who(channel.name)
channel.send_mode() channel.send_mode()
@ -170,16 +170,16 @@ def handle_PART(data):
reason = data.args[1] if len(data.args)>1 else "" reason = data.args[1] if len(data.args)>1 else ""
if not server.is_own_nickname(nickname): if not server.is_own_nickname(nickname):
user = server.get_user(nickname) user = server.get_user(nickname)
bot.events.on("received").on("part").call(data=data, channel=channel, bot.events.on("received").on("part").call(channel=channel,
reason=reason, user=user) reason=reason, user=user, **data.map())
channel.remove_user(user) channel.remove_user(user)
user.part_channel(channel) user.part_channel(channel)
if not len(user.channels): if not len(user.channels):
server.remove_user(user) server.remove_user(user)
else: else:
server.remove_channel(channel) server.remove_channel(channel)
bot.events.on("self").on("part").call(data=data, channel=channel, bot.events.on("self").on("part").call(channel=channel,
reason=reason) reason=reason, **data.map())
@handler(description="unknown command sent by us, oops!", default_event=True) @handler(description="unknown command sent by us, oops!", default_event=True)
def handle_421(data): def handle_421(data):
@ -193,8 +193,8 @@ def handle_QUIT(data):
if not server.is_own_nickname(nickname): if not server.is_own_nickname(nickname):
user = server.get_user(nickname) user = server.get_user(nickname)
server.remove_user(user) server.remove_user(user)
bot.events.on("received").on("quit").call(data=data, reason=reason, bot.events.on("received").on("quit").call(reason=reason,
user=user) user=user, **data.map())
else: else:
server.disconnect() server.disconnect()
@ -203,14 +203,13 @@ def handle_CAP(data):
capability_list = [] capability_list = []
if len(data.args) > 2: if len(data.args) > 2:
capability_list = data.args[2].split() capability_list = data.args[2].split()
bot.events.on("received").on("cap").call(data=data, bot.events.on("received").on("cap").call(subcommand=data.args[1],
subcommand=data.args[1], capabilities=capability_list) capabilities=capability_list, **data.map())
@handler(description="The server is asking for authentication") @handler(description="The server is asking for authentication")
def handle_AUTHENTICATE(data): def handle_AUTHENTICATE(data):
bot.events.on("received").on("authenticate").call(data=data, bot.events.on("received").on("authenticate").call(message=data.args[0],
message=data.args[0] **data.map())
)
@handler(description="someone has changed their nickname") @handler(description="someone has changed their nickname")
def handle_NICK(data): def handle_NICK(data):
@ -222,9 +221,8 @@ def handle_NICK(data):
old_nickname = user.nickname old_nickname = user.nickname
user.set_nickname(new_nickname) user.set_nickname(new_nickname)
server.change_user_nickname(old_nickname, new_nickname) server.change_user_nickname(old_nickname, new_nickname)
bot.events.on("received").on("nick").call(data=data, bot.events.on("received").on("nick").call(new_nickname=new_nickname,
new_nickname=new_nickname, old_nickname=old_nickname, old_nickname=old_nickname, user=user, **data.map())
user=user)
else: else:
old_nickname = server.nickname old_nickname = server.nickname
server.set_own_nickname(new_nickname) server.set_own_nickname(new_nickname)
@ -262,8 +260,8 @@ def handle_MODE(data):
channel.add_mode(char, nickname) channel.add_mode(char, nickname)
elif len(args): elif len(args):
args.pop(0) args.pop(0)
bot.events.on("received").on("mode").call( bot.events.on("received").on("mode").call(modes=modes,
data=data, modes=modes, args=args, channel=channel) mode_args=args, channel=channel, **data.map())
elif server.is_own_nickname(target): elif server.is_own_nickname(target):
modes = Utils.remove_colon(data.args[1]) modes = Utils.remove_colon(data.args[1])
remove = False remove = False
@ -277,7 +275,7 @@ def handle_MODE(data):
server.remove_own_mode(char) server.remove_own_mode(char)
else: else:
server.add_own_mode(char) 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 #:nick!user@host MODE #chan +v-v nick nick
@handler(description="I've been invited somewhere") @handler(description="I've been invited somewhere")
@ -286,7 +284,7 @@ def handle_INVITE(data):
target_channel = Utils.remove_colon(data.args[1]) target_channel = Utils.remove_colon(data.args[1])
user = data.server.get_user(nickname) user = data.server.get_user(nickname)
bot.events.on("received").on("invite").call( 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") @handler(description="we've received a message")
def handle_PRIVMSG(data): def handle_PRIVMSG(data):
@ -302,13 +300,13 @@ def handle_PRIVMSG(data):
if target[0] in server.channel_types: if target[0] in server.channel_types:
channel = server.get_channel(data.args[0]) channel = server.get_channel(data.args[0])
bot.events.on("received").on("message").on("channel").call( bot.events.on("received").on("message").on("channel").call(
data=data, user=user, message=message, message_split=message_split, user=user, message=message, message_split=message_split,
channel=channel, action=action) channel=channel, action=action, **data.map())
channel.log.add_line(user.nickname, message, action) channel.log.add_line(user.nickname, message, action)
elif server.is_own_nickname(target): elif server.is_own_nickname(target):
bot.events.on("received").on("message").on("private").call( bot.events.on("received").on("message").on("private").call(
data=data, user=user, message=message, message_split=message_split, user=user, message=message, message_split=message_split,
action=action) action=action, **data.map())
user.log.add_line(user.nickname, message, action) user.log.add_line(user.nickname, message, action)
@handler(description="response to a WHO command for user information", default_event=True) @handler(description="response to a WHO command for user information", default_event=True)

View file

@ -135,18 +135,23 @@ class Server(object):
user.part_channel(channel) user.part_channel(channel)
del self.channels[channel.name] del self.channels[channel.name]
def parse_line(self, line): def parse_line(self, line):
if not line: return if not line:
return
original_line = line original_line = line
prefix, final = None, None prefix, final = None, None
if line[0] == ":": if line[0] == ":":
prefix, line = line[1:].split(" ", 1) prefix, line = line[1:].split(" ", 1)
command, line = (line.split(" ", 1) + [""])[:2] command, line = (line.split(" ", 1) + [""])[:2]
if line[:1]==":":
if line[0] == ":":
final, line = line[1:], "" final, line = line[1:], ""
elif " :" in line: elif " :" in line:
line, final = line.split(" :", 1) line, final = line.split(" :", 1)
args_split = line.split(" ") if line else [] 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) IRCLineHandler.handle(original_line, prefix, command, args_split, final!=None, self.bot, self)
self.check_users() self.check_users()
def check_users(self): def check_users(self):

View file

@ -3,22 +3,21 @@ import Utils
class Module(object): class Module(object):
def __init__(self, bot): def __init__(self, bot):
self.bot = 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): bot.events.on("postboot").on("configure").on(
self.bot.events.on("postboot").on("configure").on(
"channelset").call(setting="automode", "channelset").call(setting="automode",
help="Disable/Enable automode", help="Disable/Enable automode",
validate=Utils.bool_or_none) 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): def on_mode(self, event):
if event["channel"].get_setting("automode", False): if event["channel"].get_setting("automode", False):
remove = event["remove"] remove = event["remove"]
channel = event["channel"] channel = event["channel"]
mode = event["mode"] mode = event["mode"]
args = event["args"] args = event["mode_args"]
def on_join(self, event): def on_join(self, event):
if event["channel"].get_setting("automode", False): if event["channel"].get_setting("automode", False):

View file

@ -56,16 +56,15 @@ class Module(object):
usage="<command>") usage="<command>")
bot.events.on("received").on("command").on("more").hook(self.more, bot.events.on("received").on("command").on("more").hook(self.more,
help="Get more output from the last command") 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("new").on("user", "channel").hook(self.new)
bot.events.on("send").on("stdout").hook(self.send_stdout) bot.events.on("send").on("stdout").hook(self.send_stdout)
bot.events.on("send").on("stderr").hook(self.send_stderr) 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): def new(self, event):
if "user" in event: if "user" in event:
target = event["user"] target = event["user"]

View file

@ -13,10 +13,8 @@ class Module(object):
bot.events.on("received").on("command").on("karma").hook( bot.events.on("received").on("command").on("karma").hook(
self.karma, help="Get your or someone else's karma", self.karma, help="Get your or someone else's karma",
usage="[target]") usage="[target]")
bot.events.on("boot").on("done").hook(self.boot_done)
def boot_done(self, event): bot.events.on("postboot").on("configure").on(
self.bot.events.on("postboot").on("configure").on(
"channelset").call(setting="karma-verbose", "channelset").call(setting="karma-verbose",
help="Disable/Enable automatically responding to karma changes", help="Disable/Enable automatically responding to karma changes",
validate=Utils.bool_or_none) validate=Utils.bool_or_none)

View file

@ -7,17 +7,16 @@ URL_SCROBBLER = "http://ws.audioscrobbler.com/2.0/"
class Module(object): class Module(object):
def __init__(self, bot): def __init__(self, bot):
self.bot = 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", bot.events.on("received").on("command").on("np",
"listening", "nowplaying").hook(self.np, "listening", "nowplaying").hook(self.np,
help="Get the last listen to track from a user", help="Get the last listen to track from a user",
usage="[username]") 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): def np(self, event):
if event["args_split"]: if event["args_split"]:
username = event["args_split"][0] username = event["args_split"][0]

View file

@ -7,16 +7,14 @@ REGEX_SED = re.compile("^s/")
class Module(object): class Module(object):
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
bot.events.on("boot").on("done").hook(self.boot_done)
bot.events.on("received").on("message").on("channel").hook( bot.events.on("received").on("message").on("channel").hook(
self.channel_message) self.channel_message)
def boot_done(self, event): bot.events.on("postboot").on("configure").on(
self.bot.events.on("postboot").on("configure").on(
"channelset").call(setting="sed", "channelset").call(setting="sed",
help="Disable/Enable sed in a channel", help="Disable/Enable sed in a channel",
validate=Utils.bool_or_none) 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", "channelset").call(setting="sed-sender-only",
help= help=
"Disable/Enable sed only looking at the messages sent by the user", "Disable/Enable sed only looking at the messages sent by the user",

View file

@ -6,9 +6,9 @@ class Module(object):
self.settings = {} self.settings = {}
self.channel_settings = {} self.channel_settings = {}
bot.events.on("postboot").on("configure").on("set").hook( 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" 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( bot.events.on("received").on("command").on("set").hook(
self.set, help="Set a specified user setting", self.set, help="Set a specified user setting",
usage="<setting> <value>") usage="<setting> <value>")

View file

@ -8,14 +8,12 @@ URL_TRAKTSLUG = "https://trakt.tv/%s/%s"
class Module(object): class Module(object):
def __init__(self, bot): def __init__(self, bot):
self.bot = bot self.bot = bot
bot.events.on("boot").on("done").hook(self.boot_done)
bot.events.on("received").on("command").on("nowwatching", bot.events.on("received").on("command").on("nowwatching",
"nw").hook(self.now_watching, "nw").hook(self.now_watching,
help="Get what you or another user is now watching " help="Get what you or another user is now watching "
"on trakt.tv", usage="[username]") "on trakt.tv", usage="[username]")
def boot_done(self, event): bot.events.on("postboot").on("configure").on("set"
self.bot.events.on("postboot").on("configure").on("set"
).call(setting="trakt", help="Set username on trakt.tv") ).call(setting="trakt", help="Set username on trakt.tv")
def now_watching(self, event): def now_watching(self, event):

View file

@ -24,14 +24,13 @@ class Module(object):
help="Find a video on youtube", usage="[query]") help="Find a video on youtube", usage="[query]")
bot.events.on("received").on("message").on("channel").hook( bot.events.on("received").on("message").on("channel").hook(
self.channel_message) self.channel_message)
bot.events.on("boot").on("done").hook(self.boot_done)
def boot_done(self, event): bot.events.on("postboot").on("configure").on(
self.bot.events.on("postboot").on("configure").on(
"channelset").call(setting="auto-youtube", "channelset").call(setting="auto-youtube",
help="Disable/Enable automatically getting info from youtube URLs", help="Disable/Enable automatically getting info from youtube URLs",
validate=Utils.bool_or_none) validate=Utils.bool_or_none)
def get_video_page(self, video_id, part): def get_video_page(self, video_id, part):
return Utils.get_url(URL_YOUTUBEVIDEO, get_params={"part": part, return Utils.get_url(URL_YOUTUBEVIDEO, get_params={"part": part,
"id": video_id, "key": self.bot.config["google-api-key"]}, "id": video_id, "key": self.bot.config["google-api-key"]},
@ -65,7 +64,8 @@ class Module(object):
) if match.group(3) else "00" ) if match.group(3) else "00"
return "%s (%s) uploaded by %s, %s views%s %s" % ( return "%s (%s) uploaded by %s, %s views%s %s" % (
video_title, video_duration, video_uploader, "{:,}".format( 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): def yt(self, event):
video_id = None video_id = None