#!/bin/sh
# WISPMap collector installer. Sets up the collector with Docker in ./wispmap-collector (or the folder you name):
#   curl -fsSL https://wispmap.gigahost.co.za/collector/install.sh | sh -s -- <token> [folder]
# It downloads compose.yaml, writes .env (readable only by you), asks for the read-only router user and its password
# (they stay in .env on this machine and are never sent to WISPMap), and starts the collector.
# Run it again in the same place with a new token to replace the token; the router settings are kept.
# Without a terminal (automation), set WISPMON_USER and WISPMON_PASSWORD in the environment.
set -eu

WISPMAP_URL="https://wispmap.gigahost.co.za"
COMPOSE_URL="https://raw.githubusercontent.com/gigahost-za/wispmap-collector/main/compose.yaml"
TOKEN="${1:-}"
DIR="${2:-wispmap-collector}"

say() { printf '%s\n' "$*"; }
die() { printf 'error: %s\n' "$*" >&2; exit 1; }

case "$TOKEN" in
  wmc_?*_?*) ;;
  *) die "no token. Usage: curl -fsSL $WISPMAP_URL/collector/install.sh | sh -s -- <token> [folder] (the token is on WISPMap's collector page)" ;;
esac
case "$TOKEN" in
  *[!A-Za-z0-9_-]*) die "that doesn't look like a WISPMap collector token" ;;
esac
case "$DIR" in
  ""|.*|*[!A-Za-z0-9._-]*) die "the folder must be a plain name such as wispmap-collector" ;;
esac
command -v curl >/dev/null 2>&1 || die "curl is missing"
command -v docker >/dev/null 2>&1 || die "Docker isn't installed: see https://docs.docker.com/engine/install/"
docker compose version >/dev/null 2>&1 || die "the Docker Compose plugin is missing (the 'docker compose' command)"
docker info >/dev/null 2>&1 || die "$(id -un) can't use Docker. Add yourself to the docker group (then log in again), or put sudo before sh: ... | sudo sh -s -- <token>"

umask 077
mkdir -p "$DIR"
cd "$DIR"
curl -fsSL "$COMPOSE_URL" -o compose.yaml.new
mv compose.yaml.new compose.yaml

if [ -f .env ]; then
  # An existing install: new token (and server address); the router user, password and other settings are kept.
  sed -e "s|^WISPMAP_URL=.*|WISPMAP_URL=$WISPMAP_URL|" -e "s|^WISPMAP_TOKEN=.*|WISPMAP_TOKEN=$TOKEN|" .env > .env.new
  grep -q '^WISPMAP_URL=' .env.new || printf 'WISPMAP_URL=%s\n' "$WISPMAP_URL" >> .env.new
  grep -q '^WISPMAP_TOKEN=' .env.new || printf 'WISPMAP_TOKEN=%s\n' "$TOKEN" >> .env.new
  mv .env.new .env
  chmod 600 .env
  say "Replaced the token in $PWD/.env (router settings kept)."
  RECREATE="--force-recreate"
else
  user="${WISPMON_USER:-}"
  pass="${WISPMON_PASSWORD:-}"
  if [ -z "$pass" ] && (: < /dev/tty) 2>/dev/null; then
    printf 'Read-only router user [wispmon]: ' > /dev/tty
    read -r user < /dev/tty || user=""
    trap 'stty echo < /dev/tty 2>/dev/null || true' EXIT INT TERM
    stty -echo < /dev/tty
    printf 'Its password (not shown; it stays on this machine): ' > /dev/tty
    read -r pass < /dev/tty || pass=""
    stty echo < /dev/tty
    printf '\n' > /dev/tty
  fi
  user="${user:-wispmon}"
  case "$user$pass" in
    *"'"*) die "the router user or password contains a single quote ('), which the .env file can't hold" ;;
  esac
  host="$(hostname 2>/dev/null || echo wispmap-collector)"
  [ "$DIR" = wispmap-collector ] || host="$host-$DIR"
  cat > .env <<EOF
# WISPMap collector settings, written by $WISPMAP_URL/collector/install.sh. They stay on this machine.
WISPMAP_URL=$WISPMAP_URL
WISPMAP_TOKEN=$TOKEN
# Read-only RouterOS user that exists on every router (a group with the read,api,test policies)
WISPMON_USER='$user'
WISPMON_PASSWORD='$pass'
# Name shown on WISPMap's Collectors page
COLLECTOR_HOSTNAME=$host
# Optional: stay on one release line, e.g. 0.5 (default: latest)
# COLLECTOR_TAG=0.5
EOF
  chmod 600 .env
  if [ -z "$pass" ]; then
    say "Wrote $PWD/.env without a router password."
    say "Set WISPMON_PASSWORD in it, then start the collector with:  cd $PWD && docker compose up -d"
    exit 0
  fi
  RECREATE=""
fi

say "Starting the collector..."
docker compose pull --quiet
docker compose up -d $RECREATE
say ""
say "Done. Within a minute the collector shows online on WISPMap's Collectors page."
say "Logs:    cd $PWD && docker compose logs -f"
say "Update:  cd $PWD && docker compose pull && docker compose up -d"
