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() { 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> { let resp = reqwest::blocking::get(endpoint)?.text()?; Ok(serde_json::from_str(&resp)?) } fn parse_current(response: Value) -> Option { 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 { 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 { '' } }