diff options
Diffstat (limited to 'config/hypr/UserScripts/Weather.sh')
| -rwxr-xr-x | config/hypr/UserScripts/Weather.sh | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/config/hypr/UserScripts/Weather.sh b/config/hypr/UserScripts/Weather.sh index deba2d41..b69662e6 100755 --- a/config/hypr/UserScripts/Weather.sh +++ b/config/hypr/UserScripts/Weather.sh @@ -12,6 +12,18 @@ if [ -z "$city" ]; then fi +# URL-encode city for safe use in URLs +encoded_city="$city" +if command -v python3 >/dev/null 2>&1; then + encoded_city=$(python3 -c 'import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))' "$city") +elif command -v jq >/dev/null 2>&1; then + encoded_city=$(printf '%s' "$city" | jq -sRr @uri) +else + # Minimal fallback: encode a few common special characters + encoded_city=$(printf '%s' "$city" | sed -e 's/ /%20/g' -e 's/&/%26/g' -e 's/?/%3F/g' -e 's/#/%23/g') +fi + + cachedir="$HOME/.cache/rbn" # Include city and arg in cache key so changing city invalidates old cache cache_key="${city}_${1}" @@ -19,12 +31,12 @@ cache_key="${city}_${1}" safe_key=$(printf '%s' "$cache_key" | tr -c '[:alnum:]_-' '_') cachefile=${0##*/}-$safe_key -if [ ! -d $cachedir ]; then - mkdir -p $cachedir +if [ ! -d "$cachedir" ]; then + mkdir -p "$cachedir" fi -if [ ! -f $cachedir/$cachefile ]; then - touch $cachedir/$cachefile +if [ ! -f "$cachedir/$cachefile" ]; then + touch "$cachedir/$cachefile" fi # Save current IFS @@ -32,26 +44,32 @@ SAVEIFS=$IFS # Change IFS to new line. IFS=$'\n' -cacheage=$(($(date +%s) - $(stat -c '%Y' "$cachedir/$cachefile"))) +file="$cachedir/$cachefile" +# Portable file mtime retrieval (GNU/BSD): +# - GNU: stat -c %Y <file> +# - BSD/macOS: stat -f %m <file> +mtime=$(stat -c %Y "$file" 2>/dev/null || stat -f %m "$file" 2>/dev/null || echo 0) +now=$(date +%s) +cacheage=$(( now - mtime )) if [ $cacheage -gt 1740 ] || [ ! -s "$cachedir/$cachefile" ]; then # Prefer structured format for reliable parsing (3 lines: location, condition, temperature) - mapfile -t sdata < <(curl -fsS "https://wttr.in/${city}?format=%25l%0A%25C%0A%25t&lang=en" 2>/dev/null || true) + mapfile -t sdata < <(curl -fsS "https://wttr.in/${encoded_city}?format=%25l%0A%25C%0A%25t&lang=en" 2>/dev/null || true) if [ ${#sdata[@]} -ge 3 ]; then printf "%s\n" "${sdata[0]}" > "$cachedir/$cachefile" printf "%s\n" "${sdata[1]}" >> "$cachedir/$cachefile" printf "%s\n" "${sdata[2]}" >> "$cachedir/$cachefile" else # Try fetching each field separately if combined format is flaky - loc=$(curl -fsS "https://wttr.in/${city}?format=%25l&lang=en" 2>/dev/null || true) - cond_only=$(curl -fsS "https://wttr.in/${city}?format=%25C&lang=en" 2>/dev/null || true) - temp_only=$(curl -fsS "https://wttr.in/${city}?format=%25t" 2>/dev/null || true) + loc=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25l&lang=en" 2>/dev/null || true) + cond_only=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25C&lang=en" 2>/dev/null || true) + temp_only=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25t" 2>/dev/null || true) if [ -n "$loc" ] && [ -n "$cond_only" ] && [ -n "$temp_only" ]; then printf "%s\n" "$loc" > "$cachedir/$cachefile" printf "%s\n" "$cond_only" >> "$cachedir/$cachefile" printf "%s\n" "$temp_only" >> "$cachedir/$cachefile" else # Fallback: try ASCII output and extract best-effort fields - url="https://en.wttr.in/${city}?1" + url="https://en.wttr.in/${encoded_city}?1" mapfile -t data < <(curl -fsS "$url" 2>/dev/null || true) if [ ${#data[@]} -ge 3 ] && ! echo "${data[0]}" | grep -qi 'not found\|unknown location'; then loc=$(echo "${data[0]}" | sed -E 's/^.*: *//') @@ -75,16 +93,16 @@ mapfile -t weather < "$cachedir/$cachefile" # If cache is still empty or invalid, emit a single error JSON and exit to avoid double-prints if [ ${#weather[@]} -lt 3 ] || ! echo "${weather[2]}" | grep -qE '[-+0-9].*°'; then # Last-chance: try live structured fetch and populate cache and runtime weather - mapfile -t sdata < <(curl -fsS "https://wttr.in/${city}?format=%25l%0A%25C%0A%25t&lang=en" 2>/dev/null || true) + mapfile -t sdata < <(curl -fsS "https://wttr.in/${encoded_city}?format=%25l%0A%25C%0A%25t&lang=en" 2>/dev/null || true) if [ ${#sdata[@]} -ge 3 ]; then weather=("${sdata[@]}") printf "%s\n" "${sdata[0]}" > "$cachedir/$cachefile" printf "%s\n" "${sdata[1]}" >> "$cachedir/$cachefile" printf "%s\n" "${sdata[2]}" >> "$cachedir/$cachefile" else - loc=$(curl -fsS "https://wttr.in/${city}?format=%25l&lang=en" 2>/dev/null || true) - cond_only=$(curl -fsS "https://wttr.in/${city}?format=%25C&lang=en" 2>/dev/null || true) - temp_only=$(curl -fsS "https://wttr.in/${city}?format=%25t" 2>/dev/null || true) + loc=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25l&lang=en" 2>/dev/null || true) + cond_only=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25C&lang=en" 2>/dev/null || true) + temp_only=$(curl -fsS "https://wttr.in/${encoded_city}?format=%25t" 2>/dev/null || true) if [ -n "$loc" ] && [ -n "$cond_only" ] && [ -n "$temp_only" ]; then weather=("$loc" "$cond_only" "$temp_only") printf "%s\n" "$loc" > "$cachedir/$cachefile" @@ -175,8 +193,17 @@ if [ -z "$temperature" ]; then fi cond_disp=$(echo "${weather[1]}" | sed -E 's/^\s+//; s/\s+$//') -echo -e "{\"text\":\""$temperature" "$condition"\", \"alt\":\""${weather[0]}"\", \"tooltip\":\""${weather[0]}: $temperature $cond_disp"\"}" -cached_weather=" $temperature \n$condition ${weather[1]}" +# Escape strings for safe JSON embedding (escape backslashes and double quotes) +json_escape() { + printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/\"/\\\"/g' +} + +text_json=$(json_escape "$temperature $condition") +alt_json=$(json_escape "${weather[0]}") +tooltip_json=$(json_escape "${weather[0]}: $temperature $cond_disp") + +printf '{"text":"%s", "alt":"%s", "tooltip":"%s"}\n' "$text_json" "$alt_json" "$tooltip_json" -echo -e $cached_weather > "$HOME/.cache/.weather_cache"
\ No newline at end of file +# Write a two-line cache with an actual newline between lines +printf ' %s \n%s %s\n' "$temperature" "$condition" "${weather[1]}" > "$HOME/.cache/.weather_cache"
\ No newline at end of file |
