diff options
| author | Jokler <jokler.contact@gmail.com> | 2017-10-09 01:56:04 +0200 |
|---|---|---|
| committer | Jokler <jokler.contact@gmail.com> | 2017-10-11 15:41:32 +0200 |
| commit | f7f86cf06de62598ed635b154c45cdc8fe4e19da (patch) | |
| tree | 8545fe9a45fd61380b9131d0b2f143b6e9500222 | |
| parent | 735f59e3421d9cd9aa908318880467e93af2d788 (diff) | |
| download | frippy-f7f86cf06de62598ed635b154c45cdc8fe4e19da.tar.gz frippy-f7f86cf06de62598ed635b154c45cdc8fe4e19da.zip | |
Add command functionality
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/lib.rs | 78 | ||||
| -rw-r--r-- | src/plugin.rs | 2 | ||||
| -rw-r--r-- | src/plugins/currency.rs | 103 | ||||
| -rw-r--r-- | src/plugins/emoji.rs | 20 |
5 files changed, 154 insertions, 51 deletions
@@ -16,10 +16,10 @@ path = "src/lib.rs" [[bin]] name = "frippy" path = "bin/main.rs" +doc = false [dependencies] irc = "0.12.5" -lazy_static = "0.2.9" reqwest = "0.8.0" regex = "0.2.2" serde = "1.0.15" @@ -2,8 +2,6 @@ #![cfg_attr(feature="clippy", plugin(clippy))] extern crate irc; -#[macro_use] -extern crate lazy_static; #[macro_use] mod plugin; @@ -12,9 +10,18 @@ mod plugins; use std::thread::spawn; use std::sync::{Arc, Mutex}; use irc::client::prelude::*; +use irc::proto::Command::PRIVMSG; +use irc::error::Error as IrcError; use plugin::Plugin; +#[derive(Clone, Debug)] +pub struct PluginCommand { + source: String, + target: String, + tokens: Vec<String>, +} + pub fn run() { let server = IrcServer::new("config.toml").unwrap(); server.identify().unwrap(); @@ -23,13 +30,39 @@ pub fn run() { vec![Arc::new(Mutex::new(plugins::emoji::Emoji::new())), Arc::new(Mutex::new(plugins::currency::Currency::new()))]; + let plugin_names: Vec<String> = plugins + .iter() + .map(|p| p.lock().unwrap().to_string().to_lowercase()) + .collect(); + server .for_each_incoming(|message| { let message = Arc::new(message); + let command = get_command(&server.current_nickname().to_lowercase(), &message); + + 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).unwrap(); + + } else if "help" == &c.tokens[0].to_lowercase() { + send_help_message(&server, c).unwrap(); + + } 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]); + + server.send_notice(&c.source, &help).unwrap(); + } + } for plugin in plugins.clone() { let server = server.clone(); let message = Arc::clone(&message); + let command = command.clone(); spawn(move || { let mut plugin = match plugin.lock() { @@ -40,12 +73,53 @@ pub fn run() { if plugin.is_allowed(&server, &message) { plugin.execute(&server, &message).unwrap(); } + + if let Some(mut c) = command { + if !c.tokens.is_empty() && + plugin.to_string().to_lowercase() == c.tokens[0].to_lowercase() { + + c.tokens.remove(0); + plugin.command(&server, c).unwrap(); + } + } }); } }) .unwrap(); } +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> { + if let PRIVMSG(_, ref content) = message.command { + let mut tokens: Vec<String> = content + .split(' ') + .filter(|&x| !x.is_empty()) + .map(ToOwned::to_owned) + .collect(); + + if tokens.is_empty() { + return None; + } + + if tokens[0].to_lowercase().starts_with(nick) { + 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 { use irc::client::prelude::*; diff --git a/src/plugin.rs b/src/plugin.rs index fdaad43..62f4fbb 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,10 +1,12 @@ use std::fmt; use irc::client::prelude::*; use irc::error::Error as IrcError; +use PluginCommand; pub trait Plugin: Send + Sync + fmt::Display + fmt::Debug { fn is_allowed(&self, server: &IrcServer, message: &Message) -> bool; fn execute(&mut self, server: &IrcServer, message: &Message) -> Result<(), IrcError>; + fn command(&mut self, server: &IrcServer, command: PluginCommand) -> Result<(), IrcError>; } #[macro_export] diff --git a/src/plugins/currency.rs b/src/plugins/currency.rs index 86ff1da..1766034 100644 --- a/src/plugins/currency.rs +++ b/src/plugins/currency.rs @@ -6,17 +6,14 @@ extern crate regex; use std::io::Read; use irc::client::prelude::*; use irc::error::Error as IrcError; -use self::regex::Regex; use plugin::Plugin; use self::reqwest::Client; use self::reqwest::header::Connection; use self::serde_json::Value; -register_plugin!(Currency); +use PluginCommand; -lazy_static! { - static ref RE: Regex = Regex::new(r"([0-9]+) ([A-Za-z]+) (?i)(to) ([A-Za-z]+)").unwrap(); -} +register_plugin!(Currency); struct ConvertionRequest<'a> { value: f64, @@ -65,61 +62,83 @@ impl<'a> ConvertionRequest<'a> { } impl Currency { - fn grep_request<'a>(&self, msg: &'a str) -> Option<ConvertionRequest<'a>> { - match RE.captures(msg) { - Some(captures) => { - Some(ConvertionRequest { - value: { - let capture = try_option!(captures.get(1)).as_str(); - try_option!(capture.parse().ok()) - }, - source: try_option!(captures.get(2)).as_str(), - target: try_option!(captures.get(4)).as_str(), // 3 is to/TO - }) + fn eval_command<'a>(&self, tokens: &'a [String]) -> Option<ConvertionRequest<'a>> { + let parsed = match tokens[0].parse() { + Ok(v) => v, + Err(_) => { + return None; } - None => None, - } + }; + + Some(ConvertionRequest { + value: parsed, + source: &tokens[1], + target: &tokens[2], + }) } - fn convert(&self, - server: &IrcServer, - _: &Message, - target: &str, - msg: &str) - -> Result<(), IrcError> { - let request = match self.grep_request(msg) { + fn convert(&self, server: &IrcServer, command: PluginCommand) -> Result<(), IrcError> { + let request = match self.eval_command(&command.tokens) { Some(request) => request, None => { - return Ok(()); + return self.invalid_command(server, &command); } }; match request.send() { Some(response) => { - server.send_privmsg(target, - &*format!("{} {} => {:.4} {}", - request.value, - request.source, - response / 1.00000000, - request.target)) + let response = format!("{} {} => {:.4} {}", + request.value, + request.source.to_lowercase(), + response / 1.00000000, + request.target.to_lowercase()); + + server.send_privmsg(&command.target, &response) } - None => server.send_privmsg(target, "Error while converting given currency"), + None => server.send_privmsg(&command.target, "Error while converting given currency"), + } + } + + fn help(&self, server: &IrcServer, command: PluginCommand) -> Result<(), IrcError> { + let usage = format!("usage: {} currency value from_currency to_currency", + server.current_nickname()); + + if let Err(e) = server.send_notice(&command.source, &usage) { + return Err(e); } + server.send_notice(&command.source, "example: 1.5 eur usd") + } + + fn invalid_command(&self, server: &IrcServer, command: &PluginCommand) -> Result<(), IrcError> { + let help = format!("Incorrect value. \ + Send \"{} help currency\" for help.", + server.current_nickname()); + + server.send_notice(&command.source, &help) } } impl Plugin for Currency { - fn is_allowed(&self, _: &IrcServer, message: &Message) -> bool { - match message.command { - Command::PRIVMSG(_, ref msg) => RE.is_match(msg), - _ => false, - } + fn is_allowed(&self, _: &IrcServer, _: &Message) -> bool { + false } - fn execute(&mut self, server: &IrcServer, message: &Message) -> Result<(), IrcError> { - match message.command { - Command::PRIVMSG(ref target, ref msg) => self.convert(server, message, target, msg), - _ => Ok(()), + fn execute(&mut self, _: &IrcServer, _: &Message) -> Result<(), IrcError> { + Ok(()) + } + + fn command(&mut self, server: &IrcServer, command: PluginCommand) -> Result<(), IrcError> { + if command.tokens.is_empty() { + self.invalid_command(server, &command) + + } else if command.tokens[0].to_lowercase() == "help" { + self.help(server, command) + + } else if command.tokens.len() >= 3 { + self.convert(server, command) + + } else { + self.invalid_command(server, &command) } } } diff --git a/src/plugins/emoji.rs b/src/plugins/emoji.rs index 506fcd2..358d965 100644 --- a/src/plugins/emoji.rs +++ b/src/plugins/emoji.rs @@ -1,8 +1,9 @@ +extern crate unicode_names; + use irc::client::prelude::*; use irc::error::Error as IrcError; use plugin::Plugin; - -extern crate unicode_names; +use PluginCommand; register_plugin!(Emoji); @@ -12,10 +13,12 @@ impl Emoji { let mut names: Vec<String> = Vec::new(); for emoji in self.return_emojis(content) { - names.push(match unicode_names::name(emoji) { - Some(v) => format!("{}", v).to_lowercase(), - None => "UNKNOWN".to_string(), - }); + let name = match unicode_names::name(emoji) { + Some(v) => format!("{}", v).to_lowercase(), + None => "UNKNOWN".to_string(), + }; + + names.push(name); } server.send_privmsg(target, &names.join(", ")) @@ -62,6 +65,11 @@ impl Plugin for Emoji { _ => Ok(()), } } + + fn command(&mut self, server: &IrcServer, command: PluginCommand) -> Result<(), IrcError> { + server.send_notice(&command.source, + "This Plugin does not implement any commands.") + } } #[cfg(test)] |
