From 928a0547d35a8a61f9c69c8c46237bfabc528475 Mon Sep 17 00:00:00 2001 From: Mahesh Asolkar Date: Sun, 20 Apr 2025 15:22:40 -0700 Subject: [PATCH] MPD and weather module --- src/main.rs | 119 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 38 deletions(-) diff --git a/src/main.rs b/src/main.rs index d6b2378..257cf16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use std::str; use std::fmt; +use std::process::{Stdio, Command}; use curl::easy::{Easy, List}; use serde_json::Value; use clap::Parser; @@ -57,53 +58,88 @@ struct AppOptions { // // Application (BarWeather) // +#[derive(Clone)] struct BarWeather { // acts :BarWeatherActions opts :AppOptions, } impl BarWeather { - fn run(self) { - self.check_options(); - self.get_weather(); - } - - fn get_weather(self) { - // Print a web page onto stdout - let mut curl = Easy::new(); - let url_string_1 :String = "https://api.weather.gov/stations/".to_owned(); - let url_string_2 :&str = self.opts.station.as_str(); - let url_string_3 :String = "/observations?limit=1".to_owned(); - - let url_string = url_string_1 + url_string_2 + &url_string_3; - - curl.url(url_string.as_str()).unwrap(); - - let mut list = List::new(); - list.append("User-Agent: Bar Weather (mahesh@heshapps.com)").unwrap(); - curl.http_headers(list).unwrap(); - - curl.write_function(move |data| { - // To debug returned JSON - if self.opts.debug_json { - use std::io::{stdout, Write}; - println!("-----> Start of debug"); - stdout().write_all(data).unwrap(); - println!("-----> End of debug"); - } - - let v: Value = serde_json::from_str(str::from_utf8(data).unwrap()).unwrap(); - let temperature_value :f32 = self.get_current_temperature(v); - let temperature_unit :String = self.get_temperature_unit(); - - println!("{:.2}{}", temperature_value, temperature_unit); - - Ok(data.len()) + // -------------------- + fn run(&self) { + if self.opts.debug_json { + self.debug_msg("Debugging ..."); } - ).unwrap(); - curl.perform().unwrap(); + self.check_options(); + let mut bar_modules = Vec::new(); + + bar_modules.push(self.clone().get_weather()); + bar_modules.push(self.clone().get_music()); + + println!("{}", bar_modules.join(" | ")); } + // -------------------- + fn get_weather(self) -> String { + // Print a web page onto stdout + let mut curl = Easy::new(); + let mut url_string = Vec::new(); + let mut curl_ret = Vec::new(); + + url_string.push("https://api.weather.gov/stations/".to_owned()); + url_string.push(self.opts.station.to_owned()); + url_string.push("/observations?limit=1".to_owned()); + + curl.url(url_string.concat().as_str()).unwrap(); + { + let mut list = List::new(); + list.append("User-Agent: Bar Weather (mahesh@heshapps.com)").unwrap(); + curl.http_headers(list).unwrap(); + + let mut transfer = curl.transfer(); + + transfer.write_function(|data| { + curl_ret.extend_from_slice(data); + Ok(data.len()) + }).unwrap(); + transfer.perform().unwrap(); + } + if self.opts.debug_json { + println!("-----> curl_data - [{}]", std::str::from_utf8(&curl_ret).unwrap()); + } + + let v: Value = serde_json::from_str(str::from_utf8(&curl_ret).unwrap()).unwrap(); + let temperature_value :f32 = self.get_current_temperature(v); + let temperature_unit :String = self.get_temperature_unit(); + + return format!("{:.2}{}", temperature_value, temperature_unit); + } + + // -------------------- + fn get_music(&self) -> String { + // MPD format options here: + // https://manpages.ubuntu.com/manpages/plucky/man1/mpc.1.html + let current_output = Command::new("mpc") + .arg("--format") + .arg("[%artist% - ][%title%]") + .arg("current") + .stdout(Stdio::piped()) + .output() + .unwrap(); + let mut current_stdout = String::from_utf8(current_output.stdout).unwrap(); + current_stdout.pop(); + let progress_output = Command::new("mpc") + .arg("status") + .arg("%percenttime% %totaltime%") + .stdout(Stdio::piped()) + .output() + .unwrap(); + let mut progress_stdout = String::from_utf8(progress_output.stdout).unwrap(); + progress_stdout.pop(); + return format!("{} [{}]", current_stdout, progress_stdout); + } + + // -------------------- fn check_options(&self) -> bool { let mut all_good = true; @@ -115,6 +151,7 @@ impl BarWeather { return all_good; } + // -------------------- fn get_current_temperature(&self, v: Value) -> f32 { let deg_c :f32 = v["features"][0]["properties"]["temperature"]["value"] .to_string().parse().unwrap(); @@ -123,10 +160,16 @@ impl BarWeather { else { (deg_c * 9.0 / 5.0) + 32.0}; } + // -------------------- fn get_temperature_unit(&self) -> String{ return if self.opts.units == TemperatureUnits::Metric { "°C".to_string() } else { "°F".to_string() }; } + + // -------------------- + fn debug_msg(&self, msg: &str) { + println!("[Debug ] -----> {}", msg); + } } //