#!/usr/bin/env bash # add-popup-source.sh — Scaffold a new popup provider end-to-end. # # Prompts for the handful of facts unique to a new source (name, label, # a sample URL), then: # 1. Probes the upstream for CORS support and content-type. # 2. Prints a PROVIDERS entry stub you paste into static/js/popups.js. # 3. If CORS-broken, prints + (on confirmation) appends an nginx # location block to nginx/popup-proxy.conf. # 4. Prints a remaining-steps checklist (icon SVG, CSS, CSP comment). # # The parse() body is left as a TODO — writing it requires eyes on the # actual API response, which this tool also fetches and pretty-prints so # you can inspect the response shape without a second terminal. # # Never writes to static/js/popups.js automatically — that file has too # much surrounding structure to edit blindly. Copy-paste is safer. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" POPUPS_JS="$REPO_ROOT/static/js/popups.js" NGINX_CONF="$REPO_ROOT/nginx/popup-proxy.conf" ORIGIN="https://levineuwirth.org" # ── helpers ────────────────────────────────────────────────────────── bold() { printf '\033[1m%s\033[0m\n' "$*"; } dim() { printf '\033[2m%s\033[0m\n' "$*"; } warn() { printf '\033[33m%s\033[0m\n' "$*" >&2; } prompt() { local v; read -r -p "$1 " v; printf '%s' "$v"; } usage() { cat <&1 || true) # grep returns 1 when no match — tolerate that under `set -e` + pipefail. CORS=$(printf '%s\n' "$HEADERS" | grep -i 'access-control-allow-origin' | head -1 | tr -d '\r' || true) CT=$(printf '%s\n' "$HEADERS" | grep -i '^content-type' | head -1 | tr -d '\r' | awk '{print tolower($2)}' || true) if [[ -n "$CORS" ]]; then echo " CORS ✓ $CORS" NEEDS_PROXY=0 else warn " CORS ✗ none — upstream needs a reverse proxy" NEEDS_PROXY=1 fi echo " Content-Type: ${CT:-unknown}" case "$CT" in *xml*|*atom*) FETCH_TYPE=xml ;; *json*) FETCH_TYPE=json ;; *) FETCH_TYPE=json; warn " (unrecognized type — defaulting to json)" ;; esac echo " fetchType → $FETCH_TYPE" else warn " no API URL supplied; assuming json + CORS-OK (edit by hand if wrong)" FETCH_TYPE=json NEEDS_PROXY=0 fi # ── sample response dump (helps write the parser) ──────────────────── if [[ -n "$API_URL" ]]; then echo bold "── sample response (first ~40 lines) ──" RAW=$(curl -sS "$API_URL" 2>&1 || true) if [[ "$FETCH_TYPE" == json ]] && command -v jq >/dev/null; then printf '%s\n' "$RAW" | jq -C . 2>/dev/null | head -40 || printf '%s\n' "$RAW" | head -40 elif [[ "$FETCH_TYPE" == xml ]] && command -v xmllint >/dev/null; then printf '%s\n' "$RAW" | xmllint --format - 2>/dev/null | head -40 || printf '%s\n' "$RAW" | head -40 else printf '%s\n' "$RAW" | head -40 fi fi # ── proxy prefix + upstream host derivation ────────────────────────── if [[ "$NEEDS_PROXY" -eq 1 ]]; then UPSTREAM_HOST=$(printf '%s' "$API_URL" | awk -F/ '{print $3}') UPSTREAM_PATH=$(printf '%s' "$API_URL" | awk -F/ 'BEGIN{OFS="/"} {$1=""; $2=""; $3=""; print}' | sed 's|^///||') PROXY_PATH="/proxy/$NAME/" PROXY_API_URL="$PROXY_PATH${UPSTREAM_PATH%%\?*}" [[ "$API_URL" == *"?"* ]] && PROXY_API_URL="$PROXY_API_URL?${API_URL#*\?}" else UPSTREAM_HOST="" PROXY_API_URL="$API_URL" fi # ── PROVIDERS entry stub ───────────────────────────────────────────── echo bold "── paste into static/js/popups.js (PROVIDERS array) ──" dim " Insertion order = match priority; pick a spot before less-specific entries." echo cat <> "$NGINX_CONF" echo " appended to $NGINX_CONF" else echo " skipped — paste manually when ready" fi fi # ── remaining-steps checklist ──────────────────────────────────────── echo bold "── remaining manual steps ──" cat <