diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py index db686a26d..89b87f80a 100644 --- a/discord/ext/commands/converter.py +++ b/discord/ext/commands/converter.py @@ -449,29 +449,76 @@ class ColourConverter(Converter): - ``0x`` - ``#`` - ``0x#`` + - ``rgb(, , )`` - Any of the ``classmethod`` in :class:`Colour` - The ``_`` in the name can be optionally replaced with spaces. + Like CSS, ```` can be either 0-255 or 0-100% and ```` can be + either a 6 digit hex number or a 3 digit hex shortcut (e.g. #fff). + .. versionchanged:: 1.5 Raise :exc:`.BadColourArgument` instead of generic :exc:`.BadArgument` + + .. versionchanged:: 1.7 + Added support for ``rgb`` function and 3-digit hex shortcuts """ - async def convert(self, ctx, argument): - arg = argument.replace('0x', '').lower() - if arg[0] == '#': - arg = arg[1:] + RGB_REGEX = re.compile(r'rgb\s*\((?P[0-9]{1,3}%?)\s*,\s*(?P[0-9]{1,3}%?)\s*,\s*(?P[0-9]{1,3}%?)\s*\)') + + def parse_hex_number(self, argument): + arg = ''.join(i * 2 for i in argument) if len(argument) == 3 else argument try: value = int(arg, base=16) if not (0 <= value <= 0xFFFFFF): - raise BadColourArgument(arg) - return discord.Colour(value=value) + raise BadColourArgument(argument) except ValueError: - arg = arg.replace(' ', '_') - method = getattr(discord.Colour, arg, None) - if arg.startswith('from_') or method is None or not inspect.ismethod(method): - raise BadColourArgument(arg) - return method() + raise BadColourArgument(argument) + else: + return discord.Color(value=value) + + def parse_rgb_number(self, argument, number): + if number[-1] == '%': + value = int(number[:-1]) + if not (0 <= value <= 100): + raise BadColourArgument(argument) + return round(255 * (value / 100)) + + value = int(number) + if not (0 <= value <= 255): + raise BadColourArgument(argument) + return value + + def parse_rgb(self, argument, *, regex=RGB_REGEX): + match = regex.match(argument) + if match is None: + raise BadColourArgument(argument) + + red = self.parse_rgb_number(argument, match.group('r')) + green = self.parse_rgb_number(argument, match.group('g')) + blue = self.parse_rgb_number(argument, match.group('b')) + return discord.Color.from_rgb(red, green, blue) + + async def convert(self, ctx, argument): + if argument[0] == '#': + return self.parse_hex_number(argument[1:]) + + if argument[0:2] == '0x': + rest = argument[2:] + # Legacy backwards compatible syntax + if rest.startswith('#'): + return self.parse_hex_number(rest[1:]) + return self.parse_hex_number(rest) + + arg = argument.lower() + if arg[0:3] == 'rgb': + return self.parse_rgb(arg) + + arg = arg.replace(' ', '_') + method = getattr(discord.Colour, arg, None) + if arg.startswith('from_') or method is None or not inspect.ismethod(method): + raise BadColourArgument(arg) + return method() ColorConverter = ColourConverter