aboutsummaryrefslogtreecommitdiff
path: root/src/framework
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2018-03-25 19:48:53 -0700
committerZeyla Hellyer <[email protected]>2018-03-25 19:48:53 -0700
commite2f3ece27934af8b7b756a70d3b6090385d37c1e (patch)
treee8085382bb92f88bfbaf95042360eb66f0a1921a /src/framework
parentRemove `http::FutureResult`, use `error`'s (diff)
parentRemove useless clones (#292) (diff)
downloadserenity-e2f3ece27934af8b7b756a70d3b6090385d37c1e.tar.xz
serenity-e2f3ece27934af8b7b756a70d3b6090385d37c1e.zip
Merge branch 'master' into futures
Diffstat (limited to 'src/framework')
-rw-r--r--src/framework/standard/args.rs38
-rw-r--r--src/framework/standard/command.rs1
-rw-r--r--src/framework/standard/create_command.rs11
-rw-r--r--src/framework/standard/create_group.rs1
-rw-r--r--src/framework/standard/help_commands.rs18
-rw-r--r--src/framework/standard/mod.rs67
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