Skip to content

Commit 2766b4a

Browse files
authored
Tighter mention filtering in auto-ban mod-alerts (#3530)
* Only remove moderators/broad pings from auto-ban mod-alerts * Add new test to validate mention removal
1 parent e1be4d5 commit 2766b4a

2 files changed

Lines changed: 39 additions & 2 deletions

File tree

bot/exts/filtering/filtering.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
build_mod_alert,
4848
format_response_error,
4949
)
50-
from bot.exts.filtering._utils import past_tense, repr_equals, starting_value, to_serializable
50+
from bot.exts.filtering._utils import past_tense, repr_equals, resolve_mention, starting_value, to_serializable
5151
from bot.exts.moderation.infraction.infractions import COMP_BAN_DURATION, COMP_BAN_REASON
5252
from bot.exts.utils.snekbox._io import FileAttachment
5353
from bot.log import get_logger
@@ -66,6 +66,21 @@
6666
WEEKLY_REPORT_ISO_DAY = 3 # 1=Monday, 7=Sunday
6767

6868

69+
def _clean_ban_mentions(mentions: set[str]) -> set[str]:
70+
"""Remove broad pings and moderators role pings from ban alerts."""
71+
blocked_mentions = {f"<@&{Roles.moderators}>", "@here", "@everyone"}
72+
cleaned_mentions = set()
73+
74+
for mention in mentions:
75+
if mention.casefold() == "moderators":
76+
continue
77+
if resolve_mention(mention) in blocked_mentions:
78+
continue
79+
cleaned_mentions.add(mention)
80+
81+
return cleaned_mentions
82+
83+
6984
async def _extract_text_file_content(att: discord.Attachment) -> str:
7085
"""Extract up to the first 30 lines or first 2000 characters (whichever is shorter) of an attachment."""
7186
file_encoding = re.search(r"charset=(\S+)", att.content_type).group(1)
@@ -981,7 +996,9 @@ async def _resolve_action(
981996
# If the action is a ban, mods don't want to be pinged.
982997
if infr_action := result_actions.get("infraction_and_notification"):
983998
if infr_action.infraction_type == Infraction.BAN:
984-
result_actions.pop("mentions", None)
999+
if mentions := result_actions.get("mentions"):
1000+
mentions.guild_pings = _clean_ban_mentions(mentions.guild_pings)
1001+
mentions.dm_pings = _clean_ban_mentions(mentions.dm_pings)
9851002
return result_actions, messages, triggers
9861003

9871004
async def _send_alert(self, ctx: FilterContext, triggered_filters: dict[FilterList, Iterable[str]]) -> None:

tests/bot/exts/filtering/test_settings_entries.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import unittest
2+
from unittest.mock import patch
23

4+
from bot.constants import Roles
35
from bot.exts.filtering._filter_context import Event, FilterContext
46
from bot.exts.filtering._settings_types.actions.infraction_and_notification import (
57
Infraction,
@@ -9,6 +11,7 @@
911
from bot.exts.filtering._settings_types.validations.bypass_roles import RoleBypass
1012
from bot.exts.filtering._settings_types.validations.channel_scope import ChannelScope
1113
from bot.exts.filtering._settings_types.validations.filter_dm import FilterDM
14+
from bot.exts.filtering.filtering import _clean_ban_mentions
1215
from tests.helpers import MockCategoryChannel, MockDMChannel, MockMember, MockMessage, MockRole, MockTextChannel
1316

1417

@@ -218,3 +221,20 @@ def test_infraction_merge_of_different_infraction_types(self):
218221
"infraction_channel": 0
219222
}
220223
)
224+
225+
@patch("bot.exts.filtering.filtering.resolve_mention")
226+
def test_clean_ban_mentions_removes_moderator_and_broad_mentions(self, resolve_mention_mock):
227+
"""Ban-alert mention cleanup should remove moderator, here, and everyone pings."""
228+
resolve_mention_mock.side_effect = lambda mention: {
229+
"here": "@here",
230+
"everyone": "@everyone",
231+
"Moderators": f"<@&{Roles.moderators}>",
232+
str(Roles.moderators): f"<@&{Roles.moderators}>",
233+
"other-role": "<@&123>",
234+
}.get(mention, mention)
235+
236+
mentions = {"here", "everyone", "Moderators", str(Roles.moderators), "other-role", "12345"}
237+
238+
cleaned = _clean_ban_mentions(mentions)
239+
240+
self.assertSetEqual(cleaned, {"other-role", "12345"})

0 commit comments

Comments
 (0)