diff options
| author | acdenisSK <[email protected]> | 2017-11-04 20:06:40 +0100 |
|---|---|---|
| committer | acdenisSK <[email protected]> | 2017-11-04 20:06:40 +0100 |
| commit | 0bd519f4ef9784d0fb5663d74db0d567f0bb1ae5 (patch) | |
| tree | cc2a6f44e97e42420507964dab4662fcccd9beb3 /src/model | |
| parent | Fix Help-Commands to list all eligible commands in DMs. (#212) (diff) | |
| parent | Bump to v0.4.3 (diff) | |
| download | serenity-0bd519f4ef9784d0fb5663d74db0d567f0bb1ae5.tar.xz serenity-0bd519f4ef9784d0fb5663d74db0d567f0bb1ae5.zip | |
Merge v0.4.3
Diffstat (limited to 'src/model')
| -rw-r--r-- | src/model/channel/guild_channel.rs | 2 | ||||
| -rw-r--r-- | src/model/error.rs | 8 | ||||
| -rw-r--r-- | src/model/guild/member.rs | 19 | ||||
| -rw-r--r-- | src/model/guild/mod.rs | 108 | ||||
| -rw-r--r-- | src/model/user.rs | 12 | ||||
| -rw-r--r-- | src/model/utils.rs | 5 |
6 files changed, 101 insertions, 53 deletions
diff --git a/src/model/channel/guild_channel.rs b/src/model/channel/guild_channel.rs index 8fc9abb..76cea47 100644 --- a/src/model/channel/guild_channel.rs +++ b/src/model/channel/guild_channel.rs @@ -512,7 +512,7 @@ impl GuildChannel { pub fn permissions_for<U: Into<UserId>>(&self, user_id: U) -> Result<Permissions> { self.guild() .ok_or_else(|| Error::Model(ModelError::GuildNotFound)) - .map(|g| g.read().permissions_for(self.id, user_id)) + .map(|g| g.read().permissions_in(self.id, user_id)) } /// Pins a [`Message`] to the channel. diff --git a/src/model/error.rs b/src/model/error.rs index 835678a..c2f568b 100644 --- a/src/model/error.rs +++ b/src/model/error.rs @@ -13,10 +13,10 @@ use super::Permissions; /// re-ban all members with an odd discriminator: /// /// ```rust,no_run -/// # #[cfg(feature="client")] +/// # #[cfg(all(feature = "client", feature = "model"))] /// # use std::error::Error; /// # -/// # #[cfg(feature="client")] +/// # #[cfg(all(feature = "client", feature = "model"))] /// # fn try_main() -> Result<(), Box<Error>> { /// use serenity::prelude::*; /// use serenity::model::*; @@ -53,12 +53,12 @@ use super::Permissions; /// # Ok(()) /// # } /// # -/// # #[cfg(feature="client")] +/// # #[cfg(all(feature = "client", feature = "model"))] /// # fn main() { /// # try_main().unwrap(); /// # } /// # -/// # #[cfg(not(feature="client"))] +/// # #[cfg(not(all(feature="client", feature = "model")))] /// # fn main() { } /// ``` /// diff --git a/src/model/guild/member.rs b/src/model/guild/member.rs index 7420faa..e5feee7 100644 --- a/src/model/guild/member.rs +++ b/src/model/guild/member.rs @@ -14,6 +14,7 @@ use utils::Colour; #[cfg(all(feature = "cache", feature = "model"))] use {CACHE, http, utils}; +/// A trait for allowing both u8 or &str or (u8, &str) to be passed into the `ban` methods in `Guild` and `Member`. pub trait BanOptions { fn dmd(&self) -> u8 { 0 } fn reason(&self) -> &str { "" } @@ -275,7 +276,7 @@ impl Member { .get(&self.guild_id) .map(|guild| guild.read().has_perms(req)); - if let Some(Ok(false)) = has_perms { + if let Some(false) = has_perms { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -283,7 +284,7 @@ impl Member { self.guild_id.kick(self.user.read().id) } - /// Returns the permissions for the member. + /// Returns the guild-level permissions for the member. /// /// # Examples /// @@ -310,19 +311,9 @@ impl Member { None => return Err(From::from(ModelError::GuildNotFound)), }; - let guild = guild.read(); + let reader = guild.read().unwrap(); - let default_channel = match guild.default_channel(self.user.read().id) { - Some(dc) => dc, - None => return Err(From::from(ModelError::ItemMissing)), - }; - - let default_channel_reader = default_channel.read(); - - Ok( - guild - .permissions_for(default_channel_reader.id, self.user.read().id), - ) + Ok(reader.member_permissions(self.user.read().unwrap().id)) } /// Removes a [`Role`] from the member, editing its roles in-place if the diff --git a/src/model/guild/mod.rs b/src/model/guild/mod.rs index 8483e75..ab74109 100644 --- a/src/model/guild/mod.rs +++ b/src/model/guild/mod.rs @@ -135,8 +135,8 @@ impl Guild { /// returns `None`) pub fn default_channel(&self, uid: UserId) -> Option<Arc<RwLock<GuildChannel>>> { for (cid, channel) in &self.channels { - if self.permissions_for(*cid, uid).read_messages() { - return Some(channel.clone()); + if self.permissions_in(*cid, uid).read_messages() { + return Some(channel.read().unwrap().clone()); } } @@ -151,8 +151,8 @@ impl Guild { pub fn default_channel_guaranteed(&self) -> Option<Arc<RwLock<GuildChannel>>> { for (cid, channel) in &self.channels { for memid in self.members.keys() { - if self.permissions_for(*cid, *memid).read_messages() { - return Some(channel.clone()); + if self.permissions_in(*cid, *memid).read_messages() { + return Some(channel.read().unwrap().clone()); } } } @@ -161,21 +161,13 @@ impl Guild { } #[cfg(feature = "cache")] - fn has_perms(&self, mut permissions: Permissions) -> Result<bool> { - let member = match self.members.get(&CACHE.read().user.id) { - Some(member) => member, - None => return Err(Error::Model(ModelError::ItemMissing)), - }; - - let default_channel = match self.default_channel(member.user.read().id) { - Some(dc) => dc, - None => return Err(Error::Model(ModelError::ItemMissing)), - }; + fn has_perms(&self, mut permissions: Permissions) -> bool { + let user_id = CACHE.read().unwrap().user.id; - let perms = self.permissions_for(default_channel.read().id, member.user.read().id); + let perms = self.member_permissions(user_id); permissions.remove(perms); - Ok(permissions.is_empty()) + permissions.is_empty() } /// Ban a [`User`] from the guild. All messages by the @@ -213,7 +205,7 @@ impl Guild { { let req = Permissions::BAN_MEMBERS; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -238,7 +230,7 @@ impl Guild { { let req = Permissions::BAN_MEMBERS; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -325,7 +317,7 @@ impl Guild { { let req = Permissions::MANAGE_CHANNELS; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -396,7 +388,7 @@ impl Guild { { let req = Permissions::MANAGE_ROLES; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -498,7 +490,7 @@ impl Guild { { let req = Permissions::MANAGE_GUILD; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -578,7 +570,7 @@ impl Guild { { let req = Permissions::CHANGE_NICKNAME; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -660,7 +652,7 @@ impl Guild { { let req = Permissions::MANAGE_GUILD; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -1007,6 +999,57 @@ impl Guild { } } + /// Calculate a [`Member`]'s permissions in the guild. + /// + /// [`Member`]: struct.Member.html + pub fn member_permissions<U>(&self, user_id: U) -> Permissions + where U: Into<UserId> { + let user_id = user_id.into(); + + if user_id == self.owner_id { + return Permissions::all(); + } + + let everyone = match self.roles.get(&RoleId(self.id.0)) { + Some(everyone) => everyone, + None => { + error!( + "(╯°□°)╯︵ ┻━┻ @everyone role ({}) missing in '{}'", + self.id, + self.name, + ); + + return Permissions::empty(); + }, + }; + + let member = match self.members.get(&user_id) { + Some(member) => member, + None => return everyone.permissions, + }; + + let mut permissions = everyone.permissions; + + for role in &member.roles { + if let Some(role) = self.roles.get(&role) { + if role.permissions.contains(Permissions::ADMINISTRATOR) { + return Permissions::all(); + } + + permissions |= role.permissions; + } else { + warn!( + "(╯°□°)╯︵ ┻━┻ {} on {} has non-existent role {:?}", + member.user.read().unwrap().id, + self.id, + role, + ); + } + } + + permissions + } + /// Moves a member to a specific voice channel. /// /// Requires the [Move Members] permission. @@ -1018,10 +1061,21 @@ impl Guild { self.id.move_member(user_id, channel_id) } + /// Alias for [`permissions_in`]. + /// + /// [`permissions_in`]: #method.permissions_in + #[deprecated(since = "0.4.3", + note = "This will serve a different purpose in 0.5")] + #[inline] + pub fn permissions_for<C, U>(&self, channel_id: C, user_id: U) + -> Permissions where C: Into<ChannelId>, U: Into<UserId> { + self.permissions_in(channel_id, user_id) + } + /// Calculate a [`User`]'s permissions in a given channel in the guild. /// /// [`User`]: struct.User.html - pub fn permissions_for<C, U>(&self, channel_id: C, user_id: U) -> Permissions + pub fn permissions_in<C, U>(&self, channel_id: C, user_id: U) -> Permissions where C: Into<ChannelId>, U: Into<UserId> { let user_id = user_id.into(); @@ -1169,7 +1223,7 @@ impl Guild { { let req = Permissions::KICK_MEMBERS; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -1252,7 +1306,7 @@ impl Guild { { let req = Permissions::KICK_MEMBERS; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } @@ -1277,7 +1331,7 @@ impl Guild { { let req = Permissions::BAN_MEMBERS; - if !self.has_perms(req)? { + if !self.has_perms(req) { return Err(Error::Model(ModelError::InvalidPermissions(req))); } } diff --git a/src/model/user.rs b/src/model/user.rs index 7eea83e..9f36d0f 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -48,7 +48,7 @@ impl CurrentUser { /// Print out the current user's avatar url if one is set: /// /// ```rust,no_run - /// # use serenity::client::CACHE; + /// # use serenity::CACHE; /// # /// # let cache = CACHE.read(); /// # @@ -127,7 +127,7 @@ impl CurrentUser { /// Print out the names of all guilds the current user is in: /// /// ```rust,no_run - /// # use serenity::client::CACHE; + /// # use serenity::CACHE; /// # /// # let cache = CACHE.read(); /// # @@ -155,7 +155,7 @@ impl CurrentUser { /// Get the invite url with no permissions set: /// /// ```rust,no_run - /// # use serenity::client::CACHE; + /// # use serenity::CACHE; /// # /// # let mut cache = CACHE.write(); /// @@ -178,7 +178,7 @@ impl CurrentUser { /// Get the invite url with some basic permissions set: /// /// ```rust,no_run - /// # use serenity::client::CACHE; + /// # use serenity::CACHE; /// # /// # let mut cache = CACHE.write(); /// @@ -234,7 +234,7 @@ impl CurrentUser { /// Print out the current user's static avatar url if one is set: /// /// ```rust,no_run - /// # use serenity::client::CACHE; + /// # use serenity::CACHE; /// # /// # let cache = CACHE.read(); /// # @@ -258,7 +258,7 @@ impl CurrentUser { /// Print out the current user's distinct identifier (e.g., Username#1234): /// /// ```rust,no_run - /// # use serenity::client::CACHE; + /// # use serenity::CACHE; /// # /// # let cache = CACHE.read(); /// # diff --git a/src/model/utils.rs b/src/model/utils.rs index 62ecc4e..d366e5f 100644 --- a/src/model/utils.rs +++ b/src/model/utils.rs @@ -178,7 +178,10 @@ pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Re None => return Err(Error::Model(ModelError::ItemMissing)), }; - let perms = guild.read().permissions_for(channel_id, current_user.id); + let perms = guild + .read() + .unwrap() + .permissions_in(channel_id, current_user.id); permissions.remove(perms); |