|  | 
| 1 |  | -from typing import Any, Optional, TYPE_CHECKING | 
|  | 1 | +from typing import TYPE_CHECKING, Any, Optional, Union | 
| 2 | 2 | 
 | 
| 3 | 3 | import attrs | 
| 4 | 4 | 
 | 
| 5 |  | -from interactions.client.const import get_logger, MISSING, Absent | 
|  | 5 | +from interactions.client.const import MISSING, Absent, get_logger | 
| 6 | 6 | from interactions.client.mixins.serialization import DictSerializationMixin | 
| 7 | 7 | from interactions.client.utils import list_converter, optional | 
| 8 | 8 | from interactions.client.utils.attr_utils import docs | 
| 9 | 9 | from interactions.models.discord.base import ClientObject, DiscordObject | 
| 10 | 10 | from interactions.models.discord.enums import ( | 
| 11 |  | -    AutoModTriggerType, | 
| 12 | 11 |     AutoModAction, | 
| 13 | 12 |     AutoModEvent, | 
| 14 | 13 |     AutoModLanuguageType, | 
|  | 14 | +    AutoModTriggerType, | 
| 15 | 15 | ) | 
| 16 |  | -from interactions.models.discord.snowflake import to_snowflake_list, to_snowflake | 
|  | 16 | +from interactions.models.discord.snowflake import to_snowflake, to_snowflake_list | 
| 17 | 17 | 
 | 
| 18 | 18 | if TYPE_CHECKING: | 
| 19 |  | -    from interactions import Snowflake_Type, Guild, GuildText, Message, Client, Member, User | 
|  | 19 | +    from interactions import ( | 
|  | 20 | +        Client, | 
|  | 21 | +        Guild, | 
|  | 22 | +        GuildText, | 
|  | 23 | +        Member, | 
|  | 24 | +        Message, | 
|  | 25 | +        Snowflake_Type, | 
|  | 26 | +        User, | 
|  | 27 | +    ) | 
| 20 | 28 | 
 | 
| 21 |  | -__all__ = ("AutoModerationAction", "AutoModRule") | 
|  | 29 | +__all__ = ("AutoModerationAction", "AutoModRule", "TYPE_ALL_ACTION", "TYPE_ALL_TRIGGER") | 
| 22 | 30 | 
 | 
| 23 | 31 | 
 | 
| 24 | 32 | @attrs.define(eq=False, order=False, hash=False, kw_only=True) | 
| @@ -71,7 +79,7 @@ def _process_dict(cls, data: dict[str, Any]) -> dict[str, Any]: | 
| 71 | 79 |         return data | 
| 72 | 80 | 
 | 
| 73 | 81 |     @classmethod | 
| 74 |  | -    def from_dict_factory(cls, data: dict) -> "BaseAction": | 
|  | 82 | +    def from_dict_factory(cls, data: dict) -> "TYPE_ALL_TRIGGER": | 
| 75 | 83 |         trigger_class = TRIGGER_MAPPING.get(data.get("trigger_type")) | 
| 76 | 84 |         meta = data.get("trigger_metadata", {}) | 
| 77 | 85 |         if not trigger_class: | 
| @@ -103,10 +111,22 @@ class KeywordTrigger(BaseTrigger): | 
| 103 | 111 |         repr=True, | 
| 104 | 112 |         metadata=docs("The type of trigger"), | 
| 105 | 113 |     ) | 
| 106 |  | -    keyword_filter: str | list[str] = attrs.field( | 
|  | 114 | +    keyword_filter: list[str] = attrs.field( | 
| 107 | 115 |         factory=list, | 
| 108 | 116 |         repr=True, | 
| 109 |  | -        metadata=docs("What words will trigger this"), | 
|  | 117 | +        metadata=docs("Substrings which will be searched for in content"), | 
|  | 118 | +        converter=_keyword_converter, | 
|  | 119 | +    ) | 
|  | 120 | +    regex_patterns: list[str] = attrs.field( | 
|  | 121 | +        factory=list, | 
|  | 122 | +        repr=True, | 
|  | 123 | +        metadata=docs("Regular expression patterns which will be matched against content"), | 
|  | 124 | +        converter=_keyword_converter, | 
|  | 125 | +    ) | 
|  | 126 | +    allow_list: list[str] = attrs.field( | 
|  | 127 | +        factory=list, | 
|  | 128 | +        repr=True, | 
|  | 129 | +        metadata=docs("Substrings which should not trigger the rule"), | 
| 110 | 130 |         converter=_keyword_converter, | 
| 111 | 131 |     ) | 
| 112 | 132 | 
 | 
| @@ -137,37 +157,57 @@ class KeywordPresetTrigger(BaseTrigger): | 
| 137 | 157 |         factory=list, | 
| 138 | 158 |         converter=list_converter(AutoModLanuguageType), | 
| 139 | 159 |         repr=True, | 
| 140 |  | -        metadata=docs("The preset list of keywords that will trigger this"), | 
|  | 160 | +        metadata=docs("The internally pre-defined wordsets which will be searched for in content"), | 
| 141 | 161 |     ) | 
| 142 | 162 | 
 | 
| 143 | 163 | 
 | 
| 144 | 164 | @attrs.define(eq=False, order=False, hash=False, kw_only=True) | 
| 145 | 165 | class MentionSpamTrigger(BaseTrigger): | 
| 146 |  | -    """A trigger that checks if content contains more mentions than allowed""" | 
|  | 166 | +    """A trigger that checks if content contains more unique mentions than allowed""" | 
| 147 | 167 | 
 | 
| 148 | 168 |     mention_total_limit: int = attrs.field( | 
| 149 | 169 |         default=3, repr=True, metadata=docs("The maximum number of mentions allowed") | 
| 150 | 170 |     ) | 
|  | 171 | +    mention_raid_protection_enabled: bool = attrs.field( | 
|  | 172 | +        repr=True, metadata=docs("Whether to automatically detect mention raids") | 
|  | 173 | +    ) | 
| 151 | 174 | 
 | 
| 152 | 175 | 
 | 
| 153 | 176 | @attrs.define(eq=False, order=False, hash=False, kw_only=True) | 
| 154 | 177 | class MemberProfileTrigger(BaseTrigger): | 
|  | 178 | +    """A trigger that checks if member profile contains words from a user defined list of keywords""" | 
|  | 179 | + | 
| 155 | 180 |     regex_patterns: list[str] = attrs.field( | 
| 156 |  | -        factory=list, repr=True, metadata=docs("The regex patterns to check against") | 
|  | 181 | +        factory=list, | 
|  | 182 | +        repr=True, | 
|  | 183 | +        metadata=docs("Regular expression patterns which will be matched against content"), | 
|  | 184 | +        converter=_keyword_converter, | 
| 157 | 185 |     ) | 
| 158 |  | -    keyword_filter: str | list[str] = attrs.field( | 
| 159 |  | -        factory=list, repr=True, metadata=docs("The keywords to check against") | 
|  | 186 | +    keyword_filter: list[str] = attrs.field( | 
|  | 187 | +        factory=list, | 
|  | 188 | +        repr=True, | 
|  | 189 | +        metadata=docs("Substrings which will be searched for in content"), | 
|  | 190 | +        converter=_keyword_converter, | 
| 160 | 191 |     ) | 
| 161 |  | -    allow_list: list["Snowflake_Type"] = attrs.field( | 
| 162 |  | -        factory=list, repr=True, metadata=docs("The roles exempt from this rule") | 
|  | 192 | +    allow_list: list[str] = attrs.field( | 
|  | 193 | +        factory=list, | 
|  | 194 | +        repr=True, | 
|  | 195 | +        metadata=docs("Substrings which should not trigger the rule"), | 
|  | 196 | +        converter=_keyword_converter, | 
| 163 | 197 |     ) | 
| 164 | 198 | 
 | 
| 165 | 199 | 
 | 
|  | 200 | +@attrs.define(eq=False, order=False, hash=False, kw_only=True) | 
|  | 201 | +class SpamTrigger(BaseTrigger): | 
|  | 202 | +    """A trigger that checks if content represents generic spam""" | 
|  | 203 | + | 
|  | 204 | + | 
| 166 | 205 | @attrs.define(eq=False, order=False, hash=False, kw_only=True) | 
| 167 | 206 | class BlockMessage(BaseAction): | 
| 168 |  | -    """blocks the content of a message according to the rule""" | 
|  | 207 | +    """Blocks the content of a message according to the rule""" | 
| 169 | 208 | 
 | 
| 170 | 209 |     type: AutoModAction = attrs.field(repr=False, default=AutoModAction.BLOCK_MESSAGE, converter=AutoModAction) | 
|  | 210 | +    custom_message: Optional[str] = attrs.field(repr=True, default=None) | 
| 171 | 211 | 
 | 
| 172 | 212 | 
 | 
| 173 | 213 | @attrs.define(eq=False, order=False, hash=False, kw_only=True) | 
| @@ -204,13 +244,13 @@ class AutoModRule(DiscordObject): | 
| 204 | 244 |     enabled: bool = attrs.field(repr=False, default=False) | 
| 205 | 245 |     """whether the rule is enabled""" | 
| 206 | 246 | 
 | 
| 207 |  | -    actions: list[BaseAction] = attrs.field(repr=False, factory=list) | 
|  | 247 | +    actions: list["TYPE_ALL_ACTION"] = attrs.field(repr=False, factory=list) | 
| 208 | 248 |     """the actions which will execute when the rule is triggered""" | 
| 209 | 249 |     event_type: AutoModEvent = attrs.field( | 
| 210 | 250 |         repr=False, | 
| 211 | 251 |     ) | 
| 212 | 252 |     """the rule event type""" | 
| 213 |  | -    trigger: BaseTrigger = attrs.field( | 
|  | 253 | +    trigger: "TYPE_ALL_TRIGGER" = attrs.field( | 
| 214 | 254 |         repr=False, | 
| 215 | 255 |     ) | 
| 216 | 256 |     """The trigger for this rule""" | 
| @@ -262,10 +302,10 @@ async def modify( | 
| 262 | 302 |         self, | 
| 263 | 303 |         *, | 
| 264 | 304 |         name: Absent[str] = MISSING, | 
| 265 |  | -        trigger: Absent[BaseTrigger] = MISSING, | 
|  | 305 | +        trigger: Absent["TYPE_ALL_TRIGGER"] = MISSING, | 
| 266 | 306 |         trigger_type: Absent[AutoModTriggerType] = MISSING, | 
| 267 | 307 |         trigger_metadata: Absent[dict] = MISSING, | 
| 268 |  | -        actions: Absent[list[BaseAction]] = MISSING, | 
|  | 308 | +        actions: Absent[list["TYPE_ALL_ACTION"]] = MISSING, | 
| 269 | 309 |         exempt_channels: Absent[list["Snowflake_Type"]] = MISSING, | 
| 270 | 310 |         exempt_roles: Absent[list["Snowflake_Type"]] = MISSING, | 
| 271 | 311 |         event_type: Absent[AutoModEvent] = MISSING, | 
| @@ -318,7 +358,7 @@ class AutoModerationAction(ClientObject): | 
| 318 | 358 |         repr=False, | 
| 319 | 359 |     ) | 
| 320 | 360 | 
 | 
| 321 |  | -    action: BaseAction = attrs.field(default=MISSING, repr=True) | 
|  | 361 | +    action: "TYPE_ALL_ACTION" = attrs.field(default=MISSING, repr=True) | 
| 322 | 362 | 
 | 
| 323 | 363 |     matched_keyword: str = attrs.field(repr=True) | 
| 324 | 364 |     matched_content: Optional[str] = attrs.field(repr=False, default=None) | 
| @@ -369,7 +409,12 @@ def member(self) -> "Optional[Member]": | 
| 369 | 409 | TRIGGER_MAPPING = { | 
| 370 | 410 |     AutoModTriggerType.KEYWORD: KeywordTrigger, | 
| 371 | 411 |     AutoModTriggerType.HARMFUL_LINK: HarmfulLinkFilter, | 
|  | 412 | +    AutoModTriggerType.SPAM: SpamTrigger, | 
| 372 | 413 |     AutoModTriggerType.KEYWORD_PRESET: KeywordPresetTrigger, | 
| 373 | 414 |     AutoModTriggerType.MENTION_SPAM: MentionSpamTrigger, | 
| 374 | 415 |     AutoModTriggerType.MEMBER_PROFILE: MemberProfileTrigger, | 
| 375 | 416 | } | 
|  | 417 | + | 
|  | 418 | +TYPE_ALL_TRIGGER = Union[KeywordTrigger, SpamTrigger, KeywordPresetTrigger, MentionSpamTrigger, MemberProfileTrigger] | 
|  | 419 | + | 
|  | 420 | +TYPE_ALL_ACTION = Union[BlockMessage, AlertMessage, TimeoutUser, BlockMemberInteraction] | 
0 commit comments