diff options
| author | 2022-10-27 23:19:21 +0300 | |
|---|---|---|
| committer | 2022-10-27 23:19:21 +0300 | |
| commit | c756c52fc0fe2705309e532fdcfe4f669e284745 (patch) | |
| tree | 695b03eb9643c345b70824ea07eb5fe104e5e887 | |
| parent | Add Discord token filter (diff) | |
Suppress exceptions while actioning filters
Filtering should not stop even if one type of action raised an exception.
For example, if deleting the message raised somehow, it should still try to infract the user.
Exceptions raised in actions are logged instead.
Additionally adds a fix to the way actions are merged.
| -rw-r--r-- | bot/exts/filtering/_filter_lists/filter_list.py | 14 | ||||
| -rw-r--r-- | bot/exts/filtering/_settings.py | 13 |
2 files changed, 20 insertions, 7 deletions
diff --git a/bot/exts/filtering/_filter_lists/filter_list.py b/bot/exts/filtering/_filter_lists/filter_list.py index 50793b085..0bb0dc7f8 100644 --- a/bot/exts/filtering/_filter_lists/filter_list.py +++ b/bot/exts/filtering/_filter_lists/filter_list.py @@ -113,12 +113,16 @@ class AtomicList: If `merge_default` is True, include it in the merge instead of using it as a fallback. """ - try: - result = reduce(or_, (filter_.actions for filter_ in filters if filter_.actions)) - except TypeError: # The sequence fed to reduce is empty. + if not filters: # Nothing to action. return None - - return result.fallback_to(self.defaults.actions) + try: + return reduce( + or_, (filter_.actions or self.defaults.actions for filter_ in filters) + ).fallback_to(self.defaults.actions) + except TypeError: + # The sequence fed to reduce is empty, meaning none of the filters have actions, + # meaning they all use the defaults. + return self.defaults.actions @staticmethod def format_messages(triggers: list[Filter], *, expand_single_filter: bool = True) -> list[str]: diff --git a/bot/exts/filtering/_settings.py b/bot/exts/filtering/_settings.py index 85a6f3d2b..a752918a6 100644 --- a/bot/exts/filtering/_settings.py +++ b/bot/exts/filtering/_settings.py @@ -1,6 +1,7 @@ from __future__ import annotations import operator +import traceback from abc import abstractmethod from functools import reduce from typing import Any, NamedTuple, Optional, TypeVar @@ -195,10 +196,18 @@ class ActionSettings(Settings[ActionEntry]): async def action(self, ctx: FilterContext) -> None: """Execute the action of every action entry stored, as well as any additional actions in the context.""" for entry in self.values(): - await entry.action(ctx) + try: + await entry.action(ctx) + # Filtering should not stop even if one type of action raised an exception. + # For example, if deleting the message raised somehow, it should still try to infract the user. + except Exception: + log.exception(traceback.format_exc()) for action in ctx.additional_actions: - await action(ctx) + try: + await action(ctx) + except Exception: + log.exception(traceback.format_exc()) def fallback_to(self, fallback: ActionSettings) -> ActionSettings: """Fill in missing entries from `fallback`.""" |