From 4267bdbae05d5516774ca72fe92789651cfa7230 Mon Sep 17 00:00:00 2001 From: Maiddog Date: Tue, 30 May 2017 22:28:18 -0500 Subject: [PATCH] Add documentation and tests for framework --- src/framework/configuration.rs | 101 ++++++++++++++++++++++- src/framework/help_commands.rs | 28 +++++++ src/framework/mod.rs | 141 +++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+), 4 deletions(-) diff --git a/src/framework/configuration.rs b/src/framework/configuration.rs index 0561f8706ed..1b8df305d7e 100644 --- a/src/framework/configuration.rs +++ b/src/framework/configuration.rs @@ -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) -> Self { self.blocked_guilds = guilds; @@ -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) -> Self { self.blocked_users = users; @@ -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) -> Self { self.disabled_commands = commands; @@ -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) -> 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(); diff --git a/src/framework/help_commands.rs b/src/framework/help_commands.rs index 5d9a1f66256..3b3248e9fdb 100644 --- a/src/framework/help_commands.rs +++ b/src/framework/help_commands.rs @@ -51,6 +51,20 @@ fn remove_aliases(cmds: &HashMap) -> 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>, @@ -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>, diff --git a/src/framework/mod.rs b/src/framework/mod.rs index 99e7c44c203..ba0aa365415 100644 --- a/src/framework/mod.rs +++ b/src/framework/mod.rs @@ -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(mut self, s: S, delay: i64, time_span: i64, limit: i32) -> Self where S: Into { self.buckets.insert(s.into(), Bucket { @@ -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(mut self, s: S, delay: i64) -> Self where S: Into { self.buckets.insert(s.into(), Bucket { @@ -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(mut self, command_name: S, f: F) -> Self where F: Fn(&mut Context, &Message, Vec) -> Result<(), String> + Send + Sync + 'static, S: Into { @@ -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(mut self, group_name: S, f: F) -> Self where F: FnOnce(CreateGroup) -> CreateGroup, S: Into { @@ -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(mut self, f: F) -> Self where F: Fn(Context, Message, DispatchError) + Send + Sync + 'static { self.dispatch_error_handler = Some(Arc::new(f)); @@ -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(mut self, f: F) -> Self where F: Fn(&mut Context, &Message, &String) -> bool + Send + Sync + 'static { self.before = Some(Arc::new(f)); @@ -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(mut self, f: F) -> Self where F: Fn(&mut Context, &Message, &String, Result<(), String>) + Send + Sync + 'static { self.after = Some(Arc::new(f));