diff --git a/discord/automod.py b/discord/automod.py index 84a00c87eaa1..5b1620f12f7d 100644 --- a/discord/automod.py +++ b/discord/automod.py @@ -25,7 +25,7 @@ from __future__ import annotations import datetime -from typing import TYPE_CHECKING, Any, Dict, Optional, List, Set, Union, Sequence, overload +from typing import TYPE_CHECKING, Any, Dict, Optional, List, Set, Union, Sequence, overload, Literal from .enums import AutoModRuleTriggerType, AutoModRuleActionType, AutoModRuleEventType, try_enum from .flags import AutoModPresets @@ -85,36 +85,76 @@ class AutoModRuleAction: __slots__ = ('type', 'channel_id', 'duration', 'custom_message') @overload - def __init__(self, *, channel_id: Optional[int] = ...) -> None: + def __init__(self, *, channel_id: int = ...) -> None: ... @overload - def __init__(self, *, duration: Optional[datetime.timedelta] = ...) -> None: + def __init__(self, *, type: Literal[AutoModRuleActionType.send_alert_message], channel_id: int = ...) -> None: ... @overload - def __init__(self, *, custom_message: Optional[str] = ...) -> None: + def __init__(self, *, duration: datetime.timedelta = ...) -> None: + ... + + @overload + def __init__(self, *, type: Literal[AutoModRuleActionType.timeout], duration: datetime.timedelta = ...) -> None: + ... + + @overload + def __init__(self, *, custom_message: str = ...) -> None: + ... + + @overload + def __init__(self, *, type: Literal[AutoModRuleActionType.block_message]) -> None: + ... + + @overload + def __init__(self, *, type: Literal[AutoModRuleActionType.block_message], custom_message: Optional[str] = ...) -> None: + ... + + @overload + def __init__( + self, + *, + type: Optional[AutoModRuleActionType] = ..., + channel_id: Optional[int] = ..., + duration: Optional[datetime.timedelta] = ..., + custom_message: Optional[str] = ..., + ) -> None: ... def __init__( self, *, + type: Optional[AutoModRuleActionType] = None, channel_id: Optional[int] = None, duration: Optional[datetime.timedelta] = None, custom_message: Optional[str] = None, ) -> None: - self.channel_id: Optional[int] = channel_id - self.duration: Optional[datetime.timedelta] = duration - self.custom_message: Optional[str] = custom_message - if sum(v is None for v in (channel_id, duration, custom_message)) < 2: raise ValueError('Only one of channel_id, duration, or custom_message can be passed.') - self.type: AutoModRuleActionType = AutoModRuleActionType.block_message - if channel_id: + self.type: AutoModRuleActionType + if type is not None: + self.type = type + elif channel_id is not None: self.type = AutoModRuleActionType.send_alert_message - elif duration: + elif duration is not None: self.type = AutoModRuleActionType.timeout + else: + self.type = AutoModRuleActionType.block_message + + if self.type is AutoModRuleActionType.send_alert_message: + if channel_id is None: + raise ValueError('channel_id cannot be None if type is send_alert_message') + self.channel_id: Optional[int] = channel_id + + if self.type is AutoModRuleActionType.timeout: + if duration is None: + raise ValueError('duration cannot be None set if type is timeout') + self.duration: Optional[datetime.timedelta] = duration + + self.custom_message: Optional[str] = custom_message def __repr__(self) -> str: return f'' @@ -127,7 +167,11 @@ def from_data(cls, data: AutoModerationActionPayload) -> Self: elif data['type'] == AutoModRuleActionType.send_alert_message.value: channel_id = int(data['metadata']['channel_id']) return cls(channel_id=channel_id) - return cls(custom_message=data.get('metadata', {}).get('custom_message')) + elif data['type'] == AutoModRuleActionType.block_message.value: + custom_message = data.get('metadata', {}).get('custom_message') + return cls(type=AutoModRuleActionType.block_message, custom_message=custom_message) + + return cls(type=AutoModRuleActionType.block_member_interactions) def to_dict(self) -> Dict[str, Any]: ret = {'type': self.type.value, 'metadata': {}} @@ -155,7 +199,11 @@ class AutoModTrigger: +-----------------------------------------------+------------------------------------------------+ | :attr:`AutoModRuleTriggerType.keyword_preset` | :attr:`presets`\, :attr:`allow_list` | +-----------------------------------------------+------------------------------------------------+ - | :attr:`AutoModRuleTriggerType.mention_spam` | :attr:`mention_limit` | + | :attr:`AutoModRuleTriggerType.mention_spam` | :attr:`mention_limit`, | + | | :attr:`mention_raid_protection` | + +-----------------------------------------------+------------------------------------------------+ + | :attr:`AutoModRuleTriggerType.member_profile` | :attr:`keyword_filter`, :attr:`regex_patterns`,| + | | :attr:`allow_list` | +-----------------------------------------------+------------------------------------------------+ .. versionadded:: 2.0 @@ -185,6 +233,10 @@ class AutoModTrigger: mention_limit: :class:`int` The total number of user and role mentions a message can contain. Has a maximum of 50. + mention_raid_protection: :class:`bool` + Whether mention raid protection is enabled or not. + + .. versionadded:: 2.4 """ __slots__ = ( @@ -194,6 +246,7 @@ class AutoModTrigger: 'allow_list', 'mention_limit', 'regex_patterns', + 'mention_raid_protection', ) def __init__( @@ -205,6 +258,7 @@ def __init__( allow_list: Optional[List[str]] = None, mention_limit: Optional[int] = None, regex_patterns: Optional[List[str]] = None, + mention_raid_protection: Optional[bool] = None, ) -> None: if type is None and sum(arg is not None for arg in (keyword_filter or regex_patterns, presets, mention_limit)) > 1: raise ValueError('Please pass only one of keyword_filter, regex_patterns, presets, or mention_limit.') @@ -215,7 +269,7 @@ def __init__( self.type = AutoModRuleTriggerType.keyword elif presets is not None: self.type = AutoModRuleTriggerType.keyword_preset - elif mention_limit is not None: + elif mention_limit is not None or mention_raid_protection is not None: self.type = AutoModRuleTriggerType.mention_spam else: raise ValueError( @@ -226,6 +280,7 @@ def __init__( self.presets: AutoModPresets = presets if presets is not None else AutoModPresets() self.allow_list: List[str] = allow_list if allow_list is not None else [] self.mention_limit: int = mention_limit if mention_limit is not None else 0 + self.mention_raid_protection: bool = mention_raid_protection if mention_raid_protection is not None else False self.regex_patterns: List[str] = regex_patterns if regex_patterns is not None else [] def __repr__(self) -> str: @@ -253,7 +308,11 @@ def from_data(cls, type: int, data: Optional[AutoModerationTriggerMetadataPayloa type=type_, presets=AutoModPresets._from_value(data.get('presets', [])), allow_list=data.get('allow_list') ) elif type_ is AutoModRuleTriggerType.mention_spam: - return cls(type=type_, mention_limit=data.get('mention_total_limit')) + return cls( + type=type_, + mention_limit=data.get('mention_total_limit'), + mention_raid_protection=data.get('mention_raid_protection_enabled'), + ) else: return cls(type=type_) @@ -267,7 +326,10 @@ def to_metadata_dict(self) -> Optional[Dict[str, Any]]: elif self.type is AutoModRuleTriggerType.keyword_preset: return {'presets': self.presets.to_array(), 'allow_list': self.allow_list} elif self.type is AutoModRuleTriggerType.mention_spam: - return {'mention_total_limit': self.mention_limit} + return { + 'mention_total_limit': self.mention_limit, + 'mention_raid_protection_enabled': self.mention_raid_protection, + } class AutoModRule: diff --git a/discord/enums.py b/discord/enums.py index 254f86bc789d..de18fe524e5f 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -750,16 +750,19 @@ class AutoModRuleTriggerType(Enum): spam = 3 keyword_preset = 4 mention_spam = 5 + member_profile = 6 class AutoModRuleEventType(Enum): message_send = 1 + member_update = 2 class AutoModRuleActionType(Enum): block_message = 1 send_alert_message = 2 timeout = 3 + block_member_interactions = 4 class ForumLayoutType(Enum): diff --git a/discord/types/automod.py b/discord/types/automod.py index 9b0b13692609..246b7ee6a73b 100644 --- a/discord/types/automod.py +++ b/discord/types/automod.py @@ -79,6 +79,7 @@ class _AutoModerationTriggerMetadataKeywordPreset(TypedDict): class _AutoModerationTriggerMetadataMentionLimit(TypedDict): mention_total_limit: int + mention_raid_protection_enabled: bool AutoModerationTriggerMetadata = Union[ diff --git a/docs/api.rst b/docs/api.rst index 253e76d85d0f..d48e6fb1a614 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -3330,6 +3330,12 @@ of :class:`enum.Enum`. The rule will trigger when combined number of role and user mentions is greater than the set limit. + .. attribute:: member_profile + + The rule will trigger when a user's profile contains a keyword. + + .. versionadded:: 2.4 + .. class:: AutoModRuleEventType Represents the event type of an automod rule. @@ -3340,6 +3346,12 @@ of :class:`enum.Enum`. The rule will trigger when a message is sent. + .. attribute:: member_update + + The rule will trigger when a member's profile is updated. + + .. versionadded:: 2.4 + .. class:: AutoModRuleActionType Represents the action type of an automod rule. @@ -3358,6 +3370,12 @@ of :class:`enum.Enum`. The rule will timeout a user. + .. attribute:: block_member_interactions + + Similar to :attr:`timeout`, except the user will be timed out indefinitely. + This will request the user to edit it's profile. + + .. versionadded:: 2.4 .. class:: ForumLayoutType