diff options
| author | Zeyla Hellyer <[email protected]> | 2017-03-20 22:05:12 -0700 |
|---|---|---|
| committer | Zeyla Hellyer <[email protected]> | 2017-03-20 22:10:15 -0700 |
| commit | cd914f503c8f0ada7473b5b56e4ad7830370ea45 (patch) | |
| tree | 3f72ca3f878efe2d96a1e64479e6e23dc7c95113 /src/model | |
| parent | Fix deadlock/panic on channel create event for private messages (diff) | |
| download | serenity-cd914f503c8f0ada7473b5b56e4ad7830370ea45.tar.xz serenity-cd914f503c8f0ada7473b5b56e4ad7830370ea45.zip | |
Fix Member methods due to variant joined_at values
Fix an issue where the library would check the Id of the guild that a
member is in by checking the Member's ID and joined_at value with those
of the members of guilds present in the cache.
Performing this check would have the issue of where a joined_at
for a member received over websocket would potentially have a varying
value than that of the same member retrieved over REST.
To fix this, attach the relevant guild's Id to the member on creation,
where the Id is available.
Fixes #68.
Diffstat (limited to 'src/model')
| -rw-r--r-- | src/model/event.rs | 12 | ||||
| -rw-r--r-- | src/model/guild.rs | 16 | ||||
| -rw-r--r-- | src/model/utils.rs | 34 |
3 files changed, 42 insertions, 20 deletions
diff --git a/src/model/event.rs b/src/model/event.rs index b9801dc..5ae6629 100644 --- a/src/model/event.rs +++ b/src/model/event.rs @@ -312,9 +312,11 @@ impl GuildMemberAddEvent { #[doc(hidden)] #[inline] pub fn decode(mut map: Map) -> Result<Self> { + let guild_id = remove(&mut map, "guild_id").and_then(GuildId::decode)?; + Ok(GuildMemberAddEvent { - guild_id: remove(&mut map, "guild_id").and_then(GuildId::decode)?, - member: Member::decode(Value::Object(map))?, + guild_id: guild_id, + member: Member::decode_guild(guild_id, Value::Object(map))?, }) } } @@ -367,9 +369,11 @@ impl GuildMembersChunkEvent { #[doc(hidden)] #[inline] pub fn decode(mut map: Map) -> Result<Self> { + let guild_id = remove(&mut map, "guild_id").and_then(GuildId::decode)?; + Ok(GuildMembersChunkEvent { - guild_id: remove(&mut map, "guild_id").and_then(GuildId::decode)?, - members: remove(&mut map, "members").and_then(decode_members)?, + guild_id: guild_id, + members: remove(&mut map, "members").and_then(|x| decode_guild_members(guild_id, x))?, }) } } diff --git a/src/model/guild.rs b/src/model/guild.rs index 8fa6d0e..b3879b1 100644 --- a/src/model/guild.rs +++ b/src/model/guild.rs @@ -1734,6 +1734,15 @@ impl Member { roles.iter().find(|r| r.colour.0 != default.0).map(|r| r.colour) } + #[doc(hidden)] + pub fn decode_guild(guild_id: GuildId, mut value: Value) -> Result<Member> { + if let Some(v) = value.as_object_mut() { + v.insert("guild_id".to_owned(), Value::U64(guild_id.0)); + } + + Self::decode(value) + } + /// Calculates the member's display name. /// /// The nickname takes priority over the member's username if it exists. @@ -1768,6 +1777,8 @@ impl Member { /// Finds the Id of the [`Guild`] that the member is in. /// + /// If some value is present in [`guild_id`], then that value is returned. + /// /// # Errors /// /// Returns a [`ClientError::GuildNotFound`] if the guild could not be @@ -1775,8 +1786,13 @@ impl Member { /// /// [`ClientError::GuildNotFound`]: ../client/enum.ClientError.html#variant.GuildNotFound /// [`Guild`]: struct.Guild.html + /// [`guild_id`]: #structfield.guild_id #[cfg(feature="cache")] pub fn find_guild(&self) -> Result<GuildId> { + if let Some(guild_id) = self.guild_id { + return Ok(guild_id); + } + for guild in CACHE.read().unwrap().guilds.values() { let guild = guild.read().unwrap(); diff --git a/src/model/utils.rs b/src/model/utils.rs index 8de7dd2..17f91f1 100644 --- a/src/model/utils.rs +++ b/src/model/utils.rs @@ -1,21 +1,6 @@ use std::collections::{BTreeMap, HashMap}; use std::sync::{Arc, RwLock}; -use super::{ - Channel, - ChannelId, - Emoji, - EmojiId, - Member, - Message, - Presence, - ReadState, - Relationship, - Role, - RoleId, - User, - UserId, - VoiceState, -}; +use super::*; use ::internal::prelude::*; use ::utils::{decode_array, into_array}; @@ -100,6 +85,23 @@ pub fn decode_members(value: Value) -> Result<HashMap<UserId, Member>> { Ok(members) } +pub fn decode_guild_members(guild_id: GuildId, value: Value) -> Result<HashMap<UserId, Member>> { + let mut members = HashMap::new(); + let member_vec = into_array(value).map(|x| x + .into_iter() + .map(|v| Member::decode_guild(guild_id, v)) + .filter_map(Result::ok) + .collect::<Vec<_>>())?; + + for member in member_vec { + let user_id = member.user.read().unwrap().id; + + members.insert(user_id, member); + } + + Ok(members) +} + // Clippy's lint is incorrect here and will result in invalid code. // // Bit more detaul: `result_unwrap_or_default` is not yet stable as of rustc |