aboutsummaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
authoracdenisSK <[email protected]>2017-11-04 20:06:40 +0100
committeracdenisSK <[email protected]>2017-11-04 20:06:40 +0100
commit0bd519f4ef9784d0fb5663d74db0d567f0bb1ae5 (patch)
treecc2a6f44e97e42420507964dab4662fcccd9beb3 /src/model
parentFix Help-Commands to list all eligible commands in DMs. (#212) (diff)
parentBump to v0.4.3 (diff)
downloadserenity-0bd519f4ef9784d0fb5663d74db0d567f0bb1ae5.tar.xz
serenity-0bd519f4ef9784d0fb5663d74db0d567f0bb1ae5.zip
Merge v0.4.3
Diffstat (limited to 'src/model')
-rw-r--r--src/model/channel/guild_channel.rs2
-rw-r--r--src/model/error.rs8
-rw-r--r--src/model/guild/member.rs19
-rw-r--r--src/model/guild/mod.rs108
-rw-r--r--src/model/user.rs12
-rw-r--r--src/model/utils.rs5
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);