From f4c983594db9dedbdadb9d7f13ff96e697d1520f Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sat, 19 Jun 2021 08:40:44 +0200 Subject: [PATCH 01/37] Added Colorpicker command --- general/__init__.py | 2 + general/color_picker/__init__.py | 1 + general/color_picker/cog.py | 63 ++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 general/color_picker/__init__.py create mode 100644 general/color_picker/cog.py diff --git a/general/__init__.py b/general/__init__.py index c012cf439..5d9134244 100644 --- a/general/__init__.py +++ b/general/__init__.py @@ -1,4 +1,5 @@ from .betheprofessional import BeTheProfessionalCog +from .color_picker import ColorPickerCog from .custom_commands import CustomCommandsCog from .discord_bot_token_deleter import DiscordBotTokenDeleterCog from .news import NewsCog @@ -12,6 +13,7 @@ __all__ = [ "BeTheProfessionalCog", + "ColorPickerCog", "CustomCommandsCog", "DiscordBotTokenDeleterCog", "NewsCog", diff --git a/general/color_picker/__init__.py b/general/color_picker/__init__.py new file mode 100644 index 000000000..644be5cb3 --- /dev/null +++ b/general/color_picker/__init__.py @@ -0,0 +1 @@ +from .cog import ColorPickerCog diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py new file mode 100644 index 000000000..059309a2c --- /dev/null +++ b/general/color_picker/cog.py @@ -0,0 +1,63 @@ +import colorsys +import io +import re + +from PIL import ImageColor, Image +from discord import Embed, Colour, File +from discord.ext import commands +from discord.ext.commands import Context + +from PyDrocsid.cog import Cog +from PyDrocsid.command import reply +from PyDrocsid.translations import t +from ...contributor import Contributor + +t = t.color_picker + + +class ColorPickerCog(Cog, name="Color Picker"): + CONTRIBUTORS = [Contributor.Tert0] + + RE_HEX = re.compile(r'^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$') + RE_RGB = re.compile(r'^rgb\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$') + RE_HSV = re.compile(r'^hsv\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$') + RE_HSL = re.compile(r'^hsl\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$') + + @commands.command(name="color_picker", aliases=["cp", "color"]) + async def color_picker(self, ctx: Context, *, color: str): + if color_re := self.RE_HEX.match(color): + color_hex = color_re.group(1) + rgb: tuple[int] = ImageColor.getcolor(color, "RGB") + hsv: tuple[int] = ImageColor.getcolor(color, "HSV") + hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 + elif color_re := self.RE_RGB.match(color): + rgb = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) + color_hex = '%02x%02x%02x' % rgb + hsv: tuple[int] = ImageColor.getcolor(f'#{color_hex}', "HSV") + hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 + elif color_re := self.RE_HSV.match(color): + hsv: tuple[int] = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) + rgb = tuple(map(int, colorsys.hsv_to_rgb(*hsv))) # skipcq: PYL-E1120 + color_hex = '%02x%02x%02x' % rgb + hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 + elif color_re := self.RE_HSL.match(color): + hsl: tuple[int] = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) + rgb = tuple(map(int, colorsys.hls_to_rgb(*hsl))) # skipcq: PYL-E1120 + hsv = tuple(map(int, colorsys.rgb_to_hsv(*rgb))) # skipcq: PYL-E1120 + color_hex = '%02x%02x%02x' % rgb + else: + embed: Embed = Embed(title=t.error_parse_color_title(color), + description=t.error_parse_color_example) + await reply(ctx, embed=embed) + return + img: Image = Image.new('RGB', (100, 100), rgb) + with io.BytesIO() as image_binary: + img.save(image_binary, 'PNG') + image_binary.seek(0) + embed: Embed = Embed(title='Color Picker', color=Colour(int(color_hex, 16))) + embed.add_field(name='HEX', value=f'#{color_hex}') + embed.add_field(name='RGB', value=f'rgb{rgb}') + embed.add_field(name='HSV', value=f'hsv{hsv}') + embed.add_field(name='HSL', value=f'hsl{hsl}') + embed.set_image(url="attachment://color.png") + await reply(ctx, embed=embed, file=File(fp=image_binary, filename='color.png')) From 0abe44b1461bf79eb3c2d4f9c31ee6cd110fae3f Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sat, 19 Jun 2021 08:41:01 +0200 Subject: [PATCH 02/37] Added Translations --- general/color_picker/translations/en.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 general/color_picker/translations/en.yml diff --git a/general/color_picker/translations/en.yml b/general/color_picker/translations/en.yml new file mode 100644 index 000000000..8d6ddd3e4 --- /dev/null +++ b/general/color_picker/translations/en.yml @@ -0,0 +1,12 @@ +error_parse_color_title: "Error cant parse HEX/RGB/HSV/HSL Color Code(\"{}\")" +error_parse_color_example: > + **Examples:** + - #fff + - #ffffff + - #000000 + - rgb(255, 0, 0) + - rgb(255, 255, 255) + - hsv(0, 0, 0) + - hsv(0, 0, 255) + - hsl(0, 106, 0) + - hsl(0, 191, 0) \ No newline at end of file From 39ca8140d676575efa51df8c7b608d8459f82112 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sat, 19 Jun 2021 08:47:22 +0200 Subject: [PATCH 03/37] Reformated wth black --- general/color_picker/cog.py | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 059309a2c..ba8e4acab 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -18,10 +18,10 @@ class ColorPickerCog(Cog, name="Color Picker"): CONTRIBUTORS = [Contributor.Tert0] - RE_HEX = re.compile(r'^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$') - RE_RGB = re.compile(r'^rgb\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$') - RE_HSV = re.compile(r'^hsv\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$') - RE_HSL = re.compile(r'^hsl\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$') + RE_HEX = re.compile(r"^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") + RE_RGB = re.compile(r"^rgb\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") + RE_HSV = re.compile(r"^hsv\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") + RE_HSL = re.compile(r"^hsl\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") @commands.command(name="color_picker", aliases=["cp", "color"]) async def color_picker(self, ctx: Context, *, color: str): @@ -32,32 +32,31 @@ async def color_picker(self, ctx: Context, *, color: str): hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 elif color_re := self.RE_RGB.match(color): rgb = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) - color_hex = '%02x%02x%02x' % rgb - hsv: tuple[int] = ImageColor.getcolor(f'#{color_hex}', "HSV") + color_hex = "%02x%02x%02x" % rgb + hsv: tuple[int] = ImageColor.getcolor(f"#{color_hex}", "HSV") hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 elif color_re := self.RE_HSV.match(color): hsv: tuple[int] = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) rgb = tuple(map(int, colorsys.hsv_to_rgb(*hsv))) # skipcq: PYL-E1120 - color_hex = '%02x%02x%02x' % rgb + color_hex = "%02x%02x%02x" % rgb hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 elif color_re := self.RE_HSL.match(color): hsl: tuple[int] = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) rgb = tuple(map(int, colorsys.hls_to_rgb(*hsl))) # skipcq: PYL-E1120 hsv = tuple(map(int, colorsys.rgb_to_hsv(*rgb))) # skipcq: PYL-E1120 - color_hex = '%02x%02x%02x' % rgb + color_hex = "%02x%02x%02x" % rgb else: - embed: Embed = Embed(title=t.error_parse_color_title(color), - description=t.error_parse_color_example) + embed: Embed = Embed(title=t.error_parse_color_title(color), description=t.error_parse_color_example) await reply(ctx, embed=embed) return - img: Image = Image.new('RGB', (100, 100), rgb) + img: Image = Image.new("RGB", (100, 100), rgb) with io.BytesIO() as image_binary: - img.save(image_binary, 'PNG') + img.save(image_binary, "PNG") image_binary.seek(0) - embed: Embed = Embed(title='Color Picker', color=Colour(int(color_hex, 16))) - embed.add_field(name='HEX', value=f'#{color_hex}') - embed.add_field(name='RGB', value=f'rgb{rgb}') - embed.add_field(name='HSV', value=f'hsv{hsv}') - embed.add_field(name='HSL', value=f'hsl{hsl}') + embed: Embed = Embed(title="Color Picker", color=Colour(int(color_hex, 16))) + embed.add_field(name="HEX", value=f"#{color_hex}") + embed.add_field(name="RGB", value=f"rgb{rgb}") + embed.add_field(name="HSV", value=f"hsv{hsv}") + embed.add_field(name="HSL", value=f"hsl{hsl}") embed.set_image(url="attachment://color.png") - await reply(ctx, embed=embed, file=File(fp=image_binary, filename='color.png')) + await reply(ctx, embed=embed, file=File(fp=image_binary, filename="color.png")) From ffddefca149fcbf897bfbfb983460ffcae5ab9ea Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Fri, 1 Oct 2021 13:30:33 +0200 Subject: [PATCH 04/37] Added _to_int function, improved type hints --- general/color_picker/cog.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index ba8e4acab..21b578347 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -1,6 +1,7 @@ import colorsys import io import re +from typing import Any from PIL import ImageColor, Image from discord import Embed, Colour, File @@ -25,25 +26,33 @@ class ColorPickerCog(Cog, name="Color Picker"): @commands.command(name="color_picker", aliases=["cp", "color"]) async def color_picker(self, ctx: Context, *, color: str): + def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: + return tuple(map(int, colors)) + + color_hex: str + rgb: tuple[int, ...] + hsv: tuple[int, ...] + hsl: tuple[int, ...] + if color_re := self.RE_HEX.match(color): color_hex = color_re.group(1) - rgb: tuple[int] = ImageColor.getcolor(color, "RGB") - hsv: tuple[int] = ImageColor.getcolor(color, "HSV") - hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 + rgb = ImageColor.getcolor(color, "RGB") + hsv = ImageColor.getcolor(color, "HSV") + hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_RGB.match(color): - rgb = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) + rgb = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) color_hex = "%02x%02x%02x" % rgb - hsv: tuple[int] = ImageColor.getcolor(f"#{color_hex}", "HSV") - hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 + hsv = ImageColor.getcolor(f"#{color_hex}", "HSV") + hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_HSV.match(color): - hsv: tuple[int] = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) - rgb = tuple(map(int, colorsys.hsv_to_rgb(*hsv))) # skipcq: PYL-E1120 + hsv = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) + rgb = _to_int(colorsys.hsv_to_rgb(*hsv)) color_hex = "%02x%02x%02x" % rgb - hsl = tuple(map(int, colorsys.rgb_to_hls(*rgb))) # skipcq: PYL-E1120 + hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_HSL.match(color): - hsl: tuple[int] = (int(color_re.group(1)), int(color_re.group(2)), int(color_re.group(3))) - rgb = tuple(map(int, colorsys.hls_to_rgb(*hsl))) # skipcq: PYL-E1120 - hsv = tuple(map(int, colorsys.rgb_to_hsv(*rgb))) # skipcq: PYL-E1120 + hsl = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) + rgb = _to_int(colorsys.hls_to_rgb(*hsl)) + hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) color_hex = "%02x%02x%02x" % rgb else: embed: Embed = Embed(title=t.error_parse_color_title(color), description=t.error_parse_color_example) From 4bf432ecf8d5232d884e0527c1688a2927425955 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Tue, 5 Oct 2021 19:29:22 +0200 Subject: [PATCH 05/37] Improved HEX Color Converter --- general/color_picker/cog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 21b578347..3979b41e3 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -41,19 +41,19 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_RGB.match(color): rgb = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) - color_hex = "%02x%02x%02x" % rgb + color_hex = "{:02x}{:02x}{:02x}".format(*rgb) hsv = ImageColor.getcolor(f"#{color_hex}", "HSV") hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_HSV.match(color): hsv = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) rgb = _to_int(colorsys.hsv_to_rgb(*hsv)) - color_hex = "%02x%02x%02x" % rgb + color_hex = "{:02x}{:02x}{:02x}".format(*rgb) hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_HSL.match(color): hsl = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) rgb = _to_int(colorsys.hls_to_rgb(*hsl)) hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) - color_hex = "%02x%02x%02x" % rgb + color_hex = "{:02x}{:02x}{:02x}".format(*rgb) else: embed: Embed = Embed(title=t.error_parse_color_title(color), description=t.error_parse_color_example) await reply(ctx, embed=embed) From 695dec8b46a999418f5873cf5858baa9766cf600 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Tue, 5 Oct 2021 20:01:33 +0200 Subject: [PATCH 06/37] Fixed PEP8 --- general/color_picker/cog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 3979b41e3..40c19c1bb 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -41,19 +41,19 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_RGB.match(color): rgb = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) - color_hex = "{:02x}{:02x}{:02x}".format(*rgb) + color_hex = "{0:02x}{1:02x}{2:02x}".format(*rgb) hsv = ImageColor.getcolor(f"#{color_hex}", "HSV") hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_HSV.match(color): hsv = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) rgb = _to_int(colorsys.hsv_to_rgb(*hsv)) - color_hex = "{:02x}{:02x}{:02x}".format(*rgb) + color_hex = "{0:02x}{1:02x}{2:02x}".format(*rgb) hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_HSL.match(color): hsl = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) rgb = _to_int(colorsys.hls_to_rgb(*hsl)) hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) - color_hex = "{:02x}{:02x}{:02x}".format(*rgb) + color_hex = "{0:02x}{1:02x}{2:02x}".format(*rgb) else: embed: Embed = Embed(title=t.error_parse_color_title(color), description=t.error_parse_color_example) await reply(ctx, embed=embed) From 0b436e343a15deee87e4cba1795034cdd2d89d94 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Tue, 5 Oct 2021 20:07:36 +0200 Subject: [PATCH 07/37] Added new Line --- general/color_picker/cog.py | 1 + 1 file changed, 1 insertion(+) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 40c19c1bb..af8de56b1 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -58,6 +58,7 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: embed: Embed = Embed(title=t.error_parse_color_title(color), description=t.error_parse_color_example) await reply(ctx, embed=embed) return + img: Image = Image.new("RGB", (100, 100), rgb) with io.BytesIO() as image_binary: img.save(image_binary, "PNG") From 107ded85f612ee4b4dabef3f641a07e2e2a7f418 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sat, 9 Oct 2021 11:22:35 +0200 Subject: [PATCH 08/37] Removed PIL, Added Color API, Better Error Message --- general/color_picker/cog.py | 34 +++++++++++------------- general/color_picker/translations/en.yml | 16 +++++------ 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index af8de56b1..a052dbd30 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -3,10 +3,9 @@ import re from typing import Any -from PIL import ImageColor, Image from discord import Embed, Colour, File from discord.ext import commands -from discord.ext.commands import Context +from discord.ext.commands import Context, CommandError from PyDrocsid.cog import Cog from PyDrocsid.command import reply @@ -34,15 +33,18 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: hsv: tuple[int, ...] hsl: tuple[int, ...] + def _hex_to_color(hex_color: str) -> tuple[int, ...]: + return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) + if color_re := self.RE_HEX.match(color): color_hex = color_re.group(1) - rgb = ImageColor.getcolor(color, "RGB") - hsv = ImageColor.getcolor(color, "HSV") + rgb = _hex_to_color(color_hex) + hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_RGB.match(color): rgb = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) color_hex = "{0:02x}{1:02x}{2:02x}".format(*rgb) - hsv = ImageColor.getcolor(f"#{color_hex}", "HSV") + hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) hsl = _to_int(colorsys.rgb_to_hls(*rgb)) elif color_re := self.RE_HSV.match(color): hsv = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) @@ -55,18 +57,12 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) color_hex = "{0:02x}{1:02x}{2:02x}".format(*rgb) else: - embed: Embed = Embed(title=t.error_parse_color_title(color), description=t.error_parse_color_example) - await reply(ctx, embed=embed) - return + raise CommandError(t.error_parse_color_example(color)) - img: Image = Image.new("RGB", (100, 100), rgb) - with io.BytesIO() as image_binary: - img.save(image_binary, "PNG") - image_binary.seek(0) - embed: Embed = Embed(title="Color Picker", color=Colour(int(color_hex, 16))) - embed.add_field(name="HEX", value=f"#{color_hex}") - embed.add_field(name="RGB", value=f"rgb{rgb}") - embed.add_field(name="HSV", value=f"hsv{hsv}") - embed.add_field(name="HSL", value=f"hsl{hsl}") - embed.set_image(url="attachment://color.png") - await reply(ctx, embed=embed, file=File(fp=image_binary, filename="color.png")) + embed: Embed = Embed(title="Color Picker", color=Colour(int(color_hex, 16))) + embed.set_image(url=f"https://singlecolorimage.com/get/{color_hex}/300x50") + embed.add_field(name="HEX", value=f"`#{color_hex}`") + embed.add_field(name="RGB", value=f"`rgb{rgb}`") + embed.add_field(name="HSV", value=f"`hsv{hsv}`") + embed.add_field(name="HSL", value=f"`hsl{hsl}`") + await reply(ctx, embed=embed) diff --git a/general/color_picker/translations/en.yml b/general/color_picker/translations/en.yml index 8d6ddd3e4..3027b6dcc 100644 --- a/general/color_picker/translations/en.yml +++ b/general/color_picker/translations/en.yml @@ -1,12 +1,8 @@ -error_parse_color_title: "Error cant parse HEX/RGB/HSV/HSL Color Code(\"{}\")" error_parse_color_example: > + **Error cant parse HEX/RGB/HSV/HSL Color Code(`{}`)** + **Examples:** - - #fff - - #ffffff - - #000000 - - rgb(255, 0, 0) - - rgb(255, 255, 255) - - hsv(0, 0, 0) - - hsv(0, 0, 255) - - hsl(0, 106, 0) - - hsl(0, 191, 0) \ No newline at end of file + - `#fdf12f` + - `rgb(255, 255, 100)` + - `hsv(0, 0, 255)` + - `hsl(0, 191, 0)` \ No newline at end of file From e382e9c7626d5045d41cd05015b594f22f320f26 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sat, 9 Oct 2021 11:24:30 +0200 Subject: [PATCH 09/37] Fixed PEP8 for Stackoverflow Copied Code :) --- general/color_picker/cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index a052dbd30..c1e332971 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -34,7 +34,7 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: hsl: tuple[int, ...] def _hex_to_color(hex_color: str) -> tuple[int, ...]: - return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) + return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4)) if color_re := self.RE_HEX.match(color): color_hex = color_re.group(1) From 66ea61813b372c3c84af319f5158c7e994d51713 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sat, 9 Oct 2021 11:26:28 +0200 Subject: [PATCH 10/37] Fix Black --- general/color_picker/cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index c1e332971..7adefc77d 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -34,7 +34,7 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: hsl: tuple[int, ...] def _hex_to_color(hex_color: str) -> tuple[int, ...]: - return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4)) + return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) if color_re := self.RE_HEX.match(color): color_hex = color_re.group(1) From 6a1e54d8d496f9b33d6d931aac205ce779ee9814 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sat, 9 Oct 2021 11:31:11 +0200 Subject: [PATCH 11/37] Fix Codestyle --- general/color_picker/cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 7adefc77d..f656ea271 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -34,7 +34,7 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: hsl: tuple[int, ...] def _hex_to_color(hex_color: str) -> tuple[int, ...]: - return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) + return tuple(int(hex_color[i: i + 2], 16) for i in (0, 2, 4)) # noqa: E203 if color_re := self.RE_HEX.match(color): color_hex = color_re.group(1) From 840053570c0398b276c2283a81de3dd1f88176e8 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sat, 9 Oct 2021 11:32:11 +0200 Subject: [PATCH 12/37] Fix Codestyle --- general/color_picker/cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index f656ea271..d1d53f972 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -34,7 +34,7 @@ def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: hsl: tuple[int, ...] def _hex_to_color(hex_color: str) -> tuple[int, ...]: - return tuple(int(hex_color[i: i + 2], 16) for i in (0, 2, 4)) # noqa: E203 + return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) # noqa: E203 if color_re := self.RE_HEX.match(color): color_hex = color_re.group(1) From 888081cbbf624316bea806df35de079cc21df170 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Mon, 18 Oct 2021 19:36:39 +0200 Subject: [PATCH 13/37] Update general/color_picker/cog.py Co-authored-by: Felix <41747605+Defelo@users.noreply.github.com> --- general/color_picker/cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index d1d53f972..d2cfac9e5 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -18,7 +18,7 @@ class ColorPickerCog(Cog, name="Color Picker"): CONTRIBUTORS = [Contributor.Tert0] - RE_HEX = re.compile(r"^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") + RE_HEX = re.compile(r"^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") RE_RGB = re.compile(r"^rgb\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") RE_HSV = re.compile(r"^hsv\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") RE_HSL = re.compile(r"^hsl\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") From 5024108016dcf88714cfd5d9ba4be447d0e00de7 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Mon, 18 Oct 2021 19:38:59 +0200 Subject: [PATCH 14/37] Update general/color_picker/cog.py Co-authored-by: Felix <41747605+Defelo@users.noreply.github.com> --- general/color_picker/cog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index d2cfac9e5..82f58b1e9 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -19,9 +19,9 @@ class ColorPickerCog(Cog, name="Color Picker"): CONTRIBUTORS = [Contributor.Tert0] RE_HEX = re.compile(r"^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") - RE_RGB = re.compile(r"^rgb\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") - RE_HSV = re.compile(r"^hsv\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") - RE_HSL = re.compile(r"^hsl\(([0-9]{1,3})\, ?([0-9]{1,3})\, ?([0-9]{1,3})\)$") + RE_RGB = re.compile(r"^rgb\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") + RE_HSV = re.compile(r"^hsv\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") + RE_HSL = re.compile(r"^hsl\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") @commands.command(name="color_picker", aliases=["cp", "color"]) async def color_picker(self, ctx: Context, *, color: str): From dac10ade243b5ce2b83a7aa4629f6030dd6e721c Mon Sep 17 00:00:00 2001 From: Defelo Date: Sat, 11 Jun 2022 23:00:48 +0200 Subject: [PATCH 15/37] Fixed color picker cog --- general/color_picker/__init__.py | 3 +++ general/color_picker/cog.py | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/general/color_picker/__init__.py b/general/color_picker/__init__.py index 644be5cb3..163ba4ee5 100644 --- a/general/color_picker/__init__.py +++ b/general/color_picker/__init__.py @@ -1 +1,4 @@ from .cog import ColorPickerCog + + +__all__ = ["ColorPickerCog"] diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 82f58b1e9..ca7f2578a 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -1,17 +1,18 @@ import colorsys -import io import re from typing import Any -from discord import Embed, Colour, File +from discord import Colour, Embed from discord.ext import commands -from discord.ext.commands import Context, CommandError +from discord.ext.commands import CommandError, Context from PyDrocsid.cog import Cog from PyDrocsid.command import reply from PyDrocsid.translations import t + from ...contributor import Contributor + t = t.color_picker From 044ca59309199613624269f7aca6c87f0cd2b822 Mon Sep 17 00:00:00 2001 From: Defelo Date: Sat, 11 Jun 2022 23:13:08 +0200 Subject: [PATCH 16/37] Added color picker documentation placeholder --- general/color_picker/documentation.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 general/color_picker/documentation.md diff --git a/general/color_picker/documentation.md b/general/color_picker/documentation.md new file mode 100644 index 000000000..ce54ccceb --- /dev/null +++ b/general/color_picker/documentation.md @@ -0,0 +1,4 @@ +# Color Picker + + +*Work in Progress* From 2d12d08c3fa553c14744074ed22935cff9c9b7de Mon Sep 17 00:00:00 2001 From: NekoFanatic <83883849+NekoFanatic@users.noreply.github.com> Date: Sun, 12 Jun 2022 00:09:01 +0200 Subject: [PATCH 17/37] Everything working (except HLS) --- general/color_picker/cog.py | 106 +++++++++++++++-------- general/color_picker/translations/en.yml | 3 + 2 files changed, 74 insertions(+), 35 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index ca7f2578a..40adb34c2 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -2,68 +2,104 @@ import re from typing import Any -from discord import Colour, Embed +from discord import Embed, Colour from discord.ext import commands -from discord.ext.commands import CommandError, Context +from discord.ext.commands import Context, CommandError from PyDrocsid.cog import Cog -from PyDrocsid.command import reply +from PyDrocsid.command import docs, reply from PyDrocsid.translations import t - from ...contributor import Contributor - t = t.color_picker +def _convert_to_floats(given: list[tuple[int, ...]]) -> tuple[float, ...]: + """3 tuples (number from user, max-value)""" + out: list[float] = [] + + for arg in given: + if int(arg[0]) < 0: + out.append(0.0) + elif int(arg[0]) > arg[1]: + out.append(1.0) + else: + out.append(float(int(arg[0]) / arg[1])) + + return out[0], out[1], out[2] + + +def _to_rgb(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: + out: list[int] = [] + + for color in colors: + if int(color) < 0: + out.append(0) + if int(color) > 255: + out.append(255) + else: + out.append(int(color)) + + return out[0], out[1], out[2] + + +def _hex_to_color(hex_color: str) -> tuple[int, ...]: + return tuple(int(hex_color[i: i + 2], 16) for i in (0, 2, 4)) + + class ColorPickerCog(Cog, name="Color Picker"): - CONTRIBUTORS = [Contributor.Tert0] + CONTRIBUTORS = [Contributor.Tert0, Contributor.NekoFanatic] RE_HEX = re.compile(r"^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") RE_RGB = re.compile(r"^rgb\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") RE_HSV = re.compile(r"^hsv\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") - RE_HSL = re.compile(r"^hsl\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") + RE_HLS = re.compile(r"^hls\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") @commands.command(name="color_picker", aliases=["cp", "color"]) + @docs(t.commands.color_picker) async def color_picker(self, ctx: Context, *, color: str): - def _to_int(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: - return tuple(map(int, colors)) - - color_hex: str - rgb: tuple[int, ...] - hsv: tuple[int, ...] - hsl: tuple[int, ...] - - def _hex_to_color(hex_color: str) -> tuple[int, ...]: - return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) # noqa: E203 if color_re := self.RE_HEX.match(color): - color_hex = color_re.group(1) - rgb = _hex_to_color(color_hex) - hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) - hsl = _to_int(colorsys.rgb_to_hls(*rgb)) + rgb = _hex_to_color(color_re.group(1)) + elif color_re := self.RE_RGB.match(color): - rgb = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) - color_hex = "{0:02x}{1:02x}{2:02x}".format(*rgb) - hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) - hsl = _to_int(colorsys.rgb_to_hls(*rgb)) + rgb = _to_rgb((color_re.group(1), color_re.group(2), color_re.group(3))) + + elif color_re := self.RE_HLS.match(color): + values = _convert_to_floats([ + (color_re.group(1), 359), + (color_re.group(2), 100), + (color_re.group(3), 100) + ]) + rgb = colorsys.hls_to_rgb(values[0], values[1], values[2]) + rgb = tuple(int(color * 255) for color in rgb) + elif color_re := self.RE_HSV.match(color): - hsv = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) - rgb = _to_int(colorsys.hsv_to_rgb(*hsv)) - color_hex = "{0:02x}{1:02x}{2:02x}".format(*rgb) - hsl = _to_int(colorsys.rgb_to_hls(*rgb)) - elif color_re := self.RE_HSL.match(color): - hsl = _to_int((color_re.group(1), color_re.group(2), color_re.group(3))) - rgb = _to_int(colorsys.hls_to_rgb(*hsl)) - hsv = _to_int(colorsys.rgb_to_hsv(*rgb)) - color_hex = "{0:02x}{1:02x}{2:02x}".format(*rgb) + values = _convert_to_floats([ + (color_re.group(1), 359), + (color_re.group(2), 100), + (color_re.group(3), 100) + ]) + rgb = colorsys.hsv_to_rgb(values[0], values[1], values[2]) + rgb = tuple(int(color * 255) for color in rgb) + else: raise CommandError(t.error_parse_color_example(color)) + color_hex = "{:02x}{:02x}{:02x}".format(*rgb) + hsv = colorsys.rgb_to_hsv(*rgb) + h, s, v = hsv + hsv = (int(h * 360), int(s * 100), int(v)) + + hls = colorsys.rgb_to_hls(*rgb) + h, l, s = hls + hls = (int(h * 360), int(s * 100), int(v)) + embed: Embed = Embed(title="Color Picker", color=Colour(int(color_hex, 16))) embed.set_image(url=f"https://singlecolorimage.com/get/{color_hex}/300x50") embed.add_field(name="HEX", value=f"`#{color_hex}`") embed.add_field(name="RGB", value=f"`rgb{rgb}`") embed.add_field(name="HSV", value=f"`hsv{hsv}`") - embed.add_field(name="HSL", value=f"`hsl{hsl}`") + embed.add_field(name="HLS", value=f"`hsl{hls}`") + await reply(ctx, embed=embed) diff --git a/general/color_picker/translations/en.yml b/general/color_picker/translations/en.yml index 3027b6dcc..1e2ce1cd9 100644 --- a/general/color_picker/translations/en.yml +++ b/general/color_picker/translations/en.yml @@ -1,3 +1,6 @@ +commands: + color_picker: Convert RGB, HEX, HSL or HSV into each other + error_parse_color_example: > **Error cant parse HEX/RGB/HSV/HSL Color Code(`{}`)** From f9623927dbc8ad5220b49f88cca2829a0cc1bfe3 Mon Sep 17 00:00:00 2001 From: NekoFanatic <83883849+NekoFanatic@users.noreply.github.com> Date: Sun, 12 Jun 2022 00:18:56 +0200 Subject: [PATCH 18/37] Fixed linting --- general/color_picker/cog.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 40adb34c2..50dc483c7 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -2,15 +2,17 @@ import re from typing import Any -from discord import Embed, Colour +from discord import Colour, Embed from discord.ext import commands -from discord.ext.commands import Context, CommandError +from discord.ext.commands import CommandError, Context from PyDrocsid.cog import Cog from PyDrocsid.command import docs, reply from PyDrocsid.translations import t + from ...contributor import Contributor + t = t.color_picker @@ -44,7 +46,7 @@ def _to_rgb(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: def _hex_to_color(hex_color: str) -> tuple[int, ...]: - return tuple(int(hex_color[i: i + 2], 16) for i in (0, 2, 4)) + return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) # noqa: E203 class ColorPickerCog(Cog, name="Color Picker"): @@ -66,27 +68,19 @@ async def color_picker(self, ctx: Context, *, color: str): rgb = _to_rgb((color_re.group(1), color_re.group(2), color_re.group(3))) elif color_re := self.RE_HLS.match(color): - values = _convert_to_floats([ - (color_re.group(1), 359), - (color_re.group(2), 100), - (color_re.group(3), 100) - ]) + values = _convert_to_floats([(color_re.group(1), 359), (color_re.group(2), 100), (color_re.group(3), 100)]) rgb = colorsys.hls_to_rgb(values[0], values[1], values[2]) rgb = tuple(int(color * 255) for color in rgb) elif color_re := self.RE_HSV.match(color): - values = _convert_to_floats([ - (color_re.group(1), 359), - (color_re.group(2), 100), - (color_re.group(3), 100) - ]) + values = _convert_to_floats([(color_re.group(1), 359), (color_re.group(2), 100), (color_re.group(3), 100)]) rgb = colorsys.hsv_to_rgb(values[0], values[1], values[2]) rgb = tuple(int(color * 255) for color in rgb) else: raise CommandError(t.error_parse_color_example(color)) - color_hex = "{:02x}{:02x}{:02x}".format(*rgb) + color_hex = f"{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}" hsv = colorsys.rgb_to_hsv(*rgb) h, s, v = hsv hsv = (int(h * 360), int(s * 100), int(v)) From 9512543fc2dc82e73e0dd2e939c91f68b3dea836 Mon Sep 17 00:00:00 2001 From: NekoFanatic <83883849+NekoFanatic@users.noreply.github.com> Date: Sun, 12 Jun 2022 10:16:35 +0200 Subject: [PATCH 19/37] Removed HLS, because transformation can be done --- general/color_picker/cog.py | 15 ++------------- general/color_picker/translations/en.yml | 7 +++---- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 50dc483c7..1156ef9b8 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -16,7 +16,7 @@ t = t.color_picker -def _convert_to_floats(given: list[tuple[int, ...]]) -> tuple[float, ...]: +def _to_floats(given: list[tuple[int, ...]]) -> tuple[float, ...]: """3 tuples (number from user, max-value)""" out: list[float] = [] @@ -55,7 +55,6 @@ class ColorPickerCog(Cog, name="Color Picker"): RE_HEX = re.compile(r"^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") RE_RGB = re.compile(r"^rgb\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") RE_HSV = re.compile(r"^hsv\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") - RE_HLS = re.compile(r"^hls\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") @commands.command(name="color_picker", aliases=["cp", "color"]) @docs(t.commands.color_picker) @@ -67,13 +66,8 @@ async def color_picker(self, ctx: Context, *, color: str): elif color_re := self.RE_RGB.match(color): rgb = _to_rgb((color_re.group(1), color_re.group(2), color_re.group(3))) - elif color_re := self.RE_HLS.match(color): - values = _convert_to_floats([(color_re.group(1), 359), (color_re.group(2), 100), (color_re.group(3), 100)]) - rgb = colorsys.hls_to_rgb(values[0], values[1], values[2]) - rgb = tuple(int(color * 255) for color in rgb) - elif color_re := self.RE_HSV.match(color): - values = _convert_to_floats([(color_re.group(1), 359), (color_re.group(2), 100), (color_re.group(3), 100)]) + values = _to_floats([(color_re.group(1), 359), (color_re.group(2), 100), (color_re.group(3), 100)]) rgb = colorsys.hsv_to_rgb(values[0], values[1], values[2]) rgb = tuple(int(color * 255) for color in rgb) @@ -85,15 +79,10 @@ async def color_picker(self, ctx: Context, *, color: str): h, s, v = hsv hsv = (int(h * 360), int(s * 100), int(v)) - hls = colorsys.rgb_to_hls(*rgb) - h, l, s = hls - hls = (int(h * 360), int(s * 100), int(v)) - embed: Embed = Embed(title="Color Picker", color=Colour(int(color_hex, 16))) embed.set_image(url=f"https://singlecolorimage.com/get/{color_hex}/300x50") embed.add_field(name="HEX", value=f"`#{color_hex}`") embed.add_field(name="RGB", value=f"`rgb{rgb}`") embed.add_field(name="HSV", value=f"`hsv{hsv}`") - embed.add_field(name="HLS", value=f"`hsl{hls}`") await reply(ctx, embed=embed) diff --git a/general/color_picker/translations/en.yml b/general/color_picker/translations/en.yml index 1e2ce1cd9..6f90293f1 100644 --- a/general/color_picker/translations/en.yml +++ b/general/color_picker/translations/en.yml @@ -1,11 +1,10 @@ commands: - color_picker: Convert RGB, HEX, HSL or HSV into each other + color_picker: Convert RGB, HEX or HSV into each other error_parse_color_example: > - **Error cant parse HEX/RGB/HSV/HSL Color Code(`{}`)** + **Error cant parse HEX/RGB/HSV Color Code(`{}`)** **Examples:** - `#fdf12f` - `rgb(255, 255, 100)` - - `hsv(0, 0, 255)` - - `hsl(0, 191, 0)` \ No newline at end of file + - `hsv(0, 0, 255)` \ No newline at end of file From d7cf4720893944b555acd40ff00ca3d3fc3c12c0 Mon Sep 17 00:00:00 2001 From: Defelo Date: Mon, 13 Jun 2022 16:50:06 +0200 Subject: [PATCH 20/37] Fixed thread auto join --- moderation/threads/cog.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/moderation/threads/cog.py b/moderation/threads/cog.py index c08a46337..7ca56ec00 100644 --- a/moderation/threads/cog.py +++ b/moderation/threads/cog.py @@ -27,6 +27,9 @@ class ThreadsCog(Cog, name="Thread Utils"): CONTRIBUTORS = [Contributor.Defelo] + async def on_thread_create(self, thread: Thread): + await self.on_thread_join(thread) + async def on_thread_join(self, thread: Thread): if await redis.exists(key := f"thread_created:{thread.id}"): return From e8bf57fcd280f9707ad3dd4d0b1b36563106e787 Mon Sep 17 00:00:00 2001 From: NekoFanatic <83883849+NekoFanatic@users.noreply.github.com> Date: Tue, 14 Jun 2022 22:24:07 +0200 Subject: [PATCH 21/37] Wrote documentation + changed some code style --- general/color_picker/cog.py | 23 +++++++++++++++++------ general/color_picker/documentation.md | 16 ++++++++++++++-- general/color_picker/translations/en.yml | 15 ++++++++++----- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 1156ef9b8..f3604a2e9 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -55,6 +55,7 @@ class ColorPickerCog(Cog, name="Color Picker"): RE_HEX = re.compile(r"^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") RE_RGB = re.compile(r"^rgb\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") RE_HSV = re.compile(r"^hsv\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") + RE_HSL = re.compile(r"^hsl\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") @commands.command(name="color_picker", aliases=["cp", "color"]) @docs(t.commands.color_picker) @@ -62,27 +63,37 @@ async def color_picker(self, ctx: Context, *, color: str): if color_re := self.RE_HEX.match(color): rgb = _hex_to_color(color_re.group(1)) + rgb = _to_floats([(rgb[0], 255), (rgb[1], 255), (rgb[2], 255)]) elif color_re := self.RE_RGB.match(color): rgb = _to_rgb((color_re.group(1), color_re.group(2), color_re.group(3))) + rgb = _to_floats([(rgb[0], 255), (rgb[1], 255), (rgb[2], 255)]) elif color_re := self.RE_HSV.match(color): - values = _to_floats([(color_re.group(1), 359), (color_re.group(2), 100), (color_re.group(3), 100)]) + values = _to_floats([(color_re.group(1), 360), (color_re.group(2), 100), (color_re.group(3), 100)]) rgb = colorsys.hsv_to_rgb(values[0], values[1], values[2]) - rgb = tuple(int(color * 255) for color in rgb) + + elif color_re := self.RE_HSL.match(color): + values = _to_floats([(color_re.group(1), 360), (color_re.group(2), 100), (color_re.group(3), 100)]) + rgb = colorsys.hls_to_rgb(values[0], values[2], values[1]) else: raise CommandError(t.error_parse_color_example(color)) + h, s, v = colorsys.rgb_to_hsv(*rgb) + hsv = (int(round(h * 360, 0)), int(round(s * 100, 0)), int(round(v * 100, 0))) + + h, l, s = colorsys.rgb_to_hls(*rgb) + hsl = (int(round(h * 360)), int(round(s * 100)), int(round(l * 100))) + + rgb = tuple(int(color * 255) for color in rgb) color_hex = f"{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}" - hsv = colorsys.rgb_to_hsv(*rgb) - h, s, v = hsv - hsv = (int(h * 360), int(s * 100), int(v)) - embed: Embed = Embed(title="Color Picker", color=Colour(int(color_hex, 16))) + embed: Embed = Embed(title=t.embed.title, color=Colour(int(color_hex, 16))) embed.set_image(url=f"https://singlecolorimage.com/get/{color_hex}/300x50") embed.add_field(name="HEX", value=f"`#{color_hex}`") embed.add_field(name="RGB", value=f"`rgb{rgb}`") embed.add_field(name="HSV", value=f"`hsv{hsv}`") + embed.add_field(name="HSL", value=f"`hsl{hsl}`") await reply(ctx, embed=embed) diff --git a/general/color_picker/documentation.md b/general/color_picker/documentation.md index ce54ccceb..d578f18ff 100644 --- a/general/color_picker/documentation.md +++ b/general/color_picker/documentation.md @@ -1,4 +1,16 @@ # Color Picker - -*Work in Progress* +Contains a command to transform different color forms into each other + + +## `color_picker` + +```css +.[color_picker|cp|color] +``` + +Arguments: + +| Argument | Required | Description | +|:--------:|:--------:|:--------------------------------------------------------------------------------------------------------------------------------------| +| `color` | | can be a hex-code or it can start with [`rgb`, `hsl` or `hsv`] and has to get in brackets behind that 3 numbers, separated by a comma | diff --git a/general/color_picker/translations/en.yml b/general/color_picker/translations/en.yml index 6f90293f1..0cece3190 100644 --- a/general/color_picker/translations/en.yml +++ b/general/color_picker/translations/en.yml @@ -1,10 +1,15 @@ commands: - color_picker: Convert RGB, HEX or HSV into each other + color_picker: Convert RGB, HEX, HSL or HSV into each other + + +embed: + title: Color Picker error_parse_color_example: > - **Error cant parse HEX/RGB/HSV Color Code(`{}`)** + **Error cant parse HEX/RGB/HSL/HSV Color Code(`{}`)** **Examples:** - - `#fdf12f` - - `rgb(255, 255, 100)` - - `hsv(0, 0, 255)` \ No newline at end of file + - `#fdf12f` # #000000 - #FFFFFF + - `rgb(255, 255, 100)` # (0-255, 0-255, 0-255) + - `hsv(343, 50, 100)` # (0-360, 0-100, 0-100) + - `hsl(298, 0, 99)` # (0-360, 0-100, 0-100) From ddf55ed4ad9d7cbaf46191aedcf21989aa5e080f Mon Sep 17 00:00:00 2001 From: Inf-inity <83883849+Inf-inity@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:42:06 +0200 Subject: [PATCH 22/37] Fixed codestyle + edited translation-text --- general/color_picker/cog.py | 12 +++++------- general/color_picker/documentation.md | 3 +-- general/color_picker/translations/en.yml | 18 ++++++++++-------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index f3604a2e9..59b47a851 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -21,12 +21,10 @@ def _to_floats(given: list[tuple[int, ...]]) -> tuple[float, ...]: out: list[float] = [] for arg in given: - if int(arg[0]) < 0: - out.append(0.0) - elif int(arg[0]) > arg[1]: - out.append(1.0) - else: - out.append(float(int(arg[0]) / arg[1])) + if 0 < int(arg[0]) > arg[1]: + raise CommandError(t.error.invalid_input(arg[0], arg[1])) + + out.append(float(int(arg[0]) / arg[1])) return out[0], out[1], out[2] @@ -78,7 +76,7 @@ async def color_picker(self, ctx: Context, *, color: str): rgb = colorsys.hls_to_rgb(values[0], values[2], values[1]) else: - raise CommandError(t.error_parse_color_example(color)) + raise CommandError(t.error.parse_color_example(color)) h, s, v = colorsys.rgb_to_hsv(*rgb) hsv = (int(round(h * 360, 0)), int(round(s * 100, 0)), int(round(v * 100, 0))) diff --git a/general/color_picker/documentation.md b/general/color_picker/documentation.md index d578f18ff..ed958b604 100644 --- a/general/color_picker/documentation.md +++ b/general/color_picker/documentation.md @@ -1,7 +1,6 @@ # Color Picker -Contains a command to transform different color forms into each other - +Contains a command that can be used to convert different types of colors into each other ## `color_picker` diff --git a/general/color_picker/translations/en.yml b/general/color_picker/translations/en.yml index 0cece3190..98950f18b 100644 --- a/general/color_picker/translations/en.yml +++ b/general/color_picker/translations/en.yml @@ -5,11 +5,13 @@ commands: embed: title: Color Picker -error_parse_color_example: > - **Error cant parse HEX/RGB/HSL/HSV Color Code(`{}`)** - - **Examples:** - - `#fdf12f` # #000000 - #FFFFFF - - `rgb(255, 255, 100)` # (0-255, 0-255, 0-255) - - `hsv(343, 50, 100)` # (0-360, 0-100, 0-100) - - `hsl(298, 0, 99)` # (0-360, 0-100, 0-100) +error: + invalid_input: "`{}` has to be bigger than `0` and smaller than `{}`" + parse_color_example: > + **Error cant parse HEX/RGB/HSL/HSV Color Code(`{}`)** + + **Examples:** + - `#fdf12f` # #000000 - #FFFFFF + - `rgb(255, 255, 100)` # (0-255, 0-255, 0-255) + - `hsv(343, 50, 100)` # (0-360, 0-100, 0-100) + - `hsl(298, 0, 99)` # (0-360, 0-100, 0-100) From 6290be458aad2070e360f48a61b8df7c820e40e7 Mon Sep 17 00:00:00 2001 From: NekoFanatic <83883849+NekoFanatic@users.noreply.github.com> Date: Fri, 8 Apr 2022 23:28:53 +0200 Subject: [PATCH 23/37] Added more options for spam_detection (incomplete) --- moderation/spam_detection/cog.py | 143 +++++++++++++----- moderation/spam_detection/permissions.py | 1 + moderation/spam_detection/settings.py | 5 +- moderation/spam_detection/translations/en.yml | 42 ++++- 4 files changed, 142 insertions(+), 49 deletions(-) diff --git a/moderation/spam_detection/cog.py b/moderation/spam_detection/cog.py index 70bf4bc63..b05a7d12c 100644 --- a/moderation/spam_detection/cog.py +++ b/moderation/spam_detection/cog.py @@ -1,18 +1,19 @@ import time +from datetime import timedelta -from discord import Embed, Member, VoiceState +from discord import Embed, Forbidden, Member, VoiceState from discord.ext import commands from discord.ext.commands import Context, UserInputError, guild_only from PyDrocsid.cog import Cog -from PyDrocsid.command import reply -from PyDrocsid.config import Contributor +from PyDrocsid.command import CommandError, docs, reply from PyDrocsid.redis import redis from PyDrocsid.translations import t from .colors import Colors from .permissions import SpamDetectionPermission from .settings import SpamDetectionSettings +from ...contributor import Contributor from ...pubsub import send_alert, send_to_changelog @@ -20,19 +21,33 @@ t = t.spam_detection +async def _send_changes(ctx: Context, amount: int, change_type: str, description): + description = description(amount, change_type) if amount > 0 else t.hop_detection_disabled(change_type) + embed = Embed(title=t.channel_hopping, description=description, colour=Colors.SpamDetection) + + await reply(ctx, embed=embed) + await send_to_changelog(ctx.guild, description) + + class SpamDetectionCog(Cog, name="Spam Detection"): - CONTRIBUTORS = [Contributor.ce_phox, Contributor.Defelo] + CONTRIBUTORS = [Contributor.ce_phox, Contributor.Defelo, Contributor.NekoFanatic] async def on_voice_state_update(self, member: Member, before: VoiceState, after: VoiceState): """ Checks for channel-hopping """ + if await SpamDetectionPermission.bypass.check_permissions(member): + return + if before.channel == after.channel: return - max_hops: int = await SpamDetectionSettings.max_hops.get() - if max_hops <= 0: + alert: int = await SpamDetectionSettings.max_hops_alert.get() + warning: int = await SpamDetectionSettings.max_hops_warning.get() + mute: int = await SpamDetectionSettings.max_hops_temp_mute.get() + duration: int = await SpamDetectionSettings.temp_mute_duration.get() + if alert == 0 and warning == 0 and mute == 0: return ts = time.time() @@ -41,30 +56,35 @@ async def on_voice_state_update(self, member: Member, before: VoiceState, after: await redis.expire(key, 60) hops: int = await redis.zcount(key, "-inf", "inf") - if hops <= max_hops: - return - - if await redis.exists(key := f"channel_hops_alert_sent:user={member.id}"): - return - - await redis.setex(key, 10, 1) - - embed = Embed(title=t.channel_hopping, color=Colors.SpamDetection, description=t.hops_in_last_minute(cnt=hops)) - embed.add_field(name=tg.member, value=member.mention) - embed.add_field(name=t.member_id, value=member.id) - embed.set_author(name=str(member), icon_url=member.display_avatar.url) - if after.channel: - embed.add_field(name=t.current_channel, value=after.channel.name) - - await send_alert(member.guild, embed) + if hops >= alert > 0 and not await redis.exists(key := f"channel_hops_alert_sent:user={member.id}"): + await redis.setex(key, 10, 1) + embed = Embed( + title=t.channel_hopping, color=Colors.SpamDetection, description=t.hops_in_last_minute(cnt=hops) + ) + embed.add_field(name=tg.member, value=member.mention) + embed.add_field(name=t.member_id, value=str(member.id)) + embed.set_author(name=str(member), icon_url=member.display_avatar.url) + if after.channel: + embed.add_field(name=t.current_channel, value=after.channel.name) + await send_alert(member.guild, embed) + + if hops >= warning > 0 and not await redis.exists(key := f"channel_hops_warning_sent:user={member.id}"): + await redis.setex(key, 10, 1) + embed = Embed(title=t.channel_hopping_warning_sent, color=Colors.SpamDetection) + await member.send(embed=embed) + + if hops >= mute > 0 and not await redis.exists(key := f"channel_hops_mute:user={member.id}"): + try: + await member.timeout_for(duration=timedelta(seconds=duration), reason=t.reason) + except Forbidden as exception: + await send_alert(member.guild, Embed(title=t.cant_mute(member.id, exception.text), color=Colors.error)) + await redis.setex(key, 10, 1) @commands.group(aliases=["spam", "sd"]) @SpamDetectionPermission.read.check @guild_only() + @docs(t.commands.spam_detection) async def spam_detection(self, ctx: Context): - """ - view and change spam detection settings - """ if ctx.subcommand_passed is not None: if ctx.invoked_subcommand is None: @@ -73,26 +93,65 @@ async def spam_detection(self, ctx: Context): embed = Embed(title=t.spam_detection, color=Colors.SpamDetection) - if (max_hops := await SpamDetectionSettings.max_hops.get()) <= 0: - embed.add_field(name=t.channel_hopping, value=tg.disabled) + if (alert := await SpamDetectionSettings.max_hops_alert.get()) <= 0: + embed.add_field(name=t.channel_hopping_alert, value=tg.disabled, inline=False) + else: + embed.add_field(name=t.channel_hopping_alert, value=t.max_x_hops(cnt=alert), inline=False) + if (dm_warning := await SpamDetectionSettings.max_hops_warning.get()) <= 0: + embed.add_field(name=t.channel_hopping_warning, value=tg.disabled, inline=False) + else: + embed.add_field(name=t.channel_hopping_warning, value=t.max_x_hops(cnt=dm_warning), inline=False) + if (mute_hops := await SpamDetectionSettings.max_hops_temp_mute.get()) <= 0: + embed.add_field(name=t.channel_hopping_mute, value=tg.disabled, inline=False) else: - embed.add_field(name=t.channel_hopping, value=t.max_x_hops(cnt=max_hops)) + embed.add_field(name=t.channel_hopping_mute, value=t.max_x_hops(cnt=mute_hops), inline=False) + mute_duration = await SpamDetectionSettings.temp_mute_duration.get() + embed.add_field(name=t.mute_duration, value=t.seconds_muted(cnt=mute_duration), inline=False) await reply(ctx, embed=embed) - @spam_detection.command(name="hops", aliases=["h"]) + @spam_detection.group(name="channel_hopping", aliases=["ch"]) @SpamDetectionPermission.write.check - async def spam_detection_hops(self, ctx: Context, amount: int): - """ - Changes the number of maximum channel hops per minute allowed before an alert is issued - set this to 0 to disable channel hopping alerts - """ + @docs(t.commands.channel_hopping) + async def channel_hopping(self, ctx: Context): - await SpamDetectionSettings.max_hops.set(amount) - embed = Embed( - title=t.channel_hopping, - description=t.hop_amount_set(amount) if amount > 0 else t.hop_detection_disabled, - colour=Colors.SpamDetection, - ) - await reply(ctx, embed=embed) - await send_to_changelog(ctx.guild, t.hop_amount_set(amount) if amount > 0 else t.hop_detection_disabled) + if not ctx.subcommand_passed or not ctx.invoked_subcommand: + raise UserInputError + + @channel_hopping.command(name="alert", aliases=["a"]) + @docs(t.commands.alert) + async def alert(self, ctx: Context, amount: int): + + await SpamDetectionSettings.max_hops_alert.set(max(amount, 0)) + await _send_changes(ctx, amount, "alerts", t.hop_amount_set) + + @channel_hopping.command(name="warning", aliases=["warn"]) + @docs(t.commands.warning) + async def warning(self, ctx: Context, amount: int): + + await SpamDetectionSettings.max_hops_warning.set(max(amount, 0)) + await _send_changes(ctx, amount, "warnings", t.hop_amount_set) + + @channel_hopping.group(name="mute", aliases=["m"]) + @docs(t.commands.temp_mute) + async def mute(self, ctx: Context): + + if not ctx.subcommand_passed or not ctx.invoked_subcommand: + raise UserInputError + + @mute.command(name="hops", aliases=["h"]) + @docs(t.commands.temp_mute_hops) + async def hops(self, ctx: Context, amount: int): + + await SpamDetectionSettings.max_hops_temp_mute.set(max(amount, 0)) + await _send_changes(ctx, amount, "mutes", t.hop_amount_set) + + @mute.command(name="duration", aliases=["d"]) + @docs(t.commands.temp_mute_duration) + async def duration(self, ctx: Context, seconds: int): + + if seconds <= 0: + raise CommandError(t.error.seconds_smaler_than_1) + + await SpamDetectionSettings.temp_mute_duration.set(seconds) + await _send_changes(ctx, seconds, "mutes", t.mute_time_set) diff --git a/moderation/spam_detection/permissions.py b/moderation/spam_detection/permissions.py index 19720f6fd..c864e9be6 100644 --- a/moderation/spam_detection/permissions.py +++ b/moderation/spam_detection/permissions.py @@ -11,3 +11,4 @@ def description(self) -> str: read = auto() write = auto() + bypass = auto() diff --git a/moderation/spam_detection/settings.py b/moderation/spam_detection/settings.py index 996d10405..94a4578a0 100644 --- a/moderation/spam_detection/settings.py +++ b/moderation/spam_detection/settings.py @@ -2,4 +2,7 @@ class SpamDetectionSettings(Settings): - max_hops = 0 + max_hops_alert = 0 + max_hops_warning = 0 + max_hops_temp_mute = 0 + temp_mute_duration = 10 diff --git a/moderation/spam_detection/translations/en.yml b/moderation/spam_detection/translations/en.yml index bacfff7f7..26dc996e5 100644 --- a/moderation/spam_detection/translations/en.yml +++ b/moderation/spam_detection/translations/en.yml @@ -1,18 +1,48 @@ +commands: + spam_detection: view and change spam detection settings + channel_hopping: edit spam detection settings + alert: set the number of allowed hops before a alert-channel notification is used (0 for disabling) + warning: set the number of allowed hops before a dm notification is used (0 for disabling) + temp_mute: edit the channel hopping mute settings + temp_mute_hops: set the number of allowed hops before a alert-channel notification is used (0 for disabling) + temp_mute_duration: set the number of seconds a user is muted (0 for disabling) + permissions: read: read spam detection configuration write: write spam detection configuration + bypass: bypass the channel hopping check spam_detection: Spam Detection + max_x_hops: - one: "Max.: {cnt} channel hop per minute" - many: "Max.: {cnt} channel hops per minute" + one: "Max.: `{cnt}` channel hop per minute" + many: "Max.: `{cnt}` channel hops per minute" +seconds_muted: + one: "{cnt} second" + many: "{cnt} seconds" + member_id: Member ID -channel_hopping: Channel Hopping Detection + +channel_hopping: Channel hopping +channel_hopping_alert: Alert message +channel_hopping_warning: Direct message +channel_hopping_mute: Temporare mute +mute_duration: Mute duration +reason: was timouted because of channelhopping + +cant_mute: "Cant mute {} because of {}" +error: + seconds_smaler_than_1: Amount of seconds for mute cant be smaller than 1 + current_channel: Current Channel -hop_amount_set: "The **maximum amount** of **channel hops per minute** has been **set to {}**." -hop_detection_disabled: "**Channel Hopping Detection** has been **disabled**." + new_amount: New amount -max_hops: Maximum channel hops per minute +hop_amount_set: "The **maximum amount** of **channel hops per minute** has been **set to {}** for **{}**." +mute_time_set: "The **muted time** for channel hooping has been **set to {}** seconds." +hop_detection_disabled: "**Channel Hopping Detection** has been **disabled** for {}." + hops_in_last_minute: one: "{cnt} hop in the last minute" many: "{cnt} hops in the last minute" + +channel_hopping_warning_sent: "Please stop channel hopping!" From ed16cf606b9075cf87050984ed221e3ce8074dab Mon Sep 17 00:00:00 2001 From: Defelo Date: Wed, 15 Jun 2022 09:26:58 +0200 Subject: [PATCH 24/37] Fixed exception if bot is blocked by the member --- moderation/spam_detection/cog.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/moderation/spam_detection/cog.py b/moderation/spam_detection/cog.py index b05a7d12c..9dc992e56 100644 --- a/moderation/spam_detection/cog.py +++ b/moderation/spam_detection/cog.py @@ -1,7 +1,7 @@ import time from datetime import timedelta -from discord import Embed, Forbidden, Member, VoiceState +from discord import Embed, Forbidden, HTTPException, Member, VoiceState from discord.ext import commands from discord.ext.commands import Context, UserInputError, guild_only @@ -71,7 +71,10 @@ async def on_voice_state_update(self, member: Member, before: VoiceState, after: if hops >= warning > 0 and not await redis.exists(key := f"channel_hops_warning_sent:user={member.id}"): await redis.setex(key, 10, 1) embed = Embed(title=t.channel_hopping_warning_sent, color=Colors.SpamDetection) - await member.send(embed=embed) + try: + await member.send(embed=embed) + except (HTTPException, Forbidden): + pass if hops >= mute > 0 and not await redis.exists(key := f"channel_hops_mute:user={member.id}"): try: From f6ef9dfb4ddb7ae71e530bd7d5c82aeff754f979 Mon Sep 17 00:00:00 2001 From: Defelo Date: Wed, 15 Jun 2022 09:29:10 +0200 Subject: [PATCH 25/37] Improved translations --- moderation/spam_detection/cog.py | 17 ++++++++--------- moderation/spam_detection/translations/en.yml | 14 ++++++++------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/moderation/spam_detection/cog.py b/moderation/spam_detection/cog.py index 9dc992e56..10283da57 100644 --- a/moderation/spam_detection/cog.py +++ b/moderation/spam_detection/cog.py @@ -79,8 +79,8 @@ async def on_voice_state_update(self, member: Member, before: VoiceState, after: if hops >= mute > 0 and not await redis.exists(key := f"channel_hops_mute:user={member.id}"): try: await member.timeout_for(duration=timedelta(seconds=duration), reason=t.reason) - except Forbidden as exception: - await send_alert(member.guild, Embed(title=t.cant_mute(member.id, exception.text), color=Colors.error)) + except Forbidden: + await send_alert(member.guild, t.cant_mute(member.mention, member.id)) await redis.setex(key, 10, 1) @commands.group(aliases=["spam", "sd"]) @@ -126,14 +126,14 @@ async def channel_hopping(self, ctx: Context): async def alert(self, ctx: Context, amount: int): await SpamDetectionSettings.max_hops_alert.set(max(amount, 0)) - await _send_changes(ctx, amount, "alerts", t.hop_amount_set) + await _send_changes(ctx, amount, t.change_types.alerts, t.hop_amount_set) @channel_hopping.command(name="warning", aliases=["warn"]) @docs(t.commands.warning) async def warning(self, ctx: Context, amount: int): await SpamDetectionSettings.max_hops_warning.set(max(amount, 0)) - await _send_changes(ctx, amount, "warnings", t.hop_amount_set) + await _send_changes(ctx, amount, t.change_types.warnings, t.hop_amount_set) @channel_hopping.group(name="mute", aliases=["m"]) @docs(t.commands.temp_mute) @@ -147,14 +147,13 @@ async def mute(self, ctx: Context): async def hops(self, ctx: Context, amount: int): await SpamDetectionSettings.max_hops_temp_mute.set(max(amount, 0)) - await _send_changes(ctx, amount, "mutes", t.hop_amount_set) + await _send_changes(ctx, amount, t.change_types.mutes, t.hop_amount_set) @mute.command(name="duration", aliases=["d"]) @docs(t.commands.temp_mute_duration) async def duration(self, ctx: Context, seconds: int): - - if seconds <= 0: - raise CommandError(t.error.seconds_smaler_than_1) + if seconds not in range(1, 28 * 24 * 60 * 60): + raise CommandError(tg.invalid_duration) await SpamDetectionSettings.temp_mute_duration.set(seconds) - await _send_changes(ctx, seconds, "mutes", t.mute_time_set) + await _send_changes(ctx, seconds, t.change_types.mutes, t.mute_time_set) diff --git a/moderation/spam_detection/translations/en.yml b/moderation/spam_detection/translations/en.yml index 26dc996e5..373906194 100644 --- a/moderation/spam_detection/translations/en.yml +++ b/moderation/spam_detection/translations/en.yml @@ -24,22 +24,24 @@ seconds_muted: member_id: Member ID channel_hopping: Channel hopping +channel_hopping_warning: Warning via DM channel_hopping_alert: Alert message -channel_hopping_warning: Direct message channel_hopping_mute: Temporare mute mute_duration: Mute duration reason: was timouted because of channelhopping -cant_mute: "Cant mute {} because of {}" -error: - seconds_smaler_than_1: Amount of seconds for mute cant be smaller than 1 +cant_mute: "Cannot mute {} ({}) for channel hopping because of missing permissions" current_channel: Current Channel new_amount: New amount hop_amount_set: "The **maximum amount** of **channel hops per minute** has been **set to {}** for **{}**." -mute_time_set: "The **muted time** for channel hooping has been **set to {}** seconds." -hop_detection_disabled: "**Channel Hopping Detection** has been **disabled** for {}." +mute_time_set: "The **muted time** for channel hooping has been **set to {} seconds**." +hop_detection_disabled: "**Channel Hopping Detection** has been **disabled** for **{}**." +change_types: + warnings: warnings + alerts: alerts + mutes: mutes hops_in_last_minute: one: "{cnt} hop in the last minute" From 6c0d6cbdac171f8beaf7f5665a819d4233eb91ba Mon Sep 17 00:00:00 2001 From: Defelo Date: Wed, 15 Jun 2022 09:30:01 +0200 Subject: [PATCH 26/37] Improved spam_detection status embed --- moderation/spam_detection/cog.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/moderation/spam_detection/cog.py b/moderation/spam_detection/cog.py index 10283da57..5525d70aa 100644 --- a/moderation/spam_detection/cog.py +++ b/moderation/spam_detection/cog.py @@ -96,18 +96,21 @@ async def spam_detection(self, ctx: Context): embed = Embed(title=t.spam_detection, color=Colors.SpamDetection) - if (alert := await SpamDetectionSettings.max_hops_alert.get()) <= 0: - embed.add_field(name=t.channel_hopping_alert, value=tg.disabled, inline=False) - else: - embed.add_field(name=t.channel_hopping_alert, value=t.max_x_hops(cnt=alert), inline=False) if (dm_warning := await SpamDetectionSettings.max_hops_warning.get()) <= 0: embed.add_field(name=t.channel_hopping_warning, value=tg.disabled, inline=False) else: embed.add_field(name=t.channel_hopping_warning, value=t.max_x_hops(cnt=dm_warning), inline=False) + + if (alert := await SpamDetectionSettings.max_hops_alert.get()) <= 0: + embed.add_field(name=t.channel_hopping_alert, value=tg.disabled, inline=False) + else: + embed.add_field(name=t.channel_hopping_alert, value=t.max_x_hops(cnt=alert), inline=False) + if (mute_hops := await SpamDetectionSettings.max_hops_temp_mute.get()) <= 0: embed.add_field(name=t.channel_hopping_mute, value=tg.disabled, inline=False) else: embed.add_field(name=t.channel_hopping_mute, value=t.max_x_hops(cnt=mute_hops), inline=False) + mute_duration = await SpamDetectionSettings.temp_mute_duration.get() embed.add_field(name=t.mute_duration, value=t.seconds_muted(cnt=mute_duration), inline=False) From 700f5a38026c3ae6c52756bb759ba3eb905b1faa Mon Sep 17 00:00:00 2001 From: Defelo Date: Wed, 15 Jun 2022 09:30:33 +0200 Subject: [PATCH 27/37] Improved aliases --- moderation/spam_detection/cog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moderation/spam_detection/cog.py b/moderation/spam_detection/cog.py index 5525d70aa..35a3c06ae 100644 --- a/moderation/spam_detection/cog.py +++ b/moderation/spam_detection/cog.py @@ -116,7 +116,7 @@ async def spam_detection(self, ctx: Context): await reply(ctx, embed=embed) - @spam_detection.group(name="channel_hopping", aliases=["ch"]) + @spam_detection.group(name="channel_hopping", aliases=["ch", "h"]) @SpamDetectionPermission.write.check @docs(t.commands.channel_hopping) async def channel_hopping(self, ctx: Context): @@ -131,7 +131,7 @@ async def alert(self, ctx: Context, amount: int): await SpamDetectionSettings.max_hops_alert.set(max(amount, 0)) await _send_changes(ctx, amount, t.change_types.alerts, t.hop_amount_set) - @channel_hopping.command(name="warning", aliases=["warn"]) + @channel_hopping.command(name="warning", aliases=["warn", "w", "dm"]) @docs(t.commands.warning) async def warning(self, ctx: Context, amount: int): From f2c6a93cf52a4cef09b64907053a2a656819b103 Mon Sep 17 00:00:00 2001 From: Infinity <83883849+Inf-inity@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:48:26 +0200 Subject: [PATCH 28/37] Update cog.py --- general/color_picker/cog.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 59b47a851..f3c1f62d6 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -29,16 +29,16 @@ def _to_floats(given: list[tuple[int, ...]]) -> tuple[float, ...]: return out[0], out[1], out[2] -def _to_rgb(colors: tuple[Any, Any, Any]) -> tuple[int, ...]: +def _to_rgb(colors: tuple[int, ...]) -> tuple[int, ...]: out: list[int] = [] for color in colors: - if int(color) < 0: + if color < 0: out.append(0) - if int(color) > 255: + if color > 255: out.append(255) else: - out.append(int(color)) + out.append(color) return out[0], out[1], out[2] From 88b0eae6bfc4dc986039927f63e06f9c6e351690 Mon Sep 17 00:00:00 2001 From: Infinity <83883849+Inf-inity@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:48:54 +0200 Subject: [PATCH 29/37] Update documentation.md --- general/color_picker/documentation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/general/color_picker/documentation.md b/general/color_picker/documentation.md index ed958b604..f81c9ec4f 100644 --- a/general/color_picker/documentation.md +++ b/general/color_picker/documentation.md @@ -2,6 +2,7 @@ Contains a command that can be used to convert different types of colors into each other + ## `color_picker` ```css From c1b1fed93e2a765474f1afeeb2cb0fbbb67e25ac Mon Sep 17 00:00:00 2001 From: Inf-inity <83883849+Inf-inity@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:51:12 +0200 Subject: [PATCH 30/37] Removed useless _to_rgb function --- general/color_picker/cog.py | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index f3c1f62d6..0572b853f 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -1,6 +1,5 @@ import colorsys import re -from typing import Any from discord import Colour, Embed from discord.ext import commands @@ -29,20 +28,6 @@ def _to_floats(given: list[tuple[int, ...]]) -> tuple[float, ...]: return out[0], out[1], out[2] -def _to_rgb(colors: tuple[int, ...]) -> tuple[int, ...]: - out: list[int] = [] - - for color in colors: - if color < 0: - out.append(0) - if color > 255: - out.append(255) - else: - out.append(color) - - return out[0], out[1], out[2] - - def _hex_to_color(hex_color: str) -> tuple[int, ...]: return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) # noqa: E203 @@ -64,8 +49,7 @@ async def color_picker(self, ctx: Context, *, color: str): rgb = _to_floats([(rgb[0], 255), (rgb[1], 255), (rgb[2], 255)]) elif color_re := self.RE_RGB.match(color): - rgb = _to_rgb((color_re.group(1), color_re.group(2), color_re.group(3))) - rgb = _to_floats([(rgb[0], 255), (rgb[1], 255), (rgb[2], 255)]) + rgb = _to_floats([(color_re.group(1), 255), (color_re.group(2), 255), (color_re.group(3), 255)]) elif color_re := self.RE_HSV.match(color): values = _to_floats([(color_re.group(1), 360), (color_re.group(2), 100), (color_re.group(3), 100)]) From 152569bc2298125f6a82382df29d484f74e6b3c1 Mon Sep 17 00:00:00 2001 From: Inf-inity <83883849+Inf-inity@users.noreply.github.com> Date: Fri, 17 Jun 2022 20:36:16 +0200 Subject: [PATCH 31/37] Changed Contributor name 'NekoFanatic' into 'Infinity' --- administration/roles/cog.py | 2 +- contributor.py | 2 +- moderation/content_filter/cog.py | 2 +- moderation/invites/cog.py | 2 +- moderation/logging/cog.py | 2 +- moderation/spam_detection/cog.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/administration/roles/cog.py b/administration/roles/cog.py index 338b6f77f..92f8fc647 100644 --- a/administration/roles/cog.py +++ b/administration/roles/cog.py @@ -84,7 +84,7 @@ async def inner(_, ctx: Context, *, role: Role): class RolesCog(Cog, name="Roles"): - CONTRIBUTORS = [Contributor.Defelo, Contributor.NekoFanatic] + CONTRIBUTORS = [Contributor.Defelo, Contributor.Infinity] def __init__(self): super().__init__() diff --git a/contributor.py b/contributor.py index 29e62f9e3..a12b674ed 100644 --- a/contributor.py +++ b/contributor.py @@ -11,6 +11,6 @@ class Contributor(ContributorBase): Tristan = (277069925678317568, "MDQ6VXNlcjQ1MzMwNjY3") Tert0 = (621330363167539210, "MDQ6VXNlcjYyMDM2NDY0") MarcelCoding = (398895973490884608, "MDQ6VXNlcjM0ODE5NTI0") - NekoFanatic = (846009958062358548, "MDQ6VXNlcjgzODgzODQ5") + Infinity = (846009958062358548, "MDQ6VXNlcjgzODgzODQ5") Felux = (206815202375761920, "MDQ6VXNlcjMyNzQ5NzE0") hackandcode = (301823559737671680, "MDQ6VXNlcjI3Njc5Mjc0") diff --git a/moderation/content_filter/cog.py b/moderation/content_filter/cog.py index b79369ba4..805e98383 100644 --- a/moderation/content_filter/cog.py +++ b/moderation/content_filter/cog.py @@ -123,7 +123,7 @@ async def check_message(message: Message) -> None: class ContentFilterCog(Cog, name="Content Filter"): - CONTRIBUTORS = [Contributor.NekoFanatic, Contributor.Defelo] + CONTRIBUTORS = [Contributor.Infinity, Contributor.Defelo] @get_userlog_entries.subscribe async def handle_get_ulog_entries(self, user_id: int, _): diff --git a/moderation/invites/cog.py b/moderation/invites/cog.py index c6c47db17..576942116 100644 --- a/moderation/invites/cog.py +++ b/moderation/invites/cog.py @@ -91,7 +91,7 @@ class InvitesCog(Cog, name="Allowed Discord Invites"): Contributor.wolflu, Contributor.TNT2k, Contributor.Florian, - Contributor.NekoFanatic, + Contributor.Infinity, ] @get_userlog_entries.subscribe diff --git a/moderation/logging/cog.py b/moderation/logging/cog.py index 73723f391..b304ede6d 100644 --- a/moderation/logging/cog.py +++ b/moderation/logging/cog.py @@ -111,7 +111,7 @@ async def disable_channel(ctx: Context): class LoggingCog(Cog, name="Logging"): - CONTRIBUTORS = [Contributor.Defelo, Contributor.wolflu, Contributor.Tert0, Contributor.NekoFanatic] + CONTRIBUTORS = [Contributor.Defelo, Contributor.wolflu, Contributor.Tert0, Contributor.Infinity] async def get_logging_channel(self, setting: LoggingSettings) -> Optional[TextChannel]: return self.bot.get_channel(await setting.get()) diff --git a/moderation/spam_detection/cog.py b/moderation/spam_detection/cog.py index 35a3c06ae..79b2377b2 100644 --- a/moderation/spam_detection/cog.py +++ b/moderation/spam_detection/cog.py @@ -30,7 +30,7 @@ async def _send_changes(ctx: Context, amount: int, change_type: str, description class SpamDetectionCog(Cog, name="Spam Detection"): - CONTRIBUTORS = [Contributor.ce_phox, Contributor.Defelo, Contributor.NekoFanatic] + CONTRIBUTORS = [Contributor.ce_phox, Contributor.Defelo, Contributor.Infinity] async def on_voice_state_update(self, member: Member, before: VoiceState, after: VoiceState): """ From 119a3c1b8ad8b2c7e9a91ae2305aba0064bb5744 Mon Sep 17 00:00:00 2001 From: Inf-inity <83883849+Inf-inity@users.noreply.github.com> Date: Mon, 20 Jun 2022 20:50:18 +0200 Subject: [PATCH 32/37] Rewrote code with namedtuples --- general/color_picker/cog.py | 39 +++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 0572b853f..46d05fdf2 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -1,5 +1,6 @@ import colorsys import re +from collections import namedtuple from discord import Colour, Embed from discord.ext import commands @@ -15,15 +16,14 @@ t = t.color_picker -def _to_floats(given: list[tuple[int, ...]]) -> tuple[float, ...]: - """3 tuples (number from user, max-value)""" +def _to_floats(given: list[namedtuple]) -> tuple[float, float, float]: out: list[float] = [] for arg in given: - if 0 < int(arg[0]) > arg[1]: - raise CommandError(t.error.invalid_input(arg[0], arg[1])) + if 0 < int(arg.value) > arg.max_value: + raise CommandError(t.error.invalid_input(arg.value, arg.max_value)) - out.append(float(int(arg[0]) / arg[1])) + out.append(float(int(arg.value) / arg.max_value)) return out[0], out[1], out[2] @@ -33,7 +33,7 @@ def _hex_to_color(hex_color: str) -> tuple[int, ...]: class ColorPickerCog(Cog, name="Color Picker"): - CONTRIBUTORS = [Contributor.Tert0, Contributor.NekoFanatic] + CONTRIBUTORS = [Contributor.Tert0, Contributor.Infinity] RE_HEX = re.compile(r"^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") RE_RGB = re.compile(r"^rgb\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") @@ -43,20 +43,39 @@ class ColorPickerCog(Cog, name="Color Picker"): @commands.command(name="color_picker", aliases=["cp", "color"]) @docs(t.commands.color_picker) async def color_picker(self, ctx: Context, *, color: str): + color_args = namedtuple("ColorParameter", ["value", "max_value"]) if color_re := self.RE_HEX.match(color): rgb = _hex_to_color(color_re.group(1)) - rgb = _to_floats([(rgb[0], 255), (rgb[1], 255), (rgb[2], 255)]) + rgb = _to_floats([color_args(rgb[0], 255), color_args(rgb[1], 255), color_args(rgb[2], 255)]) elif color_re := self.RE_RGB.match(color): - rgb = _to_floats([(color_re.group(1), 255), (color_re.group(2), 255), (color_re.group(3), 255)]) + rgb = _to_floats( + [ + color_args(color_re.group(1), 255), + color_args(color_re.group(2), 255), + color_args(color_re.group(3), 255), + ] + ) elif color_re := self.RE_HSV.match(color): - values = _to_floats([(color_re.group(1), 360), (color_re.group(2), 100), (color_re.group(3), 100)]) + values = _to_floats( + [ + color_args(color_re.group(1), 360), + color_args(color_re.group(2), 100), + color_args(color_re.group(3), 100), + ] + ) rgb = colorsys.hsv_to_rgb(values[0], values[1], values[2]) elif color_re := self.RE_HSL.match(color): - values = _to_floats([(color_re.group(1), 360), (color_re.group(2), 100), (color_re.group(3), 100)]) + values = _to_floats( + [ + color_args(color_re.group(1), 360), + color_args(color_re.group(2), 100), + color_args(color_re.group(3), 100), + ] + ) rgb = colorsys.hls_to_rgb(values[0], values[2], values[1]) else: From e86bec1e686899ff40609ebf91238c64b808f807 Mon Sep 17 00:00:00 2001 From: Inf-inity <83883849+Inf-inity@users.noreply.github.com> Date: Mon, 20 Jun 2022 21:00:24 +0200 Subject: [PATCH 33/37] Fixed mistake in translation --- general/color_picker/translations/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/color_picker/translations/en.yml b/general/color_picker/translations/en.yml index 98950f18b..51dc5e234 100644 --- a/general/color_picker/translations/en.yml +++ b/general/color_picker/translations/en.yml @@ -6,7 +6,7 @@ embed: title: Color Picker error: - invalid_input: "`{}` has to be bigger than `0` and smaller than `{}`" + invalid_input: "`{}` has to be at least `0` or smaller than `{}`" parse_color_example: > **Error cant parse HEX/RGB/HSL/HSV Color Code(`{}`)** From 4f312210a1999aad95aabcc5b24e7b4e9b4a715e Mon Sep 17 00:00:00 2001 From: TheCataliasTNT2k <44349750+TheCataliasTNT2k@users.noreply.github.com> Date: Mon, 20 Jun 2022 21:44:19 +0200 Subject: [PATCH 34/37] Made brackets optional in regex --- general/color_picker/cog.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 46d05fdf2..2d6c48255 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -36,9 +36,9 @@ class ColorPickerCog(Cog, name="Color Picker"): CONTRIBUTORS = [Contributor.Tert0, Contributor.Infinity] RE_HEX = re.compile(r"^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") - RE_RGB = re.compile(r"^rgb\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") - RE_HSV = re.compile(r"^hsv\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") - RE_HSL = re.compile(r"^hsl\(([0-9]{1,3}), *([0-9]{1,3}), *([0-9]{1,3})\)$") + RE_RGB = re.compile(r"^rgb *(\()?([0-9]{1,3}),? *([0-9]{1,3}),? *([0-9]{1,3})(?(1)\)|)$") + RE_HSV = re.compile(r"^hsv *(\()?([0-9]{1,3}),? *([0-9]{1,3}),? *([0-9]{1,3})(?(1)\)|)$") + RE_HSL = re.compile(r"^hsl *(\()?([0-9]{1,3}),? *([0-9]{1,3}),? *([0-9]{1,3})(?(1)\)|)$") @commands.command(name="color_picker", aliases=["cp", "color"]) @docs(t.commands.color_picker) @@ -52,18 +52,19 @@ async def color_picker(self, ctx: Context, *, color: str): elif color_re := self.RE_RGB.match(color): rgb = _to_floats( [ - color_args(color_re.group(1), 255), color_args(color_re.group(2), 255), color_args(color_re.group(3), 255), + color_args(color_re.group(4), 255), ] ) elif color_re := self.RE_HSV.match(color): + print(color_re.groups()) values = _to_floats( [ - color_args(color_re.group(1), 360), - color_args(color_re.group(2), 100), + color_args(color_re.group(2), 360), color_args(color_re.group(3), 100), + color_args(color_re.group(4), 100), ] ) rgb = colorsys.hsv_to_rgb(values[0], values[1], values[2]) @@ -71,9 +72,9 @@ async def color_picker(self, ctx: Context, *, color: str): elif color_re := self.RE_HSL.match(color): values = _to_floats( [ - color_args(color_re.group(1), 360), - color_args(color_re.group(2), 100), + color_args(color_re.group(2), 360), color_args(color_re.group(3), 100), + color_args(color_re.group(4), 100), ] ) rgb = colorsys.hls_to_rgb(values[0], values[2], values[1]) From 8cae34e200e35682483e2dc05bdb4e92bf7b62ef Mon Sep 17 00:00:00 2001 From: Inf-inity <83883849+Inf-inity@users.noreply.github.com> Date: Mon, 20 Jun 2022 22:28:17 +0200 Subject: [PATCH 35/37] Refactored code --- general/color_picker/cog.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 2d6c48255..8d520fe6e 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -36,9 +36,10 @@ class ColorPickerCog(Cog, name="Color Picker"): CONTRIBUTORS = [Contributor.Tert0, Contributor.Infinity] RE_HEX = re.compile(r"^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$") - RE_RGB = re.compile(r"^rgb *(\()?([0-9]{1,3}),? *([0-9]{1,3}),? *([0-9]{1,3})(?(1)\)|)$") - RE_HSV = re.compile(r"^hsv *(\()?([0-9]{1,3}),? *([0-9]{1,3}),? *([0-9]{1,3})(?(1)\)|)$") - RE_HSL = re.compile(r"^hsl *(\()?([0-9]{1,3}),? *([0-9]{1,3}),? *([0-9]{1,3})(?(1)\)|)$") + REG = r" *(\()?([0-9]{1,3}),? *([0-9]{1,3}),? *([0-9]{1,3})(?(1)\)|)$" + RE_RGB = re.compile(r"^rgb" + REG) + RE_HSV = re.compile(r"^hsv" + REG) + RE_HSL = re.compile(r"^hsl" + REG) @commands.command(name="color_picker", aliases=["cp", "color"]) @docs(t.commands.color_picker) @@ -59,7 +60,6 @@ async def color_picker(self, ctx: Context, *, color: str): ) elif color_re := self.RE_HSV.match(color): - print(color_re.groups()) values = _to_floats( [ color_args(color_re.group(2), 360), From 0b5e139edf7f931c2444f455879452b6f6f2deed Mon Sep 17 00:00:00 2001 From: Inf-inity <83883849+Inf-inity@users.noreply.github.com> Date: Mon, 27 Jun 2022 20:45:12 +0200 Subject: [PATCH 36/37] Resolved change requests --- general/color_picker/cog.py | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 8d520fe6e..9078a4e55 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -16,7 +16,11 @@ t = t.color_picker -def _to_floats(given: list[namedtuple]) -> tuple[float, float, float]: +COLOR_ARGS = namedtuple("ColorParameter", ["value", "max_value"]) +COLOR = namedtuple("RGB_Tuple", ["R", "G", "B"]) + + +def _to_floats(given: list[COLOR_ARGS]) -> tuple[float, float, float]: out: list[float] = [] for arg in given: @@ -28,8 +32,8 @@ def _to_floats(given: list[namedtuple]) -> tuple[float, float, float]: return out[0], out[1], out[2] -def _hex_to_color(hex_color: str) -> tuple[int, ...]: - return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4)) # noqa: E203 +def _hex_to_color(hex_color: str) -> COLOR: + return COLOR(*tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))) # noqa: E203 class ColorPickerCog(Cog, name="Color Picker"): @@ -44,39 +48,20 @@ class ColorPickerCog(Cog, name="Color Picker"): @commands.command(name="color_picker", aliases=["cp", "color"]) @docs(t.commands.color_picker) async def color_picker(self, ctx: Context, *, color: str): - color_args = namedtuple("ColorParameter", ["value", "max_value"]) if color_re := self.RE_HEX.match(color): rgb = _hex_to_color(color_re.group(1)) - rgb = _to_floats([color_args(rgb[0], 255), color_args(rgb[1], 255), color_args(rgb[2], 255)]) + rgb = _to_floats([COLOR_ARGS(rgb[i], 255) for i in range(3)]) elif color_re := self.RE_RGB.match(color): - rgb = _to_floats( - [ - color_args(color_re.group(2), 255), - color_args(color_re.group(3), 255), - color_args(color_re.group(4), 255), - ] - ) + rgb = _to_floats([COLOR_ARGS(color_re.group(i), 255) for i in range(2, 5)]) elif color_re := self.RE_HSV.match(color): - values = _to_floats( - [ - color_args(color_re.group(2), 360), - color_args(color_re.group(3), 100), - color_args(color_re.group(4), 100), - ] - ) + values = _to_floats([COLOR_ARGS(color_re.group(i[0]), i[1]) for i in ((2, 360), (3, 100), (4, 100))]) rgb = colorsys.hsv_to_rgb(values[0], values[1], values[2]) elif color_re := self.RE_HSL.match(color): - values = _to_floats( - [ - color_args(color_re.group(2), 360), - color_args(color_re.group(3), 100), - color_args(color_re.group(4), 100), - ] - ) + values = _to_floats([COLOR_ARGS(color_re.group(i[0]), i[1]) for i in ((2, 360), (3, 100), (4, 100))]) rgb = colorsys.hls_to_rgb(values[0], values[2], values[1]) else: From 1e2121da89fb353e8e895abbcb6edc2cad34904b Mon Sep 17 00:00:00 2001 From: Inf-inity <83883849+Inf-inity@users.noreply.github.com> Date: Mon, 27 Jun 2022 20:57:59 +0200 Subject: [PATCH 37/37] Formatted code --- general/color_picker/cog.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/general/color_picker/cog.py b/general/color_picker/cog.py index 9078a4e55..4b00cd3f2 100644 --- a/general/color_picker/cog.py +++ b/general/color_picker/cog.py @@ -21,6 +21,10 @@ def _to_floats(given: list[COLOR_ARGS]) -> tuple[float, float, float]: + """ + takes a list with tuples containing a value and a max_values + at the end it should return a number between 0 and 1 for each tuple + """ out: list[float] = [] for arg in given: @@ -57,12 +61,14 @@ async def color_picker(self, ctx: Context, *, color: str): rgb = _to_floats([COLOR_ARGS(color_re.group(i), 255) for i in range(2, 5)]) elif color_re := self.RE_HSV.match(color): - values = _to_floats([COLOR_ARGS(color_re.group(i[0]), i[1]) for i in ((2, 360), (3, 100), (4, 100))]) - rgb = colorsys.hsv_to_rgb(values[0], values[1], values[2]) + rgb = colorsys.hsv_to_rgb( + *_to_floats([COLOR_ARGS(color_re.group(i), value) for i, value in ((2, 360), (3, 100), (4, 100))]) + ) elif color_re := self.RE_HSL.match(color): - values = _to_floats([COLOR_ARGS(color_re.group(i[0]), i[1]) for i in ((2, 360), (3, 100), (4, 100))]) - rgb = colorsys.hls_to_rgb(values[0], values[2], values[1]) + rgb = colorsys.hls_to_rgb( + *_to_floats([COLOR_ARGS(color_re.group(i), value) for i, value in ((2, 360), (3, 100), (4, 100))]) + ) else: raise CommandError(t.error.parse_color_example(color))