aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoracdenisSK <[email protected]>2017-07-22 16:59:10 +0200
committeracdenisSK <[email protected]>2017-07-22 16:59:10 +0200
commit2b053ea007d6ca9cc820cb910597e8b5dad89d70 (patch)
treec0664957758043b80fc7e40d9acc7923da53d3c1 /src
parentRemove the uneccessary function and `Send + Sync` bounds (diff)
downloadserenity-2b053ea007d6ca9cc820cb910597e8b5dad89d70.tar.xz
serenity-2b053ea007d6ca9cc820cb910597e8b5dad89d70.zip
Fix #130
Removed action support from the builtin one as well, due to it adding some uneccassery complexity and it being only asked upon by one user
Diffstat (limited to 'src')
-rw-r--r--src/client/dispatch.rs113
-rw-r--r--src/client/mod.rs80
-rw-r--r--src/framework/configuration.rs30
-rw-r--r--src/framework/help_commands.rs9
-rw-r--r--src/framework/mod.rs384
-rw-r--r--src/model/channel/message.rs3
6 files changed, 314 insertions, 305 deletions
diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs
index 68190d1..6c732d7 100644
--- a/src/client/dispatch.rs
+++ b/src/client/dispatch.rs
@@ -7,12 +7,12 @@ use super::Context;
use typemap::ShareMap;
use ::gateway::Shard;
use ::model::event::Event;
-use ::model::{Message, Reaction, GuildId, Channel};
+use ::model::{Message, GuildId, Channel};
use chrono::{Utc, Timelike};
use tokio_core::reactor::Handle;
#[cfg(feature="framework")]
-use ::ext::framework::{Framework, ReactionAction};
+use ::ext::framework::Framework;
#[cfg(feature="cache")]
use super::CACHE;
@@ -61,66 +61,37 @@ fn context(conn: &Arc<Mutex<Shard>>,
Context::new(conn.clone(), data.clone())
}
-// Heck you macro hygiene.
-macro_rules! impl_reaction_events {
- (($event:ident, $conn:ident, $data:ident, $event_handler:ident, $framework:ident, $handle:ident), $type_of_action:ident, $dispatch_name:ident) => {
- let context = context($conn, $data);
- let framework = $framework.lock().unwrap();
-
- if framework.initialized {
- $dispatch_name(context.clone(),
- $event.reaction.clone(),
- $event_handler,
- $handle);
-
- let res = framework.reaction_actions
- .iter()
- .find(|&(ra, _)| {
- if let ReactionAction::$type_of_action(ref kind) = *ra {
- *kind == $event.reaction.emoji
- } else {
- false
- }
- });
-
- if let Some((_, f)) = res {
- f(context, $event.reaction.message_id, $event.reaction.channel_id);
- }
- } else {
- $dispatch_name(context, $event.reaction, $event_handler, $handle);
- }
- }
-}
-
#[cfg(feature="framework")]
pub fn dispatch<H: EventHandler + 'static>(event: Event,
conn: &Arc<Mutex<Shard>>,
- framework: &Arc<sync::Mutex<Framework>>,
+ framework: &Arc<sync::Mutex<Option<Box<Framework>>>>,
data: &Arc<Mutex<ShareMap>>,
event_handler: &Arc<H>,
tokio_handle: &Handle) {
match event {
Event::MessageCreate(event) => {
let context = context(conn, data);
- let mut framework = framework.lock().unwrap();
-
- if framework.initialized {
+ if let Some(ref mut framework) = *framework.lock().unwrap() {
+ if framework.initialized() {
+ dispatch_message(context.clone(),
+ event.message.clone(),
+ event_handler,
+ tokio_handle);
+
+ framework.dispatch(context, event.message, tokio_handle);
+ } else {
+ dispatch_message(context.clone(),
+ event.message.clone(),
+ event_handler,
+ tokio_handle);
+ }
+ } else {
dispatch_message(context.clone(),
event.message.clone(),
event_handler,
tokio_handle);
-
- framework.dispatch(context, event.message, tokio_handle);
- } else {
- dispatch_message(context, event.message, event_handler, tokio_handle);
}
},
- Event::ReactionAdd(event) => {
- impl_reaction_events!((event, conn, data, event_handler, framework, tokio_handle), Add, dispatch_reaction_add);
- },
- Event::ReactionRemove(event) => {
- impl_reaction_events!((event, conn, data, event_handler, framework, tokio_handle), Remove, dispatch_reaction_remove);
- },
other => handle_event(other, conn, data, event_handler, tokio_handle),
}
}
@@ -139,14 +110,6 @@ pub fn dispatch<H: EventHandler + 'static>(event: Event,
event_handler,
tokio_handle);
},
- Event::ReactionAdd(event) => {
- let context = context(conn, data);
- dispatch_reaction_add(context, event.reaction, tokio_handle);
- },
- Event::ReactionRemove(event) => {
- let context = context(conn, data);
- dispatch_reaction_remove(context, event.reaction, tokio_handle);
- },
other => handle_event(other, conn, data, event_handler, tokio_handle),
}
}
@@ -169,28 +132,6 @@ fn dispatch_message<H: EventHandler + 'static>(context: Context,
});
}
-fn dispatch_reaction_add<H: EventHandler + 'static>(context: Context,
- reaction: Reaction,
- event_handler: &Arc<H>,
- tokio_handle: &Handle) {
- let h = event_handler.clone();
- tokio_handle.spawn_fn(move || {
- h.on_reaction_add(context, reaction);
- Ok(())
- });
-}
-
-fn dispatch_reaction_remove<H: EventHandler + 'static>(context: Context,
- reaction: Reaction,
- event_handler: &Arc<H>,
- tokio_handle: &Handle) {
- let h = event_handler.clone();
- tokio_handle.spawn_fn(move || {
- h.on_reaction_remove(context, reaction);
- Ok(())
- });
-}
-
#[allow(cyclomatic_complexity, unused_assignments, unused_mut)]
fn handle_event<H: EventHandler + 'static>(event: Event,
conn: &Arc<Mutex<Shard>>,
@@ -603,8 +544,22 @@ fn handle_event<H: EventHandler + 'static>(event: Event,
},
// Already handled by the framework check macro
- Event::ReactionAdd(_) => {},
- Event::ReactionRemove(_) => {},
+ Event::ReactionAdd(event) => {
+ let h = event_handler.clone();
+ let context = context(conn, data);
+ tokio_handle.spawn_fn(move || {
+ h.on_reaction_add(context, event.reaction);
+ Ok(())
+ });
+ },
+ Event::ReactionRemove(event) => {
+ let h = event_handler.clone();
+ let context = context(conn, data);
+ tokio_handle.spawn_fn(move || {
+ h.on_reaction_remove(context, event.reaction);
+ Ok(())
+ });
+ },
Event::ReactionRemoveAll(event) => {
let context = context(conn, data);
diff --git a/src/client/mod.rs b/src/client/mod.rs
index 93e09ce..6241b5b 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -51,7 +51,7 @@ use ::internal::prelude::*;
use ::internal::ws_impl::ReceiverExt;
use ::model::event::*;
-#[cfg(feature="framework")]
+#[cfg(any(feature="framework", feature="builtin_framework"))]
use ::framework::Framework;
static HANDLE_STILL: AtomicBool = ATOMIC_BOOL_INIT;
@@ -193,7 +193,7 @@ pub struct Client<H: EventHandler + 'static> {
/// [`on_ready`]: #method.on_ready
event_handler: Arc<H>,
#[cfg(feature="framework")]
- framework: Arc<sync::Mutex<Framework>>,
+ framework: Arc<sync::Mutex<Option<Box<Framework>>>>,
token: Arc<sync::Mutex<String>>,
}
@@ -241,7 +241,7 @@ impl<H: EventHandler + 'static> Client<H> {
Client {
data: Arc::new(Mutex::new(ShareMap::custom())),
event_handler: Arc::new(handler),
- framework: Arc::new(sync::Mutex::new(Framework::default())),
+ framework: Arc::new(sync::Mutex::new(None)),
token: locked,
}
} else {
@@ -268,6 +268,8 @@ impl<H: EventHandler + 'static> Client<H> {
/// # use serenity::prelude::EventHandler;
/// # use std::error::Error;
/// #
+ /// use serenity::framework::BuiltinFramework;
+ ///
/// struct Handler;
///
/// impl EventHandler for Handler {}
@@ -276,7 +278,7 @@ impl<H: EventHandler + 'static> Client<H> {
/// use std::env;
///
/// let mut client = Client::new(&env::var("DISCORD_TOKEN")?, Handler);
- /// client.with_framework(|f| f
+ /// client.with_framework(BuiltinFramework::new()
/// .configure(|c| c.prefix("~"))
/// .command("ping", |c| c.exec_str("Pong!")));
/// # Ok(())
@@ -286,16 +288,69 @@ impl<H: EventHandler + 'static> Client<H> {
/// # try_main().unwrap();
/// # }
/// ```
+ ///
+ /// Using your own framework:
+ ///
+ /// ```rust,ignore
+ /// # use serenity::prelude::EventHandler;
+ /// # use std::error::Error;
+ /// #
+ /// use serenity::framework::Framework;
+ /// use serenity::client::Context;
+ /// use serenity::model::*;
+ /// use tokio_core::reactor::Handle;
+ /// use std::collections::HashMap;
+ ///
+ ///
+ /// struct MyFramework {
+ /// commands: HashMap<String, Box<Fn(Message, Vec<String>)>>,
+ /// }
+ ///
+ /// impl Framework for MyFramework {
+ /// fn dispatch(&mut self, _: Context, msg: Message, tokio_handle: &Handle) {
+ /// let args = msg.content.split_whitespace();
+ /// let command = match args.next() {
+ /// Some(command) => {
+ /// if !command.starts_with('*') { return; }
+ /// command
+ /// },
+ /// None => return,
+ /// };
+ ///
+ /// let command = match self.commands.get(&command) {
+ /// Some(command) => command, None => return,
+ /// };
+ ///
+ /// tokio_handle.spawn_fn(move || { (command)(msg, args); Ok() });
+ /// }
+ /// }
+ ///
+ /// struct Handler;
+ ///
+ /// impl EventHandler for Handler {}
+ ///
+ ///
+ /// # fn try_main() -> Result<(), Box<Error>> {
+ /// use serenity::Client;
+ /// use std::env;
///
+ /// let mut client = Client::new(&env::var("DISCORD_TOKEN")?, Handler);
+ /// client.with_framework(MyFramework { commands: { let mut map = HashMap::new(); map.insert("ping".to_string(), Box::new(|msg, _| msg.channel_id.say("pong!"))); map }});
+ /// # Ok(())
+ /// # }
+ /// #
+ /// # fn main() {
+ /// # try_main().unwrap();
+ /// # }
+ /// ```
/// Refer to the documentation for the `framework` module for more in-depth
/// information.
///
/// [`on_message`]: #method.on_message
/// [framework docs]: ../framework/index.html
#[cfg(feature="framework")]
- pub fn with_framework<F>(&mut self, f: F)
- where F: FnOnce(Framework) -> Framework + Send + Sync + 'static {
- self.framework = Arc::new(sync::Mutex::new(f(Framework::default())));
+ pub fn with_framework<F: Framework + 'static>(&mut self, f: F) {
+ self.framework = Arc::new(sync::Mutex::new(Some(Box::new(f))));
}
/// Establish the connection and start listening for events.
@@ -631,13 +686,13 @@ impl<H: EventHandler + 'static> Client<H> {
// Update the framework's current user if the feature is enabled.
//
// This also acts as a form of check to ensure the token is correct.
- #[cfg(feature="framework")]
+ #[cfg(all(feature="builtin_framework", feature="framework"))]
{
let user = http::get_current_user()?;
- self.framework.lock()
- .unwrap()
- .update_current_user(user.id, user.bot);
+ if let Some(ref mut framework) = *self.framework.lock().unwrap() {
+ framework.update_current_user(user.id, user.bot);
+ }
}
let gateway_url = Arc::new(sync::Mutex::new(url));
@@ -678,6 +733,7 @@ impl<H: EventHandler + 'static> Client<H> {
shard: shard,
shard_info: shard_info,
token: self.token.clone(),
+ _pd: std::marker::PhantomData,
}
}};
@@ -718,7 +774,7 @@ struct BootInfo {
struct MonitorInfo<H: EventHandler + 'static> {
data: Arc<Mutex<ShareMap>>,
event_handler: Arc<H>,
- framework: Arc<sync::Mutex<Framework>>,
+ framework: Arc<sync::Mutex<Option<Box<Framework>>>>,
gateway_url: Arc<sync::Mutex<String>>,
shard: Arc<Mutex<Shard>>,
shard_info: [u64; 2],
diff --git a/src/framework/configuration.rs b/src/framework/configuration.rs
index 16c595f..c74739e 100644
--- a/src/framework/configuration.rs
+++ b/src/framework/configuration.rs
@@ -22,10 +22,11 @@ use ::model::{GuildId, Message, UserId};
/// impl EventHandler for Handler {}
/// use serenity::Client;
/// use std::env;
+/// use serenity::framework::BuiltinFramework;
///
/// let mut client = Client::new(&env::var("DISCORD_BOT_TOKEN").unwrap(), Handler);
///
-/// client.with_framework(|f| f
+/// client.with_framework(BuiltinFramework::new()
/// .configure(|c| c.on_mention(true).prefix("~")));
/// ```
///
@@ -109,8 +110,9 @@ impl Configuration {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// use serenity::model::GuildId;
+ /// use serenity::framework::BuiltinFramework;
///
- /// client.with_framework(|f| f.configure(|c| c
+ /// client.with_framework(BuiltinFramework::new().configure(|c| c
/// .blocked_guilds(vec![GuildId(7), GuildId(77)].into_iter().collect())));
/// ```
pub fn blocked_guilds(mut self, guilds: HashSet<GuildId>) -> Self {
@@ -133,8 +135,9 @@ impl Configuration {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// use serenity::model::UserId;
+ /// use serenity::framework::BuiltinFramework;
///
- /// client.with_framework(|f| f.configure(|c| c
+ /// client.with_framework(BuiltinFramework::new().configure(|c| c
/// .blocked_users(vec![UserId(7), UserId(77)].into_iter().collect())));
/// ```
pub fn blocked_users(mut self, users: HashSet<UserId>) -> Self {
@@ -169,10 +172,11 @@ impl Configuration {
/// #
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
+ /// use serenity::framework::BuiltinFramework;
///
/// let disabled = vec!["ping"].into_iter().map(|x| x.to_owned()).collect();
///
- /// client.with_framework(|f| f
+ /// client.with_framework(BuiltinFramework::new()
/// .command("ping", |c| c.exec_str("pong!"))
/// .configure(|c| c.disabled_commands(disabled)));
/// ```
@@ -198,7 +202,9 @@ impl Configuration {
/// #
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .command("ping", |c| c.exec_str("Pong!"))
/// .configure(|c| c.dynamic_prefix(|_, msg| {
/// Some(if msg.channel_id.0 % 5 == 0 {
@@ -282,8 +288,9 @@ impl Configuration {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// use serenity::model::UserId;
+ /// use serenity::framework::BuiltinFramework;
///
- /// client.with_framework(|f| f.configure(|c| c
+ /// client.with_framework(BuiltinFramework::new().configure(|c| c
/// .owners(vec![UserId(7), UserId(77)].into_iter().collect())));
/// ```
///
@@ -297,12 +304,13 @@ impl Configuration {
/// # let mut client = Client::new("token", Handler);
/// use serenity::model::UserId;
/// use std::collections::HashSet;
+ /// use serenity::framework::BuiltinFramework;
///
/// let mut set = HashSet::new();
/// set.insert(UserId(7));
/// set.insert(UserId(77));
///
- /// client.with_framework(|f| f.configure(|c| c.owners(set)));
+ /// client.with_framework(BuiltinFramework::new().configure(|c| c.owners(set)));
/// ```
pub fn owners(mut self, user_ids: HashSet<UserId>) -> Self {
self.owners = user_ids;
@@ -324,7 +332,9 @@ impl Configuration {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f.configure(|c| c
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new().configure(|c| c
/// .prefix("!")));
/// ```
pub fn prefix(mut self, prefix: &str) -> Self {
@@ -347,7 +357,9 @@ impl Configuration {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f.configure(|c| c
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new().configure(|c| c
/// .prefixes(vec!["!", ">", "+"])));
/// ```
pub fn prefixes(mut self, prefixes: Vec<&str>) -> Self {
diff --git a/src/framework/help_commands.rs b/src/framework/help_commands.rs
index a35ce7d..d589ded 100644
--- a/src/framework/help_commands.rs
+++ b/src/framework/help_commands.rs
@@ -11,8 +11,9 @@
//! use std::env;
//!
//! let mut client = Client::new(&env::var("DISCORD_TOKEN").unwrap());
+//! use serenity::framework::BuiltinFramework;
//!
-//! client.with_framework(|f| f
+//! client.with_framework(BuiltinFramework::new()
//! .command("help", |c| c.exec_help(help_commands::with_embeds)));
//! ```
//!
@@ -65,8 +66,9 @@ fn remove_aliases(cmds: &HashMap<String, CommandOrAlias>) -> HashMap<&String, &I
/// # let mut client = Client::new("token", Handler);
/// #
/// use serenity::ext::framework::help_commands;
+/// use serenity::framework::BuiltinFramework;
///
-/// client.with_framework(|f| f
+/// client.with_framework(BuiltinFramework::new()
/// .command("help", |c| c.exec_help(help_commands::with_embeds)));
/// ```
pub fn with_embeds(_: &mut Context,
@@ -217,8 +219,9 @@ pub fn with_embeds(_: &mut Context,
/// # let mut client = Client::new("token", Handler);
/// #
/// use serenity::ext::framework::help_commands;
+/// use serenity::framework::BuiltinFramework;
///
-/// client.with_framework(|f| f
+/// client.with_framework(BuiltinFramework::new()
/// .command("help", |c| c.exec_help(help_commands::plain)));
/// ```
pub fn plain(_: &mut Context,
diff --git a/src/framework/mod.rs b/src/framework/mod.rs
index 73188ca..d04f60f 100644
--- a/src/framework/mod.rs
+++ b/src/framework/mod.rs
@@ -74,7 +74,7 @@ use std::collections::HashMap;
use std::default::Default;
use std::sync::Arc;
use ::client::Context;
-use ::model::{Message, MessageId, UserId, GuildId, ChannelId, ReactionType};
+use ::model::{Message, UserId, GuildId, ChannelId};
use ::model::permissions::Permissions;
use ::utils;
use tokio_core::reactor::Handle;
@@ -84,6 +84,20 @@ use ::client::CACHE;
#[cfg(feature="cache")]
use ::model::Channel;
+/// This trait allows for serenity to either use its builtin framework, or yours.
+///
+/// When implementing, be sure to use `tokio_handle.spawn_fn(|| ...; Ok())` when dispatching commands.
+///
+/// Note that you may see some other methods in here as well, but they're meant to be internal only for the builtin framework.
+pub trait Framework {
+ fn dispatch(&mut self, Context, Message, &Handle);
+
+ #[cfg(feature="builtin_framework")]
+ fn update_current_user(&mut self, UserId, bool) {}
+ #[cfg(feature="builtin_framework")]
+ fn initialized(&self) -> bool { false }
+}
+
/// A macro to generate "named parameters". This is useful to avoid manually
/// using the "arguments" parameter and manually parsing types.
///
@@ -209,16 +223,6 @@ pub enum DispatchError {
type DispatchErrorHook = Fn(Context, Message, DispatchError) + 'static;
-pub(crate) type ActionFn = Fn(Context, MessageId, ChannelId) + 'static;
-
-/// Defines wheter this action should be called when
-/// a reaction's added, or removed.
-#[derive(Clone, Eq, Hash, PartialEq)]
-pub enum ReactionAction {
- Add(ReactionType),
- Remove(ReactionType),
-}
-
/// A utility for easily managing dispatches to commands.
///
/// Refer to the [module-level documentation] for more information.
@@ -226,13 +230,12 @@ pub enum ReactionAction {
/// [module-level documentation]: index.html
#[allow(type_complexity)]
#[derive(Default)]
-pub struct Framework {
+pub struct BuiltinFramework {
configuration: Configuration,
groups: HashMap<String, Arc<CommandGroup>>,
before: Option<Arc<BeforeHook>>,
dispatch_error_handler: Option<Arc<DispatchErrorHook>>,
buckets: HashMap<String, Bucket>,
- pub(crate) reaction_actions: HashMap<ReactionAction, Arc<ActionFn>>,
after: Option<Arc<AfterHook>>,
/// Whether the framework has been "initialized".
///
@@ -253,7 +256,11 @@ pub struct Framework {
user_info: (u64, bool),
}
-impl Framework {
+impl BuiltinFramework {
+ pub fn new() -> Self {
+ BuiltinFramework::default()
+ }
+
/// Configures the framework, setting non-default values. All fields are
/// optional. Refer to [`Configuration::default`] for more information on
/// the default values.
@@ -268,10 +275,11 @@ impl Framework {
/// # struct Handler;
/// # impl EventHandler for Handler {}
/// use serenity::Client;
+ /// use serenity::framework::BuiltinFramework;
/// use std::env;
///
/// let mut client = Client::new(&env::var("DISCORD_TOKEN").unwrap(), Handler);
- /// client.with_framework(|f| f
+ /// client.with_framework(BuiltinFramework::new()
/// .configure(|c| c
/// .depth(3)
/// .allow_whitespace(true)
@@ -305,7 +313,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .bucket("basic", 2, 10, 3)
/// .command("ping", |c| c
/// .bucket("basic")
@@ -336,12 +346,14 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .complex_bucket("basic", 2, 10, 3, |_, guild_id, channel_id, user_id| {
/// // check if the guild is `123` and the channel where the command(s) was called: `456`
/// // and if the user who called the command(s) is `789`
/// // otherwise don't apply the bucket at all.
- /// guild_id == 123 && channel_id == 456 && user_id == 789
+ /// guild_id.is_some() && guild_id.unwrap() == 123 && channel_id == 456 && user_id == 789
/// })
/// .command("ping", |c| c
/// .bucket("basic")
@@ -376,7 +388,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .complex_bucket("basic", 2, 10, 3, |_, channel_id, user_id| {
/// // check if the channel's id where the command(s) was called is `456`
/// // and if the user who called the command(s) is `789`
@@ -418,7 +432,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .simple_bucket("simple", 2)
/// .command("ping", |c| c
/// .bucket("simple")
@@ -438,58 +454,6 @@ impl Framework {
self
}
- /// Defines a "reaction action", that will be called if a reaction was
- /// added; or deleted in a message.
- ///
- /// # Examples
- /// ```rust,no_run
- /// use serenity::model::ReactionType;
- /// use serenity::framework::ReactionAction;
- /// # use serenity::prelude::*;
- /// # struct Handler;
- /// #
- /// # impl EventHandler for Handler {}
- /// # let mut client = Client::new("token", Handler);
- /// #
- /// client.with_framework(|f| f
- /// .action(ReactionAction::Add(ReactionType::Unicode("❤".to_string())), |_, _, channel_id| {
- /// let _ = channel_id.say("love you too");
- /// })
- /// );
- /// ```
- pub fn action<F>(mut self, action: ReactionAction, f: F) -> Self
- where F: Fn(Context, MessageId, ChannelId) + Send + Sync + 'static {
- self.reaction_actions.insert(action, Arc::new(f));
-
- self
- }
-
- /// Remove the action from any further usage by the framework.
- ///
- /// # Examples
- /// ```rust,no_run
- /// use serenity::model::ReactionType;
- /// use serenity::framework::ReactionAction;
- /// # use serenity::prelude::*;
- /// # struct Handler;
- /// #
- /// # impl EventHandler for Handler {}
- /// # let mut client = Client::new("token", Handler);
- /// #
- /// let action = ReactionAction::Add(ReactionType::Unicode("❤".to_string()));
- /// client.with_framework(|f| f
- /// .action(action.clone(), |_, _, channel_id| {
- /// let _ = channel_id.say("love you too");
- /// })
- /// .remove_action(action)
- /// );
- /// ```
- pub fn remove_action(mut self, action: ReactionAction) -> Self {
- self.reaction_actions.remove(&action);
-
- self
- }
-
#[cfg(feature="cache")]
fn is_blocked_guild(&self, message: &Message) -> bool {
if let Some(Channel::Guild(channel)) = CACHE.read().unwrap().channel(message.channel_id) {
@@ -613,126 +577,6 @@ impl Framework {
}
}
- #[allow(cyclomatic_complexity)]
- pub(crate) fn dispatch(&mut self, mut context: Context, message: Message, tokio_handle: &Handle) {
- let res = command::positions(&mut context, &message, &self.configuration);
-
- let positions = match res {
- Some(mut positions) => {
- // First, take out the prefixes that are as long as _or_ longer
- // than the message, to avoid character boundary violations.
- positions.retain(|p| *p < message.content.len());
-
- // Ensure that there is _at least one_ position remaining. There
- // is no point in continuing if there is not.
- if positions.is_empty() {
- return;
- }
-
- positions
- },
- None => return,
- };
-
- 'outer: for position in positions {
- let mut built = String::new();
- let round = message.content.chars()
- .skip(position)
- .collect::<String>();
- let round = round.trim()
- .split_whitespace()
- .collect::<Vec<&str>>();
-
- for i in 0..self.configuration.depth {
- if i != 0 {
- built.push(' ');
- }
-
- built.push_str(match round.get(i) {
- Some(piece) => piece,
- None => continue 'outer,
- });
-
- let groups = self.groups.clone();
-
- for group in groups.values() {
- let command_length = built.len();
-
- if let Some(&CommandOrAlias::Alias(ref points_to)) = group.commands.get(&built) {
- built = points_to.to_owned();
- }
-
- let to_check = if let Some(ref prefix) = group.prefix {
- if built.starts_with(prefix) && command_length > prefix.len() + 1 {
- built[(prefix.len() + 1)..].to_owned()
- } else {
- continue;
- }
- } else {
- built.clone()
- };
-
- if let Some(&CommandOrAlias::Command(ref command)) = group.commands.get(&to_check) {
- let before = self.before.clone();
- let command = command.clone();
- let after = self.after.clone();
- let groups = self.groups.clone();
-
- let args = {
- let content = message.content[position..].trim();
-
- if command.use_quotes {
- utils::parse_quotes(&content[command_length..])
- } else {
- content[command_length..]
- .split_whitespace()
- .map(|arg| arg.to_owned())
- .collect::<Vec<String>>()
- }
- };
-
- if let Some(error) = self.should_fail(&mut context, &message, &command, args.len(), &to_check, &built) {
- if let Some(ref handler) = self.dispatch_error_handler {
- handler(context, message, error);
- }
- return;
- }
-
- tokio_handle.spawn_fn(move || {
- if let Some(before) = before {
- if !(before)(&mut context, &message, &built) {
- return Ok(());
- }
- }
-
- let result = match command.exec {
- CommandType::StringResponse(ref x) => {
- let _ = message.channel_id.say(x);
-
- Ok(())
- },
- CommandType::Basic(ref x) => {
- (x)(&mut context, &message, args)
- },
- CommandType::WithCommands(ref x) => {
- (x)(&mut context, &message, groups, &args)
- }
- };
-
- if let Some(after) = after {
- (after)(&mut context, &message, &built, result);
- }
-
- Ok(())
- });
-
- return;
- }
- }
- }
- }
- }
-
/// Adds a function to be associated with a command, which will be called
/// when a command is used in a message.
///
@@ -763,7 +607,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f.on("ping", ping));
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new().on("ping", ping));
///
/// command!(ping(_ctx, msg) {
/// let _ = msg.channel_id.say("pong!");
@@ -771,7 +617,7 @@ impl Framework {
/// # }
/// ```
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,
+ where F: Fn(&mut Context, &Message, Vec<String>) -> Result<(), String> + 'static,
S: Into<String> {
{
let ungrouped = self.groups.entry("Ungrouped".to_owned())
@@ -844,7 +690,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .group("ping-pong", |g| g
/// .command("ping", |c| c.exec_str("pong!"))
/// .command("pong", |c| c.exec_str("ping!"))));
@@ -875,8 +723,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// use serenity::framework::DispatchError::{NotEnoughArguments, TooManyArguments};
+ /// use serenity::framework::BuiltinFramework;
///
- /// client.with_framework(|f| f
+ /// client.with_framework(BuiltinFramework::new()
/// .on_dispatch_error(|_, msg, error| {
/// match error {
/// NotEnoughArguments { min, given } => {
@@ -914,7 +763,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .before(|ctx, msg, cmd_name| {
/// println!("Running command {}", cmd_name);
/// true
@@ -930,7 +781,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .before(|_, msg, cmd_name| {
/// if let Ok(channel) = msg.channel_id.get() {
/// // Don't run unless in nsfw channel
@@ -966,7 +819,9 @@ impl Framework {
/// # impl EventHandler for Handler {}
/// # let mut client = Client::new("token", Handler);
/// #
- /// client.with_framework(|f| f
+ /// use serenity::framework::BuiltinFramework;
+ ///
+ /// client.with_framework(BuiltinFramework::new()
/// .after(|ctx, msg, cmd_name, error| {
/// // Print out an error if it happened
/// if let Err(why) = error {
@@ -980,8 +835,135 @@ impl Framework {
self
}
+}
+
+impl Framework for BuiltinFramework {
+ fn dispatch(&mut self, mut context: Context, message: Message, tokio_handle: &Handle) {
+ let res = command::positions(&mut context, &message, &self.configuration);
+
+ let positions = match res {
+ Some(mut positions) => {
+ // First, take out the prefixes that are as long as _or_ longer
+ // than the message, to avoid character boundary violations.
+ positions.retain(|p| *p < message.content.len());
+
+ // Ensure that there is _at least one_ position remaining. There
+ // is no point in continuing if there is not.
+ if positions.is_empty() {
+ return;
+ }
- pub(crate) fn update_current_user(&mut self, user_id: UserId, is_bot: bool) {
+ positions
+ },
+ None => return,
+ };
+
+ 'outer: for position in positions {
+ let mut built = String::new();
+ let round = message.content.chars()
+ .skip(position)
+ .collect::<String>();
+ let round = round.trim()
+ .split_whitespace()
+ .collect::<Vec<&str>>();
+
+ for i in 0..self.configuration.depth {
+ if i != 0 {
+ built.push(' ');
+ }
+
+ built.push_str(match round.get(i) {
+ Some(piece) => piece,
+ None => continue 'outer,
+ });
+
+ let groups = self.groups.clone();
+
+ for group in groups.values() {
+ let command_length = built.len();
+
+ if let Some(&CommandOrAlias::Alias(ref points_to)) = group.commands.get(&built) {
+ built = points_to.to_owned();
+ }
+
+ let to_check = if let Some(ref prefix) = group.prefix {
+ if built.starts_with(prefix) && command_length > prefix.len() + 1 {
+ built[(prefix.len() + 1)..].to_owned()
+ } else {
+ continue;
+ }
+ } else {
+ built.clone()
+ };
+
+ if let Some(&CommandOrAlias::Command(ref command)) = group.commands.get(&to_check) {
+ let before = self.before.clone();
+ let command = command.clone();
+ let after = self.after.clone();
+ let groups = self.groups.clone();
+
+ let args = {
+ let content = message.content[position..].trim();
+
+ if command.use_quotes {
+ utils::parse_quotes(&content[command_length..])
+ } else {
+ content[command_length..]
+ .split_whitespace()
+ .map(|arg| arg.to_owned())
+ .collect::<Vec<String>>()
+ }
+ };
+
+ if let Some(error) = self.should_fail(&mut context, &message, &command, args.len(), &to_check, &built) {
+ if let Some(ref handler) = self.dispatch_error_handler {
+ handler(context, message, error);
+ }
+ return;
+ }
+
+ tokio_handle.spawn_fn(move || {
+ if let Some(before) = before {
+ if !(before)(&mut context, &message, &built) {
+ return Ok(());
+ }
+ }
+
+ let result = match command.exec {
+ CommandType::StringResponse(ref x) => {
+ let _ = message.channel_id.say(x);
+
+ Ok(())
+ },
+ CommandType::Basic(ref x) => {
+ (x)(&mut context, &message, args)
+ },
+ CommandType::WithCommands(ref x) => {
+ (x)(&mut context, &message, groups, &args)
+ }
+ };
+
+ if let Some(after) = after {
+ (after)(&mut context, &message, &built, result);
+ }
+
+ Ok(())
+ });
+
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ #[cfg(feature="builtin_framework")]
+ fn update_current_user(&mut self, user_id: UserId, is_bot: bool) {
self.user_info = (user_id.0, is_bot);
}
-}
+
+ #[cfg(feature="builtin_framework")]
+ fn initialized(&self) -> bool {
+ self.initialized
+ }
+} \ No newline at end of file
diff --git a/src/model/channel/message.rs b/src/model/channel/message.rs
index e1eccf0..372c3de 100644
--- a/src/model/channel/message.rs
+++ b/src/model/channel/message.rs
@@ -88,8 +88,9 @@ impl Message {
/// # let mut client = Client::new("token", Handler);
/// #
/// use serenity::model::Channel;
+ /// use serenity::framework::BuiltinFramework;
///
- /// client.with_framework(|f| f
+ /// client.with_framework(BuiltinFramework::new()
/// .configure(|c| c.prefix("~"))
/// .command("channelname", |c| c.exec(channel_name)));
///