Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions bot/exts/filtering/filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
build_mod_alert,
format_response_error,
)
from bot.exts.filtering._utils import past_tense, repr_equals, starting_value, to_serializable
from bot.exts.filtering._utils import past_tense, repr_equals, resolve_mention, starting_value, to_serializable
from bot.exts.moderation.infraction.infractions import COMP_BAN_DURATION, COMP_BAN_REASON
from bot.exts.utils.snekbox._io import FileAttachment
from bot.log import get_logger
Expand All @@ -66,6 +66,21 @@
WEEKLY_REPORT_ISO_DAY = 3 # 1=Monday, 7=Sunday


def _clean_ban_mentions(mentions: set[str]) -> set[str]:
"""Remove broad pings and moderators role pings from ban alerts."""
blocked_mentions = {f"<@&{Roles.moderators}>", "@here", "@everyone"}
cleaned_mentions = set()

for mention in mentions:
if mention.casefold() == "moderators":
continue
if resolve_mention(mention) in blocked_mentions:
continue
cleaned_mentions.add(mention)

return cleaned_mentions
Comment thread
jb3 marked this conversation as resolved.


async def _extract_text_file_content(att: discord.Attachment) -> str:
"""Extract up to the first 30 lines or first 2000 characters (whichever is shorter) of an attachment."""
file_encoding = re.search(r"charset=(\S+)", att.content_type).group(1)
Expand Down Expand Up @@ -981,7 +996,9 @@ async def _resolve_action(
# If the action is a ban, mods don't want to be pinged.
if infr_action := result_actions.get("infraction_and_notification"):
if infr_action.infraction_type == Infraction.BAN:
result_actions.pop("mentions", None)
if mentions := result_actions.get("mentions"):
mentions.guild_pings = _clean_ban_mentions(mentions.guild_pings)
mentions.dm_pings = _clean_ban_mentions(mentions.dm_pings)
return result_actions, messages, triggers

async def _send_alert(self, ctx: FilterContext, triggered_filters: dict[FilterList, Iterable[str]]) -> None:
Expand Down
20 changes: 20 additions & 0 deletions tests/bot/exts/filtering/test_settings_entries.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import unittest
from unittest.mock import patch

from bot.constants import Roles
from bot.exts.filtering._filter_context import Event, FilterContext
from bot.exts.filtering._settings_types.actions.infraction_and_notification import (
Infraction,
Expand All @@ -9,6 +11,7 @@
from bot.exts.filtering._settings_types.validations.bypass_roles import RoleBypass
from bot.exts.filtering._settings_types.validations.channel_scope import ChannelScope
from bot.exts.filtering._settings_types.validations.filter_dm import FilterDM
from bot.exts.filtering.filtering import _clean_ban_mentions
from tests.helpers import MockCategoryChannel, MockDMChannel, MockMember, MockMessage, MockRole, MockTextChannel


Expand Down Expand Up @@ -218,3 +221,20 @@ def test_infraction_merge_of_different_infraction_types(self):
"infraction_channel": 0
}
)

@patch("bot.exts.filtering.filtering.resolve_mention")
def test_clean_ban_mentions_removes_moderator_and_broad_mentions(self, resolve_mention_mock):
"""Ban-alert mention cleanup should remove moderator, here, and everyone pings."""
resolve_mention_mock.side_effect = lambda mention: {
"here": "@here",
"everyone": "@everyone",
"Moderators": f"<@&{Roles.moderators}>",
str(Roles.moderators): f"<@&{Roles.moderators}>",
"other-role": "<@&123>",
}.get(mention, mention)

mentions = {"here", "everyone", "Moderators", str(Roles.moderators), "other-role", "12345"}

cleaned = _clean_ban_mentions(mentions)

self.assertSetEqual(cleaned, {"other-role", "12345"})