diff options
| author | Austin Hellyer <[email protected]> | 2016-11-15 08:12:53 -0800 |
|---|---|---|
| committer | Austin Hellyer <[email protected]> | 2016-11-15 08:12:53 -0800 |
| commit | b0be1414dc75c8ace19fa033fd54046c71640c13 (patch) | |
| tree | 7b125327e35b21506a8c25b54e1cb3a9dfe41e70 /src/client | |
| parent | Decode embed/role colours into Colour struct (diff) | |
| download | serenity-b0be1414dc75c8ace19fa033fd54046c71640c13.tar.xz serenity-b0be1414dc75c8ace19fa033fd54046c71640c13.zip | |
State: on update, return old instances
When updating the State, return the old instance of removed/updated
fields where possible, so that they can be used to send to event
handlers as a "this is what it used to look like, this is what it looks
like now" type of thing.
Very descriptive, I know.
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/dispatch.rs | 85 | ||||
| -rw-r--r-- | src/client/event_store.rs | 16 | ||||
| -rw-r--r-- | src/client/mod.rs | 58 |
3 files changed, 81 insertions, 78 deletions
diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs index 7efee75..985f03e 100644 --- a/src/client/dispatch.rs +++ b/src/client/dispatch.rs @@ -20,7 +20,10 @@ macro_rules! handler { macro_rules! update { ($method:ident, $event:expr) => { STATE.lock().unwrap().$method(&$event); - } + }; + ($method:ident, $event:expr, $old:expr) => { + STATE.lock().unwrap().$method(&$event, $old); + }; } fn context(channel_id: Option<ChannelId>, @@ -71,13 +74,7 @@ pub fn dispatch(event: Result<Event>, }, Ok(Event::CallUpdate(event)) => { if let Some(ref handler) = handler!(on_call_update, event_store) { - let before = STATE - .lock() - .unwrap() - .calls - .get(&event.channel_id) - .cloned(); - update!(update_with_call_update, event); + let before = update!(update_with_call_update, event, true); let after = STATE .lock() .unwrap() @@ -92,7 +89,7 @@ pub fn dispatch(event: Result<Event>, (handler)(context, before, after); }); } else { - update!(update_with_call_update, event); + update!(update_with_call_update, event, false); } }, Ok(Event::ChannelCreate(event)) => { @@ -226,15 +223,16 @@ pub fn dispatch(event: Result<Event>, } }, Ok(Event::GuildDelete(event)) => { - update!(update_with_guild_delete, event); - if let Some(ref handler) = handler!(on_guild_delete, event_store) { + let full = update!(update_with_guild_delete, event); let context = context(None, conn, login_type); let handler = handler.clone(); thread::spawn(move || { - (handler)(context, event.guild); + (handler)(context, event.guild, full); }); + } else { + let _full = update!(update_with_guild_delete, event); } }, Ok(Event::GuildEmojisUpdate(event)) => { @@ -245,7 +243,7 @@ pub fn dispatch(event: Result<Event>, let handler = handler.clone(); thread::spawn(move || { - (handler)(context, event); + (handler)(context, event.guild_id, event.emojis); }); } }, @@ -255,7 +253,7 @@ pub fn dispatch(event: Result<Event>, let handler = handler.clone(); thread::spawn(move || { - (handler)(context, event); + (handler)(context, event.guild_id); }); } }, @@ -272,30 +270,21 @@ pub fn dispatch(event: Result<Event>, } }, Ok(Event::GuildMemberRemove(event)) => { - update!(update_with_guild_member_remove, event); - if let Some(ref handler) = handler!(on_guild_member_removal, event_store) { + let member = update!(update_with_guild_member_remove, event); let context = context(None, conn, login_type); let handler = handler.clone(); thread::spawn(move || { - (handler)(context, event.guild_id, event.user); + (handler)(context, event.guild_id, event.user, member); }); + } else { + let _member = update!(update_with_guild_member_remove, event); } }, Ok(Event::GuildMemberUpdate(event)) => { if let Some(ref handler) = handler!(on_guild_member_update, event_store) { - let before = STATE.lock() - .unwrap() - .guilds - .get_mut(&event.guild_id) - .map(|mut guild| { - guild.members.remove(&event.user.id) - }).and_then(|x| match x { - Some(x) => Some(x), - _ => None, - }); - update!(update_with_guild_member_update, event); + let before = update!(update_with_guild_member_update, event, true); // This is safe, as the update would have created the member // if it did not exist. Thus, there _should_ be no way that this @@ -311,6 +300,8 @@ pub fn dispatch(event: Result<Event>, thread::spawn(move || { (handler)(context, before, after); }); + } else { + let _ = update!(update_with_guild_member_update, event, false); } }, Ok(Event::GuildMembersChunk(event)) => { @@ -338,26 +329,25 @@ pub fn dispatch(event: Result<Event>, } }, Ok(Event::GuildRoleDelete(event)) => { - update!(update_with_guild_role_delete, event); - if let Some(ref handler) = handler!(on_guild_role_delete, event_store) { + let role = update!(update_with_guild_role_delete, event); let context = context(None, conn, login_type); let handler = handler.clone(); thread::spawn(move || { - (handler)(context, event.guild_id, event.role_id); + (handler)(context, event.guild_id, event.role_id, role); }); } }, Ok(Event::GuildRoleUpdate(event)) => { - update!(update_with_guild_role_update, event); + let before = update!(update_with_guild_role_update, event); if let Some(ref handler) = handler!(on_guild_role_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); thread::spawn(move || { - (handler)(context, event.guild_id, event.role); + (handler)(context, event.guild_id, before, event.role); }); } }, @@ -596,13 +586,9 @@ pub fn dispatch(event: Result<Event>, } }, Ok(Event::UserGuildSettingsUpdate(event)) => { - if let Some(ref handler) = handler!(on_user_guild_settings_update, event_store) { - let before = STATE.lock() - .unwrap() - .guild_settings - .remove(&event.settings.guild_id); - update!(update_with_user_guild_settings_update, event); + let before = update!(update_with_user_guild_settings_update, event); + if let Some(ref handler) = handler!(on_user_guild_settings_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -612,19 +598,20 @@ pub fn dispatch(event: Result<Event>, } }, Ok(Event::UserNoteUpdate(event)) => { + let before = update!(update_with_user_note_update, event); + if let Some(ref handler) = handler!(on_note_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); thread::spawn(move || { - (handler)(context, event.user_id, event.note); + (handler)(context, event.user_id, before, event.note); }); } }, Ok(Event::UserSettingsUpdate(event)) => { if let Some(ref handler) = handler!(on_user_settings_update, event_store) { - let before = STATE.lock().unwrap().settings.clone(); - update!(update_with_user_settings_update, event); + let before = update!(update_with_user_settings_update, event, true); let after = STATE.lock().unwrap().settings.clone(); let context = context(None, conn, login_type); @@ -634,19 +621,13 @@ pub fn dispatch(event: Result<Event>, (handler)(context, before.unwrap(), after.unwrap()); }); } else { - update!(update_with_user_settings_update, event); + update!(update_with_user_settings_update, event, false); } }, Ok(Event::UserUpdate(event)) => { - if let Some(ref handler) = handler!(on_user_update, event_store) { - // This is equivilant to performing a - // `update_with_voice_state_update`, and will be more efficient. - let before = { - let mut state = STATE.lock().unwrap(); - - mem::replace(&mut state.user, event.current_user.clone()) - }; + let before = update!(update_with_user_update, event); + if let Some(ref handler) = handler!(on_user_update, event_store) { let context = context(None, conn, login_type); let handler = handler.clone(); @@ -673,7 +654,7 @@ pub fn dispatch(event: Result<Event>, let handler = handler.clone(); thread::spawn(move || { - (handler)(context, event); + (handler)(context, event.guild_id, event.voice_state); }); } }, diff --git a/src/client/event_store.rs b/src/client/event_store.rs index 576fe29..387f9e7 100644 --- a/src/client/event_store.rs +++ b/src/client/event_store.rs @@ -38,16 +38,16 @@ pub struct EventStore { pub on_guild_ban_addition: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>, pub on_guild_ban_removal: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>, pub on_guild_create: Option<Arc<Fn(Context, LiveGuild) + Send + Sync + 'static>>, - pub on_guild_delete: Option<Arc<Fn(Context, Guild) + Send + Sync + 'static>>, - pub on_guild_emojis_update: Option<Arc<Fn(Context, GuildEmojisUpdateEvent) + Send + Sync + 'static>>, - pub on_guild_integrations_update: Option<Arc<Fn(Context, GuildIntegrationsUpdateEvent) + Send + Sync + 'static>>, + pub on_guild_delete: Option<Arc<Fn(Context, Guild, Option<LiveGuild>) + Send + Sync + 'static>>, + pub on_guild_emojis_update: Option<Arc<Fn(Context, GuildId, HashMap<EmojiId, Emoji>) + Send + Sync + 'static>>, + pub on_guild_integrations_update: Option<Arc<Fn(Context, GuildId) + Send + Sync + 'static>>, pub on_guild_member_addition: Option<Arc<Fn(Context, GuildId, Member) + Send + Sync + 'static>>, - pub on_guild_member_removal: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>, + pub on_guild_member_removal: Option<Arc<Fn(Context, GuildId, User, Option<Member>) + Send + Sync + 'static>>, pub on_guild_member_update: Option<Arc<Fn(Context, Option<Member>, Member) + Send + Sync + 'static>>, pub on_guild_members_chunk: Option<Arc<Fn(Context, GuildId, HashMap<UserId, Member>) + Send + Sync + 'static>>, pub on_guild_role_create: Option<Arc<Fn(Context, GuildId, Role) + Send + Sync + 'static>>, - pub on_guild_role_delete: Option<Arc<Fn(Context, GuildId, RoleId) + Send + Sync + 'static>>, - pub on_guild_role_update: Option<Arc<Fn(Context, GuildId, Role) + Send + Sync + 'static>>, + pub on_guild_role_delete: Option<Arc<Fn(Context, GuildId, RoleId, Option<Role>) + Send + Sync + 'static>>, + pub on_guild_role_update: Option<Arc<Fn(Context, GuildId, Option<Role>, Role) + Send + Sync + 'static>>, pub on_guild_sync: Option<Arc<Fn(Context, GuildSyncEvent) + Send + Sync + 'static>>, pub on_guild_unavailable: Option<Arc<Fn(Context, GuildId) + Send + Sync + 'static>>, pub on_guild_update: Option<Arc<Fn(Context, Option<LiveGuild>, Guild) + Send + Sync + 'static>>, @@ -59,7 +59,7 @@ pub struct EventStore { pub on_reaction_remove: Option<Arc<Fn(Context, Reaction) + Send + Sync + 'static>>, pub on_reaction_remove_all: Option<Arc<Fn(Context, ChannelId, MessageId) + Send + Sync + 'static>>, pub on_message_update: Option<Arc<Fn(Context, MessageUpdateEvent) + Send + Sync + 'static>>, - pub on_note_update: Option<Arc<Fn(Context, UserId, String) + Send + Sync + 'static>>, + pub on_note_update: Option<Arc<Fn(Context, UserId, Option<String>, String) + Send + Sync + 'static>>, pub on_presence_replace: Option<Arc<Fn(Context, Vec<Presence>) + Send + Sync + 'static>>, pub on_presence_update: Option<Arc<Fn(Context, PresenceUpdateEvent) + Send + Sync + 'static>>, pub on_ready: Option<Arc<Fn(Context, Ready) + Send + Sync + 'static>>, @@ -71,7 +71,7 @@ pub struct EventStore { pub on_user_guild_settings_update: Option<Arc<Fn(Context, Option<UserGuildSettings>, UserGuildSettings) + Send + Sync + 'static>>, pub on_user_update: Option<Arc<Fn(Context, CurrentUser, CurrentUser) + Send + Sync + 'static>>, pub on_user_settings_update: Option<Arc<Fn(Context, UserSettings, UserSettings) + Send + Sync + 'static>>, - pub on_voice_state_update: Option<Arc<Fn(Context, VoiceStateUpdateEvent) + Send + Sync + 'static>>, pub on_voice_server_update: Option<Arc<Fn(Context, VoiceServerUpdateEvent) + Send + Sync + 'static>>, + pub on_voice_state_update: Option<Arc<Fn(Context, Option<GuildId>, VoiceState) + Send + Sync + 'static>>, pub on_webhook_update: Option<Arc<Fn(Context, GuildId, ChannelId) + Send + Sync + 'static>>, } diff --git a/src/client/mod.rs b/src/client/mod.rs index 661d477..f270b31 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -475,9 +475,19 @@ impl Client { /// Attaches a handler for when a [`GuilDelete`] is received. /// - /// [`GuilDelete`]: ../model/enum.Event.html#variant.GuildDelete + /// 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 [`State`]. + /// + /// **Note**: The relevant guild is _removed_ from the State when this event + /// is received. If you need to keep it, you can either re-insert it + /// yourself back into the State or manage it in another way. + /// + /// [`GuildDelete`]: ../model/enum.Event.html#variant.GuildDelete + /// [`Role`]: ../model/struct.Role.html + /// [`State`]: ../ext/state/struct.State.html pub fn on_guild_delete<F>(&mut self, handler: F) - where F: Fn(Context, Guild) + Send + Sync + 'static { + where F: Fn(Context, Guild, Option<LiveGuild>) + Send + Sync + 'static { self.event_store.lock() .unwrap() .on_guild_delete = Some(Arc::new(handler)); @@ -485,9 +495,11 @@ impl Client { /// Attaches a handler for when a [`GuildEmojisUpdate`] is received. /// + /// The `HashMap` of emojis is the new full list of emojis. + /// /// [`GuildEmojisUpdate`]: ../model/enum.Event.html#variant.GuildEmojisUpdate pub fn on_guild_emojis_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildEmojisUpdateEvent) + Send + Sync + 'static { + where F: Fn(Context, GuildId, HashMap<EmojiId, Emoji>) + Send + Sync + 'static { self.event_store.lock() .unwrap() .on_guild_emojis_update = Some(Arc::new(handler)); @@ -497,7 +509,7 @@ impl Client { /// /// [`GuildIntegrationsUpdate`]: ../model/enum.Event.html#variant.GuildIntegrationsUpdate pub fn on_guild_integrations_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildIntegrationsUpdateEvent) + Send + Sync + 'static { + where F: Fn(Context, GuildId) + Send + Sync + 'static { self.event_store.lock() .unwrap() .on_guild_integrations_update = Some(Arc::new(handler)); @@ -515,9 +527,12 @@ impl Client { /// Attaches a handler for when a [`GuildMemberRemove`] is received. /// + /// Returns the user's associated `Member` object, _if_ it existed in the + /// state. + /// /// [`GuildMemberRemove`]: ../model/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 { + where F: Fn(Context, GuildId, User, Option<Member>) + Send + Sync + 'static { self.event_store.lock() .unwrap() .on_guild_member_removal = Some(Arc::new(handler)); @@ -557,7 +572,7 @@ impl Client { /// /// [`GuildRoleDelete`]: ../model/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 { + where F: Fn(Context, GuildId, RoleId, Option<Role>) + Send + Sync + 'static { self.event_store.lock() .unwrap() .on_guild_role_delete = Some(Arc::new(handler)); @@ -565,9 +580,13 @@ impl Client { /// 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 [`State`] before the update. + /// /// [`GuildRoleUpdate`]: ../model/enum.Event.html#variant.GuildRoleUpdate + /// [`State`]: ../ext/state/struct.State.html pub fn on_guild_role_update<F>(&mut self, handler: F) - where F: Fn(Context, GuildId, Role) + Send + Sync + 'static { + where F: Fn(Context, GuildId, Option<Role>, Role) + Send + Sync + 'static { self.event_store.lock() .unwrap() .on_guild_role_update = Some(Arc::new(handler)); @@ -676,9 +695,12 @@ impl Client { /// Attaches a handler for when a [`UserNoteUpdate`] is received. /// + /// Optionally returns the old note for the [`User`], if one existed. + /// + /// [`User`]: ../model/struct.User.html /// [`UserNoteUpdate`]: ../model/enum.Event.html#variant.UserNoteUpdate pub fn on_note_update<F>(&mut self, handler: F) - where F: Fn(Context, UserId, String) + Send + Sync + 'static { + where F: Fn(Context, UserId, Option<String>, String) + Send + Sync + 'static { self.event_store.lock() .unwrap() .on_note_update = Some(Arc::new(handler)); @@ -866,16 +888,6 @@ impl Client { .on_user_settings_update = Some(Arc::new(handler)); } - /// Attaches a handler for when a [`VoiceStateUpdate`] is received. - /// - /// [`VoiceStateUpdate`]: ../model/enum.Event.html#variant.VoiceStateUpdate - pub fn on_voice_state_update<F>(&mut self, handler: F) - where F: Fn(Context, VoiceStateUpdateEvent) + Send + Sync + 'static { - self.event_store.lock() - .unwrap() - .on_voice_state_update = Some(Arc::new(handler)); - } - /// Attaches a handler for when a [`VoiceServerUpdate`] is received. /// /// [`VoiceServerUpdate`]: ../model/enum.Event.html#variant.VoiceServerUpdate @@ -886,6 +898,16 @@ impl Client { .on_voice_server_update = Some(Arc::new(handler)); } + /// Attaches a handler for when a [`VoiceStateUpdate`] is received. + /// + /// [`VoiceStateUpdate`]: ../model/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.lock() + .unwrap() + .on_voice_state_update = Some(Arc::new(handler)); + } + /// Attaches a handler for when a [`WebhookUpdate`] is received. /// /// [`WebhookUpdate`]: ../model/enum.Event.html#variant.WebhookUpdate |