summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs107
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 {
+ ''
+ }
}