twilight_model/gateway/
intents.rs

1use bitflags::bitflags;
2use serde::{
3    de::{Deserialize, Deserializer},
4    ser::{Serialize, Serializer},
5};
6
7bitflags! {
8    /// Gateway intents.
9    ///
10    /// Developers must specify intents when connecting to the gateway. The
11    /// intents specified correspond with the events received. To specify
12    /// multiple intents, create a union using the `|` operator. See
13    /// [Discord Docs/Gateway Intents].
14    ///
15    /// [Discord Docs/Gateway Intents]: https://discord.com/developers/docs/topics/gateway#gateway-intents
16    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
17    pub struct Intents: u64 {
18        /// Guilds intent.
19        ///
20        /// Event(s) received:
21        ///  - [`GUILD_CREATE`]
22        ///  - [`GUILD_UPDATE`]
23        ///  - [`GUILD_DELETE`]
24        ///  - [`GUILD_ROLE_CREATE`]
25        ///  - [`GUILD_ROLE_UPDATE`]
26        ///  - [`GUILD_ROLE_DELETE`]
27        ///  - [`CHANNEL_CREATE`]
28        ///  - [`CHANNEL_UPDATE`]
29        ///  - [`CHANNEL_DELETE`]
30        ///  - [`CHANNEL_PINS_UPDATE`]
31        ///  - [`THREAD_CREATE`]
32        ///  - [`THREAD_UPDATE`]
33        ///  - [`THREAD_DELETE`]
34        ///  - [`THREAD_LIST_SYNC`]
35        ///  - [`THREAD_MEMBER_UPDATE`]
36        ///  - [`THREAD_MEMBERS_UPDATE`]
37        ///  - [`STAGE_INSTANCE_CREATE`]
38        ///  - [`STAGE_INSTANCE_UPDATE`]
39        ///  - [`STAGE_INSTANCE_DELETE`]
40        ///
41        /// [`GUILD_CREATE`]: super::event::Event::GuildCreate
42        /// [`GUILD_UPDATE`]: super::event::Event::GuildUpdate
43        /// [`GUILD_DELETE`]: super::event::Event::GuildDelete
44        /// [`GUILD_ROLE_CREATE`]: super::event::Event::RoleCreate
45        /// [`GUILD_ROLE_UPDATE`]: super::event::Event::RoleUpdate
46        /// [`GUILD_ROLE_DELETE`]: super::event::Event::RoleDelete
47        /// [`CHANNEL_CREATE`]: super::event::Event::ChannelCreate
48        /// [`CHANNEL_UPDATE`]: super::event::Event::ChannelUpdate
49        /// [`CHANNEL_DELETE`]: super::event::Event::ChannelDelete
50        /// [`CHANNEL_PINS_UPDATE`]: super::event::Event::ChannelPinsUpdate
51        /// [`THREAD_CREATE`]: super::event::Event::ThreadCreate
52        /// [`THREAD_UPDATE`]: super::event::Event::ThreadUpdate
53        /// [`THREAD_DELETE`]: super::event::Event::ThreadDelete
54        /// [`THREAD_LIST_SYNC`]: super::event::Event::ThreadListSync
55        /// [`THREAD_MEMBER_UPDATE`]: super::event::Event::ThreadMemberUpdate
56        /// [`THREAD_MEMBERS_UPDATE`]: super::event::Event::ThreadMembersUpdate
57        /// [`STAGE_INSTANCE_CREATE`]: super::event::Event::StageInstanceCreate
58        /// [`STAGE_INSTANCE_UPDATE`]: super::event::Event::StageInstanceUpdate
59        /// [`STAGE_INSTANCE_DELETE`]: super::event::Event::StageInstanceDelete
60        const GUILDS = 1;
61        /// Guild members intent.
62        ///
63        /// This intent is privileged. See [Discord Docs/Privileged Intents].
64        ///
65        /// Event(s) received:
66        ///  - [`GUILD_MEMBER_ADD`]
67        ///  - [`GUILD_MEMBER_UPDATE`]
68        ///  - [`GUILD_MEMBER_REMOVE`]
69        ///  - [`THREAD_MEMBERS_UPDATE`]
70        ///
71        /// [Discord Docs/Privileged Intents]: https://discord.com/developers/docs/topics/gateway#privileged-intents
72        /// [`GUILD_MEMBER_ADD`]: super::event::Event::MemberAdd
73        /// [`GUILD_MEMBER_UPDATE`]: super::event::Event::MemberUpdate
74        /// [`GUILD_MEMBER_REMOVE`]: super::event::Event::MemberRemove
75        /// [`THREAD_MEMBERS_UPDATE`]: super::event::Event::ThreadMembersUpdate
76        const GUILD_MEMBERS = 1 << 1;
77        /// Guild moderation intent.
78        ///
79        /// Event(s) received:
80        ///  - [`GUILD_AUDIT_LOG_ENTRY_CREATE`]
81        ///  - [`GUILD_BAN_ADD`]
82        ///  - [`GUILD_BAN_REMOVE`]
83        ///
84        /// [`GUILD_AUDIT_LOG_ENTRY_CREATE`]: super::event::Event::
85        /// [`GUILD_BAN_ADD`]: super::event::Event::BanAdd
86        /// [`GUILD_BAN_REMOVE`]: super::event::Event::BanRemove
87        const GUILD_MODERATION = 1 << 2;
88        /// Guild emojis and stickers intent.
89        ///
90        /// Event(s) received:
91        ///  - [`GUILD_EMOJIS_UPDATE`]
92        ///  - [`GUILD_STICKERS_UPDATE`]
93        ///
94        /// [`GUILD_EMOJIS_UPDATE`]: super::event::Event::GuildEmojisUpdate
95        /// [`GUILD_STICKERS_UPDATE`]: super::event::Event::GuildStickersUpdate
96        const GUILD_EMOJIS_AND_STICKERS = 1 << 3;
97        /// Guild integrations intent.
98        ///
99        /// Event(s) received:
100        ///  - [`GUILD_INTEGRATIONS_UPDATE`]
101        ///  - [`INTEGRATION_CREATE`]
102        ///  - [`INTEGRATION_UPDATE`]
103        ///  - [`INTEGRATION_DELETE`]
104        ///
105        /// [`GUILD_INTEGRATIONS_UPDATE`]: super::event::Event::GuildIntegrationsUpdate
106        /// [`INTEGRATION_CREATE`]: super::event::Event::IntegrationCreate
107        /// [`INTEGRATION_UPDATE`]: super::event::Event::IntegrationUpdate
108        /// [`INTEGRATION_DELETE`]: super::event::Event::IntegrationDelete
109        const GUILD_INTEGRATIONS = 1 << 4;
110        /// Guild webhooks intent.
111        ///
112        /// Event(s) received:
113        ///  - [`WEBHOOKS_UPDATE`]
114        ///
115        /// [`WEBHOOKS_UPDATE`]: super::event::Event::WebhooksUpdate
116        const GUILD_WEBHOOKS = 1 << 5;
117        /// Guild invites intent.
118        ///
119        /// Event(s) received:
120        ///  - [`INVITE_CREATE`]
121        ///  - [`INVITE_DELETE`]
122        ///
123        /// [`INVITE_CREATE`]: super::event::Event::InviteCreate
124        /// [`INVITE_DELETE`]: super::event::Event::InviteDelete
125        const GUILD_INVITES = 1 << 6;
126        /// Guild voice states intent.
127        ///
128        /// Event(s) received:
129        ///  - [`VOICE_STATE_UPDATE`]
130        ///
131        /// [`VOICE_STATE_UPDATE`]: super::event::Event::VoiceStateUpdate
132        const GUILD_VOICE_STATES = 1 << 7;
133        /// Guild presences intent.
134        ///
135        /// This intent is privileged. See [Discord Docs/Privileged Intents].
136        ///
137        /// Event(s) received:
138        ///  - [`PRESENCE_UPDATE`]
139        ///
140        /// [Discord Docs/Privileged Intents]: https://discord.com/developers/docs/topics/gateway#privileged-intents
141        /// [`PRESENCE_UPDATE`]: super::event::Event::PresenceUpdate
142        const GUILD_PRESENCES = 1 << 8;
143        /// Guild messages intent.
144        ///
145        /// Event(s) received:
146        ///  - [`MESSAGE_CREATE`]
147        ///  - [`MESSAGE_UPDATE`]
148        ///  - [`MESSAGE_DELETE`]
149        ///  - [`MESSAGE_DELETE_BULK`]
150        ///
151        /// [`MESSAGE_CREATE`]: super::event::Event::MessageCreate
152        /// [`MESSAGE_UPDATE`]: super::event::Event::MessageUpdate
153        /// [`MESSAGE_DELETE`]: super::event::Event::MessageDelete
154        /// [`MESSAGE_DELETE_BULK`]: super::event::Event::MessageDeleteBulk
155        const GUILD_MESSAGES = 1 << 9;
156        /// Guild message reactions intent.
157        ///
158        /// Event(s) received:
159        ///  - [`MESSAGE_REACTION_ADD`]
160        ///  - [`MESSAGE_REACTION_REMOVE`]
161        ///  - [`MESSAGE_REACTION_REMOVE_ALL`]
162        ///  - [`MESSAGE_REACTION_REMOVE_EMOJI`]
163        ///
164        /// [`MESSAGE_REACTION_ADD`]: super::event::Event::ReactionAdd
165        /// [`MESSAGE_REACTION_REMOVE`]: super::event::Event::ReactionRemove
166        /// [`MESSAGE_REACTION_REMOVE_ALL`]: super::event::Event::ReactionRemoveAll
167        /// [`MESSAGE_REACTION_REMOVE_EMOJI`]: super::event::Event::ReactionRemoveEmoji
168        const GUILD_MESSAGE_REACTIONS = 1 << 10;
169        /// Guild message typing intent.
170        ///
171        /// Event(s) received:
172        ///  - [`TYPING_START`]
173        ///
174        /// [`TYPING_START`]: super::event::Event::TypingStart
175        const GUILD_MESSAGE_TYPING = 1 << 11;
176        /// Direct messages intent.
177        ///
178        /// Event(s) received:
179        ///  - [`MESSAGE_CREATE`]
180        ///  - [`MESSAGE_UPDATE`]
181        ///  - [`MESSAGE_DELETE`]
182        ///  - [`MESSAGE_DELETE_BULK`]
183        ///
184        /// This is different from the [`GUILD_MESSAGES`] intent in that the bot
185        /// will receive message events from locations other than guilds.
186        ///
187        /// [`MESSAGE_CREATE`]: super::event::Event::MessageCreate
188        /// [`MESSAGE_UPDATE`]: super::event::Event::MessageUpdate
189        /// [`MESSAGE_DELETE`]: super::event::Event::MessageDelete
190        /// [`MESSAGE_DELETE_BULK`]: super::event::Event::MessageDeleteBulk
191        /// [`GUILD_MESSAGES`]: Self::GUILD_MESSAGES
192        const DIRECT_MESSAGES = 1 << 12;
193        /// Direct message reactions intent.
194        ///
195        /// Event(s) received:
196        ///  - [`MESSAGE_REACTION_ADD`]
197        ///  - [`MESSAGE_REACTION_REMOVE`]
198        ///  - [`MESSAGE_REACTION_REMOVE_ALL`]
199        ///  - [`MESSAGE_REACTION_REMOVE_EMOJI`]
200        ///
201        /// This is different from the [`GUILD_MESSAGE_REACTIONS`] event in that
202        /// the bot will receive message reaction events from locations other
203        /// than guilds.
204        ///
205        /// [`MESSAGE_REACTION_ADD`]: super::event::Event::ReactionAdd
206        /// [`MESSAGE_REACTION_REMOVE`]: super::event::Event::ReactionRemove
207        /// [`MESSAGE_REACTION_REMOVE_ALL`]: super::event::Event::ReactionRemoveAll
208        /// [`MESSAGE_REACTION_REMOVE_EMOJI`]: super::event::Event::ReactionRemoveEmoji
209        /// [`GUILD_MESSAGE_REACTIONS`]: Self::GUILD_MESSAGE_REACTIONS
210        const DIRECT_MESSAGE_REACTIONS = 1 << 13;
211        /// Direct message typing intent.
212        ///
213        /// Event(s) received:
214        ///  - [`TYPING_START`]
215        ///
216        /// This is different from the [`GUILD_MESSAGE_TYPING`] intent in that
217        /// the bot will receive typing start events from locations other than
218        /// guilds.
219        ///
220        /// [`TYPING_START`]: super::event::Event::TypingStart
221        /// [`GUILD_MESSAGE_TYPING`]: Self::GUILD_MESSAGE_TYPING
222        const DIRECT_MESSAGE_TYPING = 1 << 14;
223        /// Message content intent.
224        ///
225        /// This intent is privileged. See [Discord Docs/Privileged Intents].
226        ///
227        /// This intent allows you to receive the contents of all messages.
228        ///
229        /// [Discord Docs/Privileged Intents]: https://discord.com/developers/docs/topics/gateway#privileged-intents
230        const MESSAGE_CONTENT = 1 << 15;
231        /// Guild scheduled events intent.
232        ///
233        /// Event(s) received:
234        ///
235        /// - [`GUILD_SCHEDULED_EVENT_CREATE`]
236        /// - [`GUILD_SCHEDULED_EVENT_UPDATE`]
237        /// - [`GUILD_SCHEDULED_EVENT_DELETE`]
238        /// - [`GUILD_SCHEDULED_EVENT_USER_ADD`]
239        /// - [`GUILD_SCHEDULED_EVENT_USER_REMOVE`]
240        ///
241        /// [`GUILD_SCHEDULED_EVENT_CREATE`]: super::event::Event::GuildScheduledEventCreate
242        /// [`GUILD_SCHEDULED_EVENT_UPDATE`]: super::event::Event::GuildScheduledEventDelete
243        /// [`GUILD_SCHEDULED_EVENT_DELETE`]: super::event::Event::GuildScheduledEventUpdate
244        /// [`GUILD_SCHEDULED_EVENT_USER_ADD`]: super::event::Event::GuildScheduledEventUserAdd
245        /// [`GUILD_SCHEDULED_EVENT_USER_REMOVE`]: super::event::Event::GuildScheduledEventUserRemove
246        const GUILD_SCHEDULED_EVENTS = 1 << 16;
247        /// Auto moderation configuration intent.
248        ///
249        /// Event(s) received:
250        /// - [`AUTO_MODERATION_RULE_CREATE`]
251        /// - [`AUTO_MODERATION_RULE_DELETE`]
252        /// - [`AUTO_MODERATION_RULE_UPDATE`]
253        ///
254        /// [`AUTO_MODERATION_RULE_CREATE`]: super::event::Event::AutoModerationRuleCreate
255        /// [`AUTO_MODERATION_RULE_DELETE`]: super::event::Event::AutoModerationRuleDelete
256        /// [`AUTO_MODERATION_RULE_UPDATE`]: super::event::Event::AutoModerationRuleUpdate
257        const AUTO_MODERATION_CONFIGURATION = 1 << 20;
258        /// Auto moderation execution event.
259        ///
260        /// Event(s) received:
261        /// - [`AUTO_MODERATION_ACTION_EXECUTION`]
262        ///
263        /// [`AUTO_MODERATION_ACTION_EXECUTION`]: super::event::Event::AutoModerationActionExecution
264        const AUTO_MODERATION_EXECUTION = 1 << 21;
265        /// Guild polls intent.
266        ///
267        /// Event(s) received:
268        /// - [`MESSAGE_POLL_VOTE_ADD`]
269        /// - [`MESSAGE_POLL_VOTE_REMOVE`]
270        ///
271        /// [`MESSAGE_POLL_VOTE_ADD`]: super::event::Event::MessagePollVoteAdd
272        /// [`MESSAGE_POLL_VOTE_REMOVE`]: super::event::Event::MessagePollVoteRemove
273        const GUILD_MESSAGE_POLLS = 1 << 24;
274        /// Direct message polls intent.
275        ///
276        /// Event(s) received:
277        /// - [`MESSAGE_POLL_VOTE_ADD`]
278        /// - [`MESSAGE_POLL_VOTE_REMOVE`]
279        ///
280        /// [`MESSAGE_POLL_VOTE_ADD`]: super::event::Event::MessagePollVoteAdd
281        /// [`MESSAGE_POLL_VOTE_REMOVE`]: super::event::Event::MessagePollVoteRemove
282        const DIRECT_MESSAGE_POLLS = 1 << 25;
283    }
284}
285
286impl<'de> Deserialize<'de> for Intents {
287    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
288        Ok(Self::from_bits_truncate(u64::deserialize(deserializer)?))
289    }
290}
291
292impl Serialize for Intents {
293    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
294    where
295        S: Serializer,
296    {
297        serializer.serialize_u64(self.bits())
298    }
299}
300
301#[cfg(test)]
302mod tests {
303    #![allow(deprecated)]
304
305    use super::Intents;
306    use serde::{Deserialize, Serialize};
307    use serde_test::Token;
308    use static_assertions::{assert_impl_all, const_assert_eq};
309    use std::{
310        fmt::{Binary, Debug, LowerHex, Octal, UpperHex},
311        hash::Hash,
312        ops::{
313            BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Sub, SubAssign,
314        },
315    };
316
317    assert_impl_all!(
318        Intents: Binary,
319        BitAnd,
320        BitAndAssign,
321        BitOr,
322        BitOrAssign,
323        BitXor,
324        BitXorAssign,
325        Clone,
326        Copy,
327        Debug,
328        Deserialize<'static>,
329        Eq,
330        Extend<Intents>,
331        FromIterator<Intents>,
332        Hash,
333        LowerHex,
334        Not,
335        Octal,
336        PartialEq,
337        Send,
338        Serialize,
339        Sub,
340        SubAssign,
341        Sync,
342        UpperHex
343    );
344    const_assert_eq!(Intents::GUILDS.bits(), 1);
345    const_assert_eq!(Intents::GUILD_MEMBERS.bits(), 1 << 1);
346    const_assert_eq!(Intents::GUILD_MODERATION.bits(), 1 << 2);
347    const_assert_eq!(Intents::GUILD_EMOJIS_AND_STICKERS.bits(), 1 << 3);
348    const_assert_eq!(Intents::GUILD_INTEGRATIONS.bits(), 1 << 4);
349    const_assert_eq!(Intents::GUILD_WEBHOOKS.bits(), 1 << 5);
350    const_assert_eq!(Intents::GUILD_INVITES.bits(), 1 << 6);
351    const_assert_eq!(Intents::GUILD_VOICE_STATES.bits(), 1 << 7);
352    const_assert_eq!(Intents::GUILD_PRESENCES.bits(), 1 << 8);
353    const_assert_eq!(Intents::GUILD_MESSAGES.bits(), 1 << 9);
354    const_assert_eq!(Intents::GUILD_MESSAGE_REACTIONS.bits(), 1 << 10);
355    const_assert_eq!(Intents::GUILD_MESSAGE_TYPING.bits(), 1 << 11);
356    const_assert_eq!(Intents::DIRECT_MESSAGES.bits(), 1 << 12);
357    const_assert_eq!(Intents::DIRECT_MESSAGE_REACTIONS.bits(), 1 << 13);
358    const_assert_eq!(Intents::DIRECT_MESSAGE_TYPING.bits(), 1 << 14);
359    const_assert_eq!(Intents::MESSAGE_CONTENT.bits(), 1 << 15);
360    const_assert_eq!(Intents::GUILD_SCHEDULED_EVENTS.bits(), 1 << 16);
361    const_assert_eq!(Intents::AUTO_MODERATION_CONFIGURATION.bits(), 1 << 20);
362    const_assert_eq!(Intents::AUTO_MODERATION_EXECUTION.bits(), 1 << 21);
363    const_assert_eq!(Intents::GUILD_MESSAGE_POLLS.bits(), 1 << 24);
364    const_assert_eq!(Intents::DIRECT_MESSAGE_POLLS.bits(), 1 << 25);
365
366    #[test]
367    fn serde() {
368        serde_test::assert_tokens(
369            &Intents::MESSAGE_CONTENT,
370            &[Token::U64(Intents::MESSAGE_CONTENT.bits())],
371        );
372        // Deserialization truncates unknown bits.
373        serde_test::assert_de_tokens(&Intents::empty(), &[Token::U64(1 << 63)]);
374    }
375}