From 6b6d71a9d2c2228f0e22e92cdfdf155ffe96c496 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 7 May 2026 10:48:32 +0200 Subject: [PATCH] Add live weather (#5633) * Add live weather * Just use jq * Add Weather app and make it click target * Simplify * Looks better * Nicer flow * Simplify * Move to using the notification instead of tooltip * No longer needed --- bin/omarchy | 1 + bin/omarchy-weather-icon | 36 ++++++++++++++++++++++++++++ bin/omarchy-weather-status | 26 ++++++++++++++++++++ config/waybar/config.jsonc | 9 ++++++- config/waybar/style.css | 11 +++++++++ default/hypr/bindings/utilities.conf | 1 + default/waybar/weather.sh | 10 ++++++++ migrations/1778139028.sh | 29 ++++++++++++++++++++++ 8 files changed, 122 insertions(+), 1 deletion(-) create mode 100755 bin/omarchy-weather-icon create mode 100755 bin/omarchy-weather-status create mode 100755 default/waybar/weather.sh create mode 100644 migrations/1778139028.sh diff --git a/bin/omarchy b/bin/omarchy index ad743ce7..29b7cfb4 100755 --- a/bin/omarchy +++ b/bin/omarchy @@ -69,6 +69,7 @@ GROUP_DESCRIPTIONS[tz]="Timezone selection" GROUP_DESCRIPTIONS[update]="Omarchy and system updates" GROUP_DESCRIPTIONS[version]="Version and channel information" GROUP_DESCRIPTIONS[voxtype]="Voxtype dictation" +GROUP_DESCRIPTIONS[weather]="Weather status" GROUP_DESCRIPTIONS[webapp]="Web app launchers" GROUP_DESCRIPTIONS[wifi]="Wi-Fi helpers" GROUP_DESCRIPTIONS[windows]="Windows VM management" diff --git a/bin/omarchy-weather-icon b/bin/omarchy-weather-icon new file mode 100755 index 00000000..072af706 --- /dev/null +++ b/bin/omarchy-weather-icon @@ -0,0 +1,36 @@ +#!/bin/bash + +# omarchy:summary=Returns a weather condition icon, adjusted for live sunrise and sunset. + +weather_data=$(curl -fsS --max-time 3 "https://wttr.in?format=j1" 2>/dev/null | jq -er '[.current_condition[0].weatherCode, .weather[0].astronomy[0].sunrise, .weather[0].astronomy[0].sunset] | select(all(. != null and . != "")) | @tsv' 2>/dev/null) || exit 1 + +IFS=$'\t' read -r weather_code sunrise sunset <<< "$weather_data" +if [[ ! $weather_code =~ ^[0-9]+$ || ! $sunrise =~ ^[0-9]{1,2}:[0-9]{2}\ [AP]M$ || ! $sunset =~ ^[0-9]{1,2}:[0-9]{2}\ [AP]M$ ]]; then + exit 1 +fi + +now_epoch=$(date +%s) +sunrise_epoch=$(date -d "today $sunrise" +%s 2>/dev/null || echo 0) +sunset_epoch=$(date -d "today $sunset" +%s 2>/dev/null || echo 0) + +if (( sunrise_epoch > 0 && sunset_epoch > 0 && (now_epoch < sunrise_epoch || now_epoch >= sunset_epoch) )); then + night=true +else + night=false +fi + +case $weather_code in + 113) [[ $night == "true" ]] && icon="" || icon="" ;; + 116) [[ $night == "true" ]] && icon="" || icon="" ;; + 119|122) icon="" ;; + 143|248|260) icon="" ;; + 176|263|266|293|296|353) [[ $night == "true" ]] && icon="" || icon="" ;; + 179|227|230|323|326|368) [[ $night == "true" ]] && icon="" || icon="" ;; + 182|185|281|284|311|314|317|320|350|362|365|374|377) icon="" ;; + 200|386|389|392|395) icon="" ;; + 299|302|305|308|356|359) icon="" ;; + 329|332|335|338|371) icon="" ;; + *) icon="" ;; +esac + +printf '%s\n' "$icon" diff --git a/bin/omarchy-weather-status b/bin/omarchy-weather-status new file mode 100755 index 00000000..126d6582 --- /dev/null +++ b/bin/omarchy-weather-status @@ -0,0 +1,26 @@ +#!/bin/bash + +# omarchy:summary=Returns a formatted weather status string with temperature and wind speed. + +weather=$(curl -fsS --max-time 4 "https://wttr.in?format=%l|%t|%w" 2>/dev/null | tr -d '\n') + +if [[ -z $weather ]]; then + echo "Weather unavailable" + exit 1 +fi + +IFS='|' read -r place temperature wind <<< "$weather" +place=${place%%,*} +place=${place^} +format_temperature() { + local celsius=${1#+} + celsius=${celsius//°/} + celsius=${celsius%C} + + echo "${celsius}°c / $((celsius * 9 / 5 + 32))°f" +} + +temperature=$(format_temperature "$temperature") +wind=${wind//km\// km/} + +echo "$(omarchy-weather-icon) $place · Temperature $temperature · Wind $wind" diff --git a/config/waybar/config.jsonc b/config/waybar/config.jsonc index cbf211c3..61a11eca 100644 --- a/config/waybar/config.jsonc +++ b/config/waybar/config.jsonc @@ -5,7 +5,7 @@ "spacing": 0, "height": 26, "modules-left": ["custom/omarchy", "hyprland/workspaces"], - "modules-center": ["clock", "custom/update", "custom/voxtype", "custom/screenrecording-indicator", "custom/idle-indicator", "custom/notification-silencing-indicator"], + "modules-center": ["clock", "custom/weather", "custom/update", "custom/voxtype", "custom/screenrecording-indicator", "custom/idle-indicator", "custom/notification-silencing-indicator"], "modules-right": [ "group/tray-expander", "bluetooth", @@ -66,6 +66,13 @@ "tooltip": false, "on-click-right": "omarchy-launch-floating-terminal-with-presentation omarchy-tz-select" }, + "custom/weather": { + "exec": "$OMARCHY_PATH/default/waybar/weather.sh", + "return-type": "json", + "interval": 600, + "tooltip": false, + "on-click": "notify-send -u low \"$(omarchy-weather-status)\"" + }, "network": { "format-icons": ["󰤯", "󰤟", "󰤢", "󰤥", "󰤨"], "format": "{icon}", diff --git a/config/waybar/style.css b/config/waybar/style.css index 4bbf0ddb..63302efa 100644 --- a/config/waybar/style.css +++ b/config/waybar/style.css @@ -67,6 +67,17 @@ tooltip { margin-left: 8.75px; } +#custom-weather { + margin-left: 7.5px; + margin-right: 7.5px; +} + +#custom-weather.unavailable { + min-width: 0; + margin: 0; + padding: 0; +} + .hidden { opacity: 0; } diff --git a/default/hypr/bindings/utilities.conf b/default/hypr/bindings/utilities.conf index 083a4c91..c152f884 100644 --- a/default/hypr/bindings/utilities.conf +++ b/default/hypr/bindings/utilities.conf @@ -49,6 +49,7 @@ bindd = SUPER CTRL, R, Transcode, exec, omarchy-menu transcode # Waybar-less information bindd = SUPER CTRL ALT, T, Show time, exec, notify-send -u low " $(date +"%A %H:%M · %d %B %Y · Week %V")" bindd = SUPER CTRL ALT, B, Show battery remaining, exec, notify-send -u low "$(omarchy-battery-status)" +bindd = SUPER CTRL ALT, W, Show weather, exec, notify-send -u low "$(omarchy-weather-status)" # Control panels bindd = SUPER CTRL, A, Audio controls, exec, omarchy-launch-audio diff --git a/default/waybar/weather.sh b/default/waybar/weather.sh new file mode 100755 index 00000000..02e7bc2b --- /dev/null +++ b/default/waybar/weather.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +icon=$(omarchy-weather-icon 2>/dev/null) + +if [[ -n $icon ]]; then + icon=$(printf '%s' "$icon" | sed 's/["\\]/\\&/g') + printf '{"text":"%s"}\n' "$icon" +else + printf '{"text":"","class":"unavailable"}\n' +fi diff --git a/migrations/1778139028.sh b/migrations/1778139028.sh new file mode 100644 index 00000000..e5728ced --- /dev/null +++ b/migrations/1778139028.sh @@ -0,0 +1,29 @@ +echo "Add weather widget to Waybar" + +WAYBAR_CONFIG="$HOME/.config/waybar/config.jsonc" +WAYBAR_STYLE="$HOME/.config/waybar/style.css" + +if [[ -f $WAYBAR_CONFIG ]]; then + if ! grep -q '"custom/weather"' "$WAYBAR_CONFIG"; then + sed -i 's/"modules-center": \["clock",/"modules-center": ["clock", "custom\/weather",/' "$WAYBAR_CONFIG" + sed -i '/"network": {/i\ "custom/weather": {\n "exec": "$OMARCHY_PATH/default/waybar/weather.sh",\n "return-type": "json",\n "interval": 600,\n "tooltip": false,\n "on-click": "notify-send -u low \\"$(omarchy-weather-status)\\""\n },' "$WAYBAR_CONFIG" + fi +fi + +if [[ -f $WAYBAR_STYLE ]] && ! grep -q '#custom-weather' "$WAYBAR_STYLE"; then + cat >>"$WAYBAR_STYLE" <<'EOF' + +#custom-weather { + margin-left: 7.5px; + margin-right: 7.5px; +} + +#custom-weather.unavailable { + min-width: 0; + margin: 0; + padding: 0; +} +EOF +fi + +omarchy-restart-waybar