|
|
@ -449,29 +449,76 @@ class ColourConverter(Converter): |
|
|
|
- ``0x<hex>`` |
|
|
|
- ``#<hex>`` |
|
|
|
- ``0x#<hex>`` |
|
|
|
- ``rgb(<number>, <number>, <number>)`` |
|
|
|
- Any of the ``classmethod`` in :class:`Colour` |
|
|
|
|
|
|
|
- The ``_`` in the name can be optionally replaced with spaces. |
|
|
|
|
|
|
|
Like CSS, ``<number>`` can be either 0-255 or 0-100% and ``<hex>`` 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<r>[0-9]{1,3}%?)\s*,\s*(?P<g>[0-9]{1,3}%?)\s*,\s*(?P<b>[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 |
|
|
|
|
|
|
|