diff --git a/lynxie/assets/liveleak.png b/lynxie/assets/liveleak.png new file mode 100644 index 0000000..351201c Binary files /dev/null and b/lynxie/assets/liveleak.png differ diff --git a/lynxie/commands/image.py b/lynxie/commands/image.py index 2f0285f..a1b3806 100644 --- a/lynxie/commands/image.py +++ b/lynxie/commands/image.py @@ -15,81 +15,73 @@ class Img(commands.Cog): def __init__(self, bot): self.bot = bot + @staticmethod + async def get_image_attachments(ctx): + if ctx.message.attachments: + return ctx.message.attachments[0] + elif ctx.message.reference: + if ctx.message.reference.resolved.attachments: + return ctx.message.reference.resolved.attachments[0] + elif ctx.message.reference.resolved.embeds and ctx.message.reference.resolved.embeds[0].image: + return ctx.message.reference.resolved.embeds[0].image + elif ctx.message.embeds and ctx.message.embeds[0].image: + return ctx.message.embeds[0].image + else: + channel = ctx.guild.get_channel(ctx.channel.id) + async for message in channel.history(limit=10): + if message.attachments: + return message.attachments[0] + break + if message.embeds and message.embeds[0].image: + return message.embeds[0].image + break + + return None + @commands.command() - async def overlay( - self, ctx, overlay_choice: str = None, overlay_style: str = "default" - ): + async def overlay(self, ctx, overlay_choice: str = None, overlay_style: str = "default"): start_time = datetime.datetime.now() overlay_choice = overlay_choice.lower().strip() if overlay_choice else None overlay_style = overlay_style.lower().strip() if overlay_style else "default" - image_attachments = None - if ctx.message.attachments: - image_attachments = ctx.message.attachments[0] - elif ctx.message.reference and ctx.message.reference.resolved.attachments: - image_attachments = ctx.message.reference.resolved.attachments[0] - elif ctx.message.embeds and ctx.message.embeds[0].image: - image_attachments = ctx.message.embeds[0].image - else: - channel = ctx.guild.get_channel(ctx.channel.id) - async for message in channel.history(limit=10): - if message.attachments: - image_attachments = message.attachments[0] - break - if message.embeds and message.embeds[0].image: - image_attachments = message.embeds[0].image - break + image_attachments = await self.get_image_attachments(ctx) + + if not image_attachments: + error = "No image was found!" + await ctx.reply(embed=error_message(error)) + return + + if not overlay_choice or overlay_choice not in IMAGE_OVERLAYS: + error = f"Invalid overlay choice! Use one of these: {', '.join(IMAGE_OVERLAYS)}" + await ctx.reply(embed=error_message(error)) + return + + if overlay_style not in IMAGE_OVERLAYS[overlay_choice]["options"]: + error = f"{overlay_choice} has these options: {', '.join(IMAGE_OVERLAYS[overlay_choice]['options'])}" + await ctx.reply(embed=error_message(error)) + return + + # Defaults to gwa as I cant be asked to make a better error handler + file_name = (image_attachments.filename or image_attachments.url or "balls").lower() + file_extension = file_name.split(".")[-1] + if file_extension not in IMAGE_EXTENSIONS: + error = f"Unsupported file type! Use one of these: {', '.join(IMAGE_EXTENSIONS)}" + await ctx.reply(embed=error_message(error)) + return + + if image_attachments.size and image_attachments.size > 8 * 1024 * 1024: + error = "Image must be less than 8MB!" + await ctx.reply(embed=error_message(error)) + return + + width, height = image_attachments.width, image_attachments.height + if not 10 < width <= 4500 or not 10 < height <= 4500: + error = "Image must be at least 10x10 and under 4500x4500!" + await ctx.reply(embed=error_message(error)) + return async with ctx.typing(): - if not image_attachments: - error = "No image was found!" - await ctx.reply(embed=error_message(error)) - return - - if not overlay_choice or overlay_choice not in IMAGE_OVERLAYS: - error = ( - "That is not a valid option! Valid options are:\n" - f"`{', '.join(IMAGE_OVERLAYS)}`" - ) - await ctx.reply(embed=error_message(error)) - return - - if overlay_style not in IMAGE_OVERLAYS[overlay_choice]["options"]: - error = ( - "That is not a valid option! Valid options are:\n" - f"`{', '.join(IMAGE_OVERLAYS[overlay_choice]['options'])}`" - ) - await ctx.reply(embed=error_message(error)) - return - - # Defaults to gwa as I cant be asked to make a better error handler - filename = ( - image_attachments.filename or image_attachments.url or "image.gwa" - ) - if not filename.split(".")[-1].lower() in IMAGE_EXTENSIONS: - error = "Unsupported file type! Supported file types are " ", ".join( - IMAGE_EXTENSIONS - ) - await ctx.reply(embed=error_message(error)) - return - - if image_attachments.size and image_attachments.size > 8 * 1024 * 1024: - error = ( - "That image is too big! " - "Please use an image that is less than 8MB." - ) - await ctx.reply(embed=error_message(error)) - return - - if ( - not 10 < image_attachments.width <= 3500 - or not 10 < image_attachments.height <= 3500 - ): - error = "Image must be at least 10x10 and under 3500x3500!" - await ctx.reply(embed=error_message(error)) - return - request = requests.get(image_attachments.url) attachment = Image.open(BytesIO(request.content)) width, height = attachment.width, attachment.height @@ -149,6 +141,10 @@ class Img(commands.Cog): ((width - overlay.width) // 2, height - overlay.height), overlay, ) + elif overlay_choice == "liveleak": + overlay = Image.open(IMAGE_OVERLAYS[overlay_choice]["path"]) + overlay.thumbnail((width, overlay.height)) + attachment.paste(overlay, (0, 0), overlay) with BytesIO() as response: attachment.save(response, format="PNG") @@ -167,3 +163,59 @@ class Img(commands.Cog): ) await ctx.reply(embed=embed, file=response, mention_author=False) + + + @commands.command() + async def saveable(self, ctx): + start_time = datetime.datetime.now() + + image_attachments = await self.get_image_attachments(ctx) + + if not image_attachments: + error = "No image was found!" + await ctx.reply(embed=error_message(error)) + return + + # Defaults to gwa as I cant be asked to make a better error handler + file_name = (image_attachments.filename or image_attachments.url or "balls").lower() + file_extension = file_name.split(".")[-1] + if file_extension not in IMAGE_EXTENSIONS: + error = f"Unsupported file type! Use one of these: {', '.join(IMAGE_EXTENSIONS)}" + await ctx.reply(embed=error_message(error)) + return + + if image_attachments.size and image_attachments.size > 8 * 1024 * 1024: + error = "Image must be less than 8MB!" + await ctx.reply(embed=error_message(error)) + return + + width, height = image_attachments.width, image_attachments.height + if not 10 < width <= 4500 or not 10 < height <= 4500: + error = "Image must be at least 10x10 and under 4500x4500!" + await ctx.reply(embed=error_message(error)) + return + + async with ctx.typing(): + request = requests.get(image_attachments.url) + attachment = Image.open(BytesIO(request.content)) + width, height = attachment.width, attachment.height + + with BytesIO() as response: + attachment.save(response, format="GIF") + + response.seek(0) + response = discord.File(response, filename="image.gif") + + time_taken = (datetime.datetime.now() - start_time).microseconds / 1000 + + embed = ( + discord.Embed( + title="Saveable", + description="Image converted to GIF, click the star to save it :3", + colour=discord.Colour.orange(), + ) + .set_image(url="attachment://image.gif") + .set_footer(text=f"{width}x{height}, {time_taken}ms") + ) + + await ctx.reply(embed=embed, file=response, mention_author=False) diff --git a/lynxie/config.py b/lynxie/config.py index 7341c0a..4d1c153 100644 --- a/lynxie/config.py +++ b/lynxie/config.py @@ -75,4 +75,8 @@ IMAGE_OVERLAYS = { "path": os.path.join(ASSETS_PATH, "jerm-a.png"), "options": ["default"], }, + "liveleak": { + "path": os.path.join(ASSETS_PATH, "liveleak.png"), + "options": ["default"], + }, }