From ecc33e02757b1e2a243b6761ae9478b72558e2c4 Mon Sep 17 00:00:00 2001 From: Anonymous4045 <99518880+Anonymous4045@users.noreply.github.com> Date: Mon, 14 Nov 2022 22:01:30 -0600 Subject: [PATCH 01/10] Add ability to view previous topics with .topic command After a user invokes the ".topic" command and reacts with the reroll emoji, the embed will now show the previous few messages. It cannot display more than 256 characters, which is usually around 5 prompts. Implements: #1145 --- bot/exts/utilities/conversationstarters.py | 61 ++++++++++++++++------ 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index 410ea884a6..f15eddafce 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -43,7 +43,7 @@ def __init__(self, bot: Bot): self.bot = bot @staticmethod - def _build_topic_embed(channel_id: int) -> discord.Embed: + def _build_topic_embed(channel_id: int, previous_topic: None | str) -> discord.Embed: """ Build an embed containing a conversation topic. @@ -56,21 +56,46 @@ def _build_topic_embed(channel_id: int) -> discord.Embed: color=discord.Colour.og_blurple() ) - try: - channel_topics = TOPICS[channel_id] - except KeyError: - # Channel doesn't have any topics. - embed.title = f"**{next(TOPICS['default'])}**" + if previous_topic is None: + # Message first sent + try: + channel_topics = TOPICS[channel_id] + except KeyError: + # Channel doesn't have any topics. + embed.title = f"**{next(TOPICS['default'])}**" + else: + embed.title = f"**{next(channel_topics)}**" else: - embed.title = f"**{next(channel_topics)}**" + # Message is being edited + + try: + channel_topics = TOPICS[channel_id] + except KeyError: + # Channel doesn't have any topics. + new_topic = f"**{next(TOPICS['default'])}**" + else: + new_topic = f"\n**{next(channel_topics)}**" + + total_topics = previous_topic.count("\n") + 1 + + # Add 1 before first topic + if total_topics == 1: + previous_topic = f"1. {previous_topic}" + + embed.title = previous_topic + f"\n{total_topics + 1}. {new_topic}" + + # When the embed will be larger than the limit, use the previous embed instead + if len(embed.title) > 256: + embed.title = previous_topic + return embed @staticmethod def _predicate( - command_invoker: Union[discord.User, discord.Member], - message: discord.Message, - reaction: discord.Reaction, - user: discord.User + command_invoker: Union[discord.User, discord.Member], + message: discord.Message, + reaction: discord.Reaction, + user: discord.User ) -> bool: user_is_moderator = any(role.id in MODERATION_ROLES for role in getattr(user, "roles", [])) user_is_invoker = user.id == command_invoker.id @@ -83,9 +108,9 @@ def _predicate( return is_right_reaction async def _listen_for_refresh( - self, - command_invoker: Union[discord.User, discord.Member], - message: discord.Message + self, + command_invoker: Union[discord.User, discord.Member], + message: discord.Message ) -> None: await message.add_reaction("🔄") while True: @@ -101,7 +126,9 @@ async def _listen_for_refresh( break try: - await message.edit(embed=self._build_topic_embed(message.channel.id)) + # The returned discord.Message object from discord.Message.edit is different than the current + # discord.Message object, so it must be reassigned to update properly + message = await message.edit(embed=self._build_topic_embed(message.channel.id, message.embeds[0].title)) except discord.NotFound: break @@ -109,7 +136,7 @@ async def _listen_for_refresh( await message.remove_reaction(reaction, user) @commands.command() - @commands.cooldown(1, 60*2, commands.BucketType.channel) + @commands.cooldown(1, 60 * 2, commands.BucketType.channel) @whitelist_override(channels=ALL_ALLOWED_CHANNELS) async def topic(self, ctx: commands.Context) -> None: """ @@ -117,7 +144,7 @@ async def topic(self, ctx: commands.Context) -> None: Allows the refresh of a topic by pressing an emoji. """ - message = await ctx.send(embed=self._build_topic_embed(ctx.channel.id)) + message = await ctx.send(embed=self._build_topic_embed(ctx.channel.id, None)) self.bot.loop.create_task(self._listen_for_refresh(ctx.author, message)) From 7c1f0f8170871b00876e3417b154b734a6dbf415 Mon Sep 17 00:00:00 2001 From: Anonymous4045 <99518880+Anonymous4045@users.noreply.github.com> Date: Tue, 15 Nov 2022 18:15:45 -0600 Subject: [PATCH 02/10] Fix rerolled message in channels with specific topics --- bot/exts/utilities/conversationstarters.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index f15eddafce..dd68ba035a 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -67,14 +67,13 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> discord.E embed.title = f"**{next(channel_topics)}**" else: # Message is being edited - try: channel_topics = TOPICS[channel_id] except KeyError: # Channel doesn't have any topics. new_topic = f"**{next(TOPICS['default'])}**" else: - new_topic = f"\n**{next(channel_topics)}**" + new_topic = f"**{next(channel_topics)}**" total_topics = previous_topic.count("\n") + 1 @@ -126,7 +125,7 @@ async def _listen_for_refresh( break try: - # The returned discord.Message object from discord.Message.edit is different than the current + # The returned discord.Message object from discord.Message.edit is different from the current # discord.Message object, so it must be reassigned to update properly message = await message.edit(embed=self._build_topic_embed(message.channel.id, message.embeds[0].title)) except discord.NotFound: From 823e8e71d0c1e6e37516be8c42ee98593be153a0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 22 Dec 2022 01:19:46 +0000 Subject: [PATCH 03/10] Reformat conversationstarters.py Revert the extra whitespaces added by my formatter to meet the style guide. --- bot/exts/utilities/conversationstarters.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index dd68ba035a..874215da34 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -91,10 +91,10 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> discord.E @staticmethod def _predicate( - command_invoker: Union[discord.User, discord.Member], - message: discord.Message, - reaction: discord.Reaction, - user: discord.User + command_invoker: Union[discord.User, discord.Member], + message: discord.Message, + reaction: discord.Reaction, + user: discord.User ) -> bool: user_is_moderator = any(role.id in MODERATION_ROLES for role in getattr(user, "roles", [])) user_is_invoker = user.id == command_invoker.id @@ -107,9 +107,9 @@ def _predicate( return is_right_reaction async def _listen_for_refresh( - self, - command_invoker: Union[discord.User, discord.Member], - message: discord.Message + self, + command_invoker: Union[discord.User, discord.Member], + message: discord.Message ) -> None: await message.add_reaction("🔄") while True: @@ -135,7 +135,7 @@ async def _listen_for_refresh( await message.remove_reaction(reaction, user) @commands.command() - @commands.cooldown(1, 60 * 2, commands.BucketType.channel) + @commands.cooldown(1, 60*2, commands.BucketType.channel) @whitelist_override(channels=ALL_ALLOWED_CHANNELS) async def topic(self, ctx: commands.Context) -> None: """ From 9ec251ac416add77600224c8f369f7067f6bd1fe Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 22 Dec 2022 01:49:32 +0000 Subject: [PATCH 04/10] Optimize nested code in conversationstarters.py This commit will remove some duplicate and unnecessary code, as suggested by @ChrisLovering. --- bot/exts/utilities/conversationstarters.py | 42 +++++++++------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index 874215da34..103ebdac1b 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -56,36 +56,28 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> discord.E color=discord.Colour.og_blurple() ) - if previous_topic is None: - # Message first sent - try: - channel_topics = TOPICS[channel_id] - except KeyError: - # Channel doesn't have any topics. - embed.title = f"**{next(TOPICS['default'])}**" - else: - embed.title = f"**{next(channel_topics)}**" + try: + channel_topics = TOPICS[channel_id] + except KeyError: + # Channel doesn't have any topics. + embed.title = f"**{next(TOPICS['default'])}**" else: - # Message is being edited - try: - channel_topics = TOPICS[channel_id] - except KeyError: - # Channel doesn't have any topics. - new_topic = f"**{next(TOPICS['default'])}**" - else: - new_topic = f"**{next(channel_topics)}**" + embed.title = f"**{next(channel_topics)}**" - total_topics = previous_topic.count("\n") + 1 + if previous_topic is None: + # This is the first topic being sent + return embed - # Add 1 before first topic - if total_topics == 1: - previous_topic = f"1. {previous_topic}" + total_topics = previous_topic.count("\n") + 1 + # Add 1 before first topic + if total_topics == 1: + previous_topic = f"1. {previous_topic}" - embed.title = previous_topic + f"\n{total_topics + 1}. {new_topic}" + embed.title = previous_topic + f"\n{total_topics + 1}. {embed.title}" - # When the embed will be larger than the limit, use the previous embed instead - if len(embed.title) > 256: - embed.title = previous_topic + # When the embed will be larger than the limit, use the previous embed instead + if len(embed.title) > 256: + embed.title = previous_topic return embed From fdc18943f1cdc9f3f3d399e2d3092c5e22527399 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 23 Dec 2022 01:27:53 +0000 Subject: [PATCH 05/10] Remove reroll reaction at max embed length Once the number of characters in the embed's title exceeds the limit of 256, the bot will remove the reroll emoji. Suggested (here)[https://github.com/python-discord/sir-lancebot/pull/1148#issuecomment-1362778083] --- bot/exts/utilities/conversationstarters.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index 103ebdac1b..26850616c2 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -43,12 +43,14 @@ def __init__(self, bot: Bot): self.bot = bot @staticmethod - def _build_topic_embed(channel_id: int, previous_topic: None | str) -> discord.Embed: + def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[discord.Embed, bool]: """ Build an embed containing a conversation topic. If in a Python channel, a python-related topic will be given. Otherwise, a random conversation topic will be received by the user. + + Also returns a value that determines whether or not to remove the reaction afterwards """ # No matter what, the form will be shown. embed = discord.Embed( @@ -66,7 +68,7 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> discord.E if previous_topic is None: # This is the first topic being sent - return embed + return embed, False total_topics = previous_topic.count("\n") + 1 # Add 1 before first topic @@ -78,8 +80,9 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> discord.E # When the embed will be larger than the limit, use the previous embed instead if len(embed.title) > 256: embed.title = previous_topic + return embed, True - return embed + return embed, False @staticmethod def _predicate( @@ -119,7 +122,10 @@ async def _listen_for_refresh( try: # The returned discord.Message object from discord.Message.edit is different from the current # discord.Message object, so it must be reassigned to update properly - message = await message.edit(embed=self._build_topic_embed(message.channel.id, message.embeds[0].title)) + embed, remove_reactions = self._build_topic_embed(message.channel.id, message.embeds[0].title) + message = await message.edit(embed=embed) + if remove_reactions: + await message.clear_reaction("🔄") except discord.NotFound: break @@ -135,7 +141,7 @@ async def topic(self, ctx: commands.Context) -> None: Allows the refresh of a topic by pressing an emoji. """ - message = await ctx.send(embed=self._build_topic_embed(ctx.channel.id, None)) + message = await ctx.send(embed=self._build_topic_embed(ctx.channel.id, None)[0]) self.bot.loop.create_task(self._listen_for_refresh(ctx.author, message)) From 53ff19f2fb291656f53fe30309763d47ab04403a Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 26 Feb 2023 19:53:22 -0600 Subject: [PATCH 06/10] Remove unneeded comment --- bot/exts/utilities/conversationstarters.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index 26850616c2..eeb83c99de 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -77,7 +77,6 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[dis embed.title = previous_topic + f"\n{total_topics + 1}. {embed.title}" - # When the embed will be larger than the limit, use the previous embed instead if len(embed.title) > 256: embed.title = previous_topic return embed, True From a149c6f985374b035f5f61bff53d7cfb19e10512 Mon Sep 17 00:00:00 2001 From: Anonymous4045 Date: Sat, 11 May 2024 20:03:41 -0500 Subject: [PATCH 07/10] Change message format This commit changes the message to have a set title, then up to 3 topics, followed by a footer (currently link is broken). --- bot/exts/utilities/conversationstarters.py | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index 7048636052..7d0bf67331 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -50,22 +50,27 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[dis Also returns a value that determines whether or not to remove the reaction afterwards """ - # No matter what, the form will be shown. + footer = f"Suggest more topics [here]({SUGGESTION_FORM})!" + max_topics = 3 + embed = discord.Embed( - description=f"Suggest more topics [here]({SUGGESTION_FORM})!", + title="Conversation Starter", color=discord.Colour.og_blurple() ) + embed.set_footer(text=footer) + try: - channel_topics = TOPICS[channel_id] + channel_topics = TOPICS[str(channel_id)] except KeyError: # Channel doesn't have any topics. - embed.title = f"**{next(TOPICS['default'])}**" + new_topic = next(TOPICS["default"]) else: - embed.title = f"**{next(channel_topics)}**" + new_topic = next(channel_topics) if previous_topic is None: # This is the first topic being sent + embed.description = new_topic return embed, False total_topics = previous_topic.count("\n") + 1 @@ -73,12 +78,14 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[dis if total_topics == 1: previous_topic = f"1. {previous_topic}" - embed.title = previous_topic + f"\n{total_topics + 1}. {embed.title}" + embed.description = previous_topic + f"\n{total_topics + 1}. {new_topic}" - if len(embed.title) > 256: - embed.title = previous_topic + if total_topics == max_topics - 1: return embed, True + # If there are 3 topics, return embed, True + if total_topics >= max_topics: + return embed, True return embed, False @staticmethod @@ -119,7 +126,7 @@ async def _listen_for_refresh( try: # The returned discord.Message object from discord.Message.edit is different from the current # discord.Message object, so it must be reassigned to update properly - embed, remove_reactions = self._build_topic_embed(message.channel.id, message.embeds[0].title) + embed, remove_reactions = self._build_topic_embed(message.channel.id, message.embeds[0].description) message = await message.edit(embed=embed) if remove_reactions: await message.clear_reaction("🔄") @@ -130,7 +137,7 @@ async def _listen_for_refresh( await message.remove_reaction(reaction, user) @commands.command() - @commands.cooldown(1, 60*2, commands.BucketType.channel) + @commands.cooldown(1, 60 * 2, commands.BucketType.channel) @whitelist_override(channels=ALL_ALLOWED_CHANNELS) async def topic(self, ctx: commands.Context) -> None: """ From 5ff99a313c9dd06265ed835b0124df4ea26f7709 Mon Sep 17 00:00:00 2001 From: Anonymous4045 Date: Sat, 11 May 2024 20:13:45 -0500 Subject: [PATCH 08/10] Handle forced topic reroll This commit handles when a user presses the reroll emoji after it's already removed by the bot. It just returns what the embed was before and re-clears the reactions. --- bot/exts/utilities/conversationstarters.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index 7d0bf67331..eb716fb9fc 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -48,7 +48,7 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[dis If in a Python channel, a python-related topic will be given. Otherwise, a random conversation topic will be received by the user. - Also returns a value that determines whether or not to remove the reaction afterwards + Also returns a value that determines whether to remove the reaction afterwards """ footer = f"Suggest more topics [here]({SUGGESTION_FORM})!" max_topics = 3 @@ -74,18 +74,21 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[dis return embed, False total_topics = previous_topic.count("\n") + 1 + + # Handle forced reactions after clear + if total_topics >= max_topics: + embed.description = previous_topic + return embed, True + # Add 1 before first topic if total_topics == 1: previous_topic = f"1. {previous_topic}" embed.description = previous_topic + f"\n{total_topics + 1}. {new_topic}" + # If this is the last topic, remove the reaction if total_topics == max_topics - 1: return embed, True - - # If there are 3 topics, return embed, True - if total_topics >= max_topics: - return embed, True return embed, False @staticmethod From d763ea933476133518483edd864cbbe00a8c59b8 Mon Sep 17 00:00:00 2001 From: Anonymous4045 Date: Sat, 11 May 2024 20:58:19 -0500 Subject: [PATCH 09/10] Move form link to description Because embed footers can't have markup, the topic suggestion hyperlink can't be in it. This commit moves it from the footer to the description of the embed. --- bot/exts/utilities/conversationstarters.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index eb716fb9fc..b723beb96b 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -41,7 +41,7 @@ def __init__(self, bot: Bot): self.bot = bot @staticmethod - def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[discord.Embed, bool]: + def _build_topic_embed(channel_id: int, previous_description: None | str) -> tuple[discord.Embed, bool]: """ Build an embed containing a conversation topic. @@ -53,13 +53,17 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[dis footer = f"Suggest more topics [here]({SUGGESTION_FORM})!" max_topics = 3 + # Remove footer from previous description + previous_topic = None + if previous_description: + previous_topic = previous_description.split("\n\n")[0] + print(previous_topic) + embed = discord.Embed( title="Conversation Starter", color=discord.Colour.og_blurple() ) - embed.set_footer(text=footer) - try: channel_topics = TOPICS[str(channel_id)] except KeyError: @@ -68,23 +72,26 @@ def _build_topic_embed(channel_id: int, previous_topic: None | str) -> tuple[dis else: new_topic = next(channel_topics) + def add_description(text: str) -> None: + embed.description = f"{text}\n\n{footer}" + if previous_topic is None: # This is the first topic being sent - embed.description = new_topic + add_description(new_topic) return embed, False total_topics = previous_topic.count("\n") + 1 # Handle forced reactions after clear if total_topics >= max_topics: - embed.description = previous_topic + add_description(new_topic) return embed, True # Add 1 before first topic if total_topics == 1: previous_topic = f"1. {previous_topic}" - embed.description = previous_topic + f"\n{total_topics + 1}. {new_topic}" + add_description(f"{previous_topic}\n{total_topics + 1}. {new_topic}") # If this is the last topic, remove the reaction if total_topics == max_topics - 1: From 9c518be1062ea9e65aee60e8fa5c08ad1066ba87 Mon Sep 17 00:00:00 2001 From: Anonymous4045 Date: Sat, 11 May 2024 21:07:24 -0500 Subject: [PATCH 10/10] Fix forced reroll --- bot/exts/utilities/conversationstarters.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bot/exts/utilities/conversationstarters.py b/bot/exts/utilities/conversationstarters.py index b723beb96b..1565833e20 100644 --- a/bot/exts/utilities/conversationstarters.py +++ b/bot/exts/utilities/conversationstarters.py @@ -57,7 +57,6 @@ def _build_topic_embed(channel_id: int, previous_description: None | str) -> tup previous_topic = None if previous_description: previous_topic = previous_description.split("\n\n")[0] - print(previous_topic) embed = discord.Embed( title="Conversation Starter", @@ -84,7 +83,7 @@ def add_description(text: str) -> None: # Handle forced reactions after clear if total_topics >= max_topics: - add_description(new_topic) + embed.description = previous_description return embed, True # Add 1 before first topic