Skip to content

Commit

Permalink
Add documentation and tests for framework
Browse files Browse the repository at this point in the history
  • Loading branch information
Roughsketch authored and Zeyla Hellyer committed May 31, 2017
1 parent d367a70 commit 4267bdb
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 4 deletions.
101 changes: 97 additions & 4 deletions src/framework/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ impl Configuration {
}

/// HashSet of guild Ids where commands will be ignored.
///
/// # Examples
///
/// Create a HashSet in-place:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// use serenity::model::GuildId;
///
/// client.with_framework(|f| f.configure(|c| c
/// .blocked_guilds(vec![GuildId(7), GuildId(77)].into_iter().collect())));
/// ```
pub fn blocked_guilds(mut self, guilds: HashSet<GuildId>) -> Self {
self.blocked_guilds = guilds;

Expand All @@ -101,6 +114,19 @@ impl Configuration {

/// HashSet of user Ids whose commands will be ignored.
/// Guilds owned by user Ids will also be ignored.
///
/// # Examples
///
/// Create a HashSet in-place:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// use serenity::model::UserId;
///
/// client.with_framework(|f| f.configure(|c| c
/// .blocked_users(vec![UserId(7), UserId(77)].into_iter().collect())));
/// ```
pub fn blocked_users(mut self, users: HashSet<UserId>) -> Self {
self.blocked_users = users;

Expand All @@ -122,6 +148,21 @@ impl Configuration {
}

/// HashSet of command names that won't be run.
///
/// # Examples
///
/// Ignore a set of commands, assuming they exist:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
///
/// let disabled = vec!["ping"].into_iter().map(|x| x.to_owned()).collect();
///
/// client.with_framework(|f| f
/// .command("ping", |c| c.exec_str("pong!"))
/// .configure(|c| c.disabled_commands(disabled)));
/// ```
pub fn disabled_commands(mut self, commands: HashSet<String>) -> Self {
self.disabled_commands = commands;

Expand Down Expand Up @@ -213,22 +254,74 @@ impl Configuration {
}

/// A `HashSet` of user Ids checks won't apply to.
///
/// # Examples
///
/// Create a HashSet in-place:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// use serenity::model::UserId;
///
/// client.with_framework(|f| f.configure(|c| c
/// .owners(vec![UserId(7), UserId(77)].into_iter().collect())));
/// ```
///
/// Create a HashSet beforehand:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// use serenity::model::UserId;
/// use std::collections::HashSet;
///
/// let mut set = HashSet::new();
/// set.insert(UserId(7));
/// set.insert(UserId(77));
///
/// client.with_framework(|f| f.configure(|c| c.owners(set)));
/// ```
pub fn owners(mut self, user_ids: HashSet<UserId>) -> Self {
self.owners = user_ids;

self
}

/// Sets the prefix to respond to. This can either be a single-char or
/// multi-char string.
/// Sets the prefix to respond to. A prefix can be a string slice of any
/// non-zero length.
///
/// # Examples
///
/// Assign a basic prefix:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f.configure(|c| c
/// .prefix("!")));
/// ```
pub fn prefix(mut self, prefix: &str) -> Self {
self.prefixes = vec![prefix.to_owned()];

self
}

/// Sets the prefixes to respond to. Those can either be single-chararacter or
/// multi-chararacter strings.
/// Sets the prefixes to respond to. Each can be a string slice of any
/// non-zero length.
///
/// # Examples
///
/// Assign a set of prefixes the bot can respond to:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f.configure(|c| c
/// .prefixes(vec!["!", ">", "+"])));
/// ```
pub fn prefixes(mut self, prefixes: Vec<&str>) -> Self {
self.prefixes = prefixes.iter().map(|x| x.to_string()).collect();

Expand Down
28 changes: 28 additions & 0 deletions src/framework/help_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ fn remove_aliases(cmds: &HashMap<String, CommandOrAlias>) -> HashMap<&String, &I
result
}

/// Posts an embed showing each individual command group and its commands.
///
/// # Examples
///
/// Use the command with `exec_help`:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// use serenity::ext::framework::help_commands;
///
/// client.with_framework(|f| f
/// .command("help", |c| c.exec_help(help_commands::with_embeds)));
/// ```
pub fn with_embeds(ctx: &mut Context,
_: &Message,
groups: HashMap<String, Arc<CommandGroup>>,
Expand Down Expand Up @@ -186,6 +200,20 @@ pub fn with_embeds(ctx: &mut Context,
Ok(())
}

/// Posts formatted text displaying each individual command group and its commands.
///
/// # Examples
///
/// Use the command with `exec_help`:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// use serenity::ext::framework::help_commands;
///
/// client.with_framework(|f| f
/// .command("help", |c| c.exec_help(help_commands::plain)));
/// ```
pub fn plain(ctx: &mut Context,
_: &Message,
groups: HashMap<String, Arc<CommandGroup>>,
Expand Down
141 changes: 141 additions & 0 deletions src/framework/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,22 @@ impl Framework {

/// Defines a bucket with `delay` between each command, and the `limit` of uses
/// per `time_span`.
///
/// # Examples
///
/// Create and use a bucket that limits a command to 3 uses per 10 seconds with
/// a 2 second delay inbetween invocations:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f
/// .bucket("basic", 2, 10, 3)
/// .command("ping", |c| c
/// .bucket("basic")
/// .exec_str("pong!")));
/// ```
pub fn bucket<S>(mut self, s: S, delay: i64, time_span: i64, limit: i32) -> Self
where S: Into<String> {
self.buckets.insert(s.into(), Bucket {
Expand All @@ -291,6 +307,21 @@ impl Framework {
}

/// Defines a bucket with only a `delay` between each command.
///
/// # Examples
///
/// Create and use a simple bucket that has a 2 second delay between invocations:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f
/// .simple_bucket("simple", 2)
/// .command("ping", |c| c
/// .bucket("simple")
/// .exec_str("pong!")));
/// ```
pub fn simple_bucket<S>(mut self, s: S, delay: i64) -> Self
where S: Into<String> {
self.buckets.insert(s.into(), Bucket {
Expand Down Expand Up @@ -552,6 +583,24 @@ impl Framework {
///
/// [`command`]: #method.command
/// [module-level documentation]: index.html
///
/// # Examples
///
/// Create and use a simple command:
///
/// ```rust
/// # #[macro_use] extern crate serenity;
/// command!(ping(_ctx, msg) {
/// msg.channel_id.say("pong!");
/// });
/// #
/// # fn main() {
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f.on("ping", ping));
/// # }
/// ```
pub fn on<F, S>(mut self, command_name: S, f: F) -> Self
where F: Fn(&mut Context, &Message, Vec<String>) -> Result<(), String> + Send + Sync + 'static,
S: Into<String> {
Expand Down Expand Up @@ -612,6 +661,22 @@ impl Framework {
self
}

/// Adds a group which can organize several related commands.
/// Groups are taken into account when using `serenity::framework::help_commands`.
///
/// # Examples
///
/// Creating a simple group:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f
/// .group("ping-pong", |g| g
/// .command("ping", |c| c.exec_str("pong!"))
/// .command("pong", |c| c.exec_str("ping!"))));
/// ```
pub fn group<F, S>(mut self, group_name: S, f: F) -> Self
where F: FnOnce(CreateGroup) -> CreateGroup,
S: Into<String> {
Expand All @@ -626,6 +691,29 @@ impl Framework {
/// Specify the function that's called in case a command wasn't executed for one reason or another.
///
/// DispatchError represents all possible fail conditions.
///
/// # Examples
///
/// Making a simple argument error responder:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// use serenity::framework::DispatchError::{NotEnoughArguments, TooManyArguments};
///
/// client.with_framework(|f| f
/// .on_dispatch_error(|ctx, msg, error| {
/// match error {
/// NotEnoughArguments { min, given } => {
/// msg.channel_id.say(&format!("Need {} arguments, but only got {}.", min, given));
/// }
/// TooManyArguments { max, given } => {
/// msg.channel_id.say(&format!("Max arguments allowed is {}, but got {}.", max, given));
/// }
/// _ => println!("Unhandled dispatch error.")
/// }
/// }));
/// ```
pub fn on_dispatch_error<F>(mut self, f: F) -> Self
where F: Fn(Context, Message, DispatchError) + Send + Sync + 'static {
self.dispatch_error_handler = Some(Arc::new(f));
Expand All @@ -635,6 +723,42 @@ impl Framework {

/// Specify the function to be called prior to every command's execution.
/// If that function returns true, the command will be executed.
///
/// # Examples
///
/// Using `before` to log command usage:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f
/// .before(|ctx, msg, cmd_name| {
/// println!("Running command {}", cmd_name);
/// true
/// }));
/// ```
///
/// Using before to prevent command usage:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f
/// .before(|ctx, msg, cmd_name| {
/// if let Ok(channel) = msg.channel_id.get() {
/// // Don't run unless in nsfw channel
/// if !channel.is_nsfw() {
/// return false;
/// }
/// }
///
/// println!("Running command {}", cmd_name);
/// true
/// }));
/// ```
///
pub fn before<F>(mut self, f: F) -> Self
where F: Fn(&mut Context, &Message, &String) -> bool + Send + Sync + 'static {
self.before = Some(Arc::new(f));
Expand All @@ -644,6 +768,23 @@ impl Framework {

/// Specify the function to be called after every command's execution.
/// Fourth argument exists if command returned an error which you can handle.
///
/// # Examples
///
/// Using `after` to log command usage:
///
/// ```rust
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// #
/// client.with_framework(|f| f
/// .after(|ctx, msg, cmd_name, error| {
/// // Print out an error if it happened
/// if let Err(why) = error {
/// println!("Error in {}: {:?}", cmd_name, why);
/// }
/// }));
/// ```
pub fn after<F>(mut self, f: F) -> Self
where F: Fn(&mut Context, &Message, &String, Result<(), String>) + Send + Sync + 'static {
self.after = Some(Arc::new(f));
Expand Down

0 comments on commit 4267bdb

Please sign in to comment.