#!/bin/bash # Follower-box sync of the canonical TG list. # # Pulls the master list from the svxportal master (its public /tglist.php) into # the LOCAL /etc/svxlink/tglist.json, so every local program reads ONE identical # list: svxdr (Lastheard TG name/Location) and the box's own /tglist.php (TG # Monitor) both read that local file. No extra daemon — a plain curl run by a # systemd timer. # # Master and fully-standalone boxes OWN the file locally (web editor) and must # NOT run this — leave UPSTREAM empty there (the timer is a no-op / not enabled). set -euo pipefail : "${UPSTREAM:=}" : "${DEST:=/etc/svxlink/tglist.json}" # Empty UPSTREAM = this box owns its list; nothing to sync. [ -n "$UPSTREAM" ] || { echo "UPSTREAM empty — this box owns its TG list, skipping sync"; exit 0; } tmp="$(mktemp)"; out="$(mktemp)" trap 'rm -f "$tmp" "$out"' EXIT curl -fsS -m 20 "$UPSTREAM" -o "$tmp" # Keep ONLY the canonical shape {tgs:[...],requests:[]}. Refuse to overwrite the # live file with anything that is not a valid list (a 404/HTML/partial body must # never blank the TG names) — last good copy then simply stays. python3 - "$tmp" "$out" <<'PY' import json, sys d = json.load(open(sys.argv[1])) tgs = d.get("tgs") if not isinstance(tgs, list) or not tgs: raise SystemExit("upstream has no tgs list — refusing to overwrite") json.dump({"tgs": tgs, "requests": []}, open(sys.argv[2], "w"), indent=2) PY # www-data owns it so the web can still read it; atomic replace via install. install -o www-data -g www-data -m 0664 "$out" "$DEST" echo "TG list synced from $UPSTREAM -> $DEST"