From: Sondre Wold Date: Sat, 6 Apr 2024 14:52:45 +0000 (+0200) Subject: Add draft X-Git-Url: https://letsjmore.com/?a=commitdiff_plain;h=3a10c9cd41e4a6bf8764937a6291830816255dfa;p=weather_cli.git Add draft --- diff --git a/weather_cli/Cargo.toml b/weather_cli/Cargo.toml new file mode 100644 index 0000000..9a87c45 --- /dev/null +++ b/weather_cli/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "weather_cli" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lazy_static = "1.4.0" +reqwest = { version = "0.10", features = ["blocking", "json"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1.0.114" diff --git a/weather_cli/src/main.rs b/weather_cli/src/main.rs new file mode 100644 index 0000000..767e260 --- /dev/null +++ b/weather_cli/src/main.rs @@ -0,0 +1,119 @@ +use serde::{Deserialize, Serialize}; +use std::env; + +struct Config { + hours: usize, +} + +impl Config { + fn new(args: &[String]) -> Config { + let hours = match args[1].clone().parse() { + Ok(hours) => hours, + Err(error) => panic!( + "Failed to provide a digit for the hours argument: {:?}", + error + ), + }; + Config { hours } + } +} + +struct Location { + lat: String, + lon: String, +} + +#[derive(Debug, Deserialize, Serialize)] +struct LocationResponse { + loc: String, +} + +impl Location { + fn new() -> Location { + let response = match reqwest::blocking::get("https://ipinfo.io") { + Ok(response) => response, + Err(error) => panic!("Failed to fetch current location: {:?}", error), + }; + + let location_response: LocationResponse = match response.json() { + Ok(location_response) => location_response, + Err(error) => panic!("Failed to parse location response: {:?}", error), + }; + let parsed = location_response.loc.split(","); + let collection: Vec<&str> = parsed.collect(); + Location { + lat: String::from(collection[0]), + lon: String::from(collection[1]), + } + } +} + +#[derive(Debug, Deserialize, Serialize)] +struct Detail { + air_temperature: f32, +} + +#[derive(Debug, Deserialize, Serialize)] +struct Details { + details: Detail, +} + +#[derive(Debug, Deserialize, Serialize)] +struct Instant { + instant: Details, +} + +#[derive(Debug, Deserialize, Serialize)] +struct Data { + data: Instant, +} + +#[derive(Debug, Deserialize, Serialize)] +struct Timeseries { + timeseries: Vec, +} + +#[derive(Debug, Deserialize, Serialize)] +struct Properties { + properties: Timeseries, +} + +#[derive(Debug, Deserialize, Serialize)] +struct YrResponse { + properties: Properties, +} + +fn main() { + let args: Vec = env::args().collect(); + let config: Config = Config::new(&args); + let hours: usize = config.hours; + let location: Location = Location::new(); + //println!("Current latitude: {:?}", location.lat); + //println!("Current longitude: {:?}", location.lon); + let req_str = format!( + "https://api.met.no/weatherapi/locationforecast/2.0/compact?lat={}&lon={}", + location.lat, location.lon + ); + let response = match reqwest::blocking::get(&req_str) { + Ok(response) => response, + Err(error) => panic!("Failed to fetch weather data from YR: {:?}", error), + }; + let obj: Properties = match response.json() { + Ok(prop) => prop, + Err(error) => panic!("Failed to parse json: {:?}", error), + }; + let mut temperatures: f32 = 0.0; + for hour in 0..hours { + temperatures = temperatures + + obj.properties.timeseries[hour] + .data + .instant + .details + .air_temperature; + } + let avg = temperatures / hours as f32; + println!( + "Average temperature for the next {} hour(s) is going to be {}", + hours, avg + ); +}