From fe2de3269be7aa57eebebc2321cba01c91a26ae7 Mon Sep 17 00:00:00 2001 From: Lui Date: Sat, 21 Oct 2023 22:56:42 -0700 Subject: [PATCH] [VxTwit] Add `ddinstagram.com` replacements (#656) * [VxTwit] Add `ddinstagram.com` replacements This commit adds event listeners to replace instagram.com links with ddinstagram.com. It is using the same toggle as VxTwit. Since instagram.com embeds don't have videos or photos, we will need to replace all embeds. As such, the `valid` method was modified to not check for videos in embeds: this is deferred to a later check for the VxTwitter case. This commit doesn't change the cog name; this will be done in a follow up. * [VxTwit] Use Enum for SocialMedia * [VxTwit] Remove unnecessary debug statement * [VxTwit] Sort the imports * [VxTwit] Move INSTA_REGEX_MATCH to constants.py * [VxTwit] Refactor urls_to_string Co-authored-by: Dat Quach * [VxTwit] Fix docstrings * [VxTwit] Compile regex pattern Co-authored-by: Dat Quach * [VxTwit] Add on_message_edit listener for instagram --- cogs/vxtwitconverter/constants.py | 10 ++++- cogs/vxtwitconverter/eventHandlers.py | 2 + cogs/vxtwitconverter/eventsCore.py | 62 +++++++++++++++++++++++++-- cogs/vxtwitconverter/helpers.py | 51 +++++++++++++++++----- 4 files changed, 109 insertions(+), 16 deletions(-) diff --git a/cogs/vxtwitconverter/constants.py b/cogs/vxtwitconverter/constants.py index e59a59af469..82c5baf0445 100644 --- a/cogs/vxtwitconverter/constants.py +++ b/cogs/vxtwitconverter/constants.py @@ -1,3 +1,11 @@ -KEY_ENABLED = "enabled" +import enum +import re +KEY_ENABLED = "enabled" DEFAULT_GUILD = {KEY_ENABLED: False} +INSTA_REGEX_PATTERN = re.compile(r"https://(?:www\.)?(instagram.com)") + + +class SocialMedia(enum.Enum): + INSTAGRAM = "Instagram" + TWITTER = "Twitter" diff --git a/cogs/vxtwitconverter/eventHandlers.py b/cogs/vxtwitconverter/eventHandlers.py index 0f43e0a869b..84a2e096cc1 100644 --- a/cogs/vxtwitconverter/eventHandlers.py +++ b/cogs/vxtwitconverter/eventHandlers.py @@ -9,7 +9,9 @@ class EventHandlers(EventsCore): @commands.Cog.listener("on_message") async def twit_replacer(self, message: Message): await self._on_message_twit_replacer(message) + await self._on_message_insta_replacer(message) @commands.Cog.listener("on_message_edit") async def twit_edit_replacer(self, message_before: Message, message_after): await self._on_edit_twit_replacer(message_before, message_after) + await self._on_edit_insta_replacer(message_before, message_after) diff --git a/cogs/vxtwitconverter/eventsCore.py b/cogs/vxtwitconverter/eventsCore.py index f303311b9f7..cddbab9630f 100644 --- a/cogs/vxtwitconverter/eventsCore.py +++ b/cogs/vxtwitconverter/eventsCore.py @@ -1,11 +1,65 @@ from discord import Message -from .constants import KEY_ENABLED +from .constants import KEY_ENABLED, SocialMedia from .core import Core -from .helpers import convert_to_vx_twitter_url, urls_to_string, valid +from .helpers import convert_to_ddinsta_url, convert_to_vx_twitter_url, urls_to_string, valid class EventsCore(Core): + async def _on_message_insta_replacer(self, message: Message): + if not valid(message): + return + + if not await self.config.guild(message.guild).get_attr(KEY_ENABLED)(): + self.logger.debug( + "VxTwit disabled for guild %s (%s), skipping", message.guild.name, message.guild.id + ) + return + + ddinsta_urls = convert_to_ddinsta_url(message.embeds) + + if not ddinsta_urls: + return + + # constructs the message and replies with a mention + ok = await message.reply(urls_to_string(ddinsta_urls, SocialMedia.INSTAGRAM)) + + # Remove embeds from user message if reply is successful + if ok: + await message.edit(suppress=True) + + async def _on_edit_insta_replacer(self, message_before: Message, message_after: Message): + if not valid(message_after): + return + + if not await self.config.guild(message_after.guild).get_attr(KEY_ENABLED)(): + self.logger.debug( + "VxTwit disabled for guild %s (%s), skipping", + message_after.guild.name, + message_after.guild.id, + ) + return + + new_embeds = [ + embed for embed in message_after.embeds if embed not in message_before.embeds + ] + + # skips if the message has no new embeds + if not new_embeds: + return + + ddinsta_urls = convert_to_ddinsta_url(new_embeds) + + if not ddinsta_urls: + return + + # constructs the message and replies with a mention + ok = await message_after.reply(urls_to_string(ddinsta_urls, SocialMedia.INSTAGRAM)) + + # Remove embeds from user message if reply is successful + if ok: + await message_after.edit(suppress=True) + async def _on_message_twit_replacer(self, message: Message): if not valid(message): return @@ -24,7 +78,7 @@ async def _on_message_twit_replacer(self, message: Message): return # constructs the message and replies with a mention - ok = await message.reply(urls_to_string(vx_twtter_urls)) + ok = await message.reply(urls_to_string(vx_twtter_urls, SocialMedia.TWITTER)) # Remove embeds from user message if reply is successful if ok: @@ -60,7 +114,7 @@ async def _on_edit_twit_replacer(self, message_before: Message, message_after: M return # constructs the message and replies with a mention - ok = await message_after.reply(urls_to_string(vx_twtter_urls)) + ok = await message_after.reply(urls_to_string(vx_twtter_urls, SocialMedia.TWITTER)) # Remove embeds from user message if reply is successful if ok: diff --git a/cogs/vxtwitconverter/helpers.py b/cogs/vxtwitconverter/helpers.py index c7fb2e79647..e5fc444dbef 100644 --- a/cogs/vxtwitconverter/helpers.py +++ b/cogs/vxtwitconverter/helpers.py @@ -1,11 +1,38 @@ +import re + from discord import Embed, Message, channel +from .constants import INSTA_REGEX_PATTERN, SocialMedia + + +def convert_to_ddinsta_url(embeds: list[Embed]): + """ + Parameters + ---------- + embeds: list of Discord embeds + + Returns + ------- + filtered list of Instagram URLs that have been converted to ddinstagram + """ + + # pulls only video embeds from list of embeds + urls = [entry.url for entry in embeds] + + ddinsta_urls = [ + re.sub(INSTA_REGEX_PATTERN, r"https://dd\1", result) + for result in urls + if re.match(INSTA_REGEX_PATTERN, result) + ] + + return ddinsta_urls + def convert_to_vx_twitter_url(embeds: list[Embed]): """ Parameters ---------- - embeds: list of discord embeds + embeds: list of Discord embeds Returns ------- @@ -24,23 +51,25 @@ def convert_to_vx_twitter_url(embeds: list[Embed]): return vxtwitter_urls -def urls_to_string(vx_twit_links: list[str]): +def urls_to_string(links: list[str], socialMedia: SocialMedia): """ Parameters ---------- - vx_twit_links: list of urls + links: list[str] + A list of urls + socialMedia: SocialMedia + The social media to replace. Returns ------- Formatted output """ - - return "".join( + return "\n".join( [ - "OwO what's this?\n", - "*notices your terrible twitter embeds*\n", - "Here's a better alternative:\n", - "\n".join(vx_twit_links), + "OwO what's this?", + f"*notices your terrible {socialMedia.value} embeds*", + "Here's a better alternative:", + *links, ] ) @@ -53,7 +82,7 @@ def valid(message: Message): Returns ------- - True if the message is from a human in a guild and contains video embeds + True if the message is from a human in a guild and contains embeds False otherwise """ @@ -66,7 +95,7 @@ def valid(message: Message): return False # skips if the message has no embeds - if not any(embed.video for embed in message.embeds): + if not message.embeds: return False return True