diff options
6 files changed, 17 insertions, 18 deletions
diff --git a/bot/exts/filtering/FILTERS-DEVELOPMENT.md b/bot/exts/filtering/FILTERS-DEVELOPMENT.md index d5896d556..c6237b60c 100644 --- a/bot/exts/filtering/FILTERS-DEVELOPMENT.md +++ b/bot/exts/filtering/FILTERS-DEVELOPMENT.md @@ -9,7 +9,7 @@ There are several types of filters, and two filters of the same type differ by t For example, filters of type "token" search for a specific token inside the provided string. One token filter might look for the string "lemon", while another will look for the string "joe". -Each filter has a set of settings that decide when it triggers (e.g. in which channels), and what happens if it does (e.g. delete the message). +Each filter has a set of settings that decide when it triggers (e.g. in which channels, in which categories, etc.), and what happens if it does (e.g. delete the message, ping specific roles/users, etc.). Filters of a specific type can have additional settings that are special to them. A list of filters is contained within a filter list. diff --git a/bot/exts/filtering/_filter_lists/antispam.py b/bot/exts/filtering/_filter_lists/antispam.py index 9745372af..94f80e6eb 100644 --- a/bot/exts/filtering/_filter_lists/antispam.py +++ b/bot/exts/filtering/_filter_lists/antispam.py @@ -18,7 +18,7 @@ from bot.exts.filtering._filter_lists.filter_list import ListType, SubscribingAt from bot.exts.filtering._filters.antispam import antispam_filter_types from bot.exts.filtering._filters.filter import Filter, UniqueFilter from bot.exts.filtering._settings import ActionSettings -from bot.exts.filtering._settings_types.actions.infraction_and_notification import Infraction +from bot.exts.filtering._settings_types.actions.infraction_and_notification import Infraction, InfractionAndNotification from bot.exts.filtering._ui.ui import AlertView, build_mod_alert if typing.TYPE_CHECKING: @@ -93,22 +93,22 @@ class AntispamList(UniquesListBase): current_actions.pop("ping", None) current_actions.pop("send_alert", None) - new_infraction = current_actions["infraction_and_notification"].copy() + new_infraction = current_actions[InfractionAndNotification.name].copy() # Smaller infraction value => higher in hierarchy. if not current_infraction or new_infraction.infraction_type.value < current_infraction.value: # Pick the first triggered filter for the reason, there's no good way to decide between them. new_infraction.infraction_reason = ( f"{triggers[0].name.replace('_', ' ')} spam – {ctx.filter_info[triggers[0]]}" ) - current_actions["infraction_and_notification"] = new_infraction + current_actions[InfractionAndNotification.name] = new_infraction self.message_deletion_queue[ctx.author].current_infraction = new_infraction.infraction_type else: - current_actions.pop("infraction_and_notification", None) + current_actions.pop(InfractionAndNotification.name, None) # Provide some message in case another filter list wants there to be an alert. return current_actions, ["Handling spam event..."], {ListType.DENY: triggers} - def _create_deletion_context_handler(self, context_id: Member) -> Callable[[FilterContext], Coroutine]: + def _create_deletion_context_handler(self, member: Member) -> Callable[[FilterContext], Coroutine]: async def schedule_processing(ctx: FilterContext) -> None: """ Schedule a coroutine to process the deletion context. @@ -123,11 +123,11 @@ class AntispamList(UniquesListBase): log.trace("Sleeping before processing message deletion queue.") await asyncio.sleep(ALERT_DELAY) - if context_id not in self.message_deletion_queue: - log.error(f"Started processing deletion queue for context `{context_id}`, but it was not found!") + if member not in self.message_deletion_queue: + log.error(f"Started processing deletion queue for context `{member}`, but it was not found!") return - deletion_context = self.message_deletion_queue.pop(context_id) + deletion_context = self.message_deletion_queue.pop(member) await deletion_context.send_alert(self) scheduling.create_task(process_deletion_context()) diff --git a/bot/exts/filtering/_filter_lists/extension.py b/bot/exts/filtering/_filter_lists/extension.py index dda2c3179..9d6c4c0e7 100644 --- a/bot/exts/filtering/_filter_lists/extension.py +++ b/bot/exts/filtering/_filter_lists/extension.py @@ -27,7 +27,7 @@ TXT_EMBED_DESCRIPTION = ( ) DISALLOWED_EMBED_DESCRIPTION = ( - "It looks like you tried to attach file type(s) that we do not allow ({blocked_extensions_str}). " + "It looks like you tried to attach file type(s) that we do not allow ({joined_blacklist}). " "We currently allow the following file types: **{joined_whitelist}**.\n\n" "Feel free to ask in {meta_channel_mention} if you think this is a mistake." ) @@ -99,11 +99,7 @@ class ExtensionsList(FilterList[ExtensionFilter]): ctx.dm_embed = PY_EMBED_DESCRIPTION elif txt_extensions := {ext for ext in TXT_LIKE_FILES if ext in not_allowed}: # Work around Discord auto-conversion of messages longer than 2000 chars to .txt - cmd_channel = bot.instance.get_channel(Channels.bot_commands) - ctx.dm_embed = TXT_EMBED_DESCRIPTION.format( - blocked_extension=txt_extensions.pop(), - cmd_channel_mention=cmd_channel.mention - ) + ctx.dm_embed = TXT_EMBED_DESCRIPTION.format(blocked_extension=txt_extensions.pop()) else: meta_channel = bot.instance.get_channel(Channels.meta) if not self._whitelisted_description: @@ -112,7 +108,7 @@ class ExtensionsList(FilterList[ExtensionFilter]): ) ctx.dm_embed = DISALLOWED_EMBED_DESCRIPTION.format( joined_whitelist=self._whitelisted_description, - blocked_extensions_str=", ".join(not_allowed), + joined_blacklist=", ".join(not_allowed), meta_channel_mention=meta_channel.mention, ) diff --git a/bot/exts/filtering/_settings.py b/bot/exts/filtering/_settings.py index f472c5d1d..f51a42704 100644 --- a/bot/exts/filtering/_settings.py +++ b/bot/exts/filtering/_settings.py @@ -73,7 +73,7 @@ class Settings(FieldRequiring, dict[str, T]): _already_warned: set[str] = set() - @abstractmethod + @abstractmethod # ABCs have to have at least once abstract method to actually count as such. def __init__(self, settings_data: dict, *, defaults: Settings | None = None, keep_empty: bool = False): super().__init__() diff --git a/bot/exts/filtering/_settings_types/actions/infraction_and_notification.py b/bot/exts/filtering/_settings_types/actions/infraction_and_notification.py index e3df47029..3b59c2feb 100644 --- a/bot/exts/filtering/_settings_types/actions/infraction_and_notification.py +++ b/bot/exts/filtering/_settings_types/actions/infraction_and_notification.py @@ -232,6 +232,7 @@ class InfractionAndNotification(ActionEntry): # If the winner has no message but the loser does, copy the message to the winner. result_overrides = result.overrides + # Either take both or nothing, don't mix content from one filter and embed from another. if "dm_content" not in result_overrides and "dm_embed" not in result_overrides: other_overrides = other.overrides if "dm_content" in other_overrides: diff --git a/bot/exts/filtering/_settings_types/validations/channel_scope.py b/bot/exts/filtering/_settings_types/validations/channel_scope.py index d37efaa09..737465137 100644 --- a/bot/exts/filtering/_settings_types/validations/channel_scope.py +++ b/bot/exts/filtering/_settings_types/validations/channel_scope.py @@ -10,7 +10,7 @@ class ChannelScope(ValidationEntry): """A setting entry which tells whether the filter was invoked in a whitelisted channel or category.""" name: ClassVar[str] = "channel_scope" - description: ClassVar[str] = { + description: ClassVar[dict[str, str]] = { "disabled_channels": ( "A list of channel IDs or channel names. " "The filter will not trigger in these channels even if the category is expressly enabled." @@ -29,6 +29,8 @@ class ChannelScope(ValidationEntry): ) } + # NOTE: Don't change this to use the new 3.10 union syntax unless you ensure Pydantic type validation and coercion + # work properly. At the time of writing this code there's a difference. disabled_channels: set[Union[int, str]] disabled_categories: set[Union[int, str]] enabled_channels: set[Union[int, str]] |