aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-17 19:12:23 +0200
committerDanilo M. <danix@danix.xyz>2026-09-17 19:12:23 +0200
commit8a6c0730f8e9f2c1e6033d3e66d2c524d7b9f91d (patch)
treed9b515c5c14129d3de4ed03bac59ef3b20507e01
parent0048d3075adfd0336def9a25ce039765e43b4b3a (diff)
downloadconky-theme-udt-8a6c0730f8e9f2c1e6033d3e66d2c524d7b9f91d.tar.gz
conky-theme-udt-8a6c0730f8e9f2c1e6033d3e66d2c524d7b9f91d.zip
feat: sample the public IP into a cache file
The draw hook must never make a network call: a hung request blocks the Cairo draw and freezes the dashboard. Thirty minutes, not the old config's five, because a residential address is stable for days. Validates the response before writing. A captive portal and a rate-limit message both arrive with a 200 and would otherwise be drawn as an address. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
-rwxr-xr-xbin/pubip-sample.sh48
1 files changed, 48 insertions, 0 deletions
diff --git a/bin/pubip-sample.sh b/bin/pubip-sample.sh
new file mode 100755
index 0000000..c5100f8
--- /dev/null
+++ b/bin/pubip-sample.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Fetch the public IP address into a cache file, for widgets/network.lua.
+#
+# Run from conky's ${execi} every 30 minutes. The draw hook must never make a
+# network call: a hung request would block the Cairo draw and freeze the whole
+# dashboard, and a residential address is stable for days anyway.
+#
+# Exits non-zero with a message on stderr when it cannot fetch, leaving any
+# existing cache untouched rather than replacing a good address with an error
+# page.
+
+set -u
+
+CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/udt"
+CACHE="$CACHE_DIR/pubip.txt"
+
+umask 077
+mkdir -p "$CACHE_DIR"
+
+# The temp file sits in the same directory as the target: rename is only
+# atomic within a filesystem, and the widget reads this on its own 2s cadence.
+TMP="$CACHE.tmp.$$"
+trap 'rm -f "$TMP"' EXIT
+
+# --max-time, not just --connect-timeout: a server that accepts the connection
+# and then stalls would otherwise hold a curl process for as long as it likes.
+if ! IP=$(curl -fsS --max-time 10 https://ipinfo.io/ip 2>/dev/null); then
+ echo "pubip-sample: fetch failed" >&2
+ exit 1
+fi
+
+# Validate before writing. A captive portal, a rate-limit message and an error
+# page all arrive with a 200 and would otherwise be written to the cache and
+# drawn on the dashboard as though they were an address.
+IP=$(echo "$IP" | tr -d '[:space:]')
+if ! echo "$IP" | grep -qE '^([0-9]{1,3}\.){3}[0-9]{1,3}$'; then
+ echo "pubip-sample: response is not an IPv4 address" >&2
+ exit 1
+fi
+
+# The epoch travels with the address so the widget can refuse to show a stale
+# one.
+{
+ echo "ip $IP"
+ echo "fetched $(date +%s)"
+} > "$TMP"
+
+mv -f "$TMP" "$CACHE"