summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJokler <jokler.contact@gmail.com>2017-10-09 01:56:04 +0200
committerJokler <jokler.contact@gmail.com>2017-10-11 15:41:32 +0200
commitf7f86cf06de62598ed635b154c45cdc8fe4e19da (patch)
tree8545fe9a45fd61380b9131d0b2f143b6e9500222
parent735f59e3421d9cd9aa908318880467e93af2d788 (diff)
downloadfrippy-f7f86cf06de62598ed635b154c45cdc8fe4e19da.tar.gz
frippy-f7f86cf06de62598ed635b154c45cdc8fe4e19da.zip
Add command functionality
-rw-r--r--Cargo.toml2
-rw-r--r--src/lib.rs78
-rw-r--r--src/plugin.rs2
-rw-r--r--src/plugins/currency.rs103
-rw-r--r--src/plugins/emoji.rs20
5 files changed, 154 insertions, 51 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 621b681..21af580 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/src/lib.rs b/src/lib.rs
index b0c1615..4cb6c44 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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)]