#!/bin/sh # Weather forecast with Nerd Font icons # Uses wttr.in weather codes to determine icon url="${WTTRURL:-wttr.in}" weatherreport="${XDG_CACHE_HOME:-$HOME/.cache}/weatherreport" # Get a weather report from 'wttr.in' and save it locally. getforecast() { timeout --signal=1 2s curl -sf "$url/$LOCATION" > "$weatherreport" || exit 1; } # Check if forecast is fresh (less than 30 minutes old) checkforecast() { [ -s "$weatherreport" ] || return 1 last_modified=$(stat -c %Y "$weatherreport" 2>/dev/null) || return 1 now=$(date +%s) age=$((now - last_modified)) [ "$age" -lt 1800 ] # 1800 seconds = 30 minutes } # Get weather icon based on wttr.in output # Weather conditions from line 3 of the report getweathericon() { condition=$(echo "$weatherdata" | sed '3q;d' | tr '[:upper:]' '[:lower:]') case "$condition" in *thunder*rain*|*storm*) echo "󰙾" ;; # lightning_rainy *thunder*|*lightning*) echo "󰖓" ;; # lightning *snow*rain*|*sleet*) echo "󰙿" ;; # snowy_rainy *heavy*snow*) echo "󰼶" ;; # partly_snowy_heavy *snow*) echo "󰖘" ;; # snowy *heavy*rain*|*pour*) echo "󰖖" ;; # pouring *rain*|*drizzle*) echo "󰖗" ;; # rainy *hail*) echo "󰖒" ;; # hail *fog*|*mist*) echo "󰖑" ;; # fog *haz*) echo "󰼰" ;; # hazy *tornado*) echo "󰼸" ;; # tornado *hurricane*) echo "󰢘" ;; # hurricane *wind*) echo "󰖝" ;; # windy *partly*cloud*|*overcast*) echo "󰖕" ;; # partly_cloudy *cloud*) echo "󰖐" ;; # cloudy *sun*|*clear*) echo "󰖙" ;; # sunny *) echo "󰖕" ;; # default: partly_cloudy esac } getprecipchance() { precipdata=$(echo "$weatherdata" | sed '16q;d' | grep -wo "[0-9]*%" 2>/dev/null) if [ -n "$precipdata" ]; then echo "$precipdata" | sort -rn 2>/dev/null | head -1 else echo "0%" fi } getdailyhighlow() { tempdata=$(echo "$weatherdata" | sed '13q;d' | grep -o "m\\([-+]\\)*[0-9]\\+" 2>/dev/null | sed 's/[+m]//g') if [ -n "$tempdata" ]; then echo "$tempdata" | sort -g 2>/dev/null | sed -e 1b -e '$!d' else echo "??" echo "??" fi } readfile() { weatherdata="$(cat "$weatherreport")" ;} validateweather() { [ -z "$weatherdata" ] && return 1 tempdata=$(echo "$weatherdata" | sed '13q;d' | grep -o "m\\([-+]\\)*[0-9]\\+" 2>/dev/null | sed 's/[+m]//g') [ -z "$tempdata" ] && return 1 return 0 } showweather() { readfile # If data invalid, try fetching new data if ! validateweather; then getforecast 2>/dev/null || exit 0 readfile validateweather || exit 0 fi icon=$(getweathericon) precip=$(getprecipchance) temps=$(getdailyhighlow) low=$(echo "$temps" | head -1) high=$(echo "$temps" | tail -1) # Don't show if we got placeholder data echo "$temps" | grep -q "??" && exit 0 printf "%s %s° %s°\n" "$icon" "$low" "$high" } case $BLOCK_BUTTON in 1) setsid -f "$TERMINAL" -e less -Sf "$weatherreport" ;; 2) getforecast && showweather ;; 3) notify-send "󰖙 Weather module" "\- Left click for full forecast. - Middle click to update forecast. - Shows current conditions with temp range" ;; 6) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;; esac checkforecast || getforecast 2>/dev/null showweather