diff --git a/src/main.rs b/src/main.rs index d6aca58..b325150 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,10 +5,11 @@ extern crate regex; #[macro_use] extern crate lazy_static; use std::io::Read; -use irc::client::prelude::*; +use std::time::{Instant}; use hyper::{Client}; -use rustc_serialize::json::{self}; +use irc::client::prelude::*; use regex::Regex; +use rustc_serialize::json::{self}; static WEATHER_API_BASE: &'static str = "http://api.wunderground.com/api/"; @@ -21,7 +22,6 @@ fn main() { let mentions_regex = Regex::new(&format!("({}(:|,) )(.+)$", my_nick)).unwrap(); for message in server.iter() { let message = message.unwrap(); - //println!("Received message: {}", message); match message.command { Command::PRIVMSG(ref target, ref msg) => handle_privmsg(target, msg, &message, &mentions_regex, &server), _ => (), @@ -30,53 +30,84 @@ fn main() { } fn handle_privmsg(target: &String, message_body: &String, message_obj: &Message, mentions_regex: &Regex, server: &IrcServer) { + let now = Instant::now(); println!("Received message in {} from {}: {}", target, message_obj.source_nickname().unwrap(), message_body); let source_nick = message_obj.source_nickname().unwrap(); let mut inner_message = String::new(); match mentions_regex.captures(message_body) { Some(capture) => match capture.at(3) { - Some(inner_message_match) => {inner_message = String::from(inner_message_match); println!("mentioned_message: {}", inner_message)}, + Some(inner_message_match) => inner_message = String::from(inner_message_match), _ => (), }, _ => (), } - println!("mentioned_message: {}", inner_message); - if inner_message == String::from("test") { - server.send_privmsg(target, &format!("{}: Hello!", source_nick)).unwrap(); - } else if inner_message.starts_with("weather") { - // Weather - lazy_static! {static ref WEATHER_REGEX: Regex = Regex::new("(weather )(.+), (\\w+)$").unwrap(); } - match server.config().options { - None => println!("Options not configured!"), - Some(ref options) => match options.get("wunderground_api_key") { - None => println!("wunderground_api_key not configured!"), - Some(api_key) => { - let mut location_city = String::new(); - let mut location_area = String::new(); - match WEATHER_REGEX.captures(&inner_message) { - Some(capture) => {match capture.at(2) { - Some(city_match) => location_city = String::from(city_match), - None => (), - }; - match capture.at(3) { - Some(area_match) => location_area = String::from(area_match), - None => (), - }; - server.send_privmsg(target, &format!("{}: {}", source_nick, &test_get_weather(api_key, &location_city, &location_area))).unwrap(); - }, - None => (), - } + // This code only triggers if the bot is mentioned. + if !inner_message.is_empty() { + println!("Mentioned message inner message: {}", inner_message); - }, + if inner_message == String::from("test") { + server.send_privmsg(target, &format!("{}: Hello!", source_nick)).unwrap(); + } else if inner_message.starts_with("weather") { + // Weather regular expressions + lazy_static! { static ref WEATHER_REGEX: Regex = Regex::new("(weather )(.+), (\\w+)$").unwrap(); } + lazy_static! { static ref WEATHER_LOCID_REGEX: Regex = Regex::new("(weather )(\\w+):(\\w+)$").unwrap(); } + + // Make sure necessary options are configured. + match server.config().options { + None => println!("Options not configured!"), + Some(ref options) => match options.get("wunderground_api_key") { + None => println!("wunderground_api_key not configured!"), + Some(api_key) => { + // First try to match using WEATHER_REGEX, in the form of weather City, ST or City, Country + let mut location_city = String::new(); + let mut location_area = String::new(); + match WEATHER_REGEX.captures(&inner_message) { + Some(capture) => { + match capture.at(2) { + Some(city_match) => location_city = String::from(city_match), + None => (), + }; + match capture.at(3) { + Some(area_match) => location_area = String::from(area_match), + None => (), + }; + server.send_privmsg(target, &format!("{}: {}", source_nick, &get_weather(api_key, &location_city, &location_area))).unwrap(); + }, + None => { + // Failing this, try to match using WEATHER_LOCID_REGEX, in the form of weather locid:USWA0741 or pws:KCATAHOE2 + let mut locid = String::new(); + let mut locid_type = String::new(); + match WEATHER_LOCID_REGEX.captures(&inner_message) { + Some(capture) => { + match capture.at(2) { + Some(locid_type_match) => locid_type = String::from(locid_type_match), + None => (), + } + match capture.at(3) { + Some(locid_match) => locid = String::from(locid_match), + None => (), + } + server.send_privmsg(target, &format!("{}: {}", source_nick, &get_weather_locid(api_key, &locid_type, &locid))).unwrap(); + }, + None => (), + } + }, + } + + }, + } + } + } else if inner_message.starts_with("bot-quit") { + if server.config().is_owner(source_nick) { + std::process::exit(0); } } - } else if message_body.contains("bot-quit") { - std::process::exit(0); } + println!("Processing message took {} seconds, {} milliseconds", now.elapsed().as_secs(), now.elapsed().subsec_nanos()/1000000); } -fn test_get_weather(api_key: &String, location_city: &String, location_area: &String) -> String { +fn get_weather(api_key: &String, location_city: &String, location_area: &String) -> String { let client = Client::new(); let data_type = "conditions"; let url = &format!("{}{}/{}/q/{}/{}.json", WEATHER_API_BASE, api_key, data_type, location_area, location_city); @@ -106,3 +137,34 @@ fn test_get_weather(api_key: &String, location_city: &String, location_area: &St } reply_message } + +fn get_weather_locid(api_key: &String, locid_type: &String, locid: &String) -> String { + let client = Client::new(); + let data_type = "conditions"; + let url = &format!("{}{}/{}/q/{}:{}.json", WEATHER_API_BASE, api_key, data_type, locid_type, locid); + println!("Attempting to fetch {}", url); + let mut response = match client.get(url).send() { + Ok(response) => response, + Err(_) => panic!("Error fetching JSON!"), + }; + let mut response_body = String::new(); + match response.read_to_string(&mut response_body) { + Ok(_) => (), + Err(_) => panic!("Error reading to buffer"), + }; + let mut reply_message = String::new(); + if let Ok(parsed_response) = json::Json::from_str(&response_body) { + if let Some(ref current_observation) = parsed_response.find("current_observation") { + let ref display_location = current_observation.find("display_location").unwrap(); + let display_location_string = display_location.find("full").unwrap().as_string().unwrap(); + let temperature_string = current_observation.find("temperature_string").unwrap().as_string().unwrap(); + let weather = current_observation.find("weather").unwrap().as_string().unwrap(); + let wind_string = current_observation.find("wind_string").unwrap().as_string().unwrap(); + let humidity = current_observation.find("relative_humidity").unwrap().as_string().unwrap(); + let observation_time = current_observation.find("observation_time").unwrap().as_string().unwrap(); + reply_message = format!("It is {} and {} in {}. Wind: {}, Humidity: {}, {}", + weather, temperature_string, display_location_string, wind_string, humidity, observation_time); + } + } + reply_message +}