From ade570b8afa9d3349cd037eb2384fcc1939ccf7d Mon Sep 17 00:00:00 2001 From: Mahesh Asolkar Date: Sat, 10 May 2025 20:39:43 -0700 Subject: [PATCH] Added weather symbols --- Cargo.toml | 1 + src/bar_modules/bar_module_weather.rs | 125 +++++++++++++++++++++++++- src/common/mod.rs | 1 + src/main.rs | 14 ++- 4 files changed, 137 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e534775..535af57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,5 @@ edition = "2021" serde = "1.0.196" serde_json = "1.0.113" curl = "0.4.46" +regex = "1.11.1" clap = { version = "4.5.1", features = ["derive"] } diff --git a/src/bar_modules/bar_module_weather.rs b/src/bar_modules/bar_module_weather.rs index 6566ee1..6aaf607 100644 --- a/src/bar_modules/bar_module_weather.rs +++ b/src/bar_modules/bar_module_weather.rs @@ -1,6 +1,7 @@ use std::str; use curl::easy::{Easy, List}; use serde_json::Value; +use regex::Regex; use crate::common; use crate::bar_modules; @@ -26,7 +27,124 @@ impl UnibarModuleWeather { // -------------------- fn get_temperature_unit(&self) -> String{ return if self.opts.weather_units == common::TemperatureUnits::Metric { "°C".to_string() } - else { "°F".to_string() }; + else { "°F".to_string() }; + } + + // -------------------- + fn get_icon(&self, v: Value) -> String { + // "icon": "https://api.weather.gov/icons/land/night/ovc?size=medium", + let re = Regex::new(r"(\w+)\?size").unwrap(); + let json_val = v["features"][0]["properties"]["icon"].to_string(); + let caps = re.captures(&json_val).unwrap(); + + // println!("{}", caps.get(1).unwrap().as_str()); + return self.get_unicode_symbol(caps.get(1).unwrap().as_str()); + } + + // -------------------- + fn get_unicode_symbol(&self, v: &str) -> String { + match v { + "skc" => { return "☀️".to_string(); } // Fair/clear + "few" => { return "🌥️".to_string(); } // A few clouds + "sct" => { return "🌥️".to_string(); } // Partly cloudy + "bkn" => { return "🌥️".to_string(); } // Mostly cloudy + "ovc" => { return "☁️".to_string(); } // Overcast + "wind_skc" => { return "☀️".to_string(); } // Fair/clear and windy + "wind_few" => { return "🌥️".to_string(); } // A few clouds and windy + "wind_sct" => { return "🌥️".to_string(); } // Partly cloudy and windy + "wind_bkn" => { return "🌥️".to_string(); } // Mostly cloudy and windy + "wind_ovc" => { return "☁️".to_string(); } // Overcast and windy + "snow" => { return "❄️".to_string(); } // Snow + "rain_snow" => { return "🌨️".to_string(); } // Rain/snow + "rain_sleet" => { return "🌨️".to_string(); } // Rain/sleet + "snow_sleet" => { return "🌨️".to_string(); } // Snow/sleet + "fzra" => { return "🌨️".to_string(); } // Freezing rain + "rain_fzra" => { return "🌨️".to_string(); } // Rain/freezing rain + "snow_fzra" => { return "🌨️".to_string(); } // Freezing rain/snow + "sleet" => { return "🌨️".to_string(); } // Sleet + "rain" => { return "🌧️".to_string(); } // Rain + "rain_showers" => { return "🌧️".to_string(); } // Rain showers (high cloud cover) + "rain_showers_hi" => { return "🌧️".to_string(); } // Rain showers (low cloud cover) + "tsra" => { return "⛈️".to_string(); } // Thunderstorm (high cloud cover) + "tsra_sct" => { return "⛈️".to_string(); } // Thunderstorm (medium cloud cover) + "tsra_hi" => { return "⛈️".to_string(); } // Thunderstorm (low cloud cover) + "tornado" => { return "🌪️".to_string(); } // Tornado + "hurricane" => { return "🌬️".to_string(); } // Hurricane conditions + "tropical_storm" => { return "🌬️".to_string(); } // Tropical storm conditions + "dust" => { return "🌫️".to_string(); } // Dust + "smoke" => { return "🌫️".to_string(); } // Smoke + "haze" => { return "🌫️".to_string(); } // Haze + "hot" => { return "🥵".to_string(); } // Hot + "cold" => { return "🧣".to_string(); } // Cold + "blizzard" => { return "🥶".to_string(); } // Blizzard + "fog" => { return "🌫️".to_string(); } // Fog/mist + _ => { return "🌤️".to_string(); } // It is always sunny here + } + } + + // -------------------- + pub fn get_icons(&self) { + // 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/icons".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(); + } + println!("-----> curl_data - [{}]", std::str::from_utf8(&curl_ret).unwrap()); + } + + // -------------------- + pub fn show_icons(&self) { + println!("{} skc Fair/clear", self.get_unicode_symbol("skc")); + println!("{} few A few clouds", self.get_unicode_symbol("few")); + println!("{} sct Partly cloudy", self.get_unicode_symbol("sct")); + println!("{} bkn Mostly cloudy", self.get_unicode_symbol("bkn")); + println!("{} ovc Overcast", self.get_unicode_symbol("ovc")); + println!("{} wind_skc Fair/clear and windy", self.get_unicode_symbol("wind_skc")); + println!("{} wind_few A few clouds and windy", self.get_unicode_symbol("wind_few")); + println!("{} wind_sct Partly cloudy and windy", self.get_unicode_symbol("wind_sct")); + println!("{} wind_bkn Mostly cloudy and windy", self.get_unicode_symbol("wind_bkn")); + println!("{} wind_ovc Overcast and windy", self.get_unicode_symbol("wind_ovc")); + println!("{} snow Snow", self.get_unicode_symbol("snow")); + println!("{} rain_snow Rain/snow", self.get_unicode_symbol("rain_snow")); + println!("{} rain_sleet Rain/sleet", self.get_unicode_symbol("rain_sleet")); + println!("{} snow_sleet Snow/sleet", self.get_unicode_symbol("snow_sleet")); + println!("{} fzra Freezing rain", self.get_unicode_symbol("fzra")); + println!("{} rain_fzra Rain/freezing rain", self.get_unicode_symbol("rain_fzra")); + println!("{} snow_fzra Freezing rain/snow", self.get_unicode_symbol("snow_fzra")); + println!("{} sleet Sleet", self.get_unicode_symbol("sleet")); + println!("{} rain Rain", self.get_unicode_symbol("rain")); + println!("{} rain_showers Rain showers (high cloud cover)", self.get_unicode_symbol("rain_showers")); + println!("{} rain_showers_hi Rain showers (low cloud cover)", self.get_unicode_symbol("rain_showers_hi")); + println!("{} tsra Thunderstorm (high cloud cover)", self.get_unicode_symbol("tsra")); + println!("{} tsra_sct Thunderstorm (medium cloud cover)", self.get_unicode_symbol("tsra_sct")); + println!("{} tsra_hi Thunderstorm (low cloud cover)", self.get_unicode_symbol("tsra_hi")); + println!("{} tornado Tornado", self.get_unicode_symbol("tornado")); + println!("{} hurricane Hurricane conditions", self.get_unicode_symbol("hurricane")); + println!("{} tropical_storm Tropical storm conditions", self.get_unicode_symbol("tropical_storm")); + println!("{} dust Dust", self.get_unicode_symbol("dust")); + println!("{} smoke Smoke", self.get_unicode_symbol("smoke")); + println!("{} haze Haze", self.get_unicode_symbol("haze")); + println!("{} hot Hot", self.get_unicode_symbol("hot")); + println!("{} cold Cold", self.get_unicode_symbol("cold")); + println!("{} blizzard Blizzard", self.get_unicode_symbol("blizzard")); + println!("{} fog Fog/mist", self.get_unicode_symbol("fog")); + println!("{} _ It is always sunny here", self.get_unicode_symbol("_")); } } @@ -63,9 +181,10 @@ impl bar_modules::BarModuleActions for UnibarModuleWeather { } 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_value :f32 = self.get_current_temperature(v.clone()); let temperature_unit :String = self.get_temperature_unit(); + let temperature_icon :String = self.get_icon(v.clone()); - return format!("{:.2}{}", temperature_value, temperature_unit); + return format!("{} {:.2}{}", temperature_icon, temperature_value, temperature_unit); } } diff --git a/src/common/mod.rs b/src/common/mod.rs index 8a6003d..9a1efbc 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -27,4 +27,5 @@ pub struct AppOptions { pub weather_station: String, pub music_progress: bool, pub debug_json: bool, + pub debug_icons: bool, } diff --git a/src/main.rs b/src/main.rs index 9d2ea08..530e690 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,10 @@ struct CommandlineArgs { /// Show JSON data returned by query #[arg(short = 'D', long)] debug_json: bool, + + /// Show ICON debug information + #[arg(short = 'I', long)] + debug_icons: bool, } // @@ -58,6 +62,13 @@ impl Unibar { parts.push(md.get()); } println!("{}", parts.join(" | ")); + + if self.opts.debug_icons { + let w = bar_modules::bar_module_weather::UnibarModuleWeather { opts: self.opts.clone() }; + w.get_icons(); + w.show_icons(); + } + } // -------------------- @@ -87,7 +98,8 @@ fn main() { else { common::TemperatureUnits::Imperial }, weather_station: cmd_args.weather_station, music_progress: cmd_args.music_progress, - debug_json: cmd_args.debug_json + debug_json: cmd_args.debug_json, + debug_icons: cmd_args.debug_icons }, };