diff options
| author | acdenisSK <[email protected]> | 2017-08-10 09:06:28 +0200 |
|---|---|---|
| committer | acdenisSK <[email protected]> | 2017-08-10 09:06:56 +0200 |
| commit | eee857a855831851599e5196750b27b26151eb16 (patch) | |
| tree | 12c87e91559b682b4f5a27d26fa423e325bc2b28 /src/cache | |
| parent | Remove the `I` bound for the language param and fix `push_mono_safe` (diff) | |
| download | serenity-eee857a855831851599e5196750b27b26151eb16.tar.xz serenity-eee857a855831851599e5196750b27b26151eb16.zip | |
Split event handling in the cache to a trait
note: This trait might become like `framework::Framework` in the future.
Diffstat (limited to 'src/cache')
| -rw-r--r-- | src/cache/cache_events_impl.rs | 540 | ||||
| -rw-r--r-- | src/cache/mod.rs | 477 |
2 files changed, 544 insertions, 473 deletions
diff --git a/src/cache/cache_events_impl.rs b/src/cache/cache_events_impl.rs new file mode 100644 index 0000000..308a3b5 --- /dev/null +++ b/src/cache/cache_events_impl.rs @@ -0,0 +1,540 @@ +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::*; + +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); + + fn update_user_entry(&mut self, user: &User); +} + +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 = { + let writer = group.write().unwrap(); + + for (recipient_id, recipient) in &mut group.write().unwrap().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) = { + let channel = channel.read().unwrap(); + + (channel.guild_id, channel.id) + }; + + self.channels.insert(channel_id, channel.clone()); + + self.guilds + .get_mut(&guild_id) + .and_then(|guild| { + guild + .write() + .unwrap() + .channels + .insert(channel_id, channel.clone()) + }) + .map(Channel::Guild) + }, + Channel::Private(ref channel) => { + let channel = channel.clone(); + + let mut channel_writer = channel.write().unwrap(); + + let user_id = { + let user_reader = channel_writer.recipient.read().unwrap(); + + self.update_user_entry(&user_reader); + + user_reader.id + }; + + channel_writer.recipient = self.users[&user_id].clone(); + + let ch = self.private_channels + .insert(channel_writer.id, channel.clone()); + ch.map(Channel::Private) + }, + } + } + + fn update_with_channel_delete(&mut self, event: &ChannelDeleteEvent) { + let channel = match event.channel { + Channel::Guild(ref channel) => channel, + // We ignore these two due to the fact that the delete event for dms/groups will _not_ fire + // anymore. + Channel::Private(_) | Channel::Group(_) => unreachable!(), + }; + + let (channel_id, guild_id) = { + let channel = channel.read().unwrap(); + + (channel.id, channel.guild_id) + }; + + self.channels.remove(&channel_id); + + self.guilds + .get_mut(&guild_id) + .and_then(|guild| guild.write().unwrap().channels.remove(&channel_id)); + } + + #[allow(dead_code)] + fn update_with_channel_pins_update(&mut self, event: &ChannelPinsUpdateEvent) { + if let Some(channel) = self.channels.get(&event.channel_id) { + channel.write().unwrap().last_pin_timestamp = event.last_pin_timestamp; + + return; + } + + if let Some(channel) = self.private_channels.get_mut(&event.channel_id) { + channel.write().unwrap().last_pin_timestamp = event.last_pin_timestamp; + + return; + } + + if let Some(group) = self.groups.get_mut(&event.channel_id) { + group.write().unwrap().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.write().unwrap().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) = { + let group = group.read().unwrap(); + + (group.channel_id, group.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 (channel_id, guild_id) = { + let channel = channel.read().unwrap(); + + (channel.id, channel.guild_id) + }; + + self.channels.insert(channel_id, channel.clone()); + self.guilds.get_mut(&guild_id).map(|guild| { + guild + .write() + .unwrap() + .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)); + }, + } + } + + 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.read().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.write().unwrap().emojis.extend(event.emojis.clone()) + }); + } + + fn update_with_guild_member_add(&mut self, event: &mut GuildMemberAddEvent) { + let user_id = event.member.user.read().unwrap().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| { + let mut guild = guild.write().unwrap(); + + 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| { + let mut guild = guild.write().unwrap(); + + 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.write().unwrap().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.write().unwrap().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 + .write() + .unwrap() + .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; + } + } + + 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()))); + }, + Entry::Occupied(mut e) => { + e.get_mut().write().unwrap().clone_from(user); + }, + } + } +}
\ No newline at end of file diff --git a/src/cache/mod.rs b/src/cache/mod.rs index ad426d5..a3d0058 100644 --- a/src/cache/mod.rs +++ b/src/cache/mod.rs @@ -42,13 +42,14 @@ //! [`CACHE`]: ../struct.CACHE.html //! [`http`]: ../http/index.html -use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::default::Default; use std::sync::{Arc, RwLock}; -use std::mem; use model::*; -use model::event::*; + +mod cache_events_impl; + +pub(crate) use self::cache_events_impl::*; /// A cache of all events received over a [`Shard`], where storing at least /// some data from the event is possible. @@ -591,476 +592,6 @@ impl Cache { pub fn user<U: Into<UserId>>(&self, user_id: U) -> Option<Arc<RwLock<User>>> { self.users.get(&user_id.into()).cloned() } - - pub(crate) 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 = { - let writer = group.write().unwrap(); - - for (recipient_id, recipient) in &mut group.write().unwrap().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) = { - let channel = channel.read().unwrap(); - - (channel.guild_id, channel.id) - }; - - self.channels.insert(channel_id, channel.clone()); - - self.guilds - .get_mut(&guild_id) - .and_then(|guild| { - guild - .write() - .unwrap() - .channels - .insert(channel_id, channel.clone()) - }) - .map(Channel::Guild) - }, - Channel::Private(ref channel) => { - let channel = channel.clone(); - - let mut channel_writer = channel.write().unwrap(); - - let user_id = { - let user_reader = channel_writer.recipient.read().unwrap(); - - self.update_user_entry(&user_reader); - - user_reader.id - }; - - channel_writer.recipient = self.users[&user_id].clone(); - - let ch = self.private_channels - .insert(channel_writer.id, channel.clone()); - ch.map(Channel::Private) - }, - } - } - - pub(crate) fn update_with_channel_delete(&mut self, event: &ChannelDeleteEvent) { - // We ignore these two due to the fact that the delete event for dms/groups will _not_ fire - // anymore. - let channel = match event.channel { - Channel::Guild(ref channel) => channel, - Channel::Private(_) | Channel::Group(_) => unreachable!(), - }; - - let (channel_id, guild_id) = { - let channel = channel.read().unwrap(); - - (channel.id, channel.guild_id) - }; - - self.channels.remove(&channel_id); - - self.guilds - .get_mut(&guild_id) - .and_then(|guild| guild.write().unwrap().channels.remove(&channel_id)); - } - - #[allow(dead_code)] - pub(crate) fn update_with_channel_pins_update(&mut self, event: &ChannelPinsUpdateEvent) { - if let Some(channel) = self.channels.get(&event.channel_id) { - channel.write().unwrap().last_pin_timestamp = event.last_pin_timestamp; - - return; - } - - if let Some(channel) = self.private_channels.get_mut(&event.channel_id) { - channel.write().unwrap().last_pin_timestamp = event.last_pin_timestamp; - - return; - } - - if let Some(group) = self.groups.get_mut(&event.channel_id) { - group.write().unwrap().last_pin_timestamp = event.last_pin_timestamp; - - return; - } - } - - pub(crate) 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); - }); - } - - pub(crate) fn update_with_channel_recipient_remove(&mut self, - event: &ChannelRecipientRemoveEvent) { - self.groups.get_mut(&event.channel_id).map(|group| { - group.write().unwrap().recipients.remove(&event.user.id) - }); - } - - pub(crate) fn update_with_channel_update(&mut self, event: &ChannelUpdateEvent) { - match event.channel { - Channel::Group(ref group) => { - let (ch_id, no_recipients) = { - let group = group.read().unwrap(); - - (group.channel_id, group.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 (channel_id, guild_id) = { - let channel = channel.read().unwrap(); - - (channel.id, channel.guild_id) - }; - - self.channels.insert(channel_id, channel.clone()); - self.guilds.get_mut(&guild_id).map(|guild| { - guild - .write() - .unwrap() - .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)); - }, - } - } - - pub(crate) 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))); - } - - pub(crate) 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.read().unwrap().channels.keys() { - self.channels.remove(channel_id); - } - - guild - }) - } - - pub(crate) fn update_with_guild_emojis_update(&mut self, event: &GuildEmojisUpdateEvent) { - self.guilds.get_mut(&event.guild_id).map(|guild| { - guild.write().unwrap().emojis.extend(event.emojis.clone()) - }); - } - - pub(crate) fn update_with_guild_member_add(&mut self, event: &mut GuildMemberAddEvent) { - let user_id = event.member.user.read().unwrap().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| { - let mut guild = guild.write().unwrap(); - - guild.member_count += 1; - guild.members.insert(user_id, event.member.clone()); - }); - } - - pub(crate) fn update_with_guild_member_remove(&mut self, - event: &GuildMemberRemoveEvent) - -> Option<Member> { - self.guilds.get_mut(&event.guild_id).and_then(|guild| { - let mut guild = guild.write().unwrap(); - - guild.member_count -= 1; - guild.members.remove(&event.user.id) - }) - } - - pub(crate) 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 - } - } - - pub(crate) 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.write().unwrap().members.extend(event.members.clone()) - }); - } - - pub(crate) 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()) - }); - } - - pub(crate) fn update_with_guild_role_delete(&mut self, - event: &GuildRoleDeleteEvent) - -> Option<Role> { - self.guilds - .get_mut(&event.guild_id) - .and_then(|guild| guild.write().unwrap().roles.remove(&event.role_id)) - } - - pub(crate) fn update_with_guild_role_update(&mut self, - event: &GuildRoleUpdateEvent) - -> Option<Role> { - self.guilds.get_mut(&event.guild_id).and_then(|guild| { - guild - .write() - .unwrap() - .roles - .get_mut(&event.role.id) - .map(|role| mem::replace(role, event.role.clone())) - }) - } - - pub(crate) fn update_with_guild_unavailable(&mut self, event: &GuildUnavailableEvent) { - self.unavailable_guilds.insert(event.guild_id); - self.guilds.remove(&event.guild_id); - } - - pub(crate) 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; - }); - } - - pub(crate) 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 - }); - } - - pub(crate) 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()); - } - } - - pub(crate) 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; - } - - pub(crate) fn update_with_user_update(&mut self, event: &UserUpdateEvent) -> CurrentUser { - mem::replace(&mut self.user, event.current_user.clone()) - } - - pub(crate) 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; - } - } - - // Adds or updates a user entry in the [`users`] map with a received user. - // - // [`users`]: #structfield.users - 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()))); - }, - Entry::Occupied(mut e) => { - e.get_mut().write().unwrap().clone_from(user); - }, - } - } } impl Default for Cache { |