diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/channel_op.py | 28 | ||||
| -rw-r--r-- | modules/define.py | 5 | ||||
| -rw-r--r-- | modules/dice.py | 8 | ||||
| -rw-r--r-- | modules/eval_python.py | 2 | ||||
| -rw-r--r-- | modules/git_webhooks/github.py | 6 | ||||
| -rw-r--r-- | modules/healthcheck.py | 7 | ||||
| -rw-r--r-- | modules/hostmask_tracking.py | 40 | ||||
| -rw-r--r-- | modules/ircv3_typing.py | 7 | ||||
| -rw-r--r-- | modules/karma.py | 6 | ||||
| -rw-r--r-- | modules/quotes.py | 28 | ||||
| -rw-r--r-- | modules/relay.py | 2 | ||||
| -rw-r--r-- | modules/sed.py | 7 | ||||
| -rw-r--r-- | modules/user_time.py | 32 | ||||
| -rw-r--r-- | modules/words.py | 19 |
14 files changed, 150 insertions, 47 deletions
diff --git a/modules/channel_op.py b/modules/channel_op.py index bc307778..98f170bb 100644 --- a/modules/channel_op.py +++ b/modules/channel_op.py @@ -51,13 +51,12 @@ class Module(ModuleManager.BaseModule): event["args_split"][1:]) def _format_hostmask(self, user, s): - mask_split = s.split("$$") - for i, mask_part in enumerate(mask_split): - mask_split[i] = (mask_part.replace("$n", user.nickname) - .replace("$u", user.username) - .replace("$h", user.hostname) - .replace("$a", user.account or "")) - return "$".join(mask_split) + vars = {} + vars["n"] = vars["nickname"] = user.nickname + vars["u"] = vars["username"] = user.username + vars["h"] = vars["hostname"] = user.hostname + vars["a"] = vars["account"] = user.account or "" + return utils.parse.format_token_replace(s, vars) def _get_hostmask(self, channel, user): if not user.account == None: account_format = channel.get_setting("ban-format-account", None) @@ -123,13 +122,24 @@ class Module(ModuleManager.BaseModule): self._kick(event["server"], event["target"], args[0], args[1:]) @utils.hook("received.command.op") - @utils.hook("received.command.deop") + @utils.hook("received.command.up", alias_of="op") @utils.kwarg("channel_only", True) @utils.kwarg("require_mode", "o") @utils.kwarg("require_access", "op") @utils.kwarg("usage", "[nickname]") def op(self, event): - add = event["command"] == "op" + self._op(True, event) + + @utils.hook("received.command.deop") + @utils.hook("received.command.down", alias_of="deop") + @utils.kwarg("channel_only", True) + @utils.kwarg("require_mode", "o") + @utils.kwarg("require_access", "op") + @utils.kwarg("usage", "[nickname]") + def deop(self, event): + self._op(False, event) + + def _op(self, add, event): target = event["args_split"][0] if event["args"] else event[ "user"].nickname event["target"].send_mode("+o" if add else "-o", [target]) diff --git a/modules/define.py b/modules/define.py index 4e83c65c..6bc37774 100644 --- a/modules/define.py +++ b/modules/define.py @@ -36,6 +36,11 @@ class Module(ModuleManager.BaseModule): word = event["args"] else: word = event["target"].buffer.get(from_self=False) + if word: + word = word.message + + if not word: + raise utils.EventError("No phrase provided") word = word.replace(" ", "+") success, definition = self._get_definition(word) diff --git a/modules/dice.py b/modules/dice.py index cf4f53a2..8e34c9e0 100644 --- a/modules/dice.py +++ b/modules/dice.py @@ -4,7 +4,8 @@ import random, re from src import ModuleManager, utils ERROR_FORMAT = "Incorrect format! Format must be [number]d[number], e.g. 1d20" -RE_DICE = re.compile("^([1-9]\d*)?d([1-9]\d*)((?:[-+][1-9]\d{,2})*)$", re.I) +RE_DICE = re.compile("^([1-9]\d*)?d([1-9]\d*)((?:\s*[-+][1-9]\d{,2})*)\s*$", + re.I) RE_MODIFIERS = re.compile("([-+]\d+)") MAX_DICE = 6 @@ -18,7 +19,7 @@ class Module(ModuleManager.BaseModule): def roll_dice(self, event): args = None if event["args_split"]: - args = event["args_split"][0] + args = event["args"] else: args = "1d6" @@ -27,7 +28,8 @@ class Module(ModuleManager.BaseModule): roll = match.group(0) dice_count = int(match.group(1) or "1") side_count = int(match.group(2)) - modifiers = RE_MODIFIERS.findall(match.group(3)) + modifiers_str = "".join(match.group(3).split()) + modifiers = RE_MODIFIERS.findall(modifiers_str) if dice_count > 6: raise utils.EventError("Max number of dice is %s" % MAX_DICE) diff --git a/modules/eval_python.py b/modules/eval_python.py index 5454b7d3..eb2b5898 100644 --- a/modules/eval_python.py +++ b/modules/eval_python.py @@ -21,6 +21,6 @@ class Module(ModuleManager.BaseModule): if page and page.data: event["stdout"].write("%s: %s" % (event["user"].nickname, - page.decode().rstrip("\n"))) + page.decode("utf8").rstrip("\n"))) else: event["stderr"].write("%s: failed to eval" % event["user"].nickname) diff --git a/modules/git_webhooks/github.py b/modules/git_webhooks/github.py index 20a3fb74..96dc26c3 100644 --- a/modules/git_webhooks/github.py +++ b/modules/git_webhooks/github.py @@ -39,12 +39,14 @@ EVENT_CATEGORIES = { "pull_request_review_comment/deleted" ], "issue-minimal": [ - "issues/opened", "issues/closed", "issues/reopened", "issues/deleted" + "issues/opened", "issues/closed", "issues/reopened", "issues/deleted", + "issues/transferred" ], "issue": [ "issues/opened", "issues/closed", "issues/reopened", "issues/deleted", "issues/edited", "issues/assigned", "issues/unassigned", - "issues/locked", "issues/unlocked", "issue_comment" + "issues/locked", "issues/unlocked", "issues/transferred", + "issue_comment", ], "issue-all": [ "issues", "issue_comment" diff --git a/modules/healthcheck.py b/modules/healthcheck.py index 0cf2c72b..3b5acfe2 100644 --- a/modules/healthcheck.py +++ b/modules/healthcheck.py @@ -9,4 +9,9 @@ class Module(ModuleManager.BaseModule): @utils.hook("cron") @utils.kwarg("schedule", "*/10") def ten_minutes(self, event): - utils.http.request(self.bot.config["healthcheck-url"]) + url = self.bot.config["healthcheck-url"] + try: + utils.http.request(url) + except Exception as e: + self.log.error("Failed to cal healthcheck-url (%s)", [url], + exc_info=True) diff --git a/modules/hostmask_tracking.py b/modules/hostmask_tracking.py new file mode 100644 index 00000000..5cf82232 --- /dev/null +++ b/modules/hostmask_tracking.py @@ -0,0 +1,40 @@ +from src import ModuleManager, utils + +class Module(ModuleManager.BaseModule): + _name = "Hostmasks" + + @utils.hook("new.user") + def new_user(self, event): + userhost = event["user"].userhost() + if not userhost == None: + known_hostmasks = event["user"].get_setting("known-hostmasks", []) + if not userhost in known_hostmasks: + known_hostmasks.append(userhost) + event["user"].set_setting("known-hostmasks", known_hostmasks) + + @utils.hook("received.command.maskfind") + @utils.kwarg("min_args", 1) + @utils.kwarg("help", "Find all nicknames that used a given hostmask") + @utils.kwarg("usage", "<hostmask>") + @utils.kwarg("permission", "maskfind") + def maskfind(self, event): + all_userhosts = event["server"].get_all_user_settings("known-hostmasks") + nicknames = set([]) + hostmask_str = event["args_split"][0] + hostmask = utils.irc.hostmask_parse(hostmask_str) + + searched = 0 + for nickname, userhosts in all_userhosts: + searched += len(userhosts) + for userhost in userhosts: + if hostmask.match(userhost): + nicknames.add((nickname, userhost)) + + if nicknames: + outs = [] + for nickname, userhost in sorted(nicknames): + outs.append("%s (%s)" % (utils.irc.bold(nickname), userhost)) + event["stdout"].write("%s (%d/%d): %s" % + (hostmask_str, len(nicknames), searched, ", ".join(outs))) + else: + event["stderr"].write("Hostmask not found") diff --git a/modules/ircv3_typing.py b/modules/ircv3_typing.py index ca2fce2b..3c8c9c6d 100644 --- a/modules/ircv3_typing.py +++ b/modules/ircv3_typing.py @@ -9,10 +9,13 @@ class Module(ModuleManager.BaseModule): def _has_tags(self, server): return server.has_capability(CAP) + def _expect_output(self, event): + kwarg = event["hook"].get_kwarg("expect_output", None) + return kwarg if not kwarg is None else event["expect_output"] + @utils.hook("preprocess.command") def preprocess(self, event): - if (self._has_tags(event["server"]) and - event["hook"].get_kwarg("expect_output", True)): + if self._has_tags(event["server"]) and self._expect_output(event): event["target"]._typing = True event["server"].send(self._tagmsg(event["target_str"], "active"), immediate=True) diff --git a/modules/karma.py b/modules/karma.py index f728e7e1..194bd424 100644 --- a/modules/karma.py +++ b/modules/karma.py @@ -7,7 +7,7 @@ from src import EventManager, ModuleManager, utils KARMA_DELAY_SECONDS = 3 -REGEX_WORD = re.compile(r"^([^(\s,:]+)(?:[:,]\s*)?(\+\+|--)\s*$") +REGEX_WORD = re.compile(r"^([^(\s,:]+)(?:[:,])?\s*(\+\+|--)\s*$") REGEX_WORD_START = re.compile(r"^(\+\+|--)(?:\s*)([^(\s,:]+)\s*$") REGEX_PARENS = re.compile(r"\(([^)]+)\)(\+\+|--)") @@ -68,8 +68,8 @@ class Module(ModuleManager.BaseModule): karma_total = self._karma_str(self._get_karma(server, target)) - return True, "%s has given %s %s karma (%s total)" % ( - sender.nickname, target, karma_str, karma_total) + return True, "%s now has %s karma (%s from %s)" % ( + target, karma_total, karma_str, sender.nickname) @utils.hook("command.regex", pattern=REGEX_WORD) @utils.hook("command.regex", pattern=REGEX_PARENS) diff --git a/modules/quotes.py b/modules/quotes.py index 7a1c0939..f6dd223f 100644 --- a/modules/quotes.py +++ b/modules/quotes.py @@ -14,10 +14,10 @@ class Module(ModuleManager.BaseModule): return category, None return category, quote.strip() - def _get_quotes(self, server, category): - return server.get_setting("quotes-%s" % category, []) - def _set_quotes(self, server, category, quotes): - server.set_setting("quotes-%s" % category, quotes) + def _get_quotes(self, target, category): + return target.get_setting("quotes-%s" % category, []) + def _set_quotes(self, target, category, quotes): + target.set_setting("quotes-%s" % category, quotes) @utils.hook("received.command.qadd", alias_of="quoteadd") @utils.hook("received.command.quoteadd", min_args=1) @@ -39,6 +39,9 @@ class Module(ModuleManager.BaseModule): else: event["stderr"].write("Please provide a category AND quote") + def _target_zip(self, target, quotes): + return [[u, t, q, target] for u, t, q in quotes] + @utils.hook("received.command.qdel", alias_of="quotedel") @utils.hook("received.command.quotedel", min_args=1) @utils.kwarg("help", "Delete a given quote from a given category") @@ -48,27 +51,34 @@ class Module(ModuleManager.BaseModule): category = category or event["args"].strip() message = None - setting = "quotes-%s" % category - quotes = event["server"].get_setting(setting, []) + quotes = self._target_zip(event["server"], + self._get_quotes(event["server"], category)) + if event["is_channel"]: + quotes += self._target_zip(event["target"], + self._get_quotes(event["target"], category)) + quotes = sorted(quotes, key=lambda q: q[1]) if not quotes: raise utils.EventError("Quote category '%s' not found" % category) + found_target = None if not remove_quote == None: remove_quote_lower = remove_quote.lower() - for nickname, time_added, quote in quotes[:]: + for nickname, time_added, quote, target in quotes[:]: if quote.lower() == remove_quote_lower: quotes.remove([nickname, time_added, quote]) + found_target = target message = "Removed quote from '%s'" break else: if quotes: - quotes.pop(-1) + quote = quotes.pop(-1) + found_target = quote[-1] message = "Removed last '%s' quote" if not message == None: - event["server"].set_setting(setting, quotes) + self._set_quotes(found_target, category, quotes) event["stdout"].write(message % category) else: event["stderr"].write("Quote not found") diff --git a/modules/relay.py b/modules/relay.py index 9e266043..4719ee85 100644 --- a/modules/relay.py +++ b/modules/relay.py @@ -81,8 +81,6 @@ class Module(ModuleManager.BaseModule): @utils.kwarg("min_args", 1) @utils.kwarg("help", "Edit configured relay groups") @utils.kwarg("usage", "list") - @utils.kwarg("usage", "add <name>") - @utils.kwarg("usage", "remove <name>") @utils.kwarg("usage", "join <name>") @utils.kwarg("usage", "leave <name>") @utils.kwarg("permission", "relay") diff --git a/modules/sed.py b/modules/sed.py index f3fe4864..af597f81 100644 --- a/modules/sed.py +++ b/modules/sed.py @@ -73,7 +73,12 @@ class Module(ModuleManager.BaseModule): if match: replace = sed_split[2] replace = replace.replace("\\/", "/") - replace = re.sub(SED_AMPERSAND, "\\1%s" % match, replace) + + with utils.deadline(): + for found in SED_AMPERSAND.finditer(replace): + found = found.group(1) + replace.replace(found, "%s%s" % (found, match)) + replace_color = utils.irc.bold(replace) new_message = re.sub(pattern, replace, message, count) diff --git a/modules/user_time.py b/modules/user_time.py index 19ed4b22..48077d81 100644 --- a/modules/user_time.py +++ b/modules/user_time.py @@ -15,6 +15,9 @@ class LocationType(enum.Enum): class Module(ModuleManager.BaseModule): _name = "Time" + def on_load(self): + self.exports.add("time-localise", self.time_localise) + def _find_setting(self, event): query = None target_user = None @@ -41,6 +44,15 @@ class Module(ModuleManager.BaseModule): else: return LocationType.NAME, event["args"], None + def _timezoned(self, dt, timezone): + dt = dt.astimezone(pytz.timezone(timezone)) + utc_offset = (dt.utcoffset().total_seconds()/60)/60 + tz = "UTC" + if not utc_offset == 0.0: + if utc_offset > 0: + tz += "+" + tz += "%g" % utc_offset + return "%s %s" % (utils.datetime.datetime_human(dt), tz) @utils.hook("received.command.time") @utils.kwarg("help", "Get the time for you or someone else") @@ -51,20 +63,13 @@ class Module(ModuleManager.BaseModule): type, name, timezone = self._find_setting(event) if not timezone == None: - dt = datetime.datetime.now(tz=pytz.timezone(timezone)) - utc_offset = (dt.utcoffset().total_seconds()/60)/60 - tz = "UTC" - if not utc_offset == 0.0: - if utc_offset > 0: - tz += "+" - tz += "%g" % utc_offset - human = utils.datetime.datetime_human(dt) + human = self._timezoned(datetime.datetime.now(), timezone) out = None if type == LocationType.USER: - out = "Time for %s: %s %s" % (name, human, tz) + out = "Time for %s: %s" % (name, human) else: - out = "It is %s in %s %s" % (human, name, tz) + out = "It is %s in %s" % (human, name) event["stdout"].write(out) else: out = None @@ -74,3 +79,10 @@ class Module(ModuleManager.BaseModule): out = NOLOCATION_NAME event["stderr"].write(out % name) + + def time_localise(self, user, dt): + location = user.get_setting("location", None) + timezone = "UTC" + if not location == None: + timezone = location["timezone"] + return self._timezoned(dt, timezone) diff --git a/modules/words.py b/modules/words.py index c76fb3dc..716b7437 100644 --- a/modules/words.py +++ b/modules/words.py @@ -129,6 +129,12 @@ class Module(ModuleManager.BaseModule): else: event["stderr"].write("That word is not being tracked") + def _get_nickname(self, server, target, nickname): + nickname = server.get_user(nickname).nickname + if target.get_setting("wordiest-prevent-highlight", True): + nickname = utils.prevent_highlight(nickname) + return nickname + @utils.hook("received.command.wordiest") def wordiest(self, event): """ @@ -137,8 +143,13 @@ class Module(ModuleManager.BaseModule): """ channel_query = None word_prefix = "" - if event["args_split"]: - channel_query = event["args_split"][0].lower() + if event["args"]: + if not event["args_split"][0] == "*": + channel_query = event["args_split"][0].lower() + elif event["is_channel"]: + channel_query = event["target"].name + + if channel_query: word_prefix = " (%s)" % channel_query words = event["server"].find_all_user_channel_settings("words") @@ -150,7 +161,7 @@ class Module(ModuleManager.BaseModule): user_words[nickname] += word_count top_10 = utils.top_10(user_words, - convert_key=lambda nickname: - event["server"].get_user(nickname).nickname) + convert_key=lambda nickname: self._get_nickname( + event["server"], event["target"], nickname)) event["stdout"].write("wordiest%s: %s" % ( word_prefix, ", ".join(top_10))) |
