serenity_self/model/
event.rs

1//! All the events this library handles.
2//!
3//! Every event includes the gateway intent required to receive it, as well as a link to the
4//! Discord documentation for the event.
5
6// Just for MessageUpdateEvent (for some reason the #[allow] doesn't work when placed directly)
7#![allow(clippy::option_option)]
8
9use serde::de::Error as DeError;
10use serde::Serialize;
11
12use crate::constants::Opcode;
13use crate::model::prelude::*;
14use crate::model::utils::{
15    deserialize_val,
16    emojis,
17    members,
18    optional_deserialize_components,
19    remove_from_map,
20    remove_from_map_opt,
21    stickers,
22};
23
24/// Requires no gateway intents.
25///
26/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#application-command-permissions-update).
27#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
28#[derive(Clone, Debug, Deserialize, Serialize)]
29#[serde(transparent)]
30#[non_exhaustive]
31pub struct CommandPermissionsUpdateEvent {
32    pub permission: CommandPermissions,
33}
34
35/// Requires [`GatewayIntents::AUTO_MODERATION_CONFIGURATION`].
36///
37/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#auto-moderation-rule-create).
38#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
39#[derive(Clone, Debug, Deserialize, Serialize)]
40#[serde(transparent)]
41#[non_exhaustive]
42pub struct AutoModRuleCreateEvent {
43    pub rule: Rule,
44}
45
46/// Requires [`GatewayIntents::AUTO_MODERATION_CONFIGURATION`].
47///
48/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#auto-moderation-rule-update).
49#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
50#[derive(Clone, Debug, Deserialize, Serialize)]
51#[serde(transparent)]
52#[non_exhaustive]
53pub struct AutoModRuleUpdateEvent {
54    pub rule: Rule,
55}
56
57/// Requires [`GatewayIntents::AUTO_MODERATION_CONFIGURATION`].
58///
59/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#auto-moderation-rule-delete).
60#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
61#[derive(Clone, Debug, Deserialize, Serialize)]
62#[serde(transparent)]
63#[non_exhaustive]
64pub struct AutoModRuleDeleteEvent {
65    pub rule: Rule,
66}
67
68/// Requires [`GatewayIntents::AUTO_MODERATION_EXECUTION`].
69///
70/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#auto-moderation-action-execution).
71#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
72#[derive(Clone, Debug, Deserialize, Serialize)]
73#[serde(transparent)]
74#[non_exhaustive]
75pub struct AutoModActionExecutionEvent {
76    pub execution: ActionExecution,
77}
78
79/// Event data for the channel creation event.
80///
81/// This is fired when:
82/// - A [`Channel`] is created in a [`Guild`]
83///
84/// Requires [`GatewayIntents::GUILDS`].
85///
86/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#channel-create).
87#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
88#[derive(Clone, Debug, Deserialize, Serialize)]
89#[serde(transparent)]
90#[non_exhaustive]
91pub struct ChannelCreateEvent {
92    /// The channel that was created.
93    pub channel: GuildChannel,
94}
95
96/// Requires [`GatewayIntents::GUILDS`].
97///
98/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#channel-delete).
99#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
100#[derive(Clone, Debug, Deserialize, Serialize)]
101#[serde(transparent)]
102#[non_exhaustive]
103pub struct ChannelDeleteEvent {
104    pub channel: GuildChannel,
105}
106
107/// Requires [`GatewayIntents::GUILDS`] or [`GatewayIntents::DIRECT_MESSAGES`].
108///
109/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#channel-pins-update).
110#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
111#[derive(Clone, Debug, Deserialize, Serialize)]
112#[non_exhaustive]
113pub struct ChannelPinsUpdateEvent {
114    pub guild_id: Option<GuildId>,
115    pub channel_id: ChannelId,
116    pub last_pin_timestamp: Option<Timestamp>,
117}
118
119/// Requires [`GatewayIntents::GUILDS`].
120///
121/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#channel-update).
122#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
123#[derive(Clone, Debug, Deserialize, Serialize)]
124#[serde(transparent)]
125#[non_exhaustive]
126pub struct ChannelUpdateEvent {
127    pub channel: GuildChannel,
128}
129
130/// Requires [`GatewayIntents::GUILD_MODERATION`] and [`Permissions::VIEW_AUDIT_LOG`].
131///
132/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-audit-log-entry-create).
133#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
134#[derive(Clone, Debug, Deserialize, Serialize)]
135#[non_exhaustive]
136pub struct GuildAuditLogEntryCreateEvent {
137    pub guild_id: GuildId,
138    #[serde(flatten)]
139    pub entry: AuditLogEntry,
140}
141
142/// Requires [`GatewayIntents::GUILD_MODERATION`].
143///
144/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-ban-add).
145#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
146#[derive(Clone, Debug, Deserialize, Serialize)]
147#[non_exhaustive]
148pub struct GuildBanAddEvent {
149    pub guild_id: GuildId,
150    pub user: User,
151}
152
153/// Requires [`GatewayIntents::GUILD_MODERATION`].
154///
155/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-ban-remove).
156#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
157#[derive(Clone, Debug, Deserialize, Serialize)]
158#[non_exhaustive]
159pub struct GuildBanRemoveEvent {
160    pub guild_id: GuildId,
161    pub user: User,
162}
163
164/// Requires [`GatewayIntents::GUILDS`].
165///
166/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-create).
167#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
168#[derive(Clone, Debug, Serialize)]
169#[serde(transparent)]
170#[non_exhaustive]
171pub struct GuildCreateEvent {
172    pub guild: Guild,
173}
174
175// Manual impl needed to insert guild_id fields in GuildChannel, Member, Role
176impl<'de> Deserialize<'de> for GuildCreateEvent {
177    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
178        let mut guild: Guild = Guild::deserialize(deserializer)?;
179        guild.channels.values_mut().for_each(|x| x.guild_id = guild.id);
180        guild.members.values_mut().for_each(|x| x.guild_id = guild.id);
181        guild.roles.values_mut().for_each(|x| x.guild_id = guild.id);
182        Ok(Self {
183            guild,
184        })
185    }
186}
187
188/// Requires [`GatewayIntents::GUILDS`].
189///
190/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-delete).
191#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
192#[derive(Clone, Debug, Deserialize, Serialize)]
193#[serde(transparent)]
194#[non_exhaustive]
195pub struct GuildDeleteEvent {
196    pub guild: UnavailableGuild,
197}
198
199/// Requires [`GatewayIntents::GUILD_EMOJIS_AND_STICKERS`].
200///
201/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-emojis-update).
202#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
203#[derive(Clone, Debug, Deserialize, Serialize)]
204#[non_exhaustive]
205pub struct GuildEmojisUpdateEvent {
206    #[serde(with = "emojis")]
207    pub emojis: HashMap<EmojiId, Emoji>,
208    pub guild_id: GuildId,
209}
210
211/// Requires [`GatewayIntents::GUILD_INTEGRATIONS`].
212///
213/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-integrations-update).
214#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
215#[derive(Clone, Debug, Deserialize, Serialize)]
216#[non_exhaustive]
217pub struct GuildIntegrationsUpdateEvent {
218    pub guild_id: GuildId,
219}
220
221/// Requires [`GatewayIntents::GUILD_MEMBERS`].
222///
223/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-member-add).
224#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
225#[derive(Clone, Debug, Deserialize, Serialize)]
226#[serde(transparent)]
227#[non_exhaustive]
228pub struct GuildMemberAddEvent {
229    pub member: Member,
230}
231
232/// Requires [`GatewayIntents::GUILD_MEMBERS`].
233///
234/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-member-remove).
235#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
236#[derive(Clone, Debug, Deserialize, Serialize)]
237#[non_exhaustive]
238pub struct GuildMemberRemoveEvent {
239    pub guild_id: GuildId,
240    pub user: User,
241}
242
243/// Requires [`GatewayIntents::GUILD_MEMBERS`].
244///
245/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-member-update).
246#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
247#[derive(Clone, Debug, Deserialize, Serialize)]
248#[non_exhaustive]
249pub struct GuildMemberUpdateEvent {
250    pub guild_id: GuildId,
251    pub nick: Option<String>,
252    pub joined_at: Timestamp,
253    pub roles: Vec<RoleId>,
254    pub user: User,
255    pub premium_since: Option<Timestamp>,
256    #[serde(default)]
257    pub pending: bool,
258    #[serde(default)]
259    pub deaf: bool,
260    #[serde(default)]
261    pub mute: bool,
262    pub avatar: Option<ImageHash>,
263    pub communication_disabled_until: Option<Timestamp>,
264    pub unusual_dm_activity_until: Option<Timestamp>,
265}
266
267/// Requires no gateway intents.
268///
269/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-members-chunk).
270#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
271#[derive(Clone, Debug, Deserialize, Serialize)]
272#[serde(remote = "Self")]
273#[non_exhaustive]
274pub struct GuildMembersChunkEvent {
275    /// ID of the guild.
276    pub guild_id: GuildId,
277    /// Set of guild members.
278    #[serde(with = "members")]
279    pub members: HashMap<UserId, Member>,
280    /// Chunk index in the expected chunks for this response (0 <= chunk_index < chunk_count).
281    pub chunk_index: u32,
282    /// Total number of expected chunks for this response.
283    pub chunk_count: u32,
284    /// When passing an invalid ID to [`crate::gateway::ShardRunnerMessage::ChunkGuild`], it will
285    /// be returned here.
286    #[serde(default)]
287    pub not_found: Vec<GenericId>,
288    /// When passing true to [`crate::gateway::ShardRunnerMessage::ChunkGuild`], presences of the
289    /// returned members will be here.
290    pub presences: Option<Vec<Presence>>,
291    /// Nonce used in the [`crate::gateway::ShardRunnerMessage::ChunkGuild`] request.
292    pub nonce: Option<String>,
293}
294
295// Manual impl needed to insert guild_id fields in Member
296impl<'de> Deserialize<'de> for GuildMembersChunkEvent {
297    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
298        let mut event = Self::deserialize(deserializer)?; // calls #[serde(remote)]-generated inherent method
299        event.members.values_mut().for_each(|m| m.guild_id = event.guild_id);
300        Ok(event)
301    }
302}
303
304impl Serialize for GuildMembersChunkEvent {
305    fn serialize<S: serde::Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
306        Self::serialize(self, serializer) // calls #[serde(remote)]-generated inherent method
307    }
308}
309
310/// Helper to deserialize `GuildRoleCreateEvent` and `GuildRoleUpdateEvent`.
311#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
312#[derive(Deserialize)]
313struct RoleEventHelper {
314    guild_id: GuildId,
315    role: Role,
316}
317
318/// Requires [`GatewayIntents::GUILDS`].
319///
320/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-role-create).
321#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
322#[derive(Clone, Debug, Serialize)]
323#[non_exhaustive]
324pub struct GuildRoleCreateEvent {
325    pub role: Role,
326}
327
328// Manual impl needed to insert guild_id field in Role
329impl<'de> Deserialize<'de> for GuildRoleCreateEvent {
330    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
331        let mut event = RoleEventHelper::deserialize(deserializer)?;
332        event.role.guild_id = event.guild_id;
333        Ok(Self {
334            role: event.role,
335        })
336    }
337}
338
339/// Requires [`GatewayIntents::GUILDS`].
340///
341/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-role-delete).
342#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
343#[derive(Clone, Debug, Deserialize, Serialize)]
344#[non_exhaustive]
345pub struct GuildRoleDeleteEvent {
346    pub guild_id: GuildId,
347    pub role_id: RoleId,
348}
349
350/// Requires [`GatewayIntents::GUILDS`].
351///
352/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-role-update).
353#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
354#[derive(Clone, Debug, Serialize)]
355#[non_exhaustive]
356pub struct GuildRoleUpdateEvent {
357    pub role: Role,
358}
359
360// Manual impl needed to insert guild_id field in Role
361impl<'de> Deserialize<'de> for GuildRoleUpdateEvent {
362    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
363        let mut event = RoleEventHelper::deserialize(deserializer)?;
364        event.role.guild_id = event.guild_id;
365        Ok(Self {
366            role: event.role,
367        })
368    }
369}
370
371/// Requires [`GatewayIntents::GUILD_EMOJIS_AND_STICKERS`].
372///
373/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-stickers-update).
374#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
375#[derive(Clone, Debug, Deserialize, Serialize)]
376#[non_exhaustive]
377pub struct GuildStickersUpdateEvent {
378    #[serde(with = "stickers")]
379    pub stickers: HashMap<StickerId, Sticker>,
380    pub guild_id: GuildId,
381}
382
383/// Requires [`GatewayIntents::GUILD_INVITES`] and [`Permissions::MANAGE_CHANNELS´] permission.
384///
385/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#invite-create).
386#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
387#[derive(Clone, Debug, Deserialize, Serialize)]
388#[non_exhaustive]
389pub struct InviteCreateEvent {
390    /// Whether or not the invite is temporary (invited users will be kicked on disconnect unless
391    /// Channel the invite is for.
392    pub channel_id: ChannelId,
393    /// Unique invite [code](Invite::code).
394    pub code: String,
395    /// Time at which the invite was created.
396    pub created_at: Timestamp,
397    /// Guild of the invite.
398    pub guild_id: Option<GuildId>,
399    /// User that created the invite.
400    pub inviter: Option<User>,
401    /// How long the invite is valid for (in seconds).
402    pub max_age: u32,
403    /// Maximum number of times the invite can be used.
404    pub max_uses: u8,
405    /// Type of target for this voice channel invite.
406    pub target_type: Option<InviteTargetType>,
407    /// User whose stream to display for this voice channel stream invite.
408    pub target_user: Option<User>,
409    /// Embedded application to open for this voice channel embedded application invite.
410    pub target_application: Option<Value>,
411    /// they're assigned a role).
412    pub temporary: bool,
413    /// How many times the invite has been used (always will be 0).
414    pub uses: u64,
415}
416
417/// Requires [`GatewayIntents::GUILD_INVITES`] and [`Permissions::MANAGE_CHANNELS´] permission.
418///
419/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#invite-delete).
420#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
421#[derive(Clone, Debug, Deserialize, Serialize)]
422#[non_exhaustive]
423pub struct InviteDeleteEvent {
424    pub channel_id: ChannelId,
425    pub guild_id: Option<GuildId>,
426    pub code: String,
427}
428
429/// Requires [`GatewayIntents::GUILDS`].
430///
431/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-update).
432#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
433#[derive(Clone, Debug, Deserialize, Serialize)]
434#[serde(transparent)]
435#[non_exhaustive]
436pub struct GuildUpdateEvent {
437    /// GuildUpdateEvent doesn't have GuildCreate's extra fields, so this is a partial guild
438    pub guild: PartialGuild,
439}
440
441/// Requires [`GatewayIntents::GUILD_MESSAGES`] or [`GatewayIntents::DIRECT_MESSAGES`].
442///
443/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-create).
444#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
445#[derive(Clone, Debug, Deserialize, Serialize)]
446#[serde(transparent)]
447#[non_exhaustive]
448pub struct MessageCreateEvent {
449    pub message: Message,
450}
451
452/// Requires [`GatewayIntents::GUILD_MESSAGES`] or [`GatewayIntents::DIRECT_MESSAGES`].
453///
454/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-delete-bulk).
455#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
456#[derive(Clone, Debug, Deserialize, Serialize)]
457#[non_exhaustive]
458pub struct MessageDeleteBulkEvent {
459    pub guild_id: Option<GuildId>,
460    pub channel_id: ChannelId,
461    pub ids: Vec<MessageId>,
462}
463
464/// Requires [`GatewayIntents::GUILD_MESSAGES`] or [`GatewayIntents::DIRECT_MESSAGES`].
465///
466/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-delete).
467#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
468#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
469#[non_exhaustive]
470pub struct MessageDeleteEvent {
471    pub guild_id: Option<GuildId>,
472    pub channel_id: ChannelId,
473    #[serde(rename = "id")]
474    pub message_id: MessageId,
475}
476
477// Any value that is present is considered Some value, including null.
478// Taken from https://github.com/serde-rs/serde/issues/984#issuecomment-314143738
479fn deserialize_some<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
480where
481    T: Deserialize<'de>,
482    D: Deserializer<'de>,
483{
484    Deserialize::deserialize(deserializer).map(Some)
485}
486
487/// Requires [`GatewayIntents::GUILD_MESSAGES`].
488///
489/// Contains identical fields to [`Message`], except everything but `id` and `channel_id` are
490/// optional. Even fields that cannot change in a message update event are included, because Discord
491/// may include them anyways, independent from whether they have actually changed (like
492/// [`Self::guild_id`])
493///
494/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-update).
495#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
496#[derive(Clone, Debug, Deserialize, Serialize)]
497#[non_exhaustive]
498pub struct MessageUpdateEvent {
499    pub id: MessageId,
500    pub channel_id: ChannelId,
501    pub author: Option<User>,
502    pub content: Option<String>,
503    pub timestamp: Option<Timestamp>,
504    pub edited_timestamp: Option<Timestamp>,
505    pub tts: Option<bool>,
506    pub mention_everyone: Option<bool>,
507    pub mentions: Option<Vec<User>>,
508    pub mention_roles: Option<Vec<RoleId>>,
509    pub mention_channels: Option<Vec<ChannelMention>>,
510    pub attachments: Option<Vec<Attachment>>,
511    pub embeds: Option<Vec<Embed>>,
512    pub reactions: Option<Vec<MessageReaction>>,
513    pub pinned: Option<bool>,
514    #[serde(default, deserialize_with = "deserialize_some")]
515    pub webhook_id: Option<Option<WebhookId>>,
516    #[serde(rename = "type")]
517    pub kind: Option<MessageType>,
518    #[serde(default, deserialize_with = "deserialize_some")]
519    pub activity: Option<Option<MessageActivity>>,
520    #[serde(default, deserialize_with = "deserialize_some")]
521    pub application: Option<Option<MessageApplication>>,
522    #[serde(default, deserialize_with = "deserialize_some")]
523    pub application_id: Option<Option<ApplicationId>>,
524    pub message_reference: Option<Option<MessageReference>>,
525    #[serde(default, deserialize_with = "deserialize_some")]
526    pub flags: Option<Option<MessageFlags>>,
527    #[serde(default, deserialize_with = "deserialize_some")]
528    pub referenced_message: Option<Option<Box<Message>>>,
529    #[cfg_attr(not(ignore_serenity_deprecated), deprecated = "Use interaction_metadata")]
530    #[serde(default, deserialize_with = "deserialize_some")]
531    pub interaction: Option<Option<Box<MessageInteraction>>>,
532    pub interaction_metadata: Option<Option<Box<MessageInteractionMetadata>>>,
533    #[serde(default, deserialize_with = "deserialize_some")]
534    pub thread: Option<Option<GuildChannel>>,
535    #[serde(default, deserialize_with = "optional_deserialize_components")]
536    pub components: Option<Vec<ActionRow>>,
537    pub sticker_items: Option<Vec<StickerItem>>,
538    pub position: Option<Option<u64>>,
539    pub role_subscription_data: Option<Option<RoleSubscriptionData>>,
540    pub guild_id: Option<GuildId>,
541    pub member: Option<Option<Box<PartialMember>>>,
542}
543
544impl MessageUpdateEvent {
545    #[allow(clippy::clone_on_copy)] // For consistency between fields
546    #[rustfmt::skip]
547    /// Writes the updated data in this message update event into the given [`Message`].
548    pub fn apply_to_message(&self, message: &mut Message) {
549        // Destructure, so we get an `unused` warning when we forget to process one of the fields
550        // in this method
551        #[allow(deprecated)] // yes rust, exhaustive means exhaustive, even the deprecated ones
552        let Self {
553            id,
554            channel_id,
555            author,
556            content,
557            timestamp,
558            edited_timestamp,
559            tts,
560            mention_everyone,
561            mentions,
562            mention_roles,
563            mention_channels,
564            attachments,
565            embeds,
566            reactions,
567            pinned,
568            webhook_id,
569            kind,
570            activity,
571            application,
572            application_id,
573            message_reference,
574            flags,
575            referenced_message,
576            interaction,
577            interaction_metadata,
578            thread,
579            components,
580            sticker_items,
581            position,
582            role_subscription_data,
583            guild_id,
584            member,
585        } = self;
586
587        // Discord won't send a MessageUpdateEvent with a different MessageId and ChannelId than we
588        // already have. But let's set the fields anyways, in case the user calls this method with
589        // a self-constructed MessageUpdateEvent that does change these fields.
590        message.id = *id;
591        message.channel_id = *channel_id;
592
593        if let Some(x) = author { message.author = x.clone() }
594        if let Some(x) = content { message.content.clone_from(x) }
595        if let Some(x) = timestamp { message.timestamp = x.clone() }
596        message.edited_timestamp = *edited_timestamp;
597        if let Some(x) = tts { message.tts = x.clone() }
598        if let Some(x) = mention_everyone { message.mention_everyone = x.clone() }
599        if let Some(x) = mentions { message.mentions.clone_from(x) }
600        if let Some(x) = mention_roles { message.mention_roles.clone_from(x) }
601        if let Some(x) = mention_channels { message.mention_channels.clone_from(x) }
602        if let Some(x) = attachments { message.attachments.clone_from(x) }
603        if let Some(x) = embeds { message.embeds.clone_from(x) }
604        if let Some(x) = reactions { message.reactions.clone_from(x) }
605        if let Some(x) = pinned { message.pinned = x.clone() }
606        if let Some(x) = webhook_id { message.webhook_id.clone_from(x) }
607        if let Some(x) = kind { message.kind = x.clone() }
608        if let Some(x) = activity { message.activity.clone_from(x) }
609        if let Some(x) = application { message.application.clone_from(x) }
610        if let Some(x) = application_id { message.application_id.clone_from(x) }
611        if let Some(x) = message_reference { message.message_reference.clone_from(x) }
612        if let Some(x) = flags { message.flags.clone_from(x) }
613        if let Some(x) = referenced_message { message.referenced_message.clone_from(x) }
614        if let Some(x) = interaction { message.interaction.clone_from(x) }
615        if let Some(x) = interaction_metadata { message.interaction_metadata.clone_from(x) }
616        if let Some(x) = thread { message.thread.clone_from(x) }
617        if let Some(x) = components { message.components.clone_from(x) }
618        if let Some(x) = sticker_items { message.sticker_items.clone_from(x) }
619        if let Some(x) = position { message.position.clone_from(x) }
620        if let Some(x) = role_subscription_data { message.role_subscription_data.clone_from(x) }
621        message.guild_id = *guild_id;
622        if let Some(x) = member { message.member.clone_from(x) }
623    }
624}
625
626/// Requires [`GatewayIntents::GUILD_PRESENCES`].
627///
628/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#presence-update).
629#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
630#[derive(Clone, Debug, Deserialize, Serialize)]
631#[serde(transparent)]
632#[non_exhaustive]
633pub struct PresenceUpdateEvent {
634    pub presence: Presence,
635}
636
637/// Not officially documented.
638#[cfg_attr(not(ignore_serenity_deprecated), deprecated = "This event doesn't exist")]
639#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
640#[derive(Clone, Debug, Deserialize, Serialize)]
641#[serde(transparent)]
642#[non_exhaustive]
643pub struct PresencesReplaceEvent {
644    pub presences: Vec<Presence>,
645}
646
647/// Requires [`GatewayIntents::GUILD_MESSAGE_REACTIONS`] or
648/// [`GatewayIntents::DIRECT_MESSAGE_REACTIONS`].
649///
650/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-reaction-add).
651#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
652#[derive(Clone, Debug, Deserialize, Serialize)]
653#[serde(transparent)]
654#[non_exhaustive]
655pub struct ReactionAddEvent {
656    pub reaction: Reaction,
657}
658
659/// Requires [`GatewayIntents::GUILD_MESSAGE_REACTIONS`] or
660/// [`GatewayIntents::DIRECT_MESSAGE_REACTIONS`].
661///
662/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-reaction-remove).
663#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
664#[derive(Clone, Debug, Deserialize, Serialize)]
665#[serde(transparent)]
666#[non_exhaustive]
667pub struct ReactionRemoveEvent {
668    // The Discord API doesn't share the same schema for Reaction Remove Event and Reaction Add
669    // Event (which [`Reaction`] is), but the two currently match up well enough, so re-using the
670    // [`Reaction`] struct here is fine.
671    pub reaction: Reaction,
672}
673
674/// Requires [`GatewayIntents::GUILD_MESSAGE_REACTIONS`] or
675/// [`GatewayIntents::DIRECT_MESSAGE_REACTIONS`].
676///
677/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-reaction-remove-all).
678#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
679#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
680#[non_exhaustive]
681pub struct ReactionRemoveAllEvent {
682    pub channel_id: ChannelId,
683    pub message_id: MessageId,
684    pub guild_id: Option<GuildId>,
685}
686
687/// Requires [`GatewayIntents::GUILD_MESSAGE_REACTIONS`] or
688/// [`GatewayIntents::DIRECT_MESSAGE_REACTIONS`].
689///
690/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-reaction-remove-emoji-message-reaction-remove-emoji-event-fields).
691#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
692#[derive(Clone, Debug, Deserialize, Serialize)]
693#[serde(transparent)]
694#[non_exhaustive]
695pub struct ReactionRemoveEmojiEvent {
696    pub reaction: Reaction,
697}
698
699/// The "Ready" event, containing initial ready cache
700///
701/// Requires no gateway intents.
702///
703/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#ready).
704#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
705#[derive(Clone, Debug, Deserialize, Serialize)]
706#[serde(transparent)]
707#[non_exhaustive]
708pub struct ReadyEvent {
709    pub ready: Ready,
710}
711
712/// Requires no gateway intents.
713///
714/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#resumed).
715#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
716#[derive(Clone, Debug, Deserialize, Serialize)]
717#[non_exhaustive]
718pub struct ResumedEvent {}
719
720/// Requires [`GatewayIntents::GUILD_MESSAGE_TYPING`] or [`GatewayIntents::DIRECT_MESSAGE_TYPING`].
721///
722/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#typing-start).
723#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
724#[derive(Clone, Debug, Deserialize, Serialize)]
725#[non_exhaustive]
726pub struct TypingStartEvent {
727    /// ID of the channel.
728    pub channel_id: ChannelId,
729    /// ID of the guild.
730    pub guild_id: Option<GuildId>,
731    /// ID of the user.
732    pub user_id: UserId,
733    /// Timestamp of when the user started typing.
734    pub timestamp: u64,
735    /// Member who started typing if this happened in a guild.
736    pub member: Option<Member>,
737}
738
739#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
740#[derive(Clone, Debug, Deserialize, Serialize)]
741#[non_exhaustive]
742pub struct UnknownEvent {
743    #[serde(rename = "t")]
744    pub kind: String,
745    #[serde(rename = "d")]
746    pub value: Value,
747}
748
749/// Sent when properties about the current bot's user change.
750///
751/// Requires no gateway intents.
752///
753/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#user-update).
754#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
755#[derive(Clone, Debug, Deserialize, Serialize)]
756#[serde(transparent)]
757#[non_exhaustive]
758pub struct UserUpdateEvent {
759    pub current_user: CurrentUser,
760}
761
762/// Requires no gateway intents.
763///
764/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#voice-server-update).
765#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
766#[derive(Clone, Debug, Deserialize, Serialize)]
767#[non_exhaustive]
768pub struct VoiceServerUpdateEvent {
769    pub token: String,
770    pub guild_id: Option<GuildId>,
771    pub endpoint: Option<String>,
772}
773
774/// Requires [`GatewayIntents::GUILD_VOICE_STATES`].
775///
776/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#voice-state-update).
777#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
778#[derive(Clone, Debug, Deserialize, Serialize)]
779#[serde(transparent)]
780#[non_exhaustive]
781pub struct VoiceStateUpdateEvent {
782    pub voice_state: VoiceState,
783}
784
785/// Requires [`GatewayIntents::GUILDS`].
786///
787/// [Incomplete documentation](https://github.com/discord/discord-api-docs/pull/6398)
788#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
789#[derive(Clone, Debug, Deserialize, Serialize)]
790#[non_exhaustive]
791pub struct VoiceChannelStatusUpdateEvent {
792    pub status: Option<String>,
793    pub id: ChannelId,
794    pub guild_id: GuildId,
795}
796
797/// Requires [`GatewayIntents::GUILD_WEBHOOKS`].
798///
799/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#webhooks-update).
800#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
801#[derive(Clone, Debug, Deserialize, Serialize)]
802#[non_exhaustive]
803pub struct WebhookUpdateEvent {
804    pub channel_id: ChannelId,
805    pub guild_id: GuildId,
806}
807
808/// Requires no gateway intents.
809///
810/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#interaction-create).
811#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
812#[derive(Clone, Debug, Deserialize, Serialize)]
813#[serde(transparent)]
814#[non_exhaustive]
815pub struct InteractionCreateEvent {
816    pub interaction: Interaction,
817}
818
819/// Requires [`GatewayIntents::GUILD_INTEGRATIONS`].
820///
821/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#integration-create).
822#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
823#[derive(Clone, Debug, Deserialize, Serialize)]
824#[serde(transparent)]
825#[non_exhaustive]
826pub struct IntegrationCreateEvent {
827    pub integration: Integration,
828}
829
830/// Requires [`GatewayIntents::GUILD_INTEGRATIONS`].
831///
832/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#integration-update).
833#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
834#[derive(Clone, Debug, Deserialize, Serialize)]
835#[serde(transparent)]
836#[non_exhaustive]
837pub struct IntegrationUpdateEvent {
838    pub integration: Integration,
839}
840
841/// Requires [`GatewayIntents::GUILD_INTEGRATIONS`].
842///
843/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#integration-delete).
844#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
845#[derive(Clone, Debug, Serialize, Deserialize)]
846#[non_exhaustive]
847pub struct IntegrationDeleteEvent {
848    pub id: IntegrationId,
849    pub guild_id: GuildId,
850    pub application_id: Option<ApplicationId>,
851}
852
853/// Requires [`GatewayIntents::GUILDS`].
854///
855/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#stage-instance-create).
856#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
857#[derive(Clone, Debug, Deserialize, Serialize)]
858#[serde(transparent)]
859#[non_exhaustive]
860pub struct StageInstanceCreateEvent {
861    pub stage_instance: StageInstance,
862}
863
864/// Requires [`GatewayIntents::GUILDS`].
865///
866/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#stage-instance-update).
867#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
868#[derive(Clone, Debug, Deserialize, Serialize)]
869#[serde(transparent)]
870#[non_exhaustive]
871pub struct StageInstanceUpdateEvent {
872    pub stage_instance: StageInstance,
873}
874
875/// Requires [`GatewayIntents::GUILDS`].
876///
877/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#stage-instance-delete).
878#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
879#[derive(Clone, Debug, Deserialize, Serialize)]
880#[serde(transparent)]
881#[non_exhaustive]
882pub struct StageInstanceDeleteEvent {
883    pub stage_instance: StageInstance,
884}
885
886/// Requires [`GatewayIntents::GUILDS`].
887///
888/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#thread-create).
889#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
890#[derive(Clone, Debug, Deserialize, Serialize)]
891#[serde(transparent)]
892#[non_exhaustive]
893pub struct ThreadCreateEvent {
894    pub thread: GuildChannel,
895}
896
897/// Requires [`GatewayIntents::GUILDS`].
898///
899/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#thread-update).
900#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
901#[derive(Clone, Debug, Deserialize, Serialize)]
902#[serde(transparent)]
903#[non_exhaustive]
904pub struct ThreadUpdateEvent {
905    pub thread: GuildChannel,
906}
907
908/// Requires [`GatewayIntents::GUILDS`].
909///
910/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#thread-delete).
911#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
912#[derive(Clone, Debug, Deserialize, Serialize)]
913#[serde(transparent)]
914#[non_exhaustive]
915pub struct ThreadDeleteEvent {
916    pub thread: PartialGuildChannel,
917}
918
919/// Requires [`GatewayIntents::GUILDS`].
920///
921/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#thread-list-sync).
922#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
923#[derive(Clone, Debug, Deserialize, Serialize)]
924#[non_exhaustive]
925pub struct ThreadListSyncEvent {
926    /// The guild Id.
927    pub guild_id: GuildId,
928    /// The parent channel Id whose threads are being synced. If omitted, then threads were synced
929    /// for the entire guild. This array may contain channel Ids that have no active threads as
930    /// well, so you know to clear that data.
931    pub channel_ids: Option<Vec<ChannelId>>,
932    /// All active threads in the given channels that the current user can access.
933    pub threads: Vec<GuildChannel>,
934    /// All thread member objects from the synced threads for the current user, indicating which
935    /// threads the current user has been added to
936    pub members: Vec<ThreadMember>,
937}
938
939/// Requires [`GatewayIntents::GUILDS`], and, to receive this event for other users,
940/// [`GatewayIntents::GUILD_MEMBERS`].
941///
942/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#thread-member-update).
943#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
944#[derive(Clone, Debug, Deserialize, Serialize)]
945#[serde(transparent)]
946#[non_exhaustive]
947pub struct ThreadMemberUpdateEvent {
948    pub member: ThreadMember,
949}
950
951/// Requires [`GatewayIntents::GUILD_MEMBERS`].
952///
953/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#thread-members-update).
954#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
955#[derive(Clone, Debug, Deserialize, Serialize)]
956#[non_exhaustive]
957pub struct ThreadMembersUpdateEvent {
958    /// The id of the thread.
959    pub id: ChannelId,
960    /// The id of the Guild.
961    pub guild_id: GuildId,
962    /// The approximate number of members in the thread, capped at 50.
963    ///
964    /// NOTE: This count has been observed to be above 50, or below 0.
965    /// See: <https://github.com/discord/discord-api-docs/issues/5139>
966    pub member_count: i16,
967    /// The users who were added to the thread.
968    #[serde(default)]
969    pub added_members: Vec<ThreadMember>,
970    /// The ids of the users who were removed from the thread.
971    #[serde(default)]
972    pub removed_member_ids: Vec<UserId>,
973}
974
975/// Requires [`GatewayIntents::GUILD_SCHEDULED_EVENTS`].
976///
977/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-scheduled-event-create).
978#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
979#[derive(Clone, Debug, Deserialize, Serialize)]
980#[serde(transparent)]
981#[non_exhaustive]
982pub struct GuildScheduledEventCreateEvent {
983    pub event: ScheduledEvent,
984}
985
986/// Requires [`GatewayIntents::GUILD_SCHEDULED_EVENTS`].
987///
988/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-scheduled-event-update).
989#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
990#[derive(Clone, Debug, Deserialize, Serialize)]
991#[serde(transparent)]
992#[non_exhaustive]
993pub struct GuildScheduledEventUpdateEvent {
994    pub event: ScheduledEvent,
995}
996
997/// Requires [`GatewayIntents::GUILD_SCHEDULED_EVENTS`].
998///
999/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-scheduled-event-delete).
1000#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1001#[derive(Clone, Debug, Deserialize, Serialize)]
1002#[serde(transparent)]
1003#[non_exhaustive]
1004pub struct GuildScheduledEventDeleteEvent {
1005    pub event: ScheduledEvent,
1006}
1007
1008/// Requires [`GatewayIntents::GUILD_SCHEDULED_EVENTS`].
1009///
1010/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-scheduled-event-user-add).
1011#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1012#[derive(Clone, Debug, Deserialize, Serialize)]
1013#[non_exhaustive]
1014pub struct GuildScheduledEventUserAddEvent {
1015    #[serde(rename = "guild_scheduled_event_id")]
1016    pub scheduled_event_id: ScheduledEventId,
1017    pub user_id: UserId,
1018    pub guild_id: GuildId,
1019}
1020
1021/// Requires [`GatewayIntents::GUILD_SCHEDULED_EVENTS`].
1022///
1023/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#guild-scheduled-event-user-remove).
1024#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1025#[derive(Clone, Debug, Deserialize, Serialize)]
1026#[non_exhaustive]
1027pub struct GuildScheduledEventUserRemoveEvent {
1028    #[serde(rename = "guild_scheduled_event_id")]
1029    pub scheduled_event_id: ScheduledEventId,
1030    pub user_id: UserId,
1031    pub guild_id: GuildId,
1032}
1033
1034/// Requires no gateway intents.
1035///
1036/// [Discord docs](https://discord.com/developers/docs/monetization/entitlements#new-entitlement)
1037#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1038#[derive(Clone, Debug, Deserialize, Serialize)]
1039#[serde(transparent)]
1040#[non_exhaustive]
1041pub struct EntitlementCreateEvent {
1042    pub entitlement: Entitlement,
1043}
1044
1045/// Requires no gateway intents.
1046///
1047/// [Discord docs](https://discord.com/developers/docs/monetization/entitlements#new-entitlement)
1048#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1049#[derive(Clone, Debug, Deserialize, Serialize)]
1050#[serde(transparent)]
1051#[non_exhaustive]
1052pub struct EntitlementUpdateEvent {
1053    pub entitlement: Entitlement,
1054}
1055
1056/// Requires no gateway intents.
1057///
1058/// [Discord docs](https://discord.com/developers/docs/monetization/entitlements#new-entitlement)
1059#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1060#[derive(Clone, Debug, Deserialize, Serialize)]
1061#[serde(transparent)]
1062#[non_exhaustive]
1063pub struct EntitlementDeleteEvent {
1064    pub entitlement: Entitlement,
1065}
1066
1067/// Requires [`GatewayIntents::GUILD_MESSAGE_POLLS`] or [`GatewayIntents::DIRECT_MESSAGE_POLLS`].
1068///
1069/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-poll-vote-add)
1070#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1071#[derive(Clone, Debug, Deserialize, Serialize)]
1072#[non_exhaustive]
1073pub struct MessagePollVoteAddEvent {
1074    pub user_id: UserId,
1075    pub channel_id: ChannelId,
1076    pub message_id: MessageId,
1077    pub guild_id: Option<GuildId>,
1078    pub answer_id: AnswerId,
1079}
1080
1081/// Requires [`GatewayIntents::GUILD_MESSAGE_POLLS`] or [`GatewayIntents::DIRECT_MESSAGE_POLLS`].
1082///
1083/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#message-poll-vote-remove)
1084#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1085#[derive(Clone, Debug, Deserialize, Serialize)]
1086#[non_exhaustive]
1087pub struct MessagePollVoteRemoveEvent {
1088    pub user_id: UserId,
1089    pub channel_id: ChannelId,
1090    pub message_id: MessageId,
1091    pub guild_id: Option<GuildId>,
1092    pub answer_id: AnswerId,
1093}
1094
1095/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#payload-structure).
1096#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1097#[allow(clippy::large_enum_variant)]
1098#[derive(Debug, Clone, Serialize)]
1099#[non_exhaustive]
1100#[serde(untagged)]
1101pub enum GatewayEvent {
1102    Dispatch(u64, Event),
1103    Heartbeat(#[deprecated = "always 0 because it is never provided by the gateway"] u64),
1104    Reconnect,
1105    /// Whether the session can be resumed.
1106    InvalidateSession(bool),
1107    Hello(u64),
1108    HeartbeatAck,
1109}
1110
1111// Manual impl needed to emulate integer enum tags
1112impl<'de> Deserialize<'de> for GatewayEvent {
1113    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
1114        let mut map = JsonMap::deserialize(deserializer)?;
1115        let seq = remove_from_map_opt(&mut map, "s")?.flatten();
1116
1117        Ok(match remove_from_map(&mut map, "op")? {
1118            Opcode::Dispatch => Self::Dispatch(
1119                seq.ok_or_else(|| DeError::missing_field("s"))?,
1120                deserialize_val(Value::from(map))?,
1121            ),
1122            Opcode::Heartbeat => {
1123                // Placeholder value. Discord expects the last Dispatch
1124                // sequence number and doesn't send it with the heartbeat.
1125                GatewayEvent::Heartbeat(0)
1126            },
1127            Opcode::InvalidSession => {
1128                GatewayEvent::InvalidateSession(remove_from_map(&mut map, "d")?)
1129            },
1130            Opcode::Hello => {
1131                #[derive(Deserialize)]
1132                struct HelloPayload {
1133                    heartbeat_interval: u64,
1134                }
1135
1136                let inner: HelloPayload = remove_from_map(&mut map, "d")?;
1137                GatewayEvent::Hello(inner.heartbeat_interval)
1138            },
1139            Opcode::Reconnect => GatewayEvent::Reconnect,
1140            Opcode::HeartbeatAck => GatewayEvent::HeartbeatAck,
1141            _ => return Err(DeError::custom("invalid opcode")),
1142        })
1143    }
1144}
1145
1146/// Event received over a websocket connection
1147///
1148/// [Discord docs](https://discord.com/developers/docs/topics/gateway-events#receive-events).
1149#[allow(clippy::large_enum_variant)]
1150#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
1151#[derive(Clone, Debug, Deserialize, Serialize)]
1152#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1153#[serde(tag = "t", content = "d")]
1154#[non_exhaustive]
1155pub enum Event {
1156    /// The permissions of an [`Command`] was changed.
1157    ///
1158    /// Fires the [`EventHandler::command_permissions_update`] event.
1159    ///
1160    /// [`Command`]: crate::model::application::Command
1161    /// [`EventHandler::command_permissions_update`]: crate::client::EventHandler::command_permissions_update
1162    #[serde(rename = "APPLICATION_COMMAND_PERMISSIONS_UPDATE")]
1163    CommandPermissionsUpdate(CommandPermissionsUpdateEvent),
1164    /// A [`Rule`] was created.
1165    ///
1166    /// Fires the [`EventHandler::auto_moderation_rule_create`] event.
1167    ///
1168    /// [`EventHandler::auto_moderation_rule_create`]:
1169    /// crate::client::EventHandler::auto_moderation_rule_create
1170    #[serde(rename = "AUTO_MODERATION_RULE_CREATE")]
1171    AutoModRuleCreate(AutoModRuleCreateEvent),
1172    /// A [`Rule`] has been updated.
1173    ///
1174    /// Fires the [`EventHandler::auto_moderation_rule_update`] event.
1175    ///
1176    /// [`EventHandler::auto_moderation_rule_update`]:
1177    /// crate::client::EventHandler::auto_moderation_rule_update
1178    #[serde(rename = "AUTO_MODERATION_RULE_UPDATE")]
1179    AutoModRuleUpdate(AutoModRuleUpdateEvent),
1180    /// A [`Rule`] was deleted.
1181    ///
1182    /// Fires the [`EventHandler::auto_moderation_rule_delete`] event.
1183    ///
1184    /// [`EventHandler::auto_moderation_rule_delete`]:
1185    /// crate::client::EventHandler::auto_moderation_rule_delete
1186    #[serde(rename = "AUTO_MODERATION_RULE_DELETE")]
1187    AutoModRuleDelete(AutoModRuleDeleteEvent),
1188    /// A [`Rule`] was triggered and an action was executed.
1189    ///
1190    /// Fires the [`EventHandler::auto_moderation_action_execution`] event.
1191    ///
1192    /// [`EventHandler::auto_moderation_action_execution`]:
1193    /// crate::client::EventHandler::auto_moderation_action_execution
1194    #[serde(rename = "AUTO_MODERATION_ACTION_EXECUTION")]
1195    AutoModActionExecution(AutoModActionExecutionEvent),
1196    /// A [`Channel`] was created.
1197    ///
1198    /// Fires the [`EventHandler::channel_create`] event.
1199    ///
1200    /// [`EventHandler::channel_create`]: crate::client::EventHandler::channel_create
1201    ChannelCreate(ChannelCreateEvent),
1202    /// A [`Channel`] has been deleted.
1203    ///
1204    /// Fires the [`EventHandler::channel_delete`] event.
1205    ///
1206    /// [`EventHandler::channel_delete`]: crate::client::EventHandler::channel_delete
1207    ChannelDelete(ChannelDeleteEvent),
1208    /// The pins for a [`Channel`] have been updated.
1209    ///
1210    /// Fires the [`EventHandler::channel_pins_update`] event.
1211    ///
1212    /// [`EventHandler::channel_pins_update`]: crate::client::EventHandler::channel_pins_update
1213    ChannelPinsUpdate(ChannelPinsUpdateEvent),
1214    /// A [`Channel`] has been updated.
1215    ///
1216    /// Fires the [`EventHandler::channel_update`] event.
1217    ///
1218    /// [`EventHandler::channel_update`]: crate::client::EventHandler::channel_update
1219    ChannelUpdate(ChannelUpdateEvent),
1220    GuildAuditLogEntryCreate(GuildAuditLogEntryCreateEvent),
1221    GuildBanAdd(GuildBanAddEvent),
1222    GuildBanRemove(GuildBanRemoveEvent),
1223    GuildCreate(GuildCreateEvent),
1224    GuildDelete(GuildDeleteEvent),
1225    GuildEmojisUpdate(GuildEmojisUpdateEvent),
1226    GuildIntegrationsUpdate(GuildIntegrationsUpdateEvent),
1227    GuildMemberAdd(GuildMemberAddEvent),
1228    GuildMemberRemove(GuildMemberRemoveEvent),
1229    /// A member's roles have changed
1230    GuildMemberUpdate(GuildMemberUpdateEvent),
1231    GuildMembersChunk(GuildMembersChunkEvent),
1232    GuildRoleCreate(GuildRoleCreateEvent),
1233    GuildRoleDelete(GuildRoleDeleteEvent),
1234    GuildRoleUpdate(GuildRoleUpdateEvent),
1235    /// A [`Sticker`] was created, updated, or deleted
1236    GuildStickersUpdate(GuildStickersUpdateEvent),
1237    GuildUpdate(GuildUpdateEvent),
1238    /// An [`Invite`] was created.
1239    ///
1240    /// Fires the [`EventHandler::invite_create`] event handler.
1241    ///
1242    /// [`EventHandler::invite_create`]: crate::client::EventHandler::invite_create
1243    InviteCreate(InviteCreateEvent),
1244    /// An [`Invite`] was deleted.
1245    ///
1246    /// Fires the [`EventHandler::invite_delete`] event handler.
1247    ///
1248    /// [`EventHandler::invite_delete`]: crate::client::EventHandler::invite_delete
1249    InviteDelete(InviteDeleteEvent),
1250    MessageCreate(MessageCreateEvent),
1251    MessageDelete(MessageDeleteEvent),
1252    MessageDeleteBulk(MessageDeleteBulkEvent),
1253    /// A message has been edited, either by the user or the system
1254    MessageUpdate(MessageUpdateEvent),
1255    /// A member's presence state (or username or avatar) has changed
1256    PresenceUpdate(PresenceUpdateEvent),
1257    /// The presence list of the user's friends should be replaced entirely
1258    #[cfg_attr(not(ignore_serenity_deprecated), deprecated = "This event doesn't exist")]
1259    PresencesReplace(PresencesReplaceEvent),
1260    /// A reaction was added to a message.
1261    ///
1262    /// Fires the [`EventHandler::reaction_add`] event handler.
1263    ///
1264    /// [`EventHandler::reaction_add`]: crate::client::EventHandler::reaction_add
1265    #[serde(rename = "MESSAGE_REACTION_ADD")]
1266    ReactionAdd(ReactionAddEvent),
1267    /// A reaction was removed to a message.
1268    ///
1269    /// Fires the [`EventHandler::reaction_remove`] event handler.
1270    ///
1271    /// [`EventHandler::reaction_remove`]: crate::client::EventHandler::reaction_remove
1272    #[serde(rename = "MESSAGE_REACTION_REMOVE")]
1273    ReactionRemove(ReactionRemoveEvent),
1274    /// A request was issued to remove all [`Reaction`]s from a [`Message`].
1275    ///
1276    /// Fires the [`EventHandler::reaction_remove_all`] event handler.
1277    ///
1278    /// [`EventHandler::reaction_remove_all`]: crate::client::EventHandler::reaction_remove_all
1279    #[serde(rename = "MESSAGE_REACTION_REMOVE_ALL")]
1280    ReactionRemoveAll(ReactionRemoveAllEvent),
1281    /// Sent when a bot removes all instances of a given emoji from the reactions of a message.
1282    ///
1283    /// Fires the [`EventHandler::reaction_remove_emoji`] event handler.
1284    ///
1285    /// [`EventHandler::reaction_remove_emoji`]: crate::client::EventHandler::reaction_remove_emoji
1286    #[serde(rename = "MESSAGE_REACTION_REMOVE_EMOJI")]
1287    ReactionRemoveEmoji(ReactionRemoveEmojiEvent),
1288    /// The first event in a connection, containing the initial ready cache.
1289    ///
1290    /// May also be received at a later time in the event of a reconnect.
1291    Ready(ReadyEvent),
1292    /// The connection has successfully resumed after a disconnect.
1293    Resumed(ResumedEvent),
1294    /// A user is typing; considered to last 5 seconds
1295    TypingStart(TypingStartEvent),
1296    /// Update to the logged-in user's information
1297    UserUpdate(UserUpdateEvent),
1298    /// A member's voice state has changed
1299    VoiceStateUpdate(VoiceStateUpdateEvent),
1300    /// Voice server information is available
1301    VoiceServerUpdate(VoiceServerUpdateEvent),
1302    /// Fired when the status of a Voice Channel changes.
1303    VoiceChannelStatusUpdate(VoiceChannelStatusUpdateEvent),
1304    /// A webhook for a [channel][`GuildChannel`] was updated in a [`Guild`].
1305    #[serde(rename = "WEBHOOKS_UPDATE")]
1306    WebhookUpdate(WebhookUpdateEvent),
1307    /// An interaction was created.
1308    InteractionCreate(InteractionCreateEvent),
1309    /// A guild integration was created
1310    IntegrationCreate(IntegrationCreateEvent),
1311    /// A guild integration was updated
1312    IntegrationUpdate(IntegrationUpdateEvent),
1313    /// A guild integration was deleted
1314    IntegrationDelete(IntegrationDeleteEvent),
1315    /// A stage instance was created.
1316    StageInstanceCreate(StageInstanceCreateEvent),
1317    /// A stage instance was updated.
1318    StageInstanceUpdate(StageInstanceUpdateEvent),
1319    /// A stage instance was deleted.
1320    StageInstanceDelete(StageInstanceDeleteEvent),
1321    /// A thread was created or the current user was added
1322    /// to a private thread.
1323    ThreadCreate(ThreadCreateEvent),
1324    /// A thread was updated.
1325    ThreadUpdate(ThreadUpdateEvent),
1326    /// A thread was deleted.
1327    ThreadDelete(ThreadDeleteEvent),
1328    /// The current user gains access to a channel.
1329    ThreadListSync(ThreadListSyncEvent),
1330    /// The [`ThreadMember`] object for the current user is updated.
1331    ThreadMemberUpdate(ThreadMemberUpdateEvent),
1332    /// Anyone is added to or removed from a thread.
1333    ThreadMembersUpdate(ThreadMembersUpdateEvent),
1334    /// A scheduled event was created.
1335    GuildScheduledEventCreate(GuildScheduledEventCreateEvent),
1336    /// A scheduled event was updated.
1337    GuildScheduledEventUpdate(GuildScheduledEventUpdateEvent),
1338    /// A scheduled event was deleted.
1339    GuildScheduledEventDelete(GuildScheduledEventDeleteEvent),
1340    /// A guild member has subscribed to a scheduled event.
1341    GuildScheduledEventUserAdd(GuildScheduledEventUserAddEvent),
1342    /// A guild member has unsubscribed from a scheduled event.
1343    GuildScheduledEventUserRemove(GuildScheduledEventUserRemoveEvent),
1344    /// A user subscribed to a SKU.
1345    EntitlementCreate(EntitlementCreateEvent),
1346    /// A user's entitlement was updated or renewed.
1347    EntitlementUpdate(EntitlementUpdateEvent),
1348    /// A user's entitlement was deleted by Discord, or refunded.
1349    EntitlementDelete(EntitlementDeleteEvent),
1350    /// A user has voted on a Message Poll.
1351    MessagePollVoteAdd(MessagePollVoteAddEvent),
1352    /// A user has removed a previous vote on a Message Poll.
1353    MessagePollVoteRemove(MessagePollVoteRemoveEvent),
1354    /// An event type not covered by the above
1355    #[serde(untagged)]
1356    Unknown(UnknownEvent),
1357}
1358
1359impl Event {
1360    /// Return the event name of this event. Returns [`None`] if the event is
1361    /// [`Unknown`](Event::Unknown).
1362    #[must_use]
1363    pub fn name(&self) -> Option<String> {
1364        if let Self::Unknown(_) = self {
1365            None
1366        } else {
1367            let map = serde_json::to_value(self).ok()?;
1368            Some(map.get("t")?.as_str()?.to_string())
1369        }
1370    }
1371}