From 871a262ee37aa09c557b8543f18fd699b940c07f Mon Sep 17 00:00:00 2001 From: Rapptz Date: Tue, 6 Mar 2018 00:37:12 -0500 Subject: [PATCH] [commands] Add ability to have case insensitive commands. This is powered by a dict-like class for the people who want to opt-in to the performance downgrade for usability for majority English speaking users. Since it is slower than the regular dict due to the excessive calls to str.lower along with the possibilities of gotchas for other languages outside of English, this is kept as False for the default case. --- discord/ext/commands/bot.py | 4 ++++ discord/ext/commands/core.py | 25 ++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/discord/ext/commands/bot.py b/discord/ext/commands/bot.py index 678537151..9ef4143c7 100644 --- a/discord/ext/commands/bot.py +++ b/discord/ext/commands/bot.py @@ -947,6 +947,10 @@ class Bot(BotBase, discord.Client): multiple checks for the prefix should be used and the first one to match will be the invocation prefix. You can get this prefix via :attr:`.Context.prefix`. + case_insensitive: :class:`bool` + Whether the commands should be case insensitive. Defaults to ``False``. This + attribute does not carry over to groups. You must set it to every group if + you require group commands to be case insensitive as well. description : :class:`str` The content prefixed into the default help message. self_bot : :class:`bool` diff --git a/discord/ext/commands/core.py b/discord/ext/commands/core.py index ef4b238c8..927fe6fa6 100644 --- a/discord/ext/commands/core.py +++ b/discord/ext/commands/core.py @@ -83,6 +83,22 @@ def _convert_to_bool(argument): else: raise BadArgument(lowered + ' is not a recognised boolean option') +class _CaseInsensitiveDict(dict): + def __contains__(self, k): + return super().__contains__(k.lower()) + + def __delitem__(self, k): + return super().__delitem__(k.lower()) + + def __getitem__(self, k): + return super().__getitem__(k.lower()) + + def get(self, k, default=None): + return super().get(k.lower(), default) + + def __setitem__(self, k, v): + super().__setitem__(k.lower(), v) + class Command: """A class that implements the protocol for a bot text command. @@ -711,9 +727,13 @@ class GroupMixin: all_commands: :class:`dict` A mapping of command name to :class:`.Command` or superclass objects. + case_insensitive: :class:`bool` + Whether the commands should be case insensitive. Defaults to ``False``. """ def __init__(self, **kwargs): - self.all_commands = {} + case_insensitive = kwargs.get('case_insensitive', False) + self.all_commands = _CaseInsensitiveDict() if case_insensitive else {} + self.case_insensitive = case_insensitive super().__init__(**kwargs) @property @@ -875,6 +895,9 @@ class Group(GroupMixin, Command): the group callback will always be invoked first. This means that the checks and the parsing dictated by its parameters will be executed. Defaults to ``False``. + case_insensitive: :class:`bool` + Indicates if the group's commands should be case insensitive. + Defaults to ``False``. """ def __init__(self, **attrs): self.invoke_without_command = attrs.pop('invoke_without_command', False)