Skip to main content

twilight_model/channel/message/
kind.rs

1use crate::guild::Permissions;
2use serde::{Deserialize, Serialize};
3
4/// Type of a [`Message`].
5///
6/// Refer to [Discord Docs/Message Types] for more information.
7///
8/// [Discord Docs/Message Types]: https://discord.com/developers/docs/resources/channel#message-object-message-types
9/// [`Message`]: super::Message
10#[allow(missing_docs)]
11#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
12#[non_exhaustive]
13#[serde(from = "u8", into = "u8")]
14pub enum MessageType {
15    /// Regular message.
16    Regular,
17    /// System message denoting a recipient has been added to a group.
18    RecipientAdd,
19    /// System message denoting a recipient has been removed from a group.
20    RecipientRemove,
21    /// System message denoting a call state, e.g. missed, started.
22    Call,
23    /// System message denoting a channel's name has been changed.
24    ChannelNameChange,
25    /// System message denoting a channel's icon has been changed.
26    ChannelIconChange,
27    /// System message denoting a message has been pinned.
28    ChannelMessagePinned,
29    /// System message denoting a member has joined a guild.
30    UserJoin,
31    /// System message denoting a user nitro boosted a guild.
32    GuildBoost,
33    /// System message denoting a user nitro boosted a guild to level 1.
34    GuildBoostTier1,
35    /// System message denoting a user nitro boosted a guild to level 2.
36    GuildBoostTier2,
37    /// System message denoting a user nitro boosted a guild to level 3.
38    GuildBoostTier3,
39    /// System message denoting a channel has been followed.
40    ChannelFollowAdd,
41    /// System message denoting a guild has been disqualified for Server Discovery.
42    GuildDiscoveryDisqualified,
43    /// System message denoting a guild has been redisqualified for Server Discovery.
44    GuildDiscoveryRequalified,
45    /// System message denoting an initial warning for Server Discovery disqualification.
46    GuildDiscoveryGracePeriodInitialWarning,
47    /// System message denoting a final warning for Server Discovery disqualification.
48    GuildDiscoveryGracePeriodFinalWarning,
49    ThreadCreated,
50    /// Message is an inline reply.
51    Reply,
52    /// Message is a chat input command.
53    ChatInputCommand,
54    ThreadStarterMessage,
55    GuildInviteReminder,
56    ContextMenuCommand,
57    /// Message is an auto moderation action.
58    AutoModerationAction,
59    /// System message denoting a user subscribed to a role.
60    RoleSubscriptionPurchase,
61    /// System message denoting a interaction premium upsell.
62    InteractionPremiumUpsell,
63    /// System message denoting a stage instance has started.
64    StageStart,
65    /// System message denoting a stage instance has ended.
66    StageEnd,
67    /// System message for stage instance speakers.
68    StageSpeaker,
69    /// System message denoting the topic for a stage instance.
70    StageTopic,
71    /// System message denoting a guild application premium subscription.
72    GuildApplicationPremiumSubscription,
73    /// System message denoting a guild auto moderation incident alerts are enabled.
74    GuildIncidentAlertModeEnabled,
75    /// System message denoting a guild auto moderation incident alerts are disabled.
76    GuildIncidentAlertModeDisabled,
77    /// System message denoting a guild raid incident report.
78    GuildIncidentReportRaid,
79    /// System message denoting a false positive guild raid incident report.
80    GuildIncidentReportRaidFalseAlarm,
81    /// Message is a purchase notification.
82    PurchaseNotification,
83    /// Message is a poll result.
84    PollResult,
85    /// Variant value is unknown to the library.
86    Unknown(u8),
87}
88
89impl MessageType {
90    /// Whether the message can be deleted, not taking permissions into account.
91    /// Some message types can't be deleted, even by server administrators.
92    ///
93    /// Some message types can only be deleted with certain permissions. For
94    /// example, [`AutoModerationAction`][`Self::AutoModerationAction`] can only
95    /// be deleted if the user has the
96    /// [Manage Messages] permission.
97    ///
98    /// To check whether a message can be deleted while taking permissions into
99    /// account, use
100    /// [`deletable_with_permissions`][`Self::deletable_with_permissions`].
101    ///
102    /// [Manage Messages]: Permissions::MANAGE_MESSAGES
103    pub const fn deletable(self) -> bool {
104        matches!(
105            self,
106            Self::Regular
107                | Self::ChannelMessagePinned
108                | Self::UserJoin
109                | Self::GuildBoost
110                | Self::GuildBoostTier1
111                | Self::GuildBoostTier2
112                | Self::GuildBoostTier3
113                | Self::ChannelFollowAdd
114                | Self::ThreadCreated
115                | Self::Reply
116                | Self::ChatInputCommand
117                | Self::GuildInviteReminder
118                | Self::ContextMenuCommand
119                | Self::AutoModerationAction
120                | Self::RoleSubscriptionPurchase
121                | Self::InteractionPremiumUpsell
122                | Self::StageStart
123                | Self::StageEnd
124                | Self::StageSpeaker
125                | Self::StageTopic
126                | Self::GuildApplicationPremiumSubscription
127                | Self::GuildIncidentAlertModeEnabled
128                | Self::GuildIncidentAlertModeDisabled
129                | Self::GuildIncidentReportRaid
130                | Self::GuildIncidentReportRaidFalseAlarm
131                | Self::PurchaseNotification
132                | Self::PollResult
133        )
134    }
135
136    /// Whether the message can be deleted, taking permissions into account.
137    /// Some message types can't be deleted, even by server administrators.
138    ///
139    /// Some message types can only be deleted with certain permissions. For
140    /// example, [`AutoModerationAction`][`Self::AutoModerationAction`] can only
141    /// be deleted if the user has the [Manage Messages] permission.
142    ///
143    /// To check whether a message can be deleted *without* taking permissions
144    /// into account, use [`deletable`][`Self::deletable`].
145    ///
146    /// [Manage Messages]: Permissions::MANAGE_MESSAGES
147    pub const fn deletable_with_permissions(self, permissions: Permissions) -> bool {
148        let required_permissions = match self {
149            Self::AutoModerationAction => Permissions::MANAGE_MESSAGES,
150            _ => Permissions::empty(),
151        };
152
153        if !permissions.contains(required_permissions) {
154            return false;
155        }
156
157        self.deletable()
158    }
159}
160
161impl From<u8> for MessageType {
162    fn from(value: u8) -> Self {
163        match value {
164            0 => Self::Regular,
165            1 => Self::RecipientAdd,
166            2 => Self::RecipientRemove,
167            3 => Self::Call,
168            4 => Self::ChannelNameChange,
169            5 => Self::ChannelIconChange,
170            6 => Self::ChannelMessagePinned,
171            7 => Self::UserJoin,
172            8 => Self::GuildBoost,
173            9 => Self::GuildBoostTier1,
174            10 => Self::GuildBoostTier2,
175            11 => Self::GuildBoostTier3,
176            12 => Self::ChannelFollowAdd,
177            14 => Self::GuildDiscoveryDisqualified,
178            15 => Self::GuildDiscoveryRequalified,
179            16 => Self::GuildDiscoveryGracePeriodInitialWarning,
180            17 => Self::GuildDiscoveryGracePeriodFinalWarning,
181            18 => Self::ThreadCreated,
182            19 => Self::Reply,
183            20 => Self::ChatInputCommand,
184            21 => Self::ThreadStarterMessage,
185            22 => Self::GuildInviteReminder,
186            23 => Self::ContextMenuCommand,
187            24 => Self::AutoModerationAction,
188            25 => Self::RoleSubscriptionPurchase,
189            26 => Self::InteractionPremiumUpsell,
190            27 => Self::StageStart,
191            28 => Self::StageEnd,
192            29 => Self::StageSpeaker,
193            31 => Self::StageTopic,
194            32 => Self::GuildApplicationPremiumSubscription,
195            36 => Self::GuildIncidentAlertModeEnabled,
196            37 => Self::GuildIncidentAlertModeDisabled,
197            38 => Self::GuildIncidentReportRaid,
198            39 => Self::GuildIncidentReportRaidFalseAlarm,
199            44 => Self::PurchaseNotification,
200            46 => Self::PollResult,
201            unknown => Self::Unknown(unknown),
202        }
203    }
204}
205
206impl From<MessageType> for u8 {
207    fn from(value: MessageType) -> Self {
208        match value {
209            MessageType::Regular => 0,
210            MessageType::RecipientAdd => 1,
211            MessageType::RecipientRemove => 2,
212            MessageType::Call => 3,
213            MessageType::ChannelNameChange => 4,
214            MessageType::ChannelIconChange => 5,
215            MessageType::ChannelMessagePinned => 6,
216            MessageType::UserJoin => 7,
217            MessageType::GuildBoost => 8,
218            MessageType::GuildBoostTier1 => 9,
219            MessageType::GuildBoostTier2 => 10,
220            MessageType::GuildBoostTier3 => 11,
221            MessageType::ChannelFollowAdd => 12,
222            MessageType::GuildDiscoveryDisqualified => 14,
223            MessageType::GuildDiscoveryRequalified => 15,
224            MessageType::GuildDiscoveryGracePeriodInitialWarning => 16,
225            MessageType::GuildDiscoveryGracePeriodFinalWarning => 17,
226            MessageType::ThreadCreated => 18,
227            MessageType::Reply => 19,
228            MessageType::ChatInputCommand => 20,
229            MessageType::ThreadStarterMessage => 21,
230            MessageType::GuildInviteReminder => 22,
231            MessageType::ContextMenuCommand => 23,
232            MessageType::AutoModerationAction => 24,
233            MessageType::RoleSubscriptionPurchase => 25,
234            MessageType::InteractionPremiumUpsell => 26,
235            MessageType::StageStart => 27,
236            MessageType::StageEnd => 28,
237            MessageType::StageSpeaker => 29,
238            MessageType::StageTopic => 31,
239            MessageType::GuildApplicationPremiumSubscription => 32,
240            MessageType::GuildIncidentAlertModeEnabled => 36,
241            MessageType::GuildIncidentAlertModeDisabled => 37,
242            MessageType::GuildIncidentReportRaid => 38,
243            MessageType::GuildIncidentReportRaidFalseAlarm => 39,
244            MessageType::PurchaseNotification => 44,
245            MessageType::PollResult => 46,
246            MessageType::Unknown(unknown) => unknown,
247        }
248    }
249}
250
251#[cfg(test)]
252mod tests {
253    use super::MessageType;
254    use crate::guild::Permissions;
255    use serde::{Deserialize, Serialize};
256    use serde_test::Token;
257    use static_assertions::assert_impl_all;
258    use std::{fmt::Debug, hash::Hash};
259
260    assert_impl_all!(
261        MessageType: Clone,
262        Copy,
263        Debug,
264        Deserialize<'static>,
265        Eq,
266        Hash,
267        PartialEq,
268        Send,
269        Serialize,
270        Sync
271    );
272
273    #[test]
274    fn message_type() {
275        const MAP: &[(MessageType, u8, bool)] = &[
276            (MessageType::Regular, 0, true),
277            (MessageType::RecipientAdd, 1, false),
278            (MessageType::RecipientRemove, 2, false),
279            (MessageType::Call, 3, false),
280            (MessageType::ChannelNameChange, 4, false),
281            (MessageType::ChannelIconChange, 5, false),
282            (MessageType::ChannelMessagePinned, 6, true),
283            (MessageType::UserJoin, 7, true),
284            (MessageType::GuildBoost, 8, true),
285            (MessageType::GuildBoostTier1, 9, true),
286            (MessageType::GuildBoostTier2, 10, true),
287            (MessageType::GuildBoostTier3, 11, true),
288            (MessageType::ChannelFollowAdd, 12, true),
289            (MessageType::GuildDiscoveryDisqualified, 14, false),
290            (MessageType::GuildDiscoveryRequalified, 15, false),
291            (
292                MessageType::GuildDiscoveryGracePeriodInitialWarning,
293                16,
294                false,
295            ),
296            (
297                MessageType::GuildDiscoveryGracePeriodFinalWarning,
298                17,
299                false,
300            ),
301            (MessageType::ThreadCreated, 18, true),
302            (MessageType::Reply, 19, true),
303            (MessageType::ChatInputCommand, 20, true),
304            (MessageType::ThreadStarterMessage, 21, false),
305            (MessageType::GuildInviteReminder, 22, true),
306            (MessageType::ContextMenuCommand, 23, true),
307            (MessageType::AutoModerationAction, 24, true),
308            (MessageType::RoleSubscriptionPurchase, 25, true),
309            (MessageType::InteractionPremiumUpsell, 26, true),
310            (MessageType::StageStart, 27, true),
311            (MessageType::StageEnd, 28, true),
312            (MessageType::StageSpeaker, 29, true),
313            (MessageType::StageTopic, 31, true),
314            (MessageType::GuildApplicationPremiumSubscription, 32, true),
315            (MessageType::GuildIncidentAlertModeEnabled, 36, true),
316            (MessageType::GuildIncidentAlertModeDisabled, 37, true),
317            (MessageType::GuildIncidentReportRaid, 38, true),
318            (MessageType::GuildIncidentReportRaidFalseAlarm, 39, true),
319            (MessageType::PurchaseNotification, 44, true),
320            (MessageType::PollResult, 46, true),
321        ];
322
323        for (message_type, number, deletable) in MAP {
324            assert_eq!(*message_type, MessageType::from(*number));
325            assert_eq!(*number, u8::from(*message_type));
326            assert_eq!(*deletable, message_type.deletable());
327            serde_test::assert_tokens(message_type, &[Token::U8(*number)]);
328        }
329    }
330
331    #[test]
332    fn deletable_with_permissions() {
333        assert!(
334            MessageType::AutoModerationAction
335                .deletable_with_permissions(Permissions::MANAGE_MESSAGES)
336        );
337        assert!(
338            !MessageType::AutoModerationAction.deletable_with_permissions(Permissions::empty())
339        );
340    }
341}