diff --git a/README.md b/README.md new file mode 100644 index 0000000..e023a21 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# lo mi cabytcini + +ni'o ni'o ti cu me lo mi cabytcini be lo mi cankyralju me'e la zo DWM. + +## gaftercu'a + +.i sfaile fa zoi .py. $HOME/.config/cabytcini/gaftercu'a.toml .py. lo gaftercu'a +be ko'a .i le formato cu: + +```toml +front_url = "https://whatever.omg/path" +weather_url = "https://omg.weather/darksky" +``` + +.i lo zo `front_url` cu eilga terbe'i lo jadycau uensni fi'o benji zo HTTP + +.i lo zo `weather_url` cu eilga terbe'i lo zo JSON fi'o benji zo HTTP + +## pilno + +.i ko ci'erse'a fi'o zoi .ko. + +```console +$ nix-env -if ./cabytcini.nix +``` + +.ko. diff --git a/cabnytcini.nix b/cabytcini.nix similarity index 100% rename from cabnytcini.nix rename to cabytcini.nix diff --git a/src/main.rs b/src/main.rs index c496e8f..c233ae0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod config; mod front; +mod weather; mod xsetroot; use chrono::prelude::*; @@ -14,6 +15,14 @@ use std::{ }; use xsetroot::XSetRoot; +// Name your user agent after your app? +pub static APP_USER_AGENT: &str = concat!( + env!("CARGO_PKG_NAME"), + "/", + env!("CARGO_PKG_VERSION"), + " +https://tulpa.dev/cadey/cabytcini", +); + pub(crate) type MTState = Arc>; fn handle_client(stream: UnixStream, st: MTState) { @@ -62,6 +71,13 @@ fn main() -> std::io::Result<()> { thread::spawn(move || front::update(mtst, cfg)); } + // start weather thread + { + let mtst = mtst.clone(); + let cfg = cfg.clone(); + thread::spawn(move || weather::update(mtst, cfg)); + } + let _ = std::fs::remove_file("/home/cadey/tmp/cabytcini.sock")?; let listener = UnixListener::bind("/home/cadey/tmp/cabytcini.sock")?; for stream in listener.incoming() { @@ -83,6 +99,7 @@ fn main() -> std::io::Result<()> { pub(crate) struct State { msg: String, front: String, + weather: Option, } impl fmt::Display for State { @@ -96,6 +113,7 @@ impl State { State { msg: "".to_string(), front: "".to_string(), + weather: None, } } @@ -113,6 +131,17 @@ impl State { msg.push_str(format!("{} | ", self.front).as_str()); } + match &self.weather { + Some(datni) => msg.push_str(format!( + "{} {} / {} {} | ", + datni.currently.temperature, + datni.currently.summary, + datni.daily.data[0].temperature_high, + datni.daily.data[0].temperature_low + ).as_str()), + None => {} + }; + msg.push_str(format!("{}", now).as_str()); xsr.render(msg); diff --git a/src/weather.rs b/src/weather.rs new file mode 100644 index 0000000..2741767 --- /dev/null +++ b/src/weather.rs @@ -0,0 +1,65 @@ +use crate::{config::Config, MTState}; +use reqwest::blocking::*; +use serde::{Deserialize, Serialize}; +use std::{thread, time}; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Root { + pub currently: Currently, + pub daily: Daily, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Currently { + pub time: i64, + pub summary: String, + pub temperature: f64, + pub apparent_temperature: f64, + pub humidity: f64, + pub icon: String, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Daily { + pub summary: String, + pub icon: String, + pub data: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Daum { + pub time: i64, + pub icon: String, + pub temperature_high: f64, + pub temperature_low: f64, +} + +const UPDATE_FREQUENCY: u64 = 15 * 60; // 15 minutes + +fn get(cfg: &Config) -> reqwest::Result { + let client = Client::builder().user_agent(crate::APP_USER_AGENT).build()?; + let now: Root = client.get(&cfg.weather_url).send()?.json()?; + + Ok(now) +} + +pub(crate) fn update(st: MTState, cfg: Config) { + loop { + match get(&cfg) { + Ok(datni) => { + let mut data = st.lock().unwrap(); + data.weather = Some(datni); + } + Err(why) => { + log::error!("error getting weather from {}: {:?}", &cfg.weather_url, why); + } + } + + let amt = time::Duration::new(UPDATE_FREQUENCY, 0); + thread::sleep(amt); + } +}