Skip to content

Commit

Permalink
Add checks for groups (#349)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lakelezz authored Jul 15, 2018
1 parent 5abc7d1 commit 29480e5
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 7 deletions.
33 changes: 31 additions & 2 deletions examples/05_command_framework/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,21 @@ fn main() {
.command("latency", |c| c
.cmd(latency))
.command("ping", |c| c
.check(owner_check)
.check(owner_check) // User needs to pass this test to run command
.cmd(ping))
.command("role", |c| c
.cmd(about_role)
// Limits the usage of this command to roles named:
.allowed_roles(vec!["mods", "ultimate neko"]))
.command("some long command", |c| c.cmd(some_long_command)),
.command("some long command", |c| c.cmd(some_long_command))
.group("Owner", |g| g
// This check applies to every command on this group.
// User needs to pass the test for the command to execute.
.check(admin_check)
.command("am i admin", |c| c
.cmd(am_i_admin))
.guild_only(true)
),
);

if let Err(why) = client.start() {
Expand Down Expand Up @@ -231,6 +239,21 @@ fn owner_check(_: &mut Context, msg: &Message, _: &mut Args, _: &CommandOptions)
msg.author.id == 7
}

// A function which acts as a "check", to determine whether to call a command.
//
// This check analyses whether a guild member permissions has
// administrator-permissions.
fn admin_check(_: &mut Context, msg: &Message, _: &mut Args, _: &CommandOptions) -> bool {
if let Some(member) = msg.member() {

if let Ok(permissions) = member.permissions() {
return permissions.administrator();
}
}

false
}

command!(some_long_command(_ctx, msg, args) {
if let Err(why) = msg.channel_id.say(&format!("Arguments: {:?}", args)) {
println!("Error sending message: {:?}", why);
Expand Down Expand Up @@ -333,6 +356,12 @@ command!(ping(_ctx, msg, _args) {
}
});

command!(am_i_admin(_ctx, msg, _args) {
if let Err(why) = msg.channel_id.say("Yes you are.") {
println!("Error sending message: {:?}", why);
}
});

command!(dog(_ctx, msg, _args) {
if let Err(why) = msg.channel_id.say(":dog:") {
println!("Error sending message: {:?}", why);
Expand Down
5 changes: 4 additions & 1 deletion src/framework/standard/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ pub struct CommandGroup {
pub guild_only: bool,
pub owners_only: bool,
pub help: Option<Arc<Help>>,
/// A set of checks to be called prior to executing the command-group. The checks
/// will short-circuit on the first check that returns `false`.
pub checks: Vec<Check>,
}

impl Default for CommandGroup {
Expand All @@ -116,6 +119,7 @@ impl Default for CommandGroup {
owners_only: false,
allowed_roles: Vec::new(),
help: None,
checks: Vec::new(),
}
}
}
Expand Down Expand Up @@ -256,7 +260,6 @@ impl Default for HelpOptions {
}
}


lazy_static! {
static ref DEFAULT_OPTIONS: Arc<CommandOptions> = Arc::new(CommandOptions::default());
}
Expand Down
2 changes: 1 addition & 1 deletion src/framework/standard/create_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl CreateCommand {
/// Adds a "check" to a command, which checks whether or not the command's
/// function should be called.
///
/// These checks are bypassed for commands sent by the application owner.
/// **Note**: These checks are bypassed for commands sent by the application owner.
///
/// # Examples
///
Expand Down
17 changes: 16 additions & 1 deletion src/framework/standard/create_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ pub(crate) use super::command::CommandOrAlias;
pub use super::{
create_help_command::CreateHelpCommand,
create_command::{CreateCommand, FnOrCommand},
Args
Args,
Check,
};

use client::Context;
Expand Down Expand Up @@ -161,4 +162,18 @@ impl CreateGroup {

self
}

/// Adds a "check" to a group, which checks whether or not the groups's
/// commands should be called.
///
/// **Note**: These checks are bypassed for commands sent by the application owner.
pub fn check<F>(mut self, check: F) -> Self
where F: Fn(&mut Context, &Message, &mut Args, &CommandOptions) -> bool
+ Send
+ Sync
+ 'static {
self.0.checks.push(Check::new(check));

self
}
}
15 changes: 13 additions & 2 deletions src/framework/standard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ impl StandardFramework {
mut context: &mut Context,
message: &Message,
command: &Arc<CommandOptions>,
group: &Arc<CommandGroup>,
args: &mut Args,
to_check: &str,
built: &str)
Expand Down Expand Up @@ -600,12 +601,21 @@ impl StandardFramework {
}
}

let all_passed = command
let all_group_checks_passed = group
.checks
.iter()
.all(|check| (check.0)(&mut context, message, args, command));

if all_passed {
if !all_group_checks_passed {
return Some(DispatchError::CheckFailed);
}

let all_command_checks_passed = command
.checks
.iter()
.all(|check| (check.0)(&mut context, message, args, command));

if all_command_checks_passed {
None
} else {
Some(DispatchError::CheckFailed)
Expand Down Expand Up @@ -1061,6 +1071,7 @@ impl Framework for StandardFramework {
&mut context,
&message,
&command.options(),
&group,
&mut args,
&to_check,
&built,
Expand Down

0 comments on commit 29480e5

Please sign in to comment.