From 1085fceef176abee217427ceb0a00f7fb32fef5c Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Mon, 23 Jun 2025 01:25:10 +0100 Subject: [PATCH 1/3] Add rule alerts thread to constants file --- bot/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bot/constants.py b/bot/constants.py index 13c165e868..35e9b399f9 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -89,6 +89,8 @@ class _Channels(EnvConfig, env_prefix="channels_"): incidents: int = 714214212200562749 incidents_archive: int = 720668923636351037 mod_alerts: int = 473092532147060736 + # Actually a thread, but for bootstrap purposes we treat it as a channel + rule_alerts: int = 1386490058739290182 mod_meta: int = 775412552795947058 mods: int = 305126844661760000 nominations: int = 822920136150745168 From 0eda47a22fbbe24c0e9f237737a2523a55f1eb13 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Mon, 23 Jun 2025 02:04:13 +0100 Subject: [PATCH 2/3] Post alert in rule alerts thread when a non-staff member uses !rule --- bot/exts/info/information.py | 40 +++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index df79fbb807..adfad4b73f 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -11,6 +11,7 @@ from discord.ext.commands import BucketType, Cog, Context, command, group, has_any_role from discord.utils import escape_markdown from pydis_core.site_api import ResponseCodeError +from pydis_core.utils.channel import get_or_fetch_channel from pydis_core.utils.members import get_or_fetch_member from pydis_core.utils.paste_service import PasteFile, PasteTooLongError, PasteUploadError, send_to_paste_service @@ -602,6 +603,37 @@ async def _set_rules_command_help(self) -> None: self.rules.help = help_string + async def _send_rules_alert(self, ctx: Context, requested_rules: list[int]) -> None: + """Send an alert to the Rule Alerts thread when a non-staff member uses the rules command.""" + rules_thread = await get_or_fetch_channel(self.bot, constants.Channels.rule_alerts) + + if rules_thread is None: + log.error("Failed to find the rules alert thread channel.") + return + + rule_desc = None + + if len(requested_rules) == 1: + rule_desc = f"Rule **{requested_rules[0]}** was requested by {ctx.author.mention} in {ctx.channel.mention}." + elif len(requested_rules) > 1: + rule_desc = ( + f"Rules **{', '.join(map(str, requested_rules))}** were requested " + f"by {ctx.author.mention} in {ctx.channel.mention}." + ) + + warning_embed = Embed( + title="Rules Command Alert", + description=rule_desc, + color=Colour.red(), + url=ctx.message.jump_url + ) + + warning_embed.set_footer(text="Warnings are sent for invocations from non-staff members.") + + warning_embed.set_author(name=f"{ctx.author} ({ctx.author.id})", icon_url=ctx.author.display_avatar.url) + + await rules_thread.send(embed=warning_embed) + @command(aliases=("rule",)) async def rules(self, ctx: Context, *, args: str | None) -> set[int] | None: """ @@ -651,10 +683,16 @@ async def rules(self, ctx: Context, *, args: str | None) -> set[int] | None: final_rule_numbers = {keyword_to_rule_number[keyword] for keyword in keywords} final_rule_numbers.update(rule_numbers) - for rule_number in sorted(final_rule_numbers): + sorted_rules = sorted(final_rule_numbers) + + for rule_number in sorted_rules: self.bot.stats.incr(f"rule_uses.{rule_number}") final_rules.append(f"**{rule_number}.** {full_rules[rule_number - 1][0]}") + if constants.Roles.helpers not in {role.id for role in ctx.author.roles}: + # If the user is not a helper, send an alert to the rules thread. + await self._send_rules_alert(ctx, sorted_rules) + await LinePaginator.paginate(final_rules, ctx, rules_embed, max_lines=3) return final_rule_numbers From 3c72b27441e3ebd225e594ff389ffb730ce0a6e1 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Mon, 23 Jun 2025 02:04:40 +0100 Subject: [PATCH 3/3] Update information cog test suite to patch get_channel for rules command tests --- tests/bot/exts/info/test_information.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/bot/exts/info/test_information.py b/tests/bot/exts/info/test_information.py index e90291f62b..13a82f9b83 100644 --- a/tests/bot/exts/info/test_information.py +++ b/tests/bot/exts/info/test_information.py @@ -599,6 +599,9 @@ def setUp(self) -> None: ) ] self.bot.api_client.get.return_value = self.full_rules + # Patch get_channel to handle the rule alerts being sent to a thread for non-staff (as our mock user is). + self.bot.get_channel.return_value = helpers.MockTextChannel(id=50, name="rules") + async def test_return_none_if_one_rule_number_is_invalid(self):