|
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