aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2017-03-20 22:05:12 -0700
committerZeyla Hellyer <[email protected]>2017-03-20 22:10:15 -0700
commitcd914f503c8f0ada7473b5b56e4ad7830370ea45 (patch)
tree3f72ca3f878efe2d96a1e64479e6e23dc7c95113 /src
parentFix deadlock/panic on channel create event for private messages (diff)
downloadserenity-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')
-rw-r--r--src/client/rest/mod.rs9
-rw-r--r--src/ext/cache/mod.rs1
-rw-r--r--src/model/event.rs12
-rw-r--r--src/model/guild.rs16
-rw-r--r--src/model/utils.rs34
5 files changed, 49 insertions, 23 deletions
diff --git a/src/client/rest/mod.rs b/src/client/rest/mod.rs
index 6b5b055..a9dc88c 100644
--- a/src/client/rest/mod.rs
+++ b/src/client/rest/mod.rs
@@ -48,7 +48,7 @@ use std::sync::{Arc, Mutex};
use ::constants::{self, ErrorCode};
use ::internal::prelude::*;
use ::model::*;
-use ::utils::decode_array;
+use ::utils::{decode_array, into_array};
/// An method used for ratelimiting special routes.
///
@@ -1048,7 +1048,10 @@ pub fn get_guild_members(guild_id: u64, limit: Option<u64>, after: Option<u64>)
limit.unwrap_or(500),
after.unwrap_or(0));
- decode_array(serde_json::from_reader(response)?, Member::decode)
+ into_array(serde_json::from_reader(response)?)
+ .and_then(|x| x.into_iter()
+ .map(|v| Member::decode_guild(GuildId(guild_id), v))
+ .collect())
}
/// Gets the amount of users that can be pruned.
@@ -1167,7 +1170,7 @@ pub fn get_member(guild_id: u64, user_id: u64) -> Result<Member> {
guild_id,
user_id);
- Member::decode(serde_json::from_reader(response)?)
+ Member::decode_guild(GuildId(guild_id), serde_json::from_reader(response)?)
}
/// Gets a message by an Id, bots only.
diff --git a/src/ext/cache/mod.rs b/src/ext/cache/mod.rs
index 7d00b2a..ad0ef31 100644
--- a/src/ext/cache/mod.rs
+++ b/src/ext/cache/mod.rs
@@ -804,6 +804,7 @@ impl Cache {
if !found {
guild.members.insert(event.user.id, Member {
deaf: false,
+ guild_id: Some(event.guild_id),
joined_at: String::default(),
mute: false,
nick: event.nick.clone(),
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