From b3ad47a507ef03fdf3a1dffb56d92d6d4f627c87 Mon Sep 17 00:00:00 2001 From: F4zii Date: Tue, 18 Feb 2020 17:33:07 +0200 Subject: [PATCH 01/28] Feature: suggest command usage for misspelt commands --- bot/cogs/tags.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 54a51921c9..5f7c810b81 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -12,6 +12,8 @@ from bot.decorators import with_role from bot.pagination import LinePaginator +from fuzzywuzzy import process + log = logging.getLogger(__name__) TEST_CHANNELS = ( @@ -138,6 +140,23 @@ def _command_on_cooldown(tag_name: str) -> bool: title='Did you mean ...', description='\n'.join(tag['title'] for tag in founds[:10]) )) + else: + # No similar tag found, searching for a similar command + command_name = ctx.invoked_with + raw_commands = [cmd.name for cmd in self.bot.walk_commands()] + similar_command_data = process.extractOne(command_name, raw_commands) + # The match is not very similar, no need to suggest it + log.debug(similar_command_data) + if similar_command_data[1] < 65: + log.debug("No similar commands found") + return + similar_command = self.bot.get_command(similar_command_data[0]) + if similar_command.can_run(ctx): + misspelled_content = ctx.message.content + await ctx.send( + f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command.name)}**" + ) + return else: tags = self._cache.values() From dfe9dd8c4972e1a9e7cab1af0f0e33c44871893d Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 20:39:32 +0200 Subject: [PATCH 02/28] Seperated tags.get_command into a function and a wrapper Updated --- bot/cogs/tags.py | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 5f7c810b81..61cf55d653 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -12,8 +12,6 @@ from bot.decorators import with_role from bot.pagination import LinePaginator -from fuzzywuzzy import process - log = logging.getLogger(__name__) TEST_CHANNELS = ( @@ -94,9 +92,9 @@ async def tags_group(self, ctx: Context, *, tag_name: TagNameConverter = None) - """Show all known tags, a single tag, or run a subcommand.""" await ctx.invoke(self.get_command, tag_name=tag_name) - @tags_group.command(name='get', aliases=('show', 'g')) - async def get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: - """Get a specified tag, or a list of all tags if no tag is specified.""" + async def _get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: + log.debug(self, ctx, tag_name) + def _command_on_cooldown(tag_name: str) -> bool: """ Check if the command is currently on cooldown, on a per-tag, per-channel basis. @@ -120,7 +118,7 @@ def _command_on_cooldown(tag_name: str) -> bool: time_left = Cooldowns.tags - (time.time() - self.tag_cooldowns[tag_name]["time"]) log.warning(f"{ctx.author} tried to get the '{tag_name}' tag, but the tag is on cooldown. " f"Cooldown ends in {time_left:.1f} seconds.") - return + return False await self._get_tags() @@ -135,28 +133,13 @@ def _command_on_cooldown(tag_name: str) -> bool: "channel": ctx.channel.id } await ctx.send(embed=Embed.from_dict(tag['embed'])) + return True elif founds and len(tag_name) >= 3: await ctx.send(embed=Embed( title='Did you mean ...', description='\n'.join(tag['title'] for tag in founds[:10]) )) - else: - # No similar tag found, searching for a similar command - command_name = ctx.invoked_with - raw_commands = [cmd.name for cmd in self.bot.walk_commands()] - similar_command_data = process.extractOne(command_name, raw_commands) - # The match is not very similar, no need to suggest it - log.debug(similar_command_data) - if similar_command_data[1] < 65: - log.debug("No similar commands found") - return - similar_command = self.bot.get_command(similar_command_data[0]) - if similar_command.can_run(ctx): - misspelled_content = ctx.message.content - await ctx.send( - f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command.name)}**" - ) - return + return True else: tags = self._cache.values() @@ -165,6 +148,7 @@ def _command_on_cooldown(tag_name: str) -> bool: description="**There are no tags in the database!**", colour=Colour.red() )) + return True else: embed: Embed = Embed(title="**Current tags**") await LinePaginator.paginate( @@ -175,6 +159,14 @@ def _command_on_cooldown(tag_name: str) -> bool: empty=False, max_lines=15 ) + return True + + return False + + @tags_group.command(name='get', aliases=('show', 'g')) + async def get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: + """Get a specified tag, or a list of all tags if no tag is specified.""" + await self._get_command(ctx, tag_name) @tags_group.command(name='set', aliases=('add', 's')) @with_role(*MODERATION_ROLES) From eb01f3f54a4a3c77f927769883af7d18efb8931c Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 20:40:25 +0200 Subject: [PATCH 03/28] Feature: suggest command usage for misspelt commands Migration to error_handler.py Suggesting misspelt commands, in progress --- bot/cogs/error_handler.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 52893b2ee4..13221799bd 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -1,4 +1,5 @@ -import contextlib +# import contextlib +import difflib import logging from discord.ext.commands import ( @@ -75,7 +76,7 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: if not ctx.channel.id == Channels.verification: tags_get_command = self.bot.get_command("tags get") ctx.invoked_from_error_handler = True - + command_name = ctx.invoked_with log_msg = "Cancelling attempt to fall back to a tag due to failed checks." try: if not await tags_get_command.can_run(ctx): @@ -87,9 +88,31 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: return # Return to not raise the exception - with contextlib.suppress(ResponseCodeError): - await ctx.invoke(tags_get_command, tag_name=ctx.invoked_with) + log.debug("Calling...") + tags_cog = self.bot.get_cog("Tags") + sent = await tags_cog._get_command(ctx, command_name) + # sent = await tags_get_command.callback(tags_get_command.cog, ctx, ctx.invoked_with) + if sent: + log.debug("Found") return + # No similar tag found, or tag on cooldown - + # searching for a similar command + log.debug("Not Found") + raw_commands = [ + (cmd.name, *cmd.aliases) + for cmd in self.bot.walk_commands() + if not cmd.hidden + ] + raw_commands = [c for data in raw_commands for c in data] + similar_command_data = difflib.get_close_matches(command_name, raw_commands, 1) + log.debug(similar_command_data) + similar_command = self.bot.get_command(similar_command_data[0]) + if similar_command.can_run(ctx): + misspelled_content = ctx.message.content + await ctx.send( + f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command.name)}**" + ) + elif isinstance(e, BadArgument): await ctx.send(f"Bad argument: {e}\n") await ctx.invoke(*help_command) From f192e02d5c3c1511107e683aac22235825a33806 Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 21:02:55 +0200 Subject: [PATCH 04/28] Deletion of the consuming rest (*) used in _get_command Since its used to get the input of the command, its not needed again In the function (callback) call --- bot/cogs/tags.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 61cf55d653..65d25124a6 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -92,8 +92,7 @@ async def tags_group(self, ctx: Context, *, tag_name: TagNameConverter = None) - """Show all known tags, a single tag, or run a subcommand.""" await ctx.invoke(self.get_command, tag_name=tag_name) - async def _get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: - log.debug(self, ctx, tag_name) + async def _get_command(self, ctx: Context, tag_name: TagNameConverter = None) -> None: def _command_on_cooldown(tag_name: str) -> bool: """ From 8599c68ce7544520d50419ba9afe0f2b0b6fc63e Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 21:03:45 +0200 Subject: [PATCH 05/28] Delete_after added for suggestion message preventing message spam by the bot when commands are misspelt --- bot/cogs/error_handler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 13221799bd..1a1914b932 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -110,7 +110,8 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: if similar_command.can_run(ctx): misspelled_content = ctx.message.content await ctx.send( - f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command.name)}**" + f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command.name)}**", + delete_after=7.0 ) elif isinstance(e, BadArgument): From 1625c18265192e9560b443a574e564241b6f6883 Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 21:12:49 +0200 Subject: [PATCH 06/28] Suggest aliases when invoked instead of full command name When found a similar command, the bot sent a suggestion about the full command name This was fixed by saving the matching alias and sending it instead of sending the full command name --- bot/cogs/error_handler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 1a1914b932..fb5f59ebc8 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -105,12 +105,12 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: ] raw_commands = [c for data in raw_commands for c in data] similar_command_data = difflib.get_close_matches(command_name, raw_commands, 1) - log.debug(similar_command_data) - similar_command = self.bot.get_command(similar_command_data[0]) + similar_command_name = similar_command_data[0] + similar_command = self.bot.get_command(similar_command_name) if similar_command.can_run(ctx): misspelled_content = ctx.message.content await ctx.send( - f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command.name)}**", + f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command_name)}**", delete_after=7.0 ) From 21a3486b21e4f28bdfad24d7ebfa7e88b24a3140 Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 21:20:39 +0200 Subject: [PATCH 07/28] Removal of unused logs --- bot/cogs/error_handler.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index fb5f59ebc8..ba27d8e652 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -88,16 +88,13 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: return # Return to not raise the exception - log.debug("Calling...") tags_cog = self.bot.get_cog("Tags") sent = await tags_cog._get_command(ctx, command_name) # sent = await tags_get_command.callback(tags_get_command.cog, ctx, ctx.invoked_with) if sent: - log.debug("Found") return # No similar tag found, or tag on cooldown - # searching for a similar command - log.debug("Not Found") raw_commands = [ (cmd.name, *cmd.aliases) for cmd in self.bot.walk_commands() From 337374ed2b3e10db6f34f378a73cc6d7c0d1f73f Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 23:18:24 +0200 Subject: [PATCH 08/28] Rearrange, exception and NoneTypes handling --- bot/cogs/error_handler.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index ba27d8e652..56294e8f9a 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -1,4 +1,4 @@ -# import contextlib +import contextlib import difflib import logging @@ -74,9 +74,13 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: # Try to look for a tag with the command's name if the command isn't found. if isinstance(e, CommandNotFound) and not hasattr(ctx, "invoked_from_error_handler"): if not ctx.channel.id == Channels.verification: + command_name = ctx.invoked_with tags_get_command = self.bot.get_command("tags get") + tags_cog = self.bot.get_cog("Tags") + if not all(tags_cog, tags_get_command): + return + ctx.invoked_from_error_handler = True - command_name = ctx.invoked_with log_msg = "Cancelling attempt to fall back to a tag due to failed checks." try: if not await tags_get_command.can_run(ctx): @@ -87,12 +91,10 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: await self.on_command_error(ctx, tag_error) return - # Return to not raise the exception - tags_cog = self.bot.get_cog("Tags") - sent = await tags_cog._get_command(ctx, command_name) - # sent = await tags_get_command.callback(tags_get_command.cog, ctx, ctx.invoked_with) + sent = await tags_cog.get_command(ctx, command_name) if sent: return + # No similar tag found, or tag on cooldown - # searching for a similar command raw_commands = [ @@ -104,12 +106,14 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: similar_command_data = difflib.get_close_matches(command_name, raw_commands, 1) similar_command_name = similar_command_data[0] similar_command = self.bot.get_command(similar_command_name) - if similar_command.can_run(ctx): - misspelled_content = ctx.message.content - await ctx.send( - f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command_name)}**", - delete_after=7.0 - ) + + with contextlib.suppress(CommandError): + if similar_command.can_run(ctx): + misspelled_content = ctx.message.content + await ctx.send( + f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command_name)}**", + delete_after=7.0 + ) elif isinstance(e, BadArgument): await ctx.send(f"Bad argument: {e}\n") From e570b2960839e696a5f57a7acdd968d766894cf4 Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 23:19:05 +0200 Subject: [PATCH 09/28] Rearrange, Function naming and Docstrings --- bot/cogs/tags.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 65d25124a6..4ee40a7e30 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -92,7 +92,18 @@ async def tags_group(self, ctx: Context, *, tag_name: TagNameConverter = None) - """Show all known tags, a single tag, or run a subcommand.""" await ctx.invoke(self.get_command, tag_name=tag_name) - async def _get_command(self, ctx: Context, tag_name: TagNameConverter = None) -> None: + async def get_command(self, ctx: Context, tag_name: str = None) -> bool: + """ + Shows a specific tag or a suggestion within a given context. + + params: + ctx - a Context object , being used to send and choose the right tag + tag_name - a string representing the searched tag name + + Returns False if no tag is not found or the tag is on cooldown + + Return True if found and sent a tag + """ def _command_on_cooldown(tag_name: str) -> bool: """ @@ -160,12 +171,12 @@ def _command_on_cooldown(tag_name: str) -> bool: ) return True - return False + return True @tags_group.command(name='get', aliases=('show', 'g')) - async def get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: - """Get a specified tag, or a list of all tags if no tag is specified.""" - await self._get_command(ctx, tag_name) + async def _get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: + """Get a specified tag, or a list of related tags if no tag is specified.""" + await self.get_command(ctx, tag_name) @tags_group.command(name='set', aliases=('add', 's')) @with_role(*MODERATION_ROLES) From 72be687ccad32558f7bafeb81813b1272d5b472b Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 23:48:25 +0200 Subject: [PATCH 10/28] Rearrange, NoneTypes handling --- bot/cogs/error_handler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 56294e8f9a..cf514e5c6f 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -74,13 +74,13 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: # Try to look for a tag with the command's name if the command isn't found. if isinstance(e, CommandNotFound) and not hasattr(ctx, "invoked_from_error_handler"): if not ctx.channel.id == Channels.verification: - command_name = ctx.invoked_with - tags_get_command = self.bot.get_command("tags get") tags_cog = self.bot.get_cog("Tags") - if not all(tags_cog, tags_get_command): + tags_get_command = self.bot.get_command("tags get") + if not tags_cog and not tags_get_command: return ctx.invoked_from_error_handler = True + command_name = ctx.invoked_with log_msg = "Cancelling attempt to fall back to a tag due to failed checks." try: if not await tags_get_command.can_run(ctx): From 4ebefe42aca23532233136b0fd51e4ef9633d593 Mon Sep 17 00:00:00 2001 From: F4zii Date: Wed, 19 Feb 2020 23:50:49 +0200 Subject: [PATCH 11/28] Return Logic Fixed The returned value was changed from True to False If we didn't return True (sent the tag) throughout the code It means we didn't send anything, we should return False --- bot/cogs/tags.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 4ee40a7e30..8082a5fb7f 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -101,7 +101,6 @@ async def get_command(self, ctx: Context, tag_name: str = None) -> bool: tag_name - a string representing the searched tag name Returns False if no tag is not found or the tag is on cooldown - Return True if found and sent a tag """ @@ -171,7 +170,7 @@ def _command_on_cooldown(tag_name: str) -> bool: ) return True - return True + return False @tags_group.command(name='get', aliases=('show', 'g')) async def _get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: From aceeba62363a9e2166bd8d3c897ffefdac9923bf Mon Sep 17 00:00:00 2001 From: F4zii Date: Thu, 20 Feb 2020 07:35:06 +0200 Subject: [PATCH 12/28] Rearrange - Function naming and Docstrings --- bot/cogs/error_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index cf514e5c6f..a951dc712a 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -91,7 +91,7 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: await self.on_command_error(ctx, tag_error) return - sent = await tags_cog.get_command(ctx, command_name) + sent = await tags_cog.display_tag(ctx, command_name) if sent: return From d0c3a0795c2490b7525646982c8d7d2b3c6dd755 Mon Sep 17 00:00:00 2001 From: F4zii Date: Thu, 20 Feb 2020 07:39:39 +0200 Subject: [PATCH 13/28] Rearrange - Function naming and Docstrings get_command was changed to - display_tag, the name didn't fit, since its not the command itself. command_on_cooldown was taken out of display_tag to get the option to reuse it in another scope Docstrings modified --- Pipfile.lock | 134 ++++++++++++++++++++--------------------------- bot/cogs/tags.py | 52 +++++++++--------- 2 files changed, 81 insertions(+), 105 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index bf8ff47e94..9e09260f1a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -18,11 +18,11 @@ "default": { "aio-pika": { "hashes": [ - "sha256:a5837277e53755078db3a9e8c45bbca605c8ba9ecba7a02d74a7a1779f444723", - "sha256:fa32e33b4b7d0804dcf439ae6ff24d2f0a83d1ba280ee9f555e647d71d394ff5" + "sha256:4199122a450dffd8303b7857a9d82657bf1487fe329e489520833b40fbe92406", + "sha256:fe85c7456e5c060bce4eb9cffab5b2c4d3c563cb72177977b3556c54c8e3aeb6" ], "index": "pypi", - "version": "==6.4.1" + "version": "==6.5.2" }, "aiodns": { "hashes": [ @@ -52,10 +52,10 @@ }, "aiormq": { "hashes": [ - "sha256:8c215a970133ab5ee7c478decac55b209af7731050f52d11439fe910fa0f9e9d", - "sha256:9210f3389200aee7d8067f6435f4a9eff2d3a30b88beb5eaae406ccc11c0fc01" + "sha256:286e0b0772075580466e45f98f051b9728a9316b9c36f0c14c7bc1409be375b0", + "sha256:7ed7d6df6b57af7f8bce7d1ebcbdfc32b676192e46703e81e9e217316e56b5bd" ], - "version": "==3.2.0" + "version": "==3.2.1" }, "alabaster": { "hashes": [ @@ -164,18 +164,18 @@ }, "fuzzywuzzy": { "hashes": [ - "sha256:5ac7c0b3f4658d2743aa17da53a55598144edbc5bee3c6863840636e6926f254", - "sha256:6f49de47db00e1c71d40ad16da42284ac357936fa9b66bea1df63fed07122d62" + "sha256:45016e92264780e58972dca1b3d939ac864b78437422beecebb3095f8efd00e8", + "sha256:928244b28db720d1e0ee7587acf660ea49d7e4c632569cad4f1cd7e68a5f0993" ], "index": "pypi", - "version": "==0.17.0" + "version": "==0.18.0" }, "idna": { "hashes": [ - "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", - "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", + "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" ], - "version": "==2.8" + "version": "==2.9" }, "imagesize": { "hashes": [ @@ -420,11 +420,11 @@ }, "requests": { "hashes": [ - "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", - "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", + "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" ], "index": "pypi", - "version": "==2.22.0" + "version": "==2.23.0" }, "six": { "hashes": [ @@ -449,11 +449,11 @@ }, "sphinx": { "hashes": [ - "sha256:298537cb3234578b2d954ff18c5608468229e116a9757af3b831c2b2b4819159", - "sha256:e6e766b74f85f37a5f3e0773a1e1be8db3fcb799deb58ca6d18b70b0b44542a5" + "sha256:525527074f2e0c2585f68f73c99b4dc257c34bbe308b27f5f8c7a6e20642742f", + "sha256:543d39db5f82d83a5c1aa0c10c88f2b6cff2da3e711aa849b2c627b4b403bbd9" ], "index": "pypi", - "version": "==2.3.1" + "version": "==2.4.2" }, "sphinxcontrib-applehelp": { "hashes": [ @@ -556,6 +556,13 @@ } }, "develop": { + "appdirs": { + "hashes": [ + "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", + "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" + ], + "version": "==1.4.3" + }, "aspy.yaml": { "hashes": [ "sha256:463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc", @@ -579,10 +586,10 @@ }, "cfgv": { "hashes": [ - "sha256:edb387943b665bf9c434f717bf630fa78aecd53d5900d2e05da6ad6048553144", - "sha256:fbd93c9ab0a523bf7daec408f3be2ed99a980e20b2d19b50fc184ca6b820d289" + "sha256:04b093b14ddf9fd4d17c53ebfd55582d27b76ed30050193c14e560770c5360eb", + "sha256:f22b426ed59cd2ab2b54ff96608d846c33dfb8766a67f0b4a6ce130ce244414f" ], - "version": "==2.0.1" + "version": "==3.0.0" }, "chardet": { "hashes": [ @@ -636,6 +643,12 @@ "index": "pypi", "version": "==4.5.4" }, + "distlib": { + "hashes": [ + "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21" + ], + "version": "==0.3.0" + }, "dodgy": { "hashes": [ "sha256:28323cbfc9352139fdd3d316fa17f325cc0e9ac74438cbba51d70f9b48f86c3a", @@ -658,6 +671,13 @@ ], "version": "==0.3" }, + "filelock": { + "hashes": [ + "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", + "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" + ], + "version": "==3.0.12" + }, "flake8": { "hashes": [ "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", @@ -668,11 +688,11 @@ }, "flake8-annotations": { "hashes": [ - "sha256:05b85538014c850a86dce7374bb6621c64481c24e35e8e90af1315f4d7a3dbaa", - "sha256:43e5233a76fda002b91a54a7cc4510f099c4bfd6279502ec70164016250eebd1" + "sha256:47705be09c6e56e9e3ac1656e8f5ed70862a4657116dc472f5a56c1bdc5172b1", + "sha256:564702ace354e1059252755be79d082a70ae1851c86044ae1a96d0f5453280e9" ], "index": "pypi", - "version": "==1.1.3" + "version": "==1.2.0" }, "flake8-bugbear": { "hashes": [ @@ -700,11 +720,11 @@ }, "flake8-string-format": { "hashes": [ - "sha256:68ea72a1a5b75e7018cae44d14f32473c798cf73d75cbaed86c6a9a907b770b2", - "sha256:774d56103d9242ed968897455ef49b7d6de272000cfa83de5814273a868832f1" + "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2", + "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af" ], "index": "pypi", - "version": "==0.2.3" + "version": "==0.3.0" }, "flake8-tidy-imports": { "hashes": [ @@ -730,18 +750,10 @@ }, "idna": { "hashes": [ - "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", - "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", + "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" ], - "version": "==2.8" - }, - "importlib-metadata": { - "hashes": [ - "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302", - "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b" - ], - "markers": "python_version < '3.8'", - "version": "==1.5.0" + "version": "==2.9" }, "mccabe": { "hashes": [ @@ -818,11 +830,11 @@ }, "requests": { "hashes": [ - "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", - "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", + "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" ], "index": "pypi", - "version": "==2.22.0" + "version": "==2.23.0" }, "safety": { "hashes": [ @@ -853,33 +865,6 @@ ], "version": "==0.10.0" }, - "typed-ast": { - "hashes": [ - "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", - "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", - "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", - "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", - "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", - "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", - "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", - "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", - "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", - "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", - "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", - "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", - "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", - "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", - "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", - "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", - "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", - "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", - "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", - "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", - "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" - ], - "markers": "python_version < '3.8'", - "version": "==1.4.1" - }, "unittest-xml-reporting": { "hashes": [ "sha256:358bbdaf24a26d904cc1c26ef3078bca7fc81541e0a54c8961693cc96a6f35e0", @@ -898,17 +883,10 @@ }, "virtualenv": { "hashes": [ - "sha256:0d62c70883c0342d59c11d0ddac0d954d0431321a41ab20851facf2b222598f3", - "sha256:55059a7a676e4e19498f1aad09b8313a38fcc0cdbe4fdddc0e9b06946d21b4bb" - ], - "version": "==16.7.9" - }, - "zipp": { - "hashes": [ - "sha256:ccc94ed0909b58ffe34430ea5451f07bc0c76467d7081619a454bf5c98b89e28", - "sha256:feae2f18633c32fc71f2de629bfb3bd3c9325cd4419642b1f1da42ee488d9b98" + "sha256:08f3623597ce73b85d6854fb26608a6f39ee9d055c81178dc6583803797f8994", + "sha256:de2cbdd5926c48d7b84e0300dea9e8f276f61d186e8e49223d71d91250fbaebd" ], - "version": "==2.1.0" + "version": "==20.0.4" } } } diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 8082a5fb7f..5124fb5e73 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -92,38 +92,36 @@ async def tags_group(self, ctx: Context, *, tag_name: TagNameConverter = None) - """Show all known tags, a single tag, or run a subcommand.""" await ctx.invoke(self.get_command, tag_name=tag_name) - async def get_command(self, ctx: Context, tag_name: str = None) -> bool: + def command_on_cooldown(self, ctx: Context, tag_name: str) -> bool: """ - Shows a specific tag or a suggestion within a given context. + Check if the command is currently on cooldown, on a per-tag, per-channel basis. - params: - ctx - a Context object , being used to send and choose the right tag - tag_name - a string representing the searched tag name - - Returns False if no tag is not found or the tag is on cooldown - Return True if found and sent a tag + The cooldown duration is set in constants.py. """ + now = time.time() - def _command_on_cooldown(tag_name: str) -> bool: - """ - Check if the command is currently on cooldown, on a per-tag, per-channel basis. + cooldown_conditions = ( + tag_name + and tag_name in self.tag_cooldowns + and (now - self.tag_cooldowns[tag_name]["time"]) < Cooldowns.tags + and self.tag_cooldowns[tag_name]["channel"] == ctx.channel.id + ) - The cooldown duration is set in constants.py. - """ - now = time.time() + if cooldown_conditions: + return True + return False - cooldown_conditions = ( - tag_name - and tag_name in self.tag_cooldowns - and (now - self.tag_cooldowns[tag_name]["time"]) < Cooldowns.tags - and self.tag_cooldowns[tag_name]["channel"] == ctx.channel.id - ) + async def display_tag(self, ctx: Context, tag_name: str = None) -> bool: + """ + Show contents of the tag `tag_name` in `ctx` and return True if something is shown. - if cooldown_conditions: - return True - return False + If a tag is not found, display similar tag names as suggestions. If a tag is not specified, + display a paginated embed of all tags. - if _command_on_cooldown(tag_name): + Tags are on cooldowns on a per-tag, per-channel basis. If a tag is on cooldown, display + nothing and return False. + """ + if self.command_on_cooldown(ctx, tag_name): time_left = Cooldowns.tags - (time.time() - self.tag_cooldowns[tag_name]["time"]) log.warning(f"{ctx.author} tried to get the '{tag_name}' tag, but the tag is on cooldown. " f"Cooldown ends in {time_left:.1f} seconds.") @@ -173,9 +171,9 @@ def _command_on_cooldown(tag_name: str) -> bool: return False @tags_group.command(name='get', aliases=('show', 'g')) - async def _get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: - """Get a specified tag, or a list of related tags if no tag is specified.""" - await self.get_command(ctx, tag_name) + async def get_command(self, ctx: Context, *, tag_name: TagNameConverter = None) -> None: + """Get a specified tag, or a list of all tags if no tag is specified.""" + await self.display_tag(ctx, tag_name) @tags_group.command(name='set', aliases=('add', 's')) @with_role(*MODERATION_ROLES) From ec1ffabc926a3a6f368f024428aa57eefa925476 Mon Sep 17 00:00:00 2001 From: F4zi <44242259+F4zi780@users.noreply.github.com> Date: Thu, 20 Feb 2020 22:08:08 +0200 Subject: [PATCH 14/28] Command suggestion message reformat. The message sent when suggesting a command is now wrapped inside an embed --- bot/cogs/error_handler.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index a951dc712a..39b868e622 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -2,6 +2,7 @@ import difflib import logging +from discord import Embed from discord.ext.commands import ( BadArgument, BotMissingPermissions, @@ -19,7 +20,7 @@ from bot.api import ResponseCodeError from bot.bot import Bot -from bot.constants import Channels +from bot.constants import Channels, Icons from bot.decorators import InChannelCheckFailure log = logging.getLogger(__name__) @@ -110,8 +111,11 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: with contextlib.suppress(CommandError): if similar_command.can_run(ctx): misspelled_content = ctx.message.content + e = Embed() + e.set_author(name="Did you mean:", icon_url=Icons.questionmark) + e.description = f"{misspelled_content.replace(command_name, similar_command_name)}" await ctx.send( - f"Did you mean:\n**{misspelled_content.replace(command_name, similar_command_name)}**", + embed=e, delete_after=7.0 ) From 7fd9225d964ff90f972afd1e780ebb26df1a365c Mon Sep 17 00:00:00 2001 From: F4zii Date: Fri, 21 Feb 2020 21:10:00 +0200 Subject: [PATCH 15/28] Handling and logging CommandError the CommandError exception was ignored, We now catch the exception to handle and log the event Also added a little code reformat --- bot/cogs/error_handler.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 39b868e622..19d6e69462 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -108,16 +108,20 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: similar_command_name = similar_command_data[0] similar_command = self.bot.get_command(similar_command_name) - with contextlib.suppress(CommandError): - if similar_command.can_run(ctx): - misspelled_content = ctx.message.content - e = Embed() - e.set_author(name="Did you mean:", icon_url=Icons.questionmark) - e.description = f"{misspelled_content.replace(command_name, similar_command_name)}" - await ctx.send( - embed=e, - delete_after=7.0 - ) + log_msg = "Cancelling attempt to suggest a command due to failed checks." + try: + if not similar_command.can_run(ctx): + log.debug(log_msg) + return + except CommandError as cmd_error: + log.debug(log_msg) + await self.on_command_error(ctx, cmd_error) + + misspelled_content = ctx.message.content + e = Embed() + e.set_author(name="Did you mean:", icon_url=Icons.questionmark) + e.description = f"{misspelled_content.replace(command_name, similar_command_name)}" + await ctx.send(embed=e, delete_after=7.0) elif isinstance(e, BadArgument): await ctx.send(f"Bad argument: {e}\n") From 7eb1acd41bddf0377a3e211a87962e3af87be07e Mon Sep 17 00:00:00 2001 From: F4zii Date: Fri, 21 Feb 2020 21:11:14 +0200 Subject: [PATCH 16/28] Only replace the misspelt command, and not the whole occurrences of it --- bot/cogs/error_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 19d6e69462..a642c3b7ec 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -120,7 +120,7 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: misspelled_content = ctx.message.content e = Embed() e.set_author(name="Did you mean:", icon_url=Icons.questionmark) - e.description = f"{misspelled_content.replace(command_name, similar_command_name)}" + e.description = f"{misspelled_content.replace(command_name, similar_command_name, 1)}" await ctx.send(embed=e, delete_after=7.0) elif isinstance(e, BadArgument): From 093fb2c7a234dbea171f439871f082fcf432b524 Mon Sep 17 00:00:00 2001 From: F4zii Date: Sat, 22 Feb 2020 13:30:41 +0200 Subject: [PATCH 17/28] Handling CommandError and Optimization After CommandError was catched, the embed was sent, now we return after the exception was catched Modified the way raw_commands are collected --- bot/cogs/error_handler.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index a642c3b7ec..687eee9c7d 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -98,12 +98,10 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: # No similar tag found, or tag on cooldown - # searching for a similar command - raw_commands = [ - (cmd.name, *cmd.aliases) - for cmd in self.bot.walk_commands() - if not cmd.hidden - ] - raw_commands = [c for data in raw_commands for c in data] + raw_commands = [] + for cmd in self.bot.walk_commands(): + if not cmd.hidden: + raw_commands += (cmd.name, *cmd.aliases) similar_command_data = difflib.get_close_matches(command_name, raw_commands, 1) similar_command_name = similar_command_data[0] similar_command = self.bot.get_command(similar_command_name) @@ -116,6 +114,7 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: except CommandError as cmd_error: log.debug(log_msg) await self.on_command_error(ctx, cmd_error) + return misspelled_content = ctx.message.content e = Embed() From 5a6a5b6eef7d67901181b569b4cc5b298e06d807 Mon Sep 17 00:00:00 2001 From: F4zii Date: Sat, 22 Feb 2020 19:49:22 +0200 Subject: [PATCH 18/28] awaited can_run Coroutine --- bot/cogs/error_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 687eee9c7d..4b08546cc2 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -108,7 +108,7 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: log_msg = "Cancelling attempt to suggest a command due to failed checks." try: - if not similar_command.can_run(ctx): + if not await similar_command.can_run(ctx): log.debug(log_msg) return except CommandError as cmd_error: From bff2ea57578fde3a389e286bb9254c232a0123e4 Mon Sep 17 00:00:00 2001 From: F4zii Date: Sat, 22 Feb 2020 19:52:23 +0200 Subject: [PATCH 19/28] Return False (not sent) at the end of display_tag If the code ran to the last line of the function without returning (we return when we send a tag) It means we didn't send the tag and need to return False --- bot/cogs/tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index 5124fb5e73..e36761f85d 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -146,7 +146,7 @@ async def display_tag(self, ctx: Context, tag_name: str = None) -> bool: title='Did you mean ...', description='\n'.join(tag['title'] for tag in founds[:10]) )) - return True + return False else: tags = self._cache.values() From 53753f0c9e614789221aa5145511c0fce05d75ad Mon Sep 17 00:00:00 2001 From: F4zii Date: Sat, 22 Feb 2020 19:58:08 +0200 Subject: [PATCH 20/28] (display_tag) Return False if no tags were found. Since no tags were found, we can return false since we didn't send any matching tag --- bot/cogs/tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index e36761f85d..c3bc9861f0 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -155,7 +155,7 @@ async def display_tag(self, ctx: Context, tag_name: str = None) -> bool: description="**There are no tags in the database!**", colour=Colour.red() )) - return True + return False else: embed: Embed = Embed(title="**Current tags**") await LinePaginator.paginate( From de5360585451ea7e3a708eba3e8315906e6a9904 Mon Sep 17 00:00:00 2001 From: F4zii Date: Sat, 22 Feb 2020 22:20:30 +0200 Subject: [PATCH 21/28] Nontype handling Logic fix we cannot perform anything without the tags cog and commands --- bot/cogs/error_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/error_handler.py b/bot/cogs/error_handler.py index 5af5974cba..dab3102cfe 100644 --- a/bot/cogs/error_handler.py +++ b/bot/cogs/error_handler.py @@ -77,7 +77,7 @@ async def on_command_error(self, ctx: Context, e: CommandError) -> None: if not ctx.channel.id == Channels.verification: tags_cog = self.bot.get_cog("Tags") tags_get_command = self.bot.get_command("tags get") - if not tags_cog and not tags_get_command: + if not tags_cog or not tags_get_command: return ctx.invoked_from_error_handler = True From dc0bc87afb14f75037aa695dd6936bb061054a2d Mon Sep 17 00:00:00 2001 From: F4zii Date: Sat, 22 Feb 2020 22:22:13 +0200 Subject: [PATCH 22/28] Boolean Logic fix If we sent a message, we need to return True, the error_handler (in case it called the func) will not send another message if already sent one. --- bot/cogs/tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index c3bc9861f0..e36761f85d 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -155,7 +155,7 @@ async def display_tag(self, ctx: Context, tag_name: str = None) -> bool: description="**There are no tags in the database!**", colour=Colour.red() )) - return False + return True else: embed: Embed = Embed(title="**Current tags**") await LinePaginator.paginate( From 5f4b04b7a8631bd93627cdc61ed39bd998e15249 Mon Sep 17 00:00:00 2001 From: F4zii Date: Sat, 7 Mar 2020 09:33:36 +0200 Subject: [PATCH 23/28] Return True after a tag suggestion was sent After we send a tag or a suggestion we should return True for the error handler to know we handled the misspelt invoke --- bot/cogs/tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index e36761f85d..5124fb5e73 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -146,7 +146,7 @@ async def display_tag(self, ctx: Context, tag_name: str = None) -> bool: title='Did you mean ...', description='\n'.join(tag['title'] for tag in founds[:10]) )) - return False + return True else: tags = self._cache.values() From 34ef0991c9418ac04d9b6cf24a8381d9c4918540 Mon Sep 17 00:00:00 2001 From: Iddo Soreq <44242259+F4zii@users.noreply.github.com> Date: Sat, 7 Mar 2020 09:35:40 +0200 Subject: [PATCH 24/28] Update bot/cogs/tags.py, cleaner return logic Co-Authored-By: Shirayuki Nekomata --- bot/cogs/tags.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bot/cogs/tags.py b/bot/cogs/tags.py index e36761f85d..fdd7bb8ece 100644 --- a/bot/cogs/tags.py +++ b/bot/cogs/tags.py @@ -100,16 +100,14 @@ def command_on_cooldown(self, ctx: Context, tag_name: str) -> bool: """ now = time.time() - cooldown_conditions = ( + is_on_cooldown = ( tag_name and tag_name in self.tag_cooldowns and (now - self.tag_cooldowns[tag_name]["time"]) < Cooldowns.tags and self.tag_cooldowns[tag_name]["channel"] == ctx.channel.id ) - if cooldown_conditions: - return True - return False + return is_on_cooldown async def display_tag(self, ctx: Context, tag_name: str = None) -> bool: """ From 012f90ff552877c3fbfdd59216ab0adfc729ecd8 Mon Sep 17 00:00:00 2001 From: xithrius Date: Sat, 2 Jan 2021 20:54:48 -0800 Subject: [PATCH 25/28] Removed possibility of exception via walrus. --- bot/exts/backend/error_handler.py | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py index f3d8537bd5..fa3f706e61 100644 --- a/bot/exts/backend/error_handler.py +++ b/bot/exts/backend/error_handler.py @@ -177,25 +177,25 @@ async def send_command_suggestion(self, ctx: Context, command_name: str) -> None for cmd in self.bot.walk_commands(): if not cmd.hidden: raw_commands += (cmd.name, *cmd.aliases) - similar_command_data = difflib.get_close_matches(command_name, raw_commands, 1) - similar_command_name = similar_command_data[0] - similar_command = self.bot.get_command(similar_command_name) - - log_msg = "Cancelling attempt to suggest a command due to failed checks." - try: - if not await similar_command.can_run(ctx): + if similar_command_data := difflib.get_close_matches(command_name, raw_commands, 1): + similar_command_name = similar_command_data[0] + similar_command = self.bot.get_command(similar_command_name) + + log_msg = "Cancelling attempt to suggest a command due to failed checks." + try: + if not await similar_command.can_run(ctx): + log.debug(log_msg) + return + except errors.CommandError as cmd_error: log.debug(log_msg) + await self.on_command_error(ctx, cmd_error) return - except errors.CommandError as cmd_error: - log.debug(log_msg) - await self.on_command_error(ctx, cmd_error) - return - misspelled_content = ctx.message.content - e = Embed() - e.set_author(name="Did you mean:", icon_url=Icons.questionmark) - e.description = f"{misspelled_content.replace(command_name, similar_command_name, 1)}" - await ctx.send(embed=e, delete_after=10.0) + misspelled_content = ctx.message.content + e = Embed() + e.set_author(name="Did you mean:", icon_url=Icons.questionmark) + e.description = f"{misspelled_content.replace(command_name, similar_command_name, 1)}" + await ctx.send(embed=e, delete_after=10.0) async def handle_user_input_error(self, ctx: Context, e: errors.UserInputError) -> None: """ From 431afbfa48149d315d92c7c3ffb7974e5ae20618 Mon Sep 17 00:00:00 2001 From: xithrius Date: Tue, 5 Jan 2021 21:33:32 -0800 Subject: [PATCH 26/28] If user is a staff member, no command suggestions. --- bot/exts/backend/error_handler.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py index fa3f706e61..412c42df52 100644 --- a/bot/exts/backend/error_handler.py +++ b/bot/exts/backend/error_handler.py @@ -9,7 +9,7 @@ from bot.api import ResponseCodeError from bot.bot import Bot -from bot.constants import Channels, Colours, Icons +from bot.constants import Channels, Colours, Icons, STAFF_ROLES from bot.converters import TagNameConverter from bot.errors import LockedResourceError from bot.utils.checks import InWhitelistCheckFailure @@ -159,12 +159,13 @@ async def try_get_tag(self, ctx: Context) -> None: with contextlib.suppress(ResponseCodeError): await ctx.invoke(tags_get_command, tag_name=tag_name) - tags_cog = self.bot.get_cog("Tags") - command_name = ctx.invoked_with - sent = await tags_cog.display_tag(ctx, command_name) + if not any(role.id in STAFF_ROLES for role in ctx.author.roles): + tags_cog = self.bot.get_cog("Tags") + command_name = ctx.invoked_with + sent = await tags_cog.display_tag(ctx, command_name) - if not sent: - await self.send_command_suggestion(ctx, command_name) + if not sent: + await self.send_command_suggestion(ctx, command_name) # Return to not raise the exception return From 69ed1cc4742ec17b675d9323e46f30e028248106 Mon Sep 17 00:00:00 2001 From: xithrius Date: Wed, 6 Jan 2021 17:54:51 -0800 Subject: [PATCH 27/28] Only helpers and below now get command suggestions --- bot/exts/backend/error_handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py index 412c42df52..51fbac99bb 100644 --- a/bot/exts/backend/error_handler.py +++ b/bot/exts/backend/error_handler.py @@ -9,7 +9,7 @@ from bot.api import ResponseCodeError from bot.bot import Bot -from bot.constants import Channels, Colours, Icons, STAFF_ROLES +from bot.constants import Channels, Colours, Icons, MODERATION_ROLES from bot.converters import TagNameConverter from bot.errors import LockedResourceError from bot.utils.checks import InWhitelistCheckFailure @@ -159,7 +159,7 @@ async def try_get_tag(self, ctx: Context) -> None: with contextlib.suppress(ResponseCodeError): await ctx.invoke(tags_get_command, tag_name=tag_name) - if not any(role.id in STAFF_ROLES for role in ctx.author.roles): + if not any(role.id in MODERATION_ROLES for role in ctx.author.roles): tags_cog = self.bot.get_cog("Tags") command_name = ctx.invoked_with sent = await tags_cog.display_tag(ctx, command_name) From 491e0b93895d03a1985c2606d066c8ebd0ebd02d Mon Sep 17 00:00:00 2001 From: xithrius Date: Sat, 16 Jan 2021 16:36:10 -0800 Subject: [PATCH 28/28] Removed 'Channels' import, unused. --- bot/exts/backend/error_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py index 2402fa175a..14147398b3 100644 --- a/bot/exts/backend/error_handler.py +++ b/bot/exts/backend/error_handler.py @@ -9,7 +9,7 @@ from bot.api import ResponseCodeError from bot.bot import Bot -from bot.constants import Channels, Colours, Icons, MODERATION_ROLES +from bot.constants import Colours, Icons, MODERATION_ROLES from bot.converters import TagNameConverter from bot.errors import LockedResourceError from bot.utils.checks import InWhitelistCheckFailure