aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-17 09:07:59 +0200
committerDanilo M. <danix@danix.xyz>2026-09-17 09:07:59 +0200
commit2218d1afe5750558f222c048525cb32f8781c260 (patch)
tree7bd60102a2dedbae1ebce2b8088bf2644e2009af
parent53d39b7212ffe0753d2b10ea39348bc033f06bef (diff)
downloadconky-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-xbin/weather-fetch.sh55
-rw-r--r--weather.env.example12
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