diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-17 09:07:59 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-17 09:07:59 +0200 |
| commit | 2218d1afe5750558f222c048525cb32f8781c260 (patch) | |
| tree | 7bd60102a2dedbae1ebce2b8088bf2644e2009af | |
| parent | 53d39b7212ffe0753d2b10ea39348bc033f06bef (diff) | |
| download | conky-theme-udt-2218d1afe5750558f222c048525cb32f8781c260.tar.gz conky-theme-udt-2218d1afe5750558f222c048525cb32f8781c260.zip | |
feat: add the weather fetch script
Fetches current weather from OpenWeatherMap into a cache file, meant
to run from conky's ${execi 900 ...}. Writes to a temp file in the
same directory as the target and renames atomically, so a killed or
failed fetch never leaves the widget reading a half-written or error
response. Distinguishes HTTP failure from a 200-with-error-body (a
bad key returns the latter for some endpoints, the former here), and
leaves any existing good cache untouched on either kind of failure.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
| -rwxr-xr-x | bin/weather-fetch.sh | 55 | ||||
| -rw-r--r-- | weather.env.example | 12 |
2 files changed, 67 insertions, 0 deletions
diff --git a/bin/weather-fetch.sh b/bin/weather-fetch.sh new file mode 100755 index 0000000..aaa48e2 --- /dev/null +++ b/bin/weather-fetch.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Fetch current weather into a cache file. Run from conky's ${execi}, so it +# prints nothing on success and never blocks the dashboard: the widget only +# ever reads the cache. +# +# Exits non-zero with a message on stderr when it cannot fetch, and leaves any +# existing cache untouched rather than replacing good data with an error. + +set -u + +ENV_FILE="${WEATHER_ENV:-$HOME/.config/udt/weather.env}" +CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/udt" +CACHE="$CACHE_DIR/weather.json" + +if [ ! -r "$ENV_FILE" ]; then + echo "weather-fetch: no $ENV_FILE (copy weather.env.example)" >&2 + exit 1 +fi + +# shellcheck source=/dev/null +set -a; . "$ENV_FILE"; set +a + +if [ -z "${KEY:-}" ]; then + echo "weather-fetch: KEY is empty in $ENV_FILE" >&2 + exit 1 +fi + +mkdir -p "$CACHE_DIR" + +# The temp file sits in the same directory as the target, because rename is +# only atomic within a filesystem. The widget reads this cache on its own 2s +# cadence, so a fetch killed mid-write would otherwise hand it half a response. +TMP="$CACHE.tmp.$$" +trap 'rm -f "$TMP"' EXIT + +URL="https://api.openweathermap.org/data/2.5/weather" +if ! curl -fsS --max-time 15 --get "$URL" \ + --data-urlencode "appid=$KEY" \ + --data-urlencode "units=${UNITS:-metric}" \ + --data-urlencode "lang=${LANG_CODE:-en}" \ + --data-urlencode "q=${CITY},${COUNTRY}" \ + -o "$TMP" 2>/dev/null; then + echo "weather-fetch: request failed" >&2 + exit 1 +fi + +# A bad key returns HTTP 200 with a JSON error body, so the status code alone +# proves nothing. This check is carried over from the polybar script, which +# learned it the same way. +if [ "$(jq -r '.cod // empty' "$TMP" 2>/dev/null)" != "200" ]; then + echo "weather-fetch: API error: $(jq -r '.message // "unknown"' "$TMP" 2>/dev/null)" >&2 + exit 1 +fi + +mv -f "$TMP" "$CACHE" diff --git a/weather.env.example b/weather.env.example new file mode 100644 index 0000000..fa30879 --- /dev/null +++ b/weather.env.example @@ -0,0 +1,12 @@ +# Copy to ~/.config/udt/weather.env and fill in. That path is outside this +# repo on purpose: it holds a key, and anything committed is potentially +# public. chmod 600 it. +# +# Get a key at https://openweathermap.org/api. A new key returns +# "401 Invalid API key" for minutes to hours after creation; that is the API +# activating it, not a mistake in this file. + +KEY=your_32_character_api_key_here +CITY=Your City +COUNTRY=XX +UNITS=metric |
