fjordgard

A desktop clock application
Log | Files | Refs | README | LICENSE

commit 86aed9bb1e87e3a532f80b68ced1714e6d4af530
parent 16285c914f21e84bb22f40d95c6ca815171fb1e2
Author: Sylvia Ivory <git@sivory.net>
Date:   Mon, 16 Jun 2025 00:37:27 -0700

Implement CLI to test

Diffstat:
MCargo.lock | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MCargo.toml | 2++
Mcrates/weather/src/lib.rs | 5+++--
Mcrates/weather/src/model.rs | 1+
Msrc/main.rs | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
5 files changed, 152 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -223,6 +223,10 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fjordgard" version = "0.1.0" +dependencies = [ + "fjordgard-weather", + "tokio", +] [[package]] name = "fjordgard-unsplash" @@ -710,6 +714,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -839,6 +853,29 @@ dependencies = [ ] [[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -902,6 +939,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] +name = "redox_syscall" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +dependencies = [ + "bitflags", +] + +[[package]] name = "ref-cast" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1061,6 +1107,12 @@ dependencies = [ ] [[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] name = "security-framework" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1165,6 +1217,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + +[[package]] name = "slab" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1362,7 +1423,9 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", diff --git a/Cargo.toml b/Cargo.toml @@ -10,3 +10,5 @@ version = "0.1.0" edition = "2024" [dependencies] +fjordgard-weather = { version = "0.1.0", path = "crates/weather" } +tokio = { version = "1.45.1", features = ["full"] } diff --git a/crates/weather/src/lib.rs b/crates/weather/src/lib.rs @@ -2,12 +2,13 @@ use std::fmt::Debug; use reqwest::Client; -pub use error::*; +pub use error::Error; +use error::Result; use model::*; use serde::{Serialize, de::DeserializeOwned}; mod error; -mod model; +pub mod model; const USER_AGENT: &str = concat!("fjordgard/", env!("CARGO_PKG_VERSION")); const GEOCODING_API_HOST: &str = "geocoding-api.open-meteo.com"; diff --git a/crates/weather/src/model.rs b/crates/weather/src/model.rs @@ -58,6 +58,7 @@ pub struct Location { #[derive(Deserialize, Debug, Clone)] pub(crate) struct GeocodeResponse { + #[serde(default)] pub(crate) results: Vec<Location>, } diff --git a/src/main.rs b/src/main.rs @@ -1,3 +1,84 @@ -fn main() { - println!("Hello, world!"); +use fjordgard_weather::{ + Error, MeteoClient, + model::{CurrentVariable, ForecastOptions, GeocodeOptions}, +}; + +#[tokio::main] +async fn main() -> Result<(), Error> { + if let Some(location) = std::env::args().nth(1) { + let client = MeteoClient::new(None)?; + + let locations = client + .geocode( + &location, + Some(GeocodeOptions { + count: Some(1), + ..Default::default() + }), + ) + .await?; + + match locations.get(0) { + None => eprintln!("location not found"), + Some(loc) => { + println!( + "{}{}, {} ({}, {})", + loc.name, + loc.admin1 + .as_ref() + .map(|s| format!(", {s}")) + .unwrap_or_default(), + loc.country, + loc.latitude, + loc.longitude + ); + + let forecast = client + .forecast_single( + loc.latitude, + loc.longitude, + Some(ForecastOptions { + current: Some(vec![ + CurrentVariable::Temperature2m, + CurrentVariable::ApparentTemperature, + CurrentVariable::RelativeHumidity2m, + CurrentVariable::WindSpeed10m, + CurrentVariable::WindDirection10m, + ]), + ..Default::default() + }), + ) + .await?; + let current = forecast.current.unwrap().data; + let current_units = forecast.current_units.unwrap(); + + println!( + "It is currently {}{} (feels like {}{}) with {}{} humidity", + current.get(&CurrentVariable::Temperature2m).unwrap(), + current_units.get(&CurrentVariable::Temperature2m).unwrap(), + current.get(&CurrentVariable::ApparentTemperature).unwrap(), + current_units + .get(&CurrentVariable::ApparentTemperature) + .unwrap(), + current.get(&CurrentVariable::RelativeHumidity2m).unwrap(), + current_units + .get(&CurrentVariable::RelativeHumidity2m) + .unwrap(), + ); + println!( + "The wind speed is {}{} pointing {}{}", + current.get(&CurrentVariable::WindSpeed10m).unwrap(), + current_units.get(&CurrentVariable::WindSpeed10m).unwrap(), + current.get(&CurrentVariable::WindDirection10m).unwrap(), + current_units + .get(&CurrentVariable::WindDirection10m) + .unwrap(), + ); + } + } + } else { + eprintln!("location not specified") + } + + Ok(()) }