#!/usr/bin/env nix-shell
#!nix-shell -i bash -p curl -p dig -p iputils -p openssh

echo "this script will check that uninsane.org is baseline operational"
echo "it doesn't check all services, just the most critical ones"
echo ""

OVPNS_IPV4=156.146.51.235
DOOF_IPV4=205.201.63.12

usage() {
  echo "usage: check-uninsane [flags ...]"
  echo "flags:"
  echo "- -v | --verbose: show commands before running them"
  echo "             pass a second time to also show output of successful commands"
  exit 1
}

verbose=0
parseArgs() {
  while [ "$#" -ne 0 ]; do
    local arg=$1
    shift
    case $arg in
      (-v|--verbose)
        verbose=$(( $verbose + 1 ))
        ;;
      (*)
        usage
        ;;
    esac
  done
}

last_error=0
check() {
  local label=$1
  shift
  if [ "$verbose" -ge 1 ]; then
    printf "checking %s (%s)... " "$label" "$*"
  else
    printf "checking %s... " "$label"
  fi
  if [ "$verbose" -ge 2 ]; then
    "$@"
  else
    "$@" > /dev/null
  fi
  local rc=$?
  if [ $rc -ne 0 ]; then
    last_error=$rc
    printf "❌\n  FAILED CHECK '%s'\n" "$label" >&2
    echo "  $@" >&2
  else
    printf "✅\n"
  fi
  return $rc
}

runOnHost() {
  local host="$1"
  shift
  if [ "$host" = "$(hostname)" ]; then
    "$@"
  else
    ssh "$host-hn" "$@"
  fi
}

check "self-test" false 2> /dev/null
if [ $last_error -eq 0 ]; then
  echo "SELF-TEST FAILED" >&2
  echo "SELF-TEST FAILED"
  exit 1
fi
last_error=0

parseArgs "$@"

check "uninsane.org. DNS" nslookup uninsane.org.
check "[1.1.1.1] uninsane.org. DNS" nslookup uninsane.org. 1.1.1.1
check "[8.8.8.8] uninsane.org. DNS" nslookup uninsane.org. 8.8.8.8
check "[DOOF] uninsane.org. DNS" nslookup uninsane.org. "$DOOF_IPV4"
# OVPNS DNS is no longer used
# check "[OVPNS] uninsane.org. DNS" nslookup uninsane.org. "$OVPNS_IPV4"

check "https://uninsane.org online" curl --silent --fail-with-body https://uninsane.org
check "https://matrix.uninsane.org online" curl --silent --fail-with-body https://matrix.uninsane.org
check "https://fed.uninsane.org online" curl --silent --fail-with-body https://fed.uninsane.org

# port 80 is accessible also from my VPNs
check "http://uninsane.org online" curl --silent --fail-with-body http://uninsane.org
check "[OVPNS] http://uninsane.org online" curl "--connect-to" "uninsane.org:80:$OVPNS_IPV4:80" --silent --fail-with-body http://uninsane.org
check "[DOOF] http://uninsane.org online" curl "--connect-to" "uninsane.org:80:$DOOF_IPV4:80" --silent --fail-with-body http://uninsane.org

# port 443 is accessible over doofnet
check "[DOOF] https://uninsane.org online" curl "--connect-to" "uninsane.org:443:$DOOF_IPV4:443" --silent --fail-with-body https://uninsane.org
check "[DOOF] https://matrix.uninsane.org online" curl "--connect-to" "matrix.uninsane.org:443:$DOOF_IPV4:443" --silent --fail-with-body https://matrix.uninsane.org

check "uninsane.org DMARC record" nslookup -querytype=TXT _dmarc.uninsane.org.
_checkPtr() {
  local fwd=$1
  local rev=$2
  nslookup "$fwd" | grep "name = $rev$"
}
check "mx.uninsane.org PTR" _checkPtr "$OVPNS_IPV4" mx.uninsane.org.

check "servo-hn wireguard network" ping -c 1 -W 3 servo-hn

check "git.uninsane.org" git ls-remote https://git.uninsane.org/colin/nix-files.git --quiet

check "ftps://ftp.uninsane.org" curl --silent ftps://ftp.uninsane.org/.public_for_test/test
check "[DOOF] ftps://ftp.uninsane.org" curl "--connect-to" "ftp.uninsane.org:80:$DOOF_IPV4:80" --silent ftps://ftp.uninsane.org/.public_for_test/test

check "bitcoind is responsive" runOnHost servo bitcoin-cli echo ping
_bitcoindSynchronized() {
  local info=$(runOnHost servo bitcoin-cli getblockchaininfo)
  local infoRc=$?
  echo "$info"
  if [ $infoRc -ne 0 ]; then
    return $infoRc
  fi
  # info like:
  # {
  #  "chain": "main",
  #  "blocks": 854390,
  #  "headers": 854395,
  #  "bestblockhash": "0000000000000000000174d41cdf228666f80b2f23ad63feec9d9c0528ff8b1f",
  #  "difficulty": 82047728459932.75,
  #  "time": 1722203017,
  #  "mediantime": 1722200322,
  #  "verificationprogress": 0.9999830752447421,
  #  "initialblockdownload": false,
  #  "chainwork": "000000000000000000000000000000000000000085f224886efb655e8b4cb240",
  #  "size_on_disk": 669526205080,
  #  "pruned": false,
  #  "warnings": ""
  #}
  local btcTime=$(echo "$info" | jq .time)
  local btcBlocks=$(echo "$info" | jq .blocks)
  local btcHeaders=$(echo "$info" | jq .headers)
  local now=$(date '+%s')
  [ $(( $now - $btcTime )) -lt $(( 2*60*60 )) ] && \
    [ $(( $btcHeaders - $btcBlocks )) -lt 12 ]
}
check "Bitcoind synchronized" _bitcoindSynchronized
check "Bitcoin Lightning" runOnHost servo clightning-sane status

check "/mnt/persist/private" runOnHost servo systemctl status gocryptfs-private.service

echo ""
echo "systemctl --failed:"
runOnHost servo systemctl -q --failed

echo ""
if [ $last_error -eq 0 ]; then
  echo "SUCCESS"
  echo "now manually test email services:"
  echo "- <https://www.appmaildev.com/en/dkim>"
else
  echo "FAILED"
  exit $last_error
fi
