diff options
| author | Illia K <[email protected]> | 2016-11-28 19:21:33 +0000 |
|---|---|---|
| committer | Austin Hellyer <[email protected]> | 2016-11-28 12:13:46 -0800 |
| commit | 83515e1a5ccc850a8c352060a19394a53aed8454 (patch) | |
| tree | e5531327c82e37ae8b6874ebcba4b81746b4dd1e /src/ext | |
| parent | Improve docs and add new message builder methods (diff) | |
| download | serenity-83515e1a5ccc850a8c352060a19394a53aed8454.tar.xz serenity-83515e1a5ccc850a8c352060a19394a53aed8454.zip | |
Add before/after framework command hooks
These hooks will each be run prior to or after the command, and will
finish execution before executing the command.
These can be configured in a Framework via:
```rs
client.with_framework(|f| f
.before(|_context, message, _command_name| {
println!("Got command '{}'", command_name);
})
.after(|_context, _message, command_name| {
println!("Finished command '{}'", command_name);
}));
```
This does introduce a backwards compatibility break, by requiring
commands' Context/Message to be borrowed
Upgrade path:
If not using the `command!` macro, modify command signatures from:
```rs
fn some_command(context: Context, message: Message, args: Vec<String>)
```
to
```rs
fn some_command(context: &Context, message: &Message, args: Vec<String>)
```
Diffstat (limited to 'src/ext')
| -rw-r--r-- | src/ext/framework/command.rs | 2 | ||||
| -rw-r--r-- | src/ext/framework/mod.rs | 36 |
2 files changed, 33 insertions, 5 deletions
diff --git a/src/ext/framework/command.rs b/src/ext/framework/command.rs index 0c595b3..e0a4616 100644 --- a/src/ext/framework/command.rs +++ b/src/ext/framework/command.rs @@ -4,7 +4,7 @@ use ::client::Context; use ::model::Message; #[doc(hidden)] -pub type Command = Fn(Context, Message, Vec<String>) + Send + Sync; +pub type Command = Fn(&Context, &Message, Vec<String>) + Send + Sync; #[doc(hidden)] pub type InternalCommand = Arc<Command>; diff --git a/src/ext/framework/mod.rs b/src/ext/framework/mod.rs index 2a92840..731efd0 100644 --- a/src/ext/framework/mod.rs +++ b/src/ext/framework/mod.rs @@ -100,12 +100,12 @@ use ::model::Message; #[macro_export] macro_rules! command { ($fname:ident($c:ident, $m:ident, $a:ident) $b:block) => { - fn $fname($c: Context, $m: Message, $a: Vec<String>) { + fn $fname($c: &Context, $m: &Message, $a: Vec<String>) { $b } }; ($fname:ident($c:ident, $m:ident, $a:ident, $($name:ident: $t:ty),*) $b:block) => { - fn $fname($c: Context, $m: Message, $a: Vec<String>) { + fn $fname($c: &Context, $m: &Message, $a: Vec<String>) { let mut i = $a.iter(); $( @@ -163,6 +163,8 @@ pub enum CommandType { pub struct Framework { configuration: Configuration, commands: HashMap<String, InternalCommand>, + before: Option<Arc<Fn(&Context, &Message, &String) + Send + Sync + 'static>>, + after: Option<Arc<Fn(&Context, &Message, &String) + Send + Sync + 'static>>, checks: HashMap<String, Arc<Fn(&Context, &Message) -> bool + Send + Sync + 'static>>, /// Whether the framework has been "initialized". /// @@ -261,15 +263,25 @@ impl Framework { } } + let before = self.before.clone(); let command = command.clone(); + let after = self.after.clone(); thread::spawn(move || { + if let Some(before) = before { + (before)(&context, &message, &built); + } + let args = message.content[position + built.len()..] .split_whitespace() .map(|arg| arg.to_owned()) .collect::<Vec<String>>(); - (command)(context, message, args) + (command)(&context, &message, args); + + if let Some(after) = after { + (after)(&context, &message, &built); + } }); return; @@ -289,7 +301,7 @@ impl Framework { /// /// [module-level documentation]: index.html pub fn on<F, S>(mut self, command_name: S, f: F) -> Self - where F: Fn(Context, Message, Vec<String>) + Send + Sync + 'static, + where F: Fn(&Context, &Message, Vec<String>) + Send + Sync + 'static, S: Into<String> { self.commands.insert(command_name.into(), Arc::new(f)); self.initialized = true; @@ -297,6 +309,22 @@ impl Framework { self } + /// This will call given closure before every command's execution + pub fn before<F>(mut self, f: F) -> Self + where F: Fn(&Context, &Message, &String) + Send + Sync + 'static { + self.before = Some(Arc::new(f)); + + self + } + + /// This will call given closure after every command's execution + pub fn after<F>(mut self, f: F) -> Self + where F: Fn(&Context, &Message, &String) + Send + Sync + 'static { + self.after = Some(Arc::new(f)); + + self + } + /// Adds a "check" to a command, which checks whether or not the command's /// associated function should be called. /// |