aboutsummaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
authorLakelezz <[email protected]>2018-12-18 20:55:32 +0100
committerAlex M. M <[email protected]>2018-12-18 20:55:32 +0100
commit8cb1bdc6cf992cc55810f5af753666d54f2237d5 (patch)
tree052e2f425a6117e45323886bb2b2b683b6d5a1e8 /src/model
parentMutably borrow on `ChannelId`'s `edit`-method. (#447) (diff)
downloadserenity-8cb1bdc6cf992cc55810f5af753666d54f2237d5.tar.xz
serenity-8cb1bdc6cf992cc55810f5af753666d54f2237d5.zip
Remove global Cache (#448)
* Update to use Rust 2018. * Update examples and use Rust 2018. * Pass cache via `Context` around instead of being global. * Remove `lazy_static` from `cache`-feature. * Update examples to use `Context`'s cache. * Replace cache's update-timeout-setting with `update_cache_timeout`. * Update documentation to stop using global cache. * Move `HttpAndCache` to `lib.rs`. * Add `__nonexhaustive`-field to `CacheAndHttp`. * Add `__nonexhaustive` in `CacheAndHttp`-initialisers. * Avoid `__nonexhaustive`-usage in doctest. * Remove unnecessary comma in `cfg`-attribute.
Diffstat (limited to 'src/model')
-rw-r--r--src/model/channel/channel_category.rs18
-rw-r--r--src/model/channel/channel_id.rs25
-rw-r--r--src/model/channel/guild_channel.rs94
-rw-r--r--src/model/channel/message.rs78
-rw-r--r--src/model/channel/mod.rs60
-rw-r--r--src/model/channel/reaction.rs37
-rw-r--r--src/model/guild/emoji.rs55
-rw-r--r--src/model/guild/guild_id.rs20
-rw-r--r--src/model/guild/member.rs36
-rw-r--r--src/model/guild/mod.rs91
-rw-r--r--src/model/guild/partial_guild.rs12
-rw-r--r--src/model/guild/role.rs32
-rw-r--r--src/model/invite.rs26
-rw-r--r--src/model/misc.rs14
-rw-r--r--src/model/user.rs140
-rw-r--r--src/model/utils.rs6
16 files changed, 425 insertions, 319 deletions
diff --git a/src/model/channel/channel_category.rs b/src/model/channel/channel_category.rs
index f38b0f6..50720f9 100644
--- a/src/model/channel/channel_category.rs
+++ b/src/model/channel/channel_category.rs
@@ -1,5 +1,7 @@
-use crate::model::prelude::*;
+use crate::{model::prelude::*};
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(all(feature = "builder", feature = "model"))]
use crate::builder::EditChannel;
#[cfg(all(feature = "builder", feature = "model"))]
@@ -55,14 +57,18 @@ impl ChannelCategory {
self.id.delete_permission(permission_type)
}
- /// Deletes this category.
+
+ /// Deletes this category if required permissions are met.
+ ///
+ /// **Note**: If the `cache`-feature is enabled permissions will be checked and upon
+ /// owning the required permissions the HTTP-request will be issued.
#[inline]
- pub fn delete(&self) -> Result<()> {
+ pub fn delete(&self, context: &Context) -> Result<()> {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_CHANNELS;
- if !utils::user_has_perms(self.id, req)? {
+ if !utils::user_has_perms(&context.cache, self.id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -82,13 +88,13 @@ impl ChannelCategory {
/// category.edit(|c| c.name("test").bitrate(86400));
/// ```
#[cfg(all(feature = "builder", feature = "model", feature = "utils"))]
- pub fn edit<F>(&mut self, f: F) -> Result<()>
+ pub fn edit<F>(&mut self, context: &Context, f: F) -> Result<()>
where F: FnOnce(EditChannel) -> EditChannel {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_CHANNELS;
- if !utils::user_has_perms(self.id, req)? {
+ if !utils::user_has_perms(&context.cache, self.id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
diff --git a/src/model/channel/channel_id.rs b/src/model/channel/channel_id.rs
index 782ea5b..3f452fa 100644
--- a/src/model/channel/channel_id.rs
+++ b/src/model/channel/channel_id.rs
@@ -1,6 +1,7 @@
-use crate::internal::RwLockExt;
-use crate::model::prelude::*;
+use crate::{internal::RwLockExt, model::prelude::*};
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(feature = "model")]
use std::borrow::Cow;
#[cfg(feature = "model")]
@@ -13,9 +14,9 @@ use crate::builder::{
GetMessages
};
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::CACHE;
+use crate::cache::Cache;
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::Cache;
+use parking_lot::RwLock;
#[cfg(feature = "model")]
use crate::http::{self, AttachmentType};
#[cfg(feature = "model")]
@@ -293,8 +294,8 @@ impl ChannelId {
/// [`Channel`]: ../channel/enum.Channel.html
#[cfg(feature = "cache")]
#[inline]
- pub fn to_channel_cached(self) -> Option<Channel> {
- self._to_channel_cached(&CACHE)
+ pub fn to_channel_cached(self, cache: &Arc<RwLock<Cache>>) -> Option<Channel> {
+ self._to_channel_cached(&cache)
}
/// To allow testing pass their own cache instead of using the globale one.
@@ -307,15 +308,15 @@ impl ChannelId {
/// First attempts to find a [`Channel`] by its Id in the cache,
/// upon failure requests it via the REST API.
///
- /// **Note**: If the cache is not enabled,
- /// REST API will be used only.
+ /// **Note**: If the `cache`-feature is enabled permissions will be checked and upon
+ /// owning the required permissions the HTTP-request will be issued.
///
/// [`Channel`]: ../channel/enum.Channel.html
#[inline]
- pub fn to_channel(self) -> Result<Channel> {
+ pub fn to_channel(self, context: &Context) -> Result<Channel> {
#[cfg(feature = "cache")]
{
- if let Some(channel) = CACHE.read().channel(self) {
+ if let Some(channel) = context.cache.read().channel(self) {
return Ok(channel);
}
}
@@ -385,11 +386,11 @@ impl ChannelId {
/// Returns the name of whatever channel this id holds.
#[cfg(feature = "model")]
- pub fn name(&self) -> Option<String> {
+ pub fn name(&self, context: &Context) -> Option<String> {
use self::Channel::*;
let finding = feature_cache! {{
- Some(self.to_channel_cached())
+ Some(self.to_channel_cached(&context.cache))
} else {
None
}};
diff --git a/src/model/channel/guild_channel.rs b/src/model/channel/guild_channel.rs
index b976b0b..0c476e6 100644
--- a/src/model/channel/guild_channel.rs
+++ b/src/model/channel/guild_channel.rs
@@ -1,8 +1,14 @@
use chrono::{DateTime, FixedOffset};
-use crate::model::prelude::*;
+use crate::{model::prelude::*};
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::CACHE;
+use crate::cache::Cache;
+#[cfg(feature = "cache")]
+use parking_lot::RwLock;
+#[cfg(feature = "cache")]
+use std::sync::Arc;
#[cfg(feature = "model")]
use crate::builder::{
CreateInvite,
@@ -119,16 +125,17 @@ impl GuildChannel {
/// let invite = channel.create_invite(|i| i.max_uses(5));
/// ```
#[cfg(feature = "utils")]
- pub fn create_invite<F>(&self, f: F) -> Result<RichInvite>
+ pub fn create_invite<F>(&self, context: &Context, f: F) -> Result<RichInvite>
where F: FnOnce(&mut CreateInvite) -> &mut CreateInvite {
#[cfg(feature = "cache")]
{
let req = Permissions::CREATE_INVITE;
- if !utils::user_has_perms(self.id, req)? {
+ if !utils::user_has_perms(&context.cache, self.id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
+
let mut invite = CreateInvite::default();
f(&mut invite);
@@ -153,10 +160,15 @@ impl GuildChannel {
/// permissions:
///
/// ```rust,no_run
- /// # use serenity::model::id::{ChannelId, UserId};
- /// # use std::error::Error;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
/// #
- /// # fn try_main() -> Result<(), Box<Error>> {
+ /// # use serenity::{cache::Cache, model::id::{ChannelId, UserId}};
+ /// # use parking_lot::RwLock;
+ /// # use std::{error::Error, sync::Arc};
+ /// #
+ /// # fn main() -> Result<(), Box<Error>> {
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
/// # let (channel_id, user_id) = (ChannelId(0), UserId(0));
/// #
/// use serenity::model::channel::{
@@ -164,8 +176,6 @@ impl GuildChannel {
/// PermissionOverwriteType,
/// };
/// use serenity::model::{ModelError, Permissions};
- /// use serenity::CACHE;
- ///
/// let allow = Permissions::SEND_MESSAGES;
/// let deny = Permissions::SEND_TTS_MESSAGES | Permissions::ATTACH_FILES;
/// let overwrite = PermissionOverwrite {
@@ -173,18 +183,14 @@ impl GuildChannel {
/// deny: deny,
/// kind: PermissionOverwriteType::Member(user_id),
/// };
- ///
- /// let cache = CACHE.read();
+ /// # let cache = cache.read();
+ /// // assuming the cache has been unlocked
/// let channel = cache
/// .guild_channel(channel_id)
/// .ok_or(ModelError::ItemMissing)?;
///
/// channel.read().create_permission(&overwrite)?;
- /// # Ok(())
- /// # }
- /// #
- /// # fn main() {
- /// # try_main().unwrap();
+ /// # Ok(())
/// # }
/// ```
///
@@ -194,18 +200,22 @@ impl GuildChannel {
/// permissions:
///
/// ```rust,no_run
- /// # use serenity::model::id::{ChannelId, UserId};
- /// # use std::error::Error;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
+ ///
+ /// # use serenity::{cache::Cache, model::id::{ChannelId, UserId}};
+ /// # use parking_lot::RwLock;
+ /// # use std::{error::Error, sync::Arc};
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
- /// # let (channel_id, user_id) = (ChannelId(0), UserId(0));
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let (channel_id, user_id) = (ChannelId(0), UserId(0));
/// #
/// use serenity::model::channel::{
/// PermissionOverwrite,
/// PermissionOverwriteType,
/// };
/// use serenity::model::{ModelError, Permissions};
- /// use serenity::CACHE;
///
/// let allow = Permissions::SEND_MESSAGES;
/// let deny = Permissions::SEND_TTS_MESSAGES | Permissions::ATTACH_FILES;
@@ -215,7 +225,7 @@ impl GuildChannel {
/// kind: PermissionOverwriteType::Member(user_id),
/// };
///
- /// let cache = CACHE.read();
+ /// let cache = cache.read();
/// let channel = cache
/// .guild_channel(channel_id)
/// .ok_or(ModelError::ItemMissing)?;
@@ -247,12 +257,15 @@ impl GuildChannel {
}
/// Deletes this channel, returning the channel on a successful deletion.
- pub fn delete(&self) -> Result<Channel> {
+ ///
+ /// **Note**: If the `cache`-feature is enabled permissions will be checked and upon
+ /// owning the required permissions the HTTP-request will be issued.
+ pub fn delete(&self, context: &Context) -> Result<Channel> {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_CHANNELS;
- if !utils::user_has_perms(self.id, req)? {
+ if !utils::user_has_perms(&context.cache, self.id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -322,13 +335,13 @@ impl GuildChannel {
/// channel.edit(|c| c.name("test").bitrate(86400));
/// ```
#[cfg(feature = "utils")]
- pub fn edit<F>(&mut self, f: F) -> Result<()>
+ pub fn edit<F>(&mut self, context: &Context, f: F) -> Result<()>
where F: FnOnce(EditChannel) -> EditChannel {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_CHANNELS;
- if !utils::user_has_perms(self.id, req)? {
+ if !utils::user_has_perms(&context.cache, self.id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -380,7 +393,7 @@ impl GuildChannel {
/// **Note**: Right now this performs a clone of the guild. This will be
/// optimized in the future.
#[cfg(feature = "cache")]
- pub fn guild(&self) -> Option<Arc<RwLock<Guild>>> { CACHE.read().guild(self.guild_id) }
+ pub fn guild(&self, cache: &Arc<RwLock<Cache>>) -> Option<Arc<RwLock<Guild>>> { cache.read().guild(self.guild_id) }
/// Gets all of the channel's invites.
///
@@ -443,16 +456,14 @@ impl GuildChannel {
/// use serenity::model::prelude::*;
/// struct Handler;
///
- /// use serenity::CACHE;
- ///
/// impl EventHandler for Handler {
- /// fn message(&self, _: Context, msg: Message) {
- /// let channel = match CACHE.read().guild_channel(msg.channel_id) {
+ /// fn message(&self, context: Context, msg: Message) {
+ /// let channel = match context.cache.read().guild_channel(msg.channel_id) {
/// Some(channel) => channel,
/// None => return,
/// };
///
- /// let permissions = channel.read().permissions_for(&msg.author).unwrap();
+ /// let permissions = channel.read().permissions_for(&context.cache, &msg.author).unwrap();
///
/// println!("The user's permissions: {:?}", permissions);
/// }
@@ -467,7 +478,6 @@ impl GuildChannel {
/// for demonstrative purposes):
///
/// ```rust,no_run
- /// use serenity::CACHE;
/// use serenity::prelude::*;
/// use serenity::model::prelude::*;
/// use std::fs::File;
@@ -475,15 +485,15 @@ impl GuildChannel {
/// struct Handler;
///
/// impl EventHandler for Handler {
- /// fn message(&self, _: Context, mut msg: Message) {
- /// let channel = match CACHE.read().guild_channel(msg.channel_id) {
+ /// fn message(&self, context: Context, mut msg: Message) {
+ /// let channel = match context.cache.read().guild_channel(msg.channel_id) {
/// Some(channel) => channel,
/// None => return,
/// };
///
- /// let current_user_id = CACHE.read().user.id;
+ /// let current_user_id = context.cache.read().user.id;
/// let permissions =
- /// channel.read().permissions_for(current_user_id).unwrap();
+ /// channel.read().permissions_for(&context.cache, current_user_id).unwrap();
///
/// if !permissions.contains(Permissions::ATTACH_FILES | Permissions::SEND_MESSAGES) {
/// return;
@@ -526,13 +536,13 @@ impl GuildChannel {
/// [Send Messages]: ../permissions/struct.Permissions.html#associatedconstant.SEND_MESSAGES
#[cfg(feature = "cache")]
#[inline]
- pub fn permissions_for<U: Into<UserId>>(&self, user_id: U) -> Result<Permissions> {
- self._permissions_for(user_id.into())
+ pub fn permissions_for<U: Into<UserId>>(&self, cache: &Arc<RwLock<Cache>>, user_id: U) -> Result<Permissions> {
+ self._permissions_for(&cache, user_id.into())
}
#[cfg(feature = "cache")]
- fn _permissions_for(&self, user_id: UserId) -> Result<Permissions> {
- self.guild()
+ fn _permissions_for(&self, cache: &Arc<RwLock<Cache>>, user_id: UserId) -> Result<Permissions> {
+ self.guild(&cache)
.ok_or_else(|| Error::Model(ModelError::GuildNotFound))
.map(|g| g.read().permissions_in(self.id, user_id))
}
@@ -628,13 +638,13 @@ impl GuildChannel {
/// [`ModelError::MessageTooLong`]: ../error/enum.Error.html#variant.MessageTooLong
/// [`Message`]: struct.Message.html
/// [Send Messages]: ../permissions/struct.Permissions.html#associatedconstant.SEND_MESSAGES
- pub fn send_message<F>(&self, f: F) -> Result<Message>
+ pub fn send_message<F>(&self, context: &Context, f: F) -> Result<Message>
where for <'b> F: FnOnce(&'b mut CreateMessage<'b>) -> &'b mut CreateMessage<'b> {
#[cfg(feature = "cache")]
{
let req = Permissions::SEND_MESSAGES;
- if !utils::user_has_perms(self.id, req)? {
+ if !utils::user_has_perms(&context.cache, self.id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
diff --git a/src/model/channel/message.rs b/src/model/channel/message.rs
index 28c00fe..60ee3df 100644
--- a/src/model/channel/message.rs
+++ b/src/model/channel/message.rs
@@ -1,13 +1,19 @@
//! Models relating to Discord channels.
use chrono::{DateTime, FixedOffset};
-use crate::model::prelude::*;
+use crate::{model::prelude::*};
use serde_json::Value;
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(feature = "model")]
use crate::builder::{CreateEmbed, EditMessage};
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::CACHE;
+use crate::cache::Cache;
+#[cfg(all(feature = "cache", feature = "model"))]
+use parking_lot::RwLock;
+#[cfg(all(feature = "cache", feature = "model"))]
+use std::sync::Arc;
#[cfg(all(feature = "cache", feature = "model"))]
use std::fmt::Write;
#[cfg(feature = "model")]
@@ -102,30 +108,30 @@ impl Message {
/// .configure(|c| c.prefix("~"))
/// .cmd("channelname", channel_name));
///
- /// command!(channel_name(_ctx, msg) {
- /// let _ = match msg.channel() {
- /// Some(Channel::Category(c)) => msg.reply(&c.read().name),
- /// Some(Channel::Group(c)) => msg.reply(&c.read().name()),
- /// Some(Channel::Guild(c)) => msg.reply(&c.read().name),
+ /// command!(channel_name(ctx, msg) {
+ /// let _ = match msg.channel(&ctx.cache) {
+ /// Some(Channel::Category(c)) => msg.reply(&ctx, &c.read().name),
+ /// Some(Channel::Group(c)) => msg.reply(&ctx, &c.read().name()),
+ /// Some(Channel::Guild(c)) => msg.reply(&ctx, &c.read().name),
/// Some(Channel::Private(c)) => {
/// let channel = c.read();
/// let user = channel.recipient.read();
///
- /// msg.reply(&format!("DM with {}", user.name.clone()))
+ /// msg.reply(&ctx, &format!("DM with {}", user.name.clone()))
/// },
- /// None => msg.reply("Unknown"),
+ /// None => msg.reply(&ctx, "Unknown"),
/// };
/// });
/// # }
/// ```
#[cfg(feature = "cache")]
#[inline]
- pub fn channel(&self) -> Option<Channel> { CACHE.read().channel(self.channel_id) }
+ pub fn channel(&self, cache: &Arc<RwLock<Cache>>) -> Option<Channel> { cache.read().channel(self.channel_id) }
/// A util function for determining whether this message was sent by someone else, or the
/// bot.
#[cfg(all(feature = "cache", feature = "utils"))]
- pub fn is_own(&self) -> bool { self.author.id == CACHE.read().user.id }
+ pub fn is_own(&self, cache: &Arc<RwLock<Cache>>) -> bool { self.author.id == cache.read().user.id }
/// Deletes the message.
///
@@ -141,12 +147,12 @@ impl Message {
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [`ModelError::InvalidUser`]: ../error/enum.Error.html#variant.InvalidUser
/// [Manage Messages]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_MESSAGES
- pub fn delete(&self) -> Result<()> {
+ pub fn delete(&self, context: &Context) -> Result<()> {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_MESSAGES;
- let is_author = self.author.id == CACHE.read().user.id;
- let has_perms = utils::user_has_perms(self.channel_id, req)?;
+ let is_author = self.author.id == context.cache.read().user.id;
+ let has_perms = utils::user_has_perms(&context.cache, self.channel_id, req)?;
if !is_author && !has_perms {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
@@ -169,12 +175,12 @@ impl Message {
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [`Reaction`]: struct.Reaction.html
/// [Manage Messages]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_MESSAGES
- pub fn delete_reactions(&self) -> Result<()> {
+ pub fn delete_reactions(&self, context: &Context) -> Result<()> {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_MESSAGES;
- if !utils::user_has_perms(self.channel_id, req)? {
+ if !utils::user_has_perms(&context.cache, self.channel_id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -214,11 +220,11 @@ impl Message {
/// [`ModelError::MessageTooLong`]: ../error/enum.Error.html#variant.MessageTooLong
/// [`EditMessage`]: ../../builder/struct.EditMessage.html
/// [`the limit`]: ../../builder/struct.EditMessage.html#method.content
- pub fn edit<F>(&mut self, f: F) -> Result<()>
+ pub fn edit<F>(&mut self, context: &Context, f: F) -> Result<()>
where F: FnOnce(&mut EditMessage) -> &mut EditMessage {
#[cfg(feature = "cache")]
{
- if self.author.id != CACHE.read().user.id {
+ if self.author.id != context.cache.read().user.id {
return Err(Error::Model(ModelError::InvalidUser));
}
}
@@ -276,7 +282,7 @@ impl Message {
/// Returns message content, but with user and role mentions replaced with
/// names and everyone/here mentions cancelled.
#[cfg(feature = "cache")]
- pub fn content_safe(&self) -> String {
+ pub fn content_safe(&self, cache: &Arc<RwLock<Cache>>) -> String {
let mut result = self.content.clone();
// First replace all user mentions.
@@ -293,7 +299,7 @@ impl Message {
for id in &self.mention_roles {
let mention = id.mention();
- if let Some(role) = id.to_role_cached() {
+ if let Some(role) = id.to_role_cached(&cache) {
result = result.replace(&mention, &format!("@{}", role.name));
} else {
result = result.replace(&mention, "@deleted-role");
@@ -342,8 +348,8 @@ impl Message {
///
/// [`guild_id`]: #method.guild_id
#[cfg(feature = "cache")]
- pub fn guild(&self) -> Option<Arc<RwLock<Guild>>> {
- CACHE.read().guild(self.guild_id?)
+ pub fn guild(&self, cache: &Arc<RwLock<Cache>>) -> Option<Arc<RwLock<Guild>>> {
+ cache.read().guild(self.guild_id?)
}
/// True if message was sent using direct messages.
@@ -360,8 +366,8 @@ impl Message {
///
/// [`Guild::members`]: ../guild/struct.Guild.html#structfield.members
#[cfg(feature = "cache")]
- pub fn member(&self) -> Option<Member> {
- self.guild().and_then(|g| g.read().members.get(&self.author.id).cloned())
+ pub fn member(&self, cache: &Arc<RwLock<Cache>>) -> Option<Member> {
+ self.guild(&cache).and_then(|g| g.read().members.get(&self.author.id).cloned())
}
/// Checks the length of a string to ensure that it is within Discord's
@@ -395,13 +401,13 @@ impl Message {
///
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Manage Messages]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_MESSAGES.html
- pub fn pin(&self) -> Result<()> {
+ pub fn pin(&self, context: &Context) -> Result<()> {
#[cfg(feature = "cache")]
{
if self.guild_id.is_some() {
let req = Permissions::MANAGE_MESSAGES;
- if !utils::user_has_perms(self.channel_id, req)? {
+ if !utils::user_has_perms(&context.cache, self.channel_id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -426,17 +432,17 @@ impl Message {
/// ../permissions/struct.Permissions.html#associatedconstant.ADD_REACTIONS
/// [permissions]: ../permissions/index.html
#[inline]
- pub fn react<R: Into<ReactionType>>(&self, reaction_type: R) -> Result<()> {
- self._react(&reaction_type.into())
+ pub fn react<R: Into<ReactionType>>(&self, context: &Context, reaction_type: R) -> Result<()> {
+ self._react(&context, &reaction_type.into())
}
- fn _react(&self, reaction_type: &ReactionType) -> Result<()> {
+ fn _react(&self, context: &Context, reaction_type: &ReactionType) -> Result<()> {
#[cfg(feature = "cache")]
{
if self.guild_id.is_some() {
let req = Permissions::ADD_REACTIONS;
- if !utils::user_has_perms(self.channel_id, req)? {
+ if !utils::user_has_perms(&context.cache, self.channel_id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -467,7 +473,7 @@ impl Message {
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [`ModelError::MessageTooLong`]: ../error/enum.Error.html#variant.MessageTooLong
/// [Send Messages]: ../permissions/struct.Permissions.html#associatedconstant.SEND_MESSAGES
- pub fn reply(&self, content: &str) -> Result<Message> {
+ pub fn reply(&self, context: &Context, content: &str) -> Result<Message> {
if let Some(length_over) = Message::overflow_length(content) {
return Err(Error::Model(ModelError::MessageTooLong(length_over)));
}
@@ -477,7 +483,7 @@ impl Message {
if self.guild_id.is_some() {
let req = Permissions::SEND_MESSAGES;
- if !utils::user_has_perms(self.channel_id, req)? {
+ if !utils::user_has_perms(&context.cache, self.channel_id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -526,13 +532,13 @@ impl Message {
///
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Manage Messages]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_MESSAGES
- pub fn unpin(&self) -> Result<()> {
+ pub fn unpin(&self, context: &Context) -> Result<()> {
#[cfg(feature = "cache")]
{
if self.guild_id.is_some() {
let req = Permissions::MANAGE_MESSAGES;
- if !utils::user_has_perms(self.channel_id, req)? {
+ if !utils::user_has_perms(&context.cache, self.channel_id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -546,8 +552,8 @@ impl Message {
/// **Note**:
/// If message was sent in a private channel, then the function will return
/// `None`.
- pub fn author_nick(&self) -> Option<String> {
- self.guild_id.as_ref().and_then(|guild_id| self.author.nick_in(*guild_id))
+ pub fn author_nick(&self, context: &Context) -> Option<String> {
+ self.guild_id.as_ref().and_then(|guild_id| self.author.nick_in(&context, *guild_id))
}
pub(crate) fn check_content_length(map: &JsonMap) -> Result<()> {
diff --git a/src/model/channel/mod.rs b/src/model/channel/mod.rs
index 9c913cb..d21acb2 100644
--- a/src/model/channel/mod.rs
+++ b/src/model/channel/mod.rs
@@ -20,22 +20,29 @@ pub use self::private_channel::*;
pub use self::reaction::*;
pub use self::channel_category::*;
-use crate::internal::RwLockExt;
-use crate::model::prelude::*;
+use crate::{internal::RwLockExt, model::prelude::*};
use serde::de::Error as DeError;
use serde::ser::{SerializeStruct, Serialize, Serializer};
use serde_json;
use super::utils::deserialize_u64;
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(feature = "model")]
use std::fmt::{Display, Formatter, Result as FmtResult};
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
-use std::str::FromStr;
+use crate::cache::FromStrAndCache;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use crate::model::misc::ChannelParseError;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use crate::utils::parse_channel;
+#[cfg(feature = "cache")]
+use crate::cache::Cache;
+#[cfg(feature = "cache")]
+use std::sync::Arc;
+#[cfg(feature = "cache")]
+use parking_lot::RwLock;
/// A container for any channel.
#[derive(Clone, Debug)]
@@ -71,13 +78,17 @@ impl Channel {
/// Basic usage:
///
/// ```rust,no_run
+ /// # extern crate parking_lot;
/// # extern crate serenity;
/// #
- /// # use self::serenity::model::id::ChannelId;
+ /// # use serenity::{cache::Cache, model::id::ChannelId};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
/// # #[cfg(feature = "model")]
/// # fn main() {
- /// # let channel = ChannelId(0).to_channel().unwrap();
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let channel = ChannelId(0).to_channel_cached(&cache).unwrap();
/// #
/// match channel.group() {
/// Some(group_lock) => {
@@ -113,13 +124,17 @@ impl Channel {
/// Basic usage:
///
/// ```rust,no_run
+ /// # extern crate parking_lot;
/// # extern crate serenity;
/// #
- /// # use self::serenity::model::id::ChannelId;
+ /// # use serenity::{cache::Cache, model::id::ChannelId};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
/// # #[cfg(feature = "model")]
/// # fn main() {
- /// # let channel = ChannelId(0).to_channel().unwrap();
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let channel = ChannelId(0).to_channel_cached(&cache).unwrap();
/// #
/// match channel.guild() {
/// Some(guild_lock) => {
@@ -151,13 +166,17 @@ impl Channel {
/// Basic usage:
///
/// ```rust,no_run
+ /// # extern crate parking_lot;
/// # extern crate serenity;
/// #
- /// # use self::serenity::model::id::ChannelId;
+ /// # use serenity::{cache::Cache, model::id::ChannelId};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
/// # #[cfg(feature = "model")]
/// # fn main() {
- /// # let channel = ChannelId(0).to_channel().unwrap();
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let channel = ChannelId(0).to_channel_cached(&cache).unwrap();
/// #
/// match channel.private() {
/// Some(private_lock) => {
@@ -192,13 +211,17 @@ impl Channel {
/// Basic usage:
///
/// ```rust,no_run
+ /// # extern crate parking_lot;
/// # extern crate serenity;
/// #
- /// # use self::serenity::model::id::ChannelId;
+ /// # use serenity::{cache::Cache, model::id::ChannelId};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
/// # #[cfg(feature = "model")]
/// # fn main() {
- /// # let channel = ChannelId(0).to_channel().unwrap();
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let channel = ChannelId(0).to_channel_cached(&cache).unwrap();
/// #
/// match channel.category() {
/// Some(category_lock) => {
@@ -221,24 +244,27 @@ impl Channel {
/// Deletes the inner channel.
///
+ /// **Note**: If the `cache`-feature is enabled permissions will be checked and upon
+ /// owning the required permissions the HTTP-request will be issued.
+ ///
/// **Note**: There is no real function as _deleting_ a [`Group`]. The
/// closest functionality is leaving it.
///
/// [`Group`]: struct.Group.html
#[cfg(feature = "model")]
- pub fn delete(&self) -> Result<()> {
+ pub fn delete(&self, context: &Context) -> Result<()> {
match *self {
Channel::Group(ref group) => {
let _ = group.read().leave()?;
},
Channel::Guild(ref public_channel) => {
- let _ = public_channel.read().delete()?;
+ let _ = public_channel.read().delete(&context)?;
},
Channel::Private(ref private_channel) => {
let _ = private_channel.read().delete()?;
},
Channel::Category(ref category) => {
- category.read().delete()?;
+ category.read().delete(&context)?;
},
}
@@ -564,12 +590,12 @@ mod test {
}
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
-impl FromStr for Channel {
+impl FromStrAndCache for Channel {
type Err = ChannelParseError;
- fn from_str(s: &str) -> StdResult<Self, Self::Err> {
+ fn from_str(cache: &Arc<RwLock<Cache>>, s: &str) -> StdResult<Self, Self::Err> {
match parse_channel(s) {
- Some(x) => match ChannelId(x).to_channel_cached() {
+ Some(x) => match ChannelId(x).to_channel_cached(&cache) {
Some(channel) => Ok(channel),
_ => Err(ChannelParseError::NotPresentInCache),
},
diff --git a/src/model/channel/reaction.rs b/src/model/channel/reaction.rs
index a1df12a..6c5bdeb 100644
--- a/src/model/channel/reaction.rs
+++ b/src/model/channel/reaction.rs
@@ -1,4 +1,4 @@
-use crate::model::prelude::*;
+use crate::{model::prelude::*};
use serde::de::{Deserialize, Error as DeError, MapAccess, Visitor};
use serde::ser::{SerializeMap, Serialize, Serializer};
use std::{
@@ -11,10 +11,11 @@ use std::{
},
str::FromStr
};
+
use crate::internal::prelude::*;
-#[cfg(all(feature = "cache", feature = "model"))]
-use crate::CACHE;
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(feature = "model")]
use crate::http;
@@ -50,8 +51,8 @@ impl Reaction {
///
/// [Read Message History]: ../permissions/struct.Permissions.html#associatedconstant.READ_MESSAGE_HISTORY
#[inline]
- pub fn channel(&self) -> Result<Channel> {
- self.channel_id.to_channel()
+ pub fn channel(&self, context: &Context) -> Result<Channel> {
+ self.channel_id.to_channel(&context)
}
/// Deletes the reaction, but only if the current user is the user who made
@@ -69,10 +70,10 @@ impl Reaction {
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Manage Messages]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_MESSAGES
/// [permissions]: ../permissions/index.html
- pub fn delete(&self) -> Result<()> {
+ pub fn delete(&self, context: &Context) -> Result<()> {
let user_id = feature_cache! {
{
- let user = if self.user_id == CACHE.read().user.id {
+ let user = if self.user_id == context.cache.read().user.id {
None
} else {
Some(self.user_id.0)
@@ -87,7 +88,7 @@ impl Reaction {
if user.is_some() {
let req = Permissions::MANAGE_MESSAGES;
- if !utils::user_has_perms(self.channel_id, req).unwrap_or(true) {
+ if !utils::user_has_perms(&context.cache, self.channel_id, req).unwrap_or(true) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -122,8 +123,8 @@ impl Reaction {
/// If not - or the user was not found - this will perform a request over
/// the REST API for the user.
#[inline]
- pub fn user(&self) -> Result<User> {
- self.user_id.to_user()
+ pub fn user(&self, context: &Context) -> Result<User> {
+ self.user_id.to_user(&context)
}
/// Retrieves the list of [`User`]s who have reacted to a [`Message`] with a
@@ -326,19 +327,13 @@ impl From<char> for ReactionType {
/// Reacting to a message with an apple:
///
/// ```rust,no_run
- /// # use serenity::model::id::ChannelId;
- /// # use std::error::Error;
- /// #
- /// # fn try_main() -> Result<(), Box<Error>> {
- /// # let message = ChannelId(0).message(0)?;
+ /// # use serenity::{command, model::id::ChannelId};
/// #
- /// message.react('🍎')?;
- /// # Ok(())
- /// # }
+ /// # command!(example(context) {
+ /// # let message = ChannelId(0).message(0)?;
/// #
- /// # fn main() {
- /// # try_main().unwrap();
- /// # }
+ /// message.react(&context, '🍎')?;
+ /// # });
/// ```
fn from(ch: char) -> ReactionType { ReactionType::Unicode(ch.to_string()) }
}
diff --git a/src/model/guild/emoji.rs b/src/model/guild/emoji.rs
index 03c7a7e..dde379e 100644
--- a/src/model/guild/emoji.rs
+++ b/src/model/guild/emoji.rs
@@ -15,7 +15,11 @@ use super::super::ModelError;
#[cfg(all(feature = "cache", feature = "model"))]
use super::super::id::GuildId;
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::{CACHE, http};
+use crate::{cache::Cache, http};
+#[cfg(all(feature = "cache", feature = "model"))]
+use parking_lot::RwLock;
+#[cfg(all(feature = "cache", feature = "model"))]
+use std::sync::Arc;
/// Represents a custom guild emoji, which can either be created using the API,
/// or via an integration. Emojis created using the API only work within the
@@ -52,7 +56,7 @@ impl Emoji {
///
/// **Note**: Only user accounts may use this method.
///
- /// [Manage Emojis]:
+ /// [Manage Emojis]:
/// ../permissions/struct.Permissions.html#associatedconstant.MANAGE_EMOJIS
///
/// # Examples
@@ -60,8 +64,14 @@ impl Emoji {
/// Delete a given emoji:
///
/// ```rust,no_run
- /// # use serenity::model::guild::Emoji;
- /// # use serenity::model::id::EmojiId;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
+ /// #
+ /// # use serenity::{cache::Cache, model::{guild::Emoji, id::EmojiId}};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
+ /// #
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
/// #
/// # let mut emoji = Emoji {
/// # animated: false,
@@ -73,14 +83,14 @@ impl Emoji {
/// # };
/// #
/// // assuming emoji has been set already
- /// match emoji.delete() {
+ /// match emoji.delete(&cache) {
/// Ok(()) => println!("Emoji deleted."),
/// Err(_) => println!("Could not delete emoji.")
/// }
/// ```
#[cfg(feature = "cache")]
- pub fn delete(&self) -> Result<()> {
- match self.find_guild_id() {
+ pub fn delete(&self, cache: &Arc<RwLock<Cache>>) -> Result<()> {
+ match self.find_guild_id(&cache) {
Some(guild_id) => http::delete_emoji(guild_id.0, self.id.0),
None => Err(Error::Model(ModelError::ItemMissing)),
}
@@ -99,9 +109,9 @@ impl Emoji {
/// Change the name of an emoji:
///
/// ```rust,no_run
- /// # use serenity::model::guild::Emoji;
- /// # use serenity::model::id::EmojiId;
+ /// # use serenity::{command, model::{guild::Emoji, id::EmojiId}};
/// #
+ /// # command!(example(context) {
/// # let mut emoji = Emoji {
/// # animated: false,
/// # id: EmojiId(7),
@@ -110,14 +120,14 @@ impl Emoji {
/// # require_colons: false,
/// # roles: vec![],
/// # };
- /// #
/// // assuming emoji has been set already
- /// let _ = emoji.edit("blobuwu");
+ /// let _ = emoji.edit(&context.cache, "blobuwu");
/// assert_eq!(emoji.name, "blobuwu");
+ /// # });
/// ```
#[cfg(feature = "cache")]
- pub fn edit(&mut self, name: &str) -> Result<()> {
- match self.find_guild_id() {
+ pub fn edit(&mut self, cache: &Arc<RwLock<Cache>>, name: &str) -> Result<()> {
+ match self.find_guild_id(&cache) {
Some(guild_id) => {
let map = json!({
"name": name,
@@ -145,8 +155,14 @@ impl Emoji {
/// Print the guild id that owns this emoji:
///
/// ```rust,no_run
- /// # use serenity::model::guild::Emoji;
- /// # use serenity::model::id::EmojiId;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
+ /// #
+ /// # use serenity::{cache::Cache, model::{guild::Emoji, id::EmojiId}};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
+ /// #
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
/// #
/// # let mut emoji = Emoji {
/// # animated: false,
@@ -158,13 +174,13 @@ impl Emoji {
/// # };
/// #
/// // assuming emoji has been set already
- /// if let Some(guild_id) = emoji.find_guild_id() {
+ /// if let Some(guild_id) = emoji.find_guild_id(&cache) {
/// println!("{} is owned by {}", emoji.name, guild_id);
/// }
/// ```
#[cfg(feature = "cache")]
- pub fn find_guild_id(&self) -> Option<GuildId> {
- for guild in CACHE.read().guilds.values() {
+ pub fn find_guild_id(&self, cache: &Arc<RwLock<Cache>>) -> Option<GuildId> {
+ for guild in cache.read().guilds.values() {
let guild = guild.read();
if guild.emojis.contains_key(&self.id) {
@@ -182,8 +198,7 @@ impl Emoji {
/// Print the direct link to the given emoji:
///
/// ```rust,no_run
- /// # use serenity::model::guild::Emoji;
- /// # use serenity::model::id::EmojiId;
+ /// # use serenity::model::{guild::Emoji, id::EmojiId};
/// #
/// # let mut emoji = Emoji {
/// # animated: false,
diff --git a/src/model/guild/guild_id.rs b/src/model/guild/guild_id.rs
index c488b52..3146c78 100644
--- a/src/model/guild/guild_id.rs
+++ b/src/model/guild/guild_id.rs
@@ -1,7 +1,9 @@
-use crate::model::prelude::*;
+use crate::{model::prelude::*};
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::CACHE;
+use crate::cache::Cache;
#[cfg(feature = "model")]
use crate::builder::{EditGuild, EditMember, EditRole};
#[cfg(feature = "model")]
@@ -407,7 +409,7 @@ impl GuildId {
/// [`Guild`]: ../guild/struct.Guild.html
#[cfg(feature = "cache")]
#[inline]
- pub fn to_guild_cached(self) -> Option<Arc<RwLock<Guild>>> { CACHE.read().guild(self) }
+ pub fn to_guild_cached(self, cache: &Arc<RwLock<Cache>>) -> Option<Arc<RwLock<Guild>>> { cache.read().guild(self) }
/// Requests [`PartialGuild`] over REST API.
///
@@ -456,14 +458,14 @@ impl GuildId {
/// [`Guild`]: ../guild/struct.Guild.html
/// [`Member`]: ../guild/struct.Member.html
#[inline]
- pub fn member<U: Into<UserId>>(&self, user_id: U) -> Result<Member> {
- self._member(user_id.into())
+ pub fn member<U: Into<UserId>>(&self, context: &Context, user_id: U) -> Result<Member> {
+ self._member(&context, user_id.into())
}
- fn _member(&self, user_id: UserId) -> Result<Member> {
+ fn _member(&self, context: &Context, user_id: UserId) -> Result<Member> {
#[cfg(feature = "cache")]
{
- if let Some(member) = CACHE.read().member(self.0, user_id) {
+ if let Some(member) = context.cache.read().member(self.0, user_id) {
return Ok(member);
}
}
@@ -563,7 +565,9 @@ impl GuildId {
/// [`utils::shard_id`]: ../../utils/fn.shard_id.html
#[cfg(all(feature = "cache", feature = "utils"))]
#[inline]
- pub fn shard_id(&self) -> u64 { crate::utils::shard_id(self.0, CACHE.read().shard_count) }
+ pub fn shard_id(&self, cache: &Arc<RwLock<Cache>>) -> u64 {
+ crate::utils::shard_id(self.0, cache.read().shard_count)
+ }
/// Returns the Id of the shard associated with the guild.
///
diff --git a/src/model/guild/member.rs b/src/model/guild/member.rs
index cbda4c3..d969bd0 100644
--- a/src/model/guild/member.rs
+++ b/src/model/guild/member.rs
@@ -1,4 +1,4 @@
-use crate::model::prelude::*;
+use crate::{model::prelude::*};
use chrono::{DateTime, FixedOffset};
use std::fmt::{
Display,
@@ -7,6 +7,8 @@ use std::fmt::{
};
use super::deserialize_sync_user;
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(all(feature = "builder", feature = "cache", feature = "model"))]
use crate::builder::EditMember;
#[cfg(all(feature = "cache", feature = "model"))]
@@ -16,7 +18,7 @@ use std::borrow::Cow;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use crate::utils::Colour;
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::{CACHE, http, utils};
+use crate::{cache::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 {
@@ -169,8 +171,8 @@ impl Member {
/// Determines the member's colour.
#[cfg(all(feature = "cache", feature = "utils"))]
- pub fn colour(&self) -> Option<Colour> {
- let cache = CACHE.read();
+ pub fn colour(&self, cache: &Arc<RwLock<Cache>>) -> Option<Colour> {
+ let cache = cache.read();
let guild = cache.guilds.get(&self.guild_id)?.read();
let mut roles = self.roles
@@ -191,8 +193,8 @@ impl Member {
/// (This returns the first channel that can be read by the member, if there isn't
/// one returns `None`)
#[cfg(feature = "cache")]
- pub fn default_channel(&self) -> Option<Arc<RwLock<GuildChannel>>> {
- let guild = match self.guild_id.to_guild_cached() {
+ pub fn default_channel(&self, cache: &Arc<RwLock<Cache>>) -> Option<Arc<RwLock<GuildChannel>>> {
+ let guild = match self.guild_id.to_guild_cached(&cache) {
Some(guild) => guild,
None => return None,
};
@@ -257,8 +259,8 @@ impl Member {
/// position. If two or more roles have the same highest position, then the
/// role with the lowest ID is the highest.
#[cfg(feature = "cache")]
- pub fn highest_role_info(&self) -> Option<(RoleId, i64)> {
- let guild = self.guild_id.to_guild_cached()?;
+ pub fn highest_role_info(&self, cache: &Arc<RwLock<Cache>>) -> Option<(RoleId, i64)> {
+ let guild = self.guild_id.to_guild_cached(&cache)?;
let reader = guild.try_read()?;
let mut highest = None;
@@ -315,20 +317,20 @@ impl Member {
/// [`ModelError::GuildNotFound`]: ../error/enum.Error.html#variant.GuildNotFound
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Kick Members]: ../permissions/struct.Permissions.html#associatedconstant.KICK_MEMBERS
- pub fn kick(&self) -> Result<()> {
+ pub fn kick(&self, context: &Context) -> Result<()> {
#[cfg(feature = "cache")]
{
- let cache = CACHE.read();
+ let locked_cache = context.cache.read();
- if let Some(guild) = cache.guilds.get(&self.guild_id) {
+ if let Some(guild) = locked_cache.guilds.get(&self.guild_id) {
let req = Permissions::KICK_MEMBERS;
let reader = guild.read();
- if !reader.has_perms(req) {
+ if !reader.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
- reader.check_hierarchy(self.user.read().id)?;
+ reader.check_hierarchy(&context.cache, self.user.read().id)?;
}
}
@@ -356,8 +358,8 @@ impl Member {
/// [`ModelError::GuildNotFound`]: ../error/enum.Error.html#variant.GuildNotFound
/// [`ModelError::ItemMissing`]: ../error/enum.Error.html#variant.ItemMissing
#[cfg(feature = "cache")]
- pub fn permissions(&self) -> Result<Permissions> {
- let guild = match self.guild_id.to_guild_cached() {
+ pub fn permissions(&self, cache: &Arc<RwLock<Cache>>) -> Result<Permissions> {
+ let guild = match self.guild_id.to_guild_cached(&cache) {
Some(guild) => guild,
None => return Err(From::from(ModelError::GuildNotFound)),
};
@@ -426,10 +428,10 @@ impl Member {
///
/// If role data can not be found for the member, then `None` is returned.
#[cfg(feature = "cache")]
- pub fn roles(&self) -> Option<Vec<Role>> {
+ pub fn roles(&self, cache: &Arc<RwLock<Cache>>) -> Option<Vec<Role>> {
self
.guild_id
- .to_guild_cached()
+ .to_guild_cached(&cache)
.map(|g| g
.read()
.roles
diff --git a/src/model/guild/mod.rs b/src/model/guild/mod.rs
index 86cba3d..3ea8d06 100644
--- a/src/model/guild/mod.rs
+++ b/src/model/guild/mod.rs
@@ -17,13 +17,19 @@ pub use self::role::*;
pub use self::audit_log::*;
use chrono::{DateTime, FixedOffset};
-use crate::model::prelude::*;
+use crate::{model::prelude::*};
use serde::de::Error as DeError;
use serde_json;
use super::utils::*;
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::CACHE;
+use crate::cache::Cache;
+#[cfg(all(feature = "cache", feature = "model"))]
+use parking_lot::RwLock;
+#[cfg(all(feature = "cache", feature = "model"))]
+use std::sync::Arc;
#[cfg(feature = "model")]
use crate::http;
#[cfg(feature = "model")]
@@ -146,10 +152,10 @@ pub struct Guild {
#[cfg(feature = "model")]
impl Guild {
#[cfg(feature = "cache")]
- fn check_hierarchy(&self, other_user: UserId) -> Result<()> {
- let current_id = CACHE.read().user.id;
+ fn check_hierarchy(&self, cache: &Arc<RwLock<Cache>>, other_user: UserId) -> Result<()> {
+ let current_id = cache.read().user.id;
- if let Some(higher) = self.greater_member_hierarchy(other_user, current_id) {
+ if let Some(higher) = self.greater_member_hierarchy(&cache, other_user, current_id) {
if higher != current_id {
return Err(Error::Model(ModelError::Hierarchy));
}
@@ -189,8 +195,8 @@ impl Guild {
}
#[cfg(feature = "cache")]
- fn has_perms(&self, mut permissions: Permissions) -> bool {
- let user_id = CACHE.read().user.id;
+ fn has_perms(&self, cache: &Arc<RwLock<Cache>>, mut permissions: Permissions) -> bool {
+ let user_id = cache.read().user.id;
let perms = self.member_permissions(user_id);
permissions.remove(perms);
@@ -228,20 +234,20 @@ impl Guild {
/// [`User`]: ../user/struct.User.html
/// [Ban Members]: ../permissions/struct.Permissions.html#associatedconstant.BAN_MEMBERS
#[inline]
- pub fn ban<U: Into<UserId>, BO: BanOptions>(&self, user: U, options: &BO) -> Result<()> {
- self._ban(user.into(), options)
+ pub fn ban<U: Into<UserId>, BO: BanOptions>(&self, context: &Context, user: U, options: &BO) -> Result<()> {
+ self._ban(&context, user.into(), options)
}
- fn _ban<BO: BanOptions>(&self, user: UserId, options: &BO) -> Result<()> {
+ fn _ban<BO: BanOptions>(&self, context: &Context, user: UserId, options: &BO) -> Result<()> {
#[cfg(feature = "cache")]
{
let req = Permissions::BAN_MEMBERS;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
- self.check_hierarchy(user)?;
+ self.check_hierarchy(&context.cache, user)?;
}
self.id.ban(user, options)
@@ -259,12 +265,12 @@ impl Guild {
/// [`Ban`]: struct.Ban.html
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Ban Members]: ../permissions/struct.Permissions.html#associatedconstant.BAN_MEMBERS
- pub fn bans(&self) -> Result<Vec<Ban>> {
+ pub fn bans(&self, context: &Context) -> Result<Vec<Ban>> {
#[cfg(feature = "cache")]
{
let req = Permissions::BAN_MEMBERS;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -346,13 +352,13 @@ impl Guild {
/// [`Channel`]: ../channel/enum.Channel.html
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Manage Channels]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_CHANNELS
- pub fn create_channel<C>(&self, name: &str, kind: ChannelType, category: C) -> Result<GuildChannel>
+ pub fn create_channel<C>(&self, context: &Context, name: &str, kind: ChannelType, category: C) -> Result<GuildChannel>
where C: Into<Option<ChannelId>> {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_CHANNELS;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -417,13 +423,13 @@ impl Guild {
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [`Role`]: struct.Role.html
/// [Manage Roles]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_ROLES
- pub fn create_role<F>(&self, f: F) -> Result<Role>
+ pub fn create_role<F>(&self, context: &Context, f: F) -> Result<Role>
where F: FnOnce(&mut EditRole) -> &mut EditRole {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_ROLES;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -442,10 +448,10 @@ impl Guild {
/// if the current user is not the guild owner.
///
/// [`ModelError::InvalidUser`]: ../error/enum.Error.html#variant.InvalidUser
- pub fn delete(&self) -> Result<PartialGuild> {
+ pub fn delete(&self, context: &Context) -> Result<PartialGuild> {
#[cfg(feature = "cache")]
{
- if self.owner_id != CACHE.read().user.id {
+ if self.owner_id != context.cache.read().user.id {
let req = Permissions::MANAGE_GUILD;
return Err(Error::Model(ModelError::InvalidPermissions(req)));
@@ -519,13 +525,13 @@ impl Guild {
///
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Manage Guild]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_GUILD
- pub fn edit<F>(&mut self, f: F) -> Result<()>
+ pub fn edit<F>(&mut self, context: &Context, f: F) -> Result<()>
where F: FnOnce(&mut EditGuild) -> &mut EditGuild {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_GUILD;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -600,12 +606,12 @@ impl Guild {
///
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Change Nickname]: ../permissions/struct.Permissions.html#associatedconstant.CHANGE_NICKNAME
- pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> {
+ pub fn edit_nickname(&self, context: &Context, new_nickname: Option<&str>) -> Result<()> {
#[cfg(feature = "cache")]
{
let req = Permissions::CHANGE_NICKNAME;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -673,14 +679,15 @@ impl Guild {
/// [`position`]: struct.Role.html#structfield.position
#[cfg(feature = "cache")]
#[inline]
- pub fn greater_member_hierarchy<T, U>(&self, lhs_id: T, rhs_id: U)
+ pub fn greater_member_hierarchy<T, U>(&self, cache: &Arc<RwLock<Cache>>, lhs_id: T, rhs_id: U)
-> Option<UserId> where T: Into<UserId>, U: Into<UserId> {
- self._greater_member_hierarchy(lhs_id.into(), rhs_id.into())
+ self._greater_member_hierarchy(&cache, lhs_id.into(), rhs_id.into())
}
#[cfg(feature = "cache")]
fn _greater_member_hierarchy(
&self,
+ cache: &Arc<RwLock<Cache>>,
lhs_id: UserId,
rhs_id: UserId,
) -> Option<UserId> {
@@ -697,10 +704,10 @@ impl Guild {
}
let lhs = self.members.get(&lhs_id)?
- .highest_role_info()
+ .highest_role_info(&cache)
.unwrap_or((RoleId(0), 0));
let rhs = self.members.get(&rhs_id)?
- .highest_role_info()
+ .highest_role_info(&cache)
.unwrap_or((RoleId(0), 0));
// If LHS and RHS both have no top position or have the same role ID,
@@ -754,12 +761,12 @@ impl Guild {
///
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Manage Guild]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_GUILD
- pub fn invites(&self) -> Result<Vec<RichInvite>> {
+ pub fn invites(&self, context: &Context) -> Result<Vec<RichInvite>> {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_GUILD;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -790,7 +797,9 @@ impl Guild {
/// [`Guild`]: ../guild/struct.Guild.html
/// [`Member`]: struct.Member.html
#[inline]
- pub fn member<U: Into<UserId>>(&self, user_id: U) -> Result<Member> { self.id.member(user_id) }
+ pub fn member<U: Into<UserId>>(&self, context: &Context, user_id: U) -> Result<Member> {
+ self.id.member(&context, user_id)
+ }
/// Gets a list of the guild's members.
///
@@ -1339,12 +1348,12 @@ impl Guild {
/// [`GuildPrune`]: struct.GuildPrune.html
/// [`Member`]: struct.Member.html
/// [Kick Members]: ../permissions/struct.Permissions.html#associatedconstant.KICK_MEMBERS
- pub fn prune_count(&self, days: u16) -> Result<GuildPrune> {
+ pub fn prune_count(&self, context: &Context, days: u16) -> Result<GuildPrune> {
#[cfg(feature = "cache")]
{
let req = Permissions::KICK_MEMBERS;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -1374,7 +1383,7 @@ impl Guild {
/// [`utils::shard_id`]: ../../utils/fn.shard_id.html
#[cfg(all(feature = "cache", feature = "utils"))]
#[inline]
- pub fn shard_id(&self) -> u64 { self.id.shard_id() }
+ pub fn shard_id(&self, cache: &Arc<RwLock<Cache>>) -> u64 { self.id.shard_id(&cache) }
/// Returns the Id of the shard associated with the guild.
///
@@ -1432,12 +1441,12 @@ impl Guild {
/// [`GuildPrune`]: struct.GuildPrune.html
/// [`Member`]: struct.Member.html
/// [Kick Members]: ../permissions/struct.Permissions.html#associatedconstant.KICK_MEMBERS
- pub fn start_prune(&self, days: u16) -> Result<GuildPrune> {
+ pub fn start_prune(&self, context: &Context, days: u16) -> Result<GuildPrune> {
#[cfg(feature = "cache")]
{
let req = Permissions::KICK_MEMBERS;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -1457,12 +1466,12 @@ impl Guild {
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [`User`]: ../user/struct.User.html
/// [Ban Members]: ../permissions/struct.Permissions.html#associatedconstant.BAN_MEMBERS
- pub fn unban<U: Into<UserId>>(&self, user_id: U) -> Result<()> {
+ pub fn unban<U: Into<UserId>>(&self, context: &Context, user_id: U) -> Result<()> {
#[cfg(feature = "cache")]
{
let req = Permissions::BAN_MEMBERS;
- if !self.has_perms(req) {
+ if !self.has_perms(&context.cache, req) {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -1503,11 +1512,9 @@ impl Guild {
///
/// struct Handler;
///
- /// use serenity::CACHE;
- ///
/// impl EventHandler for Handler {
- /// fn message(&self, _: Context, msg: Message) {
- /// if let Some(arc) = msg.guild_id.unwrap().to_guild_cached() {
+ /// fn message(&self, ctx: Context, msg: Message) {
+ /// if let Some(arc) = msg.guild_id.unwrap().to_guild_cached(&ctx.cache) {
/// if let Some(role) = arc.read().role_by_name("role_name") {
/// println!("{:?}", role);
/// }
diff --git a/src/model/guild/partial_guild.rs b/src/model/guild/partial_guild.rs
index 6276db2..8b1be58 100644
--- a/src/model/guild/partial_guild.rs
+++ b/src/model/guild/partial_guild.rs
@@ -1,6 +1,8 @@
-use crate::model::prelude::*;
+use crate::{model::prelude::*};
use super::super::utils::{deserialize_emojis, deserialize_roles};
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(feature = "model")]
use crate::builder::{EditGuild, EditMember, EditRole};
@@ -333,7 +335,9 @@ impl PartialGuild {
///
/// [`Guild`]: struct.Guild.html
/// [`Member`]: struct.Member.html
- pub fn member<U: Into<UserId>>(&self, user_id: U) -> Result<Member> { self.id.member(user_id) }
+ pub fn member<U: Into<UserId>>(&self, context: &Context, user_id: U) -> Result<Member> {
+ self.id.member(&context, user_id)
+ }
/// Gets a list of the guild's members.
///
@@ -380,7 +384,7 @@ impl PartialGuild {
/// [`utils::shard_id`]: ../../utils/fn.shard_id.html
#[cfg(all(feature = "cache", feature = "utils"))]
#[inline]
- pub fn shard_id(&self) -> u64 { self.id.shard_id() }
+ pub fn shard_id(&self, context: &Context) -> u64 { self.id.shard_id(&context.cache) }
/// Returns the Id of the shard associated with the guild.
///
@@ -465,8 +469,6 @@ impl PartialGuild {
///
/// struct Handler;
///
- /// use serenity::CACHE;
- ///
/// impl EventHandler for Handler {
/// fn message(&self, _: Context, msg: Message) {
/// let guild = msg.guild_id.unwrap().to_partial_guild().unwrap();
diff --git a/src/model/guild/role.rs b/src/model/guild/role.rs
index b68803b..404cfcf 100644
--- a/src/model/guild/role.rs
+++ b/src/model/guild/role.rs
@@ -6,10 +6,10 @@ use crate::builder::EditRole;
#[cfg(all(feature = "cache", feature = "model"))]
use crate::internal::prelude::*;
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::{CACHE, Cache, http};
+use crate::{cache::Cache, http};
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
-use std::str::FromStr;
+use crate::cache::FromStrAndCache;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use crate::model::misc::RoleParseError;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
@@ -75,7 +75,9 @@ impl Role {
/// [Manage Roles]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_ROLES
#[cfg(feature = "cache")]
#[inline]
- pub fn delete(&self) -> Result<()> { http::delete_role(self.find_guild()?.0, self.id.0) }
+ pub fn delete(&self, cache: &Arc<RwLock<Cache>>) -> Result<()> {
+ http::delete_role(self.find_guild(&cache)?.0, self.id.0)
+ }
/// Edits a [`Role`], optionally setting its new fields.
///
@@ -85,9 +87,9 @@ impl Role {
///
/// Make a role hoisted:
///
- /// ```rust,no_run
+ /// ```rust,ignore
/// # use serenity::model::id::RoleId;
- /// # let role = RoleId(7).to_role_cached().unwrap();
+ /// # let role = RoleId(7).to_role_cached(&cache).unwrap();
/// // assuming a `role` has already been bound
//
/// role.edit(|mut r| {
@@ -100,8 +102,8 @@ impl Role {
/// [`Role`]: struct.Role.html
/// [Manage Roles]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_ROLES
#[cfg(all(feature = "builder", feature = "cache"))]
- pub fn edit<F: FnOnce(EditRole) -> EditRole>(&self, f: F) -> Result<Role> {
- self.find_guild()
+ pub fn edit<F: FnOnce(EditRole) -> EditRole>(&self, cache: &Arc<RwLock<Cache>>, f: F) -> Result<Role> {
+ self.find_guild(&cache)
.and_then(|guild_id| guild_id.edit_role(self.id, f))
}
@@ -114,8 +116,8 @@ impl Role {
///
/// [`ModelError::GuildNotFound`]: ../error/enum.Error.html#variant.GuildNotFound
#[cfg(feature = "cache")]
- pub fn find_guild(&self) -> Result<GuildId> {
- for guild in CACHE.read().guilds.values() {
+ pub fn find_guild(&self, cache: &Arc<RwLock<Cache>>) -> Result<GuildId> {
+ for guild in cache.read().guilds.values() {
let guild = guild.read();
if guild.roles.contains_key(&RoleId(self.id.0)) {
@@ -178,12 +180,12 @@ impl RoleId {
///
/// [`Role`]: ../guild/struct.Role.html
#[cfg(feature = "cache")]
- pub fn to_role_cached(self) -> Option<Role> {
- self._to_role_cached(&CACHE)
+ pub fn to_role_cached(self, cache: &Arc<RwLock<Cache>>) -> Option<Role> {
+ self._to_role_cached(&cache)
}
#[cfg(feature = "cache")]
- pub(crate) fn _to_role_cached(self, cache: &RwLock<Cache>) -> Option<Role> {
+ pub(crate) fn _to_role_cached(self, cache: &Arc<RwLock<Cache>>) -> Option<Role> {
for guild in cache.read().guilds.values() {
let guild = guild.read();
@@ -211,12 +213,12 @@ impl<'a> From<&'a Role> for RoleId {
}
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
-impl FromStr for Role {
+impl FromStrAndCache for Role {
type Err = RoleParseError;
- fn from_str(s: &str) -> StdResult<Self, Self::Err> {
+ fn from_str(cache: &Arc<RwLock<Cache>>, s: &str) -> StdResult<Self, Self::Err> {
match parse_role(s) {
- Some(x) => match RoleId(x).to_role_cached() {
+ Some(x) => match RoleId(x).to_role_cached(&cache) {
Some(role) => Ok(role),
_ => Err(RoleParseError::NotPresentInCache),
},
diff --git a/src/model/invite.rs b/src/model/invite.rs
index 74a46dc..a6f0479 100644
--- a/src/model/invite.rs
+++ b/src/model/invite.rs
@@ -3,6 +3,8 @@
use chrono::{DateTime, FixedOffset};
use super::prelude::*;
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(feature = "model")]
use crate::builder::CreateInvite;
#[cfg(feature = "model")]
@@ -11,6 +13,12 @@ use crate::internal::prelude::*;
use super::{Permissions, utils as model_utils};
#[cfg(feature = "model")]
use crate::{http, utils};
+#[cfg(feature = "cache")]
+use crate::cache::Cache;
+#[cfg(feature = "cache")]
+use parking_lot::RwLock;
+#[cfg(feature = "cache")]
+use std::sync::Arc;
/// Information about an invite code.
///
@@ -70,18 +78,18 @@ impl Invite {
/// [`GuildChannel`]: ../channel/struct.GuildChannel.html
/// [Create Invite]: ../permissions/struct.Permissions.html#associatedconstant.CREATE_INVITE
/// [permission]: ../permissions/index.html
- pub fn create<C, F>(channel_id: C, f: F) -> Result<RichInvite>
+ pub fn create<C, F>(context: &Context, channel_id: C, f: F) -> Result<RichInvite>
where C: Into<ChannelId>, F: FnOnce(CreateInvite) -> CreateInvite {
- Self::_create(channel_id.into(), f)
+ Self::_create(&context, channel_id.into(), f)
}
- fn _create<F>(channel_id: ChannelId, f: F) -> Result<RichInvite>
+ fn _create<F>(context: &Context, channel_id: ChannelId, f: F) -> Result<RichInvite>
where F: FnOnce(CreateInvite) -> CreateInvite {
#[cfg(feature = "cache")]
{
let req = Permissions::CREATE_INVITE;
- if !model_utils::user_has_perms(channel_id, req)? {
+ if !model_utils::user_has_perms(&context.cache, channel_id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -103,12 +111,12 @@ impl Invite {
/// [`ModelError::InvalidPermissions`]: ../error/enum.Error.html#variant.InvalidPermissions
/// [Manage Guild]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_GUILD
/// [permission]: ../permissions/index.html
- pub fn delete(&self) -> Result<Invite> {
+ pub fn delete(&self, context: &Context) -> Result<Invite> {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_GUILD;
- if !model_utils::user_has_perms(self.channel.id, req)? {
+ if !model_utils::user_has_perms(&context.cache, self.channel.id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
@@ -195,7 +203,7 @@ impl InviteGuild {
/// [`utils::shard_id`]: ../../utils/fn.shard_id.html
#[cfg(all(feature = "cache", feature = "utils"))]
#[inline]
- pub fn shard_id(&self) -> u64 { self.id.shard_id() }
+ pub fn shard_id(&self, cache: &Arc<RwLock<Cache>>) -> u64 { self.id.shard_id(&cache) }
/// Returns the Id of the shard associated with the guild.
///
@@ -288,12 +296,12 @@ impl RichInvite {
/// [`http::delete_invite`]: ../../http/fn.delete_invite.html
/// [Manage Guild]: ../permissions/struct.Permissions.html#associatedconstant.MANAGE_GUILD.html
/// [permission]: ../permissions/index.html
- pub fn delete(&self) -> Result<Invite> {
+ pub fn delete(&self, context: &Context) -> Result<Invite> {
#[cfg(feature = "cache")]
{
let req = Permissions::MANAGE_GUILD;
- if !model_utils::user_has_perms(self.channel.id, req)? {
+ if !model_utils::user_has_perms(&context.cache, self.channel.id, req)? {
return Err(Error::Model(ModelError::InvalidPermissions(req)));
}
}
diff --git a/src/model/misc.rs b/src/model/misc.rs
index e2adbcc..5726af6 100644
--- a/src/model/misc.rs
+++ b/src/model/misc.rs
@@ -112,20 +112,6 @@ impl StdError for UserParseError {
}
}
-#[cfg(all(feature = "model", feature = "utils"))]
-impl FromStr for User {
- type Err = UserParseError;
-
- fn from_str(s: &str) -> StdResult<Self, Self::Err> {
- match utils::parse_username(s) {
- Some(x) => UserId(x as u64)
- .to_user()
- .map_err(|e| UserParseError::Rest(Box::new(e))),
- _ => Err(UserParseError::InvalidUsername),
- }
- }
-}
-
macro_rules! impl_from_str {
(id: $($id:tt, $err:ident;)*) => {
$(
diff --git a/src/model/user.rs b/src/model/user.rs
index 80bf40e..923d4d1 100644
--- a/src/model/user.rs
+++ b/src/model/user.rs
@@ -4,11 +4,10 @@ use serde_json;
use std::fmt;
use super::utils::deserialize_u16;
use super::prelude::*;
-use crate::internal::prelude::*;
-use crate::model::misc::Mentionable;
+use crate::{internal::prelude::*, model::misc::Mentionable};
-#[cfg(all(feature = "cache", feature = "model"))]
-use crate::CACHE;
+#[cfg(feature = "client")]
+use crate::client::Context;
#[cfg(feature = "model")]
use crate::builder::{CreateMessage, EditProfile};
#[cfg(feature = "model")]
@@ -22,6 +21,8 @@ use std::fmt::Write;
#[cfg(feature = "model")]
use std::mem;
#[cfg(all(feature = "cache", feature = "model"))]
+use crate::cache::Cache;
+#[cfg(all(feature = "cache", feature = "model"))]
use std::sync::Arc;
#[cfg(feature = "model")]
use crate::utils::{self, VecMap};
@@ -50,10 +51,15 @@ impl CurrentUser {
/// Print out the current user's avatar url if one is set:
///
/// ```rust,no_run
- /// # use serenity::CACHE;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
/// #
- /// # let cache = CACHE.read();
+ /// # use serenity::{cache::Cache, model::prelude::*, prelude::*};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let cache = cache.read();
/// // assuming the cache has been unlocked
/// let user = &cache.user;
///
@@ -82,11 +88,9 @@ impl CurrentUser {
/// Change the avatar:
///
/// ```rust,ignore
- /// use serenity::CACHE;
- ///
/// let avatar = serenity::utils::read_image("./avatar.png").unwrap();
///
- /// CACHE.write().user.edit(|p| p.avatar(Some(&avatar)));
+ /// context.cache.write().user.edit(|p| p.avatar(Some(&avatar)));
/// ```
///
/// [`EditProfile`]: ../../builder/struct.EditProfile.html
@@ -131,10 +135,15 @@ impl CurrentUser {
/// Print out the names of all guilds the current user is in:
///
/// ```rust,no_run
- /// # use serenity::CACHE;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
/// #
- /// # let cache = CACHE.read();
+ /// # use serenity::{cache::Cache, model::prelude::*, prelude::*};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let cache = cache.read();
/// // assuming the cache has been unlocked
/// let user = &cache.user;
///
@@ -159,9 +168,15 @@ impl CurrentUser {
/// Get the invite url with no permissions set:
///
/// ```rust,no_run
- /// # use serenity::CACHE;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
+ /// #
+ /// # use serenity::{cache::Cache, model::prelude::*, prelude::*};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
- /// # let mut cache = CACHE.write();
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let mut cache = cache.write();
///
/// use serenity::model::Permissions;
///
@@ -182,10 +197,15 @@ impl CurrentUser {
/// Get the invite url with some basic permissions set:
///
/// ```rust,no_run
- /// # use serenity::CACHE;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
/// #
- /// # let mut cache = CACHE.write();
- ///
+ /// # use serenity::{cache::Cache, model::prelude::*, prelude::*};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
+ /// #
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let mut cache = cache.write();
/// use serenity::model::Permissions;
///
/// // assuming the cache has been unlocked
@@ -238,10 +258,15 @@ impl CurrentUser {
/// Print out the current user's static avatar url if one is set:
///
/// ```rust,no_run
- /// # use serenity::CACHE;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
/// #
- /// # let cache = CACHE.read();
+ /// # use serenity::{cache::Cache, model::prelude::*, prelude::*};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let cache = cache.read();
/// // assuming the cache has been unlocked
/// let user = &cache.user;
///
@@ -262,10 +287,15 @@ impl CurrentUser {
/// Print out the current user's distinct identifier (e.g., Username#1234):
///
/// ```rust,no_run
- /// # use serenity::CACHE;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
/// #
- /// # let cache = CACHE.read();
+ /// # use serenity::{cache::Cache, model::prelude::*, prelude::*};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// #
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
+ /// # let cache = cache.read();
/// // assuming the cache has been unlocked
/// println!("The current user's distinct identifier is {}", cache.user.tag());
/// ```
@@ -415,14 +445,13 @@ impl User {
/// # use serenity::model::prelude::*;
/// #
/// use serenity::model::Permissions;
- /// use serenity::CACHE;
///
/// struct Handler;
///
/// impl EventHandler for Handler {
- /// fn message(&self, _: Context, msg: Message) {
+ /// fn message(&self, ctx: Context, msg: Message) {
/// if msg.content == "~help" {
- /// let cache = CACHE.read();
+ /// let cache = ctx.cache.read();
///
/// let url = match cache.user.invite_url(Permissions::empty()) {
/// Ok(v) => v,
@@ -438,18 +467,18 @@ impl User {
/// url,
/// );
///
- /// let dm = msg.author.direct_message(|m| {
+ /// let dm = msg.author.direct_message(&ctx, |m| {
/// m.content(&help)
/// });
///
/// match dm {
/// Ok(_) => {
- /// let _ = msg.react('👌');
+ /// let _ = msg.react(&ctx, '👌');
/// },
/// Err(why) => {
/// println!("Err sending help: {:?}", why);
///
- /// let _ = msg.reply("There was an error DMing you help.");
+ /// let _ = msg.reply(&ctx, "There was an error DMing you help.");
/// },
/// };
/// }
@@ -483,7 +512,7 @@ impl User {
// (AKA: Clippy is wrong and so we have to mark as allowing this lint.)
#[allow(clippy::let_and_return)]
#[cfg(feature = "builder")]
- pub fn direct_message<F>(&self, f: F) -> Result<Message>
+ pub fn direct_message<F>(&self, context: &Context, f: F) -> Result<Message>
where for <'b> F: FnOnce(&'b mut CreateMessage<'b>) -> &'b mut CreateMessage<'b> {
if self.bot {
return Err(Error::Model(ModelError::MessagingBot));
@@ -492,7 +521,7 @@ impl User {
let private_channel_id = feature_cache! {
{
let finding = {
- let cache = CACHE.read();
+ let cache = context.cache.read();
let finding = cache.private_channels
.values()
@@ -545,9 +574,9 @@ impl User {
/// [direct_message]: #method.direct_message
#[cfg(feature = "builder")]
#[inline]
- pub fn dm<F>(&self, f: F) -> Result<Message>
+ pub fn dm<F>(&self, context: &Context, f: F) -> Result<Message>
where for <'b> F: FnOnce(&'b mut CreateMessage<'b>) -> &'b mut CreateMessage<'b> {
- self.direct_message(f)
+ self.direct_message(&context, f)
}
/// Retrieves the URL to the user's avatar, falling back to the default
@@ -585,17 +614,17 @@ impl User {
/// [`Role`]: ../guild/struct.Role.html
/// [`Cache`]: ../../cache/struct.Cache.html
// no-cache would warn on guild_id.
- pub fn has_role<G, R>(&self, guild: G, role: R) -> bool
+ pub fn has_role<G, R>(&self, context: &Context, guild: G, role: R) -> bool
where G: Into<GuildContainer>, R: Into<RoleId> {
- self._has_role(guild.into(), role.into())
+ self._has_role(&context, guild.into(), role.into())
}
- fn _has_role(&self, guild: GuildContainer, role: RoleId) -> bool {
+ fn _has_role(&self, context: &Context, guild: GuildContainer, role: RoleId) -> bool {
match guild {
GuildContainer::Guild(guild) => guild.roles.contains_key(&role),
GuildContainer::Id(_guild_id) => {
feature_cache! {{
- CACHE.read()
+ context.cache.read()
.guilds
.get(&_guild_id)
.map(|g| {
@@ -622,9 +651,12 @@ impl User {
/// out-of-sync:
///
/// ```rust,no_run
- /// # use serenity::prelude::*;
- /// # use serenity::model::prelude::*;
+ /// # extern crate parking_lot;
+ /// # extern crate serenity;
/// #
+ /// # use serenity::{cache::Cache, model::prelude::*, prelude::*};
+ /// # use parking_lot::RwLock;
+ /// # use std::sync::Arc;
/// struct Handler;
///
/// impl EventHandler for Handler {
@@ -635,38 +667,42 @@ impl User {
///
/// let mut client = Client::new("token", Handler).unwrap();
/// #
- /// use serenity::model::id::UserId;
- /// use serenity::CACHE;
+ /// use serenity::{command, model::id::UserId};
/// use std::thread;
/// use std::time::Duration;
///
- /// let special_users = vec![UserId(114941315417899012), UserId(87600987040120832)];
- ///
/// // start a new thread to periodically refresh the special users' data
/// // every 12 hours
+ /// # command!(example(context) {
+ /// # let context = context.clone();
+ ///
/// let handle = thread::spawn(move || {
+ /// let special_users = vec![UserId(114941315417899012), UserId(87600987040120832)];
+ /// # let cache = Arc::new(RwLock::new(Cache::default()));
/// // 12 hours in seconds
/// let duration = Duration::from_secs(43200);
///
/// loop {
/// thread::sleep(duration);
///
- /// let cache = CACHE.read();
+ /// let cache = cache.read();
///
/// for id in &special_users {
+ ///
/// if let Some(user) = cache.user(*id) {
- /// if let Err(why) = user.write().refresh() {
+ ///
+ /// if let Err(why) = user.write().refresh(&context) {
/// println!("Error refreshing {}: {:?}", id, why);
/// }
/// }
/// }
/// }
/// });
- ///
+ /// # });
/// println!("{:?}", client.start());
/// ```
- pub fn refresh(&mut self) -> Result<()> {
- self.id.to_user().map(|replacement| {
+ pub fn refresh(&mut self, context: &Context) -> Result<()> {
+ self.id.to_user(&context).map(|replacement| {
mem::replace(self, replacement);
()
@@ -722,15 +758,15 @@ impl User {
///
/// If none is used, it returns `None`.
#[inline]
- pub fn nick_in<G>(&self, guild_id: G) -> Option<String>
+ pub fn nick_in<G>(&self, context: &Context, guild_id: G) -> Option<String>
where G: Into<GuildId> {
- self._nick_in(guild_id.into())
+ self._nick_in(&context, guild_id.into())
}
- fn _nick_in(&self, guild_id: GuildId) -> Option<String> {
+ fn _nick_in(&self, context: &Context, guild_id: GuildId) -> Option<String> {
#[cfg(feature = "cache")]
{
- guild_id.to_guild_cached().and_then(|guild| {
+ guild_id.to_guild_cached(&context.cache).and_then(|guild| {
guild.read().members.get(&self.id).and_then(|member| member.nick.clone())
})
}
@@ -769,7 +805,7 @@ impl UserId {
/// [`User`]: ../user/struct.User.html
#[cfg(feature = "cache")]
#[inline]
- pub fn to_user_cached(self) -> Option<Arc<RwLock<User>>> { CACHE.read().user(self) }
+ pub fn to_user_cached(self, cache: &Arc<RwLock<Cache>>) -> Option<Arc<RwLock<User>>> { cache.read().user(self) }
/// First attempts to find a [`User`] by its Id in the cache,
/// upon failure requests it via the REST API.
@@ -779,10 +815,10 @@ impl UserId {
///
/// [`User`]: ../user/struct.User.html
#[inline]
- pub fn to_user(self) -> Result<User> {
+ pub fn to_user(self, context: &Context) -> Result<User> {
#[cfg(feature = "cache")]
{
- if let Some(user) = CACHE.read().user(self) {
+ if let Some(user) = context.cache.read().user(self) {
return Ok(user.read().clone());
}
}
diff --git a/src/model/utils.rs b/src/model/utils.rs
index 2399db3..9cb9571 100644
--- a/src/model/utils.rs
+++ b/src/model/utils.rs
@@ -14,7 +14,7 @@ use crate::internal::prelude::*;
#[cfg(all(feature = "cache", feature = "model"))]
use super::permissions::Permissions;
#[cfg(all(feature = "cache", feature = "model"))]
-use crate::CACHE;
+use crate::cache::Cache;
pub fn default_true() -> bool {
true
@@ -206,8 +206,8 @@ pub fn serialize_gen_locked_map<K: Eq + Hash, S: Serializer, V: Serialize>(
}
#[cfg(all(feature = "cache", feature = "model"))]
-pub fn user_has_perms(channel_id: ChannelId, mut permissions: Permissions) -> Result<bool> {
- let cache = CACHE.read();
+pub fn user_has_perms(cache: &Arc<RwLock<Cache>>, channel_id: ChannelId, mut permissions: Permissions) -> Result<bool> {
+ let cache = cache.read();
let current_user = &cache.user;
let channel = match cache.channel(channel_id) {