aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib.rs
diff options
context:
space:
mode:
authorJokler <jokler.contact@gmail.com>2017-10-27 15:39:06 +0200
committerJokler <jokler.contact@gmail.com>2017-10-27 15:39:06 +0200
commit0139861d1e41a765b6ffde7cae37c1e16f9c053c (patch)
tree22d6f26b998edeb06e01ad80ada2fd92ff4b4fab /src/lib.rs
parent4c6f2f088521cf0876b67f21a25e524983b7ada7 (diff)
downloadfrippy-0139861d1e41a765b6ffde7cae37c1e16f9c053c.tar.gz
frippy-0139861d1e41a765b6ffde7cae37c1e16f9c053c.zip
Refactor plugin management
ThreadedPlugins should take care of anything Plugin related now.
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs150
1 files changed, 16 insertions, 134 deletions
diff --git a/src/lib.rs b/src/lib.rs
index da36d91..55b121e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -24,29 +24,17 @@ extern crate glob;
mod plugin;
mod plugins;
-use std::thread::spawn;
-use std::sync::{Arc, Mutex};
-use glob::glob;
+use std::sync::Arc;
use irc::client::prelude::*;
-use irc::proto::Command::PRIVMSG;
use irc::error::Error as IrcError;
use tokio_core::reactor::Core;
use futures::future;
+use glob::glob;
use plugin::*;
-// Lock the mutex and ignore if it is poisoned
-macro_rules! lock_plugin {
- ($e:expr) => {
- match $e.lock() {
- Ok(plugin) => plugin,
- Err(poisoned) => poisoned.into_inner(),
- }
- }
-}
-
/// Runs the bot
///
/// # Remarks
@@ -76,18 +64,10 @@ pub fn run() {
}
// The list of plugins in use
- let plugins: Vec<Arc<Mutex<Plugin>>> =
- vec![Arc::new(Mutex::new(plugins::emoji::Emoji::new())),
- Arc::new(Mutex::new(plugins::currency::Currency::new()))];
-
- // We need the plugins' names to make sure the user gets a response
- // if they use an incorrect plugin name
- let plugin_names: Vec<String> = plugins
- .iter()
- .map(|p| lock_plugin!(p).name().to_lowercase())
- .collect();
-
- info!("Plugins loaded: {}", plugin_names.join(", "));
+ let mut plugins = ThreadedPlugins::new();
+ plugins.add(plugins::emoji::Emoji::new());
+ plugins.add(plugins::currency::Currency::new());
+ info!("Plugins loaded: {}", plugins);
// Create an event loop to run the connections on.
let mut reactor = Core::new().unwrap();
@@ -110,13 +90,12 @@ pub fn run() {
Err(e) => error!("Failed to identify: {}", e),
};
- // TODO Duplicate clone...
+ // TODO Verify if we actually need to clone plugins twice
let plugins = plugins.clone();
- let plugin_names = plugin_names.clone();
let task = server
.stream()
- .for_each(move |message| process_msg(&server, &plugin_names, plugins.clone(), message))
+ .for_each(move |message| process_msg(&server, plugins.clone(), message))
.map_err(|e| error!("Failed to process message: {}", e));
reactor.handle().spawn(task);
@@ -127,8 +106,7 @@ pub fn run() {
}
fn process_msg(server: &IrcServer,
- plugin_names: &[String],
- plugins: Vec<Arc<Mutex<Plugin>>>,
+ mut plugins: ThreadedPlugins,
message: Message)
-> Result<(), IrcError> {
@@ -138,118 +116,22 @@ fn process_msg(server: &IrcServer,
}
}
- let message = Arc::new(message);
// Check for possible command and save the result for later
- let command = get_command(&server.current_nickname().to_lowercase(), &message);
+ let command = PluginCommand::from(&server.current_nickname().to_lowercase(), &message);
- // Check if the first token of the command is valid
- if let Some(ref c) = command {
- if c.tokens.is_empty() {
- let help = format!("Use \"{} help\" to get help", server.current_nickname());
- server.send_notice(&c.source, &help)?;
-
- } else if "help" == &c.tokens[0].to_lowercase() {
- send_help_message(server, c)?;
-
- } else if !plugin_names.contains(&c.tokens[0].to_lowercase()) {
-
- let help = format!("\"{} {}\" is not a command, \
- try \"{0} help\" instead.",
- server.current_nickname(),
- c.tokens[0]);
+ let message = Arc::new(message);
+ plugins.execute_plugins(server, message);
- server.send_notice(&c.source, &help)?;
+ // If the message contained a command, handle it
+ if let Some(command) = command {
+ if let Err(e) = plugins.handle_command(server, command) {
+ error!("Failed to handle command: {}", e);
}
}
- for plugin in plugins {
- // Send the message to the plugin if the plugin needs it
- if lock_plugin!(plugin).is_allowed(server, &message) {
-
- // Clone everything before the move
- // The server uses an Arc internally too
- let plugin = Arc::clone(&plugin);
- let message = Arc::clone(&message);
- let server = server.clone();
-
- // Execute the plugin in another thread
- spawn(move || {
- if let Err(e) = lock_plugin!(plugin).execute(&server, &message) {
- let name = lock_plugin!(plugin).name().to_string();
- error!("Error in {} - {}", name, e);
- };
- });
- }
-
- // Check if the command is for this plugin
- if let Some(mut c) = command.clone() {
-
- // Skip empty commands
- if c.tokens.is_empty() {
- continue;
- }
-
- if lock_plugin!(plugin).name().to_lowercase() == c.tokens[0].to_lowercase() {
-
- // The first token contains the name of the plugin
- let name = c.tokens.remove(0);
-
- // Clone the server for the move - it uses an Arc internally
- let server = server.clone();
- spawn(move || {
- if let Err(e) = lock_plugin!(plugin).command(&server, c) {
- error!("Error in {} - {}", name, e);
- };
- });
- }
- }
- }
Ok(())
}
-fn send_help_message(server: &IrcServer, command: &PluginCommand) -> Result<(), IrcError> {
- server.send_notice(&command.source, "Help has not been added yet.")
-}
-
-fn get_command(nick: &str, message: &Message) -> Option<PluginCommand> {
-
- // Get the actual message out of PRIVMSG
- if let PRIVMSG(_, ref content) = message.command {
-
- // Split content by spaces and filter empty tokens
- let mut tokens: Vec<String> = content.split(' ').map(ToOwned::to_owned).collect();
-
- // Commands start with our name
- if tokens[0].to_lowercase().starts_with(nick) {
-
- // Remove the bot's name from the first token
- tokens[0].drain(..nick.len());
-
- // We assume that only ':' and ',' are used as suffixes on IRC
- // If there are any other chars we assume that it is not ment for the bot
- tokens[0] = tokens[0]
- .chars()
- .filter(|&c| !":,".contains(c))
- .collect();
- if !tokens[0].is_empty() {
- return None;
- }
-
- // The first token contained the name of the bot
- tokens.remove(0);
-
- Some(PluginCommand {
- source: message.source_nickname().unwrap().to_string(),
- target: message.response_target().unwrap().to_string(),
- tokens: tokens,
- })
- } else {
- None
- }
- } else {
- None
- }
-}
#[cfg(test)]
mod tests {}