serenity/client/
event_handler.rs

1use async_trait::async_trait;
2
3use super::context::Context;
4use crate::gateway::ShardStageUpdateEvent;
5use crate::http::RatelimitInfo;
6use crate::model::prelude::*;
7
8macro_rules! event_handler {
9    ( $(
10        $( #[doc = $doc:literal] )*
11        $( #[deprecated = $deprecated:literal] )?
12        $( #[cfg(feature = $feature:literal)] )?
13        $variant_name:ident { $( $arg_name:ident: $arg_type:ty ),* } => async fn $method_name:ident(&self $(, $context:ident: Context)?);
14    )* ) => {
15        /// The core trait for handling events by serenity.
16        #[async_trait]
17        pub trait EventHandler: Send + Sync {
18            $(
19                $( #[doc = $doc] )*
20                $( #[cfg(feature = $feature)] )?
21                $( #[deprecated = $deprecated] )?
22                async fn $method_name(&self, $($context: Context,)? $( $arg_name: $arg_type ),*) {
23                    // Suppress unused argument warnings
24                    drop(( $($context,)? $($arg_name),* ))
25                }
26            )*
27        }
28
29        /// This enum stores every possible event that an [`EventHandler`] can receive.
30        #[non_exhaustive]
31        #[allow(clippy::large_enum_variant)] // TODO: do some boxing to fix this
32        #[derive(Clone, Debug)]
33        pub enum FullEvent {
34            $(
35                $( #[doc = $doc] )*
36                $( #[cfg(feature = $feature)] )?
37                $( #[deprecated = $deprecated] )?
38                $variant_name {
39                    $( $arg_name: $arg_type ),*
40                },
41            )*
42        }
43
44        impl FullEvent {
45            /// Returns the name of this event as a snake case string
46            ///
47            /// ```rust,no_run
48            /// # use serenity::client::{Context, FullEvent};
49            /// # fn foo_(ctx: Context, event: FullEvent) {
50            /// if let FullEvent::Message { .. } = &event {
51            ///     assert_eq!(event.snake_case_name(), "message");
52            /// }
53            /// # }
54            /// ```
55            #[must_use]
56            pub fn snake_case_name(&self) -> &'static str {
57                #[allow(deprecated)]
58                match self {
59                    $(
60                        $( #[cfg(feature = $feature)] )?
61                        Self::$variant_name { .. } => stringify!($method_name),
62                    )*
63                }
64            }
65
66            /// Runs the given [`EventHandler`]'s code for this event.
67            pub async fn dispatch(self, ctx: Context, handler: &dyn EventHandler) {
68                #[allow(deprecated)]
69                match self {
70                    $(
71                        $( #[cfg(feature = $feature)] )?
72                        Self::$variant_name { $( $arg_name ),* } => {
73                            $( let $context = ctx; )?
74                            handler.$method_name( $($context,)? $( $arg_name ),* ).await;
75                        }
76                    )*
77                }
78            }
79        }
80    };
81}
82
83event_handler! {
84    /// Dispatched when the permissions of an application command was updated.
85    ///
86    /// Provides said permission's data.
87    CommandPermissionsUpdate { permission: CommandPermissions } => async fn command_permissions_update(&self, ctx: Context);
88
89    /// Dispatched when an auto moderation rule was created.
90    ///
91    /// Provides said rule's data.
92    AutoModRuleCreate { rule: Rule } => async fn auto_moderation_rule_create(&self, ctx: Context);
93
94    /// Dispatched when an auto moderation rule was updated.
95    ///
96    /// Provides said rule's data.
97    AutoModRuleUpdate { rule: Rule } => async fn auto_moderation_rule_update(&self, ctx: Context);
98
99    /// Dispatched when an auto moderation rule was deleted.
100    ///
101    /// Provides said rule's data.
102    AutoModRuleDelete { rule: Rule } => async fn auto_moderation_rule_delete(&self, ctx: Context);
103
104    /// Dispatched when an auto moderation rule was triggered and an action was executed.
105    ///
106    /// Provides said action execution's data.
107    AutoModActionExecution { execution: ActionExecution } => async fn auto_moderation_action_execution(&self, ctx: Context);
108
109    /// Dispatched when the cache has received and inserted all data from guilds.
110    ///
111    /// This process happens upon starting your bot and should be fairly quick. However, cache
112    /// actions performed prior this event may fail as the data could be not inserted yet.
113    ///
114    /// Provides the cached guilds' ids.
115    #[cfg(feature = "cache")]
116    CacheReady { guilds: Vec<GuildId> } => async fn cache_ready(&self, ctx: Context);
117
118    /// Dispatched when every shard has received a Ready event
119    #[cfg(feature = "cache")]
120    ShardsReady { total_shards: u32 } => async fn shards_ready(&self, ctx: Context);
121
122    /// Dispatched when a channel is created.
123    ///
124    /// Provides said channel's data.
125    ChannelCreate { channel: GuildChannel } => async fn channel_create(&self, ctx: Context);
126
127    /// Dispatched when a category is created.
128    ///
129    /// Provides said category's data.
130    CategoryCreate { category: GuildChannel } => async fn category_create(&self, ctx: Context);
131
132    /// Dispatched when a category is deleted.
133    ///
134    /// Provides said category's data.
135    CategoryDelete { category: GuildChannel } => async fn category_delete(&self, ctx: Context);
136
137    /// Dispatched when a channel is deleted.
138    ///
139    /// Provides said channel's data.
140    ChannelDelete { channel: GuildChannel, messages: Option<Vec<Message>> } => async fn channel_delete(&self, ctx: Context);
141
142    /// Dispatched when a pin is added, deleted.
143    ///
144    /// Provides said pin's data.
145    ChannelPinsUpdate { pin: ChannelPinsUpdateEvent } => async fn channel_pins_update(&self, ctx: Context);
146
147    /// Dispatched when a channel is updated.
148    ///
149    /// The old channel data is only provided when the cache feature is enabled.
150    ChannelUpdate { old: Option<GuildChannel>, new: GuildChannel } => async fn channel_update(&self, ctx: Context);
151
152    /// Dispatched when a new audit log entry is created.
153    ///
154    /// Provides said entry's data and the id of the guild where it was created.
155    GuildAuditLogEntryCreate { entry: AuditLogEntry, guild_id: GuildId } => async fn guild_audit_log_entry_create(&self, ctx: Context);
156
157    /// Dispatched when a user is banned from a guild.
158    ///
159    /// Provides the guild's id and the banned user's data.
160    GuildBanAddition { guild_id: GuildId, banned_user: User } => async fn guild_ban_addition(&self, ctx: Context);
161
162    /// Dispatched when a user's ban is lifted from a guild.
163    ///
164    /// Provides the guild's id and the lifted user's data.
165    GuildBanRemoval { guild_id: GuildId, unbanned_user: User } => async fn guild_ban_removal(&self, ctx: Context);
166
167    /// Dispatched when a guild is created; or an existing guild's data is sent to us.
168    ///
169    /// Provides the guild's data and whether the guild is new (only when cache feature is enabled).
170    GuildCreate { guild: Guild, is_new: Option<bool> } => async fn guild_create(&self, ctx: Context);
171
172    /// Dispatched when a guild is deleted.
173    ///
174    /// Provides the partial data of the guild sent by discord, and the full data from the cache,
175    /// if cache feature is enabled and the data is available.
176    ///
177    /// The [`unavailable`] flag in the partial data determines the status of the guild. If the
178    /// flag is false, the bot was removed from the guild, either by being kicked or banned. If the
179    /// flag is true, the guild went offline.
180    ///
181    /// [`unavailable`]: UnavailableGuild::unavailable
182    GuildDelete { incomplete: UnavailableGuild, full: Option<Guild> } => async fn guild_delete(&self, ctx: Context);
183
184    // the emojis were updated.
185
186    /// Dispatched when the emojis are updated.
187    ///
188    /// Provides the guild's id and the new state of the emojis in the guild.
189    GuildEmojisUpdate { guild_id: GuildId, current_state: HashMap<EmojiId, Emoji> } => async fn guild_emojis_update(&self, ctx: Context);
190
191    /// Dispatched when a guild's integration is added, updated or removed.
192    ///
193    /// Provides the guild's id.
194    GuildIntegrationsUpdate { guild_id: GuildId } => async fn guild_integrations_update(&self, ctx: Context);
195
196    /// Dispatched when a user joins a guild.
197    ///
198    /// Provides the guild's id and the user's member data.
199    ///
200    /// Note: This event will not trigger unless the "guild members" privileged intent is enabled
201    /// on the bot application page.
202    GuildMemberAddition { new_member: Member } => async fn guild_member_addition(&self, ctx: Context);
203
204    /// Dispatched when a user's membership ends by leaving, getting kicked, or being banned.
205    ///
206    /// Provides the guild's id, the user's data, and the user's member data if cache feature is
207    /// enabled and the data is available.
208    ///
209    /// Note: This event will not trigger unless the "guild members" privileged intent is enabled
210    /// on the bot application page.
211    GuildMemberRemoval { guild_id: GuildId, user: User, member_data_if_available: Option<Member> } => async fn guild_member_removal(&self, ctx: Context);
212
213    /// Dispatched when a member is updated (e.g their nickname is updated).
214    ///
215    /// Provides the member's old and new data (if cache feature is enabled and data is available)
216    /// and the new raw data about updated fields.
217    ///
218    /// Note: This event will not trigger unless the "guild members" privileged intent is enabled
219    /// on the bot application page.
220    GuildMemberUpdate { old_if_available: Option<Member>, new: Option<Member>, event: GuildMemberUpdateEvent } => async fn guild_member_update(&self, ctx: Context);
221
222    /// Dispatched when the data for offline members was requested.
223    ///
224    /// Provides the guild's id and the data.
225    GuildMembersChunk { chunk: GuildMembersChunkEvent } => async fn guild_members_chunk(&self, ctx: Context);
226
227    /// Dispatched when a role is created.
228    ///
229    /// Provides the guild's id and the new role's data.
230    GuildRoleCreate { new: Role } => async fn guild_role_create(&self, ctx: Context);
231
232    /// Dispatched when a role is deleted.
233    ///
234    /// Provides the guild's id, the role's id and its data (if cache feature is enabled and the
235    /// data is available).
236    GuildRoleDelete { guild_id: GuildId, removed_role_id: RoleId, removed_role_data_if_available: Option<Role> } => async fn guild_role_delete(&self, ctx: Context);
237
238    /// Dispatched when a role is updated.
239    ///
240    /// Provides the guild's id, the role's old (if cache feature is enabled and the data is
241    /// available) and new data.
242    GuildRoleUpdate { old_data_if_available: Option<Role>, new: Role } => async fn guild_role_update(&self, ctx: Context);
243
244    /// Dispatched when the stickers are updated.
245    ///
246    /// Provides the guild's id and the new state of the stickers in the guild.
247    GuildStickersUpdate { guild_id: GuildId, current_state: HashMap<StickerId, Sticker> } => async fn guild_stickers_update(&self, ctx: Context);
248
249    /// Dispatched when the guild is updated.
250    ///
251    /// Provides the guild's old data (if cache feature is enabled and the data is available)
252    /// and the new data.
253    GuildUpdate { old_data_if_available: Option<Guild>, new_data: PartialGuild } => async fn guild_update(&self, ctx: Context);
254
255    /// Dispatched when a invite is created.
256    ///
257    /// Provides data about the invite.
258    InviteCreate { data: InviteCreateEvent } => async fn invite_create(&self, ctx: Context);
259
260    /// Dispatched when a invite is deleted.
261    ///
262    /// Provides data about the invite.
263    InviteDelete { data: InviteDeleteEvent } => async fn invite_delete(&self, ctx: Context);
264
265    /// Dispatched when a message is created.
266    ///
267    /// Provides the message's data.
268    Message { new_message: Message } => async fn message(&self, ctx: Context);
269
270    /// Dispatched when a message is deleted.
271    ///
272    /// Provides the guild's id, the channel's id and the message's id.
273    MessageDelete { channel_id: ChannelId, deleted_message_id: MessageId, guild_id: Option<GuildId> } => async fn message_delete(&self, ctx: Context);
274
275    /// Dispatched when multiple messages were deleted at once.
276    ///
277    /// Provides the guild's id, channel's id and the deleted messages' ids.
278    MessageDeleteBulk { channel_id: ChannelId, multiple_deleted_messages_ids: Vec<MessageId>, guild_id: Option<GuildId> } => async fn message_delete_bulk(&self, ctx: Context);
279
280    /// Dispatched when a message is updated.
281    ///
282    /// Provides the message update data, as well as the actual old and new message if cache
283    /// feature is enabled and the data is available.
284    MessageUpdate { old_if_available: Option<Message>, new: Option<Message>, event: MessageUpdateEvent } => async fn message_update(&self, ctx: Context);
285
286    /// Dispatched when a new reaction is attached to a message.
287    ///
288    /// Provides the reaction's data.
289    ReactionAdd { add_reaction: Reaction } => async fn reaction_add(&self, ctx: Context);
290
291    /// Dispatched when a reaction is detached from a message.
292    ///
293    /// Provides the reaction's data.
294    ReactionRemove { removed_reaction: Reaction } => async fn reaction_remove(&self, ctx: Context);
295
296    /// Dispatched when all reactions of a message are detached from a message.
297    ///
298    /// Provides the channel's id and the message's id.
299    ReactionRemoveAll { channel_id: ChannelId, removed_from_message_id: MessageId } => async fn reaction_remove_all(&self, ctx: Context);
300
301    /// Dispatched when all reactions of a message are detached from a message.
302    ///
303    /// Provides the channel's id and the message's id.
304    ReactionRemoveEmoji { removed_reactions: Reaction } => async fn reaction_remove_emoji(&self, ctx: Context);
305
306    #[deprecated = "This event does not exist"]
307    PresenceReplace { presences: Vec<Presence> } => async fn presence_replace(&self, ctx: Context);
308
309    /// Dispatched when a user's presence is updated (e.g off -> on).
310    ///
311    /// Provides the presence's new data.
312    ///
313    /// Note: This event will not trigger unless the "guild presences" privileged intent is enabled
314    /// on the bot application page.
315    PresenceUpdate { new_data: Presence } => async fn presence_update(&self, ctx: Context);
316
317    /// Dispatched upon startup.
318    ///
319    /// Provides data about the bot and the guilds it's in.
320    Ready { data_about_bot: Ready } => async fn ready(&self, ctx: Context);
321
322    /// Dispatched upon reconnection.
323    Resume { event: ResumedEvent } => async fn resume(&self, ctx: Context);
324
325    /// Dispatched when a shard's connection stage is updated
326    ///
327    /// Provides the context of the shard and the event information about the update.
328    ShardStageUpdate { event: ShardStageUpdateEvent } => async fn shard_stage_update(&self, ctx: Context);
329
330    /// Dispatched when a user starts typing.
331    TypingStart { event: TypingStartEvent } => async fn typing_start(&self, ctx: Context);
332
333    /// Dispatched when the bot's data is updated.
334    ///
335    /// Provides the old (if cache feature is enabled and the data is available) and new data.
336    UserUpdate { old_data: Option<CurrentUser>, new: CurrentUser } => async fn user_update(&self, ctx: Context);
337
338    /// Dispatched when a guild's voice server was updated (or changed to another one).
339    ///
340    /// Provides the voice server's data.
341    VoiceServerUpdate { event: VoiceServerUpdateEvent } => async fn voice_server_update(&self, ctx: Context);
342
343    /// Dispatched when a user joins, leaves or moves to a voice channel.
344    ///
345    /// Provides the guild's id (if available) and the old state (if cache feature is enabled and
346    /// [`GatewayIntents::GUILDS`] is enabled) and the new state of the guild's voice channels.
347    VoiceStateUpdate { old: Option<VoiceState>, new: VoiceState } => async fn voice_state_update(&self, ctx: Context);
348
349    /// Dispatched when a voice channel's status is updated.
350    ///
351    /// Provides the status, channel's id and the guild's id.
352    VoiceChannelStatusUpdate { old: Option<String>, status: Option<String>, id: ChannelId, guild_id: GuildId } => async fn voice_channel_status_update(&self, ctx: Context);
353
354    /// Dispatched when a guild's webhook is updated.
355    ///
356    /// Provides the guild's id and the channel's id the webhook belongs in.
357    WebhookUpdate { guild_id: GuildId, belongs_to_channel_id: ChannelId } => async fn webhook_update(&self, ctx: Context);
358
359    /// Dispatched when an interaction is created (e.g a slash command was used or a button was clicked).
360    ///
361    /// Provides the created interaction.
362    InteractionCreate { interaction: Interaction } => async fn interaction_create(&self, ctx: Context);
363
364    /// Dispatched when a guild integration is created.
365    ///
366    /// Provides the created integration.
367    IntegrationCreate { integration: Integration } => async fn integration_create(&self, ctx: Context);
368
369    /// Dispatched when a guild integration is updated.
370    ///
371    /// Provides the updated integration.
372    IntegrationUpdate { integration: Integration } => async fn integration_update(&self, ctx: Context);
373
374    /// Dispatched when a guild integration is deleted.
375    ///
376    /// Provides the integration's id, the id of the guild it belongs to, and its associated application id
377    IntegrationDelete { integration_id: IntegrationId, guild_id: GuildId, application_id: Option<ApplicationId> } => async fn integration_delete(&self, ctx: Context);
378
379    /// Dispatched when a stage instance is created.
380    ///
381    /// Provides the created stage instance.
382    StageInstanceCreate { stage_instance: StageInstance } => async fn stage_instance_create(&self, ctx: Context);
383
384    /// Dispatched when a stage instance is updated.
385    ///
386    /// Provides the updated stage instance.
387    StageInstanceUpdate { stage_instance: StageInstance } => async fn stage_instance_update(&self, ctx: Context);
388
389    /// Dispatched when a stage instance is deleted.
390    ///
391    /// Provides the deleted stage instance.
392    StageInstanceDelete { stage_instance: StageInstance } => async fn stage_instance_delete(&self, ctx: Context);
393
394    /// Dispatched when a thread is created or the current user is added to a private thread.
395    ///
396    /// Provides the thread.
397    ThreadCreate { thread: GuildChannel } => async fn thread_create(&self, ctx: Context);
398
399    /// Dispatched when a thread is updated.
400    ///
401    /// Provides the updated thread and the old thread data, provided the thread was cached prior to dispatch.
402    ThreadUpdate { old: Option<GuildChannel>, new: GuildChannel } => async fn thread_update(&self, ctx: Context);
403
404    /// Dispatched when a thread is deleted.
405    ///
406    /// Provides the partial data about the deleted thread and, if it was present in the cache
407    /// before its deletion, its full data.
408    ThreadDelete { thread: PartialGuildChannel, full_thread_data: Option<GuildChannel> } => async fn thread_delete(&self, ctx: Context);
409
410    /// Dispatched when the current user gains access to a channel.
411    ///
412    /// Provides the threads the current user can access, the thread members, the guild Id, and the
413    /// channel Ids of the parent channels being synced.
414    ThreadListSync { thread_list_sync: ThreadListSyncEvent } => async fn thread_list_sync(&self, ctx: Context);
415
416    /// Dispatched when the [`ThreadMember`] for the current user is updated.
417    ///
418    /// Provides the updated thread member.
419    ThreadMemberUpdate { thread_member: ThreadMember } => async fn thread_member_update(&self, ctx: Context);
420
421    /// Dispatched when anyone is added to or removed from a thread. If the current user does not
422    /// have the [`GatewayIntents::GUILDS`], then this event will only be sent if the current user
423    /// was added to or removed from the thread.
424    ///
425    /// Provides the added/removed members, the approximate member count of members in the thread,
426    /// the thread Id and its guild Id.
427    ///
428    /// [`GatewayIntents::GUILDS`]: crate::model::gateway::GatewayIntents::GUILDS
429    ThreadMembersUpdate { thread_members_update: ThreadMembersUpdateEvent } => async fn thread_members_update(&self, ctx: Context);
430
431    /// Dispatched when a scheduled event is created.
432    ///
433    /// Provides data about the scheduled event.
434    GuildScheduledEventCreate { event: ScheduledEvent } => async fn guild_scheduled_event_create(&self, ctx: Context);
435
436    /// Dispatched when a scheduled event is updated.
437    ///
438    /// Provides data about the scheduled event.
439    GuildScheduledEventUpdate { event: ScheduledEvent } => async fn guild_scheduled_event_update(&self, ctx: Context);
440
441    /// Dispatched when a scheduled event is deleted.
442    ///
443    /// Provides data about the scheduled event.
444    GuildScheduledEventDelete { event: ScheduledEvent } => async fn guild_scheduled_event_delete(&self, ctx: Context);
445
446    /// Dispatched when a guild member has subscribed to a scheduled event.
447    ///
448    /// Provides data about the subscription.
449    GuildScheduledEventUserAdd { subscribed: GuildScheduledEventUserAddEvent } => async fn guild_scheduled_event_user_add(&self, ctx: Context);
450
451    /// Dispatched when a guild member has unsubscribed from a scheduled event.
452    ///
453    /// Provides data about the cancelled subscription.
454    GuildScheduledEventUserRemove { unsubscribed: GuildScheduledEventUserRemoveEvent } => async fn guild_scheduled_event_user_remove(&self, ctx: Context);
455
456    /// Dispatched when a user subscribes to a SKU.
457    ///
458    /// Provides data about the subscription.
459    EntitlementCreate { entitlement: Entitlement } => async fn entitlement_create(&self, ctx: Context);
460
461    /// Dispatched when a user's entitlement has been updated, such as when a subscription is
462    /// renewed for the next billing period.
463    ///
464    /// Provides data abut the updated subscription. If the entitlement is renewed, the
465    /// [`Entitlement::ends_at`] field will have changed.
466    EntitlementUpdate { entitlement: Entitlement } => async fn entitlement_update(&self, ctx: Context);
467
468    /// Dispatched when a user's entitlement has been deleted. This happens rarely, but can occur
469    /// if a subscription is refunded or otherwise deleted by Discord. Entitlements are not deleted
470    /// when they expire.
471    ///
472    /// Provides data about the subscription. Specifically, the [`Entitlement::deleted`] field will
473    /// be set.
474    EntitlementDelete { entitlement: Entitlement } => async fn entitlement_delete(&self, ctx: Context);
475
476    /// Dispatched when a user votes on a message poll.
477    ///
478    /// This will be dispatched multiple times if multiple answers are selected.
479    MessagePollVoteAdd { event: MessagePollVoteAddEvent } => async fn poll_vote_add(&self, ctx: Context);
480
481    /// Dispatched when a user removes a previous vote on a poll.
482    MessagePollVoteRemove { event: MessagePollVoteRemoveEvent } => async fn poll_vote_remove(&self, ctx: Context);
483
484    /// Dispatched when an HTTP rate limit is hit
485    Ratelimit { data: RatelimitInfo } => async fn ratelimit(&self);
486}
487
488/// This core trait for handling raw events
489#[async_trait]
490pub trait RawEventHandler: Send + Sync {
491    /// Dispatched when any event occurs
492    async fn raw_event(&self, _ctx: Context, _ev: Event) {}
493}