aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/currency.rs
diff options
context:
space:
mode:
authorJokler <jokler.contact@gmail.com>2017-10-06 01:14:39 +0200
committerJokler <jokler.contact@gmail.com>2017-10-11 15:41:32 +0200
commit76a5131bd9e8acd32ea8c382c0c608e57022512e (patch)
tree5e3064cdfc0ef731424cc98755031447871e6da5 /src/plugins/currency.rs
parent3d22bb82e6bf9851b361346a17d36aaffdf0fb98 (diff)
downloadfrippy-76a5131bd9e8acd32ea8c382c0c608e57022512e.tar.gz
frippy-76a5131bd9e8acd32ea8c382c0c608e57022512e.zip
Add fixed currency plugin
Diffstat (limited to 'src/plugins/currency.rs')
-rw-r--r--src/plugins/currency.rs165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/plugins/currency.rs b/src/plugins/currency.rs
new file mode 100644
index 0000000..71b943a
--- /dev/null
+++ b/src/plugins/currency.rs
@@ -0,0 +1,165 @@
+extern crate reqwest;
+extern crate serde;
+extern crate serde_json;
+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);
+
+lazy_static! {
+ static ref RE: Regex = Regex::new(r"([0-9]+) ([A-Za-z]+) (?i)(to) ([A-Za-z]+)").unwrap();
+}
+
+struct ConvertionRequest<'a> {
+ value: f64,
+ source: &'a str,
+ target: &'a str,
+}
+
+macro_rules! try_option {
+ ($e:expr) => {
+ match $e {
+ Some(v) => v,
+ None => { return None; }
+ }
+ }
+}
+
+impl<'a> ConvertionRequest<'a> {
+ fn send(&self) -> Option<f64> {
+
+ let response = Client::new()
+ .get("https://api.fixer.io/latest")
+ .form(&[("base", self.source)])
+ .header(Connection::close())
+ .send();
+
+ match response {
+ Ok(mut response) => {
+ let mut body = String::new();
+ try_option!(response.read_to_string(&mut body).ok());
+ println!("{}", body);
+
+ let convertion_rates: Result<Value, _> = serde_json::from_str(&body);
+ match convertion_rates {
+ Ok(convertion_rates) => {
+
+ let rates: &Value = try_option!(convertion_rates.get("rates"));
+ let target_rate: &Value = try_option!(rates.get(self.target.to_uppercase()));
+ Some(self.value * try_option!(target_rate.as_f64()))
+ }
+ Err(_) => None,
+ }
+ }
+ Err(_) => None,
+ }
+ }
+}
+
+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
+ })
+ }
+ None => None,
+ }
+ }
+
+ fn convert(&self,
+ server: &IrcServer,
+ _: &Message,
+ target: &str,
+ msg: &str)
+ -> Result<(), IrcError> {
+ let request = match self.grep_request(msg) {
+ Some(request) => request,
+ None => {
+ return Ok(());
+ }
+ };
+
+ match request.send() {
+ Some(response) => {
+ server.send_privmsg(target,
+ &*format!("{} {} => {:.4} {}",
+ request.value,
+ request.source,
+ response / 1.00000000,
+ request.target))
+ }
+ None => server.send_privmsg(target, "Error while converting given currency"),
+ }
+ }
+}
+
+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 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(()),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use tests::{make_server, get_server_value};
+
+ use irc::client::prelude::*;
+
+ use plugin::Plugin;
+ use regex::Regex;
+ use super::Currency;
+
+ #[test]
+ fn test_big_jpy_to_eur() {
+ let server = make_server("PRIVMSG test :5000000 JPY to EUR\r\n");
+ let mut plugin = Currency::new();
+
+ for message in server.iter() {
+ let message = message.unwrap();
+ assert!(plugin.is_allowed(&server, &message));
+ assert!(plugin.execute(&server, &message).is_ok());
+ }
+
+ let regex = Regex::new(r"=> ([0-9]{2})").unwrap();
+ let msg = get_server_value(&server);
+ let captures = regex.captures(&*msg).unwrap();
+ assert!(captures.at(0).is_some());
+
+ let result = captures
+ .at(0)
+ .unwrap()
+ .split_whitespace()
+ .last()
+ .unwrap()
+ .parse::<i32>();
+ assert!(result.is_ok());
+
+ let value = result.unwrap();
+ assert!(value > 10 && value < 100);
+ }
+}