aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoracdenisSK <[email protected]>2017-09-12 14:57:52 +0200
committeracdenisSK <[email protected]>2017-09-12 14:59:21 +0200
commitbc3491cf3a70a02ce5725e66887746567ae4660c (patch)
treedc1086bfae3f2cb56ab8ea89e13cba8bf46c0513 /src
parentCopy some methods from Command to Group (#164) (diff)
downloadserenity-bc3491cf3a70a02ce5725e66887746567ae4660c.tar.xz
serenity-bc3491cf3a70a02ce5725e66887746567ae4660c.zip
Revamp `CacheEventsImpl`
Diffstat (limited to 'src')
-rw-r--r--src/cache/cache_events_impl.rs514
-rw-r--r--src/cache/cache_update.rs7
-rw-r--r--src/cache/mod.rs10
-rw-r--r--src/client/dispatch.rs128
-rw-r--r--src/lib.rs2
-rw-r--r--src/model/event.rs611
6 files changed, 684 insertions, 588 deletions
diff --git a/src/cache/cache_events_impl.rs b/src/cache/cache_events_impl.rs
deleted file mode 100644
index a1d2e82..0000000
--- a/src/cache/cache_events_impl.rs
+++ /dev/null
@@ -1,514 +0,0 @@
-use std::collections::hash_map::Entry;
-use std::collections::HashMap;
-use std::default::Default;
-use std::sync::{Arc, RwLock};
-use std::mem;
-use model::*;
-use model::event::*;
-use internal::RwLockExt;
-
-pub(crate) trait CacheEventsImpl {
- fn update_with_channel_create(&mut self, event: &ChannelCreateEvent) -> Option<Channel>;
-
- fn update_with_channel_delete(&mut self, event: &ChannelDeleteEvent);
-
- fn update_with_channel_pins_update(&mut self, event: &ChannelPinsUpdateEvent);
-
- fn update_with_channel_recipient_add(&mut self, event: &mut ChannelRecipientAddEvent);
-
- fn update_with_channel_recipient_remove(&mut self, event: &ChannelRecipientRemoveEvent);
-
- fn update_with_channel_update(&mut self, event: &ChannelUpdateEvent);
-
- fn update_with_guild_create(&mut self, event: &GuildCreateEvent);
-
- fn update_with_guild_delete(&mut self, event: &GuildDeleteEvent) -> Option<Arc<RwLock<Guild>>>;
-
- fn update_with_guild_emojis_update(&mut self, event: &GuildEmojisUpdateEvent);
-
- fn update_with_guild_member_add(&mut self, event: &mut GuildMemberAddEvent);
-
- fn update_with_guild_member_remove(&mut self, event: &GuildMemberRemoveEvent)
- -> Option<Member>;
-
- fn update_with_guild_member_update(&mut self, event: &GuildMemberUpdateEvent)
- -> Option<Member>;
-
- fn update_with_guild_members_chunk(&mut self, event: &GuildMembersChunkEvent);
-
- fn update_with_guild_role_create(&mut self, event: &GuildRoleCreateEvent);
-
- fn update_with_guild_role_delete(&mut self, event: &GuildRoleDeleteEvent) -> Option<Role>;
-
- fn update_with_guild_role_update(&mut self, event: &GuildRoleUpdateEvent) -> Option<Role>;
-
- fn update_with_guild_unavailable(&mut self, event: &GuildUnavailableEvent);
-
- fn update_with_guild_update(&mut self, event: &GuildUpdateEvent);
-
- fn update_with_presences_replace(&mut self, event: &PresencesReplaceEvent);
-
- fn update_with_presence_update(&mut self, event: &mut PresenceUpdateEvent);
-
- fn update_with_ready(&mut self, event: &ReadyEvent);
-
- fn update_with_user_update(&mut self, event: &UserUpdateEvent) -> CurrentUser;
-
- fn update_with_voice_state_update(&mut self, event: &VoiceStateUpdateEvent);
-}
-
-impl CacheEventsImpl for super::Cache {
- fn update_with_channel_create(&mut self, event: &ChannelCreateEvent) -> Option<Channel> {
- match event.channel {
- Channel::Group(ref group) => {
- let group = group.clone();
-
- let channel_id = group.with_mut(|writer| {
- for (recipient_id, recipient) in &mut writer.recipients {
- self.update_user_entry(&recipient.read().unwrap());
-
- *recipient = self.users[recipient_id].clone();
- }
-
- writer.channel_id
- });
-
- let ch = self.groups.insert(channel_id, group);
-
- ch.map(Channel::Group)
- },
- Channel::Guild(ref channel) => {
- let (guild_id, channel_id) = channel.with(|channel| (channel.guild_id, channel.id));
-
- self.channels.insert(channel_id, channel.clone());
-
- self.guilds
- .get_mut(&guild_id)
- .and_then(|guild| {
- guild.with_mut(|guild| {
- guild.channels.insert(channel_id, channel.clone())
- })
- })
- .map(Channel::Guild)
- },
- Channel::Private(ref channel) => {
- if let Some(channel) = self.private_channels.get(&channel.with(|c| c.id)) {
- return Some(Channel::Private((*channel).clone()));
- }
-
- let channel = channel.clone();
-
- let id = channel.with_mut(|writer| {
- let user_id = writer.recipient.with_mut(|user| {
- self.update_user_entry(&user);
-
- user.id
- });
-
- writer.recipient = self.users[&user_id].clone();
- writer.id
- });
-
- let ch = self.private_channels.insert(id, channel.clone());
- ch.map(Channel::Private)
- },
- Channel::Category(ref category) => {
- self.categories
- .insert(category.read().unwrap().id, category.clone())
- .map(Channel::Category)
- },
- }
- }
-
- fn update_with_channel_delete(&mut self, event: &ChannelDeleteEvent) {
- match event.channel {
- Channel::Guild(ref channel) => {
- let (guild_id, channel_id) = channel.with(|channel| (channel.guild_id, channel.id));
-
- self.channels.remove(&channel_id);
-
- self.guilds.get_mut(&guild_id).and_then(|guild| {
- guild.with_mut(|g| g.channels.remove(&channel_id))
- });
- },
- Channel::Category(ref category) => {
- let channel_id = category.with(|cat| cat.id);
-
- self.categories.remove(&channel_id);
- },
- // We ignore these two due to the fact that the delete event for dms/groups
- // will _not_ fire anymore.
- Channel::Private(_) |
- Channel::Group(_) => unreachable!(),
- };
- }
-
- #[allow(dead_code)]
- fn update_with_channel_pins_update(&mut self, event: &ChannelPinsUpdateEvent) {
- if let Some(channel) = self.channels.get(&event.channel_id) {
- channel.with_mut(|c| {
- c.last_pin_timestamp = event.last_pin_timestamp;
- });
-
- return;
- }
-
- if let Some(channel) = self.private_channels.get_mut(&event.channel_id) {
- channel.with_mut(|c| {
- c.last_pin_timestamp = event.last_pin_timestamp;
- });
-
- return;
- }
-
- if let Some(group) = self.groups.get_mut(&event.channel_id) {
- group.with_mut(|c| {
- c.last_pin_timestamp = event.last_pin_timestamp;
- });
-
- return;
- }
- }
-
- fn update_with_channel_recipient_add(&mut self, event: &mut ChannelRecipientAddEvent) {
- self.update_user_entry(&event.user);
- let user = self.users[&event.user.id].clone();
-
- self.groups.get_mut(&event.channel_id).map(|group| {
- group.write().unwrap().recipients.insert(
- event.user.id,
- user,
- );
- });
- }
-
- fn update_with_channel_recipient_remove(&mut self, event: &ChannelRecipientRemoveEvent) {
- self.groups.get_mut(&event.channel_id).map(|group| {
- group.with_mut(|g| g.recipients.remove(&event.user.id))
- });
- }
-
- fn update_with_channel_update(&mut self, event: &ChannelUpdateEvent) {
- match event.channel {
- Channel::Group(ref group) => {
- let (ch_id, no_recipients) =
- group.with(|g| (g.channel_id, g.recipients.is_empty()));
-
- match self.groups.entry(ch_id) {
- Entry::Vacant(e) => {
- e.insert(group.clone());
- },
- Entry::Occupied(mut e) => {
- let mut dest = e.get_mut().write().unwrap();
-
- if no_recipients {
- let recipients = mem::replace(&mut dest.recipients, HashMap::new());
-
- dest.clone_from(&group.read().unwrap());
-
- dest.recipients = recipients;
- } else {
- dest.clone_from(&group.read().unwrap());
- }
- },
- }
- },
- Channel::Guild(ref channel) => {
- let (guild_id, channel_id) = channel.with(|channel| (channel.guild_id, channel.id));
-
- self.channels.insert(channel_id, channel.clone());
- self.guilds.get_mut(&guild_id).map(|guild| {
- guild.with_mut(
- |g| g.channels.insert(channel_id, channel.clone()),
- )
- });
- },
- Channel::Private(ref channel) => {
- self.private_channels
- .get_mut(&channel.read().unwrap().id)
- .map(|private| private.clone_from(channel));
- },
- Channel::Category(ref category) => {
- self.categories.get_mut(&category.read().unwrap().id).map(
- |c| {
- c.clone_from(category)
- },
- );
- },
- }
- }
-
- fn update_with_guild_create(&mut self, event: &GuildCreateEvent) {
- self.unavailable_guilds.remove(&event.guild.id);
-
- let mut guild = event.guild.clone();
-
- for (user_id, member) in &mut guild.members {
- self.update_user_entry(&member.user.read().unwrap());
- let user = self.users[user_id].clone();
-
- member.user = user.clone();
- }
-
- self.channels.extend(guild.channels.clone());
- self.guilds.insert(
- event.guild.id,
- Arc::new(RwLock::new(guild)),
- );
- }
-
- fn update_with_guild_delete(&mut self, event: &GuildDeleteEvent) -> Option<Arc<RwLock<Guild>>> {
- // Remove channel entries for the guild if the guild is found.
- self.guilds.remove(&event.guild.id).map(|guild| {
- for channel_id in guild.write().unwrap().channels.keys() {
- self.channels.remove(channel_id);
- }
-
- guild
- })
- }
-
- fn update_with_guild_emojis_update(&mut self, event: &GuildEmojisUpdateEvent) {
- self.guilds.get_mut(&event.guild_id).map(|guild| {
- guild.with_mut(|g| g.emojis.extend(event.emojis.clone()))
- });
- }
-
- fn update_with_guild_member_add(&mut self, event: &mut GuildMemberAddEvent) {
- let user_id = event.member.user.with(|u| u.id);
- self.update_user_entry(&event.member.user.read().unwrap());
-
- // Always safe due to being inserted above.
- event.member.user = self.users[&user_id].clone();
-
- self.guilds.get_mut(&event.guild_id).map(|guild| {
- guild.with_mut(|guild| {
- guild.member_count += 1;
- guild.members.insert(user_id, event.member.clone());
- })
- });
- }
-
- fn update_with_guild_member_remove(&mut self,
- event: &GuildMemberRemoveEvent)
- -> Option<Member> {
- self.guilds.get_mut(&event.guild_id).and_then(|guild| {
- guild.with_mut(|guild| {
- guild.member_count -= 1;
- guild.members.remove(&event.user.id)
- })
- })
- }
-
- fn update_with_guild_member_update(&mut self,
- event: &GuildMemberUpdateEvent)
- -> Option<Member> {
- self.update_user_entry(&event.user);
-
- if let Some(guild) = self.guilds.get_mut(&event.guild_id) {
- let mut guild = guild.write().unwrap();
-
- let mut found = false;
-
- let item = if let Some(member) = guild.members.get_mut(&event.user.id) {
- let item = Some(member.clone());
-
- member.nick.clone_from(&event.nick);
- member.roles.clone_from(&event.roles);
- member.user.write().unwrap().clone_from(&event.user);
-
- found = true;
-
- item
- } else {
- None
- };
-
- if !found {
- guild.members.insert(
- event.user.id,
- Member {
- deaf: false,
- guild_id: event.guild_id,
- joined_at: None,
- mute: false,
- nick: event.nick.clone(),
- roles: event.roles.clone(),
- user: Arc::new(RwLock::new(event.user.clone())),
- },
- );
- }
-
- item
- } else {
- None
- }
- }
-
- fn update_with_guild_members_chunk(&mut self, event: &GuildMembersChunkEvent) {
- for member in event.members.values() {
- self.update_user_entry(&member.user.read().unwrap());
- }
-
- self.guilds.get_mut(&event.guild_id).map(|guild| {
- guild.with_mut(|g| g.members.extend(event.members.clone()))
- });
- }
-
- fn update_with_guild_role_create(&mut self, event: &GuildRoleCreateEvent) {
- self.guilds.get_mut(&event.guild_id).map(|guild| {
- guild.write().unwrap().roles.insert(
- event.role.id,
- event.role.clone(),
- )
- });
- }
-
- fn update_with_guild_role_delete(&mut self, event: &GuildRoleDeleteEvent) -> Option<Role> {
- self.guilds.get_mut(&event.guild_id).and_then(|guild| {
- guild.with_mut(|g| g.roles.remove(&event.role_id))
- })
- }
-
- fn update_with_guild_role_update(&mut self, event: &GuildRoleUpdateEvent) -> Option<Role> {
- self.guilds.get_mut(&event.guild_id).and_then(|guild| {
- guild.with_mut(|g| {
- g.roles.get_mut(&event.role.id).map(|role| {
- mem::replace(role, event.role.clone())
- })
- })
- })
- }
-
- fn update_with_guild_unavailable(&mut self, event: &GuildUnavailableEvent) {
- self.unavailable_guilds.insert(event.guild_id);
- self.guilds.remove(&event.guild_id);
- }
-
- fn update_with_guild_update(&mut self, event: &GuildUpdateEvent) {
- self.guilds.get_mut(&event.guild.id).map(|guild| {
- let mut guild = guild.write().unwrap();
-
- guild.afk_timeout = event.guild.afk_timeout;
- guild.afk_channel_id.clone_from(&event.guild.afk_channel_id);
- guild.icon.clone_from(&event.guild.icon);
- guild.name.clone_from(&event.guild.name);
- guild.owner_id.clone_from(&event.guild.owner_id);
- guild.region.clone_from(&event.guild.region);
- guild.roles.clone_from(&event.guild.roles);
- guild.verification_level = event.guild.verification_level;
- });
- }
-
- fn update_with_presences_replace(&mut self, event: &PresencesReplaceEvent) {
- self.presences.extend({
- let mut p: HashMap<UserId, Presence> = HashMap::default();
-
- for presence in &event.presences {
- p.insert(presence.user_id, presence.clone());
- }
-
- p
- });
- }
-
- fn update_with_presence_update(&mut self, event: &mut PresenceUpdateEvent) {
- let user_id = event.presence.user_id;
-
- if let Some(user) = event.presence.user.as_mut() {
- self.update_user_entry(&user.read().unwrap());
- *user = self.users[&user_id].clone();
- }
-
- if let Some(guild_id) = event.guild_id {
- if let Some(guild) = self.guilds.get_mut(&guild_id) {
- let mut guild = guild.write().unwrap();
-
- // If the member went offline, remove them from the presence list.
- if event.presence.status == OnlineStatus::Offline {
- guild.presences.remove(&event.presence.user_id);
- } else {
- guild.presences.insert(
- event.presence.user_id,
- event.presence.clone(),
- );
- }
- }
- } else if event.presence.status == OnlineStatus::Offline {
- self.presences.remove(&event.presence.user_id);
- } else {
- self.presences.insert(
- event.presence.user_id,
- event.presence.clone(),
- );
- }
- }
-
- fn update_with_ready(&mut self, event: &ReadyEvent) {
- let mut ready = event.ready.clone();
-
- for guild in ready.guilds {
- match guild {
- GuildStatus::Offline(unavailable) => {
- self.guilds.remove(&unavailable.id);
- self.unavailable_guilds.insert(unavailable.id);
- },
- GuildStatus::OnlineGuild(guild) => {
- self.unavailable_guilds.remove(&guild.id);
- self.guilds.insert(guild.id, Arc::new(RwLock::new(guild)));
- },
- GuildStatus::OnlinePartialGuild(_) => {},
- }
- }
-
- // `ready.private_channels` will always be empty, and possibly be removed in the future.
- // So don't handle it at all.
-
- for (user_id, presence) in &mut ready.presences {
- if let Some(ref user) = presence.user {
- self.update_user_entry(&user.read().unwrap());
- }
-
- presence.user = self.users.get(user_id).cloned();
- }
-
- self.presences.extend(ready.presences);
- self.shard_count = ready.shard.map_or(1, |s| s[1]);
- self.user = ready.user;
- }
-
- fn update_with_user_update(&mut self, event: &UserUpdateEvent) -> CurrentUser {
- mem::replace(&mut self.user, event.current_user.clone())
- }
-
- fn update_with_voice_state_update(&mut self, event: &VoiceStateUpdateEvent) {
- if let Some(guild_id) = event.guild_id {
- if let Some(guild) = self.guilds.get_mut(&guild_id) {
- let mut guild = guild.write().unwrap();
-
- if event.voice_state.channel_id.is_some() {
- // Update or add to the voice state list
- {
- let finding = guild.voice_states.get_mut(&event.voice_state.user_id);
-
- if let Some(srv_state) = finding {
- srv_state.clone_from(&event.voice_state);
-
- return;
- }
- }
-
- guild.voice_states.insert(
- event.voice_state.user_id,
- event.voice_state.clone(),
- );
- } else {
- // Remove the user from the voice state list
- guild.voice_states.remove(&event.voice_state.user_id);
- }
- }
-
- return;
- }
- }
-}
diff --git a/src/cache/cache_update.rs b/src/cache/cache_update.rs
new file mode 100644
index 0000000..a05cc3d
--- /dev/null
+++ b/src/cache/cache_update.rs
@@ -0,0 +1,7 @@
+use super::Cache;
+
+pub(crate) trait CacheUpdate {
+ type Output;
+
+ fn update(&mut self, &mut Cache) -> Option<Self::Output>;
+}
diff --git a/src/cache/mod.rs b/src/cache/mod.rs
index 88e4266..ba9efaa 100644
--- a/src/cache/mod.rs
+++ b/src/cache/mod.rs
@@ -47,9 +47,9 @@ use std::default::Default;
use std::sync::{Arc, RwLock};
use model::*;
-mod cache_events_impl;
+mod cache_update;
-pub(crate) use self::cache_events_impl::*;
+pub(crate) use self::cache_update::*;
/// A cache of all events received over a [`Shard`], where storing at least
/// some data from the event is possible.
@@ -602,7 +602,11 @@ impl Cache {
self.categories.get(&channel_id.into()).cloned()
}
- fn update_user_entry(&mut self, user: &User) {
+ pub(crate) fn update<E: CacheUpdate>(&mut self, e: &mut E) -> Option<E::Output> {
+ e.update(self)
+ }
+
+ pub(crate) fn update_user_entry(&mut self, user: &User) {
match self.users.entry(user.id) {
Entry::Vacant(e) => {
e.insert(Arc::new(RwLock::new(user.clone())));
diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs
index f6d9dd3..bda0677 100644
--- a/src/client/dispatch.rs
+++ b/src/client/dispatch.rs
@@ -16,23 +16,13 @@ use framework::Framework;
#[cfg(feature = "cache")]
use super::CACHE;
-#[cfg(feature = "cache")]
-use super::super::CacheEventsImpl;
macro_rules! update {
- ($method:ident, @$event:expr) => {
- {
- #[cfg(feature="cache")]
- {
- CacheEventsImpl::$method(&mut *CACHE.write().unwrap(), &mut $event)
- }
- }
- };
- ($method:ident, $event:expr) => {
+ ($event:expr) => {
{
#[cfg(feature="cache")]
{
- CacheEventsImpl::$method(&mut *CACHE.write().unwrap(), &$event)
+ CACHE.write().unwrap().update(&mut $event)
}
}
};
@@ -141,8 +131,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
};
match event {
- Event::ChannelCreate(event) => {
- update!(update_with_channel_create, event);
+ Event::ChannelCreate(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -172,8 +162,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
},
}
},
- Event::ChannelDelete(event) => {
- update!(update_with_channel_delete, event);
+ Event::ChannelDelete(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -196,7 +186,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
},
}
},
- Event::ChannelPinsUpdate(event) => {
+ Event::ChannelPinsUpdate(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -206,7 +196,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
},
Event::ChannelRecipientAdd(mut event) => {
- update!(update_with_channel_recipient_add, @event);
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -220,8 +210,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::ChannelRecipientRemove(event) => {
- update!(update_with_channel_recipient_remove, event);
+ Event::ChannelRecipientRemove(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -235,8 +225,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::ChannelUpdate(event) => {
- update!(update_with_channel_update, event);
+ Event::ChannelUpdate(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -254,7 +244,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
}}
},
- Event::GuildBanAdd(event) => {
+ Event::GuildBanAdd(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -263,7 +253,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::GuildBanRemove(event) => {
+ Event::GuildBanRemove(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -272,7 +262,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::GuildCreate(event) => {
+ Event::GuildCreate(mut event) => {
#[cfg(feature="cache")]
let _is_new = {
let cache = CACHE.read().unwrap();
@@ -280,7 +270,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
!cache.unavailable_guilds.contains(&event.guild.id)
};
- update!(update_with_guild_create, event);
+ update!(event);
#[cfg(feature = "cache")]
{
@@ -321,8 +311,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
}}
},
- Event::GuildDelete(event) => {
- let _full = update!(update_with_guild_delete, event);
+ Event::GuildDelete(mut event) => {
+ let _full = update!(event);
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -338,8 +328,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
}}
},
- Event::GuildEmojisUpdate(event) => {
- update!(update_with_guild_emojis_update, event);
+ Event::GuildEmojisUpdate(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -353,7 +343,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::GuildIntegrationsUpdate(event) => {
+ Event::GuildIntegrationsUpdate(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -363,7 +353,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
},
Event::GuildMemberAdd(mut event) => {
- update!(update_with_guild_member_add, @event);
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -377,8 +367,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::GuildMemberRemove(event) => {
- let _member = update!(update_with_guild_member_remove, event);
+ Event::GuildMemberRemove(mut event) => {
+ let _member = update!(event);
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -394,8 +384,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
}}
},
- Event::GuildMemberUpdate(event) => {
- let _before = update!(update_with_guild_member_update, event);
+ Event::GuildMemberUpdate(mut event) => {
+ let _before = update!(event);
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -422,8 +412,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
}
}
},
- Event::GuildMembersChunk(event) => {
- update!(update_with_guild_members_chunk, event);
+ Event::GuildMembersChunk(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -437,8 +427,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::GuildRoleCreate(event) => {
- update!(update_with_guild_role_create, event);
+ Event::GuildRoleCreate(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -448,8 +438,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::GuildRoleDelete(event) => {
- let _role = update!(update_with_guild_role_delete, event);
+ Event::GuildRoleDelete(mut event) => {
+ let _role = update!(event);
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -465,8 +455,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
}}
},
- Event::GuildRoleUpdate(event) => {
- let _before = update!(update_with_guild_role_update, event);
+ Event::GuildRoleUpdate(mut event) => {
+ let _before = update!(event);
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -482,8 +472,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
}}
},
- Event::GuildUnavailable(event) => {
- update!(update_with_guild_unavailable, event);
+ Event::GuildUnavailable(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -493,8 +483,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::GuildUpdate(event) => {
- update!(update_with_guild_update, event);
+ Event::GuildUpdate(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -521,7 +511,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
},
// Already handled by the framework check macro
Event::MessageCreate(_) => {},
- Event::MessageDeleteBulk(event) => {
+ Event::MessageDeleteBulk(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -534,7 +524,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::MessageDelete(event) => {
+ Event::MessageDelete(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -547,7 +537,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::MessageUpdate(event) => {
+ Event::MessageUpdate(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -556,8 +546,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::PresencesReplace(event) => {
- update!(update_with_presences_replace, event);
+ Event::PresencesReplace(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -568,7 +558,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
},
Event::PresenceUpdate(mut event) => {
- update!(update_with_presence_update, @event);
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -578,7 +568,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::ReactionAdd(event) => {
+ Event::ReactionAdd(mut event) => {
let h = event_handler.clone();
let context = context(conn, data, tokio_handle);
tokio_handle.spawn_fn(move || {
@@ -586,7 +576,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::ReactionRemove(event) => {
+ Event::ReactionRemove(mut event) => {
let h = event_handler.clone();
let context = context(conn, data, tokio_handle);
tokio_handle.spawn_fn(move || {
@@ -594,7 +584,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::ReactionRemoveAll(event) => {
+ Event::ReactionRemoveAll(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -607,8 +597,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::Ready(event) => {
- update!(update_with_ready, event);
+ Event::Ready(mut event) => {
+ update!(event);
feature_cache!{
{
@@ -635,7 +625,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
}
}
},
- Event::Resumed(event) => {
+ Event::Resumed(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -644,7 +634,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::TypingStart(event) => {
+ Event::TypingStart(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -653,7 +643,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::Unknown(event) => {
+ Event::Unknown(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -662,14 +652,14 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::UserUpdate(event) => {
- let _before = update!(update_with_user_update, event);
+ Event::UserUpdate(mut event) => {
+ let _before = update!(event);
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
feature_cache! {{
tokio_handle.spawn_fn(move || {
- h.on_user_update(context, _before, event.current_user);
+ h.on_user_update(context, _before.unwrap(), event.current_user);
Ok(())
});
} else {
@@ -679,7 +669,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
});
}}
},
- Event::VoiceServerUpdate(event) => {
+ Event::VoiceServerUpdate(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
@@ -688,8 +678,8 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::VoiceStateUpdate(event) => {
- update!(update_with_voice_state_update, event);
+ Event::VoiceStateUpdate(mut event) => {
+ update!(event);
let context = context(conn, data, tokio_handle);
@@ -703,7 +693,7 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
Ok(())
});
},
- Event::WebhookUpdate(event) => {
+ Event::WebhookUpdate(mut event) => {
let context = context(conn, data, tokio_handle);
let h = event_handler.clone();
diff --git a/src/lib.rs b/src/lib.rs
index 066d926..75774c2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -167,8 +167,6 @@ pub use client::Client;
#[cfg(feature = "cache")]
use cache::Cache;
#[cfg(feature = "cache")]
-pub(crate) use cache::CacheEventsImpl;
-#[cfg(feature = "cache")]
use std::sync::RwLock;
#[cfg(feature = "cache")]
diff --git a/src/model/event.rs b/src/model/event.rs
index 22cf649..8cdea1f 100644
--- a/src/model/event.rs
+++ b/src/model/event.rs
@@ -10,6 +10,14 @@ use super::utils::deserialize_emojis;
use super::*;
use constants::VoiceOpCode;
use internal::prelude::*;
+#[cfg(feature = "cache")]
+use cache::{Cache, CacheUpdate};
+#[cfg(feature = "cache")]
+use internal::RwLockExt;
+#[cfg(feature = "cache")]
+use std::mem;
+#[cfg(feature = "cache")]
+use std::collections::hash_map::Entry;
#[cfg(feature = "gateway")]
use constants::OpCode;
@@ -42,11 +50,108 @@ impl<'de> Deserialize<'de> for ChannelCreateEvent {
}
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for ChannelCreateEvent {
+ type Output = Channel;
+
+ fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> {
+ match self.channel {
+ Channel::Group(ref group) => {
+ let group = group.clone();
+
+ let channel_id = group.with_mut(|writer| {
+ for (recipient_id, recipient) in &mut writer.recipients {
+ cache.update_user_entry(&recipient.read().unwrap());
+
+ *recipient = cache.users[recipient_id].clone();
+ }
+
+ writer.channel_id
+ });
+
+ let ch = cache.groups.insert(channel_id, group);
+
+ ch.map(Channel::Group)
+ },
+ Channel::Guild(ref channel) => {
+ let (guild_id, channel_id) = channel.with(|channel| (channel.guild_id, channel.id));
+
+ cache.channels.insert(channel_id, channel.clone());
+
+ cache.guilds
+ .get_mut(&guild_id)
+ .and_then(|guild| {
+ guild.with_mut(|guild| {
+ guild.channels.insert(channel_id, channel.clone())
+ })
+ })
+ .map(Channel::Guild)
+ },
+ Channel::Private(ref channel) => {
+ if let Some(channel) = cache.private_channels.get(&channel.with(|c| c.id)) {
+ return Some(Channel::Private((*channel).clone()));
+ }
+
+ let channel = channel.clone();
+
+ let id = channel.with_mut(|writer| {
+ let user_id = writer.recipient.with_mut(|user| {
+ cache.update_user_entry(&user);
+
+ user.id
+ });
+
+ writer.recipient = cache.users[&user_id].clone();
+ writer.id
+ });
+
+ let ch = cache.private_channels.insert(id, channel.clone());
+ ch.map(Channel::Private)
+ },
+ Channel::Category(ref category) => {
+ cache.categories
+ .insert(category.read().unwrap().id, category.clone())
+ .map(Channel::Category)
+ },
+ }
+ }
+}
+
#[derive(Clone, Debug)]
pub struct ChannelDeleteEvent {
pub channel: Channel,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for ChannelDeleteEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ match self.channel {
+ Channel::Guild(ref channel) => {
+ let (guild_id, channel_id) = channel.with(|channel| (channel.guild_id, channel.id));
+
+ cache.channels.remove(&channel_id);
+
+ cache.guilds.get_mut(&guild_id).and_then(|guild| {
+ guild.with_mut(|g| g.channels.remove(&channel_id))
+ });
+ },
+ Channel::Category(ref category) => {
+ let channel_id = category.with(|cat| cat.id);
+
+ cache.categories.remove(&channel_id);
+ },
+ // We ignore these two due to the fact that the delete event for dms/groups
+ // will _not_ fire anymore.
+ Channel::Private(_) |
+ Channel::Group(_) => unreachable!(),
+ };
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for ChannelDeleteEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
Ok(Self {
@@ -61,23 +166,149 @@ pub struct ChannelPinsUpdateEvent {
pub last_pin_timestamp: Option<DateTime<FixedOffset>>,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for ChannelPinsUpdateEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ if let Some(channel) = cache.channels.get(&self.channel_id) {
+ channel.with_mut(|c| {
+ c.last_pin_timestamp = self.last_pin_timestamp;
+ });
+
+ return None;
+ }
+
+ if let Some(channel) = cache.private_channels.get_mut(&self.channel_id) {
+ channel.with_mut(|c| {
+ c.last_pin_timestamp = self.last_pin_timestamp;
+ });
+
+ return None;
+ }
+
+ if let Some(group) = cache.groups.get_mut(&self.channel_id) {
+ group.with_mut(|c| {
+ c.last_pin_timestamp = self.last_pin_timestamp;
+ });
+
+ return None;
+ }
+
+ None
+ }
+}
+
+
#[derive(Clone, Debug, Deserialize)]
pub struct ChannelRecipientAddEvent {
pub channel_id: ChannelId,
pub user: User,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for ChannelRecipientAddEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ cache.update_user_entry(&self.user);
+ let user = cache.users[&self.user.id].clone();
+
+ cache.groups.get_mut(&self.channel_id).map(|group| {
+ group.write().unwrap().recipients.insert(
+ self.user.id,
+ user,
+ );
+ });
+
+ None
+ }
+}
+
+
#[derive(Clone, Debug, Deserialize)]
pub struct ChannelRecipientRemoveEvent {
pub channel_id: ChannelId,
pub user: User,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for ChannelRecipientRemoveEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ cache.groups.get_mut(&self.channel_id).map(|group| {
+ group.with_mut(|g| g.recipients.remove(&self.user.id))
+ });
+
+ None
+ }
+}
+
+
+
#[derive(Clone, Debug)]
pub struct ChannelUpdateEvent {
pub channel: Channel,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for ChannelUpdateEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ match self.channel {
+ Channel::Group(ref group) => {
+ let (ch_id, no_recipients) =
+ group.with(|g| (g.channel_id, g.recipients.is_empty()));
+
+ match cache.groups.entry(ch_id) {
+ Entry::Vacant(e) => {
+ e.insert(group.clone());
+ },
+ Entry::Occupied(mut e) => {
+ let mut dest = e.get_mut().write().unwrap();
+
+ if no_recipients {
+ let recipients = mem::replace(&mut dest.recipients, HashMap::new());
+
+ dest.clone_from(&group.read().unwrap());
+
+ dest.recipients = recipients;
+ } else {
+ dest.clone_from(&group.read().unwrap());
+ }
+ },
+ }
+ },
+ Channel::Guild(ref channel) => {
+ let (guild_id, channel_id) = channel.with(|channel| (channel.guild_id, channel.id));
+
+ cache.channels.insert(channel_id, channel.clone());
+ cache.guilds.get_mut(&guild_id).map(|guild| {
+ guild.with_mut(
+ |g| g.channels.insert(channel_id, channel.clone()),
+ )
+ });
+ },
+ Channel::Private(ref channel) => {
+ cache.private_channels
+ .get_mut(&channel.read().unwrap().id)
+ .map(|private| private.clone_from(channel));
+ },
+ Channel::Category(ref category) => {
+ cache.categories.get_mut(&category.read().unwrap().id).map(
+ |c| {
+ c.clone_from(category)
+ },
+ );
+ },
+ }
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for ChannelUpdateEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
Ok(Self {
@@ -92,6 +323,7 @@ pub struct GuildBanAddEvent {
pub user: User,
}
+
#[derive(Clone, Debug, Deserialize)]
pub struct GuildBanRemoveEvent {
pub guild_id: GuildId,
@@ -103,6 +335,32 @@ pub struct GuildCreateEvent {
pub guild: Guild,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildCreateEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ cache.unavailable_guilds.remove(&self.guild.id);
+
+ let mut guild = self.guild.clone();
+
+ for (user_id, member) in &mut guild.members {
+ cache.update_user_entry(&member.user.read().unwrap());
+ let user = cache.users[user_id].clone();
+
+ member.user = user.clone();
+ }
+
+ cache.channels.extend(guild.channels.clone());
+ cache.guilds.insert(
+ self.guild.id,
+ Arc::new(RwLock::new(guild)),
+ );
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for GuildCreateEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
Ok(Self {
@@ -116,6 +374,22 @@ pub struct GuildDeleteEvent {
pub guild: PartialGuild,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildDeleteEvent {
+ type Output = Arc<RwLock<Guild>>;
+
+ fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> {
+ // Remove channel entries for the guild if the guild is found.
+ cache.guilds.remove(&self.guild.id).map(|guild| {
+ for channel_id in guild.write().unwrap().channels.keys() {
+ cache.channels.remove(channel_id);
+ }
+
+ guild
+ })
+ }
+}
+
impl<'de> Deserialize<'de> for GuildDeleteEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
Ok(Self {
@@ -131,6 +405,19 @@ pub struct GuildEmojisUpdateEvent {
pub guild_id: GuildId,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildEmojisUpdateEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ cache.guilds.get_mut(&self.guild_id).map(|guild| {
+ guild.with_mut(|g| g.emojis.extend(self.emojis.clone()))
+ });
+
+ None
+ }
+}
+
#[derive(Clone, Debug, Deserialize)]
pub struct GuildIntegrationsUpdateEvent {
pub guild_id: GuildId,
@@ -142,6 +429,29 @@ pub struct GuildMemberAddEvent {
pub member: Member,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildMemberAddEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ let user_id = self.member.user.with(|u| u.id);
+ cache.update_user_entry(&self.member.user.read().unwrap());
+
+ // Always safe due to being inserted above.
+ self.member.user = cache.users[&user_id].clone();
+
+ cache.guilds.get_mut(&self.guild_id).map(|guild| {
+ guild.with_mut(|guild| {
+ guild.member_count += 1;
+ guild.members.insert(user_id, self.member.clone());
+ })
+ });
+
+ None
+ }
+}
+
+
impl<'de> Deserialize<'de> for GuildMemberAddEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
let map = JsonMap::deserialize(deserializer)?;
@@ -166,6 +476,20 @@ pub struct GuildMemberRemoveEvent {
pub user: User,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildMemberRemoveEvent {
+ type Output = Member;
+
+ fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> {
+ cache.guilds.get_mut(&self.guild_id).and_then(|guild| {
+ guild.with_mut(|guild| {
+ guild.member_count -= 1;
+ guild.members.remove(&self.user.id)
+ })
+ })
+ }
+}
+
#[derive(Clone, Debug, Deserialize)]
pub struct GuildMemberUpdateEvent {
pub guild_id: GuildId,
@@ -174,12 +498,77 @@ pub struct GuildMemberUpdateEvent {
pub user: User,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildMemberUpdateEvent {
+ type Output = Member;
+
+ fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> {
+ cache.update_user_entry(&self.user);
+
+ if let Some(guild) = cache.guilds.get_mut(&self.guild_id) {
+ let mut guild = guild.write().unwrap();
+
+ let mut found = false;
+
+ let item = if let Some(member) = guild.members.get_mut(&self.user.id) {
+ let item = Some(member.clone());
+
+ member.nick.clone_from(&self.nick);
+ member.roles.clone_from(&self.roles);
+ member.user.write().unwrap().clone_from(&self.user);
+
+ found = true;
+
+ item
+ } else {
+ None
+ };
+
+ if !found {
+ guild.members.insert(
+ self.user.id,
+ Member {
+ deaf: false,
+ guild_id: self.guild_id,
+ joined_at: None,
+ mute: false,
+ nick: self.nick.clone(),
+ roles: self.roles.clone(),
+ user: Arc::new(RwLock::new(self.user.clone())),
+ },
+ );
+ }
+
+ item
+ } else {
+ None
+ }
+ }
+}
+
#[derive(Clone, Debug)]
pub struct GuildMembersChunkEvent {
pub guild_id: GuildId,
pub members: HashMap<UserId, Member>,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildMembersChunkEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ for member in self.members.values() {
+ cache.update_user_entry(&member.user.read().unwrap());
+ }
+
+ cache.guilds.get_mut(&self.guild_id).map(|guild| {
+ guild.with_mut(|g| g.members.extend(self.members.clone()))
+ });
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for GuildMembersChunkEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
let mut map = JsonMap::deserialize(deserializer)?;
@@ -219,29 +608,105 @@ pub struct GuildRoleCreateEvent {
pub role: Role,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildRoleCreateEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ cache.guilds.get_mut(&self.guild_id).map(|guild| {
+ guild.write().unwrap().roles.insert(
+ self.role.id,
+ self.role.clone(),
+ )
+ });
+
+ None
+ }
+}
+
#[derive(Clone, Debug, Deserialize)]
pub struct GuildRoleDeleteEvent {
pub guild_id: GuildId,
pub role_id: RoleId,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildRoleDeleteEvent {
+ type Output = Role;
+
+ fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> {
+ cache.guilds.get_mut(&self.guild_id).and_then(|guild| {
+ guild.with_mut(|g| g.roles.remove(&self.role_id))
+ })
+ }
+}
+
#[derive(Clone, Debug, Deserialize)]
pub struct GuildRoleUpdateEvent {
pub guild_id: GuildId,
pub role: Role,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildRoleUpdateEvent {
+ type Output = Role;
+
+ fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> {
+ cache.guilds.get_mut(&self.guild_id).and_then(|guild| {
+ guild.with_mut(|g| {
+ g.roles.get_mut(&self.role.id).map(|role| {
+ mem::replace(role, self.role.clone())
+ })
+ })
+ })
+ }
+}
+
#[derive(Clone, Debug, Deserialize)]
pub struct GuildUnavailableEvent {
#[serde(rename = "id")]
pub guild_id: GuildId,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildUnavailableEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ cache.unavailable_guilds.insert(self.guild_id);
+ cache.guilds.remove(&self.guild_id);
+
+ None
+ }
+}
+
#[derive(Clone, Debug)]
pub struct GuildUpdateEvent {
pub guild: PartialGuild,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for GuildUpdateEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ cache.guilds.get_mut(&self.guild.id).map(|guild| {
+ let mut guild = guild.write().unwrap();
+
+ guild.afk_timeout = self.guild.afk_timeout;
+ guild.afk_channel_id.clone_from(&self.guild.afk_channel_id);
+ guild.icon.clone_from(&self.guild.icon);
+ guild.name.clone_from(&self.guild.name);
+ guild.owner_id.clone_from(&self.guild.owner_id);
+ guild.region.clone_from(&self.guild.region);
+ guild.roles.clone_from(&self.guild.roles);
+ guild.verification_level = self.guild.verification_level;
+ });
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for GuildUpdateEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
Ok(Self {
@@ -302,6 +767,45 @@ pub struct PresenceUpdateEvent {
pub roles: Option<Vec<RoleId>>,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for PresenceUpdateEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ let user_id = self.presence.user_id;
+
+ if let Some(user) = self.presence.user.as_mut() {
+ cache.update_user_entry(&user.read().unwrap());
+ *user = cache.users[&user_id].clone();
+ }
+
+ if let Some(guild_id) = self.guild_id {
+ if let Some(guild) = cache.guilds.get_mut(&guild_id) {
+ let mut guild = guild.write().unwrap();
+
+ // If the member went offline, remove them from the presence list.
+ if self.presence.status == OnlineStatus::Offline {
+ guild.presences.remove(&self.presence.user_id);
+ } else {
+ guild.presences.insert(
+ self.presence.user_id,
+ self.presence.clone(),
+ );
+ }
+ }
+ } else if self.presence.status == OnlineStatus::Offline {
+ cache.presences.remove(&self.presence.user_id);
+ } else {
+ cache.presences.insert(
+ self.presence.user_id,
+ self.presence.clone(),
+ );
+ }
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for PresenceUpdateEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
let mut map = JsonMap::deserialize(deserializer)?;
@@ -339,6 +843,25 @@ pub struct PresencesReplaceEvent {
pub presences: Vec<Presence>,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for PresencesReplaceEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ cache.presences.extend({
+ let mut p: HashMap<UserId, Presence> = HashMap::default();
+
+ for presence in &self.presences {
+ p.insert(presence.user_id, presence.clone());
+ }
+
+ p
+ });
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for PresencesReplaceEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
let presences: Vec<Presence> = Deserialize::deserialize(deserializer)?;
@@ -387,6 +910,46 @@ pub struct ReadyEvent {
pub ready: Ready,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for ReadyEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ let mut ready = self.ready.clone();
+
+ for guild in ready.guilds {
+ match guild {
+ GuildStatus::Offline(unavailable) => {
+ cache.guilds.remove(&unavailable.id);
+ cache.unavailable_guilds.insert(unavailable.id);
+ },
+ GuildStatus::OnlineGuild(guild) => {
+ cache.unavailable_guilds.remove(&guild.id);
+ cache.guilds.insert(guild.id, Arc::new(RwLock::new(guild)));
+ },
+ GuildStatus::OnlinePartialGuild(_) => {},
+ }
+ }
+
+ // `ready.private_channels` will always be empty, and possibly be removed in the future.
+ // So don't handle it at all.
+
+ for (user_id, presence) in &mut ready.presences {
+ if let Some(ref user) = presence.user {
+ cache.update_user_entry(&user.read().unwrap());
+ }
+
+ presence.user = cache.users.get(user_id).cloned();
+ }
+
+ cache.presences.extend(ready.presences);
+ cache.shard_count = ready.shard.map_or(1, |s| s[1]);
+ cache.user = ready.user;
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for ReadyEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
Ok(Self {
@@ -419,6 +982,15 @@ pub struct UserUpdateEvent {
pub current_user: CurrentUser,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for UserUpdateEvent {
+ type Output = CurrentUser;
+
+ fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> {
+ Some(mem::replace(&mut cache.user, self.current_user.clone()))
+ }
+}
+
impl<'de> Deserialize<'de> for UserUpdateEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
Ok(Self {
@@ -435,12 +1007,51 @@ pub struct VoiceServerUpdateEvent {
pub token: String,
}
+
#[derive(Clone, Debug)]
pub struct VoiceStateUpdateEvent {
pub guild_id: Option<GuildId>,
pub voice_state: VoiceState,
}
+#[cfg(feature = "cache")]
+impl CacheUpdate for VoiceStateUpdateEvent {
+ type Output = ();
+
+ fn update(&mut self, cache: &mut Cache) -> Option<()> {
+ if let Some(guild_id) = self.guild_id {
+ if let Some(guild) = cache.guilds.get_mut(&guild_id) {
+ let mut guild = guild.write().unwrap();
+
+ if self.voice_state.channel_id.is_some() {
+ // Update or add to the voice state list
+ {
+ let finding = guild.voice_states.get_mut(&self.voice_state.user_id);
+
+ if let Some(srv_state) = finding {
+ srv_state.clone_from(&self.voice_state);
+
+ return None;
+ }
+ }
+
+ guild.voice_states.insert(
+ self.voice_state.user_id,
+ self.voice_state.clone(),
+ );
+ } else {
+ // Remove the user from the voice state list
+ guild.voice_states.remove(&self.voice_state.user_id);
+ }
+ }
+
+ return None;
+ }
+
+ None
+ }
+}
+
impl<'de> Deserialize<'de> for VoiceStateUpdateEvent {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
let map = JsonMap::deserialize(deserializer)?;