aboutsummaryrefslogtreecommitdiff
path: root/src/ext/framework
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/framework')
-rw-r--r--src/ext/framework/buckets.rs26
-rw-r--r--src/ext/framework/configuration.rs151
-rw-r--r--src/ext/framework/create_command.rs87
-rw-r--r--src/ext/framework/create_group.rs38
-rw-r--r--src/ext/framework/help_commands.rs30
-rw-r--r--src/ext/framework/mod.rs75
6 files changed, 200 insertions, 207 deletions
diff --git a/src/ext/framework/buckets.rs b/src/ext/framework/buckets.rs
index 2e42250..c0d0017 100644
--- a/src/ext/framework/buckets.rs
+++ b/src/ext/framework/buckets.rs
@@ -10,7 +10,7 @@ pub struct Ratelimit {
#[doc(hidden)]
pub struct MemberRatelimit {
- pub count: i32,
+ pub tickets: i32,
pub last_time: i64,
pub set_time: i64,
}
@@ -18,7 +18,7 @@ pub struct MemberRatelimit {
impl Default for MemberRatelimit {
fn default() -> Self {
MemberRatelimit {
- count: 0,
+ tickets: 0,
last_time: 0,
set_time: 0,
}
@@ -28,31 +28,31 @@ impl Default for MemberRatelimit {
#[doc(hidden)]
pub struct Bucket {
pub ratelimit: Ratelimit,
- pub limits: HashMap<u64, MemberRatelimit>,
+ pub users: HashMap<u64, MemberRatelimit>,
}
impl Bucket {
pub fn take(&mut self, user_id: u64) -> i64 {
let time =- time::get_time().sec;
- let member = self.limits.entry(user_id)
+ let user = self.users.entry(user_id)
.or_insert_with(MemberRatelimit::default);
if let Some((timespan, limit)) = self.ratelimit.limit {
- if (member.count + 1) > limit {
- if time < (member.set_time + timespan) {
- return (member.set_time + timespan) - time;
+ if (user.tickets + 1) > limit {
+ if time < (user.set_time + timespan) {
+ return (user.set_time + timespan) - time;
} else {
- member.count = 0;
- member.set_time = time;
+ user.tickets = 0;
+ user.set_time = time;
}
}
}
- if time < member.last_time + self.ratelimit.delay {
- (member.last_time + self.ratelimit.delay) - time
+ if time < user.last_time + self.ratelimit.delay {
+ (user.last_time + self.ratelimit.delay) - time
} else {
- member.count += 1;
- member.last_time = time;
+ user.tickets += 1;
+ user.last_time = time;
0
}
diff --git a/src/ext/framework/configuration.rs b/src/ext/framework/configuration.rs
index f841a85..cd48e44 100644
--- a/src/ext/framework/configuration.rs
+++ b/src/ext/framework/configuration.rs
@@ -67,6 +67,44 @@ pub struct Configuration {
}
impl Configuration {
+ /// Allows you to change what accounts to ignore.
+ pub fn account_type(mut self, account_type: AccountType) -> Self {
+ self.account_type = account_type;
+
+ self
+ }
+
+ /// Whether to allow whitespace being optional between a mention/prefix and
+ /// a command.
+ ///
+ /// **Note**: Defaults to `false`.
+ ///
+ /// # Examples
+ ///
+ /// Setting this to `false` will _only_ allow this scenario to occur:
+ ///
+ /// ```ignore
+ /// <@245571012924538880> about
+ /// !about
+ ///
+ /// // bot processes and executes the "about" command if it exists
+ /// ```
+ ///
+ /// while setting this to `true` will _also_ allow this scenario to occur:
+ ///
+ /// ```ignore
+ /// <@245571012924538880>about
+ /// ! about
+ ///
+ /// // bot processes and executes the "about" command if it exists
+ /// ```
+ pub fn allow_whitespace(mut self, allow_whitespace: bool)
+ -> Self {
+ self.allow_whitespace = allow_whitespace;
+
+ self
+ }
+
/// The default depth of the message to check for commands. Defaults to 5.
/// This determines how "far" into a message to check for a valid command.
///
@@ -81,57 +119,49 @@ impl Configuration {
self
}
- /// Message that's sent when a command is on cooldown.
- /// See framework documentation to see where is this utilized.
- ///
- /// %time% will be replaced with waiting time in seconds.
- pub fn rate_limit_message<S>(mut self, rate_limit_message: S) -> Self
- where S: Into<String> {
- self.rate_limit_message = Some(rate_limit_message.into());
+ /// Sets the prefix to respond to. This can either be a single-char or
+ /// multi-char string.
+ pub fn dynamic_prefix<F>(mut self, dynamic_prefix: F) -> Self
+ where F: Fn(&Context) -> Option<String> + Send + Sync + 'static {
+ self.dynamic_prefix = Some(Box::new(dynamic_prefix));
self
}
- /// Message that's sent when a user with wrong permissions calls a command.
- pub fn invalid_permission_message<S>(mut self, invalid_permission_message: S) -> Self
- where S: Into<String> {
- self.invalid_permission_message = Some(invalid_permission_message.into());
+ /// Message that's sent when one of a command's checks doesn't succeed.
+ pub fn invalid_check_message(mut self, content: &str) -> Self {
+ self.invalid_check_message = Some(content.to_owned());
self
}
- /// Message that's sent when one of a command's checks doesn't succeed.
- pub fn invalid_check_message<S>(mut self, invalid_check_message: S) -> Self
- where S: Into<String> {
- self.invalid_check_message = Some(invalid_check_message.into());
+ /// Message that's sent when a user with wrong permissions calls a command.
+ pub fn invalid_permission_message(mut self, content: &str) -> Self {
+ self.invalid_permission_message = Some(content.to_owned());
self
}
- /// Message that's sent when a command isn't available in DM.
- pub fn no_dm_message<S>(mut self, no_dm_message: S) -> Self
- where S: Into<String> {
- self.no_dm_message = Some(no_dm_message.into());
+ /// Message that's sent when a command is on cooldown.
+ /// See framework documentation to see where is this utilized.
+ ///
+ /// %time% will be replaced with waiting time in seconds.
+ pub fn rate_limit_message(mut self, content: &str) -> Self {
+ self.rate_limit_message = Some(content.to_owned());
self
}
- /// Message that's sent when a command isn't available in guilds.
- pub fn no_guild_message<S>(mut self, no_guild_message: S) -> Self
- where S: Into<String> {
- self.no_guild_message = Some(no_guild_message.into());
+ /// Message that's sent when a command isn't available in DM.
+ pub fn no_dm_message(mut self, content: &str) -> Self {
+ self.no_dm_message = Some(content.to_owned());
self
}
- /// Message that's sent when user sends too many arguments to a command.
- ///
- /// %max% will be replaced with maximum allowed amount of arguments.
- ///
- /// %given% will be replced with the given amount of arguments.
- pub fn too_many_args_message<S>(mut self, too_many_args_message: S) -> Self
- where S: Into<String> {
- self.too_many_args_message = Some(too_many_args_message.into());
+ /// Message that's sent when a command isn't available in guilds.
+ pub fn no_guild_message(mut self, content: &str) -> Self {
+ self.no_guild_message = Some(content.to_owned());
self
}
@@ -141,9 +171,8 @@ impl Configuration {
/// %min% will be replaced with minimum allowed amount of arguments.
///
/// %given% will be replced with the given amount of arguments.
- pub fn not_enough_args_message<S>(mut self, not_enough_args_message: S) -> Self
- where S: Into<String> {
- self.not_enough_args_message = Some(not_enough_args_message.into());
+ pub fn not_enough_args_message(mut self, content: &str) -> Self {
+ self.not_enough_args_message = Some(content.to_owned());
self
}
@@ -184,41 +213,10 @@ impl Configuration {
self
}
- /// Whether to allow whitespace being optional between a mention/prefix and
- /// a command.
- ///
- /// **Note**: Defaults to `false`.
- ///
- /// # Examples
- ///
- /// Setting this to `false` will _only_ allow this scenario to occur:
- ///
- /// ```ignore
- /// <@245571012924538880> about
- /// !about
- ///
- /// // bot processes and executes the "about" command if it exists
- /// ```
- ///
- /// while setting this to `true` will _also_ allow this scenario to occur:
- ///
- /// ```ignore
- /// <@245571012924538880>about
- /// ! about
- ///
- /// // bot processes and executes the "about" command if it exists
- /// ```
- pub fn allow_whitespace(mut self, allow_whitespace: bool)
- -> Self {
- self.allow_whitespace = allow_whitespace;
-
- self
- }
-
/// Sets the prefix to respond to. This can either be a single-char or
/// multi-char string.
- pub fn prefix<S: Into<String>>(mut self, prefix: S) -> Self {
- self.prefixes = vec![prefix.into()];
+ pub fn prefix(mut self, prefix: &str) -> Self {
+ self.prefixes = vec![prefix.to_owned()];
self
}
@@ -231,18 +229,13 @@ impl Configuration {
self
}
- /// Allows you to change what accounts to ignore.
- pub fn account_type(mut self, account_type: AccountType) -> Self {
- self.account_type = account_type;
-
- self
- }
-
- /// Sets the prefix to respond to. This can either be a single-char or
- /// multi-char string.
- pub fn dynamic_prefix<F>(mut self, dynamic_prefix: F) -> Self
- where F: Fn(&Context) -> Option<String> + Send + Sync + 'static {
- self.dynamic_prefix = Some(Box::new(dynamic_prefix));
+ /// Message that's sent when user sends too many arguments to a command.
+ ///
+ /// %max% will be replaced with maximum allowed amount of arguments.
+ ///
+ /// %given% will be replced with the given amount of arguments.
+ pub fn too_many_args_message(mut self, content: &str) -> Self {
+ self.too_many_args_message = Some(content.to_owned());
self
}
diff --git a/src/ext/framework/create_command.rs b/src/ext/framework/create_command.rs
index e3faffd..7a1d744 100644
--- a/src/ext/framework/create_command.rs
+++ b/src/ext/framework/create_command.rs
@@ -4,12 +4,18 @@ use std::collections::HashMap;
use std::default::Default;
use std::sync::Arc;
use ::client::Context;
-use ::model::Message;
-use ::model::Permissions;
+use ::model::{Message, Permissions};
pub struct CreateCommand(pub Command);
impl CreateCommand {
+ /// Adds a ratelimit bucket.
+ pub fn bucket(mut self, bucket: &str) -> Self {
+ self.0.bucket = Some(bucket.to_owned());
+
+ self
+ }
+
/// Adds a "check" to a command, which checks whether or not the command's
/// function should be called.
///
@@ -57,20 +63,6 @@ impl CreateCommand {
self
}
- /// Adds a ratelimit bucket.
- pub fn bucket(mut self, bucket: &str) -> Self {
- self.0.bucket = Some(bucket.to_owned());
-
- self
- }
-
- /// Whether command should be displayed in help list or not, used by other commands.
- pub fn help_available(mut self, help_available: bool) -> Self {
- self.0.help_available = help_available;
-
- self
- }
-
/// Whether command can be used only privately or not.
pub fn dm_only(mut self, dm_only: bool) -> Self {
self.0.dm_only = dm_only;
@@ -78,34 +70,6 @@ impl CreateCommand {
self
}
- /// Whether command can be used only in guilds or not.
- pub fn guild_only(mut self, guild_only: bool) -> Self {
- self.0.guild_only = guild_only;
-
- self
- }
-
- /// Minumum amount of arguments that should be passed.
- pub fn min_args(mut self, min_args: i32) -> Self {
- self.0.min_args = Some(min_args);
-
- self
- }
-
- /// Maximum amount of arguments that can be passed.
- pub fn max_args(mut self, max_args: i32) -> Self {
- self.0.max_args = Some(max_args);
-
- self
- }
-
- /// Maximum amount of arguments that can be passed.
- pub fn required_permissions(mut self, required_permissions: Permissions) -> Self {
- self.0.required_permissions = required_permissions;
-
- self
- }
-
/// A function that can be called when a command is received.
/// You can return Err(string) if there's an error.
///
@@ -148,6 +112,41 @@ impl CreateCommand {
self
}
+ /// Whether command can be used only in guilds or not.
+ pub fn guild_only(mut self, guild_only: bool) -> Self {
+ self.0.guild_only = guild_only;
+
+ self
+ }
+
+ /// Whether command should be displayed in help list or not, used by other commands.
+ pub fn help_available(mut self, help_available: bool) -> Self {
+ self.0.help_available = help_available;
+
+ self
+ }
+
+ /// Maximum amount of arguments that can be passed.
+ pub fn max_args(mut self, max_args: i32) -> Self {
+ self.0.max_args = Some(max_args);
+
+ self
+ }
+
+ /// Minumum amount of arguments that should be passed.
+ pub fn min_args(mut self, min_args: i32) -> Self {
+ self.0.min_args = Some(min_args);
+
+ self
+ }
+
+ /// Maximum amount of arguments that can be passed.
+ pub fn required_permissions(mut self, required_permissions: Permissions) -> Self {
+ self.0.required_permissions = required_permissions;
+
+ self
+ }
+
/// Command usage schema, used by other commands.
pub fn usage(mut self, usage: &str) -> Self {
self.0.usage = Some(usage.to_owned());
diff --git a/src/ext/framework/create_group.rs b/src/ext/framework/create_group.rs
index db2832b..8374e8b 100644
--- a/src/ext/framework/create_group.rs
+++ b/src/ext/framework/create_group.rs
@@ -24,34 +24,34 @@ pub struct CreateGroup(pub CommandGroup);
/// .exec_str("meew0")))
/// ```
impl CreateGroup {
- /// If prefix is set, it will be required before all command names.
- /// For example, if bot prefix is "~" and group prefix is "image"
- /// we'd call a subcommand named "hibiki" by sending "~image hibiki".
- ///
- /// **Note**: serenity automatically puts a space after group prefix.
- pub fn prefix(mut self, desc: &str) -> Self {
- self.0.prefix = Some(desc.to_owned());
-
- self
- }
-
/// Adds a command to group.
- pub fn command<F, S>(mut self, command_name: S, f: F) -> Self
- where F: FnOnce(CreateCommand) -> CreateCommand,
- S: Into<String> {
+ pub fn command<F>(mut self, command_name: &str, f: F) -> Self
+ where F: FnOnce(CreateCommand) -> CreateCommand {
let cmd = f(CreateCommand(Command::default())).0;
- self.0.commands.insert(command_name.into(), Arc::new(cmd));
+ self.0.commands.insert(command_name.to_owned(), Arc::new(cmd));
self
}
/// Adds a command to group with simplified API.
/// You can return Err(string) if there's an error.
- pub fn on<F, S>(mut self, command_name: S, f: F) -> Self
- where F: Fn(&Context, &Message, Vec<String>) -> Result<(), String> + Send + Sync + 'static,
- S: Into<String> {
- self.0.commands.insert(command_name.into(), Arc::new(Command::new(f)));
+ pub fn on<F>(mut self, command_name: &str, f: F) -> Self
+ where F: Fn(&Context, &Message, Vec<String>) -> Result<(), String> + Send + Sync + 'static {
+ let cmd = Arc::new(Command::new(f));
+
+ self.0.commands.insert(command_name.to_owned(), cmd);
+
+ self
+ }
+
+ /// If prefix is set, it will be required before all command names.
+ /// For example, if bot prefix is "~" and group prefix is "image"
+ /// we'd call a subcommand named "hibiki" by sending "~image hibiki".
+ ///
+ /// **Note**: serenity automatically puts a space after group prefix.
+ pub fn prefix(mut self, desc: &str) -> Self {
+ self.0.prefix = Some(desc.to_owned());
self
}
diff --git a/src/ext/framework/help_commands.rs b/src/ext/framework/help_commands.rs
index 375b8dc..385afe4 100644
--- a/src/ext/framework/help_commands.rs
+++ b/src/ext/framework/help_commands.rs
@@ -1,8 +1,7 @@
-pub use super::{Command, CommandGroup};
-
use std::collections::HashMap;
use std::sync::Arc;
use std::fmt::Write;
+use super::{Command, CommandGroup};
use ::client::Context;
use ::model::Message;
use ::utils::Colour;
@@ -41,6 +40,7 @@ pub fn with_embeds(ctx: &Context,
if let Some((command_name, command)) = found {
if !command.help_available {
error_embed(ctx, message, "**Error**: No help available.");
+
return Ok(());
}
@@ -96,6 +96,7 @@ pub fn with_embeds(ctx: &Context,
return Ok(());
}
+
let _ = ctx.send_message(message.channel_id, |m| {
m.embed(|mut e| {
e = e.colour(Colour::rosewater())
@@ -109,8 +110,9 @@ pub fn with_embeds(ctx: &Context,
let _ = write!(desc, "Prefix: {}\n", x);
}
+ desc.push_str("Commands:\n");
+
let mut no_commands = true;
- let _ = write!(desc, "Commands:\n");
for (n, cmd) in &group.commands {
if cmd.help_available {
@@ -143,6 +145,7 @@ pub fn plain(ctx: &Context,
for (group_name, group) in groups {
let mut found: Option<(&String, &Command)> = None;
+
if let Some(ref prefix) = group.prefix {
for (command_name, command) in &group.commands {
if name == format!("{} {}", prefix, command_name) {
@@ -177,16 +180,15 @@ pub fn plain(ctx: &Context,
let _ = write!(result, "**Group:** {}\n", group_name);
}
- let available = if command.dm_only {
+ result.push_str("**Available:** ");
+ result.push_str(if command.dm_only {
"Only in DM"
} else if command.guild_only {
"Only in guilds"
} else {
"In DM and guilds"
- };
-
- let _ = write!(result, "**Available:** {}\n", available);
- let _ = ctx.say(&result);
+ });
+ result.push_str("\n");
return Ok(());
}
@@ -196,31 +198,31 @@ pub fn plain(ctx: &Context,
return Ok(());
}
+
let mut result = "**Commands**\nTo get help about individual command, pass \
its name as an argument to this command.\n\n"
.to_string();
for (group_name, group) in groups {
- let mut desc = String::new();
+ let _ = write!(result, "**{}:** ", group_name);
if let Some(ref x) = group.prefix {
- let _ = write!(desc, "(prefix: `{}`): ", x);
+ let _ = write!(result, "(prefix: `{}`): ", x);
}
let mut no_commands = true;
for (n, cmd) in &group.commands {
if cmd.help_available {
- let _ = write!(desc, "`{}` ", n);
+ let _ = write!(result, "`{}` ", n);
+
no_commands = false;
}
}
if no_commands {
- let _ = write!(desc, "*[No commands]*");
+ result.push_str("*[No Commands]*");
}
-
- let _ = write!(result, "**{}:** {}\n", group_name, desc);
}
let _ = ctx.say(&result);
diff --git a/src/ext/framework/mod.rs b/src/ext/framework/mod.rs
index 6cd222f..796f1a3 100644
--- a/src/ext/framework/mod.rs
+++ b/src/ext/framework/mod.rs
@@ -61,11 +61,11 @@ mod create_command;
mod create_group;
mod buckets;
+pub use self::buckets::{Bucket, MemberRatelimit, Ratelimit};
pub use self::command::{Command, CommandType, CommandGroup};
pub use self::configuration::{AccountType, Configuration};
pub use self::create_command::CreateCommand;
pub use self::create_group::CreateGroup;
-pub use self::buckets::{Bucket, MemberRatelimit, Ratelimit};
use self::command::{AfterHook, Hook};
use std::collections::HashMap;
@@ -225,9 +225,9 @@ impl Framework {
self.buckets.insert(s.into(), Bucket {
ratelimit: Ratelimit {
delay: delay,
- limit: Some((time_span, limit))
+ limit: Some((time_span, limit)),
},
- limits: HashMap::new()
+ users: HashMap::new(),
});
self
@@ -239,22 +239,14 @@ impl Framework {
self.buckets.insert(s.into(), Bucket {
ratelimit: Ratelimit {
delay: delay,
- limit: None
+ limit: None,
},
- limits: HashMap::new()
+ users: HashMap::new(),
});
self
}
- #[allow(map_entry)]
- fn ratelimit_time(&mut self, bucket_name: &str, user_id: u64) -> i64 {
- self.buckets
- .get_mut(bucket_name)
- .map(|bucket| bucket.take(user_id))
- .unwrap_or(0)
- }
-
#[allow(cyclomatic_complexity)]
#[doc(hidden)]
pub fn dispatch(&mut self, context: Context, message: Message) {
@@ -264,10 +256,8 @@ impl Framework {
return;
}
},
- AccountType::Bot => {
- if message.author.bot {
- return;
- }
+ AccountType::Bot => if message.author.bot {
+ return;
},
AccountType::Automatic => {
let cache = CACHE.read().unwrap();
@@ -481,13 +471,14 @@ impl Framework {
pub fn on<F, S>(mut self, command_name: S, f: F) -> Self
where F: Fn(&Context, &Message, Vec<String>) -> Result<(), String> + Send + Sync + 'static,
S: Into<String> {
- if !self.groups.contains_key("Ungrouped") {
- self.groups.insert("Ungrouped".to_string(), Arc::new(CommandGroup::default()));
- }
+ {
+ let ungrouped = self.groups.entry("Ungrouped".to_owned())
+ .or_insert_with(|| Arc::new(CommandGroup::default()));
- if let Some(ref mut x) = self.groups.get_mut("Ungrouped") {
- if let Some(ref mut y) = Arc::get_mut(x) {
- y.commands.insert(command_name.into(), Arc::new(Command::new(f)));
+ if let Some(ref mut group) = Arc::get_mut(ungrouped) {
+ let name = command_name.into();
+
+ group.commands.insert(name, Arc::new(Command::new(f)));
}
}
@@ -510,15 +501,15 @@ impl Framework {
pub fn command<F, S>(mut self, command_name: S, f: F) -> Self
where F: FnOnce(CreateCommand) -> CreateCommand,
S: Into<String> {
- let cmd = f(CreateCommand(Command::default())).0;
+ {
+ let ungrouped = self.groups.entry("Ungrouped".to_owned())
+ .or_insert_with(|| Arc::new(CommandGroup::default()));
- if !self.groups.contains_key("Ungrouped") {
- self.groups.insert("Ungrouped".to_string(), Arc::new(CommandGroup::default()));
- }
+ if let Some(ref mut group) = Arc::get_mut(ungrouped) {
+ let cmd = f(CreateCommand(Command::default())).0;
+ let name = command_name.into();
- if let Some(ref mut x) = self.groups.get_mut("Ungrouped") {
- if let Some(ref mut y) = Arc::get_mut(x) {
- y.commands.insert(command_name.into(), Arc::new(cmd));
+ group.commands.insert(name, Arc::new(cmd));
}
}
@@ -588,15 +579,16 @@ impl Framework {
pub fn set_check<F, S>(mut self, command: S, check: F) -> Self
where F: Fn(&Context, &Message) -> bool + Send + Sync + 'static,
S: Into<String> {
- if !self.groups.contains_key("Ungrouped") {
- self.groups.insert("Ungrouped".to_string(), Arc::new(CommandGroup::default()));
- }
+ {
+ let ungrouped = self.groups.entry("Ungrouped".to_owned())
+ .or_insert_with(|| Arc::new(CommandGroup::default()));
- if let Some(ref mut group) = self.groups.get_mut("Ungrouped") {
- if let Some(group_mut) = Arc::get_mut(group) {
- if let Some(ref mut command) = group_mut.commands.get_mut(&command.into()) {
- if let Some(c) = Arc::get_mut(command) {
- c.checks.push(Box::new(check));
+ if let Some(group) = Arc::get_mut(ungrouped) {
+ let name = command.into();
+
+ if let Some(ref mut command) = group.commands.get_mut(&name) {
+ if let Some(command) = Arc::get_mut(command) {
+ command.checks.push(Box::new(check));
}
}
}
@@ -604,4 +596,11 @@ impl Framework {
self
}
+
+ fn ratelimit_time(&mut self, bucket_name: &str, user_id: u64) -> i64 {
+ self.buckets
+ .get_mut(bucket_name)
+ .map(|bucket| bucket.take(user_id))
+ .unwrap_or(0)
+ }
}