diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 107 |
1 files changed, 106 insertions, 1 deletions
diff --git a/src/main.rs b/src/main.rs index e7a11a9..cf4dc66 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,108 @@ +use serde_json::Value; +use std::error::Error; +use std::fs; +use std::path::Path; + +const CONFIG_PATH: &str = "/home/adam/.config/forecast"; + +#[derive(Debug)] +struct WeatherInfo { + icon: char, + temp: i32, +} + fn main() { - println!("Hello, world!"); + let (current_endpoint, forecast_endpoint) = init(); + let current_data = req_weather(current_endpoint).unwrap(); + let forecast_data = req_weather(forecast_endpoint).unwrap(); + + let current_weather = parse_current(current_data).unwrap(); + let forecast_weather = parse_forecast(forecast_data).unwrap(); + let trend = get_trend(current_weather.temp, forecast_weather.temp); + + println!( + " {} {}°C {} {} {}°C ", + current_weather.icon, + current_weather.temp, + trend, + forecast_weather.icon, + forecast_weather.temp + ); +} + +fn init() -> (String, String) { + let city_id = read_config_file("city_id"); + let api_key = read_config_file("api_key"); + + let current_endpoint: String = format!( + "https://api.openweathermap.org/data/2.5/weather?id={}&appid={}&units=metric", + city_id, api_key + ); + let forecast_endpoint: String = format!( + "https://api.openweathermap.org/data/2.5/forecast?id={}&appid={}&units=metric&cnt=1", + city_id, api_key + ); + (current_endpoint, forecast_endpoint) +} + +fn read_config_file(file_name: &str) -> String { + let path = Path::new(CONFIG_PATH).join(file_name); + fs::read_to_string(path.to_string_lossy().to_string()).unwrap() +} + +fn req_weather(endpoint: String) -> Result<Value, Box<dyn Error>> { + let resp = reqwest::blocking::get(endpoint)?.text()?; + Ok(serde_json::from_str(&resp)?) +} + +fn parse_current(response: Value) -> Option<WeatherInfo> { + let icon_code = response["weather"][0]["icon"].as_str()?; + let temperature = response["main"]["temp"].as_f64()?.round(); + + Some(WeatherInfo { + icon: get_icon(icon_code), + temp: temperature as i32, + }) +} + +fn parse_forecast(response: Value) -> Option<WeatherInfo> { + let icon_code = response["list"][0]["weather"][0]["icon"].as_str()?; + let temperature = response["list"][0]["main"]["temp"].as_f64()?.round(); + + Some(WeatherInfo { + icon: get_icon(icon_code), + temp: temperature as i32, + }) +} + +fn get_icon(code: &str) -> char { + match code { + "01d" => '', // Clear sky - day + "01n" => '', // Clear sky - night + "02d" => '', // Few clouds (11-25%) - day + "02n" => '', // Few clouds (11-25%) - night + "03d" | "03n" => '', // Scattered clouds (25-50%) - day/night + "04d" | "04n" => '', // Broken / Overcast clouds (51-84% / 85-100%) - day/night + "09d" => '', // Shower rain - day + "09n" => '', // Shower rain - night + "10d" => '', // Moderate / heavy rain - day + "10n" => '', // Moderate / heavy rain - night + "11d" => '', // Thunderstorm - day + "11n" => '', // Thunderstorm - night + "13d" => '', // Snow - day + "13n" => '', // Snow - night + "50d" => '', // Fog - day + "50n" => '', // Fog - night + _ => '', // ?? + } +} + +fn get_trend(t1: i32, t2: i32) -> char { + if t1 < t2 { + '' + } else if t1 > t2 { + '' + } else { + '' + } } |