diff options
| author | acdenisSK <[email protected]> | 2017-06-28 19:38:51 +0200 |
|---|---|---|
| committer | acdenisSK <[email protected]> | 2017-06-28 19:38:51 +0200 |
| commit | ea432af97a87b8a3d673a1f40fe06cde4d84e146 (patch) | |
| tree | 1afbc7d396f83e1eea0550b848764a14832c277a /src/client | |
| parent | Add reaction actions (#115) (diff) | |
| download | serenity-ea432af97a87b8a3d673a1f40fe06cde4d84e146.tar.xz serenity-ea432af97a87b8a3d673a1f40fe06cde4d84e146.zip | |
Merge branch "trait-based-event-handling"
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/dispatch.rs | 520 | ||||
| -rw-r--r-- | src/client/event_handler.rs | 77 | ||||
| -rw-r--r-- | src/client/mod.rs | 662 |
3 files changed, 322 insertions, 937 deletions
diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs index 4021838..fc3daaf 100644 --- a/src/client/dispatch.rs +++ b/src/client/dispatch.rs @@ -1,7 +1,7 @@ -use std::sync::{Arc, Mutex, RwLock}; +use std::sync::{Arc, Mutex}; use std::thread; use std::time; -use super::event_store::EventStore; +use super::event_handler::EventHandler; use super::Context; use typemap::ShareMap; use ::gateway::Shard; @@ -15,16 +15,6 @@ use ::ext::framework::{Framework, ReactionAction}; #[cfg(feature="cache")] use super::CACHE; -macro_rules! handler { - ($field:ident, $event_store:ident) => { - $event_store.read() - .unwrap() - .$field - .as_ref() - .cloned() - } -} - macro_rules! update { ($method:ident, @$event:expr) => { { @@ -70,11 +60,11 @@ fn context(conn: &Arc<Mutex<Shard>>, } #[cfg(feature="framework")] -pub fn dispatch(event: Event, +pub fn dispatch<H: EventHandler + Send + Sync + 'static>(event: Event, conn: &Arc<Mutex<Shard>>, framework: &Arc<Mutex<Framework>>, data: &Arc<Mutex<ShareMap>>, - event_store: &Arc<RwLock<EventStore>>) { + event_handler: &Arc<H>) { match event { Event::MessageCreate(event) => { let context = context(conn, data); @@ -83,11 +73,11 @@ pub fn dispatch(event: Event, if framework.initialized { dispatch_message(context.clone(), event.message.clone(), - event_store); + event_handler); framework.dispatch(context, event.message); } else { - dispatch_message(context, event.message, event_store); + dispatch_message(context, event.message, event_handler); } }, Event::ReactionAdd(event) => { @@ -97,11 +87,11 @@ pub fn dispatch(event: Event, if framework.initialized { dispatch_reaction_add(context.clone(), event.reaction.clone(), - event_store); + event_handler); let res = framework.reaction_actions .iter() - .find(|&(ra, ..)| { + .find(|&(ra, _)| { if let ReactionAction::Add(ref kind) = *ra { *kind == event.reaction.emoji } else { @@ -113,7 +103,7 @@ pub fn dispatch(event: Event, f(context, event.reaction.message_id, event.reaction.channel_id); } } else { - dispatch_reaction_add(context, event.reaction, event_store); + dispatch_reaction_add(context, event.reaction, event_handler); } }, Event::ReactionRemove(event) => { @@ -123,7 +113,7 @@ pub fn dispatch(event: Event, if framework.initialized { dispatch_reaction_remove(context.clone(), event.reaction.clone(), - event_store); + event_handler); let res = framework.reaction_actions .iter() @@ -139,24 +129,24 @@ pub fn dispatch(event: Event, f(context, event.reaction.message_id, event.reaction.channel_id); } } else { - dispatch_reaction_remove(context, event.reaction, event_store); + dispatch_reaction_remove(context, event.reaction, event_handler); } }, - other => handle_event(other, conn, data, event_store), + other => handle_event(other, conn, data, event_handler), } } #[cfg(not(feature="framework"))] -pub fn dispatch(event: Event, +pub fn dispatch<H: EventHandler + Send + Sync + 'static>(event: Event, conn: &Arc<Mutex<Shard>>, data: &Arc<Mutex<ShareMap>>, - event_store: &Arc<RwLock<EventStore>>) { + event_handler: &Arc<H>) { match event { Event::MessageCreate(event) => { let context = context(conn, data); dispatch_message(context, event.message, - event_store); + event_handler); }, Event::ReactionAdd(event) => { let context = context(conn, data); @@ -166,53 +156,52 @@ pub fn dispatch(event: Event, let context = context(conn, data); dispatch_reaction_remove(context, event.reaction); }, - other => handle_event(other, conn, data, event_store), + other => handle_event(other, conn, data, event_handler), } } #[allow(unused_mut)] -fn dispatch_message(context: Context, +fn dispatch_message<H: EventHandler + Send + Sync + 'static>(context: Context, mut message: Message, - event_store: &Arc<RwLock<EventStore>>) { - if let Some(handler) = handler!(on_message, event_store) { - thread::spawn(move || { - #[cfg(feature="model")] - { - message.transform_content(); - } + event_handler: &Arc<H>) { + let h = event_handler.clone(); + thread::spawn(move || { + #[cfg(feature="model")] + { + message.transform_content(); + } - (handler)(context, message); - }); - } + h.on_message(context, message); + }); } -fn dispatch_reaction_add(context: Context, +fn dispatch_reaction_add<H: EventHandler + Send + Sync + 'static>(context: Context, reaction: Reaction, - event_store: &Arc<RwLock<EventStore>>) { - if let Some(handler) = handler!(on_reaction_add, event_store) { - thread::spawn(move || { - (handler)(context, reaction); - }); - } + event_handler: &Arc<H>) { + let h = event_handler.clone(); + thread::spawn(move || { + h.on_reaction_add(context, reaction); + }); } -fn dispatch_reaction_remove(context: Context, +fn dispatch_reaction_remove<H: EventHandler + Send + Sync + 'static>(context: Context, reaction: Reaction, - event_store: &Arc<RwLock<EventStore>>) { - if let Some(handler) = handler!(on_reaction_remove, event_store) { - thread::spawn(move || { - (handler)(context, reaction); - }); - } + event_handler: &Arc<H>) { + let h = event_handler.clone(); + thread::spawn(move || { + h.on_reaction_remove(context, reaction); + }); } #[allow(cyclomatic_complexity, unused_assignments, unused_mut)] -fn handle_event(event: Event, +fn handle_event<H: EventHandler + Send + Sync + 'static>(event: Event, conn: &Arc<Mutex<Shard>>, data: &Arc<Mutex<ShareMap>>, - event_store: &Arc<RwLock<EventStore>>) { - let mut last_guild_create_time = now!(); + event_handler: &Arc<H>) { + #[cfg(feature="cache")] + let mut last_guild_create_time = now!(); + #[cfg(feature="cache")] let wait_for_guilds = move || -> ::Result<()> { let unavailable_guilds = CACHE.read().unwrap().unavailable_guilds.len(); @@ -225,406 +214,337 @@ fn handle_event(event: Event, match event { Event::ChannelCreate(event) => { - if let Some(handler) = handler!(on_channel_create, event_store) { - update!(update_with_channel_create, event); + update!(update_with_channel_create, event); - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.channel)); - } else { - update!(update_with_channel_create, event); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_channel_create(context, event.channel)); }, Event::ChannelDelete(event) => { - if let Some(handler) = handler!(on_channel_delete, event_store) { - update!(update_with_channel_delete, event); - let context = context(conn, data); + update!(update_with_channel_delete, event); - thread::spawn(move || (handler)(context, event.channel)); - } else { - update!(update_with_channel_delete, event); - } + let context = context(conn, data); + + let h = event_handler.clone(); + thread::spawn(move || h.on_channel_delete(context, event.channel)); }, Event::ChannelPinsUpdate(event) => { - if let Some(handler) = handler!(on_channel_pins_update, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_channel_pins_update(context, event)); }, Event::ChannelRecipientAdd(mut event) => { update!(update_with_channel_recipient_add, @event); - if let Some(handler) = handler!(on_channel_recipient_addition, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.channel_id, event.user)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_channel_recipient_addition(context, event.channel_id, event.user)); }, Event::ChannelRecipientRemove(event) => { update!(update_with_channel_recipient_remove, event); - if let Some(handler) = handler!(on_channel_recipient_removal, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.channel_id, event.user)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_channel_recipient_removal(context, event.channel_id, event.user)); }, Event::ChannelUpdate(event) => { - if let Some(handler) = handler!(on_channel_update, event_store) { - let context = context(conn, data); + update!(update_with_channel_update, event); - feature_cache! {{ - let before = CACHE.read().unwrap().channel(event.channel.id()); - update!(update_with_channel_update, event); + let context = context(conn, data); - thread::spawn(move || (handler)(context, before, event.channel)); - } else { - thread::spawn(move || (handler)(context, event.channel)); - }} + let h = event_handler.clone(); + feature_cache! {{ + let before = CACHE.read().unwrap().channel(event.channel.id()); + thread::spawn(move || h.on_channel_update(context, before, event.channel)); } else { - update!(update_with_channel_update, event); - } + thread::spawn(move || h.on_channel_update(context, event.channel)); + }} }, Event::GuildBanAdd(event) => { - if let Some(handler) = handler!(on_guild_ban_addition, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.user)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_ban_addition(context, event.guild_id, event.user)); }, Event::GuildBanRemove(event) => { - if let Some(handler) = handler!(on_guild_ban_removal, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.user)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_ban_removal(context, event.guild_id, event.user)); }, Event::GuildCreate(event) => { update!(update_with_guild_create, event); - last_guild_create_time = now!(); - #[cfg(feature="cache")] { + last_guild_create_time = now!(); + let cache = CACHE.read().unwrap(); if cache.unavailable_guilds.len() == 0 { - if let Some(handler) = handler!(on_cached, event_store) { - let context = context(conn, data); + let h = event_handler.clone(); + + let context = context(conn, data); - let guild_amount = cache.guilds.iter() + let guild_amount = cache.guilds.iter() .map(|(&id, _)| id) .collect::<Vec<GuildId>>(); - - thread::spawn(move || (handler)(context, guild_amount)); - } + + thread::spawn(move || h.on_cached(context, guild_amount)); } } - if let Some(handler) = handler!(on_guild_create, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_create(context, event.guild)); }, Event::GuildDelete(event) => { - if let Some(handler) = handler!(on_guild_delete, event_store) { - let context = context(conn, data); - - feature_cache! {{ - let full = update!(update_with_guild_delete, event); + let _full = update!(update_with_guild_delete, event); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild, full)); - } else { - thread::spawn(move || (handler)(context, event.guild)); - }} + let h = event_handler.clone(); + feature_cache! {{ + thread::spawn(move || h.on_guild_delete(context, event.guild, _full)); } else { - #[cfg(feature="cache")] - { - let _ = update!(update_with_guild_delete, event); - } - } + thread::spawn(move || h.on_guild_delete(context, event.guild)); + }} }, Event::GuildEmojisUpdate(event) => { update!(update_with_guild_emojis_update, event); - if let Some(handler) = handler!(on_guild_emojis_update, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.emojis)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_emojis_update(context, event.guild_id, event.emojis)); }, Event::GuildIntegrationsUpdate(event) => { - if let Some(handler) = handler!(on_guild_integrations_update, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_integrations_update(context, event.guild_id)); }, Event::GuildMemberAdd(mut event) => { update!(update_with_guild_member_add, @event); - if let Some(handler) = handler!(on_guild_member_addition, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.member)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_member_addition(context, event.guild_id, event.member)); }, Event::GuildMemberRemove(event) => { - if let Some(handler) = handler!(on_guild_member_removal, event_store) { - let context = context(conn, data); - - feature_cache! {{ - let member = update!(update_with_guild_member_remove, event); + let _member = update!(update_with_guild_member_remove, event); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.user, member)); - } else { - thread::spawn(move || (handler)(context, event.guild_id, event.user)); - }} + let h = event_handler.clone(); + feature_cache! {{ + thread::spawn(move || h.on_guild_member_removal(context, event.guild_id, event.user, _member)); } else { - #[cfg(feature="cache")] - { - let _ = update!(update_with_guild_member_remove, event); - } - } + thread::spawn(move || h.on_guild_member_removal(context, event.guild_id, event.user)); + }} }, Event::GuildMemberUpdate(event) => { - if let Some(handler) = handler!(on_guild_member_update, event_store) { - let context = context(conn, data); - - feature_cache! {{ - let before = update!(update_with_guild_member_update, event); - - // This is safe to unwrap, as the update would have created - // the member if it did not exist. So, there is be _no_ way - // that this could fail under any circumstance. - let after = CACHE.read() - .unwrap() - .member(event.guild_id, event.user.id) - .unwrap() - .clone(); - - thread::spawn(move || (handler)(context, before, after)); - } else { - thread::spawn(move || (handler)(context, event)); - }} + let _before = update!(update_with_guild_member_update, event); + let context = context(conn, data); + + let h = event_handler.clone(); + feature_cache! {{ + // This is safe to unwrap, as the update would have created + // the member if it did not exist. So, there is be _no_ way + // that this could fail under any circumstance. + let after = CACHE.read() + .unwrap() + .member(event.guild_id, event.user.id) + .unwrap() + .clone(); + + thread::spawn(move || h.on_guild_member_update(context, _before, after)); } else { - update!(update_with_guild_member_update, event); - } + thread::spawn(move || h.on_guild_member_update(context, event)); + }} }, Event::GuildMembersChunk(event) => { update!(update_with_guild_members_chunk, event); - if let Some(handler) = handler!(on_guild_members_chunk, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.members)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_members_chunk(context, event.guild_id, event.members)); }, Event::GuildRoleCreate(event) => { update!(update_with_guild_role_create, event); - if let Some(handler) = handler!(on_guild_role_create, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.role)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_role_create(context, event.guild_id, event.role)); }, Event::GuildRoleDelete(event) => { - if let Some(handler) = handler!(on_guild_role_delete, event_store) { - let context = context(conn, data); - - feature_cache! {{ - let role = update!(update_with_guild_role_delete, event); + let _role = update!(update_with_guild_role_delete, event); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.role_id, role)); - } else { - thread::spawn(move || (handler)(context, event.guild_id, event.role_id)); - }} + let h = event_handler.clone(); + feature_cache! {{ + thread::spawn(move || h.on_guild_role_delete(context, event.guild_id, event.role_id, _role)); } else { - #[cfg(feature="cache")] - { - let _ = update!(update_with_guild_role_delete, event); - } - } + thread::spawn(move || h.on_guild_role_delete(context, event.guild_id, event.role_id)); + }} }, Event::GuildRoleUpdate(event) => { - if let Some(handler) = handler!(on_guild_role_update, event_store) { - let context = context(conn, data); - - feature_cache! {{ - let before = update!(update_with_guild_role_update, event); + let _before = update!(update_with_guild_role_update, event); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, before, event.role)); - } else { - thread::spawn(move || (handler)(context, event.guild_id, event.role)); - }} + let h = event_handler.clone(); + feature_cache! {{ + thread::spawn(move || h.on_guild_role_update(context, event.guild_id, _before, event.role)); } else { - #[cfg(feature="cache")] - { - let _ = update!(update_with_guild_role_update, event); - } - } + thread::spawn(move || h.on_guild_role_update(context, event.guild_id, event.role)); + }} }, Event::GuildUnavailable(event) => { update!(update_with_guild_unavailable, event); - if let Some(handler) = handler!(on_guild_unavailable, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_guild_unavailable(context, event.guild_id)); }, Event::GuildUpdate(event) => { - if let Some(handler) = handler!(on_guild_update, event_store) { - let context = context(conn, data); - - feature_cache! {{ - let before = CACHE.read() - .unwrap() - .guilds - .get(&event.guild.id) - .cloned(); - update!(update_with_guild_update, event); - - thread::spawn(move || (handler)(context, before, event.guild)); - } else { - thread::spawn(move || (handler)(context, event.guild)); - }} + update!(update_with_guild_update, event); + + let context = context(conn, data); + + let h = event_handler.clone(); + feature_cache! {{ + let before = CACHE.read() + .unwrap() + .guilds + .get(&event.guild.id) + .cloned(); + + thread::spawn(move || h.on_guild_update(context, before, event.guild)); } else { - update!(update_with_guild_update, event); - } + thread::spawn(move || h.on_guild_update(context, event.guild)); + }} }, // Already handled by the framework check macro Event::MessageCreate(_) => {}, Event::MessageDeleteBulk(event) => { - if let Some(handler) = handler!(on_message_delete_bulk, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.channel_id, event.ids)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_message_delete_bulk(context, event.channel_id, event.ids)); }, Event::MessageDelete(event) => { - if let Some(handler) = handler!(on_message_delete, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.channel_id, event.message_id)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_message_delete(context, event.channel_id, event.message_id)); }, Event::MessageUpdate(event) => { - if let Some(handler) = handler!(on_message_update, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_message_update(context, event)); }, Event::PresencesReplace(event) => { update!(update_with_presences_replace, event); - if let Some(handler) = handler!(on_presence_replace, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.presences)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_presence_replace(context, event.presences)); }, Event::PresenceUpdate(mut event) => { update!(update_with_presence_update, @event); - if let Some(handler) = handler!(on_presence_update, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_presence_update(context, event)); }, // Already handled by the framework check macro Event::ReactionAdd(_) => {}, Event::ReactionRemove(_) => {}, - Event::ReactionRemoveAll(event) => { - if let Some(handler) = handler!(on_reaction_remove_all, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.channel_id, event.message_id)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_reaction_remove_all(context, event.channel_id, event.message_id)); }, Event::Ready(event) => { update!(update_with_ready, event); - last_guild_create_time = now!(); - - let _ = wait_for_guilds() - .map(|_| { - if let Some(handler) = handler!(on_ready, event_store) { + feature_cache!{{ + last_guild_create_time = now!(); + let _ = wait_for_guilds() + .map(|_| { let context = context(conn, data); - thread::spawn(move || (handler)(context, event.ready)); - } - }); + let h = event_handler.clone(); + thread::spawn(move || h.on_ready(context, event.ready)); + }); + } else { + let context = context(conn, data); + + let h = event_handler.clone(); + thread::spawn(move || h.on_ready(context, event.ready)); + }} }, Event::Resumed(event) => { - if let Some(handler) = handler!(on_resume, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_resume(context, event)); }, Event::TypingStart(event) => { - if let Some(handler) = handler!(on_typing_start, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_typing_start(context, event)); }, Event::Unknown(event) => { - if let Some(handler) = handler!(on_unknown, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.kind, event.value)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_unknown(context, event.kind, event.value)); }, Event::UserUpdate(event) => { - if let Some(handler) = handler!(on_user_update, event_store) { - let context = context(conn, data); - - feature_cache! {{ - let before = update!(update_with_user_update, event); + let _before = update!(update_with_user_update, event); + let context = context(conn, data); - thread::spawn(move || (handler)(context, before, event.current_user)); - } else { - thread::spawn(move || (handler)(context, event.current_user)); - }} + let h = event_handler.clone(); + feature_cache! {{ + thread::spawn(move || h.on_user_update(context, _before, event.current_user)); } else { - #[cfg(feature="cache")] - { - let _ = update!(update_with_user_update, event); - } - } + thread::spawn(move || h.on_user_update(context, event.current_user)); + }} }, Event::VoiceServerUpdate(event) => { - if let Some(handler) = handler!(on_voice_server_update, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_voice_server_update(context, event)); }, Event::VoiceStateUpdate(event) => { update!(update_with_voice_state_update, event); - if let Some(handler) = handler!(on_voice_state_update, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.voice_state)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_voice_state_update(context, event.guild_id, event.voice_state)); }, Event::WebhookUpdate(event) => { - if let Some(handler) = handler!(on_webhook_update, event_store) { - let context = context(conn, data); + let context = context(conn, data); - thread::spawn(move || (handler)(context, event.guild_id, event.channel_id)); - } + let h = event_handler.clone(); + thread::spawn(move || h.on_webhook_update(context, event.guild_id, event.channel_id)); }, } } diff --git a/src/client/event_handler.rs b/src/client/event_handler.rs new file mode 100644 index 0000000..b233b8a --- /dev/null +++ b/src/client/event_handler.rs @@ -0,0 +1,77 @@ +use serde_json::Value; +use std::collections::HashMap; +use std::sync::Arc; +use super::context::Context; +use ::model::event::*; +use ::model::*; + +#[cfg(feature="cache")] +use std::sync::RwLock; + +#[allow(type_complexity)] +pub trait EventHandler { + #[cfg(feature="cache")] + fn on_cached(&self, Context, Vec<GuildId>) {} + fn on_channel_create(&self, Context, Channel) {} + fn on_channel_delete(&self, Context, Channel) {} + fn on_channel_pins_update(&self, Context, ChannelPinsUpdateEvent) {} + fn on_channel_recipient_addition(&self, Context, ChannelId, User) {} + fn on_channel_recipient_removal(&self, Context, ChannelId, User) {} + #[cfg(feature="cache")] + fn on_channel_update(&self, Context, Option<Channel>, Channel) {} + #[cfg(not(feature="cache"))] + fn on_channel_update(&self, Context, Channel) {} + fn on_guild_ban_addition(&self, Context, GuildId, User) {} + fn on_guild_ban_removal(&self, Context, GuildId, User) {} + fn on_guild_create(&self, Context, Guild) {} + #[cfg(feature="cache")] + fn on_guild_delete(&self, Context, PartialGuild, Option<Arc<RwLock<Guild>>>) {} + #[cfg(not(feature="cache"))] + fn on_guild_delete(&self, Context, PartialGuild) {} + fn on_guild_emojis_update(&self, Context, GuildId, HashMap<EmojiId, Emoji>) {} + fn on_guild_integrations_update(&self, Context, GuildId) {} + fn on_guild_member_addition(&self, Context, GuildId, Member) {} + #[cfg(feature="cache")] + fn on_guild_member_removal(&self, Context, GuildId, User, Option<Member>) {} + #[cfg(not(feature="cache"))] + fn on_guild_member_removal(&self, Context, GuildId, User) {} + #[cfg(feature="cache")] + fn on_guild_member_update(&self, Context, Option<Member>, Member) {} + #[cfg(not(feature="cache"))] + fn on_guild_member_update(&self, Context, GuildMemberUpdateEvent) {} + fn on_guild_members_chunk(&self, Context, GuildId, HashMap<UserId, Member>) {} + fn on_guild_role_create(&self, Context, GuildId, Role) {} + #[cfg(feature="cache")] + fn on_guild_role_delete(&self, Context, GuildId, RoleId, Option<Role>) {} + #[cfg(not(feature="cache"))] + fn on_guild_role_delete(&self, Context, GuildId, RoleId) {} + #[cfg(feature="cache")] + fn on_guild_role_update(&self, Context, GuildId, Option<Role>, Role) {} + #[cfg(not(feature="cache"))] + fn on_guild_role_update(&self, Context, GuildId, Role) {} + fn on_guild_unavailable(&self, Context, GuildId) {} + #[cfg(feature="cache")] + fn on_guild_update(&self, Context, Option<Arc<RwLock<Guild>>>, PartialGuild) {} + #[cfg(not(feature="cache"))] + fn on_guild_update(&self, Context, PartialGuild) {} + fn on_message(&self, Context, Message) {} + fn on_message_delete(&self, Context, ChannelId, MessageId) {} + fn on_message_delete_bulk(&self, Context, ChannelId, Vec<MessageId>) {} + fn on_reaction_add(&self, Context, Reaction) {} + fn on_reaction_remove(&self, Context, Reaction) {} + fn on_reaction_remove_all(&self, Context, ChannelId, MessageId) {} + fn on_message_update(&self, Context, MessageUpdateEvent) {} + fn on_presence_replace(&self, Context, Vec<Presence>) {} + fn on_presence_update(&self, Context, PresenceUpdateEvent) {} + fn on_ready(&self, Context, Ready) {} + fn on_resume(&self, Context, ResumedEvent) {} + fn on_typing_start(&self, Context, TypingStartEvent) {} + fn on_unknown(&self, Context, String, Value) {} + #[cfg(feature="cache")] + fn on_user_update(&self, Context, CurrentUser, CurrentUser) {} + #[cfg(not(feature="cache"))] + fn on_user_update(&self, Context, CurrentUser) {} + fn on_voice_server_update(&self, Context, VoiceServerUpdateEvent) {} + fn on_voice_state_update(&self, Context, Option<GuildId>, VoiceState) {} + fn on_webhook_update(&self, Context, GuildId, ChannelId) {} +} diff --git a/src/client/mod.rs b/src/client/mod.rs index 87ebfff..9895fe9 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -22,10 +22,11 @@ mod context; mod dispatch; mod error; -mod event_store; +mod event_handler; pub use self::context::Context; pub use self::error::Error as ClientError; +pub use self::event_handler::EventHandler; // Note: the following re-exports are here for backwards compatibility pub use ::gateway; @@ -35,9 +36,7 @@ pub use ::http as rest; pub use ::CACHE; use self::dispatch::dispatch; -use self::event_store::EventStore; -use std::collections::HashMap; -use std::sync::{Arc, Mutex, RwLock}; +use std::sync::{Arc, Mutex}; use std::time::Duration; use std::{mem, thread}; use super::gateway::Shard; @@ -47,7 +46,6 @@ use ::http; use ::internal::prelude::*; use ::internal::ws_impl::ReceiverExt; use ::model::event::*; -use ::model::*; #[cfg(feature="framework")] use ::framework::Framework; @@ -89,7 +87,7 @@ use ::framework::Framework; /// [`on_message`]: #method.on_message /// [`Event::MessageCreate`]: ../model/event/enum.Event.html#variant.MessageCreate /// [sharding docs]: gateway/index.html#sharding -pub struct Client { +pub struct Client<H: EventHandler + Send + Sync + 'static> { /// A ShareMap which requires types to be Send + Sync. This is a map that /// can be safely shared across contexts. /// @@ -165,14 +163,13 @@ pub struct Client { /// /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready /// [`on_ready`]: #method.on_ready - event_store: Arc<RwLock<EventStore>>, + event_handler: Arc<H>, #[cfg(feature="framework")] framework: Arc<Mutex<Framework>>, token: Arc<Mutex<String>>, } -#[allow(type_complexity)] -impl Client { +impl<H: EventHandler + Send + Sync + 'static> Client<H> { /// Creates a Client for a bot user. /// /// Discord has a requirement of prefixing bot tokens with `"Bot "`, which @@ -198,14 +195,14 @@ impl Client { /// # try_main().unwrap(); /// # } /// ``` - pub fn new(token: &str) -> Self { + pub fn new(token: &str, handler: H) -> Self { let token = if token.starts_with("Bot ") { token.to_owned() } else { format!("Bot {}", token) }; - init_client(token) + init_client(token, handler) } /// Alias of [`new`]. @@ -213,8 +210,8 @@ impl Client { /// [`new`]: #method.new #[deprecated(since="0.1.5", note="Use `new` instead")] #[inline(always)] - pub fn login_bot(token: &str) -> Self { - Self::new(token) + pub fn login_bot(token: &str, handler: H) -> Self { + Self::new(token, handler) } /// Alias for [`new`]. @@ -222,8 +219,8 @@ impl Client { /// [`new`]: #method.new #[deprecated(since="0.2.1", note="Use `new` instead")] #[inline(always)] - pub fn login(token: &str) -> Self { - Self::new(token) + pub fn login(token: &str, handler: H) -> Self { + Self::new(token, handler) } /// Sets a framework to be used with the client. All message events will be @@ -545,422 +542,6 @@ impl Client { self.start_connection([range[0], range[1], total_shards], http::get_gateway()?.url) } - /// Attaches a handler for when a [`ChannelCreate`] is received. - /// - /// # Examples - /// - /// If the channel is a guild channel, send `"first"` to the channel when - /// one is created: - /// - /// ```rust,no_run - /// # use serenity::Client; - /// # - /// # let mut client = Client::new(""); - /// use serenity::model::Channel; - /// - /// client.on_channel_create(|ctx, channel| { - /// if let Channel::Guild(ch) = channel { - /// if let Err(why) = ch.read().unwrap().say("first") { - /// println!("Err sending first message: {:?}", why); - /// } - /// } - /// }); - /// ``` - /// - /// [`ChannelCreate`]: ../model/event/enum.Event.html#variant.ChannelCreate - pub fn on_channel_create<F>(&mut self, handler: F) - where F: Fn(Context, Channel) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_channel_create = Some(Arc::new(handler)); - } - - /// Attaches a handle for when all the [`GuildCreate`]s are received; - /// providing all the guilds' id. - /// - /// notes: This requires the cache feature. And that this'll fire when - /// all the guilds from all the shards have been cached. - /// - /// # Examples - /// - /// ```rust,no_run - /// # use serenity::client::Client; - /// # - /// # let mut client = Client::new(""); - /// - /// client.on_cached(|_, guilds| { - /// println!("All the guilds have been cached; and those are: {:?}", guilds); - /// }); - /// ``` - /// - /// [`GuildCreate`]: ../model/event/enum.Event.html#variant.GuildCreate - #[cfg(feature="cache")] - pub fn on_cached<F>(&mut self, handle: F) - where F: Fn(Context, Vec<GuildId>) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_cached = Some(Arc::new(handle)); - } - /// Attaches a handler for when a [`ChannelDelete`] is received. - /// - /// # Examples - /// - /// If the channel is a guild channel, send the name of the channel to the - /// guild's default channel. - /// - /// ```rust,no_run - /// # use serenity::Client; - /// # - /// # let mut client = Client::new(""); - /// use serenity::model::{Channel, ChannelId}; - /// - /// client.on_channel_delete(|ctx, channel| { - /// if let Channel::Guild(channel) = channel { - /// let (content, default_channel_id) = { - /// let reader = channel.read().unwrap(); - /// let content = format!("A channel named '{}' was deleted.", reader.name); - /// let id = ChannelId(reader.guild_id.0); - /// - /// (content, id) - /// }; - /// - /// if let Err(why) = default_channel_id.say(&content) { - /// println!("Err sending message to default channel: {:?}", why); - /// } - /// } - /// }); - /// ``` - /// - /// [`ChannelDelete`]: ../model/event/enum.Event.html#variant.ChannelDelete - pub fn on_channel_delete<F>(&mut self, handler: F) - where F: Fn(Context, Channel) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_channel_delete = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`ChannelPinsUpdate`] is received. - /// - /// [`ChannelPinsUpdate`]: ../model/event/enum.Event.html#variant.ChannelPinsUpdate - pub fn on_channel_pins_update<F>(&mut self, handler: F) - where F: Fn(Context, ChannelPinsUpdateEvent) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_channel_pins_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildCreate`] is received. - /// - /// [`GuildCreate`]: ../model/event/enum.Event.html#variant.GuildCreate - pub fn on_guild_create<F>(&mut self, handler: F) - where F: Fn(Context, Guild) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_create = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildEmojisUpdate`] is received. - /// - /// The `HashMap` of emojis is the new full list of emojis. - /// - /// [`GuildEmojisUpdate`]: ../model/event/enum.Event.html#variant.GuildEmojisUpdate - pub fn on_guild_emojis_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, HashMap<EmojiId, Emoji>) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_emojis_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildIntegrationsUpdate`] is received. - /// - /// [`GuildIntegrationsUpdate`]: ../model/event/enum.Event.html#variant.GuildIntegrationsUpdate - pub fn on_guild_integrations_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildId) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_integrations_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildMemberAdd`] is received. - /// - /// [`GuildMemberAdd`]: ../model/event/enum.Event.html#variant.GuildMemberAdd - pub fn on_guild_member_add<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, Member) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_member_addition = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildMembersChunk`] is received. - /// - /// [`GuildMembersChunk`]: ../model/event/enum.Event.html#variant.GuildMembersChunk - pub fn on_guild_members_chunk<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, HashMap<UserId, Member>) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_members_chunk = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildRoleCreate`] is received. - /// - /// [`GuildRoleCreate`]: ../model/event/enum.Event.html#variant.GuildRoleCreate - pub fn on_guild_role_create<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, Role) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_role_create = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildUnavailable`] is received. - /// - /// [`GuildUnavailable`]: ../model/event/enum.Event.html#variant.GuildUnavailable - pub fn on_guild_unavailable<F>(&mut self, handler: F) - where F: Fn(Context, GuildId) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_unavailable = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildBan`] is received. - /// - /// [`GuildBan`]: ../model/event/enum.Event.html#variant.GuildBan - pub fn on_member_ban<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, User) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_ban_addition = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildUnban`] is received. - /// - /// [`GuildUnban`]: ../model/event/enum.Event.html#variant.GuildUnban - pub fn on_member_unban<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, User) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_ban_removal = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`MessageCreate`] is received. - /// - /// # Examples - /// - /// Print the contents of every received message: - /// - /// ```rust,ignore - /// use serenity::Client; - /// - /// let mut client = Client::new("bot token here"); - /// - /// client.on_message(|_context, message| { - /// println!("{}", message.content); - /// }); - /// - /// let _ = client.start(); - /// ``` - /// - /// [`MessageCreate`]: ../model/event/enum.Event.html#variant.MessageCreate - pub fn on_message<F>(&mut self, handler: F) - where F: Fn(Context, Message) + Send + Sync + 'static { - - self.event_store.write() - .unwrap() - .on_message = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`MessageDelete`] is received. - /// - /// [`MessageDelete`]: ../model/event/enum.Event.html#variant.MessageDelete - pub fn on_message_delete<F>(&mut self, handler: F) - where F: Fn(Context, ChannelId, MessageId) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_message_delete = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`MessageDeleteBulk`] is received. - /// - /// [`MessageDeleteBulk`]: ../model/event/enum.Event.html#variant.MessageDeleteBulk - pub fn on_message_delete_bulk<F>(&mut self, handler: F) - where F: Fn(Context, ChannelId, Vec<MessageId>) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_message_delete_bulk = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`MessageUpdate`] is received. - /// - /// [`MessageUpdate`]: ../model/event/enum.Event.html#variant.MessageUpdate - pub fn on_message_update<F>(&mut self, handler: F) - where F: Fn(Context, MessageUpdateEvent) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_message_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`PresencesReplace`] is received. - /// - /// [`PresencesReplace`]: ../model/event/enum.Event.html#variant.PresencesReplace - pub fn on_presence_replace<F>(&mut self, handler: F) - where F: Fn(Context, Vec<Presence>) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_presence_replace = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`PresenceUpdate`] is received. - /// - /// [`PresenceUpdate`]: ../model/event/enum.Event.html#variant.PresenceUpdate - pub fn on_presence_update<F>(&mut self, handler: F) - where F: Fn(Context, PresenceUpdateEvent) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_presence_update = Some(Arc::new(handler)); - } - - /// Attached a handler for when a [`ReactionAdd`] is received. - /// - /// [`ReactionAdd`]: ../model/event/enum.Event.html#variant.ReactionAdd - pub fn on_reaction_add<F>(&mut self, handler: F) - where F: Fn(Context, Reaction) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_reaction_add = Some(Arc::new(handler)); - } - - /// Attached a handler for when a [`ReactionRemove`] is received. - /// - /// [`ReactionRemove`]: ../model/event/enum.Event.html#variant.ReactionRemove - pub fn on_reaction_remove<F>(&mut self, handler: F) - where F: Fn(Context, Reaction) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_reaction_remove = Some(Arc::new(handler)); - } - - /// Attached a handler for when a [`ReactionRemoveAll`] is received. - /// - /// [`ReactionRemoveAll`]: ../model/event/enum.Event.html#variant.ReactionRemoveAll - pub fn on_reaction_remove_all<F>(&mut self, handler: F) - where F: Fn(Context, ChannelId, MessageId) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_reaction_remove_all = Some(Arc::new(handler)); - } - - /// Register an event to be called whenever a Ready event is received. - /// - /// Registering a handler for the ready event is good for noting when your - /// bot has established a connection to the gateway through a [`Shard`]. - /// - /// **Note**: The Ready event is not guarenteed to be the first event you - /// will receive by Discord. Do not actively rely on it. - /// - /// # Examples - /// - /// Print the [current user][`CurrentUser`]'s name on ready: - /// - /// ```rust,no_run - /// use serenity::Client; - /// use std::env; - /// - /// let token = env::var("DISCORD_BOT_TOKEN").unwrap(); - /// let mut client = Client::new(&token); - /// - /// client.on_ready(|_context, ready| { - /// println!("{} is connected", ready.user.name); - /// }); - /// ``` - /// - /// [`CurrentUser`]: ../model/struct.CurrentUser.html - /// [`Shard`]: gateway/struct.Shard.html - pub fn on_ready<F>(&mut self, handler: F) - where F: Fn(Context, Ready) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_ready = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`ChannelRecipientAdd`] is received. - /// - /// [`ChannelRecipientAdd`]: ../model/event/enum.Event.html#variant.ChannelRecipientAdd - pub fn on_recipient_add<F>(&mut self, handler: F) - where F: Fn(Context, ChannelId, User) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_channel_recipient_addition = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`ChannelRecipientRemove`] is received. - /// - /// [`ChannelRecipientRemove`]: ../model/event/enum.Event.html#variant.ChannelRecipientRemove - pub fn on_recipient_remove<F>(&mut self, handler: F) - where F: Fn(Context, ChannelId, User) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_channel_recipient_removal = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`Resumed`] is received. - /// - /// [`Resumed`]: ../model/event/enum.Event.html#variant.Resumed - pub fn on_resume<F>(&mut self, handler: F) - where F: Fn(Context, ResumedEvent) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_resume = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`TypingStart`] is received. - /// - /// [`TypingStart`]: ../model/event/enum.Event.html#variant.TypingStart - pub fn on_typing_start<F>(&mut self, handler: F) - where F: Fn(Context, TypingStartEvent) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_typing_start = Some(Arc::new(handler)); - } - - /// Attaches a handler for when an [`Unknown`] is received. - /// - /// [`Unknown`]: ../model/event/enum.Event.html#variant.Unknown - pub fn on_unknown<F>(&mut self, handler: F) - where F: Fn(Context, String, Value) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_unknown = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`VoiceServerUpdate`] is received. - /// - /// [`VoiceServerUpdate`]: ../model/event/enum.Event.html#variant.VoiceServerUpdate - pub fn on_voice_server_update<F>(&mut self, handler: F) - where F: Fn(Context, VoiceServerUpdateEvent) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_voice_server_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`VoiceStateUpdate`] is received. - /// - /// [`VoiceStateUpdate`]: ../model/event/enum.Event.html#variant.VoiceStateUpdate - pub fn on_voice_state_update<F>(&mut self, handler: F) - where F: Fn(Context, Option<GuildId>, VoiceState) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_voice_state_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`WebhookUpdate`] is received. - /// - /// [`WebhookUpdate`]: ../model/event/enum.Event.html#variant.WebhookUpdate - pub fn on_webhook_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, ChannelId) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_webhook_update = Some(Arc::new(handler)); - } - // Shard data layout is: // 0: first shard number to initialize // 1: shard number to initialize up to and including @@ -1011,7 +592,7 @@ impl Client { let monitor_info = feature_framework! {{ MonitorInfo { data: self.data.clone(), - event_store: self.event_store.clone(), + event_handler: self.event_handler.clone(), framework: self.framework.clone(), gateway_url: gateway_url.clone(), shard: shard, @@ -1021,7 +602,7 @@ impl Client { } else { MonitorInfo { data: self.data.clone(), - event_store: self.event_store.clone(), + event_handler: self.event_handler.clone(), gateway_url: gateway_url.clone(), shard: shard, shard_info: shard_info, @@ -1050,199 +631,6 @@ impl Client { } } -#[cfg(feature="cache")] -impl Client { - /// Attaches a handler for when a [`ChannelUpdate`] is received. - /// - /// Optionally provides the version of the channel before the update. - /// - /// [`ChannelUpdate`]: ../model/event/enum.Event.html#variant.ChannelUpdate - pub fn on_channel_update<F>(&mut self, handler: F) - where F: Fn(Context, Option<Channel>, Channel) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_channel_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildDelete`] is received. - /// - /// Returns a partial guild as well as - optionally - the full guild, with - /// data like [`Role`]s. This can be `None` in the event that it was not in - /// the [`Cache`]. - /// - /// **Note**: The relevant guild is _removed_ from the Cache when this event - /// is received. If you need to keep it, you can either re-insert it - /// yourself back into the Cache or manage it in another way. - /// - /// [`GuildDelete`]: ../model/event/enum.Event.html#variant.GuildDelete - /// [`Role`]: ../model/struct.Role.html - /// [`Cache`]: ../cache/struct.Cache.html - pub fn on_guild_delete<F>(&mut self, handler: F) - where F: Fn(Context, PartialGuild, Option<Arc<RwLock<Guild>>>) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_delete = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildMemberRemove`] is received. - /// - /// Returns the user's associated `Member` object, _if_ it existed in the - /// cache. - /// - /// [`GuildMemberRemove`]: ../model/event/enum.Event.html#variant.GuildMemberRemove - pub fn on_guild_member_remove<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, User, Option<Member>) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_member_removal = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildMemberUpdate`] is received. - /// - /// [`GuildMemberUpdate`]: ../model/event/enum.Event.html#variant.GuildMemberUpdate - pub fn on_guild_member_update<F>(&mut self, handler: F) - where F: Fn(Context, Option<Member>, Member) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_member_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildRoleDelete`] is received. - /// - /// [`GuildRoleDelete`]: ../model/event/enum.Event.html#variant.GuildRoleDelete - pub fn on_guild_role_delete<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, RoleId, Option<Role>) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_role_delete = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildRoleUpdate`] is received. - /// - /// The optional `Role` is the role prior to updating. This can be `None` if - /// it did not exist in the [`Cache`] before the update. - /// - /// [`GuildRoleUpdate`]: ../model/event/enum.Event.html#variant.GuildRoleUpdate - /// [`Cache`]: ../cache/struct.Cache.html - pub fn on_guild_role_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, Option<Role>, Role) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_role_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildUpdate`] is received. - /// - /// [`GuildUpdate`]: ../model/event/enum.Event.html#variant.GuildUpdate - pub fn on_guild_update<F>(&mut self, handler: F) - where F: Fn(Context, Option<Arc<RwLock<Guild>>>, PartialGuild) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`UserUpdate`] is received. - /// - /// The old current user will be provided as well. - /// - /// [`UserUpdate`]: ../model/event/enum.Event.html#variant.UserUpdate - pub fn on_user_update<F>(&mut self, handler: F) - where F: Fn(Context, CurrentUser, CurrentUser) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_user_update = Some(Arc::new(handler)); - } -} - -#[cfg(not(feature="cache"))] -impl Client { - /// Attaches a handler for when a [`ChannelUpdate`] is received. - /// - /// [`ChannelUpdate`]: ../model/event/enum.Event.html#variant.ChannelUpdate - pub fn on_channel_update<F>(&mut self, handler: F) - where F: Fn(Context, Channel) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_channel_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildDelete`] is received. - /// - /// [`GuildDelete`]: ../model/event/enum.Event.html#variant.GuildDelete - /// [`Role`]: ../model/struct.Role.html - /// [`Cache`]: ../cache/struct.Cache.html - pub fn on_guild_delete<F>(&mut self, handler: F) - where F: Fn(Context, PartialGuild) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_delete = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildMemberRemove`] is received. - /// - /// Returns the user's associated `Member` object, _if_ it existed in the - /// cache. - /// - /// [`GuildMemberRemove`]: ../model/event/enum.Event.html#variant.GuildMemberRemove - pub fn on_guild_member_remove<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, User) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_member_removal = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildMemberUpdate`] is received. - /// - /// [`GuildMemberUpdate`]: ../model/event/enum.Event.html#variant.GuildMemberUpdate - pub fn on_guild_member_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildMemberUpdateEvent) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_member_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildRoleDelete`] is received. - /// - /// [`GuildRoleDelete`]: ../model/event/enum.Event.html#variant.GuildRoleDelete - pub fn on_guild_role_delete<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, RoleId) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_role_delete = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildRoleUpdate`] is received. - /// - /// [`GuildRoleUpdate`]: ../model/event/enum.Event.html#variant.GuildRoleUpdate - /// [`Cache`]: ../cache/struct.Cache.html - pub fn on_guild_role_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, Role) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_role_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`GuildUpdate`] is received. - /// - /// [`GuildUpdate`]: ../model/event/enum.Event.html#variant.GuildUpdate - pub fn on_guild_update<F>(&mut self, handler: F) - where F: Fn(Context, PartialGuild) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_guild_update = Some(Arc::new(handler)); - } - - /// Attaches a handler for when a [`UserUpdate`] is received. - /// - /// [`UserUpdate`]: ../model/event/enum.Event.html#variant.UserUpdate - pub fn on_user_update<F>(&mut self, handler: F) - where F: Fn(Context, CurrentUser) + Send + Sync + 'static { - self.event_store.write() - .unwrap() - .on_user_update = Some(Arc::new(handler)); - } -} - struct BootInfo { gateway_url: Arc<Mutex<String>>, shard_info: [u64; 2], @@ -1250,9 +638,9 @@ struct BootInfo { } #[cfg(feature="framework")] -struct MonitorInfo { +struct MonitorInfo<H: EventHandler + Send + Sync + 'static> { data: Arc<Mutex<ShareMap>>, - event_store: Arc<RwLock<EventStore>>, + event_handler: Arc<H>, framework: Arc<Mutex<Framework>>, gateway_url: Arc<Mutex<String>>, shard: Arc<Mutex<Shard>>, @@ -1261,9 +649,9 @@ struct MonitorInfo { } #[cfg(not(feature="framework"))] -struct MonitorInfo { +struct MonitorInfo<H: EventHandler + Send + Sync + 'static> { data: Arc<Mutex<ShareMap>>, - event_store: Arc<RwLock<EventStore>>, + event_handler: Arc<H>, gateway_url: Arc<Mutex<String>>, shard: Arc<Mutex<Shard>>, shard_info: [u64; 2], @@ -1310,7 +698,7 @@ fn boot_shard(info: &BootInfo) -> Result<Shard> { Err(Error::Client(ClientError::ShardBootFailure)) } -fn monitor_shard(mut info: MonitorInfo) { +fn monitor_shard<H: EventHandler + Send + Sync + 'static>(mut info: MonitorInfo<H>) { handle_shard(&mut info); loop { @@ -1347,7 +735,7 @@ fn monitor_shard(mut info: MonitorInfo) { error!("Completely failed to reboot shard"); } -fn handle_shard(info: &mut MonitorInfo) { +fn handle_shard<H: EventHandler + Send + Sync + 'static>(info: &mut MonitorInfo<H>) { // This is currently all ducktape. Redo this. loop { { @@ -1420,31 +808,31 @@ fn handle_shard(info: &mut MonitorInfo) { &info.shard, &info.framework, &info.data, - &info.event_store); + &info.event_handler); } else { dispatch(event, &info.shard, &info.data, - &info.event_store); + &info.event_handler); }} } } -fn init_client(token: String) -> Client { +fn init_client<H: EventHandler + Send + Sync + 'static>(token: String, handler: H) -> Client<H> { http::set_token(&token); let locked = Arc::new(Mutex::new(token)); feature_framework! {{ Client { data: Arc::new(Mutex::new(ShareMap::custom())), - event_store: Arc::new(RwLock::new(EventStore::default())), + event_handler: Arc::new(handler), framework: Arc::new(Mutex::new(Framework::default())), token: locked, } } else { Client { data: Arc::new(Mutex::new(ShareMap::custom())), - event_store: Arc::new(RwLock::new(EventStore::default())), + event_handler: Arc::new(handler), token: locked, } }} |