diff options
| author | Zeyla Hellyer <[email protected]> | 2018-03-25 19:48:53 -0700 |
|---|---|---|
| committer | Zeyla Hellyer <[email protected]> | 2018-03-25 19:48:53 -0700 |
| commit | e2f3ece27934af8b7b756a70d3b6090385d37c1e (patch) | |
| tree | e8085382bb92f88bfbaf95042360eb66f0a1921a /src/framework | |
| parent | Remove `http::FutureResult`, use `error`'s (diff) | |
| parent | Remove useless clones (#292) (diff) | |
| download | serenity-e2f3ece27934af8b7b756a70d3b6090385d37c1e.tar.xz serenity-e2f3ece27934af8b7b756a70d3b6090385d37c1e.zip | |
Merge branch 'master' into futures
Diffstat (limited to 'src/framework')
| -rw-r--r-- | src/framework/standard/args.rs | 38 | ||||
| -rw-r--r-- | src/framework/standard/command.rs | 1 | ||||
| -rw-r--r-- | src/framework/standard/create_command.rs | 11 | ||||
| -rw-r--r-- | src/framework/standard/create_group.rs | 1 | ||||
| -rw-r--r-- | src/framework/standard/help_commands.rs | 18 | ||||
| -rw-r--r-- | src/framework/standard/mod.rs | 67 |
6 files changed, 104 insertions, 32 deletions
diff --git a/src/framework/standard/args.rs b/src/framework/standard/args.rs index 87cc0a5..1a819b6 100644 --- a/src/framework/standard/args.rs +++ b/src/framework/standard/args.rs @@ -159,7 +159,7 @@ impl Args { /// ``` pub fn single<T: FromStr>(&mut self) -> Result<T, T::Err> where T::Err: StdError { - if self.message.is_empty() { + if self.is_empty() { return Err(Error::Eos); } @@ -186,7 +186,7 @@ impl Args { /// [`single`]: #method.single pub fn single_n<T: FromStr>(&self) -> Result<T, T::Err> where T::Err: StdError { - if self.message.is_empty() { + if self.is_empty() { return Err(Error::Eos); } @@ -221,7 +221,7 @@ impl Args { if let Some(len) = self.len { len - } else if self.message.is_empty() { + } else if self.is_empty() { 0 } else { let mut words: Box<Iterator<Item = &str>> = Box::new(Some(&self.message[..]).into_iter()); @@ -263,7 +263,7 @@ impl Args { /// assert_eq!(args.len_quoted(), 2); // `2` because `["42", "69"]` /// ``` pub fn len_quoted(&mut self) -> usize { - if self.message.is_empty() { + if self.is_empty() { 0 } else if let Some(len_quoted) = self.len_quoted { len_quoted @@ -291,6 +291,10 @@ impl Args { /// assert_eq!(args.full(), "69"); /// ``` pub fn skip(&mut self) -> Option<String> { + if self.is_empty() { + return None; + } + if let Some(ref mut val) = self.len { if 1 <= *val { @@ -315,6 +319,10 @@ impl Args { /// /// [`skip`]: #method.skip pub fn skip_for(&mut self, i: u32) -> Option<Vec<String>> { + if self.is_empty() { + return None; + } + let mut vec = Vec::with_capacity(i as usize); for _ in 0..i { @@ -349,6 +357,10 @@ impl Args { /// [`single`]: #method.single pub fn single_quoted<T: FromStr>(&mut self) -> Result<T, T::Err> where T::Err: StdError { + if self.is_empty() { + return Err(Error::Eos); + } + if let Some(ref mut val) = self.len_quoted { *val -= 1 }; @@ -372,6 +384,10 @@ impl Args { /// [`single_quoted`]: #method.single_quoted pub fn single_quoted_n<T: FromStr>(&self) -> Result<T, T::Err> where T::Err: StdError { + if self.is_empty() { + return Err(Error::Eos); + } + parse_quotes::<T>(&mut self.message.clone(), &self.delimiters) } @@ -390,6 +406,10 @@ impl Args { /// [`multiple`]: #method.multiple pub fn multiple_quoted<T: FromStr>(mut self) -> Result<Vec<T>, T::Err> where T::Err: StdError { + if self.is_empty() { + return Err(Error::Eos); + } + IterQuoted::<T>::new(&mut self).collect() } @@ -425,6 +445,10 @@ impl Args { /// ``` pub fn multiple<T: FromStr>(mut self) -> Result<Vec<T>, T::Err> where T::Err: StdError { + if self.is_empty() { + return Err(Error::Eos); + } + Iter::<T>::new(&mut self).collect() } @@ -441,7 +465,7 @@ impl Args { /// assert!(args.is_empty()); /// ``` pub fn iter<T: FromStr>(&mut self) -> Iter<T> - where T::Err: StdError { + where T::Err: StdError { Iter::new(self) } @@ -462,7 +486,7 @@ impl Args { /// ``` pub fn find<T: FromStr>(&mut self) -> Result<T, T::Err> where T::Err: StdError { - if self.message.is_empty() { + if self.is_empty() { return Err(Error::Eos); } @@ -521,7 +545,7 @@ impl Args { /// ``` pub fn find_n<T: FromStr>(&mut self) -> Result<T, T::Err> where T::Err: StdError { - if self.message.is_empty() { + if self.is_empty() { return Err(Error::Eos); } diff --git a/src/framework/standard/command.rs b/src/framework/standard/command.rs index 541d1b9..a971c1f 100644 --- a/src/framework/standard/command.rs +++ b/src/framework/standard/command.rs @@ -32,6 +32,7 @@ impl HelpCommand for Help { pub type BeforeHook = Fn(&mut Context, &Message, &str) -> bool + Send + Sync + 'static; pub type AfterHook = Fn(&mut Context, &Message, &str, Result<(), Error>) + Send + Sync + 'static; +pub type UnrecognisedCommandHook = Fn(&mut Context, &Message, &str) + Send + Sync + 'static; pub(crate) type InternalCommand = Arc<Command>; pub type PrefixCheck = Fn(&mut Context, &Message) -> Option<String> + Send + Sync + 'static; diff --git a/src/framework/standard/create_command.rs b/src/framework/standard/create_command.rs index 672a955..8fbb975 100644 --- a/src/framework/standard/create_command.rs +++ b/src/framework/standard/create_command.rs @@ -218,6 +218,7 @@ impl CreateCommand { } /// Sets roles that are allowed to use the command. + #[cfg(feature="cache")] pub fn allowed_roles<T: ToString, It: IntoIterator<Item=T>>(mut self, allowed_roles: It) -> Self { self.0.allowed_roles = allowed_roles.into_iter().map(|x| x.to_string()).collect(); @@ -225,7 +226,7 @@ impl CreateCommand { } /// Sets an initialise middleware to be called upon the command's actual registration. - /// + /// /// This is similiar to implementing the `init` function on `Command`. pub fn init<F: Fn() + Send + Sync + 'static>(mut self, f: F) -> Self { self.2.init = Some(Arc::new(f)); @@ -234,9 +235,9 @@ impl CreateCommand { } /// Sets a before middleware to be called before the command's execution. - /// + /// /// This is similiar to implementing the `before` function on `Command`. - pub fn before<F: Send + Sync + 'static>(mut self, f: F) -> Self + pub fn before<F: Send + Sync + 'static>(mut self, f: F) -> Self where F: Fn(&mut Context, &Message) -> bool { self.2.before = Some(Arc::new(f)); @@ -244,9 +245,9 @@ impl CreateCommand { } /// Sets an after middleware to be called after the command's execution. - /// + /// /// This is similiar to implementing the `after` function on `Command`. - pub fn after<F: Send + Sync + 'static>(mut self, f: F) -> Self + pub fn after<F: Send + Sync + 'static>(mut self, f: F) -> Self where F: Fn(&mut Context, &Message, &Result<(), CommandError>) { self.2.after = Some(Arc::new(f)); diff --git a/src/framework/standard/create_group.rs b/src/framework/standard/create_group.rs index df3d97f..c33f67a 100644 --- a/src/framework/standard/create_group.rs +++ b/src/framework/standard/create_group.rs @@ -148,6 +148,7 @@ impl CreateGroup { } /// Sets roles that are allowed to use the command. + #[cfg(feature = "cache")] pub fn allowed_roles<T: ToString, It: IntoIterator<Item=T>>(mut self, allowed_roles: It) -> Self { self.0.allowed_roles = allowed_roles.into_iter().map(|x| x.to_string()).collect(); diff --git a/src/framework/standard/help_commands.rs b/src/framework/standard/help_commands.rs index d740086..9979423 100644 --- a/src/framework/standard/help_commands.rs +++ b/src/framework/standard/help_commands.rs @@ -24,6 +24,7 @@ //! [`with_embeds`]: fn.with_embeds.html use client::Context; +#[cfg(feature = "cache")] use framework::standard::{has_correct_roles, has_correct_permissions}; use model::channel::Message; use model::id::ChannelId; @@ -55,6 +56,7 @@ fn remove_aliases(cmds: &HashMap<String, CommandOrAlias>) -> HashMap<&String, &I /// Checks whether a user is member of required roles /// and given the required permissions. +#[cfg(feature = "cache")] pub fn has_all_requirements(cmd: &Arc<CommandOptions>, msg: &Message) -> bool { if let Some(guild) = msg.guild() { let guild = guild.read(); @@ -92,6 +94,7 @@ pub fn has_all_requirements(cmd: &Arc<CommandOptions>, msg: &Message) -> bool { /// client.with_framework(StandardFramework::new() /// .help(help_commands::with_embeds)); /// ``` +#[cfg(feature = "cache")] pub fn with_embeds<H: BuildHasher>( _: &mut Context, msg: &Message, @@ -153,20 +156,20 @@ pub fn with_embeds<H: BuildHasher>( let _ = msg.channel_id.send_message(|m| { m.embed(|e| { - let mut embed = e.colour(help_options.embed_success_colour).title(command_name.clone()); + let mut embed = e.colour(help_options.embed_success_colour).title(command_name); if let Some(ref desc) = command.desc { embed = embed.description(desc); } if let Some(ref usage) = command.usage { - let value = format!("`{} {}`", command_name.clone(), usage); + let value = format!("`{} {}`", command_name, usage); embed = embed.field(&help_options.usage_label, value, true); } if let Some(ref example) = command.example { - let value = format!("`{} {}`", command_name.clone(), example); + let value = format!("`{} {}`", command_name, example); embed = embed.field(&help_options.usage_sample_label, value, true); } @@ -208,9 +211,9 @@ pub fn with_embeds<H: BuildHasher>( let _ = msg.channel_id.send_message(|m| { m.embed(|mut e| { - if let Some(striked_command_text) = help_options.striked_commands_tip.clone() { + if let Some(ref striked_command_text) = help_options.striked_commands_tip { e = e.colour(help_options.embed_success_colour).description( - format!("{}\n{}", &help_options.individual_command_tip, &striked_command_text), + format!("{}\n{}", &help_options.individual_command_tip, striked_command_text), ); } else { e = e.colour(help_options.embed_success_colour).description( @@ -335,6 +338,7 @@ pub fn with_embeds<H: BuildHasher>( /// client.with_framework(StandardFramework::new() /// .help(help_commands::plain)); /// ``` +#[cfg(feature = "cache")] pub fn plain<H: BuildHasher>( _: &mut Context, msg: &Message, @@ -445,8 +449,8 @@ pub fn plain<H: BuildHasher>( let mut result = "**Commands**\n".to_string(); - if let Some(striked_command_text) = help_options.striked_commands_tip.clone() { - let _ = write!(result, "{}\n{}\n\n", &help_options.individual_command_tip, &striked_command_text); + if let Some(ref striked_command_text) = help_options.striked_commands_tip { + let _ = write!(result, "{}\n{}\n\n", &help_options.individual_command_tip, striked_command_text); } else { let _ = write!(result, "{}\n\n", &help_options.individual_command_tip); } diff --git a/src/framework/standard/mod.rs b/src/framework/standard/mod.rs index 16e7757..a4fbad0 100644 --- a/src/framework/standard/mod.rs +++ b/src/framework/standard/mod.rs @@ -25,7 +25,7 @@ use model::channel::Message; use model::guild::{Guild, Member}; use model::id::{ChannelId, GuildId, UserId}; use model::Permissions; -use self::command::{AfterHook, BeforeHook}; +use self::command::{AfterHook, BeforeHook, UnrecognisedCommandHook}; use std::collections::HashMap; use std::default::Default; use std::sync::Arc; @@ -205,6 +205,7 @@ pub struct StandardFramework { dispatch_error_handler: Option<Arc<DispatchErrorHook>>, buckets: HashMap<String, Bucket>, after: Option<Arc<AfterHook>>, + unrecognised_command: Option<Arc<UnrecognisedCommandHook>>, /// Whether the framework has been "initialized". /// /// The framework is initialized once one of the following occurs: @@ -566,15 +567,19 @@ impl StandardFramework { } else if self.configuration.disabled_commands.contains(built) { Some(DispatchError::CommandDisabled(built.to_string())) } else { - if !command.allowed_roles.is_empty() { - if let Some(guild) = message.guild() { - let guild = guild.read(); - - if let Some(member) = guild.members.get(&message.author.id) { - if let Ok(permissions) = member.permissions() { - if !permissions.administrator() - && !has_correct_roles(command, &guild, member) { - return Some(DispatchError::LackingRole); + + #[cfg(feature = "cache")] { + if !command.allowed_roles.is_empty() { + if let Some(guild) = message.guild() { + let guild = guild.read(); + + if let Some(member) = guild.members.get(&message.author.id) { + if let Ok(permissions) = member.permissions() { + + if !permissions.administrator() + && !has_correct_roles(command, &guild, member) { + return Some(DispatchError::LackingRole); + } } } } @@ -879,6 +884,31 @@ impl StandardFramework { self } + /// Specify the function to be called if no command could be dispatched. + /// + /// # Examples + /// + /// Using `unrecognised_command`: + /// + /// ```rust + /// # use serenity::prelude::*; + /// # struct Handler; + /// # + /// # impl EventHandler for Handler {} + /// # let mut client = Client::new("token", Handler).unwrap(); + /// # + /// use serenity::framework::StandardFramework; + /// + /// client.with_framework(StandardFramework::new() + /// .unrecognised_command(|ctx, msg, unrecognised_command_name| { })); + /// ``` + pub fn unrecognised_command<F>(mut self, f: F) -> Self + where F: Fn(&mut Context, &Message, &str) + Send + Sync + 'static { + self.unrecognised_command = Some(Arc::new(f)); + + self + } + /// Sets what code should be executed when a user sends `(prefix)help`. pub fn help(mut self, f: HelpFunction) -> Self { let a = CreateHelpCommand(HelpOptions::default(), f).finish(); @@ -909,6 +939,7 @@ impl Framework for StandardFramework { threadpool: &ThreadPool, ) { let res = command::positions(&mut context, &message, &self.configuration); + let mut unrecognised_command_name = String::from(""); let positions = match res { Some(mut positions) => { @@ -953,13 +984,17 @@ impl Framework for StandardFramework { built }; +<<<<<<< HEAD +======= + unrecognised_command_name = built.clone(); +>>>>>>> master let cmd = group.commands.get(&built); if let Some(&CommandOrAlias::Alias(ref points_to)) = cmd { built = points_to.to_string(); } - let mut to_check = if let Some(ref prefix) = group.prefix { + let to_check = if let Some(ref prefix) = group.prefix { if built.starts_with(prefix) && command_length > prefix.len() + 1 { built[(prefix.len() + 1)..].to_string() } else { @@ -1049,13 +1084,20 @@ impl Framework for StandardFramework { } } } + + let unrecognised_command = self.unrecognised_command.clone(); + + threadpool.execute(move || { + if let Some(unrecognised_command) = unrecognised_command { + (unrecognised_command)(&mut context, &message, &unrecognised_command_name); + } + }); } fn update_current_user(&mut self, user_id: UserId) { self.user_id = user_id.0; } } - #[cfg(feature = "cache")] pub fn has_correct_permissions(command: &Arc<CommandOptions>, message: &Message) -> bool { if !command.required_permissions.is_empty() { @@ -1070,7 +1112,6 @@ pub fn has_correct_permissions(command: &Arc<CommandOptions>, message: &Message) true } -#[cfg(feature = "cache")] pub fn has_correct_roles(cmd: &Arc<CommandOptions>, guild: &Guild, member: &Member) -> bool { if cmd.allowed_roles.is_empty() { true |