From 8e27794963cb6151c157d7d349404d4a4c3b9431 Mon Sep 17 00:00:00 2001 From: Raiden Sakura Date: Thu, 4 Apr 2024 23:22:50 +0800 Subject: [PATCH] Fix #3240 --- core/clients.py | 9 +++++ core/thread.py | 88 ++++++++++++++++++++++++++----------------------- core/utils.py | 27 +++++++++++++++ 3 files changed, 83 insertions(+), 41 deletions(-) diff --git a/core/clients.py b/core/clients.py index e80225d9e9..8f4171d88d 100644 --- a/core/clients.py +++ b/core/clients.py @@ -680,6 +680,15 @@ async def append_log( } for a in message.attachments ], + "stickers": [ + { + "format": s.format, + "id": s.id, + "name": s.name, + "url": s.url, + } + for s in message.stickers + ], } return await self.logs.find_one_and_update( diff --git a/core/thread.py b/core/thread.py index 556c1a30dc..03c66deab0 100644 --- a/core/thread.py +++ b/core/thread.py @@ -17,6 +17,7 @@ ConfirmThreadCreationView, DenyButton, DummyParam, + convert_sticker, create_thread_channel, get_joint_id, get_top_role, @@ -943,6 +944,11 @@ async def send( if not self.ready: await self.wait_until_ready() + for i, sticker in enumerate(message.stickers): + url = convert_sticker(sticker) + if url: + message.stickers[i] = sticker + if not from_mod and not note: self.bot.loop.create_task(self.bot.api.append_log(message, channel_id=self.channel.id)) @@ -995,7 +1001,8 @@ async def send( url=f"https://discordapp.com/users/{author.id}#{message.id}", ) - ext = [(a.url, a.filename, False) for a in message.attachments] + ext = [(a.url, a.filename) for a in message.attachments] + stickers = [(a.id, a.url, a.name) for a in message.stickers] images = [] attachments = [] @@ -1005,62 +1012,41 @@ async def send( else: attachments.append(attachment) - image_urls = re.findall( - r"http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[.\-]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", + image_regex = re.findall( + r"http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[\/#%&\-+.?=]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", message.content, ) - image_urls = [ - (is_image_url(url, convert_size=False), None, False) - for url in image_urls - if is_image_url(url, convert_size=False) - ] - images.extend(image_urls) - images.extend( - ( - i.url - if i.format in (discord.StickerFormatType.png, discord.StickerFormatType.apng) - else None, - i.name, - True, - ) - for i in message.stickers - ) + for match in image_regex: + if is_image_url(match, convert_size=False): + images.append((match, None)) - embedded_image = False + img_on_first_embed = False prioritize_uploads = any(i[1] is not None for i in images) additional_images = [] additional_count = 1 - for url, filename, is_sticker in images: + if note: + color = self.bot.main_color + elif from_mod: + color = self.bot.mod_color + else: + color = self.bot.recipient_color + + for url, filename in images: if ( not prioritize_uploads or ((url is None or is_image_url(url)) and filename) - ) and not embedded_image: - if url is not None: + ) and not img_on_first_embed: + if url: embed.set_image(url=url) if filename: - if is_sticker: - if url is None: - description = f"{filename}: Unable to retrieve sticker image" - else: - description = f"[{filename}]({url})" - embed.add_field(name="Sticker", value=description) - else: - embed.add_field(name="Image", value=f"[{filename}]({url})") - embedded_image = True + embed.add_field(name="Image", value=f"[{filename}]({url})") + img_on_first_embed = True else: - if note: - color = self.bot.main_color - elif from_mod: - color = self.bot.mod_color - else: - color = self.bot.recipient_color - img_embed = discord.Embed(color=color) - - if url is not None: + if url: img_embed.set_image(url=url) img_embed.url = url if filename is not None: @@ -1070,6 +1056,26 @@ async def send( additional_images.append(destination.send(embed=img_embed)) additional_count += 1 + for id, url, name in stickers: + if not img_on_first_embed: + embed.set_image(url=url) + embed.add_field(name="Sticker", value=f"[{name}]({url})", inline=False) + embed.url = url + embed.timestamp = message.created_at + else: + if note: + color = self.bot.main_color + elif from_mod: + color = self.bot.mod_color + else: + color = self.bot.recipient_color + sticker_embed = discord.Embed(color=self.bot.main_color) + sticker_embed.set_image(url=url) + sticker_embed.add_field(name="Sticker", value=f"[{name}]({url})", inline=False) + sticker_embed.url = url + sticker_embed.timestamp = message.created_at + additional_images.append(destination.send(embed=sticker_embed)) + file_upload_count = 1 for url, filename, _ in attachments: diff --git a/core/utils.py b/core/utils.py index e16aa45ba0..60fb119255 100644 --- a/core/utils.py +++ b/core/utils.py @@ -592,3 +592,30 @@ class DummyParam: def __init__(self, name): self.name = name self.displayed_name = name + + +def convert_sticker(sticker: discord.Sticker) -> str: + """A method to convert Discord sticker object into a displayable image URL. + + Parameters + ---------- + sticker : discord.Sticker + Discord sticker object. + + Returns + ------- + Optional[str] + URL of the image if successfully converted + """ + url = None + if sticker.format.name == "png": + url = sticker.url + elif sticker.format.name == "apng": + logger.debug("Unable to convert APNG sticker") + elif sticker.format.name == "lottie": + logger.debug("Unable to convert Lottie sticker") + elif sticker.format.name == "gif": + pattern = r"(https://)cdn\.discordapp\.com(/.+)" + replacement = r"\1media.discordapp.net\2" + url = re.sub(pattern, replacement, sticker.url) + return url