From ba68ec4c7c64779086d313fea22ea206b3d4242f Mon Sep 17 00:00:00 2001 From: Saber_0324 Date: Mon, 6 Jul 2026 12:31:53 -0400 Subject: [PATCH 1/8] Added get_reference_message helper --- bot/exts/info/tags.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bot/exts/info/tags.py b/bot/exts/info/tags.py index 65b0c5c650..896daa5afe 100644 --- a/bot/exts/info/tags.py +++ b/bot/exts/info/tags.py @@ -278,6 +278,20 @@ def accessible_tags_in_group(self, group: str, member: Member) -> list[str]: if identifier.group == group and tag.accessible_by(member) ) + async def get_reference_message(self, ctx: Context) -> discord.Message | None: + """Return a message reference if the reference exists and it does not refer to the author of the message.""" + if ctx.message.reference is None: + return None + try: + referenced_message = await ctx.fetch_message(ctx.message.reference.message_id) + except (discord.Forbidden, discord.NotFound): + referenced_message = None + if referenced_message is None: + return None + if referenced_message.author == ctx.author: + return None + return referenced_message + async def get_command_ctx( self, ctx: Context, From 5a42d7ccc3db3abe7aa3fb46be093ccf8983f317 Mon Sep 17 00:00:00 2001 From: Saber_0324 Date: Mon, 6 Jul 2026 12:33:47 -0400 Subject: [PATCH 2/8] Implemented get_reference_message in get_command_ctx --- bot/exts/info/tags.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bot/exts/info/tags.py b/bot/exts/info/tags.py index 896daa5afe..906e954a70 100644 --- a/bot/exts/info/tags.py +++ b/bot/exts/info/tags.py @@ -318,6 +318,11 @@ async def get_command_ctx( if embed is not COOLDOWN.obj: + if message_reference := await self.get_reference_message(ctx): + await wait_for_deletion( + await message_reference.reply(embed=embed), + (ctx.author.id,) + ) await wait_for_deletion( await ctx.send(embed=embed), (ctx.author.id,) From 6f61da002ca28da13cdb7a9e8f58a4f1f58860a9 Mon Sep 17 00:00:00 2001 From: Saber_0324 Date: Mon, 6 Jul 2026 12:35:40 -0400 Subject: [PATCH 3/8] Moved the ctx.send variant of get_command_ctx to the else branch --- bot/exts/info/tags.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bot/exts/info/tags.py b/bot/exts/info/tags.py index 906e954a70..856b0b740d 100644 --- a/bot/exts/info/tags.py +++ b/bot/exts/info/tags.py @@ -323,10 +323,11 @@ async def get_command_ctx( await message_reference.reply(embed=embed), (ctx.author.id,) ) - await wait_for_deletion( - await ctx.send(embed=embed), - (ctx.author.id,) - ) + else: + await wait_for_deletion( + await ctx.send(embed=embed), + (ctx.author.id,) + ) # A valid tag was found and was either sent, or is on cooldown return True From f181232088ce0cbc5392359d87cc8427da47706c Mon Sep 17 00:00:00 2001 From: Saber_0324 Date: Mon, 6 Jul 2026 12:59:38 -0400 Subject: [PATCH 4/8] Moved get_reference message from ext/info/tags.py to utils/messages.py --- bot/exts/info/tags.py | 18 ++---------------- bot/utils/messages.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/bot/exts/info/tags.py b/bot/exts/info/tags.py index 856b0b740d..f5926d2f58 100644 --- a/bot/exts/info/tags.py +++ b/bot/exts/info/tags.py @@ -13,7 +13,7 @@ from bot.bot import Bot from bot.log import get_logger from bot.pagination import LinePaginator -from bot.utils.messages import wait_for_deletion +from bot.utils.messages import get_reference_message, wait_for_deletion log = get_logger(__name__) @@ -278,20 +278,6 @@ def accessible_tags_in_group(self, group: str, member: Member) -> list[str]: if identifier.group == group and tag.accessible_by(member) ) - async def get_reference_message(self, ctx: Context) -> discord.Message | None: - """Return a message reference if the reference exists and it does not refer to the author of the message.""" - if ctx.message.reference is None: - return None - try: - referenced_message = await ctx.fetch_message(ctx.message.reference.message_id) - except (discord.Forbidden, discord.NotFound): - referenced_message = None - if referenced_message is None: - return None - if referenced_message.author == ctx.author: - return None - return referenced_message - async def get_command_ctx( self, ctx: Context, @@ -318,7 +304,7 @@ async def get_command_ctx( if embed is not COOLDOWN.obj: - if message_reference := await self.get_reference_message(ctx): + if message_reference := await get_reference_message(ctx): await wait_for_deletion( await message_reference.reply(embed=embed), (ctx.author.id,) diff --git a/bot/utils/messages.py b/bot/utils/messages.py index 57bb2c8e31..f3d939ae50 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -285,3 +285,17 @@ async def upload_log( raise return f"{URLs.site_logs_view}/{response['id']}" + +async def get_reference_message(ctx: Context) -> discord.Message | None: + """Return a message reference if the reference exists and it does not refer to the author of the message.""" + if ctx.message.reference is None: + return None + try: + referenced_message = await ctx.fetch_message(ctx.message.reference.message_id) + except (discord.Forbidden, discord.NotFound): + referenced_message = None + if referenced_message is None: + return None + if referenced_message.author == ctx.author: + return None + return referenced_message From 5a298e48b6482c9fe9dd71a0e6db7bc147672410 Mon Sep 17 00:00:00 2001 From: Saber_0324 Date: Mon, 6 Jul 2026 13:37:01 -0400 Subject: [PATCH 5/8] Added functionality from get_reference_message --- bot/exts/info/pep.py | 6 +++++- bot/exts/info/resources.py | 6 +++++- bot/exts/info/source.py | 13 +++++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/bot/exts/info/pep.py b/bot/exts/info/pep.py index 4655b21ff0..1d9e03b3d0 100644 --- a/bot/exts/info/pep.py +++ b/bot/exts/info/pep.py @@ -6,6 +6,7 @@ from bot.bot import Bot from bot.log import get_logger +from bot.utils.messages import get_reference_message log = get_logger(__name__) @@ -93,7 +94,10 @@ async def pep_command(self, ctx: Context, pep_number: int) -> None: colour=Colour.red(), ) - await ctx.send(embed=embed) + if message_reference := await get_reference_message(ctx): + await message_reference.reply(embed=embed) + else: + await ctx.send(embed=embed) async def setup(bot: Bot) -> None: diff --git a/bot/exts/info/resources.py b/bot/exts/info/resources.py index 99caa2ae0d..44c9596991 100644 --- a/bot/exts/info/resources.py +++ b/bot/exts/info/resources.py @@ -5,6 +5,7 @@ from discord.ext import commands from bot.bot import Bot +from bot.utils.messages import get_reference_message REGEX_CONSECUTIVE_NON_LETTERS = r"[^A-Za-z0-9]+" RESOURCE_URL = "https://www.pythondiscord.com/resources/" @@ -61,7 +62,10 @@ async def resources_command(self, ctx: commands.Context, *, resource_topic: str f"of hand-selected learning resources that we " f"regularly recommend to both beginners and experts." ) - await ctx.send(embed=embed) + if message_reference := await get_reference_message(ctx): + await message_reference.reply(embed=embed) + else: + await ctx.send(embed=embed) async def setup(bot: Bot) -> None: diff --git a/bot/exts/info/source.py b/bot/exts/info/source.py index 9dd5c39bf5..0639fc8611 100644 --- a/bot/exts/info/source.py +++ b/bot/exts/info/source.py @@ -9,6 +9,7 @@ from bot.bot import Bot from bot.constants import URLs from bot.exts.info.tags import TagIdentifier +from bot.utils.messages import get_reference_message SourceObject = commands.HelpCommand | commands.Command | commands.Cog | TagIdentifier | commands.ExtensionNotLoaded @@ -40,12 +41,20 @@ async def source_command( embed = Embed(title="Bot's GitHub Repository") embed.add_field(name="Repository", value=f"[Go to GitHub]({URLs.github_bot_repo})") embed.set_thumbnail(url="https://avatars1.githubusercontent.com/u/9919") - await ctx.send(embed=embed) + + if message_reference := await get_reference_message(ctx): + await message_reference.reply(embed=embed) + else: + await ctx.send(embed=embed) return obj, source_type = await self.get_source_object(ctx, source_item) embed = await self.build_embed(obj, source_type) - await ctx.send(embed=embed) + + if message_reference := await get_reference_message(ctx): + await message_reference.reply(embed=embed) + else: + await ctx.send(embed=embed) @staticmethod async def get_source_object(ctx: commands.Context, argument: str) -> tuple[SourceObject, SourceType]: From c202ee23959be04edf7baa2bad28c74ea05d876a Mon Sep 17 00:00:00 2001 From: Saber_0324 Date: Mon, 6 Jul 2026 14:52:37 -0400 Subject: [PATCH 6/8] Added send_or_reply helper --- bot/utils/messages.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/bot/utils/messages.py b/bot/utils/messages.py index f3d939ae50..fe0369de3b 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -7,7 +7,7 @@ from itertools import zip_longest import discord -from discord import Message +from discord import Embed, Message from discord.ext.commands import Context from pydis_core.site_api import ResponseCodeError from pydis_core.utils import scheduling @@ -299,3 +299,14 @@ async def get_reference_message(ctx: Context) -> discord.Message | None: if referenced_message.author == ctx.author: return None return referenced_message + +async def send_or_reply(ctx: Context, embed: Embed) -> None: + """ + Sends the bot message as a reply if the callers message has a reference. + + If the callers message does not have a reference, the bot messsage is sent without reply + """ + if message_reference := await get_reference_message(ctx): + await message_reference.reply(embed=embed) + else: + await ctx.send(embed=embed) From fb037ac0a7804f51f396999bf7b7d4d844d7f8a5 Mon Sep 17 00:00:00 2001 From: Saber_0324 Date: Mon, 6 Jul 2026 15:00:19 -0400 Subject: [PATCH 7/8] Make send_or_reply return the discord.Message instead of None --- bot/utils/messages.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bot/utils/messages.py b/bot/utils/messages.py index fe0369de3b..34e6d90244 100644 --- a/bot/utils/messages.py +++ b/bot/utils/messages.py @@ -286,7 +286,7 @@ async def upload_log( return f"{URLs.site_logs_view}/{response['id']}" -async def get_reference_message(ctx: Context) -> discord.Message | None: +async def get_reference_message(ctx: Context) -> Message | None: """Return a message reference if the reference exists and it does not refer to the author of the message.""" if ctx.message.reference is None: return None @@ -300,13 +300,12 @@ async def get_reference_message(ctx: Context) -> discord.Message | None: return None return referenced_message -async def send_or_reply(ctx: Context, embed: Embed) -> None: +async def send_or_reply(ctx: Context, embed: Embed) -> Message: """ Sends the bot message as a reply if the callers message has a reference. If the callers message does not have a reference, the bot messsage is sent without reply """ if message_reference := await get_reference_message(ctx): - await message_reference.reply(embed=embed) - else: - await ctx.send(embed=embed) + return await message_reference.reply(embed=embed) + return await ctx.send(embed=embed) From d50401d4ee7d431bfa4c06165062c9ab6c032416 Mon Sep 17 00:00:00 2001 From: Saber_0324 Date: Mon, 6 Jul 2026 15:04:57 -0400 Subject: [PATCH 8/8] Change the use of bare get_reference_message for the send_or_reply helper to avoid repetition --- bot/exts/info/pep.py | 8 ++------ bot/exts/info/resources.py | 7 ++----- bot/exts/info/source.py | 12 +++--------- bot/exts/info/tags.py | 16 +++++----------- 4 files changed, 12 insertions(+), 31 deletions(-) diff --git a/bot/exts/info/pep.py b/bot/exts/info/pep.py index 1d9e03b3d0..5423da0805 100644 --- a/bot/exts/info/pep.py +++ b/bot/exts/info/pep.py @@ -6,7 +6,7 @@ from bot.bot import Bot from bot.log import get_logger -from bot.utils.messages import get_reference_message +from bot.utils.messages import send_or_reply log = get_logger(__name__) @@ -94,11 +94,7 @@ async def pep_command(self, ctx: Context, pep_number: int) -> None: colour=Colour.red(), ) - if message_reference := await get_reference_message(ctx): - await message_reference.reply(embed=embed) - else: - await ctx.send(embed=embed) - + await send_or_reply(ctx, embed) async def setup(bot: Bot) -> None: """Load the PEP cog.""" diff --git a/bot/exts/info/resources.py b/bot/exts/info/resources.py index 44c9596991..f732fb186e 100644 --- a/bot/exts/info/resources.py +++ b/bot/exts/info/resources.py @@ -5,7 +5,7 @@ from discord.ext import commands from bot.bot import Bot -from bot.utils.messages import get_reference_message +from bot.utils.messages import send_or_reply REGEX_CONSECUTIVE_NON_LETTERS = r"[^A-Za-z0-9]+" RESOURCE_URL = "https://www.pythondiscord.com/resources/" @@ -62,10 +62,7 @@ async def resources_command(self, ctx: commands.Context, *, resource_topic: str f"of hand-selected learning resources that we " f"regularly recommend to both beginners and experts." ) - if message_reference := await get_reference_message(ctx): - await message_reference.reply(embed=embed) - else: - await ctx.send(embed=embed) + await send_or_reply(ctx, embed) async def setup(bot: Bot) -> None: diff --git a/bot/exts/info/source.py b/bot/exts/info/source.py index 0639fc8611..195c1703a3 100644 --- a/bot/exts/info/source.py +++ b/bot/exts/info/source.py @@ -9,7 +9,7 @@ from bot.bot import Bot from bot.constants import URLs from bot.exts.info.tags import TagIdentifier -from bot.utils.messages import get_reference_message +from bot.utils.messages import send_or_reply SourceObject = commands.HelpCommand | commands.Command | commands.Cog | TagIdentifier | commands.ExtensionNotLoaded @@ -42,19 +42,13 @@ async def source_command( embed.add_field(name="Repository", value=f"[Go to GitHub]({URLs.github_bot_repo})") embed.set_thumbnail(url="https://avatars1.githubusercontent.com/u/9919") - if message_reference := await get_reference_message(ctx): - await message_reference.reply(embed=embed) - else: - await ctx.send(embed=embed) + await send_or_reply(ctx, embed) return obj, source_type = await self.get_source_object(ctx, source_item) embed = await self.build_embed(obj, source_type) - if message_reference := await get_reference_message(ctx): - await message_reference.reply(embed=embed) - else: - await ctx.send(embed=embed) + await send_or_reply(ctx, embed) @staticmethod async def get_source_object(ctx: commands.Context, argument: str) -> tuple[SourceObject, SourceType]: diff --git a/bot/exts/info/tags.py b/bot/exts/info/tags.py index f5926d2f58..7029aaa940 100644 --- a/bot/exts/info/tags.py +++ b/bot/exts/info/tags.py @@ -13,7 +13,7 @@ from bot.bot import Bot from bot.log import get_logger from bot.pagination import LinePaginator -from bot.utils.messages import get_reference_message, wait_for_deletion +from bot.utils.messages import send_or_reply, wait_for_deletion log = get_logger(__name__) @@ -304,16 +304,10 @@ async def get_command_ctx( if embed is not COOLDOWN.obj: - if message_reference := await get_reference_message(ctx): - await wait_for_deletion( - await message_reference.reply(embed=embed), - (ctx.author.id,) - ) - else: - await wait_for_deletion( - await ctx.send(embed=embed), - (ctx.author.id,) - ) + await wait_for_deletion( + await send_or_reply(ctx, embed), + (ctx.author.id,) + ) # A valid tag was found and was either sent, or is on cooldown return True