aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIllia <[email protected]>2016-12-10 22:25:55 +0200
committerzeyla <[email protected]>2016-12-10 12:25:55 -0800
commite44838f4339b90817b5eba5df16230b02487f0cc (patch)
tree8513ab3d9d3f9c8826f85630524cca1e4a7e188d /src
parentFix no-cache+method conditional compiles (diff)
downloadserenity-e44838f4339b90817b5eba5df16230b02487f0cc.tar.xz
serenity-e44838f4339b90817b5eba5df16230b02487f0cc.zip
More config for CreateCommand, add various methods
Adds multiple configurations to the command builder, and adds methods to various structs. Context::get_current_user is a shortcut to retrieve the current user from the cache. Message::get_member retrieves the member object of the message, if sent in a guild. Message::is_private checks if the message was sent in a Group or PrivateChannel. User::member retrieves the user's member object in a guild by Id; Adds 6 configurations to the command builder: - dm_only: whether the command can only be used in direct messages; - guild_only: whether the command can only be used in guilds; - help_available: whether the command should be displayed in the help list; - max_args: specify the maximum number of arguments a command must be given; - min_args: specify the minimum number of arguments a command must be given; - required_permissions: the permissions a member must have to be able to use the command;
Diffstat (limited to 'src')
-rw-r--r--src/client/context.rs11
-rw-r--r--src/client/dispatch.rs2
-rw-r--r--src/client/event_store.rs54
-rw-r--r--src/client/gateway/prep.rs4
-rw-r--r--src/client/gateway/shard.rs2
-rw-r--r--src/client/mod.rs12
-rw-r--r--src/error.rs14
-rw-r--r--src/ext/framework/command.rs13
-rw-r--r--src/ext/framework/configuration.rs24
-rw-r--r--src/ext/framework/create_command.rs49
-rw-r--r--src/ext/framework/mod.rs73
-rw-r--r--src/ext/mod.rs6
-rw-r--r--src/internal/mod.rs4
-rw-r--r--src/model/channel.rs117
-rw-r--r--src/model/guild.rs68
-rw-r--r--src/model/id.rs16
-rw-r--r--src/model/invite.rs2
-rw-r--r--src/model/mod.rs8
-rw-r--r--src/model/user.rs23
-rw-r--r--src/model/utils.rs2
-rw-r--r--src/utils/macros.rs48
21 files changed, 376 insertions, 176 deletions
diff --git a/src/client/context.rs b/src/client/context.rs
index eb7246b..e646ec6 100644
--- a/src/client/context.rs
+++ b/src/client/context.rs
@@ -22,7 +22,7 @@ use ::internal::prelude::*;
use ::model::*;
use ::utils;
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
use super::CACHE;
/// The context is a general utility struct provided on event dispatches, which
@@ -1077,6 +1077,15 @@ impl Context {
Ok(channels)
}
+ /// Gets information about the current user.
+ ///
+ /// Note this is shorthand for retrieving the current user through the
+ /// cache, and will perform a clone.
+ #[cfg(all(feature = "cache", feature = "methods"))]
+ pub fn get_current_user(&self) -> CurrentUser {
+ CACHE.read().unwrap().user.clone()
+ }
+
/// Gets an [`Guild`]'s emoji by Id.
///
/// Requires the [Manage Emojis] permission.
diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs
index 7b0439d..5f61ea9 100644
--- a/src/client/dispatch.rs
+++ b/src/client/dispatch.rs
@@ -11,7 +11,7 @@ use ::model::{ChannelId, Message};
#[cfg(feature="framework")]
use ::ext::framework::Framework;
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
use super::CACHE;
macro_rules! handler {
diff --git a/src/client/event_store.rs b/src/client/event_store.rs
index e2ddf94..7cc7e81 100644
--- a/src/client/event_store.rs
+++ b/src/client/event_store.rs
@@ -14,7 +14,7 @@ use ::model::event::{
};
use ::model::*;
-#[cfg(not(feature = "cache"))]
+#[cfg(not(feature="cache"))]
use ::model::event::{
CallUpdateEvent,
GuildMemberUpdateEvent,
@@ -43,13 +43,13 @@ use ::model::event::{
#[derive(Default)]
pub struct EventStore {
pub on_call_create: Option<Arc<Fn(Context, Call) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_call_delete: Option<Arc<Fn(Context, ChannelId, Option<Call>) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_call_delete: Option<Arc<Fn(Context, ChannelId) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_call_update: Option<Arc<Fn(Context, Option<Call>, Option<Call>) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_call_update: Option<Arc<Fn(Context, CallUpdateEvent) + Send + Sync + 'static>>,
pub on_channel_create: Option<Arc<Fn(Context, Channel) + Send + Sync + 'static>>,
pub on_channel_delete: Option<Arc<Fn(Context, Channel) + Send + Sync + 'static>>,
@@ -57,45 +57,45 @@ pub struct EventStore {
pub on_channel_pins_update: Option<Arc<Fn(Context, ChannelPinsUpdateEvent) + Send + Sync + 'static>>,
pub on_channel_recipient_addition: Option<Arc<Fn(Context, ChannelId, User) + Send + Sync + 'static>>,
pub on_channel_recipient_removal: Option<Arc<Fn(Context, ChannelId, User) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_channel_update: Option<Arc<Fn(Context, Option<Channel>, Channel) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_channel_update: Option<Arc<Fn(Context, Channel) + Send + Sync + 'static>>,
pub on_friend_suggestion_create: Option<Arc<Fn(Context, User, Vec<SuggestionReason>) + Send + Sync + 'static>>,
pub on_friend_suggestion_delete: Option<Arc<Fn(Context, UserId) + Send + Sync + 'static>>,
pub on_guild_ban_addition: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>,
pub on_guild_ban_removal: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>,
pub on_guild_create: Option<Arc<Fn(Context, Guild) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_guild_delete: Option<Arc<Fn(Context, PartialGuild, Option<Guild>) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_guild_delete: Option<Arc<Fn(Context, PartialGuild) + Send + Sync + 'static>>,
pub on_guild_emojis_update: Option<Arc<Fn(Context, GuildId, HashMap<EmojiId, Emoji>) + Send + Sync + 'static>>,
pub on_guild_integrations_update: Option<Arc<Fn(Context, GuildId) + Send + Sync + 'static>>,
pub on_guild_member_addition: Option<Arc<Fn(Context, GuildId, Member) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_guild_member_removal: Option<Arc<Fn(Context, GuildId, User, Option<Member>) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_guild_member_removal: Option<Arc<Fn(Context, GuildId, User) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_guild_member_update: Option<Arc<Fn(Context, Option<Member>, Member) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_guild_member_update: Option<Arc<Fn(Context, GuildMemberUpdateEvent) + Send + Sync + 'static>>,
pub on_guild_members_chunk: Option<Arc<Fn(Context, GuildId, HashMap<UserId, Member>) + Send + Sync + 'static>>,
pub on_guild_role_create: Option<Arc<Fn(Context, GuildId, Role) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_guild_role_delete: Option<Arc<Fn(Context, GuildId, RoleId, Option<Role>) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_guild_role_delete: Option<Arc<Fn(Context, GuildId, RoleId) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_guild_role_update: Option<Arc<Fn(Context, GuildId, Option<Role>, Role) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_guild_role_update: Option<Arc<Fn(Context, GuildId, Role) + Send + Sync + 'static>>,
pub on_guild_sync: Option<Arc<Fn(Context, GuildSyncEvent) + Send + Sync + 'static>>,
pub on_guild_unavailable: Option<Arc<Fn(Context, GuildId) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_guild_update: Option<Arc<Fn(Context, Option<Guild>, PartialGuild) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_guild_update: Option<Arc<Fn(Context, PartialGuild) + Send + Sync + 'static>>,
pub on_message: Option<Arc<Fn(Context, Message) + Send + Sync + 'static>>,
pub on_message_ack: Option<Arc<Fn(Context, ChannelId, Option<MessageId>) + Send + Sync + 'static>>,
@@ -105,9 +105,9 @@ pub struct EventStore {
pub on_reaction_remove: Option<Arc<Fn(Context, Reaction) + Send + Sync + 'static>>,
pub on_reaction_remove_all: Option<Arc<Fn(Context, ChannelId, MessageId) + Send + Sync + 'static>>,
pub on_message_update: Option<Arc<Fn(Context, MessageUpdateEvent) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_note_update: Option<Arc<Fn(Context, UserId, Option<String>, String) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_note_update: Option<Arc<Fn(Context, UserId, String) + Send + Sync + 'static>>,
pub on_presence_replace: Option<Arc<Fn(Context, Vec<Presence>) + Send + Sync + 'static>>,
pub on_presence_update: Option<Arc<Fn(Context, PresenceUpdateEvent) + Send + Sync + 'static>>,
@@ -117,17 +117,17 @@ pub struct EventStore {
pub on_resume: Option<Arc<Fn(Context, ResumedEvent) + Send + Sync + 'static>>,
pub on_typing_start: Option<Arc<Fn(Context, TypingStartEvent) + Send + Sync + 'static>>,
pub on_unknown: Option<Arc<Fn(Context, String, BTreeMap<String, Value>) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_user_guild_settings_update: Option<Arc<Fn(Context, Option<UserGuildSettings>, UserGuildSettings) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_user_guild_settings_update: Option<Arc<Fn(Context, UserGuildSettings) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_user_update: Option<Arc<Fn(Context, CurrentUser, CurrentUser) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_user_update: Option<Arc<Fn(Context, CurrentUser) + Send + Sync + 'static>>,
- #[cfg(feature = "cache")]
+ #[cfg(feature="cache")]
pub on_user_settings_update: Option<Arc<Fn(Context, UserSettings, UserSettings) + Send + Sync + 'static>>,
- #[cfg(not(feature = "cache"))]
+ #[cfg(not(feature="cache"))]
pub on_user_settings_update: Option<Arc<Fn(Context, UserSettingsUpdateEvent) + Send + Sync + 'static>>,
pub on_voice_server_update: Option<Arc<Fn(Context, VoiceServerUpdateEvent) + Send + Sync + 'static>>,
pub on_voice_state_update: Option<Arc<Fn(Context, Option<GuildId>, VoiceState) + Send + Sync + 'static>>,
diff --git a/src/client/gateway/prep.rs b/src/client/gateway/prep.rs
index 3844a8d..4602ea6 100644
--- a/src/client/gateway/prep.rs
+++ b/src/client/gateway/prep.rs
@@ -80,12 +80,12 @@ pub fn identify(token: &str, shard_info: Option<[u8; 2]>) -> Value {
.build()
}
-#[cfg(not(feature = "debug"))]
+#[cfg(not(feature="debug"))]
pub fn identify_compression(object: ObjectBuilder) -> ObjectBuilder {
object.insert("compression", true)
}
-#[cfg(feature = "debug")]
+#[cfg(feature="debug")]
pub fn identify_compression(object: ObjectBuilder) -> ObjectBuilder {
object.insert("compression", false)
}
diff --git a/src/client/gateway/shard.rs b/src/client/gateway/shard.rs
index 232d2c3..c026f0c 100644
--- a/src/client/gateway/shard.rs
+++ b/src/client/gateway/shard.rs
@@ -69,7 +69,7 @@ pub struct Shard {
ws_url: String,
/// The voice connections that this Shard is responsible for. The Shard will
/// update the voice connections' states.
- #[cfg(feature = "voice")]
+ #[cfg(feature="voice")]
pub manager: VoiceManager,
}
diff --git a/src/client/mod.rs b/src/client/mod.rs
index 843bbfe..c9a9c65 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -61,20 +61,20 @@ use ::model::event::{
};
use ::model::*;
-#[cfg(feature = "framework")]
+#[cfg(feature="framework")]
use ::ext::framework::Framework;
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
use ::ext::cache::Cache;
-#[cfg(not(feature = "cache"))]
+#[cfg(not(feature="cache"))]
use ::model::event::{
CallUpdateEvent,
GuildMemberUpdateEvent,
UserSettingsUpdateEvent,
};
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
lazy_static! {
/// A mutable and lazily-initialized static binding. It can be accessed
/// across any function and in any context.
@@ -841,7 +841,7 @@ impl Client {
}
}
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
impl Client {
/// Attaches a handler for when a [`CallDelete`] is received.
///
@@ -1003,7 +1003,7 @@ impl Client {
}
}
-#[cfg(not(feature = "cache"))]
+#[cfg(not(feature="cache"))]
impl Client {
/// Attaches a handler for when a [`CallDelete`] is received.
///
diff --git a/src/error.rs b/src/error.rs
index 10f8d36..41bda57 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -7,7 +7,7 @@ use std::fmt::{self, Display, Error as FormatError};
use websocket::result::WebSocketError;
use ::client::gateway::GatewayError;
use ::client::ClientError;
-#[cfg(feature = "voice")]
+#[cfg(feature="voice")]
use opus::Error as OpusError;
#[cfg(feature="voice")]
use ::ext::voice::VoiceError;
@@ -66,12 +66,12 @@ pub enum Error {
/// An error from the `rust-websocket` crate.
WebSocket(WebSocketError),
/// An error from the `opus` crate.
- #[cfg(feature = "voice")]
+ #[cfg(feature="voice")]
Opus(OpusError),
/// Indicating an error within the [voice module].
///
/// [voice module]: ext/voice/index.html
- #[cfg(feature = "voice")]
+ #[cfg(feature="voice")]
Voice(VoiceError),
}
@@ -99,7 +99,7 @@ impl From<JsonError> for Error {
}
}
-#[cfg(feature = "voice")]
+#[cfg(feature="voice")]
impl From<OpusError> for Error {
fn from(e: OpusError) -> Error {
Error::Opus(e)
@@ -119,7 +119,7 @@ impl Display for Error {
Error::Io(ref inner) => inner.fmt(f),
Error::Json(ref inner) => inner.fmt(f),
Error::WebSocket(ref inner) => inner.fmt(f),
- #[cfg(feature = "voice")]
+ #[cfg(feature="voice")]
Error::Opus(ref inner) => inner.fmt(f),
_ => f.write_str(self.description()),
}
@@ -138,9 +138,9 @@ impl StdError for Error {
Error::Json(ref inner) => inner.description(),
Error::Url(ref inner) => inner,
Error::WebSocket(ref inner) => inner.description(),
- #[cfg(feature = "voice")]
+ #[cfg(feature="voice")]
Error::Opus(ref inner) => inner.description(),
- #[cfg(feature = "voice")]
+ #[cfg(feature="voice")]
Error::Voice(_) => "Voice error",
}
}
diff --git a/src/ext/framework/command.rs b/src/ext/framework/command.rs
index b7d5bb8..204c90c 100644
--- a/src/ext/framework/command.rs
+++ b/src/ext/framework/command.rs
@@ -2,6 +2,7 @@ use std::sync::Arc;
use super::Configuration;
use ::client::Context;
use ::model::Message;
+use ::model::Permissions;
use std::collections::HashMap;
pub type Check = Fn(&Context, &Message) -> bool + Send + Sync + 'static;
@@ -33,6 +34,18 @@ pub struct Command {
pub usage: Option<String>,
/// Whether arguments should be parsed using quote parser or not.
pub use_quotes: bool,
+ /// Minumum amount of arguments that should be passed.
+ pub min_args: Option<i32>,
+ /// Maximum amount of arguments that can be passed.
+ pub max_args: Option<i32>,
+ /// Permissions required to use this command.
+ pub required_permissions: Permissions,
+ /// Whether command should be displayed in help list or not, used by other commands.
+ pub help_available: bool,
+ /// Whether command can be used only privately or not.
+ pub dm_only: bool,
+ /// Whether command can be used only in guilds or not.
+ pub guild_only: bool,
}
pub fn positions(ctx: &Context, content: &str, conf: &Configuration) -> Option<Vec<usize>> {
diff --git a/src/ext/framework/configuration.rs b/src/ext/framework/configuration.rs
index 9caa48b..e95faea 100644
--- a/src/ext/framework/configuration.rs
+++ b/src/ext/framework/configuration.rs
@@ -3,6 +3,18 @@ use super::command::PrefixCheck;
use ::client::rest;
use ::client::Context;
+/// Account type used for configuration.
+pub enum AccountType {
+ /// Connected client will only listen to itself.
+ Selfbot,
+ /// Connected client will ignore all bot accounts.
+ Bot,
+ /// Connected client will listen to everyone.
+ Any,
+ #[doc(hidden)]
+ Automatic
+}
+
/// The configuration to use for a [`Framework`] associated with a [`Client`]
/// instance.
///
@@ -36,6 +48,8 @@ pub struct Configuration {
pub prefixes: Vec<String>,
#[doc(hidden)]
pub dynamic_prefix: Option<Box<PrefixCheck>>,
+ #[doc(hidden)]
+ pub account_type: AccountType
}
impl Configuration {
@@ -136,6 +150,13 @@ impl Configuration {
self
}
+ /// Allows you to change what accounts to ignore.
+ pub fn account_type(mut self, account_type: AccountType) -> Self {
+ self.account_type = account_type;
+
+ self
+ }
+
/// Sets the prefix to respond to. This can either be a single-char or
/// multi-char string.
pub fn dynamic_prefix<F>(mut self, dynamic_prefix: F) -> Self
@@ -159,7 +180,8 @@ impl Default for Configuration {
on_mention: None,
allow_whitespace: false,
prefixes: vec![],
- dynamic_prefix: None
+ dynamic_prefix: None,
+ account_type: AccountType::Automatic
}
}
}
diff --git a/src/ext/framework/create_command.rs b/src/ext/framework/create_command.rs
index 824c3dd..6d40592 100644
--- a/src/ext/framework/create_command.rs
+++ b/src/ext/framework/create_command.rs
@@ -5,6 +5,7 @@ use std::default::Default;
use std::sync::Arc;
use ::client::Context;
use ::model::Message;
+use ::model::Permissions;
pub struct CreateCommand(pub Command);
@@ -54,6 +55,48 @@ impl CreateCommand {
self
}
+ /// Whether command should be displayed in help list or not, used by other commands.
+ pub fn help_available(mut self, help_available: bool) -> Self {
+ self.0.help_available = help_available;
+
+ self
+ }
+
+ /// Whether command can be used only privately or not.
+ pub fn dm_only(mut self, dm_only: bool) -> Self {
+ self.0.dm_only = dm_only;
+
+ self
+ }
+
+ /// Whether command can be used only in guilds or not.
+ pub fn guild_only(mut self, guild_only: bool) -> Self {
+ self.0.guild_only = guild_only;
+
+ self
+ }
+
+ /// Minumum amount of arguments that should be passed.
+ pub fn min_args(mut self, min_args: i32) -> Self {
+ self.0.min_args = Some(min_args);
+
+ self
+ }
+
+ /// Maximum amount of arguments that can be passed.
+ pub fn max_args(mut self, max_args: i32) -> Self {
+ self.0.max_args = Some(max_args);
+
+ self
+ }
+
+ /// Maximum amount of arguments that can be passed.
+ pub fn required_permissions(mut self, required_permissions: Permissions) -> Self {
+ self.0.required_permissions = required_permissions;
+
+ self
+ }
+
/// A function that can be called when a command is received.
///
/// See [`exec_str`] if you _only_ need to return a string on command use.
@@ -126,6 +169,12 @@ impl Default for Command {
desc: None,
usage: None,
use_quotes: true,
+ min_args: None,
+ max_args: None,
+ required_permissions: Permissions::empty(),
+ dm_only: false,
+ guild_only: false,
+ help_available: true
}
}
}
diff --git a/src/ext/framework/mod.rs b/src/ext/framework/mod.rs
index 077f767..fa7fdac 100644
--- a/src/ext/framework/mod.rs
+++ b/src/ext/framework/mod.rs
@@ -58,7 +58,7 @@ mod configuration;
mod create_command;
pub use self::command::{Command, CommandType};
-pub use self::configuration::Configuration;
+pub use self::configuration::{AccountType, Configuration};
pub use self::create_command::CreateCommand;
use self::command::{Hook, InternalCommand};
@@ -68,6 +68,8 @@ use std::thread;
use ::client::Context;
use ::model::Message;
use ::utils;
+use ::client::CACHE;
+use ::model::Permissions;
/// A macro to generate "named parameters". This is useful to avoid manually
/// using the "arguments" parameter and manually parsing types.
@@ -194,6 +196,29 @@ impl Framework {
#[doc(hidden)]
pub fn dispatch(&mut self, context: Context, message: Message) {
+ match self.configuration.account_type {
+ AccountType::Selfbot => {
+ if message.author.id != CACHE.read().unwrap().user.id {
+ return;
+ }
+ },
+ AccountType::Bot => {
+ if message.author.bot {
+ return;
+ }
+ },
+ AccountType::Automatic => {
+ let cache = CACHE.read().unwrap();
+ if cache.user.bot {
+ if message.author.bot {
+ return;
+ }
+ } else if message.author.id != cache.user.id {
+ return;
+ }
+ },
+ AccountType::Any => {}
+ }
let res = command::positions(&context, &message.content, &self.configuration);
let positions = match res {
@@ -230,6 +255,14 @@ impl Framework {
});
if let Some(command) = self.commands.get(&built) {
+ if message.is_private() {
+ if command.guild_only {
+ return;
+ }
+ } else if command.dm_only {
+ return;
+ }
+
for check in &command.checks {
if !(check)(&context, &message) {
continue 'outer;
@@ -255,6 +288,38 @@ impl Framework {
.collect::<Vec<String>>()
};
+ if let Some(x) = command.min_args {
+ if args.len() < x as usize {
+ return;
+ }
+ }
+
+ if let Some(x) = command.max_args {
+ if args.len() > x as usize {
+ return;
+ }
+ }
+
+ if !command.required_permissions.is_empty() {
+ let mut permissions_fulfilled = false;
+
+ if let Some(member) = message.get_member() {
+ let cache = CACHE.read().unwrap();
+
+ if let Ok(guild_id) = member.find_guild() {
+ if let Some(guild) = cache.get_guild(guild_id) {
+ let perms = guild.permissions_for(message.channel_id, message.author.id);
+
+ permissions_fulfilled = perms.contains(command.required_permissions);
+ }
+ }
+ }
+
+ if !permissions_fulfilled {
+ return;
+ }
+ }
+
match command.exec {
CommandType::StringResponse(ref x) => {
let _ = &context.say(x);
@@ -302,6 +367,12 @@ impl Framework {
desc: None,
usage: None,
use_quotes: false,
+ dm_only: false,
+ guild_only: false,
+ help_available: true,
+ min_args: None,
+ max_args: None,
+ required_permissions: Permissions::empty()
}));
self.initialized = true;
diff --git a/src/ext/mod.rs b/src/ext/mod.rs
index 9605466..ba46daf 100644
--- a/src/ext/mod.rs
+++ b/src/ext/mod.rs
@@ -13,9 +13,9 @@
//! [`Client`]: ../client/struct.Client.html
//! [`Shard`]: ../client/gateway/struct.Shard.html
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
pub mod cache;
-#[cfg(feature = "framework")]
+#[cfg(feature="framework")]
pub mod framework;
-#[cfg(feature = "voice")]
+#[cfg(feature="voice")]
pub mod voice;
diff --git a/src/internal/mod.rs b/src/internal/mod.rs
index 9dd4676..591419b 100644
--- a/src/internal/mod.rs
+++ b/src/internal/mod.rs
@@ -1,8 +1,8 @@
pub mod prelude;
pub mod ws_impl;
-#[cfg(feature = "voice")]
+#[cfg(feature="voice")]
mod timer;
-#[cfg(feature = "voice")]
+#[cfg(feature="voice")]
pub use self::timer::Timer;
diff --git a/src/model/channel.rs b/src/model/channel.rs
index 75dfc54..2724f1e 100644
--- a/src/model/channel.rs
+++ b/src/model/channel.rs
@@ -12,34 +12,34 @@ use ::constants;
use ::internal::prelude::*;
use ::utils::decode_array;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use hyper::Client as HyperClient;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use serde_json::builder::ObjectBuilder;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use std::fs::File;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use std::io::{Read, Write as IoWrite};
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use std::mem;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use std::path::{Path, PathBuf};
-#[cfg(all(feature="cache", feature = "methods"))]
+#[cfg(all(feature="cache", feature="methods"))]
use super::utils;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use ::utils::builder::{CreateEmbed, CreateInvite, EditChannel};
-#[cfg(all(feature = "cache", feature = "methods"))]
+#[cfg(all(feature="cache", feature="methods"))]
use ::client::CACHE;
-#[cfg(all(feature = "methods"))]
+#[cfg(all(feature="methods"))]
use ::client::rest;
-#[cfg(all(feature = "cache", feature = "methods"))]
+#[cfg(all(feature="cache", feature="methods"))]
use ::ext::cache::ChannelRef;
impl Attachment {
/// If this attachment is an image, then a tuple of the width and height
/// in pixels is returned.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn dimensions(&self) -> Option<(u64, u64)> {
if let (Some(width), Some(height)) = (self.width, self.height) {
Some((width, height))
@@ -114,7 +114,7 @@ impl Attachment {
/// [`Error::Hyper`]: ../enum.Error.html#variant.Hyper
/// [`Error::Io`]: ../enum.Error.html#variant.Io
/// [`Message`]: struct.Message.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn download(&self) -> Result<Vec<u8>> {
let hyper = HyperClient::new();
let mut response = hyper.get(&self.url).send()?;
@@ -179,7 +179,7 @@ impl Attachment {
/// [`Error::Hyper`]: ../enum.Error.html#variant.Hyper
/// [`Error::Io`]: ../enum.Error.html#variant.Io
/// [`Message`]: struct.Message.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn download_to_directory<P: AsRef<Path>>(&self, path: P) -> Result<PathBuf> {
let bytes = self.download()?;
@@ -213,7 +213,7 @@ impl Channel {
/// closest functionality is leaving it.
///
/// [`Group`]: struct.Group.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete(&self) -> Result<()> {
match *self {
Channel::Group(ref group) => {
@@ -276,7 +276,7 @@ impl Embed {
/// This should only be useful in conjunction with [`Webhook::execute`].
///
/// [`Webhook::execute`]: struct.Webhook.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
#[inline(always)]
pub fn fake<F>(f: F) -> Value where F: FnOnce(CreateEmbed) -> CreateEmbed {
Value::Object(f(CreateEmbed::default()).0)
@@ -293,7 +293,7 @@ impl Group {
/// user.
///
/// [`rest::add_group_recipient`]: ../client/rest/fn.add_group_recipient.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn add_recipient<U: Into<UserId>>(&self, user: U) -> Result<()> {
let user = user.into();
@@ -306,7 +306,7 @@ impl Group {
}
/// Broadcasts that the current user is typing in the group.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn broadcast_typing(&self) -> Result<()> {
rest::broadcast_typing(self.channel_id.0)
}
@@ -326,7 +326,7 @@ impl Group {
///
/// [`ClientError::DeleteMessageDaysAmount`]: ../client/enum.ClientError.html#variant.DeleteMessageDaysAmount
/// [`Context::delete_messages`]: ../client/struct.Context.html#delete_messages
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete_messages(&self, message_ids: &[MessageId]) -> Result<()> {
if message_ids.len() < 2 || message_ids.len() > 100 {
return Err(Error::Client(ClientError::BulkDeleteAmount));
@@ -350,7 +350,7 @@ impl Group {
}
/// Leaves the group.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn leave(&self) -> Result<Group> {
rest::leave_group(self.channel_id.0)
}
@@ -379,7 +379,7 @@ impl Group {
}
/// Retrieves the list of messages that have been pinned in the group.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn pins(&self) -> Result<Vec<Message>> {
rest::get_pins(self.channel_id.0)
}
@@ -388,7 +388,7 @@ impl Group {
/// the group, then nothing is done.
///
/// **Note**: This is only available to the group owner.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn remove_recipient<U: Into<UserId>>(&self, user: U) -> Result<()> {
let user = user.into();
@@ -407,7 +407,7 @@ impl Group {
/// **Note**: Requires the [Send Messages] permission.
///
/// [Send Messages]: permissions/constant.SEND_MESSAGES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn send_message(&self, content: &str) -> Result<Message> {
let map = ObjectBuilder::new()
.insert("content", content)
@@ -436,7 +436,7 @@ impl Message {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidUser
/// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete(&self) -> Result<()> {
feature_cache_enabled! {{
let req = permissions::MANAGE_MESSAGES;
@@ -464,7 +464,7 @@ impl Message {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`Reaction`]: struct.Reaction.html
/// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete_reactions(&self) -> Result<()> {
feature_cache_enabled! {{
let req = permissions::MANAGE_MESSAGES;
@@ -501,7 +501,7 @@ impl Message {
///
/// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidUser
/// [`ClientError::MessageTooLong`]: enum.ClientError.html#variant.MessageTooLong
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn edit<F>(&mut self, new_content: &str, embed: F) -> Result<()>
where F: FnOnce(CreateEmbed) -> CreateEmbed {
if let Some(length_over) = Message::overflow_length(new_content) {
@@ -537,7 +537,7 @@ impl Message {
///
/// Returns `None` if the channel data or guild data does not exist in the
/// cache.
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn guild_id(&self) -> Option<GuildId> {
let cache = CACHE.read().unwrap();
@@ -547,6 +547,31 @@ impl Message {
}
}
+ /// Gets message author as member. Won't work on private messages.
+ #[cfg(all(feature="cache", feature="methods"))]
+ pub fn get_member(&self) -> Option<Member> {
+ let cache = CACHE.read().unwrap();
+
+ if let Some(ChannelRef::Guild(channel)) = cache.get_channel(self.channel_id) {
+ if let Some(guild) = channel.guild_id.find() {
+ if let Some(member) = guild.members.get(&self.author.id) {
+ return Some(member.clone())
+ }
+ }
+ }
+
+ None
+ }
+
+ /// True if message was sent using direct messages.
+ #[cfg(all(feature="cache", feature="methods"))]
+ pub fn is_private(&self) -> bool {
+ match CACHE.read().unwrap().get_channel(self.channel_id) {
+ Some(ChannelRef::Group(_)) | Some(ChannelRef::Private(_)) => true,
+ _ => false,
+ }
+ }
+
/// Checks the length of a string to ensure that it is within Discord's
/// maximum message length limit.
///
@@ -578,7 +603,7 @@ impl Message {
///
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn pin(&self) -> Result<()> {
feature_cache_enabled! {{
let req = permissions::MANAGE_MESSAGES;
@@ -605,7 +630,7 @@ impl Message {
/// [`Emoji`]: struct.Emoji.html
/// [Add Reactions]: permissions/constant.ADD_REACTIONS.html
/// [permissions]: permissions
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn react<R: Into<ReactionType>>(&self, reaction_type: R) -> Result<()> {
feature_cache_enabled! {{
let req = permissions::ADD_REACTIONS;
@@ -642,7 +667,7 @@ impl Message {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`ClientError::MessageTooLong`]: enum.ClientError.html#variant.MessageTooLong
/// [Send Messages]: permissions/constant.SEND_MESSAGES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn reply(&self, content: &str) -> Result<Message> {
if let Some(length_over) = Message::overflow_length(content) {
return Err(Error::Client(ClientError::MessageTooLong(length_over)));
@@ -681,7 +706,7 @@ impl Message {
///
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn unpin(&self) -> Result<()> {
feature_cache_enabled! {{
let req = permissions::MANAGE_MESSAGES;
@@ -717,7 +742,7 @@ impl PermissionOverwrite {
impl PrivateChannel {
/// Broadcasts that the current user is typing to the recipient.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn broadcast_typing(&self) -> Result<()> {
rest::broadcast_typing(self.id.0)
}
@@ -749,7 +774,7 @@ impl PrivateChannel {
/// [`ClientError::InvalidUser`] if the current user is not a bot user.
///
/// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidOperationAsUser
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete_messages(&self, message_ids: &[MessageId]) -> Result<()> {
feature_cache_enabled! {{
if !CACHE.read().unwrap().user.bot {
@@ -771,14 +796,14 @@ impl PrivateChannel {
/// Deletes the channel. This does not delete the contents of the channel,
/// and is equivilant to closing a private channel on the client, which can
/// be re-opened.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete(&self) -> Result<Channel> {
rest::delete_channel(self.id.0)
}
/// Retrieves the list of messages that have been pinned in the private
/// channel.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn pins(&self) -> Result<Vec<Message>> {
rest::get_pins(self.id.0)
}
@@ -794,7 +819,7 @@ impl PrivateChannel {
/// over the limit.
///
/// [`ClientError::MessageTooLong`]: ../client/enum.ClientError.html#variant.MessageTooLong
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn send_message(&self, content: &str) -> Result<Message> {
if let Some(length_over) = Message::overflow_length(content) {
return Err(Error::Client(ClientError::MessageTooLong(length_over)));
@@ -832,7 +857,7 @@ impl GuildChannel {
///
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Send Messages]: permissions/constants.SEND_MESSAGES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn broadcast_typing(&self) -> Result<()> {
rest::broadcast_typing(self.id.0)
}
@@ -847,7 +872,7 @@ impl GuildChannel {
/// let invite = channel.create_invite(|i| i
/// .max_uses(5));
/// ```
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn create_invite<F>(&self, f: F) -> Result<RichInvite>
where F: FnOnce(CreateInvite) -> CreateInvite {
feature_cache_enabled! {{
@@ -892,7 +917,7 @@ impl GuildChannel {
}
/// Deletes this channel, returning the channel on a successful deletion.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete(&self) -> Result<Channel> {
feature_cache_enabled! {{
let req = permissions::MANAGE_CHANNELS;
@@ -918,7 +943,7 @@ impl GuildChannel {
/// .name("test")
/// .bitrate(71));
/// ```
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn edit<F>(&mut self, f: F) -> Result<()>
where F: FnOnce(EditChannel) -> EditChannel {
@@ -951,13 +976,13 @@ impl GuildChannel {
///
/// **Note**: Right now this performs a clone of the guild. This will be
/// optimized in the future.
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn guild(&self) -> Option<Guild> {
CACHE.read().unwrap().get_guild(self.guild_id).cloned()
}
/// Gets all channel's pins.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn pins(&self) -> Result<Vec<Message>> {
rest::get_pins(self.id.0)
}
@@ -980,7 +1005,7 @@ impl GuildChannel {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`ClientError::MessageTooLong`]: ../client/enum.ClientError.html#variant.MessageTooLong
/// [Send Messages]: permissions/constant.SEND_MESSAGES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn send_message(&self, content: &str) -> Result<Message> {
if let Some(length_over) = Message::overflow_length(content) {
return Err(Error::Client(ClientError::MessageTooLong(length_over)));
@@ -1008,7 +1033,7 @@ impl GuildChannel {
/// **Note**: Requires the [Manage Webhooks] permission.
///
/// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn webhooks(&self) -> Result<Vec<Webhook>> {
rest::get_channel_webhooks(self.id.0)
}
@@ -1037,7 +1062,7 @@ impl Reaction {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Manage Messages]: permissions/constant.MANAGE_MESSAGES.html
/// [permissions]: permissions
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete(&self) -> Result<()> {
feature_cache! {{
let user = if self.user_id == CACHE.read().unwrap().user.id {
@@ -1095,7 +1120,7 @@ impl Reaction {
/// [`User`]: struct.User.html
/// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html
/// [permissions]: permissions
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn users<R, U>(&self,
reaction_type: R,
limit: Option<u8>,
diff --git a/src/model/guild.rs b/src/model/guild.rs
index 0c7bb57..0d379b9 100644
--- a/src/model/guild.rs
+++ b/src/model/guild.rs
@@ -16,7 +16,7 @@ use super::*;
use ::internal::prelude::*;
use ::utils::decode_array;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use serde_json::builder::ObjectBuilder;
#[cfg(all(feature="cache", feature = "methods"))]
use std::mem;
@@ -27,9 +27,9 @@ use ::utils::builder::EditMember;
#[cfg(feature = "methods")]
use ::client::rest;
-#[cfg(all(feature = "cache", feature = "methods"))]
+#[cfg(all(feature="cache", feature="methods"))]
use ::client::CACHE;
-#[cfg(all(feature = "cache", feature = "methods"))]
+#[cfg(all(feature="cache", feature="methods"))]
use ::utils::Colour;
impl From<PartialGuild> for GuildContainer {
@@ -54,7 +54,7 @@ impl Emoji {
/// Finds the [`Guild`] that owns the emoji by looking through the Cache.
///
/// [`Guild`]: struct.Guild.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn find_guild_id(&self) -> Option<GuildId> {
CACHE.read()
.unwrap()
@@ -71,7 +71,7 @@ impl Emoji {
/// **Note**: Only user accounts may use this method.
///
/// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn delete(&self) -> Result<()> {
match self.find_guild_id() {
Some(guild_id) => rest::delete_emoji(guild_id.0, self.id.0),
@@ -86,7 +86,7 @@ impl Emoji {
/// **Note**: Only user accounts may use this method.
///
/// [Manage Emojis]: permissions/constant.MANAGE_EMOJIS.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn edit(&mut self, name: &str) -> Result<()> {
match self.find_guild_id() {
Some(guild_id) => {
@@ -132,7 +132,7 @@ impl GuildInfo {
impl PartialGuild {
/// Finds a role by Id within the guild.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn find_role<R: Into<RoleId>>(&self, role_id: R) -> Option<&Role> {
self.roles.get(&role_id.into())
}
@@ -144,7 +144,7 @@ impl PartialGuild {
/// **Note**: Requires the [Change Nickname] permission.
///
/// [Change Nickname]: permissions/constant.CHANGE_NICKNAME.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
#[inline]
pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> {
rest::edit_nickname(self.id.0, new_nickname)
@@ -161,7 +161,7 @@ impl PartialGuild {
/// **Note**: Requires the [Manage Webhooks] permission.
///
/// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
#[inline]
pub fn webhooks(&self) -> Result<Vec<Webhook>> {
rest::get_guild_webhooks(self.id.0)
@@ -169,7 +169,7 @@ impl PartialGuild {
}
impl Guild {
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
fn has_perms(&self, mut permissions: Permissions) -> Result<bool> {
let member = match self.get_member(CACHE.read().unwrap().user.id) {
Some(member) => member,
@@ -209,7 +209,7 @@ impl Guild {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`User`]: struct.User.html
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn ban<U: Into<UserId>>(&self, user: U, delete_message_days: u8)
-> Result<()> {
if delete_message_days > 7 {
@@ -239,7 +239,7 @@ impl Guild {
/// [`Ban`]: struct.Ban.html
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn bans(&self) -> Result<Vec<Ban>> {
feature_cache_enabled! {{
let req = permissions::BAN_MEMBERS;
@@ -274,7 +274,7 @@ impl Guild {
/// [`Channel`]: struct.Channel.html
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Manage Channels]: permissions/constants.MANAGE_CHANNELS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn create_channel(&mut self, name: &str, kind: ChannelType)
-> Result<Channel> {
feature_cache_enabled! {{
@@ -308,7 +308,7 @@ impl Guild {
/// [`Context::create_role`]: ../client/struct.Context.html#method.create_role
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constants.MANAGE_ROLES.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn create_role<F>(&self, f: F) -> Result<Role>
where F: FnOnce(EditRole) -> EditRole {
feature_cache_enabled! {{
@@ -381,7 +381,7 @@ impl Guild {
/// if the current user is not the guild owner.
///
/// [`ClientError::InvalidUser`]: ../client/enum.ClientError.html#variant.InvalidUser
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete(&self) -> Result<PartialGuild> {
feature_cache_enabled! {{
if self.owner_id != CACHE.read().unwrap().user.id {
@@ -408,7 +408,7 @@ impl Guild {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`Context::edit_guild`]: ../client/struct.Context.html#method.edit_guild
/// [Manage Guild]: permissions/constants.MANAGE_GUILD.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn edit<F>(&mut self, f: F) -> Result<()>
where F: FnOnce(EditGuild) -> EditGuild {
feature_cache_enabled! {{
@@ -457,7 +457,7 @@ impl Guild {
///
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Change Nickname]: permissions/constant.CHANGE_NICKNAME.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn edit_nickname(&self, new_nickname: Option<&str>) -> Result<()> {
feature_cache_enabled! {{
let req = permissions::CHANGE_NICKNAME;
@@ -489,7 +489,7 @@ impl Guild {
///
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn get_invites(&self) -> Result<Vec<RichInvite>> {
feature_cache_enabled! {{
let req = permissions::MANAGE_GUILD;
@@ -563,7 +563,7 @@ impl Guild {
}
/// Leaves the guild.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn leave(&self) -> Result<PartialGuild> {
rest::leave_guild(self.id.0)
}
@@ -693,7 +693,7 @@ impl Guild {
/// [`GuildPrune`]: struct.GuildPrune.html
/// [`Member`]: struct.Member.html
/// [Kick Members]: permissions/constant.KICK_MEMBERS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn prune_count(&self, days: u16) -> Result<GuildPrune> {
feature_cache_enabled! {{
let req = permissions::KICK_MEMBERS;
@@ -725,7 +725,7 @@ impl Guild {
/// [`GuildPrune`]: struct.GuildPrune.html
/// [`Member`]: struct.Member.html
/// [Kick Members]: permissions/constant.KICK_MEMBERS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn start_prune(&self, days: u16) -> Result<GuildPrune> {
feature_cache_enabled! {{
let req = permissions::KICK_MEMBERS;
@@ -754,7 +754,7 @@ impl Guild {
/// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions
/// [`User`]: struct.User.html
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn unban<U: Into<UserId>>(&self, user: U) -> Result<()> {
feature_cache_enabled! {{
let req = permissions::BAN_MEMBERS;
@@ -772,7 +772,7 @@ impl Guild {
/// **Note**: Requires the [Manage Webhooks] permission.
///
/// [Manage Webhooks]: permissions/constant.MANAGE_WEBHOOKS.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
#[inline]
pub fn webhooks(&self) -> Result<Vec<Webhook>> {
rest::get_guild_webhooks(self.id.0)
@@ -787,7 +787,7 @@ impl Member {
///
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn add_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> {
let role_id = role_id.into();
@@ -814,7 +814,7 @@ impl Member {
///
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn add_roles(&mut self, role_ids: &[RoleId]) -> Result<()> {
let guild_id = self.find_guild()?;
self.roles.extend_from_slice(role_ids);
@@ -837,7 +837,7 @@ impl Member {
/// **Note**: Requires the [Ban Members] role.
///
/// [Ban Members]: permissions/constant.BAN_MEMBERS.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn ban(&self, delete_message_days: u8) -> Result<()> {
let guild_id = self.find_guild()?;
@@ -854,7 +854,7 @@ impl Member {
}
/// Determines the member's colour.
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn colour(&self) -> Option<Colour> {
let default = Colour::default();
let guild_id = match self.find_guild() {
@@ -886,7 +886,7 @@ impl Member {
///
/// [`Context::edit_member`]: ../client/struct.Context.html#method.edit_member
/// [`EditMember`]: ../builder/struct.EditMember.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn edit<F>(&self, f: F) -> Result<()>
where F: FnOnce(EditMember) -> EditMember {
let guild_id = self.find_guild()?;
@@ -898,7 +898,7 @@ impl Member {
/// Finds the Id of the [`Guild`] that the member is in.
///
/// [`Guild`]: struct.Guild.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn find_guild(&self) -> Result<GuildId> {
CACHE.read()
.unwrap()
@@ -925,7 +925,7 @@ impl Member {
///
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn remove_role<R: Into<RoleId>>(&mut self, role_id: R) -> Result<()> {
let role_id = role_id.into();
@@ -951,7 +951,7 @@ impl Member {
///
/// [`Role`]: struct.Role.html
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn remove_roles(&mut self, role_ids: &[RoleId]) -> Result<()> {
let guild_id = self.find_guild()?;
self.roles.retain(|r| !role_ids.contains(r));
@@ -973,7 +973,7 @@ impl Member {
/// This is shorthand for manually searching through the CACHE.
///
/// If role data can not be found for the member, then `None` is returned.
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn roles(&self) -> Option<Vec<Role>> {
CACHE.read().unwrap()
.guilds
@@ -1055,7 +1055,7 @@ impl Role {
/// **Note** Requires the [Manage Roles] permission.
///
/// [Manage Roles]: permissions/constant.MANAGE_ROLES.html
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn delete(&self) -> Result<()> {
let guild_id = self.find_guild()?;
@@ -1070,7 +1070,7 @@ impl Role {
/// that contains the role.
///
/// [`ClientError::GuildNotFound`]: ../client/enum.ClientError.html#variant.GuildNotFound
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn find_guild(&self) -> Result<GuildId> {
CACHE.read()
.unwrap()
diff --git a/src/model/id.rs b/src/model/id.rs
index d0d0b61..0d337fb 100644
--- a/src/model/id.rs
+++ b/src/model/id.rs
@@ -1,16 +1,16 @@
use super::*;
use std::fmt;
-#[cfg(all(feature = "cache", feature = "methods"))]
+#[cfg(all(feature="cache", feature="methods"))]
use ::client::CACHE;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use ::client::rest;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use ::internal::prelude::*;
impl ChannelId {
/// Search the cache for the channel with the Id.
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn find(&self) -> Option<Channel> {
CACHE.read().unwrap().get_channel(*self).map(|x| x.clone_inner())
}
@@ -73,7 +73,7 @@ impl From<Emoji> for EmojiId {
impl GuildId {
/// Search the cache for the guild.
- #[cfg(all(feature = "cache", feature="methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn find(&self) -> Option<Guild> {
CACHE.read().unwrap().get_guild(*self).cloned()
}
@@ -89,7 +89,7 @@ impl GuildId {
/// Returns this Id as a `ChannelId`, which is useful when needing to use
/// the guild Id to send a message to the default channel.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn to_channel(&self) -> ChannelId {
ChannelId(self.0)
}
@@ -156,7 +156,7 @@ impl From<Role> for RoleId {
impl RoleId {
/// Search the cache for the role.
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn find(&self) -> Option<Role> {
CACHE.read()
.unwrap()
@@ -174,7 +174,7 @@ impl RoleId {
impl UserId {
/// Search the cache for the channel with the Id.
- #[cfg(all(feature = "cache", feature = "methods"))]
+ #[cfg(all(feature="cache", feature="methods"))]
pub fn find(&self) -> Option<User> {
CACHE.read().unwrap().get_user(*self).cloned()
}
diff --git a/src/model/invite.rs b/src/model/invite.rs
index 804f5ef..4742b39 100644
--- a/src/model/invite.rs
+++ b/src/model/invite.rs
@@ -115,7 +115,7 @@ impl RichInvite {
/// [`rest::delete_invite`]: ../client/rest/fn.delete_invite.html
/// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
/// [permission]: permissions/index.html
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn delete(&self) -> Result<Invite> {
feature_cache_enabled! {{
let req = permissions::MANAGE_GUILD;
diff --git a/src/model/mod.rs b/src/model/mod.rs
index 298912f..70fdd75 100644
--- a/src/model/mod.rs
+++ b/src/model/mod.rs
@@ -27,9 +27,9 @@ mod id;
mod misc;
mod user;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
mod invite;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
mod webhook;
pub use self::channel::*;
@@ -40,9 +40,9 @@ pub use self::misc::*;
pub use self::permissions::Permissions;
pub use self::user::*;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
pub use self::invite::*;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
pub use self::webhook::*;
use self::utils::*;
diff --git a/src/model/user.rs b/src/model/user.rs
index adc766f..c249631 100644
--- a/src/model/user.rs
+++ b/src/model/user.rs
@@ -13,22 +13,24 @@ use ::internal::prelude::*;
use ::utils::decode_array;
use ::model::misc::Mentionable;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use serde_json::builder::ObjectBuilder;
#[cfg(feature="methods")]
use std::mem;
#[cfg(feature = "methods")]
use super::Message;
-#[cfg(feature = "methods")]
+#[cfg(all(feature = "cache", feature = "methods"))]
+use super::Member;
+#[cfg(feature="methods")]
use time::Timespec;
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
use ::client::rest::{self, GuildPagination};
#[cfg(feature="methods")]
use super::GuildInfo;
#[cfg(feature="methods")]
use ::utils::builder::EditProfile;
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
use ::client::CACHE;
impl CurrentUser {
@@ -59,7 +61,7 @@ impl CurrentUser {
/// .edit(|p| p
/// .avatar(Some(&avatar)));
/// ```
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
pub fn edit<F>(&mut self, f: F) -> Result<()>
where F: FnOnce(EditProfile) -> EditProfile {
let mut map = ObjectBuilder::new()
@@ -102,8 +104,17 @@ impl User {
format!(cdn!("/avatars/{}/{}.jpg"), self.id, av))
}
+ /// Gets user as `Member` of a server.
+ #[cfg(all(feature="cache", feature="methods"))]
+ pub fn member<G>(&self, guild_id: G) -> Option<Member>
+ where G: Into<GuildId> {
+ let cache = CACHE.read().unwrap();
+
+ cache.get_member(guild_id.into(), self.id).cloned()
+ }
+
/// Retrieves the time that this user was created at.
- #[cfg(feature = "methods")]
+ #[cfg(feature="methods")]
#[inline]
pub fn created_at(&self) -> Timespec {
self.id.created_at()
diff --git a/src/model/utils.rs b/src/model/utils.rs
index e4b2445..28f5874 100644
--- a/src/model/utils.rs
+++ b/src/model/utils.rs
@@ -260,7 +260,7 @@ pub fn remove(map: &mut BTreeMap<String, Value>, key: &str) -> Result<Value> {
}
#[doc(hidden)]
-#[cfg(all(feature = "cache", feature="methods"))]
+#[cfg(all(feature="cache", feature="methods"))]
pub fn user_has_perms(channel_id: ChannelId,
mut permissions: Permissions)
-> Result<bool> {
diff --git a/src/utils/macros.rs b/src/utils/macros.rs
index 2ba37e0..2f2ebdf 100644
--- a/src/utils/macros.rs
+++ b/src/utils/macros.rs
@@ -44,7 +44,7 @@ macro_rules! status {
}
// Enable/disable check for cache
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
macro_rules! feature_cache {
($enabled:block else $disabled:block) => {
{
@@ -53,7 +53,7 @@ macro_rules! feature_cache {
}
}
-#[cfg(not(feature = "cache"))]
+#[cfg(not(feature="cache"))]
macro_rules! feature_cache {
($enabled:block else $disabled:block) => {
{
@@ -62,7 +62,7 @@ macro_rules! feature_cache {
}
}
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
macro_rules! feature_cache_enabled {
($enabled:block) => {
{
@@ -71,17 +71,17 @@ macro_rules! feature_cache_enabled {
}
}
-#[cfg(not(feature = "cache"))]
+#[cfg(not(feature="cache"))]
macro_rules! feature_cache_enabled {
($enabled:block) => {{}}
}
-#[cfg(feature = "cache")]
+#[cfg(feature="cache")]
macro_rules! feature_cache_disabled {
($disabled:block) => {{}}
}
-#[cfg(not(feature = "cache"))]
+#[cfg(not(feature="cache"))]
macro_rules! feature_cache_disabled {
($disabled:block) => {
{
@@ -91,7 +91,7 @@ macro_rules! feature_cache_disabled {
}
// Enable/disable check for framework
-#[cfg(feature = "framework")]
+#[cfg(feature="framework")]
macro_rules! feature_framework {
($enabled:block else $disabled:block) => {
{
@@ -100,7 +100,7 @@ macro_rules! feature_framework {
}
}
-#[cfg(not(feature = "framework"))]
+#[cfg(not(feature="framework"))]
macro_rules! feature_framework {
($enabled:block else $disabled:block) => {
{
@@ -109,7 +109,7 @@ macro_rules! feature_framework {
}
}
-#[cfg(feature = "framework")]
+#[cfg(feature="framework")]
macro_rules! feature_framework_enabled {
($enabled:block) => {
{
@@ -118,17 +118,17 @@ macro_rules! feature_framework_enabled {
}
}
-#[cfg(not(feature = "framework"))]
+#[cfg(not(feature="framework"))]
macro_rules! feature_framework_enabled {
($enabled:block) => {{}}
}
-#[cfg(feature = "framework")]
+#[cfg(feature="framework")]
macro_rules! feature_framework_disabled {
($disabled:block) => {{}}
}
-#[cfg(not(feature = "framework"))]
+#[cfg(not(feature="framework"))]
macro_rules! feature_framework_disabled {
($disabled:block) => {
{
@@ -138,7 +138,7 @@ macro_rules! feature_framework_disabled {
}
// Enable/disable check for methods
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
macro_rules! feature_methods {
($enabled:block else $disabled:block) => {
{
@@ -147,7 +147,7 @@ macro_rules! feature_methods {
}
}
-#[cfg(not(feature = "methods"))]
+#[cfg(not(feature="methods"))]
macro_rules! feature_methods {
($enabled:block else $disabled:block) => {
{
@@ -156,7 +156,7 @@ macro_rules! feature_methods {
}
}
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
macro_rules! feature_methods_enabled {
($enabled:block) => {
{
@@ -165,17 +165,17 @@ macro_rules! feature_methods_enabled {
}
}
-#[cfg(not(feature = "methods"))]
+#[cfg(not(feature="methods"))]
macro_rules! feature_methods_enabled {
($enabled:block) => {{}}
}
-#[cfg(feature = "methods")]
+#[cfg(feature="methods")]
macro_rules! feature_methods_disabled {
($disabled:block) => {{}}
}
-#[cfg(not(feature = "methods"))]
+#[cfg(not(feature="methods"))]
macro_rules! feature_methods_disabled {
($disabled:block) => {
{
@@ -185,7 +185,7 @@ macro_rules! feature_methods_disabled {
}
// Enable/disable check for voice
-#[cfg(feature = "voice")]
+#[cfg(feature="voice")]
macro_rules! feature_voice {
($enabled:block else $disabled:block) => {
{
@@ -194,7 +194,7 @@ macro_rules! feature_voice {
}
}
-#[cfg(not(feature = "voice"))]
+#[cfg(not(feature="voice"))]
macro_rules! feature_voice {
($enabled:block else $disabled:block) => {
{
@@ -203,7 +203,7 @@ macro_rules! feature_voice {
}
}
-#[cfg(feature = "voice")]
+#[cfg(feature="voice")]
macro_rules! feature_voice_enabled {
($enabled:block) => {
{
@@ -212,17 +212,17 @@ macro_rules! feature_voice_enabled {
}
}
-#[cfg(not(feature = "voice"))]
+#[cfg(not(feature="voice"))]
macro_rules! feature_voice_enabled {
($enabled:block) => {{}}
}
-#[cfg(feature = "voice")]
+#[cfg(feature="voice")]
macro_rules! feature_voice_disabled {
($disabled:block) => {{}}
}
-#[cfg(not(feature = "voice"))]
+#[cfg(not(feature="voice"))]
macro_rules! feature_voice_disabled {
($disabled:block) => {
{