From 51a52e2b0e54031cce5876f54d1d48c268b5441c Mon Sep 17 00:00:00 2001 From: jesopo Date: Wed, 26 Sep 2018 18:27:17 +0100 Subject: [PATCH] Switch to using @Utils.hook and docstrings for event hooks --- modules/8ball.py | 16 +++---- modules/accept_invite.py | 2 +- modules/admin.py | 44 +++++++++++------- modules/auto_mode.py | 43 +++++++++-------- modules/bitcoin.py | 12 ++--- modules/books.py | 20 ++++---- modules/bot_channel.py | 5 +- modules/channel_op.py | 93 +++++++++++++++++++++---------------- modules/channel_save.py | 14 +++--- modules/check_mode.py | 9 ++-- modules/check_urls.py | 3 +- modules/coins.py | 65 +++++++++++++++----------- modules/commands.py | 52 ++++++++++++--------- modules/ctcp.py | 2 +- modules/database_backup.py | 3 +- modules/define.py | 15 +++--- modules/dice.py | 22 ++++----- modules/dns.py | 11 +++-- modules/ducks.py | 64 +++++++++++++------------ modules/eval.py | 12 ++--- modules/geoip.py | 11 +++-- modules/google.py | 12 +++-- modules/greeting.py | 4 +- modules/hash.py | 12 ++--- modules/haveibeenpwned.py | 15 +++--- modules/ids.py | 18 +++---- modules/imdb.py | 6 ++- modules/in.py | 8 ++-- modules/isgd.py | 9 ++-- modules/karma.py | 24 +++++----- modules/lastfm.py | 8 ++-- modules/modules.py | 52 ++++++++++++--------- modules/nickname_aliases.py | 8 ++-- modules/nickserv.py | 6 +-- modules/nr.py | 43 +++++++++-------- modules/perform.py | 9 ++-- modules/permissions.py | 66 +++++++++++++++----------- modules/print_activity.py | 52 ++++++++------------- modules/quit.py | 7 ++- modules/quotes.py | 37 ++++++++------- modules/random_number.py | 16 ++++--- modules/sasl.py | 13 +++--- modules/sed.py | 3 +- modules/seen.py | 14 +++--- modules/set.py | 57 ++++++++++++----------- modules/shakespeare.py | 12 ++--- modules/soundcloud.py | 6 ++- modules/spotify.py | 12 ++--- modules/stats.py | 12 +++-- modules/strax.py | 13 +++--- modules/telegram.py | 13 +++--- modules/tfl.py | 51 ++++++++++---------- modules/thesaurus.py | 8 ++-- modules/title.py | 12 ++--- modules/to.py | 18 ++++--- modules/todo.py | 25 +++++----- modules/torrent.py | 49 +++++++++++++++++++ modules/trakt.py | 8 ++-- modules/translate.py | 13 +++--- modules/tweets.py | 7 +-- modules/upc.py | 13 +++--- modules/urbandictionary.py | 14 +++--- modules/weather.py | 7 +-- modules/wikipedia.py | 13 +++--- modules/wolframalpha.py | 8 ++-- modules/words.py | 38 +++++++-------- modules/youtube.py | 12 ++--- 67 files changed, 743 insertions(+), 638 deletions(-) create mode 100644 modules/torrent.py diff --git a/modules/8ball.py b/modules/8ball.py index 37d38743..ebfb1b0c 100644 --- a/modules/8ball.py +++ b/modules/8ball.py @@ -1,5 +1,5 @@ import random -from src import Utils +from src import ModuleManager, Utils CHOICES = [ "Definitely", @@ -28,15 +28,11 @@ CHOICES = [ "Sources say maybe" ] -class Module(object): - def __init__(self, bot, events, exports): - events.on("received.command.8ball").hook( - self.decide, - min_args=1, - help="Ask the mystic 8ball a question!", - usage="" - ) - +class Module(ModuleManager.BaseModule): + @Utils.hook("received.command.8ball", min_args=1, usage="") def decide(selfs, event): + """ + Ask the mystic 8ball a question! + """ event["stdout"].write("You shake the magic ball... it " "says " + Utils.bold(random.choice(CHOICES))) diff --git a/modules/accept_invite.py b/modules/accept_invite.py index 40888f8a..e9b2add9 100644 --- a/modules/accept_invite.py +++ b/modules/accept_invite.py @@ -2,11 +2,11 @@ from src import Utils class Module(object): def __init__(self, bot, events, exports): - events.on("received.invite").hook(self.on_invite) exports.add("serverset", {"setting": "accept-invites", "help": "Set whether I accept invites on this server", "validate": Utils.bool_or_none}) + @Utils.hook("received.invite") def on_invite(self, event): if event["server"].is_own_nickname(event["target_user"].nickname): if event["server"].get_setting("accept-invites", True): diff --git a/modules/admin.py b/modules/admin.py index 392a44ff..1742758e 100644 --- a/modules/admin.py +++ b/modules/admin.py @@ -1,29 +1,39 @@ +from src import ModuleManager, Utils - -class Module(object): - def __init__(self, bot, events, exports): - self.bot = bot - events.on("received.command.changenickname").hook( - self.change_nickname, permission="changenickname", - min_args=1, help="Change my nickname", usage="") - events.on("received.command.raw").hook(self.raw, - permission="raw", min_args=1, usage="", - help="Send a raw IRC line through the bot") - events.on("received.command.part").hook(self.part, - permission="part", min_args=1, help="Part from a channel", - usage="<#channel>") - events.on("received.command.reconnect").hook(self.reconnect, - permission="reconnect", help="Reconnect from this network") - +class Module(ModuleManager.BaseModule): + @Utils.hook("received.command.changenickname", + permission="changenickname", min_args=1, usage="") def change_nickname(self, event): + """ + Change my nickname + """ nickname = event["args_split"][0] event["server"].send_nick(nickname) + @Utils.hook("received.command.raw", permission="raw", min_args=1, + usage="") def raw(self, event): + """ + Send a line of raw IRC data + """ event["server"].send(event["args"]) + @Utils.hook("received.command.part", permission="part", usage="[#channel]") def part(self, event): - event["server"].send_part(event["args_split"][0]) + """ + Part from the current or given channel + """ + if event["args"]: + target = event["args_split"][0] + elif event["is_channel"]: + target = event["target"].name + else: + event["stderr"].write("No channel provided") + event["server"].send_part(target) + @Utils.hook("received.command.reconnect", permission="reconnect") def reconnect(self, event): + """ + Reconnect to the current network + """ event["server"].send_quit("Reconnecting") diff --git a/modules/auto_mode.py b/modules/auto_mode.py index af6dc606..08648ca3 100644 --- a/modules/auto_mode.py +++ b/modules/auto_mode.py @@ -3,26 +3,6 @@ from src import Utils class Module(object): _name = "AutoMode" def __init__(self, bot, events, exports): - self.bot = bot - - events.on("received.join").hook(self.on_join) - - events.on("received.command.addop").hook(self.add_op, - require_mode="o", min_args=1, channel_only=True, - usage="", help="Add a user to the automode op list") - events.on("received.command.removeop").hook(self.remove_op, - require_mode="o", min_args=1, channel_only=True, - usage="", help="Remove a user from the automode " - "op list") - - events.on("received.command.addvoice").hook(self.add_voice, - require_mode="o", min_args=1, channel_only=True, - usage="", help="Add a user to the automode voice list") - events.on("received.command.removevoice").hook(self.remove_voice, - require_mode="o", min_args=1, channel_only=True, - usage="", help="Remove a user from the automode " - "voice list") - exports.add("channelset", {"setting": "automode", "help": "Disable/Enable automode", "validate": Utils.bool_or_none}) @@ -34,8 +14,11 @@ class Module(object): if modes: channel.send_mode("+%s" % "".join(modes), " ".join([user.nickname for mode in modes])) + + @Utils.hook("received.join") def on_join(self, event): self._check_modes(event["channel"], event["user"]) + @Utils.hook("received.account") def on_account(self, event): for channel in event["user"].channels: self._check_modes(channel, event["user"]) @@ -70,12 +53,32 @@ class Module(object): event["stdout"].write("Removed automode %s from '%s'" % ( mode_name, target_user.nickname)) + @Utils.hook("received.command.addop", require_mode="o", min_args=1, + channel_only=True, usage="") def add_op(self, event): + """ + Add a user to the auto-mode list as an op + """ self._add_mode(event, "o", "op") + @Utils.hook("received.command.removeop", require_mode="o", min_args=1, + channel_only=True, usage="") def remove_op(self, event): + """ + Remove a user from the auto-mode list as an op + """ self._remove_mode(event, "o", "op") + @Utils.hook("received.command.addvoice", require_mode="o", min_args=1, + channel_only=True, usage="") def add_voice(self, event): + """ + Add a user to the auto-mode list as a voice + """ self._add_mode(event, "v", "voice") + @Utils.hook("received.command.removevoice", require_mode="o", min_args=1, + channel_only=True, usage="") def remove_voice(self, event): + """ + Remove a user from the auto-mode list as anvoice + """ self._remove_mode(event, "v", "voice") diff --git a/modules/bitcoin.py b/modules/bitcoin.py index c85e6bf1..1c88c0bb 100644 --- a/modules/bitcoin.py +++ b/modules/bitcoin.py @@ -1,13 +1,13 @@ -from src import Utils +from src import ModuleManager, Utils -class Module(object): +class Module(ModuleManager.BaseModule): _name = "BTC" - def __init__(self, bot, events, exports): - self.bot = bot - events.on("received.command.btc").hook(self.btc, - help="Get the exchange rate of bitcoins", usage="[currency]") + @Utils.hook("received.command.btc", usage="[currency]") def btc(self, event): + """ + Get the exchange rate of bitcoins + """ currency = (event["args"] or "USD").upper() page = Utils.get_url("https://blockchain.info/ticker", json=True) diff --git a/modules/books.py b/modules/books.py index e0569a76..7a0204a6 100644 --- a/modules/books.py +++ b/modules/books.py @@ -1,20 +1,12 @@ import json, re -from src import Utils +from src import ModuleManager, Utils URL_GOOGLEBOOKS = "https://www.googleapis.com/books/v1/volumes" URL_BOOKINFO = "https://books.google.co.uk/books?id=%s" REGEX_BOOKID = re.compile("id=([\w\-]+)") -class Module(object): +class Module(ModuleManager.BaseModule): _name = "ISBN" - def __init__(self, bot, events, exports): - self.bot = bot - events.on("received.command.isbn").hook(self.isbn, - help="Get book information from a provided ISBN", - min_args=1, usage="") - events.on("received.command.book").hook(self.book, - help="Get book information from a provided title", - min_args=1, usage="") def get_book(self, query, event): page = Utils.get_url(URL_GOOGLEBOOKS, get_params={ @@ -44,12 +36,20 @@ class Module(object): else: event["stderr"].write("Failed to load results") + @Utils.hook("received.command.isbn", min_args=1, usage="") def isbn(self, event): + """ + Get book information from a provided ISBN + """ isbn = event["args_split"][0] if len(isbn) == 10: isbn = "978%s" % isbn isbn = isbn.replace("-", "") self.get_book("isbn:%s" % isbn, event) + @Utils.hook("received.command.book", min_args=1, usage="") def book(self, event): + """ + Get book information from a provided title + """ self.get_book(event["args"], event) diff --git a/modules/bot_channel.py b/modules/bot_channel.py index cbe50119..2e2ff6fb 100644 --- a/modules/bot_channel.py +++ b/modules/bot_channel.py @@ -1,12 +1,11 @@ - +from src import Utils class Module(object): def __init__(self, bot, events, exports): - events.on("received.numeric.001").hook(self.do_join) - exports.add("serverset", {"setting": "bot-channel", "help": "Set main channel"}) + @Utils.hook("received.numeric.001") def do_join(self, event): event["server"].send_join(event["server"].get_setting("bot-channel", "#bitbot")) diff --git a/modules/channel_op.py b/modules/channel_op.py index ad2233d9..13f9df5a 100644 --- a/modules/channel_op.py +++ b/modules/channel_op.py @@ -3,46 +3,6 @@ from src import Utils class Module(object): _name = "Channel Op" def __init__(self, bot, events, exports): - self.bot = bot - - events.on("received.command").on("kick", "k").hook(self.kick, - channel_only=True, require_mode="o", usage=" [reason]", - min_args=1, help="Kick a user from the channel") - events.on("received.command.ban").hook(self.ban, channel_only=True, - require_mode="o", min_args=1, usage="", - help="Ban a user/hostmask from the channel") - events.on("received.command.unban").hook(self.unban, - channel_only=True, require_mode="o", usage="", - min_args=1, help="Unban a user/hostmask from the channel") - - events.on("received.command").on("kickban", "kb" - ).hook(self.kickban, channel_only=True, require_mode="o", - min_args=1, help="Kickban a user from the channel", - usage=" [reason]") - - events.on("received.command.op" - ).hook(self.op, channel_only=True, require_mode="o", - help="Give +o to a user", usage="[nickname]") - events.on("received.command.deop" - ).hook(self.deop, channel_only=True, require_mode="o", - help="Take +o from a user", usage="[nickname]") - - events.on("received.command.voice").hook(self.voice, - channel_only=True, require_mode="o", usage="[nickname]", - help="Give +v to a user") - events.on("received.command.devoice").hook(self.devoice, - channel_only=True, require_mode="o", usage="[nickname]", - help="Take +v from a user") - - events.on("received.command.topic").hook(self.topic, min_args=1, - require_mode="o", channel_only=True, usage="", - help="Set the topic of the current channel") - events.on("received.command").on("topicappend", "tappend").hook( - self.tappend, min_args=1, require_mode="o", channel_only=True, - usage="", help="Set the topic of the current channel") - - events.on("received.message.channel").hook(self.highlight_spam) - exports.add("channelset", {"setting": "highlight-spam-threshold", "help": "Set the number of nicknames in a message that " "qualifies as spam", "validate": Utils.int_or_none}) @@ -56,7 +16,12 @@ class Module(object): "help": "Set ban format ($n = nick, $u = username, " "$h = hostname)"}) + @Utils.hook("received.command.kick|k", channel_only=True, + require_mode="o", usage=" [reason]", min_args=1) def kick(self, event): + """ + Kick a user from the current channel + """ target = event["args_split"][0] target_user = event["server"].get_user(target) if event["args_split"][1:]: @@ -84,48 +49,96 @@ class Module(object): channel.send_ban(hostmask) else: channel.send_unban(hostmask) + + @Utils.hook("received.command.ban", channel_only=True, min_args=1, + require_mode="o", usage="") def ban(self, event): + """ + Ban a user/hostmask from the current channel + """ target_user = event["server"].get_user(event["args_split"][0]) if event["target"].has_user(target_user): self._ban(event["target"], True, target_user) else: event["target"].send_ban(event["args_split"][0]) + @Utils.hook("received.command.unban", channel_only=True, min_args=1, + require_mode="o", usage="") def unban(self, event): + """ + Unban a user/hostmask from the current channel + """ target_user = event["server"].get_user(event["args_split"][0]) if event["target"].has_user(target_user): self._ban(event["target"], False, target_user) else: event["target"].send_unban(event["args_split"][0]) + @Utils.hook("received.command.kickban|kb", channel_only=True, + require_mode="o", usage=" [reason]", min_args=1) def kickban(self, event): + """ + Kick and ban a user from the current channel + """ if event["server"].has_user(event["args_split"][0]): self.ban(event) self.kick(event) else: event["stderr"].write("That user is not in this channel") + @Utils.hook("received.command.op", channel_only=True, + require_mode="o", usage="[nickname]") def op(self, event): + """ + Op a user in the current channel + """ target = event["user"].nickname if not event["args_split"] else event[ "args_split"][0] event["target"].send_mode("+o", target) + @Utils.hook("received.command.deop", channel_only=True, + require_mode="o", usage="[nickname]") def deop(self, event): + """ + Remove op from a user in the current channel + """ target = event["user"].nickname if not event["args_split"] else event[ "args_split"][0] event["target"].send_mode("-o", target) + + @Utils.hook("received.command.voice", channel_only=True, + require_mode="o", usage="[nickname]") def voice(self, event): + """ + Voice a user in the current channel + """ target = event["user"].nickname if not event["args_split"] else event[ "args_split"][0] event["target"].send_mode("+v", target) + @Utils.hook("received.command.devoice", channel_only=True, + require_mode="o", usage="[nickname]") def devoice(self, event): + """ + Remove voice from a user in the current channel + """ target = event["user"].nickname if not event["args_split"] else event[ "args_split"][0] event["target"].send_mode("-v", target) + @Utils.hook("received.command.topic", min_args=1, require_mode="o", + channel_only=True, usage="") def topic(self, event): + """ + Set the topic in the current channel + """ event["target"].send_topic(event["args"]) + @Utils.hook("received.command.tappend", min_args=1, require_mode="o", + channel_only=True, usage="") def tappend(self, event): + """ + Append to the topic in the current channel + """ event["target"].send_topic(event["target"].topic + event["args"]) + @Utils.hook("received.message.channel") def highlight_spam(self, event): if event["channel"].get_setting("highlight-spam-protection", False): nicknames = list(map(lambda user: user.nickname, diff --git a/modules/channel_save.py b/modules/channel_save.py index 41a68481..b352d0a6 100644 --- a/modules/channel_save.py +++ b/modules/channel_save.py @@ -1,12 +1,7 @@ +from src import ModuleManager, Utils - -class Module(object): - def __init__(self, bot, events, exports): - events.on("received.numeric.001").hook(self.on_connect) - events.on("self.join").hook(self.on_join) - events.on("self.part").hook(self.on_part) - events.on("self.kick").hook(self.on_kick) - +class Module(ModuleManager.BaseModule): + @Utils.hook("received.numeric.001") def on_connect(self, event): channels = event["server"].get_setting("autojoin", []) chan_keys = event["server"].get_setting("channel_keys", {}) @@ -25,6 +20,7 @@ class Module(object): event["server"].send_join( ",".join(channels_sorted), ",".join(keys_sorted)) + @Utils.hook("self.join") def on_join(self, event): channels = event["server"].get_setting("autojoin", []) if not event["channel"].name in channels: @@ -37,8 +33,10 @@ class Module(object): channels.remove(channel_name) server.set_setting("autojoin", channels) + @Utils.hook("self.part") def on_part(self, event): self._remove_channel(event["server"], event["channel"].name) + @Utils.hook("self.kick") def on_kick(self, event): self._remove_channel(event["server"], event["channel"].name) diff --git a/modules/check_mode.py b/modules/check_mode.py index 788f573c..2d0298b6 100644 --- a/modules/check_mode.py +++ b/modules/check_mode.py @@ -1,10 +1,7 @@ +from src import ModuleManager, Utils - -class Module(object): - def __init__(self, bot, events, exports): - self.bot = bot - events.on("preprocess.command").hook(self.preprocess_command) - +class Module(ModuleManager.BaseModule): + @Utils.hook("preprocess.command") def preprocess_command(self, event): if event["is_channel"] and event["hook"].kwargs.get( "require_mode"): diff --git a/modules/check_urls.py b/modules/check_urls.py index fa05695e..b0438ec8 100644 --- a/modules/check_urls.py +++ b/modules/check_urls.py @@ -10,8 +10,6 @@ class Module(object): def __init__(self, bot, events, exports): self.bot = bot self.events = events - events.on("received.message.channel").hook(self.message) - exports.add("channelset", {"setting": "check-urls", "help": "Enable/Disable automatically checking for " "malicious URLs", "validate": Utils.bool_or_none}) @@ -22,6 +20,7 @@ class Module(object): "help": "Enable/Disable automatically kicking users that " "send malicious URLs", "validate": Utils.bool_or_none}) + @Utils.hook("received.message.channel") def message(self, event): match = RE_URL.search(event["message"]) if match and event["channel"].get_setting("check-urls", diff --git a/modules/coins.py b/modules/coins.py index e66aff6c..47b51cf1 100644 --- a/modules/coins.py +++ b/modules/coins.py @@ -28,34 +28,6 @@ REGEX_STREET = re.compile("street([1-9]|1[0-2])$") class Module(object): def __init__(self, bot, events, exports): self.bot = bot - events.on("received.command.coins").hook(self.coins, - help="Show how many coins you have") - - events.on("received.command.richest").hook( - self.richest, help="Show the top 10 richest users") - events.on("received.command.redeemcoins").hook( - self.redeem_coins, help="Redeem free coins") - - events.on("received.command.resetcoins").hook( - self.reset_coins, permission="resetcoins", - min_args=1, help= - "Reset a specified user's coins to %s" % str(DECIMAL_ZERO), - usage="") - events.on("received.command.givecoins").hook(self.give_coins, - min_args=1, help="Give coins to a user", - usage=" ", permission="givecoins") - - - events.on("received.command.flip").hook(self.flip, - help="Bet coins on a coin flip", usage= - "heads|tails ", min_args=2, authenticated=True) - events.on("received.command.roulette").hook( - self.roulette, min_args=2, help="Spin the roulette wheel", - usage=" ", authenticated=True) - - events.on("received.command.sendcoins").hook( - self.send, min_args=2, help="Send coins to a user", - usage=" ", authenticated=True) now = datetime.datetime.now() until_next_hour = 60-now.second @@ -65,7 +37,11 @@ class Module(object): bot.add_timer("coin-interest", INTEREST_INTERVAL, persist=False, next_due=time.time()+until_next_hour) + @Utils.hook("received.command.coins") def coins(self, event): + """ + Show how many coins you have + """ if event["args_split"]: target = event["server"].get_user(event["args_split"][0]) else: @@ -74,7 +50,12 @@ class Module(object): event["stdout"].write("%s has %s coin%s" % (target.nickname, "{0:.2f}".format(coins), "" if coins == 1 else "s")) + @Utils.hook("received.command.resetcoins", permission="resetcoins", + min_args=1, usage="") def reset_coins(self, event): + """ + Reset a user's coins to 0 + """ target = event["server"].get_user(event["args_split"][0]) coins = decimal.Decimal(target.get_setting("coins", "0.0")) if coins == DECIMAL_ZERO: @@ -84,7 +65,12 @@ class Module(object): target.del_setting("coins") event["stdout"].write("Reset coins for %s" % target.nickname) + @Utils.hook("received.command.givecoins", min_args=1, + usage=" ", permission="givecoins") def give_coins(self, event): + """ + Give coins to a user + """ target = event["server"].get_user(event["args_split"][0]) coins = event["args_split"][1] match = REGEX_FLOAT.match(coins) @@ -98,7 +84,11 @@ class Module(object): event["stdout"].write("Gave '%s' %s coins" % (target.nickname, str(coins))) + @Utils.hook("received.command.richest") def richest(self, event): + """ + Show the top 10 richest users + """ all_coins = event["server"].get_all_user_settings("coins", []) all_coins = list(filter(lambda coin: decimal.Decimal(coin[1]), all_coins)) @@ -112,7 +102,11 @@ class Module(object): all_coins[nickname])) for nickname in top_10) event["stdout"].write("Richest users: %s" % top_10) + @Utils.hook("received.command.redeemcoins") def redeem_coins(self, event): + """ + Redeem your free coins + """ user_coins = decimal.Decimal(event["user"].get_setting( "coins", "0.0")) if user_coins == DECIMAL_ZERO: @@ -137,7 +131,12 @@ class Module(object): event["stderr"].write( "You can only redeem coins when you have none") + @Utils.hook("received.command.flip", usage="heads|tails ", + min_args=2, authenticated=True) def flip(self, event): + """ + Bet on a coin flip + """ side_name = event["args_split"][0].lower() coin_bet = event["args_split"][1].lower() if coin_bet == "all": @@ -176,7 +175,12 @@ class Module(object): event["user"].nickname, side_name, coin_bet_str, "" if coin_bet == 1 else "s")) + @Utils.hook("received.command.sendcoins", min_args=2, + usage=" ", authenticated=True) def send(self, event): + """ + Send coins to another user + """ if event["user"].get_id() == event["server"].get_user(event[ "args_split"][0]).get_id(): event["stderr"].write("You can't send coins to yourself") @@ -239,7 +243,12 @@ class Module(object): str(coins)) event["timer"].redo() + @Utils.hook("received.command.roulette", min_args=2, + usage=" ", authenticated=True) def roulette(self, event): + """ + Spin a roulette wheel + """ bets = event["args_split"][0].lower().split(",") if "0" in bets: event["stderr"].write("You can't bet on 0") diff --git a/modules/commands.py b/modules/commands.py index a58d0748..3bc2604f 100644 --- a/modules/commands.py +++ b/modules/commands.py @@ -45,29 +45,7 @@ class StdErr(Out): class Module(object): def __init__(self, bot, events, exports): - self.bot = bot self.events = events - events.on("received.message.channel").hook(self.channel_message, - priority=EventManager.PRIORITY_LOW) - events.on("received.message.private").hook(self.private_message, - priority=EventManager.PRIORITY_LOW) - - events.on("received.command.help").hook(self.help, - help="Show help for commands", usage="") - events.on("received.command.usage").hook(self.usage, min_args=1, - help="Show usage help for commands", usage="") - events.on("received.command.more").hook(self.more, skip_out=True, - help="Get more output from the last command") - events.on("received.command.ignore").hook(self.ignore, min_args=1, - help="Ignore commands from a given user", usage="", - permission="ignore") - events.on("received.command.unignore").hook(self.unignore, min_args=1, - help="Unignore commands from a given user", usage="", - permission="unignore") - - events.on("new").on("user", "channel").hook(self.new) - events.on("send.stdout").hook(self.send_stdout) - events.on("send.stderr").hook(self.send_stderr) exports.add("channelset", {"setting": "command-prefix", "help": "Set the command prefix used in this channel"}) @@ -76,6 +54,7 @@ class Module(object): exports.add("serverset", {"setting": "identity-mechanism", "help": "Set the identity mechanism for this server"}) + @Utils.hook("new.user|channel") def new(self, event): if "user" in event: target = event["user"] @@ -156,6 +135,7 @@ class Module(object): buffer.skip_next() event.eat() + @Utils.hook("received.message.channel", priority=EventManager.PRIORITY_LOW) def channel_message(self, event): command_prefix = event["channel"].get_setting("command-prefix", event["server"].get_setting("command-prefix", "!")) @@ -168,6 +148,7 @@ class Module(object): command = event["message_split"][1].lower() self.message(event, command, 2) + @Utils.hook("received.message.private", priority=EventManager.PRIORITY_LOW) def private_message(self, event): if event["message_split"]: command = event["message_split"][0].lower() @@ -176,7 +157,11 @@ class Module(object): def _get_help(self, hook): return hook.kwargs.get("help", None) or hook.function.__doc__ + @Utils.hook("received.command.help", usage="") def help(self, event): + """ + Show help for a given command + """ if event["args"]: command = event["args_split"][0].lower() if command in self.events.on("received").on( @@ -185,7 +170,8 @@ class Module(object): help = self._get_help(hooks[0]) if help: - event["stdout"].write("%s: %s" % (command, help.strip())) + event["stdout"].write("%s: %s" % (command, " ".join( + [line.strip() for line in help.split("\n")]))) else: event["stderr"].write("No help available for %s" % command) else: @@ -200,7 +186,11 @@ class Module(object): help_available = sorted(help_available) event["stdout"].write("Commands: %s" % ", ".join(help_available)) + @Utils.hook("received.command.usage", min_args=1, usage="") def usage(self, event): + """ + Show the usage for a given command + """ command_prefix = "" if event["is_channel"]: command_prefix = event["target"].get_setting("command-prefix", @@ -218,11 +208,20 @@ class Module(object): else: event["stderr"].write("Unknown command '%s'" % command) + @Utils.hook("received.command.more", skip_out=True) def more(self, event): + """ + Show more output from the last command + """ if event["target"].last_stdout and event["target"].last_stdout.has_text(): event["target"].last_stdout.send() + @Utils.hook("received.command.ignore", min_args=1, usage="", + permission="ignore") def ignore(self, event): + """ + Ignore commands from a given user + """ user = event["server"].get_user(event["args_split"][0]) if user.get_setting("ignore", False): event["stderr"].write("I'm already ignoring '%s'" % @@ -231,7 +230,12 @@ class Module(object): user.set_setting("ignore", True) event["stdout"].write("Now ignoring '%s'" % user.nickname) + @Utils.hook("received.command.unignore", min_args=1, usage="", + permission="unignore") def unignore(self, event): + """ + Unignore commands from a given user + """ user = event["server"].get_user(event["args_split"][0]) if not user.get_setting("ignore", False): event["stderr"].write("I'm not ignoring '%s'" % user.nickname) @@ -239,11 +243,13 @@ class Module(object): user.set_setting("ignore", False) event["stdout"].write("Removed ignore for '%s'" % user.nickname) + @Utils.hook("send.stdout") def send_stdout(self, event): stdout = StdOut(event["module_name"], event["target"]) stdout.write(event["message"]).send() if stdout.has_text(): event["target"].last_stdout = stdout + @Utils.hook("send.stderr") def send_stderr(self, event): stderr = StdErr(event["module_name"], event["target"]) stderr.write(event["message"]).send() diff --git a/modules/ctcp.py b/modules/ctcp.py index a9144974..efb855fb 100644 --- a/modules/ctcp.py +++ b/modules/ctcp.py @@ -4,11 +4,11 @@ from src import Utils class Module(object): def __init__(self, bot, events, exports): self.bot = bot - events.on("received.message.private").hook(self.private_message) exports.add("serverset", {"setting": "ctcp-responses", "help": "Set whether I respond to CTCPs on this server", "validate": Utils.bool_or_none}) + @Utils.hook("received.message.private") def private_message(self, event): if event["message"][0] == "\x01" and event["message"][-1] == "\x01": if event["server"].get_setting("ctcp-responses", True): diff --git a/modules/database_backup.py b/modules/database_backup.py index 27a366a3..45bc730f 100644 --- a/modules/database_backup.py +++ b/modules/database_backup.py @@ -1,4 +1,5 @@ import datetime, glob, os, shutil, time +from src import Utils BACKUP_INTERVAL = 60*60 # 1 hour BACKUP_COUNT = 5 @@ -10,10 +11,10 @@ class Module(object): until_next_hour = 60-now.second until_next_hour += ((60-(now.minute+1))*60) - events.on("timer.database-backup").hook(self.backup) bot.add_timer("database-backup", BACKUP_INTERVAL, persist=False, next_due=time.time()+until_next_hour) + @Utils.hook("timer.database-backup") def backup(self, event): full_location = self.bot.database.full_location files = glob.glob("%s.*" % full_location) diff --git a/modules/define.py b/modules/define.py index 1b88e83b..178a9c5a 100644 --- a/modules/define.py +++ b/modules/define.py @@ -12,13 +12,6 @@ class Module(object): def __init__(self, bot, events, exports): self.bot = bot self._last_called = 0 - self.events = events - - events.on("received.command.define").hook(self.define, - help="Define a provided term", usage="") - - events.on("received.command.randomword").hook(self.random_word, - help="Generate a random word!") def _get_definition(self, word): word = event["args"] if "args" in event else event @@ -30,7 +23,11 @@ class Module(object): return page + @Utils.hook("received.command.define", usage="") def define(self, event): + """ + Define a provided term + """ if event["args"]: word = event["args"] else: @@ -46,7 +43,11 @@ class Module(object): else: event["stderr"].write("Failed to load results") + @Utils.hook("received.command.randomword") def random_word(self, event): + """ + Define a random word + """ if not self._last_called or (time.time()-self._last_called >= RANDOM_DELAY_SECONDS): self._last_called = time.time() diff --git a/modules/dice.py b/modules/dice.py index 30e4f319..cb48efae 100644 --- a/modules/dice.py +++ b/modules/dice.py @@ -1,28 +1,24 @@ import random -from src import Utils +from src import ModuleManager, Utils -class Module(object): - def __init__(self, bot, events, exports): - events.on("received.command.roll").hook( - self.roll_dice, - min_args=1, - help="Roll some dice, DND style!", - usage="[1-5]d[1-20]" - ) - - self.err_msg = "Incorrectly formatted dice! Format must be [number]d[number], for example, 1d20" +ERROR_FORMAT = "Incorrect format! Format must be [number]d[number], e.g. 1d20" +class Module(ModuleManager.BaseModule): + @Utils.hook("received.command.roll", min_args=1, usage="[1-5]d[1-20]") def roll_dice(self, event): + """ + Roll some dice, DND style! + """ raw_input = event["args_split"][0] roll = raw_input.split("d") results = [] if len(roll) is not 2: - event["stderr"].write(self.err_msg) + event["stderr"].write(ERROR_FORMAT) return if roll[0].isdigit() is False or roll[1].isdigit() is False: - event["stderr"].write(self.err_msg) + event["stderr"].write(ERROR_FORMAT) return roll = [int(roll[0]), int(roll[1])] diff --git a/modules/dns.py b/modules/dns.py index e5552aa8..19ef7ea0 100644 --- a/modules/dns.py +++ b/modules/dns.py @@ -1,13 +1,14 @@ import socket +from src import ModuleManager, Utils -class Module(object): +class Module(ModuleManager.BaseModule): _name = "DNS" - def __init__(self, bot, events, exports): - events.on("received.command.dns").hook(self.dns, min_args=1, - help="Get all addresses for a given hostname (IPv4/IPv6)", - usage="") + @Utils.hook("received.command.dns", min_args=1, usage="") def dns(self, event): + """ + Get all addresses for a given hostname (IPv4/IPv6) + """ hostname = event["args_split"][0] try: address_info = socket.getaddrinfo(hostname, 1, 0, diff --git a/modules/ducks.py b/modules/ducks.py index a9c4f6b5..56f495c8 100644 --- a/modules/ducks.py +++ b/modules/ducks.py @@ -15,30 +15,8 @@ DUCK_MINIMUM_UNIQUE = 3 class Module(object): - def __init__(self, bot, events, exports): self.bot = bot - self.events = events - - events.on("received.command.bef").hook(self.befriend, - priority=EventManager.PRIORITY_HIGH, - help="Befriend a duck!") - events.on("received.command.bang").hook(self.shoot, - priority=EventManager.PRIORITY_HIGH, - help="Shoot a duck! Meanie.") - events.on("received.command.decoy").hook( - self.duck_decoy, - priority=EventManager.PRIORITY_HIGH, - help="Lay out a sneaky decoy!") - - - events.on("received.command.friends").hook(self.duck_friends, - help="See who the friendliest people to ducks are!") - events.on("received.command.killers").hook(self.duck_enemies, - help="See who shoots the most smount of ducks!") - events.on("received.command.duckstats").hook(self.duck_stats, - help="Shows your duck stats!") - exports.add("channelset", {"setting": "ducks-enabled", "help": "Toggle ducks!", "validate": Utils.bool_or_none}) @@ -47,24 +25,18 @@ class Module(object): "validate": Utils.bool_or_none}) exports.add("channelset", {"setting": "ducks-min-unique", - "help": "Minimum unique users required to " - "talk before a duck spawns.", - "validate": Utils.int_or_none}) + "help": "Minimum unique users required to talk before a " + "duck spawns.", "validate": Utils.int_or_none}) exports.add("channelset", {"setting": "ducks-min-messages", - "help": "Minimum messages between ducks " - "spawning.", - "validate": Utils.int_or_none}) - - events.on("new.channel").hook(self.new_channel) - - events.on("received.message.channel").hook( - self.channel_message, EventManager.PRIORITY_LOW) + "help": "Minimum messages between ducks spawning.", + "validate": Utils.int_or_none}) for server in self.bot.servers.values(): for channel in server.channels.values(): self.bootstrap(channel) + @Utils.hook("new.channel") def new_channel(self, event): self.bootstrap(event["channel"]) @@ -148,7 +120,11 @@ class Module(object): channel.send_kick(target, "You tried shooting a non-existent duck. Creepy!") + @Utils.hook("received.command.decoy") def duck_decoy(self, event): + """ + Prepare a decoy duck + """ channel = event["target"] if self.is_duck_channel(channel) == False: return @@ -219,6 +195,8 @@ class Module(object): else: game["duck_spawned"] = 1 + @Utils.hook("received.message.channel", + priority=EventManager.PRIORITY_MONITOR) def channel_message(self, event): if not event["channel"].get_setting("ducks-enabled", False): return @@ -248,7 +226,11 @@ class Module(object): if self.should_generate_duck(event) == True: self.show_duck(event) + @Utils.hook("received.command.bef") def befriend(self, event): + """ + Befriend a duck + """ channel = event["target"] user = event["user"] nick = user.nickname @@ -282,7 +264,11 @@ class Module(object): self.clear_ducks(channel) event.eat() + @Utils.hook("received.command.bang") def shoot(self, event): + """ + Shoot a duck + """ channel = event["target"] user = event["user"] nick = user.nickname @@ -317,7 +303,11 @@ class Module(object): self.clear_ducks(channel) event.eat() + @Utils.hook("received.command.duckstats") def duck_stats(self, event): + """ + Show your duck stats + """ user = event["user"] channel = event["target"].name nick = user.nickname @@ -358,7 +348,11 @@ class Module(object): event["stdout"].write(Utils.bold(nick) + ": " + msg) event.eat() + @Utils.hook("received.command.killers") def duck_enemies(self, event): + """ + Show the top duck shooters + """ the_enemy = event["server"].find_all_user_channel_settings("ducks-shot") notorious = {} @@ -392,7 +386,11 @@ class Module(object): event["stdout"].write(sentence) event.eat() + @Utils.hook("received.command.friends") def duck_friends(self, event): + """ + Show the top duck friends + """ friends = event["server"].find_all_user_channel_settings( "ducks-befriended") diff --git a/modules/eval.py b/modules/eval.py index ab68a368..3db6bd3e 100644 --- a/modules/eval.py +++ b/modules/eval.py @@ -1,14 +1,14 @@ import socket -from src import Utils +from src import ModuleManager, Utils EVAL_URL = "https://eval.appspot.com/eval" -class Module(object): - def __init__(self, bot, events, exports): - events.on("received.command.eval").hook(self.eval, min_args=1, - help="Evaluate a python statement", usage="") - +class Module(ModuleManager.BaseModule): + @Utils.hook("received.command.eval", min_args=1, usage="") def eval(self, event): + """ + Evaluate a python statement + """ try: code, page = Utils.get_url(EVAL_URL, get_params={ "statement": event["args"]}, code=True) diff --git a/modules/geoip.py b/modules/geoip.py index 5bc464b1..f20df6aa 100644 --- a/modules/geoip.py +++ b/modules/geoip.py @@ -1,14 +1,15 @@ -from src import Utils +from src import ModuleManager, Utils URL_GEOIP = "http://ip-api.com/json/%s" -class Module(object): +class Module(ModuleManager.BaseModule): _name = "GeoIP" - def __init__(self, bot, events, exports): - events.on("received.command.geoip").hook(self.geoip, min_args=1, - help="Get geoip data on a given IPv4/IPv6 address", usage="") + @Utils.hook("received.command.geoip", min_args=1, usage="") def geoip(self, event): + """ + Get geoip data on a given IPv4/IPv6 address + """ page = Utils.get_url(URL_GEOIP % event["args_split"][0], json=True) if page: diff --git a/modules/google.py b/modules/google.py index 1d7b6e8c..f98ed2ad 100644 --- a/modules/google.py +++ b/modules/google.py @@ -10,12 +10,12 @@ URL_GOOGLESUGGEST = "http://google.com/complete/search" class Module(object): def __init__(self, bot, events, exports): self.bot = bot - events.on("received.command").on("google", "g").hook(self.google, - help="Google feeling lucky", usage="[search term]") - events.on("received.command.suggest").hook(self.suggest, - help="Get suggested phrases from Google", usage="[phrase]") + @Utils.hook("received.command.google|g", usage="[search term]") def google(self, event): + """ + Get first Google result for a given search term + """ phrase = event["args"] or event["buffer"].get() if phrase: page = Utils.get_url(URL_GOOGLESEARCH, get_params={ @@ -34,7 +34,11 @@ class Module(object): else: event["stderr"].write("No phrase provided") + @Utils.hook("received.command.suggest", usage="[phrase]") def suggest(self, event): + """ + Get suggested phrases from Google + """ phrase = event["args"] or event["buffer"].get() if phrase: page = Utils.get_url(URL_GOOGLESUGGEST, get_params={ diff --git a/modules/greeting.py b/modules/greeting.py index 45ba0b7b..9d0eb838 100644 --- a/modules/greeting.py +++ b/modules/greeting.py @@ -1,11 +1,11 @@ - +from src import Utils class Module(object): def __init__(self, bot, events, exports): - events.on("received.join").hook(self.join) exports.add("channelset", {"setting": "greeting", "help": "Set a greeting to send to users when they join"}) + @Utils.hook("recevied.join") def join(self, event): greeting = event["channel"].get_setting("greeting", None) if greeting: diff --git a/modules/hash.py b/modules/hash.py index e123da9a..4508d613 100644 --- a/modules/hash.py +++ b/modules/hash.py @@ -1,12 +1,12 @@ import hashlib +from src import ModuleManager, Utils -class Module(object): - def __init__(self, bot, events, exports): - self.bot = bot - events.on("received.command.hash").hook(self.hash, min_args=2, - help="Hash a string", usage=" ") - +class Module(ModuleManager.BaseModule): + @Utils.hook("received.command.hash", min_args=2, usage=" ") def hash(self, event): + """ + Hash a given string with a given algorithm + """ algorithm = event["args_split"][0].lower() if algorithm in hashlib.algorithms_available: phrase = " ".join(event["args_split"][1:]) diff --git a/modules/haveibeenpwned.py b/modules/haveibeenpwned.py index 79662913..0a328c3e 100644 --- a/modules/haveibeenpwned.py +++ b/modules/haveibeenpwned.py @@ -1,15 +1,16 @@ -from src import Utils +from src import ModuleManager, Utils URL_HAVEIBEENPWNEDAPI = "https://haveibeenpwned.com/api/v2/breachedaccount/%s" URL_HAVEIBEENPWNED = "https://haveibeenpwned.com/" -class Module(object): - def __init__(self, bot, events, exports): - events.on("received.command.beenpwned").hook(self.beenpwned, - help="Find out if a username, email or similar has appeared " - "in any hacked databases", usage="", min_args=1) - +class Module(ModuleManager.BaseModule): + @Utils.hook("received.command.beenpwned", usage="", + min_args=1) def beenpwned(self, event): + """ + Find out if a username, email or similar has appeared in any + hacked databases + """ page = Utils.get_url(URL_HAVEIBEENPWNEDAPI % event["args"], json=True, code=True) if page: diff --git a/modules/ids.py b/modules/ids.py index 17b20a6e..fb81f492 100644 --- a/modules/ids.py +++ b/modules/ids.py @@ -1,18 +1,20 @@ +from src import ModuleManager, Utils - -class Module(object): +class Module(ModuleManager.BaseModule): _name = "IDs" - def __init__(self, bot, events, exports): - events.on("received.command.myid").hook(self.my_id, - help="Show your user ID") - events.on("received.command.channelid").hook( - self.channel_id, channel_only=True, - help="Show the current channel's ID") + @Utils.hook("received.command.myid") def my_id(self, event): + """ + Show your user ID + """ event["stdout"].write("%s: %d" % (event["user"].nickname, event["user"].get_id())) + @Utils.hook("received.command.channelid", channel_only=True) def channel_id(self, event): + """ + Show the current channel's ID + """ event["stdout"].write("%s: %d" % (event["target"].name, event["target"].id)) diff --git a/modules/imdb.py b/modules/imdb.py index 741b2955..d735910f 100644 --- a/modules/imdb.py +++ b/modules/imdb.py @@ -10,10 +10,12 @@ class Module(object): _name = "IMDb" def __init__(self, bot, events, exports): self.bot = bot - events.on("received.command.imdb").hook(self.imdb, min_args=1, - help="Search for a given title on IMDb", usage="") + @Utils.hook("received.command.imdb", min_args=1, usage="") def imdb(self, event): + """ + Search for a given title on IMDb + """ page = Utils.get_url(URL_OMDB, get_params={ "t": event["args"], "apikey": self.bot.config["omdbapi-api-key"]}, diff --git a/modules/in.py b/modules/in.py index 2351fb11..52363fec 100644 --- a/modules/in.py +++ b/modules/in.py @@ -7,11 +7,12 @@ SECONDS_MAX_DESCRIPTION = "8 weeks" class Module(object): def __init__(self, bot, events, exports): self.bot = bot - events.on("received.command.in").hook(self.in_command, min_args=2, - help="Set a reminder", usage="