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}