From ef555490e222474a48fa470f30a1e600816c465f Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 18:14:07 +0100 Subject: StatsD integration --- Pipfile | 3 ++- Pipfile.lock | 59 ++++++++++++++++++++-------------------- bot/__main__.py | 1 + bot/bot.py | 14 ++++++++-- bot/cogs/antispam.py | 1 + bot/cogs/defcon.py | 1 + bot/cogs/error_handler.py | 2 ++ bot/cogs/filtering.py | 2 ++ bot/cogs/help_channels.py | 21 +++++++++++++-- bot/cogs/stats.py | 65 +++++++++++++++++++++++++++++++++++++++++++++ bot/cogs/tags.py | 3 +++ bot/cogs/token_remover.py | 2 ++ bot/cogs/webhook_remover.py | 2 ++ bot/constants.py | 1 + config-default.yml | 2 ++ 15 files changed, 145 insertions(+), 34 deletions(-) create mode 100644 bot/cogs/stats.py diff --git a/Pipfile b/Pipfile index 04cc98427..e7fb61957 100644 --- a/Pipfile +++ b/Pipfile @@ -19,7 +19,8 @@ requests = "~=2.22" more_itertools = "~=8.2" sentry-sdk = "~=0.14" coloredlogs = "~=14.0" -colorama = {version = "~=0.4.3", sys_platform = "== 'win32'"} +colorama = {version = "~=0.4.3",sys_platform = "== 'win32'"} +statsd = "~=3.3" [dev-packages] coverage = "~=5.0" diff --git a/Pipfile.lock b/Pipfile.lock index ad9a3173a..19e03bda4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2d3ba484e8467a115126b2ba39fa5f36f103ea455477813dd658797875c79cc9" + "sha256": "10636aef5a07f17bd00608df2cc5214fcbfe3de4745cdeea7a076b871754620a" }, "pipfile-spec": 6, "requires": { @@ -87,18 +87,18 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:05fd825eb01c290877657a56df4c6e4c311b3965bda790c613a3d6fb01a5462a", - "sha256:9fbb4d6e48ecd30bcacc5b63b94088192dcda178513b2ae3c394229f8911b887", - "sha256:e1505eeed31b0f4ce2dbb3bc8eb256c04cc2b3b72af7d551a4ab6efd5cbe5dae" + "sha256:594ca51a10d2b3443cbac41214e12dbb2a1cd57e1a7344659849e2e20ba6a8d8", + "sha256:a4bbe77fd30670455c5296242967a123ec28c37e9702a8a81bd2f20a4baf0368", + "sha256:d4e96ac9b0c3a6d3f0caae2e4124e6055c5dcafde8e2f831ff194c104f0775a0" ], - "version": "==4.8.2" + "version": "==4.9.0" }, "certifi": { "hashes": [ - "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", - "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", + "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" ], - "version": "==2019.11.28" + "version": "==2020.4.5.1" }, "cffi": { "hashes": [ @@ -167,10 +167,10 @@ }, "discord-py": { "hashes": [ - "sha256:7424be26b07b37ecad4404d9383d685995a0e0b3df3f9c645bdd3a4d977b83b4" + "sha256:406871b06d86c3dc49fba63238519f28628dac946fef8a0e22988ff58ec05580" ], "index": "pypi", - "version": "==1.3.2" + "version": "==1.3.3" }, "docutils": { "hashes": [ @@ -393,17 +393,10 @@ }, "pyparsing": { "hashes": [ - "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", - "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], - "version": "==2.4.6" - }, - "pyreadline": { - "hashes": [ - "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1" - ], - "markers": "sys_platform == 'win32'", - "version": "==2.1" + "version": "==2.4.7" }, "python-dateutil": { "hashes": [ @@ -524,6 +517,14 @@ ], "version": "==1.1.4" }, + "statsd": { + "hashes": [ + "sha256:c610fb80347fca0ef62666d241bce64184bd7cc1efe582f9690e045c25535eaa", + "sha256:e3e6db4c246f7c59003e51c9720a51a7f39a396541cb9b147ff4b14d15b5dd1f" + ], + "index": "pypi", + "version": "==3.3.0" + }, "urllib3": { "hashes": [ "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", @@ -717,11 +718,11 @@ }, "flake8-tidy-imports": { "hashes": [ - "sha256:5b6e75cec6d751e66534c522fbdce7dac1c2738b1216b0f6b10453995932e188", - "sha256:cf26fbb3ab31a398f265d53b6f711d80006450c19221e41b2b7b0e0b14ac39c5" + "sha256:62059ca07d8a4926b561d392cbab7f09ee042350214a25cf12823384a45d27dd", + "sha256:c30b40337a2e6802ba3bb611c26611154a27e94c53fc45639e3e282169574fd3" ], "index": "pypi", - "version": "==4.0.1" + "version": "==4.1.0" }, "flake8-todo": { "hashes": [ @@ -732,10 +733,10 @@ }, "identify": { "hashes": [ - "sha256:a7577a1f55cee1d21953a5cf11a3c839ab87f5ef909a4cba6cf52ed72b4c6059", - "sha256:ab246293e6585a1c6361a505b68d5b501a0409310932b7de2c2ead667b564d89" + "sha256:2bb8760d97d8df4408f4e805883dad26a2d076f04be92a10a3e43f09c6060742", + "sha256:faffea0fd8ec86bb146ac538ac350ed0c73908326426d387eded0bcc9d077522" ], - "version": "==1.4.13" + "version": "==1.4.14" }, "mccabe": { "hashes": [ @@ -835,10 +836,10 @@ }, "virtualenv": { "hashes": [ - "sha256:87831f1070534b636fea2241dd66f3afe37ac9041bcca6d0af3215cdcfbf7d82", - "sha256:f3128d882383c503003130389bf892856341c1da12c881ae24d6358c82561b55" + "sha256:00cfe8605fb97f5a59d52baab78e6070e72c12ca64f51151695407cc0eb8a431", + "sha256:c8364ec469084046c779c9a11ae6340094e8a0bf1d844330fc55c1cefe67c172" ], - "version": "==20.0.13" + "version": "==20.0.17" } } } diff --git a/bot/__main__.py b/bot/__main__.py index bf98f2cfd..2125e8590 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -57,6 +57,7 @@ bot.load_extension("bot.cogs.reminders") bot.load_extension("bot.cogs.site") bot.load_extension("bot.cogs.snekbox") bot.load_extension("bot.cogs.sync") +bot.load_extension("bot.cogs.stats") bot.load_extension("bot.cogs.tags") bot.load_extension("bot.cogs.token_remover") bot.load_extension("bot.cogs.utils") diff --git a/bot/bot.py b/bot/bot.py index 950ac6751..65081e438 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -6,10 +6,10 @@ from typing import Optional import aiohttp import discord +import statsd from discord.ext import commands -from bot import api -from bot import constants +from bot import DEBUG_MODE, api, constants log = logging.getLogger('bot') @@ -33,6 +33,16 @@ class Bot(commands.Bot): self._resolver = None self._guild_available = asyncio.Event() + statsd_url = constants.Bot.statsd_host + + if DEBUG_MODE: + # Since statsd is UDP, there are no errors for sending to a down port. + # For this reason, setting the statsd host to 127.0.0.1 for development + # will effectively disable stats. + statsd_url = "127.0.0.1" + + self.stats = statsd.StatsClient(statsd_url, 8125, prefix="bot") + def add_cog(self, cog: commands.Cog) -> None: """Adds a "cog" to the bot and logs the operation.""" super().add_cog(cog) diff --git a/bot/cogs/antispam.py b/bot/cogs/antispam.py index baa6b9459..d63acbc4a 100644 --- a/bot/cogs/antispam.py +++ b/bot/cogs/antispam.py @@ -182,6 +182,7 @@ class AntiSpam(Cog): # which contains the reason for why the message violated the rule and # an iterable of all members that violated the rule. if result is not None: + self.bot.stats.incr(f"mod_alerts.{rule_name}") reason, members, relevant_messages = result full_reason = f"`{rule_name}` rule: {reason}" diff --git a/bot/cogs/defcon.py b/bot/cogs/defcon.py index cc0f79fe8..80dc6082f 100644 --- a/bot/cogs/defcon.py +++ b/bot/cogs/defcon.py @@ -104,6 +104,7 @@ class Defcon(Cog): log.exception(f"Unable to send rejection message to user: {member}") await member.kick(reason="DEFCON active, user is too new") + self.bot.stats.incr("defcon_leaves") message = ( f"{member} (`{member.id}`) was denied entry because their account is too new." diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 6a622d2ce..747ab4a6e 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -236,6 +236,8 @@ class ErrorHandler(Cog): f"```{e.__class__.__name__}: {e}```" ) + ctx.bot.stats.incr("command_error_count") + with push_scope() as scope: scope.user = { "id": ctx.author.id, diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index 3f3dbb853..fa4420be1 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -207,6 +207,8 @@ class Filtering(Cog): log.debug(message) + self.bot.stats.incr(f"bot.filters.{filter_name}") + additional_embeds = None additional_embeds_msg = None diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 697a4d3b7..389a4ad2a 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -367,6 +367,18 @@ class HelpChannels(Scheduler, commands.Cog): log.info("Cog is ready!") self.ready.set() + self.report_stats() + + def report_stats(self) -> None: + """Report the channel count stats.""" + total_in_use = len(list(self.get_category_channels(self.in_use_category))) + total_available = len(list(self.get_category_channels(self.available_category))) + total_dormant = len(list(self.get_category_channels(self.dormant_category))) + + self.bot.stats.gauge("help.total.in_use", total_in_use) + self.bot.stats.gauge("help.total.available", total_available) + self.bot.stats.gauge("help.total.dormant", total_dormant) + @staticmethod def is_dormant_message(message: t.Optional[discord.Message]) -> bool: """Return True if the contents of the `message` match `DORMANT_MSG`.""" @@ -432,6 +444,7 @@ class HelpChannels(Scheduler, commands.Cog): f"synchronized permissions after moving `{channel}` into it." ) await self.ensure_permissions_synchronization(self.available_category) + self.report_stats() async def move_to_dormant(self, channel: discord.TextChannel) -> None: """Make the `channel` dormant.""" @@ -442,7 +455,6 @@ class HelpChannels(Scheduler, commands.Cog): category=self.dormant_category, sync_permissions=True, topic=DORMANT_TOPIC, - position=10000, ) log.trace(f"Position of #{channel} ({channel.id}) is actually {channel.position}.") @@ -453,6 +465,7 @@ class HelpChannels(Scheduler, commands.Cog): log.trace(f"Pushing #{channel} ({channel.id}) into the channel queue.") self.channel_queue.put_nowait(channel) + self.report_stats() async def move_to_in_use(self, channel: discord.TextChannel) -> None: """Make a channel in-use and schedule it to be made dormant.""" @@ -463,7 +476,6 @@ class HelpChannels(Scheduler, commands.Cog): category=self.in_use_category, sync_permissions=True, topic=IN_USE_TOPIC, - position=10000, ) timeout = constants.HelpChannels.idle_minutes * 60 @@ -471,6 +483,7 @@ class HelpChannels(Scheduler, commands.Cog): log.trace(f"Scheduling #{channel} ({channel.id}) to become dormant in {timeout} sec.") data = TaskData(timeout, self.move_idle_channel(channel)) self.schedule_task(channel.id, data) + self.report_stats() async def notify(self) -> None: """ @@ -511,6 +524,8 @@ class HelpChannels(Scheduler, commands.Cog): f"using the `{constants.Bot.prefix}dormant` command within the channels." ) + self.bot.stats.incr("help.out_of_channel_alerts") + self.last_notification = message.created_at except Exception: # Handle it here cause this feature isn't critical for the functionality of the system. @@ -543,6 +558,8 @@ class HelpChannels(Scheduler, commands.Cog): await self.move_to_in_use(channel) await self.revoke_send_permissions(message.author) + self.bot.stats.incr("help.claimed") + log.trace(f"Releasing on_message lock for {message.id}.") # Move a dormant channel to the Available category to fill in the gap. diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py new file mode 100644 index 000000000..b75d29b7e --- /dev/null +++ b/bot/cogs/stats.py @@ -0,0 +1,65 @@ +from discord import Member, Message, Status +from discord.ext.commands import Bot, Cog, Context + + +class Stats(Cog): + """A cog which provides a way to hook onto Discord events and forward to stats.""" + + def __init__(self, bot: Bot): + self.bot = bot + + @Cog.listener() + async def on_message(self, message: Message) -> None: + """Report message events in the server to statsd.""" + if message.guild is None: + return + + reformatted_name = message.channel.name.replace('-', '_') + + if reformatted_name.startswith("ot"): + # Off-topic channels change names, we don't want this for stats. + # This will change 'ot1-lemon-in-the-dishwasher' to just 'ot1' + reformatted_name = reformatted_name[:3] + + stat_name = f"channels.{reformatted_name}" + self.bot.stats.incr(stat_name) + + # Increment the total message count + self.bot.stats.incr("messages") + + @Cog.listener() + async def on_command_completion(self, ctx: Context) -> None: + """Report completed commands to statsd.""" + command_name = ctx.command.qualified_name.replace(" ", "_") + + self.bot.stats.incr(f"commands.{command_name}") + + @Cog.listener() + async def on_member_join(self, member: Member) -> None: + """Update member count stat on member join.""" + self.bot.stats.gauge(f"guild.total_members", len(member.guild.members)) + + @Cog.listener() + async def on_member_leave(self, member: Member) -> None: + """Update member count stat on member leave.""" + self.bot.stats.gauge(f"guild.total_members", len(member.guild.members)) + + @Cog.listener() + async def on_member_update(self, _before: Member, after: Member) -> None: + """Update presence estimates on member update.""" + members = after.guild.members + + online = len([m for m in members if m.status == Status.online]) + idle = len([m for m in members if m.status == Status.idle]) + dnd = len([m for m in members if m.status == Status.do_not_disturb]) + offline = len([m for m in members if m.status == Status.offline]) + + self.bot.stats.gauge("guild.status.online", online) + self.bot.stats.gauge("guild.status.idle", idle) + self.bot.stats.gauge("guild.status.do_not_disturb", dnd) + self.bot.stats.gauge("guild.status.offline", offline) + + +def setup(bot: Bot) -> None: + """Load the stats cog.""" + bot.add_cog(Stats(bot)) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index a6e5952ff..b81859db1 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -207,6 +207,9 @@ class Tags(Cog): "time": time.time(), "channel": ctx.channel.id } + + self.bot.stats.incr(f"tags.usages.{tag_name.replace('-', '_')}") + await wait_for_deletion( await ctx.send(embed=Embed.from_dict(tag['embed'])), [ctx.author.id], diff --git a/bot/cogs/token_remover.py b/bot/cogs/token_remover.py index 421ad23e2..6721f0e02 100644 --- a/bot/cogs/token_remover.py +++ b/bot/cogs/token_remover.py @@ -93,6 +93,8 @@ class TokenRemover(Cog): channel_id=Channels.mod_alerts, ) + self.bot.stats.incr("tokens.removed_tokens") + @classmethod def find_token_in_message(cls, msg: Message) -> t.Optional[str]: """Return a seemingly valid token found in `msg` or `None` if no token is found.""" diff --git a/bot/cogs/webhook_remover.py b/bot/cogs/webhook_remover.py index 49692113d..1b5c3f821 100644 --- a/bot/cogs/webhook_remover.py +++ b/bot/cogs/webhook_remover.py @@ -54,6 +54,8 @@ class WebhookRemover(Cog): channel_id=Channels.mod_alerts ) + self.bot.stats.incr("tokens.removed_webhooks") + @Cog.listener() async def on_message(self, msg: Message) -> None: """Check if a Discord webhook URL is in `message`.""" diff --git a/bot/constants.py b/bot/constants.py index 60e3c4897..33c1d530d 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -199,6 +199,7 @@ class Bot(metaclass=YAMLGetter): prefix: str token: str sentry_dsn: str + statsd_host: str class Filter(metaclass=YAMLGetter): section = "filter" diff --git a/config-default.yml b/config-default.yml index 896003973..567caacbf 100644 --- a/config-default.yml +++ b/config-default.yml @@ -3,6 +3,8 @@ bot: token: !ENV "BOT_TOKEN" sentry_dsn: !ENV "BOT_SENTRY_DSN" + statsd_host: "graphite" + cooldowns: # Per channel, per tag. tags: 60 -- cgit v1.2.3 From bc17ec3f60b061ce93f627c1f69182f655d4fc37 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 19:18:31 +0100 Subject: Address review comments from Mark --- bot.svg | 3795 +++++++++++++++++++++++++++++++++++++++++++++ bot/__main__.py | 4 +- bot/cogs/defcon.py | 2 +- bot/cogs/error_handler.py | 2 +- bot/cogs/filtering.py | 2 +- bot/cogs/stats.py | 46 +- 6 files changed, 3837 insertions(+), 14 deletions(-) create mode 100644 bot.svg diff --git a/bot.svg b/bot.svg new file mode 100644 index 000000000..97a3914d4 --- /dev/null +++ b/bot.svg @@ -0,0 +1,3795 @@ + + + + + + +G + + + +bot_cogs_clean + +bot.cogs.clean + + + +requests + +requests + + + +discord_Webhook + +discord. +Webhook + + + +requests->discord_Webhook + + + + + +bot_cogs_doc + +bot.cogs.doc + + + +requests->bot_cogs_doc + + + + + +bot_bot + +bot.bot + + + +bot_bot->bot_cogs_clean + + + + + +bot_cogs_moderation_management + +bot. +cogs. +moderation. +management + + + +bot_bot->bot_cogs_moderation_management + + + + + +bot_cogs_webhook_remover + +bot. +cogs. +webhook_remover + + + +bot_bot->bot_cogs_webhook_remover + + + + + + + +bot_cogs_verification + +bot. +cogs. +verification + + + +bot_bot->bot_cogs_verification + + + + + +bot_cogs_wolfram + +bot. +cogs. +wolfram + + + +bot_bot->bot_cogs_wolfram + + + + + + +bot_cogs_site + +bot.cogs.site + + + +bot_bot->bot_cogs_site + + + + + +bot_cogs_watchchannels_watchchannel + +bot. +cogs. +watchchannels. +watchchannel + + + +bot_bot->bot_cogs_watchchannels_watchchannel + + + + + + +bot_cogs_extensions + +bot. +cogs. +extensions + + + +bot_bot->bot_cogs_extensions + + + + + +bot_cogs_antimalware + +bot. +cogs. +antimalware + + + +bot_bot->bot_cogs_antimalware + + + + + +bot___main__ + +bot.__main__ + + + +bot_bot->bot___main__ + + + + + +bot_cogs_moderation + +bot. +cogs. +moderation + + + +bot_bot->bot_cogs_moderation + + + + + +bot_cogs_duck_pond + +bot. +cogs. +duck_pond + + + +bot_bot->bot_cogs_duck_pond + + + + + + +bot_cogs_antispam + +bot. +cogs. +antispam + + + +bot_bot->bot_cogs_antispam + + + + + +bot_interpreter + +bot. +interpreter + + + +bot_bot->bot_interpreter + + + + + +bot_cogs_moderation_superstarify + +bot. +cogs. +moderation. +superstarify + + + +bot_bot->bot_cogs_moderation_superstarify + + + + +bot_cogs_defcon + +bot. +cogs. +defcon + + + +bot_bot->bot_cogs_defcon + + + + + + +bot_cogs_moderation_ModLog + +bot. +cogs. +moderation. +ModLog + + + +bot_bot->bot_cogs_moderation_ModLog + + + + + +bot_cogs_watchchannels_talentpool + +bot. +cogs. +watchchannels. +talentpool + + + +bot_bot->bot_cogs_watchchannels_talentpool + + + + +bot_cogs_information + +bot. +cogs. +information + + + +bot_bot->bot_cogs_information + + + + + +bot_cogs_off_topic_names + +bot. +cogs. +off_topic_names + + + +bot_bot->bot_cogs_off_topic_names + + + + + + +bot_cogs_alias + +bot.cogs.alias + + + +bot_bot->bot_cogs_alias + + + + + + +bot_cogs_moderation_silence + +bot. +cogs. +moderation. +silence + + + +bot_bot->bot_cogs_moderation_silence + + + + + +bot_cogs_sync_syncers + +bot. +cogs. +sync. +syncers + + + +bot_bot->bot_cogs_sync_syncers + + + + + + +bot_cogs_moderation_scheduler + +bot. +cogs. +moderation. +scheduler + + + +bot_bot->bot_cogs_moderation_scheduler + + + + + + +bot_cogs_eval + +bot.cogs.eval + + + +bot_bot->bot_cogs_eval + + + + + +bot_cogs_help_channels + +bot. +cogs. +help_channels + + + +bot_bot->bot_cogs_help_channels + + + + + +bot_cogs_tags + +bot.cogs.tags + + + +bot_bot->bot_cogs_tags + + + + + + +bot_cogs_reddit + +bot. +cogs. +reddit + + + +bot_bot->bot_cogs_reddit + + + + + + +bot_cogs_utils + +bot.cogs.utils + + + +bot_bot->bot_cogs_utils + + + + + +bot_cogs_sync + +bot.cogs.sync + + + +bot_bot->bot_cogs_sync + + + + + +bot_cogs_help + +bot.cogs.help + + + +bot_bot->bot_cogs_help + + + + + +bot_cogs_bot + +bot.cogs.bot + + + +bot_bot->bot_cogs_bot + + + + + + + + +bot_cogs_watchchannels_bigbrother + +bot. +cogs. +watchchannels. +bigbrother + + + +bot_bot->bot_cogs_watchchannels_bigbrother + + + + +bot_cogs_logging + +bot. +cogs. +logging + + + +bot_bot->bot_cogs_logging + + + + + + +bot_cogs_config_verifier + +bot. +cogs. +config_verifier + + + +bot_bot->bot_cogs_config_verifier + + + + + + +bot_cogs_moderation_modlog + +bot. +cogs. +moderation. +modlog + + + +bot_bot->bot_cogs_moderation_modlog + + + + + + +bot_cogs_sync_cog + +bot. +cogs. +sync. +cog + + + +bot_bot->bot_cogs_sync_cog + + + + + + +bot_cogs_snekbox + +bot. +cogs. +snekbox + + + +bot_bot->bot_cogs_snekbox + + + + + +bot_cogs_moderation_infractions + +bot. +cogs. +moderation. +infractions + + + +bot_bot->bot_cogs_moderation_infractions + + + + + +bot_cogs_watchchannels + +bot. +cogs. +watchchannels + + + +bot_bot->bot_cogs_watchchannels + + + + + +bot_bot->bot_cogs_doc + + + + + +bot_cogs_security + +bot. +cogs. +security + + + +bot_bot->bot_cogs_security + + + + + +bot_cogs_reminders + +bot. +cogs. +reminders + + + +bot_bot->bot_cogs_reminders + + + + + +bot_cogs_token_remover + +bot. +cogs. +token_remover + + + +bot_bot->bot_cogs_token_remover + + + + + + +bot_cogs_filtering + +bot. +cogs. +filtering + + + +bot_bot->bot_cogs_filtering + + + + + +bot_cogs_jams + +bot.cogs.jams + + + +bot_bot->bot_cogs_jams + + + + + +bot_cogs_error_handler + +bot. +cogs. +error_handler + + + +bot_bot->bot_cogs_error_handler + + + + + +bot_rules_attachments + +bot. +rules. +attachments + + + +bot_rules + +bot.rules + + + +bot_rules_attachments->bot_rules + + + + + +bot_cogs_stats + +bot.cogs.stats + + + +bot_api + +bot.api + + + +bot_api->bot_bot + + + + + +bot_api->bot_cogs_watchchannels_watchchannel + + + + +bot_cogs_moderation_utils + +bot. +cogs. +moderation. +utils + + + +bot_api->bot_cogs_moderation_utils + + + + + +bot_api->bot_cogs_watchchannels_talentpool + + + + +bot_api->bot_cogs_off_topic_names + + + + + +bot_api->bot_cogs_sync_syncers + + + + + +bot_api->bot_cogs_moderation_scheduler + + + + +bot_api->bot_cogs_sync_cog + + + + + +bot_api->bot_cogs_error_handler + + + + + + + +bot_cogs_moderation_management->bot_cogs_moderation + + + + + +urllib3_exceptions + +urllib3. +exceptions + + + +urllib3_exceptions->requests + + + + + +urllib3 + +urllib3 + + + +urllib3_exceptions->urllib3 + + + + + +urllib3_exceptions->bot_cogs_doc + + + + + +dateutil_parser + +dateutil. +parser + + + +bot_converters + +bot.converters + + + +dateutil_parser->bot_converters + + + + + +dateutil_parser->bot_cogs_watchchannels_watchchannel + + + + + + +bot_utils_time + +bot.utils.time + + + +dateutil_parser->bot_utils_time + + + + + +dateutil_parser->bot_cogs_moderation_scheduler + + + + + + +dateutil_parser->bot_cogs_reminders + + + + +dateutil_relativedelta + +dateutil. +relativedelta + + + +dateutil_relativedelta->bot_cogs_wolfram + + + + + + +dateutil_relativedelta->bot_converters + + + + + + +dateutil_relativedelta->bot_cogs_moderation_ModLog + + + + + + +dateutil_relativedelta->bot_utils_time + + + + + +dateutil_relativedelta->bot_cogs_utils + + + + + +dateutil_relativedelta->bot_cogs_moderation_modlog + + + + + +dateutil_relativedelta->bot_cogs_reminders + + + + +dateutil_relativedelta->bot_cogs_filtering + + + + + + +bot_rules_chars + +bot. +rules. +chars + + + +bot_rules_chars->bot_rules + + + + + +discord_Guild + +discord.Guild + + + +discord_Guild->bot_cogs_sync_syncers + + + + + +bot_converters->bot_cogs_moderation_management + + + + +bot_converters->bot_cogs_antispam + + + + + +bot_converters->bot_cogs_moderation_superstarify + + + + +bot_converters->bot_cogs_watchchannels_talentpool + + + + + + +bot_converters->bot_cogs_alias + + + + + +bot_converters->bot_cogs_moderation_silence + + + + +bot_converters->bot_cogs_tags + + + + + +bot_converters->bot_cogs_reddit + + + + + +bot_converters->bot_cogs_watchchannels_bigbrother + + + + +bot_converters->bot_cogs_moderation_infractions + + + + + +bot_converters->bot_cogs_doc + + + + + +bot_converters->bot_cogs_reminders + + + + +bot_converters->bot_cogs_error_handler + + + + + +bs4 + +bs4 + + + +bs4->bot_cogs_doc + + + + + +discord_Client + +discord.Client + + + +bot_utils_messages + +bot. +utils. +messages + + + +discord_Client->bot_utils_messages + + + + +bot_rules_burst_shared + +bot. +rules. +burst_shared + + + +bot_rules_burst_shared->bot_rules + + + + + +bot_cogs_watchchannels_watchchannel->bot_cogs_watchchannels_talentpool + + + + + +bot_cogs_watchchannels_watchchannel->bot_cogs_watchchannels_bigbrother + + + + + +aiohttp + +aiohttp + + + +aiohttp->bot_bot + + + + + +aiohttp->bot_api + + + + + + +aiohttp->bot_converters + + + + + +aiohttp->discord_Client + + + + + + +aiohttp->discord_Webhook + + + + + +aiohttp->bot_cogs_reddit + + + + + +bot_cogs_extensions->bot_cogs_alias + + + + + +discord_User + +discord.User + + + +discord_User->bot_cogs_clean + + + + + + +discord_User->bot_cogs_duck_pond + + + + + + + +discord_User->bot_cogs_sync_syncers + + + + + +discord_User->bot_cogs_help + + + + + +discord_User->bot_cogs_sync_cog + + + + + +discord_User->bot_cogs_snekbox + + + + + +bot_rules->bot_cogs_antispam + + + + + +bot_cogs_moderation->bot_cogs_clean + + + + + +bot_cogs_moderation->bot_cogs_webhook_remover + + + + + +bot_cogs_moderation->bot_cogs_verification + + + + + +bot_cogs_moderation->bot_cogs_watchchannels_watchchannel + + + + + +bot_cogs_moderation->bot_cogs_antispam + + + + + +bot_cogs_moderation->bot_cogs_defcon + + + + + +bot_cogs_moderation->bot_cogs_watchchannels_bigbrother + + + + +bot_cogs_moderation->bot_cogs_token_remover + + + + + +bot_cogs_moderation->bot_cogs_filtering + + + + + +discord + +discord + + + +discord->bot_cogs_clean + + + + + +discord->bot_bot + + + + + +discord->bot_rules_attachments + + + + + +discord->bot_cogs_stats + + + + + +discord->bot_cogs_moderation_management + + + + + +discord->bot_cogs_webhook_remover + + + + +discord->bot_cogs_verification + + + + + + +discord->bot_cogs_wolfram + + + + + + + +discord->bot_rules_chars + + + + + +discord->bot_converters + + + + + +discord->bot_cogs_site + + + + + + +discord->bot_rules_burst_shared + + + + + +discord->bot_cogs_watchchannels_watchchannel + + + + + +discord->bot_cogs_extensions + + + + + +discord->bot_cogs_antimalware + + + + + +discord->bot___main__ + + + + + + +discord->bot_cogs_duck_pond + + + + + +discord->bot_cogs_antispam + + + + +discord->bot_interpreter + + + + + +discord->bot_cogs_moderation_superstarify + + + + + +discord->bot_cogs_defcon + + + + + + +bot_pagination + +bot.pagination + + + +discord->bot_pagination + + + + + +discord->bot_cogs_moderation_ModLog + + + + + + +discord->bot_cogs_moderation_utils + + + + + + +bot_rules_newlines + +bot. +rules. +newlines + + + +discord->bot_rules_newlines + + + + + + +discord->bot_cogs_watchchannels_talentpool + + + + + +discord->bot_cogs_information + + + + + +discord->bot_cogs_off_topic_names + + + + + +discord->bot_cogs_alias + + + + + +discord->bot_cogs_moderation_silence + + + + + + +discord->bot_cogs_sync_syncers + + + + + + +discord->bot_cogs_moderation_scheduler + + + + + + +discord->bot_cogs_eval + + + + + + +bot_rules_burst + +bot. +rules. +burst + + + +discord->bot_rules_burst + + + + + +discord->bot_cogs_help_channels + + + + + + +discord->bot_cogs_tags + + + + + +discord->bot_cogs_reddit + + + + + + +discord->bot_cogs_utils + + + + + +bot_rules_discord_emojis + +bot. +rules. +discord_emojis + + + +discord->bot_rules_discord_emojis + + + + + +bot_rules_duplicates + +bot. +rules. +duplicates + + + +discord->bot_rules_duplicates + + + + + +discord->bot_cogs_help + + + + + +discord->bot_cogs_bot + + + + + + + +discord->bot_cogs_logging + + + + + + +bot_rules_mentions + +bot. +rules. +mentions + + + +discord->bot_rules_mentions + + + + + +bot_decorators + +bot.decorators + + + +discord->bot_decorators + + + + + +discord->bot_cogs_moderation_modlog + + + + + +discord->bot_cogs_sync_cog + + + + + +discord->bot_cogs_snekbox + + + + + +discord->bot_cogs_moderation_infractions + + + + + + +bot_rules_links + +bot. +rules. +links + + + +discord->bot_rules_links + + + + + + +discord->bot_cogs_doc + + + + + +discord->bot_utils_messages + + + + + +bot_patches_message_edited_at + +bot. +patches. +message_edited_at + + + +discord->bot_patches_message_edited_at + + + + + + + +discord->bot_cogs_reminders + + + + + +bot_rules_role_mentions + +bot. +rules. +role_mentions + + + +discord->bot_rules_role_mentions + + + + + +discord->bot_cogs_token_remover + + + + + +discord->bot_cogs_filtering + + + + + +discord->bot_cogs_jams + + + + + +bot_constants + +bot.constants + + + +bot_constants->bot_cogs_clean + + + + + +bot_constants->bot_bot + + + + + +bot_constants->bot_api + + + + + +bot_constants->bot_cogs_moderation_management + + + + + +bot_constants->bot_cogs_webhook_remover + + + + +bot_constants->bot_cogs_verification + + + + + +bot_constants->bot_cogs_wolfram + + + + +bot_constants->bot_cogs_site + + + + + + +bot_constants->bot_cogs_watchchannels_watchchannel + + + + + +bot_constants->bot_cogs_extensions + + + + + +bot_constants->bot_cogs_antimalware + + + + + +bot_constants->bot___main__ + + + + + +bot_constants->bot_cogs_duck_pond + + + + + + +bot_constants->bot_cogs_antispam + + + + + +bot_constants->bot_cogs_moderation_superstarify + + + + +bot_constants->bot_cogs_defcon + + + + + +bot_constants->bot_pagination + + + + + + +bot_constants->bot_cogs_moderation_ModLog + + + + + + +bot_constants->bot_cogs_moderation_utils + + + + + +bot_constants->bot_cogs_watchchannels_talentpool + + + + + + +bot_constants->bot_cogs_information + + + + + + +bot_constants->bot_cogs_off_topic_names + + + + + +bot_constants->bot_cogs_moderation_silence + + + + + + +bot_constants->bot_cogs_sync_syncers + + + + + +bot_constants->bot_cogs_moderation_scheduler + + + + + + +bot_constants->bot_cogs_eval + + + + + +bot_constants->bot_cogs_help_channels + + + + + +bot_constants->bot_cogs_tags + + + + + + +bot_constants->bot_cogs_reddit + + + + +bot_constants->bot_cogs_utils + + + + + +bot_constants->bot_cogs_help + + + + + + + +bot_constants->bot_cogs_bot + + + + + +bot_constants->bot_cogs_watchchannels_bigbrother + + + + + + +bot_constants->bot_cogs_logging + + + + + + +bot_constants->bot_cogs_config_verifier + + + + + +bot_constants->bot_decorators + + + + +bot_constants->bot_cogs_moderation_modlog + + + + + + +bot_constants->bot_cogs_sync_cog + + + + + + +bot_constants->bot_cogs_snekbox + + + + + + +bot_constants->bot_cogs_moderation_infractions + + + + + + +bot_constants->bot_cogs_doc + + + + + +bot_constants->bot_utils_messages + + + + + + +bot_constants->bot_cogs_reminders + + + + +bot_constants->bot_cogs_token_remover + + + + + +bot_constants->bot_cogs_filtering + + + + + + + + +bot_constants->bot_cogs_jams + + + + + +bot_constants->bot_cogs_error_handler + + + + +discord_File + +discord.File + + + +discord_File->bot_utils_messages + + + + +discord_Reaction + +discord. +Reaction + + + +discord_Reaction->bot_cogs_sync_syncers + + + + + +discord_Reaction->bot_cogs_help + + + + + +discord_Reaction->bot_cogs_snekbox + + + + + +discord_Reaction->bot_utils_messages + + + + + +bot_interpreter->bot_cogs_eval + + + + + + +bot_cogs_moderation_superstarify->bot_cogs_moderation + + + + + + +more_itertools + +more_itertools + + + +more_itertools->bot_cogs_jams + + + + + +statsd + +statsd + + + +statsd->bot_bot + + + + + +bot_pagination->bot_cogs_moderation_management + + + + + + + +bot_pagination->bot_cogs_wolfram + + + + + +bot_pagination->bot_cogs_site + + + + + +bot_pagination->bot_cogs_watchchannels_watchchannel + + + + + +bot_pagination->bot_cogs_extensions + + + + + +bot_pagination->bot_cogs_watchchannels_talentpool + + + + + +bot_pagination->bot_cogs_information + + + + + +bot_pagination->bot_cogs_off_topic_names + + + + + + +bot_pagination->bot_cogs_alias + + + + + +bot_pagination->bot_cogs_tags + + + + + +bot_pagination->bot_cogs_reddit + + + + + + +bot_pagination->bot_cogs_help + + + + + +bot_pagination->bot_cogs_doc + + + + + +bot_pagination->bot_cogs_reminders + + + + + +bot_utils_checks + +bot. +utils. +checks + + + +bot_utils_checks->bot_cogs_moderation_management + + + + + +bot_utils_checks->bot_cogs_verification + + + + + +bot_utils_checks->bot_cogs_extensions + + + + + + +bot_utils_checks->bot_cogs_moderation_superstarify + + + + + +bot_utils_checks->bot_cogs_information + + + + + +bot_utils_checks->bot_cogs_moderation_silence + + + + + + +bot_utils_checks->bot_decorators + + + + + +bot_utils_checks->bot_cogs_moderation_infractions + + + + + + +bot_utils_checks->bot_cogs_reminders + + + + +bot_cogs_moderation_ModLog->bot_cogs_clean + + + + + + +bot_cogs_moderation_ModLog->bot_cogs_verification + + + + + +bot_cogs_moderation_ModLog->bot_cogs_watchchannels_watchchannel + + + + + +bot_cogs_moderation_ModLog->bot_cogs_antispam + + + + + +bot_cogs_moderation_ModLog->bot_cogs_defcon + + + + + + +bot_cogs_moderation_ModLog->bot_cogs_token_remover + + + + + + + +bot_cogs_moderation_ModLog->bot_cogs_filtering + + + + + + + +discord_Object + +discord.Object + + + +discord_Object->bot_cogs_verification + + + + + +discord_Object->bot_cogs_antispam + + + + + + +bot_cogs_moderation_utils->bot_cogs_moderation_management + + + + + +bot_cogs_moderation_utils->bot_cogs_moderation_superstarify + + + + + + +bot_cogs_moderation_utils->bot_cogs_moderation_scheduler + + + + + +bot_cogs_moderation_utils->bot_cogs_watchchannels_bigbrother + + + + + + + +bot_cogs_moderation_utils->bot_cogs_moderation_infractions + + + + + +discord_Webhook->bot_utils_messages + + + + + + + +bot_rules_newlines->bot_rules + + + + + +bot_cogs_watchchannels_talentpool->bot_cogs_watchchannels + + + + + +discord_utils + +discord.utils + + + +discord_utils->discord_Guild + + + + + +discord_utils->discord_Client + + + + +discord_utils->discord_User + + + + + +discord_utils->discord + + + + + +discord_utils->bot_cogs_moderation_ModLog + + + + + + +discord_utils->discord_Object + + + + + +discord_utils->discord_Webhook + + + + + +discord_utils->bot_cogs_information + + + + + + +discord_Message + +discord. +Message + + + +discord_utils->discord_Message + + + + + +discord_abc + +discord.abc + + + +discord_utils->discord_abc + + + + + +discord_message + +discord. +message + + + +discord_utils->discord_message + + + + + +discord_Role + +discord.Role + + + +discord_utils->discord_Role + + + + + +discord_Member + +discord.Member + + + +discord_utils->discord_Member + + + + + + +discord_utils->bot_cogs_moderation_modlog + + + + + +discord_utils->bot_patches_message_edited_at + + + + + +discord_utils->bot_cogs_token_remover + + + + + +discord_utils->bot_cogs_filtering + + + + + + +discord_utils->bot_cogs_jams + + + + + +bot_cogs_moderation_silence->bot_cogs_moderation + + + + + +bot_utils_time->bot_cogs_moderation_management + + + + + + +bot_utils_time->bot_cogs_wolfram + + + + + +bot_utils_time->bot_cogs_watchchannels_watchchannel + + + + + +bot_utils_time->bot_cogs_moderation_superstarify + + + + + +bot_utils_time->bot_cogs_moderation_ModLog + + + + + +bot_utils_time->bot_cogs_watchchannels_talentpool + + + + +bot_utils_time->bot_cogs_information + + + + + + +bot_utils_time->bot_cogs_moderation_scheduler + + + + + +bot_utils_time->bot_cogs_utils + + + + + +bot_utils_time->bot_cogs_moderation_modlog + + + + + + + +bot_utils_time->bot_cogs_reminders + + + + + +discord_Message->bot_cogs_clean + + + + + +discord_Message->bot_rules_attachments + + + + + +discord_Message->bot_cogs_stats + + + + + +discord_Message->bot_cogs_webhook_remover + + + + + + + +discord_Message->bot_cogs_verification + + + + + +discord_Message->bot_rules_chars + + + + + + +discord_Message->bot_rules_burst_shared + + + + + +discord_Message->bot_cogs_watchchannels_watchchannel + + + + + + +discord_Message->bot_cogs_antimalware + + + + + +discord_Message->bot_cogs_duck_pond + + + + + +discord_Message->bot_cogs_antispam + + + + + +discord_Message->bot_rules_newlines + + + + + + +discord_Message->bot_cogs_information + + + + + +discord_Message->bot_cogs_sync_syncers + + + + + +discord_Message->bot_rules_burst + + + + + + + +discord_Message->bot_cogs_utils + + + + + +discord_Message->bot_rules_discord_emojis + + + + + + +discord_Message->bot_rules_duplicates + + + + + + +discord_Message->bot_cogs_help + + + + + + + + +discord_Message->bot_cogs_bot + + + + + + +discord_Message->bot_rules_mentions + + + + + + +discord_Message->bot_cogs_snekbox + + + + + + + +discord_Message->bot_rules_links + + + + + + +discord_Message->bot_utils_messages + + + + + +discord_Message->bot_rules_role_mentions + + + + + +discord_Message->bot_cogs_token_remover + + + + + + +discord_Message->bot_cogs_filtering + + + + + + + +bot_cogs_sync_syncers->bot_cogs_sync_cog + + + + + +dateutil + +dateutil + + + +dateutil->bot_cogs_wolfram + + + + + +dateutil->bot_converters + + + + + + + +dateutil->bot_cogs_watchchannels_watchchannel + + + + +dateutil->bot_cogs_moderation_ModLog + + + + + +dateutil->bot_utils_time + + + + + +dateutil->bot_cogs_moderation_scheduler + + + + + +dateutil->bot_cogs_utils + + + + + +dateutil->bot_cogs_moderation_modlog + + + + + +dateutil->bot_cogs_reminders + + + + +dateutil->bot_cogs_filtering + + + + + +bot_cogs_moderation_scheduler->bot_cogs_moderation_superstarify + + + + + +bot_cogs_moderation_scheduler->bot_cogs_moderation_infractions + + + + + +bot_rules_burst->bot_rules + + + + + +discord_abc->discord_User + + + + + +discord_abc->discord + + + + + +discord_abc->bot_pagination + + + + + +discord_abc->bot_cogs_moderation_ModLog + + + + + +discord_abc->discord_Member + + + + + +discord_abc->bot_cogs_moderation_modlog + + + + + +discord_abc->bot_utils_messages + + + + +discord_message->discord + + + + + +discord_message->discord_Webhook + + + + + +discord_message->bot_patches_message_edited_at + + + + + + +bot_rules_discord_emojis->bot_rules + + + + + +yaml + +yaml + + + +yaml->bot_constants + + + + + +bot_rules_duplicates->bot_rules + + + + + +urllib3->requests + + + + + +urllib3->bot_cogs_doc + + + + + + +discord_Role->bot_cogs_information + + + + + +discord_Role->bot_cogs_utils + + + + + +discord_Role->bot_cogs_sync_cog + + + + + +discord_Colour + +discord.Colour + + + +discord_Colour->bot_cogs_clean + + + + +discord_Colour->bot_cogs_webhook_remover + + + + + +discord_Colour->bot_cogs_verification + + + + + +discord_Colour->bot_cogs_site + + + + + + +discord_Colour->bot_cogs_extensions + + + + + +discord_Colour->bot_cogs_antispam + + + + + +discord_Colour->bot_cogs_moderation_superstarify + + + + + + +discord_Colour->bot_cogs_defcon + + + + + + +discord_Colour->bot_cogs_moderation_ModLog + + + + + + +discord_Colour->bot_cogs_information + + + + + +discord_Colour->bot_cogs_off_topic_names + + + + + +discord_Colour->bot_cogs_alias + + + + + +discord_Colour->bot_cogs_tags + + + + + +discord_Colour->bot_cogs_reddit + + + + + +discord_Colour->bot_cogs_utils + + + + + +discord_Colour->bot_cogs_help + + + + + +discord_Colour->bot_decorators + + + + + +discord_Colour->bot_cogs_moderation_modlog + + + + + + +discord_Colour->bot_cogs_token_remover + + + + + + +discord_Colour->bot_cogs_filtering + + + + + +bot_cogs_watchchannels_bigbrother->bot_cogs_watchchannels + + + + + +discord_Member->bot_rules_attachments + + + + + + + +discord_Member->bot_cogs_stats + + + + + +discord_Member->bot_rules_chars + + + + + +discord_Member->bot_rules_burst_shared + + + + + +discord_Member->bot_cogs_duck_pond + + + + + + +discord_Member->bot_cogs_antispam + + + + +discord_Member->bot_cogs_moderation_superstarify + + + + + +discord_Member->bot_cogs_defcon + + + + + +discord_Member->bot_rules_newlines + + + + + +discord_Member->bot_cogs_watchchannels_talentpool + + + + + + +discord_Member->bot_cogs_information + + + + + +discord_Member->bot_cogs_sync_syncers + + + + + +discord_Member->bot_rules_burst + + + + + +discord_Member->bot_rules_discord_emojis + + + + + +discord_Member->bot_rules_duplicates + + + + +discord_Member->bot_rules_mentions + + + + +discord_Member->bot_decorators + + + + + +discord_Member->bot_cogs_sync_cog + + + + + +discord_Member->bot_cogs_moderation_infractions + + + + + +discord_Member->bot_rules_links + + + + + +discord_Member->bot_utils_messages + + + + + + +discord_Member->bot_rules_role_mentions + + + + + +discord_Member->bot_cogs_filtering + + + + + + + +discord_Member->bot_cogs_jams + + + + + +bot_rules_mentions->bot_rules + + + + + +bot_decorators->bot_cogs_clean + + + + + + + + +bot_decorators->bot_cogs_verification + + + + +bot_decorators->bot_cogs_defcon + + + + + +bot_decorators->bot_cogs_watchchannels_talentpool + + + + + +bot_decorators->bot_cogs_information + + + + + +bot_decorators->bot_cogs_off_topic_names + + + + + +bot_decorators->bot_cogs_eval + + + + + +bot_decorators->bot_cogs_help_channels + + + + + + +bot_decorators->bot_cogs_reddit + + + + + +bot_decorators->bot_cogs_utils + + + + + +bot_decorators->bot_cogs_help + + + + + +bot_decorators->bot_cogs_bot + + + + +bot_decorators->bot_cogs_watchchannels_bigbrother + + + + + +bot_decorators->bot_cogs_snekbox + + + + + + +bot_decorators->bot_cogs_moderation_infractions + + + + + +bot_decorators->bot_cogs_doc + + + + + +bot_decorators->bot_cogs_jams + + + + + +bot_decorators->bot_cogs_error_handler + + + + + +bot_cogs_moderation_modlog->bot_cogs_moderation_management + + + + + + +bot_cogs_moderation_modlog->bot_cogs_webhook_remover + + + + + +bot_cogs_moderation_modlog->bot_cogs_moderation + + + + +bot_cogs_moderation_modlog->bot_cogs_moderation_scheduler + + + + + +bot_patches + +bot.patches + + + +bot_patches->bot___main__ + + + + + +bot_cogs_sync_cog->bot_cogs_sync + + + + + +bot_utils + +bot.utils + + + +bot_utils->bot_cogs_moderation_management + + + + +bot_utils->bot_cogs_verification + + + + + + +bot_utils->bot_cogs_wolfram + + + + + +bot_utils->bot_cogs_watchchannels_watchchannel + + + + + + +bot_utils->bot_cogs_extensions + + + + + +bot_utils->bot_cogs_duck_pond + + + + +bot_utils->bot_cogs_antispam + + + + + + +bot_utils->bot_cogs_moderation_superstarify + + + + + +bot_utils->bot_cogs_moderation_ModLog + + + + + + +bot_utils->bot_cogs_watchchannels_talentpool + + + + + + +bot_utils->bot_cogs_information + + + + +bot_utils->bot_cogs_moderation_silence + + + + + + + +bot_utils->bot_cogs_moderation_scheduler + + + + + +bot_utils->bot_cogs_help_channels + + + + + +bot_utils->bot_cogs_tags + + + + + +bot_utils->bot_cogs_utils + + + + + +bot_utils->bot_cogs_bot + + + + + + +bot_utils->bot_decorators + + + + + +bot_utils->bot_cogs_moderation_modlog + + + + + +bot_utils->bot_cogs_snekbox + + + + + +bot_utils->bot_cogs_moderation_infractions + + + + + + + +bot_utils->bot_cogs_reminders + + + + + + +bot_cogs_moderation_infractions->bot_cogs_moderation_management + + + + + +bot_cogs_moderation_infractions->bot_cogs_moderation + + + + + +bot_rules_links->bot_rules + + + + + +discord_errors + +discord.errors + + + +discord_errors->discord_Guild + + + + + +discord_errors->discord_Client + + + + + + +discord_errors->bot_cogs_watchchannels_watchchannel + + + + +discord_errors->discord_User + + + + + + +discord_errors->discord + + + + + +discord_errors->bot_cogs_duck_pond + + + + + +discord_errors->discord_Webhook + + + + + +discord_errors->discord_utils + + + + + +discord_errors->discord_Message + + + + + + +discord_errors->discord_abc + + + + + +discord_errors->discord_message + + + + + +discord_errors->discord_Role + + + + + + +discord_errors->bot_decorators + + + + + + +discord_errors->bot_cogs_doc + + + + + + +discord_errors->bot_utils_messages + + + + + +discord_errors->bot_cogs_filtering + + + + + +bot_utils_scheduling + +bot. +utils. +scheduling + + + +bot_utils_scheduling->bot_cogs_moderation_scheduler + + + + +bot_utils_scheduling->bot_cogs_help_channels + + + + + +bot_utils_scheduling->bot_cogs_reminders + + + + + +bs4_element + +bs4.element + + + +bs4_element->bs4 + + + + + +bs4_element->bot_cogs_doc + + + + + +dateutil_tz + +dateutil.tz + + + +dateutil_tz->bot_converters + + + + +bot_utils_messages->bot_cogs_watchchannels_watchchannel + + + + + + + +bot_utils_messages->bot_cogs_duck_pond + + + + + +bot_utils_messages->bot_cogs_antispam + + + + + + +bot_utils_messages->bot_cogs_tags + + + + + +bot_utils_messages->bot_cogs_bot + + + + +bot_utils_messages->bot_cogs_snekbox + + + + +bot_patches_message_edited_at->bot_patches + + + + + +bot_rules_role_mentions->bot_rules + + + + + +bot_cogs_token_remover->bot_cogs_bot + + + + + diff --git a/bot/__main__.py b/bot/__main__.py index 2125e8590..3aa36bfc0 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -46,8 +46,8 @@ bot.load_extension("bot.cogs.verification") # Feature cogs bot.load_extension("bot.cogs.alias") bot.load_extension("bot.cogs.defcon") -bot.load_extension("bot.cogs.eval") bot.load_extension("bot.cogs.duck_pond") +bot.load_extension("bot.cogs.eval") bot.load_extension("bot.cogs.information") bot.load_extension("bot.cogs.jams") bot.load_extension("bot.cogs.moderation") @@ -56,8 +56,8 @@ bot.load_extension("bot.cogs.reddit") bot.load_extension("bot.cogs.reminders") bot.load_extension("bot.cogs.site") bot.load_extension("bot.cogs.snekbox") -bot.load_extension("bot.cogs.sync") bot.load_extension("bot.cogs.stats") +bot.load_extension("bot.cogs.sync") bot.load_extension("bot.cogs.tags") bot.load_extension("bot.cogs.token_remover") bot.load_extension("bot.cogs.utils") diff --git a/bot/cogs/defcon.py b/bot/cogs/defcon.py index 80dc6082f..06b2f25c6 100644 --- a/bot/cogs/defcon.py +++ b/bot/cogs/defcon.py @@ -104,7 +104,7 @@ class Defcon(Cog): log.exception(f"Unable to send rejection message to user: {member}") await member.kick(reason="DEFCON active, user is too new") - self.bot.stats.incr("defcon_leaves") + self.bot.stats.incr("defcon.leaves") message = ( f"{member} (`{member.id}`) was denied entry because their account is too new." diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 747ab4a6e..722376cc6 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -236,7 +236,7 @@ class ErrorHandler(Cog): f"```{e.__class__.__name__}: {e}```" ) - ctx.bot.stats.incr("command_error_count") + ctx.bot.stats.incr("errors.commands") with push_scope() as scope: scope.user = { diff --git a/bot/cogs/filtering.py b/bot/cogs/filtering.py index fa4420be1..6a703f5a1 100644 --- a/bot/cogs/filtering.py +++ b/bot/cogs/filtering.py @@ -207,7 +207,7 @@ class Filtering(Cog): log.debug(message) - self.bot.stats.incr(f"bot.filters.{filter_name}") + self.bot.stats.incr(f"filters.{filter_name}") additional_embeds = None additional_embeds_msg = None diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py index b75d29b7e..e963dc312 100644 --- a/bot/cogs/stats.py +++ b/bot/cogs/stats.py @@ -1,6 +1,16 @@ from discord import Member, Message, Status from discord.ext.commands import Bot, Cog, Context +from bot.constants import Guild + + +CHANNEL_NAME_OVERRIDES = { + Guild.channels.off_topic_0: "off_topic_0", + Guild.channels.off_topic_1: "off_topic_1", + Guild.channels.off_topic_2: "off_topic_2", + Guild.channels.staff_lounge: "staff_lounge" +} + class Stats(Cog): """A cog which provides a way to hook onto Discord events and forward to stats.""" @@ -14,12 +24,13 @@ class Stats(Cog): if message.guild is None: return + if message.guild.id != Guild.id: + return + reformatted_name = message.channel.name.replace('-', '_') - if reformatted_name.startswith("ot"): - # Off-topic channels change names, we don't want this for stats. - # This will change 'ot1-lemon-in-the-dishwasher' to just 'ot1' - reformatted_name = reformatted_name[:3] + if CHANNEL_NAME_OVERRIDES.get(message.channel.id): + reformatted_name = CHANNEL_NAME_OVERRIDES.get(message.channel.id) stat_name = f"channels.{reformatted_name}" self.bot.stats.incr(stat_name) @@ -37,22 +48,39 @@ class Stats(Cog): @Cog.listener() async def on_member_join(self, member: Member) -> None: """Update member count stat on member join.""" + if member.guild.id != Guild.id: + return + self.bot.stats.gauge(f"guild.total_members", len(member.guild.members)) @Cog.listener() async def on_member_leave(self, member: Member) -> None: """Update member count stat on member leave.""" + if member.guild.id != Guild.id: + return + self.bot.stats.gauge(f"guild.total_members", len(member.guild.members)) @Cog.listener() async def on_member_update(self, _before: Member, after: Member) -> None: """Update presence estimates on member update.""" - members = after.guild.members + if after.guild.id != Guild.id: + return - online = len([m for m in members if m.status == Status.online]) - idle = len([m for m in members if m.status == Status.idle]) - dnd = len([m for m in members if m.status == Status.do_not_disturb]) - offline = len([m for m in members if m.status == Status.offline]) + online = 0 + idle = 0 + dnd = 0 + offline = 0 + + for member in after.guild.members: + if member.status == Status.online: + online += 1 + elif member.status == Status.dnd: + dnd += 1 + elif member.status == Status.idle: + idle += 1 + else: + offline += 1 self.bot.stats.gauge("guild.status.online", online) self.bot.stats.gauge("guild.status.idle", idle) -- cgit v1.2.3 From 77c07fc2bdad4d7caa9dc654f62a9b1c4dfb63b2 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 19:24:54 +0100 Subject: Address review comments from Mark --- bot.svg | 3795 ----------------------------------------------------- bot/cogs/stats.py | 10 +- 2 files changed, 5 insertions(+), 3800 deletions(-) delete mode 100644 bot.svg diff --git a/bot.svg b/bot.svg deleted file mode 100644 index 97a3914d4..000000000 --- a/bot.svg +++ /dev/null @@ -1,3795 +0,0 @@ - - - - - - -G - - - -bot_cogs_clean - -bot.cogs.clean - - - -requests - -requests - - - -discord_Webhook - -discord. -Webhook - - - -requests->discord_Webhook - - - - - -bot_cogs_doc - -bot.cogs.doc - - - -requests->bot_cogs_doc - - - - - -bot_bot - -bot.bot - - - -bot_bot->bot_cogs_clean - - - - - -bot_cogs_moderation_management - -bot. -cogs. -moderation. -management - - - -bot_bot->bot_cogs_moderation_management - - - - - -bot_cogs_webhook_remover - -bot. -cogs. -webhook_remover - - - -bot_bot->bot_cogs_webhook_remover - - - - - - - -bot_cogs_verification - -bot. -cogs. -verification - - - -bot_bot->bot_cogs_verification - - - - - -bot_cogs_wolfram - -bot. -cogs. -wolfram - - - -bot_bot->bot_cogs_wolfram - - - - - - -bot_cogs_site - -bot.cogs.site - - - -bot_bot->bot_cogs_site - - - - - -bot_cogs_watchchannels_watchchannel - -bot. -cogs. -watchchannels. -watchchannel - - - -bot_bot->bot_cogs_watchchannels_watchchannel - - - - - - -bot_cogs_extensions - -bot. -cogs. -extensions - - - -bot_bot->bot_cogs_extensions - - - - - -bot_cogs_antimalware - -bot. -cogs. -antimalware - - - -bot_bot->bot_cogs_antimalware - - - - - -bot___main__ - -bot.__main__ - - - -bot_bot->bot___main__ - - - - - -bot_cogs_moderation - -bot. -cogs. -moderation - - - -bot_bot->bot_cogs_moderation - - - - - -bot_cogs_duck_pond - -bot. -cogs. -duck_pond - - - -bot_bot->bot_cogs_duck_pond - - - - - - -bot_cogs_antispam - -bot. -cogs. -antispam - - - -bot_bot->bot_cogs_antispam - - - - - -bot_interpreter - -bot. -interpreter - - - -bot_bot->bot_interpreter - - - - - -bot_cogs_moderation_superstarify - -bot. -cogs. -moderation. -superstarify - - - -bot_bot->bot_cogs_moderation_superstarify - - - - -bot_cogs_defcon - -bot. -cogs. -defcon - - - -bot_bot->bot_cogs_defcon - - - - - - -bot_cogs_moderation_ModLog - -bot. -cogs. -moderation. -ModLog - - - -bot_bot->bot_cogs_moderation_ModLog - - - - - -bot_cogs_watchchannels_talentpool - -bot. -cogs. -watchchannels. -talentpool - - - -bot_bot->bot_cogs_watchchannels_talentpool - - - - -bot_cogs_information - -bot. -cogs. -information - - - -bot_bot->bot_cogs_information - - - - - -bot_cogs_off_topic_names - -bot. -cogs. -off_topic_names - - - -bot_bot->bot_cogs_off_topic_names - - - - - - -bot_cogs_alias - -bot.cogs.alias - - - -bot_bot->bot_cogs_alias - - - - - - -bot_cogs_moderation_silence - -bot. -cogs. -moderation. -silence - - - -bot_bot->bot_cogs_moderation_silence - - - - - -bot_cogs_sync_syncers - -bot. -cogs. -sync. -syncers - - - -bot_bot->bot_cogs_sync_syncers - - - - - - -bot_cogs_moderation_scheduler - -bot. -cogs. -moderation. -scheduler - - - -bot_bot->bot_cogs_moderation_scheduler - - - - - - -bot_cogs_eval - -bot.cogs.eval - - - -bot_bot->bot_cogs_eval - - - - - -bot_cogs_help_channels - -bot. -cogs. -help_channels - - - -bot_bot->bot_cogs_help_channels - - - - - -bot_cogs_tags - -bot.cogs.tags - - - -bot_bot->bot_cogs_tags - - - - - - -bot_cogs_reddit - -bot. -cogs. -reddit - - - -bot_bot->bot_cogs_reddit - - - - - - -bot_cogs_utils - -bot.cogs.utils - - - -bot_bot->bot_cogs_utils - - - - - -bot_cogs_sync - -bot.cogs.sync - - - -bot_bot->bot_cogs_sync - - - - - -bot_cogs_help - -bot.cogs.help - - - -bot_bot->bot_cogs_help - - - - - -bot_cogs_bot - -bot.cogs.bot - - - -bot_bot->bot_cogs_bot - - - - - - - - -bot_cogs_watchchannels_bigbrother - -bot. -cogs. -watchchannels. -bigbrother - - - -bot_bot->bot_cogs_watchchannels_bigbrother - - - - -bot_cogs_logging - -bot. -cogs. -logging - - - -bot_bot->bot_cogs_logging - - - - - - -bot_cogs_config_verifier - -bot. -cogs. -config_verifier - - - -bot_bot->bot_cogs_config_verifier - - - - - - -bot_cogs_moderation_modlog - -bot. -cogs. -moderation. -modlog - - - -bot_bot->bot_cogs_moderation_modlog - - - - - - -bot_cogs_sync_cog - -bot. -cogs. -sync. -cog - - - -bot_bot->bot_cogs_sync_cog - - - - - - -bot_cogs_snekbox - -bot. -cogs. -snekbox - - - -bot_bot->bot_cogs_snekbox - - - - - -bot_cogs_moderation_infractions - -bot. -cogs. -moderation. -infractions - - - -bot_bot->bot_cogs_moderation_infractions - - - - - -bot_cogs_watchchannels - -bot. -cogs. -watchchannels - - - -bot_bot->bot_cogs_watchchannels - - - - - -bot_bot->bot_cogs_doc - - - - - -bot_cogs_security - -bot. -cogs. -security - - - -bot_bot->bot_cogs_security - - - - - -bot_cogs_reminders - -bot. -cogs. -reminders - - - -bot_bot->bot_cogs_reminders - - - - - -bot_cogs_token_remover - -bot. -cogs. -token_remover - - - -bot_bot->bot_cogs_token_remover - - - - - - -bot_cogs_filtering - -bot. -cogs. -filtering - - - -bot_bot->bot_cogs_filtering - - - - - -bot_cogs_jams - -bot.cogs.jams - - - -bot_bot->bot_cogs_jams - - - - - -bot_cogs_error_handler - -bot. -cogs. -error_handler - - - -bot_bot->bot_cogs_error_handler - - - - - -bot_rules_attachments - -bot. -rules. -attachments - - - -bot_rules - -bot.rules - - - -bot_rules_attachments->bot_rules - - - - - -bot_cogs_stats - -bot.cogs.stats - - - -bot_api - -bot.api - - - -bot_api->bot_bot - - - - - -bot_api->bot_cogs_watchchannels_watchchannel - - - - -bot_cogs_moderation_utils - -bot. -cogs. -moderation. -utils - - - -bot_api->bot_cogs_moderation_utils - - - - - -bot_api->bot_cogs_watchchannels_talentpool - - - - -bot_api->bot_cogs_off_topic_names - - - - - -bot_api->bot_cogs_sync_syncers - - - - - -bot_api->bot_cogs_moderation_scheduler - - - - -bot_api->bot_cogs_sync_cog - - - - - -bot_api->bot_cogs_error_handler - - - - - - - -bot_cogs_moderation_management->bot_cogs_moderation - - - - - -urllib3_exceptions - -urllib3. -exceptions - - - -urllib3_exceptions->requests - - - - - -urllib3 - -urllib3 - - - -urllib3_exceptions->urllib3 - - - - - -urllib3_exceptions->bot_cogs_doc - - - - - -dateutil_parser - -dateutil. -parser - - - -bot_converters - -bot.converters - - - -dateutil_parser->bot_converters - - - - - -dateutil_parser->bot_cogs_watchchannels_watchchannel - - - - - - -bot_utils_time - -bot.utils.time - - - -dateutil_parser->bot_utils_time - - - - - -dateutil_parser->bot_cogs_moderation_scheduler - - - - - - -dateutil_parser->bot_cogs_reminders - - - - -dateutil_relativedelta - -dateutil. -relativedelta - - - -dateutil_relativedelta->bot_cogs_wolfram - - - - - - -dateutil_relativedelta->bot_converters - - - - - - -dateutil_relativedelta->bot_cogs_moderation_ModLog - - - - - - -dateutil_relativedelta->bot_utils_time - - - - - -dateutil_relativedelta->bot_cogs_utils - - - - - -dateutil_relativedelta->bot_cogs_moderation_modlog - - - - - -dateutil_relativedelta->bot_cogs_reminders - - - - -dateutil_relativedelta->bot_cogs_filtering - - - - - - -bot_rules_chars - -bot. -rules. -chars - - - -bot_rules_chars->bot_rules - - - - - -discord_Guild - -discord.Guild - - - -discord_Guild->bot_cogs_sync_syncers - - - - - -bot_converters->bot_cogs_moderation_management - - - - -bot_converters->bot_cogs_antispam - - - - - -bot_converters->bot_cogs_moderation_superstarify - - - - -bot_converters->bot_cogs_watchchannels_talentpool - - - - - - -bot_converters->bot_cogs_alias - - - - - -bot_converters->bot_cogs_moderation_silence - - - - -bot_converters->bot_cogs_tags - - - - - -bot_converters->bot_cogs_reddit - - - - - -bot_converters->bot_cogs_watchchannels_bigbrother - - - - -bot_converters->bot_cogs_moderation_infractions - - - - - -bot_converters->bot_cogs_doc - - - - - -bot_converters->bot_cogs_reminders - - - - -bot_converters->bot_cogs_error_handler - - - - - -bs4 - -bs4 - - - -bs4->bot_cogs_doc - - - - - -discord_Client - -discord.Client - - - -bot_utils_messages - -bot. -utils. -messages - - - -discord_Client->bot_utils_messages - - - - -bot_rules_burst_shared - -bot. -rules. -burst_shared - - - -bot_rules_burst_shared->bot_rules - - - - - -bot_cogs_watchchannels_watchchannel->bot_cogs_watchchannels_talentpool - - - - - -bot_cogs_watchchannels_watchchannel->bot_cogs_watchchannels_bigbrother - - - - - -aiohttp - -aiohttp - - - -aiohttp->bot_bot - - - - - -aiohttp->bot_api - - - - - - -aiohttp->bot_converters - - - - - -aiohttp->discord_Client - - - - - - -aiohttp->discord_Webhook - - - - - -aiohttp->bot_cogs_reddit - - - - - -bot_cogs_extensions->bot_cogs_alias - - - - - -discord_User - -discord.User - - - -discord_User->bot_cogs_clean - - - - - - -discord_User->bot_cogs_duck_pond - - - - - - - -discord_User->bot_cogs_sync_syncers - - - - - -discord_User->bot_cogs_help - - - - - -discord_User->bot_cogs_sync_cog - - - - - -discord_User->bot_cogs_snekbox - - - - - -bot_rules->bot_cogs_antispam - - - - - -bot_cogs_moderation->bot_cogs_clean - - - - - -bot_cogs_moderation->bot_cogs_webhook_remover - - - - - -bot_cogs_moderation->bot_cogs_verification - - - - - -bot_cogs_moderation->bot_cogs_watchchannels_watchchannel - - - - - -bot_cogs_moderation->bot_cogs_antispam - - - - - -bot_cogs_moderation->bot_cogs_defcon - - - - - -bot_cogs_moderation->bot_cogs_watchchannels_bigbrother - - - - -bot_cogs_moderation->bot_cogs_token_remover - - - - - -bot_cogs_moderation->bot_cogs_filtering - - - - - -discord - -discord - - - -discord->bot_cogs_clean - - - - - -discord->bot_bot - - - - - -discord->bot_rules_attachments - - - - - -discord->bot_cogs_stats - - - - - -discord->bot_cogs_moderation_management - - - - - -discord->bot_cogs_webhook_remover - - - - -discord->bot_cogs_verification - - - - - - -discord->bot_cogs_wolfram - - - - - - - -discord->bot_rules_chars - - - - - -discord->bot_converters - - - - - -discord->bot_cogs_site - - - - - - -discord->bot_rules_burst_shared - - - - - -discord->bot_cogs_watchchannels_watchchannel - - - - - -discord->bot_cogs_extensions - - - - - -discord->bot_cogs_antimalware - - - - - -discord->bot___main__ - - - - - - -discord->bot_cogs_duck_pond - - - - - -discord->bot_cogs_antispam - - - - -discord->bot_interpreter - - - - - -discord->bot_cogs_moderation_superstarify - - - - - -discord->bot_cogs_defcon - - - - - - -bot_pagination - -bot.pagination - - - -discord->bot_pagination - - - - - -discord->bot_cogs_moderation_ModLog - - - - - - -discord->bot_cogs_moderation_utils - - - - - - -bot_rules_newlines - -bot. -rules. -newlines - - - -discord->bot_rules_newlines - - - - - - -discord->bot_cogs_watchchannels_talentpool - - - - - -discord->bot_cogs_information - - - - - -discord->bot_cogs_off_topic_names - - - - - -discord->bot_cogs_alias - - - - - -discord->bot_cogs_moderation_silence - - - - - - -discord->bot_cogs_sync_syncers - - - - - - -discord->bot_cogs_moderation_scheduler - - - - - - -discord->bot_cogs_eval - - - - - - -bot_rules_burst - -bot. -rules. -burst - - - -discord->bot_rules_burst - - - - - -discord->bot_cogs_help_channels - - - - - - -discord->bot_cogs_tags - - - - - -discord->bot_cogs_reddit - - - - - - -discord->bot_cogs_utils - - - - - -bot_rules_discord_emojis - -bot. -rules. -discord_emojis - - - -discord->bot_rules_discord_emojis - - - - - -bot_rules_duplicates - -bot. -rules. -duplicates - - - -discord->bot_rules_duplicates - - - - - -discord->bot_cogs_help - - - - - -discord->bot_cogs_bot - - - - - - - -discord->bot_cogs_logging - - - - - - -bot_rules_mentions - -bot. -rules. -mentions - - - -discord->bot_rules_mentions - - - - - -bot_decorators - -bot.decorators - - - -discord->bot_decorators - - - - - -discord->bot_cogs_moderation_modlog - - - - - -discord->bot_cogs_sync_cog - - - - - -discord->bot_cogs_snekbox - - - - - -discord->bot_cogs_moderation_infractions - - - - - - -bot_rules_links - -bot. -rules. -links - - - -discord->bot_rules_links - - - - - - -discord->bot_cogs_doc - - - - - -discord->bot_utils_messages - - - - - -bot_patches_message_edited_at - -bot. -patches. -message_edited_at - - - -discord->bot_patches_message_edited_at - - - - - - - -discord->bot_cogs_reminders - - - - - -bot_rules_role_mentions - -bot. -rules. -role_mentions - - - -discord->bot_rules_role_mentions - - - - - -discord->bot_cogs_token_remover - - - - - -discord->bot_cogs_filtering - - - - - -discord->bot_cogs_jams - - - - - -bot_constants - -bot.constants - - - -bot_constants->bot_cogs_clean - - - - - -bot_constants->bot_bot - - - - - -bot_constants->bot_api - - - - - -bot_constants->bot_cogs_moderation_management - - - - - -bot_constants->bot_cogs_webhook_remover - - - - -bot_constants->bot_cogs_verification - - - - - -bot_constants->bot_cogs_wolfram - - - - -bot_constants->bot_cogs_site - - - - - - -bot_constants->bot_cogs_watchchannels_watchchannel - - - - - -bot_constants->bot_cogs_extensions - - - - - -bot_constants->bot_cogs_antimalware - - - - - -bot_constants->bot___main__ - - - - - -bot_constants->bot_cogs_duck_pond - - - - - - -bot_constants->bot_cogs_antispam - - - - - -bot_constants->bot_cogs_moderation_superstarify - - - - -bot_constants->bot_cogs_defcon - - - - - -bot_constants->bot_pagination - - - - - - -bot_constants->bot_cogs_moderation_ModLog - - - - - - -bot_constants->bot_cogs_moderation_utils - - - - - -bot_constants->bot_cogs_watchchannels_talentpool - - - - - - -bot_constants->bot_cogs_information - - - - - - -bot_constants->bot_cogs_off_topic_names - - - - - -bot_constants->bot_cogs_moderation_silence - - - - - - -bot_constants->bot_cogs_sync_syncers - - - - - -bot_constants->bot_cogs_moderation_scheduler - - - - - - -bot_constants->bot_cogs_eval - - - - - -bot_constants->bot_cogs_help_channels - - - - - -bot_constants->bot_cogs_tags - - - - - - -bot_constants->bot_cogs_reddit - - - - -bot_constants->bot_cogs_utils - - - - - -bot_constants->bot_cogs_help - - - - - - - -bot_constants->bot_cogs_bot - - - - - -bot_constants->bot_cogs_watchchannels_bigbrother - - - - - - -bot_constants->bot_cogs_logging - - - - - - -bot_constants->bot_cogs_config_verifier - - - - - -bot_constants->bot_decorators - - - - -bot_constants->bot_cogs_moderation_modlog - - - - - - -bot_constants->bot_cogs_sync_cog - - - - - - -bot_constants->bot_cogs_snekbox - - - - - - -bot_constants->bot_cogs_moderation_infractions - - - - - - -bot_constants->bot_cogs_doc - - - - - -bot_constants->bot_utils_messages - - - - - - -bot_constants->bot_cogs_reminders - - - - -bot_constants->bot_cogs_token_remover - - - - - -bot_constants->bot_cogs_filtering - - - - - - - - -bot_constants->bot_cogs_jams - - - - - -bot_constants->bot_cogs_error_handler - - - - -discord_File - -discord.File - - - -discord_File->bot_utils_messages - - - - -discord_Reaction - -discord. -Reaction - - - -discord_Reaction->bot_cogs_sync_syncers - - - - - -discord_Reaction->bot_cogs_help - - - - - -discord_Reaction->bot_cogs_snekbox - - - - - -discord_Reaction->bot_utils_messages - - - - - -bot_interpreter->bot_cogs_eval - - - - - - -bot_cogs_moderation_superstarify->bot_cogs_moderation - - - - - - -more_itertools - -more_itertools - - - -more_itertools->bot_cogs_jams - - - - - -statsd - -statsd - - - -statsd->bot_bot - - - - - -bot_pagination->bot_cogs_moderation_management - - - - - - - -bot_pagination->bot_cogs_wolfram - - - - - -bot_pagination->bot_cogs_site - - - - - -bot_pagination->bot_cogs_watchchannels_watchchannel - - - - - -bot_pagination->bot_cogs_extensions - - - - - -bot_pagination->bot_cogs_watchchannels_talentpool - - - - - -bot_pagination->bot_cogs_information - - - - - -bot_pagination->bot_cogs_off_topic_names - - - - - - -bot_pagination->bot_cogs_alias - - - - - -bot_pagination->bot_cogs_tags - - - - - -bot_pagination->bot_cogs_reddit - - - - - - -bot_pagination->bot_cogs_help - - - - - -bot_pagination->bot_cogs_doc - - - - - -bot_pagination->bot_cogs_reminders - - - - - -bot_utils_checks - -bot. -utils. -checks - - - -bot_utils_checks->bot_cogs_moderation_management - - - - - -bot_utils_checks->bot_cogs_verification - - - - - -bot_utils_checks->bot_cogs_extensions - - - - - - -bot_utils_checks->bot_cogs_moderation_superstarify - - - - - -bot_utils_checks->bot_cogs_information - - - - - -bot_utils_checks->bot_cogs_moderation_silence - - - - - - -bot_utils_checks->bot_decorators - - - - - -bot_utils_checks->bot_cogs_moderation_infractions - - - - - - -bot_utils_checks->bot_cogs_reminders - - - - -bot_cogs_moderation_ModLog->bot_cogs_clean - - - - - - -bot_cogs_moderation_ModLog->bot_cogs_verification - - - - - -bot_cogs_moderation_ModLog->bot_cogs_watchchannels_watchchannel - - - - - -bot_cogs_moderation_ModLog->bot_cogs_antispam - - - - - -bot_cogs_moderation_ModLog->bot_cogs_defcon - - - - - - -bot_cogs_moderation_ModLog->bot_cogs_token_remover - - - - - - - -bot_cogs_moderation_ModLog->bot_cogs_filtering - - - - - - - -discord_Object - -discord.Object - - - -discord_Object->bot_cogs_verification - - - - - -discord_Object->bot_cogs_antispam - - - - - - -bot_cogs_moderation_utils->bot_cogs_moderation_management - - - - - -bot_cogs_moderation_utils->bot_cogs_moderation_superstarify - - - - - - -bot_cogs_moderation_utils->bot_cogs_moderation_scheduler - - - - - -bot_cogs_moderation_utils->bot_cogs_watchchannels_bigbrother - - - - - - - -bot_cogs_moderation_utils->bot_cogs_moderation_infractions - - - - - -discord_Webhook->bot_utils_messages - - - - - - - -bot_rules_newlines->bot_rules - - - - - -bot_cogs_watchchannels_talentpool->bot_cogs_watchchannels - - - - - -discord_utils - -discord.utils - - - -discord_utils->discord_Guild - - - - - -discord_utils->discord_Client - - - - -discord_utils->discord_User - - - - - -discord_utils->discord - - - - - -discord_utils->bot_cogs_moderation_ModLog - - - - - - -discord_utils->discord_Object - - - - - -discord_utils->discord_Webhook - - - - - -discord_utils->bot_cogs_information - - - - - - -discord_Message - -discord. -Message - - - -discord_utils->discord_Message - - - - - -discord_abc - -discord.abc - - - -discord_utils->discord_abc - - - - - -discord_message - -discord. -message - - - -discord_utils->discord_message - - - - - -discord_Role - -discord.Role - - - -discord_utils->discord_Role - - - - - -discord_Member - -discord.Member - - - -discord_utils->discord_Member - - - - - - -discord_utils->bot_cogs_moderation_modlog - - - - - -discord_utils->bot_patches_message_edited_at - - - - - -discord_utils->bot_cogs_token_remover - - - - - -discord_utils->bot_cogs_filtering - - - - - - -discord_utils->bot_cogs_jams - - - - - -bot_cogs_moderation_silence->bot_cogs_moderation - - - - - -bot_utils_time->bot_cogs_moderation_management - - - - - - -bot_utils_time->bot_cogs_wolfram - - - - - -bot_utils_time->bot_cogs_watchchannels_watchchannel - - - - - -bot_utils_time->bot_cogs_moderation_superstarify - - - - - -bot_utils_time->bot_cogs_moderation_ModLog - - - - - -bot_utils_time->bot_cogs_watchchannels_talentpool - - - - -bot_utils_time->bot_cogs_information - - - - - - -bot_utils_time->bot_cogs_moderation_scheduler - - - - - -bot_utils_time->bot_cogs_utils - - - - - -bot_utils_time->bot_cogs_moderation_modlog - - - - - - - -bot_utils_time->bot_cogs_reminders - - - - - -discord_Message->bot_cogs_clean - - - - - -discord_Message->bot_rules_attachments - - - - - -discord_Message->bot_cogs_stats - - - - - -discord_Message->bot_cogs_webhook_remover - - - - - - - -discord_Message->bot_cogs_verification - - - - - -discord_Message->bot_rules_chars - - - - - - -discord_Message->bot_rules_burst_shared - - - - - -discord_Message->bot_cogs_watchchannels_watchchannel - - - - - - -discord_Message->bot_cogs_antimalware - - - - - -discord_Message->bot_cogs_duck_pond - - - - - -discord_Message->bot_cogs_antispam - - - - - -discord_Message->bot_rules_newlines - - - - - - -discord_Message->bot_cogs_information - - - - - -discord_Message->bot_cogs_sync_syncers - - - - - -discord_Message->bot_rules_burst - - - - - - - -discord_Message->bot_cogs_utils - - - - - -discord_Message->bot_rules_discord_emojis - - - - - - -discord_Message->bot_rules_duplicates - - - - - - -discord_Message->bot_cogs_help - - - - - - - - -discord_Message->bot_cogs_bot - - - - - - -discord_Message->bot_rules_mentions - - - - - - -discord_Message->bot_cogs_snekbox - - - - - - - -discord_Message->bot_rules_links - - - - - - -discord_Message->bot_utils_messages - - - - - -discord_Message->bot_rules_role_mentions - - - - - -discord_Message->bot_cogs_token_remover - - - - - - -discord_Message->bot_cogs_filtering - - - - - - - -bot_cogs_sync_syncers->bot_cogs_sync_cog - - - - - -dateutil - -dateutil - - - -dateutil->bot_cogs_wolfram - - - - - -dateutil->bot_converters - - - - - - - -dateutil->bot_cogs_watchchannels_watchchannel - - - - -dateutil->bot_cogs_moderation_ModLog - - - - - -dateutil->bot_utils_time - - - - - -dateutil->bot_cogs_moderation_scheduler - - - - - -dateutil->bot_cogs_utils - - - - - -dateutil->bot_cogs_moderation_modlog - - - - - -dateutil->bot_cogs_reminders - - - - -dateutil->bot_cogs_filtering - - - - - -bot_cogs_moderation_scheduler->bot_cogs_moderation_superstarify - - - - - -bot_cogs_moderation_scheduler->bot_cogs_moderation_infractions - - - - - -bot_rules_burst->bot_rules - - - - - -discord_abc->discord_User - - - - - -discord_abc->discord - - - - - -discord_abc->bot_pagination - - - - - -discord_abc->bot_cogs_moderation_ModLog - - - - - -discord_abc->discord_Member - - - - - -discord_abc->bot_cogs_moderation_modlog - - - - - -discord_abc->bot_utils_messages - - - - -discord_message->discord - - - - - -discord_message->discord_Webhook - - - - - -discord_message->bot_patches_message_edited_at - - - - - - -bot_rules_discord_emojis->bot_rules - - - - - -yaml - -yaml - - - -yaml->bot_constants - - - - - -bot_rules_duplicates->bot_rules - - - - - -urllib3->requests - - - - - -urllib3->bot_cogs_doc - - - - - - -discord_Role->bot_cogs_information - - - - - -discord_Role->bot_cogs_utils - - - - - -discord_Role->bot_cogs_sync_cog - - - - - -discord_Colour - -discord.Colour - - - -discord_Colour->bot_cogs_clean - - - - -discord_Colour->bot_cogs_webhook_remover - - - - - -discord_Colour->bot_cogs_verification - - - - - -discord_Colour->bot_cogs_site - - - - - - -discord_Colour->bot_cogs_extensions - - - - - -discord_Colour->bot_cogs_antispam - - - - - -discord_Colour->bot_cogs_moderation_superstarify - - - - - - -discord_Colour->bot_cogs_defcon - - - - - - -discord_Colour->bot_cogs_moderation_ModLog - - - - - - -discord_Colour->bot_cogs_information - - - - - -discord_Colour->bot_cogs_off_topic_names - - - - - -discord_Colour->bot_cogs_alias - - - - - -discord_Colour->bot_cogs_tags - - - - - -discord_Colour->bot_cogs_reddit - - - - - -discord_Colour->bot_cogs_utils - - - - - -discord_Colour->bot_cogs_help - - - - - -discord_Colour->bot_decorators - - - - - -discord_Colour->bot_cogs_moderation_modlog - - - - - - -discord_Colour->bot_cogs_token_remover - - - - - - -discord_Colour->bot_cogs_filtering - - - - - -bot_cogs_watchchannels_bigbrother->bot_cogs_watchchannels - - - - - -discord_Member->bot_rules_attachments - - - - - - - -discord_Member->bot_cogs_stats - - - - - -discord_Member->bot_rules_chars - - - - - -discord_Member->bot_rules_burst_shared - - - - - -discord_Member->bot_cogs_duck_pond - - - - - - -discord_Member->bot_cogs_antispam - - - - -discord_Member->bot_cogs_moderation_superstarify - - - - - -discord_Member->bot_cogs_defcon - - - - - -discord_Member->bot_rules_newlines - - - - - -discord_Member->bot_cogs_watchchannels_talentpool - - - - - - -discord_Member->bot_cogs_information - - - - - -discord_Member->bot_cogs_sync_syncers - - - - - -discord_Member->bot_rules_burst - - - - - -discord_Member->bot_rules_discord_emojis - - - - - -discord_Member->bot_rules_duplicates - - - - -discord_Member->bot_rules_mentions - - - - -discord_Member->bot_decorators - - - - - -discord_Member->bot_cogs_sync_cog - - - - - -discord_Member->bot_cogs_moderation_infractions - - - - - -discord_Member->bot_rules_links - - - - - -discord_Member->bot_utils_messages - - - - - - -discord_Member->bot_rules_role_mentions - - - - - -discord_Member->bot_cogs_filtering - - - - - - - -discord_Member->bot_cogs_jams - - - - - -bot_rules_mentions->bot_rules - - - - - -bot_decorators->bot_cogs_clean - - - - - - - - -bot_decorators->bot_cogs_verification - - - - -bot_decorators->bot_cogs_defcon - - - - - -bot_decorators->bot_cogs_watchchannels_talentpool - - - - - -bot_decorators->bot_cogs_information - - - - - -bot_decorators->bot_cogs_off_topic_names - - - - - -bot_decorators->bot_cogs_eval - - - - - -bot_decorators->bot_cogs_help_channels - - - - - - -bot_decorators->bot_cogs_reddit - - - - - -bot_decorators->bot_cogs_utils - - - - - -bot_decorators->bot_cogs_help - - - - - -bot_decorators->bot_cogs_bot - - - - -bot_decorators->bot_cogs_watchchannels_bigbrother - - - - - -bot_decorators->bot_cogs_snekbox - - - - - - -bot_decorators->bot_cogs_moderation_infractions - - - - - -bot_decorators->bot_cogs_doc - - - - - -bot_decorators->bot_cogs_jams - - - - - -bot_decorators->bot_cogs_error_handler - - - - - -bot_cogs_moderation_modlog->bot_cogs_moderation_management - - - - - - -bot_cogs_moderation_modlog->bot_cogs_webhook_remover - - - - - -bot_cogs_moderation_modlog->bot_cogs_moderation - - - - -bot_cogs_moderation_modlog->bot_cogs_moderation_scheduler - - - - - -bot_patches - -bot.patches - - - -bot_patches->bot___main__ - - - - - -bot_cogs_sync_cog->bot_cogs_sync - - - - - -bot_utils - -bot.utils - - - -bot_utils->bot_cogs_moderation_management - - - - -bot_utils->bot_cogs_verification - - - - - - -bot_utils->bot_cogs_wolfram - - - - - -bot_utils->bot_cogs_watchchannels_watchchannel - - - - - - -bot_utils->bot_cogs_extensions - - - - - -bot_utils->bot_cogs_duck_pond - - - - -bot_utils->bot_cogs_antispam - - - - - - -bot_utils->bot_cogs_moderation_superstarify - - - - - -bot_utils->bot_cogs_moderation_ModLog - - - - - - -bot_utils->bot_cogs_watchchannels_talentpool - - - - - - -bot_utils->bot_cogs_information - - - - -bot_utils->bot_cogs_moderation_silence - - - - - - - -bot_utils->bot_cogs_moderation_scheduler - - - - - -bot_utils->bot_cogs_help_channels - - - - - -bot_utils->bot_cogs_tags - - - - - -bot_utils->bot_cogs_utils - - - - - -bot_utils->bot_cogs_bot - - - - - - -bot_utils->bot_decorators - - - - - -bot_utils->bot_cogs_moderation_modlog - - - - - -bot_utils->bot_cogs_snekbox - - - - - -bot_utils->bot_cogs_moderation_infractions - - - - - - - -bot_utils->bot_cogs_reminders - - - - - - -bot_cogs_moderation_infractions->bot_cogs_moderation_management - - - - - -bot_cogs_moderation_infractions->bot_cogs_moderation - - - - - -bot_rules_links->bot_rules - - - - - -discord_errors - -discord.errors - - - -discord_errors->discord_Guild - - - - - -discord_errors->discord_Client - - - - - - -discord_errors->bot_cogs_watchchannels_watchchannel - - - - -discord_errors->discord_User - - - - - - -discord_errors->discord - - - - - -discord_errors->bot_cogs_duck_pond - - - - - -discord_errors->discord_Webhook - - - - - -discord_errors->discord_utils - - - - - -discord_errors->discord_Message - - - - - - -discord_errors->discord_abc - - - - - -discord_errors->discord_message - - - - - -discord_errors->discord_Role - - - - - - -discord_errors->bot_decorators - - - - - - -discord_errors->bot_cogs_doc - - - - - - -discord_errors->bot_utils_messages - - - - - -discord_errors->bot_cogs_filtering - - - - - -bot_utils_scheduling - -bot. -utils. -scheduling - - - -bot_utils_scheduling->bot_cogs_moderation_scheduler - - - - -bot_utils_scheduling->bot_cogs_help_channels - - - - - -bot_utils_scheduling->bot_cogs_reminders - - - - - -bs4_element - -bs4.element - - - -bs4_element->bs4 - - - - - -bs4_element->bot_cogs_doc - - - - - -dateutil_tz - -dateutil.tz - - - -dateutil_tz->bot_converters - - - - -bot_utils_messages->bot_cogs_watchchannels_watchchannel - - - - - - - -bot_utils_messages->bot_cogs_duck_pond - - - - - -bot_utils_messages->bot_cogs_antispam - - - - - - -bot_utils_messages->bot_cogs_tags - - - - - -bot_utils_messages->bot_cogs_bot - - - - -bot_utils_messages->bot_cogs_snekbox - - - - -bot_patches_message_edited_at->bot_patches - - - - - -bot_rules_role_mentions->bot_rules - - - - - -bot_cogs_token_remover->bot_cogs_bot - - - - - diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py index e963dc312..8fb7d8639 100644 --- a/bot/cogs/stats.py +++ b/bot/cogs/stats.py @@ -1,14 +1,14 @@ from discord import Member, Message, Status from discord.ext.commands import Bot, Cog, Context -from bot.constants import Guild +from bot.constants import Channels, Guild CHANNEL_NAME_OVERRIDES = { - Guild.channels.off_topic_0: "off_topic_0", - Guild.channels.off_topic_1: "off_topic_1", - Guild.channels.off_topic_2: "off_topic_2", - Guild.channels.staff_lounge: "staff_lounge" + Channels.off_topic_0: "off_topic_0", + Channels.off_topic_1: "off_topic_1", + Channels.off_topic_2: "off_topic_2", + Channels.staff_lounge: "staff_lounge" } -- cgit v1.2.3 From bca47a1c2e59fb112b947876cea1836879ac7282 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 21:02:13 +0100 Subject: Implement an AsyncStatsClient to send statsd communications asynchronously --- bot/async_stats.py | 39 +++++++++++++++++++++++++++++++++++++++ bot/bot.py | 13 ++++++++++--- 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 bot/async_stats.py diff --git a/bot/async_stats.py b/bot/async_stats.py new file mode 100644 index 000000000..58a80f528 --- /dev/null +++ b/bot/async_stats.py @@ -0,0 +1,39 @@ +import asyncio +import socket + +from statsd.client.base import StatsClientBase + + +class AsyncStatsClient(StatsClientBase): + """An async transport method for statsd communication.""" + + def __init__( + self, + loop: asyncio.AbstractEventLoop, + host: str = 'localhost', + port: int = 8125, + prefix: str = None + ): + """Create a new client.""" + family, _, _, _, addr = socket.getaddrinfo( + host, port, socket.AF_INET, socket.SOCK_DGRAM)[0] + self._addr = addr + self._prefix = prefix + self._loop = loop + self._transport = None + + async def create_socket(self) -> None: + """Use the loop.create_datagram_endpoint method to create a socket.""" + self._transport, _ = await self._loop.create_datagram_endpoint( + asyncio.DatagramProtocol, + family=socket.AF_INET, + remote_addr=self._addr + ) + + def _send(self, data: str) -> None: + """Start an async task to send data to statsd.""" + self._loop.create_task(self._async_send(data)) + + async def _async_send(self, data: str) -> None: + """Send data to the statsd server using the async transport.""" + self._transport.sendto(data.encode('ascii'), self._addr) diff --git a/bot/bot.py b/bot/bot.py index 65081e438..c5d490409 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -6,10 +6,10 @@ from typing import Optional import aiohttp import discord -import statsd from discord.ext import commands from bot import DEBUG_MODE, api, constants +from bot.async_stats import AsyncStatsClient log = logging.getLogger('bot') @@ -41,7 +41,7 @@ class Bot(commands.Bot): # will effectively disable stats. statsd_url = "127.0.0.1" - self.stats = statsd.StatsClient(statsd_url, 8125, prefix="bot") + self.stats = AsyncStatsClient(self.loop, statsd_url, 8125, prefix="bot") def add_cog(self, cog: commands.Cog) -> None: """Adds a "cog" to the bot and logs the operation.""" @@ -60,7 +60,7 @@ class Bot(commands.Bot): super().clear() async def close(self) -> None: - """Close the Discord connection and the aiohttp session, connector, and resolver.""" + """Close the Discord connection and the aiohttp session, connector, statsd client, and resolver.""" await super().close() await self.api_client.close() @@ -74,6 +74,9 @@ class Bot(commands.Bot): if self._resolver: await self._resolver.close() + if self.stats._transport: + await self.stats._transport.close() + async def login(self, *args, **kwargs) -> None: """Re-create the connector and set up sessions before logging into Discord.""" self._recreate() @@ -111,6 +114,10 @@ class Bot(commands.Bot): self.http_session = aiohttp.ClientSession(connector=self._connector) self.api_client.recreate(force=True, connector=self._connector) + async def on_ready(self) -> None: + """Construct an asynchronous transport for the statsd client.""" + await self.stats.create_socket() + async def on_guild_available(self, guild: discord.Guild) -> None: """ Set the internal guild available event when constants.Guild.id becomes available. -- cgit v1.2.3 From 7da559647db7dfd4386f1711e2c053efd9a6c897 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 21:37:49 +0100 Subject: Move create_socket to the login method of the bot --- bot/bot.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bot/bot.py b/bot/bot.py index c5d490409..ef4a325dc 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -80,6 +80,7 @@ class Bot(commands.Bot): async def login(self, *args, **kwargs) -> None: """Re-create the connector and set up sessions before logging into Discord.""" self._recreate() + await self.stats.create_socket() await super().login(*args, **kwargs) def _recreate(self) -> None: @@ -114,10 +115,6 @@ class Bot(commands.Bot): self.http_session = aiohttp.ClientSession(connector=self._connector) self.api_client.recreate(force=True, connector=self._connector) - async def on_ready(self) -> None: - """Construct an asynchronous transport for the statsd client.""" - await self.stats.create_socket() - async def on_guild_available(self, guild: discord.Guild) -> None: """ Set the internal guild available event when constants.Guild.id becomes available. -- cgit v1.2.3 From ee5a4df9537b46cdceb35243d887e84601d07795 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 22:11:43 +0100 Subject: Additional statistics --- bot/cogs/defcon.py | 2 ++ bot/cogs/error_handler.py | 14 +++++++++++++- bot/cogs/help_channels.py | 24 ++++++++++++++++++++---- bot/cogs/stats.py | 14 ++++++++++---- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/bot/cogs/defcon.py b/bot/cogs/defcon.py index 06b2f25c6..9197dcca3 100644 --- a/bot/cogs/defcon.py +++ b/bot/cogs/defcon.py @@ -146,6 +146,8 @@ class Defcon(Cog): await ctx.send(self.build_defcon_msg(action, error)) await self.send_defcon_log(action, ctx.author, error) + self.bot.stats.gauge("defcon.days", days) + @defcon_group.command(name='enable', aliases=('on', 'e')) @with_role(Roles.admins, Roles.owners) async def enable_command(self, ctx: Context) -> None: diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 722376cc6..dae283c6a 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -171,19 +171,25 @@ class ErrorHandler(Cog): if isinstance(e, errors.MissingRequiredArgument): await ctx.send(f"Missing required argument `{e.param.name}`.") await ctx.invoke(*help_command) + self.bot.stats.incr("errors.missing_required_argument") elif isinstance(e, errors.TooManyArguments): await ctx.send(f"Too many arguments provided.") await ctx.invoke(*help_command) + self.bot.stats.incr("errors.too_many_arguments") elif isinstance(e, errors.BadArgument): await ctx.send(f"Bad argument: {e}\n") await ctx.invoke(*help_command) + self.bot.stats.incr("errors.bad_argument") elif isinstance(e, errors.BadUnionArgument): await ctx.send(f"Bad argument: {e}\n```{e.errors[-1]}```") + self.bot.stats.incr("errors.bad_union_argument") elif isinstance(e, errors.ArgumentParsingError): await ctx.send(f"Argument parsing error: {e}") + self.bot.stats.incr("errors.argument_parsing_error") else: await ctx.send("Something about your input seems off. Check the arguments:") await ctx.invoke(*help_command) + self.bot.stats.incr("errors.other_user_input_error") @staticmethod async def handle_check_failure(ctx: Context, e: errors.CheckFailure) -> None: @@ -205,10 +211,12 @@ class ErrorHandler(Cog): ) if isinstance(e, bot_missing_errors): + ctx.bot.stats.incr("errors.bot_permission_error") await ctx.send( f"Sorry, it looks like I don't have the permissions or roles I need to do that." ) elif isinstance(e, (InChannelCheckFailure, errors.NoPrivateMessage)): + ctx.bot.stats.incr("errors.wrong_channel_or_dm_error") await ctx.send(e) @staticmethod @@ -217,16 +225,20 @@ class ErrorHandler(Cog): if e.status == 404: await ctx.send("There does not seem to be anything matching your query.") log.debug(f"API responded with 404 for command {ctx.command}") + ctx.bot.stats.incr("errors.api_error_404") elif e.status == 400: content = await e.response.json() log.debug(f"API responded with 400 for command {ctx.command}: %r.", content) await ctx.send("According to the API, your request is malformed.") + ctx.bot.stats.incr("errors.api_error_400") elif 500 <= e.status < 600: await ctx.send("Sorry, there seems to be an internal issue with the API.") log.warning(f"API responded with {e.status} for command {ctx.command}") + ctx.bot.stats.incr("errors.api_internal_server_error") else: await ctx.send(f"Got an unexpected status code from the API (`{e.status}`).") log.warning(f"Unexpected API response for command {ctx.command}: {e.status}") + ctx.bot.stats.incr(f"errors.api_error_{e.status}") @staticmethod async def handle_unexpected_error(ctx: Context, e: errors.CommandError) -> None: @@ -236,7 +248,7 @@ class ErrorHandler(Cog): f"```{e.__class__.__name__}: {e}```" ) - ctx.bot.stats.incr("errors.commands") + ctx.bot.stats.incr("errors.unexpected") with push_scope() as scope: scope.user = { diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 389a4ad2a..01a77db2b 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -127,6 +127,9 @@ class HelpChannels(Scheduler, commands.Cog): self.on_message_lock = asyncio.Lock() self.init_task = self.bot.loop.create_task(self.init_cog()) + # Stats + self.claim_times = {} + def cog_unload(self) -> None: """Cancel the init task and scheduled tasks when the cog unloads.""" log.trace("Cog unload: cancelling the init_cog task") @@ -195,7 +198,7 @@ class HelpChannels(Scheduler, commands.Cog): if ctx.channel.category == self.in_use_category: self.cancel_task(ctx.channel.id) - await self.move_to_dormant(ctx.channel) + await self.move_to_dormant(ctx.channel, "command") else: log.debug(f"{ctx.author} invoked command 'dormant' outside an in-use help channel") @@ -406,7 +409,7 @@ class HelpChannels(Scheduler, commands.Cog): f"and will be made dormant." ) - await self.move_to_dormant(channel) + await self.move_to_dormant(channel, "auto") else: # Cancel the existing task, if any. if has_task: @@ -446,8 +449,12 @@ class HelpChannels(Scheduler, commands.Cog): await self.ensure_permissions_synchronization(self.available_category) self.report_stats() - async def move_to_dormant(self, channel: discord.TextChannel) -> None: - """Make the `channel` dormant.""" + async def move_to_dormant(self, channel: discord.TextChannel, caller: str) -> None: + """ + Make the `channel` dormant. + + A caller argument is provided for metrics. + """ log.info(f"Moving #{channel} ({channel.id}) to the Dormant category.") await channel.edit( @@ -457,6 +464,13 @@ class HelpChannels(Scheduler, commands.Cog): topic=DORMANT_TOPIC, ) + self.bot.stats.incr(f"help.dormant_calls.{caller}") + + if self.claim_times.get(channel.id): + claimed = self.claim_times[channel.id] + in_use_time = datetime.now() - claimed + self.bot.stats.timer("help.in_use_time", in_use_time) + log.trace(f"Position of #{channel} ({channel.id}) is actually {channel.position}.") log.trace(f"Sending dormant message for #{channel} ({channel.id}).") @@ -560,6 +574,8 @@ class HelpChannels(Scheduler, commands.Cog): self.bot.stats.incr("help.claimed") + self.claim_times[channel.id] = datetime.now() + log.trace(f"Releasing on_message lock for {message.id}.") # Move a dormant channel to the Available category to fill in the gap. diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py index 8fb7d8639..772ae2c97 100644 --- a/bot/cogs/stats.py +++ b/bot/cogs/stats.py @@ -1,3 +1,5 @@ +import string + from discord import Member, Message, Status from discord.ext.commands import Bot, Cog, Context @@ -11,6 +13,8 @@ CHANNEL_NAME_OVERRIDES = { Channels.staff_lounge: "staff_lounge" } +ALLOWED_CHARS = string.ascii_letters + string.digits + class Stats(Cog): """A cog which provides a way to hook onto Discord events and forward to stats.""" @@ -32,6 +36,8 @@ class Stats(Cog): if CHANNEL_NAME_OVERRIDES.get(message.channel.id): reformatted_name = CHANNEL_NAME_OVERRIDES.get(message.channel.id) + reformatted_name = "".join([char for char in reformatted_name if char in ALLOWED_CHARS]) + stat_name = f"channels.{reformatted_name}" self.bot.stats.incr(stat_name) @@ -73,13 +79,13 @@ class Stats(Cog): offline = 0 for member in after.guild.members: - if member.status == Status.online: + if member.status is Status.online: online += 1 - elif member.status == Status.dnd: + elif member.status is Status.dnd: dnd += 1 - elif member.status == Status.idle: + elif member.status is Status.idle: idle += 1 - else: + elif member.status is Status.offline: offline += 1 self.bot.stats.gauge("guild.status.online", online) -- cgit v1.2.3 From ea9db39715199ea05eafe124dbf74231d1e7e3d4 Mon Sep 17 00:00:00 2001 From: Joseph Date: Sat, 11 Apr 2020 22:25:44 +0100 Subject: Update bot/cogs/stats.py Co-Authored-By: Mark --- bot/cogs/stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/stats.py b/bot/cogs/stats.py index 772ae2c97..c15d0eb1b 100644 --- a/bot/cogs/stats.py +++ b/bot/cogs/stats.py @@ -36,7 +36,7 @@ class Stats(Cog): if CHANNEL_NAME_OVERRIDES.get(message.channel.id): reformatted_name = CHANNEL_NAME_OVERRIDES.get(message.channel.id) - reformatted_name = "".join([char for char in reformatted_name if char in ALLOWED_CHARS]) + reformatted_name = "".join(char for char in reformatted_name if char in ALLOWED_CHARS) stat_name = f"channels.{reformatted_name}" self.bot.stats.incr(stat_name) -- cgit v1.2.3 From 33c40ce2913e2a324647c4eb8f5c511cb26cf8ae Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 22:28:24 +0100 Subject: Use in for membership check as opposed to .get() --- bot/cogs/help_channels.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 01a77db2b..632c78701 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -466,7 +466,7 @@ class HelpChannels(Scheduler, commands.Cog): self.bot.stats.incr(f"help.dormant_calls.{caller}") - if self.claim_times.get(channel.id): + if channel.id in self.claim_times: claimed = self.claim_times[channel.id] in_use_time = datetime.now() - claimed self.bot.stats.timer("help.in_use_time", in_use_time) -- cgit v1.2.3 From 673869062ff49a74a2d2f8338c4d26003bee995e Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sat, 11 Apr 2020 22:44:13 +0100 Subject: Add a metric for tracking how long defcon was active --- bot/cogs/defcon.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/bot/cogs/defcon.py b/bot/cogs/defcon.py index 9197dcca3..7043c7cbb 100644 --- a/bot/cogs/defcon.py +++ b/bot/cogs/defcon.py @@ -126,6 +126,19 @@ class Defcon(Cog): async def _defcon_action(self, ctx: Context, days: int, action: Action) -> None: """Providing a structured way to do an defcon action.""" + try: + response = await self.bot.api_client.get('bot/bot-settings/defcon') + data = response['data'] + + if "enable_date" in data and action is Action.DISABLED: + enabled = datetime.fromisoformat(data["enable_date"]) + + delta = datetime.now() - enabled + + self.bot.stats.timer("defcon.enabled", delta) + except Exception: + pass + error = None try: await self.bot.api_client.put( @@ -136,6 +149,7 @@ class Defcon(Cog): # TODO: retrieve old days count 'days': days, 'enabled': action is not Action.DISABLED, + 'enable_date': datetime.now().isoformat() } } ) @@ -146,7 +160,7 @@ class Defcon(Cog): await ctx.send(self.build_defcon_msg(action, error)) await self.send_defcon_log(action, ctx.author, error) - self.bot.stats.gauge("defcon.days", days) + self.bot.stats.gauge("defcon.threshold", days) @defcon_group.command(name='enable', aliases=('on', 'e')) @with_role(Roles.admins, Roles.owners) -- cgit v1.2.3 From 4adcb0b0ab2b8768e31043429bdfcbf4dab607e6 Mon Sep 17 00:00:00 2001 From: Joseph Banks Date: Sun, 12 Apr 2020 00:09:53 +0100 Subject: Address aeros' review comment regarding help channel stat reporting --- bot/cogs/help_channels.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot/cogs/help_channels.py b/bot/cogs/help_channels.py index 632c78701..d260a6a33 100644 --- a/bot/cogs/help_channels.py +++ b/bot/cogs/help_channels.py @@ -374,9 +374,9 @@ class HelpChannels(Scheduler, commands.Cog): def report_stats(self) -> None: """Report the channel count stats.""" - total_in_use = len(list(self.get_category_channels(self.in_use_category))) - total_available = len(list(self.get_category_channels(self.available_category))) - total_dormant = len(list(self.get_category_channels(self.dormant_category))) + total_in_use = sum(1 for _ in self.get_category_channels(self.in_use_category)) + total_available = sum(1 for _ in self.get_category_channels(self.available_category)) + total_dormant = sum(1 for _ in self.get_category_channels(self.dormant_category)) self.bot.stats.gauge("help.total.in_use", total_in_use) self.bot.stats.gauge("help.total.available", total_available) -- cgit v1.2.3