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