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)