diff --git a/scripts/detect.sh b/scripts/detect.sh new file mode 100755 index 0000000..f00f190 --- /dev/null +++ b/scripts/detect.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash +# ============================================================================= +# Strix -- detect.sh (worker) +# +# Detects system environment: OS type, Docker, Compose, Frigate, go2rtc. +# Fast, silent, returns JSON events to stdout. +# +# Protocol: +# - Every action is reported as a single-line JSON to stdout. +# - Types: check, ok, miss, error, done +# - Exit code: 0 always (detection never "fails", it just reports what it finds) +# +# Usage: +# bash scripts/detect.sh +# ============================================================================= + +set -uo pipefail + +# --------------------------------------------------------------------------- +# JSON helpers +# --------------------------------------------------------------------------- +emit() { + local type="$1" + local msg="$2" + local data="${3:-}" + + msg="${msg//\\/\\\\}" + msg="${msg//\"/\\\"}" + + if [[ -n "$data" ]]; then + printf '{"type":"%s","msg":"%s","data":%s}\n' "$type" "$msg" "$data" + else + printf '{"type":"%s","msg":"%s"}\n' "$type" "$msg" + fi +} + +# --------------------------------------------------------------------------- +# 1. System type +# --------------------------------------------------------------------------- +detect_system() { + emit "check" "Detecting system" + + if command -v pveversion &>/dev/null; then + local pve_ver + pve_ver=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+\.[0-9]+' || echo "unknown") + emit "ok" "Proxmox VE ${pve_ver}" "{\"type\":\"proxmox\",\"pve_version\":\"${pve_ver}\"}" + + elif [[ "$(uname -s 2>/dev/null)" == "Darwin" ]]; then + local mac_ver + mac_ver=$(sw_vers -productVersion 2>/dev/null || echo "unknown") + local arch + arch=$(uname -m 2>/dev/null || echo "unknown") + emit "ok" "macOS ${mac_ver} (${arch})" "{\"type\":\"macos\",\"version\":\"${mac_ver}\",\"arch\":\"${arch}\"}" + + else + local os_name="Linux" + local os_id="unknown" + local os_ver="unknown" + local arch + arch=$(uname -m 2>/dev/null || echo "unknown") + + if [[ -f /etc/os-release ]]; then + . /etc/os-release + os_name="${PRETTY_NAME:-Linux}" + os_id="${ID:-unknown}" + os_ver="${VERSION_ID:-unknown}" + fi + + emit "ok" "${os_name} (${arch})" "{\"type\":\"linux\",\"id\":\"${os_id}\",\"version\":\"${os_ver}\",\"arch\":\"${arch}\"}" + fi +} + +# --------------------------------------------------------------------------- +# 2. Docker +# --------------------------------------------------------------------------- +detect_docker() { + emit "check" "Checking Docker" + + if command -v docker &>/dev/null; then + local ver + ver=$(docker --version 2>/dev/null | grep -oP '\d+\.\d+\.\d+' | head -1 || echo "unknown") + emit "ok" "Docker ${ver}" "{\"version\":\"${ver}\"}" + else + emit "miss" "Docker not installed" + fi +} + +# --------------------------------------------------------------------------- +# 3. Docker Compose +# --------------------------------------------------------------------------- +detect_compose() { + emit "check" "Checking Docker Compose" + + if docker compose version &>/dev/null 2>&1; then + local ver + ver=$(docker compose version --short 2>/dev/null || echo "unknown") + emit "ok" "Compose ${ver}" "{\"version\":\"${ver}\",\"type\":\"plugin\"}" + elif command -v docker-compose &>/dev/null; then + local ver + ver=$(docker-compose --version 2>/dev/null | grep -oP '\d+\.\d+\.\d+' | head -1 || echo "unknown") + emit "ok" "Compose ${ver}" "{\"version\":\"${ver}\",\"type\":\"standalone\"}" + else + emit "miss" "Docker Compose not installed" + fi +} + +# --------------------------------------------------------------------------- +# 4. Frigate +# --------------------------------------------------------------------------- +detect_frigate() { + emit "check" "Checking Frigate" + + if command -v curl &>/dev/null; then + if curl -sf --connect-timeout 2 --max-time 3 "http://localhost:5000/api/config" &>/dev/null; then + emit "ok" "Frigate on port 5000" "{\"url\":\"http://localhost:5000\",\"port\":5000}" + return + fi + if curl -sf --connect-timeout 2 --max-time 3 "http://localhost:8971/api/config" &>/dev/null; then + emit "ok" "Frigate on port 8971" "{\"url\":\"http://localhost:8971\",\"port\":8971}" + return + fi + fi + + emit "miss" "Frigate not found" +} + +# --------------------------------------------------------------------------- +# 5. go2rtc +# --------------------------------------------------------------------------- +detect_go2rtc() { + emit "check" "Checking go2rtc" + + if command -v curl &>/dev/null; then + if curl -sf --connect-timeout 2 --max-time 3 "http://localhost:1984/api" &>/dev/null; then + emit "ok" "go2rtc on port 1984" "{\"url\":\"http://localhost:1984\",\"port\":1984}" + return + fi + if curl -sf --connect-timeout 2 --max-time 3 "http://localhost:11984/api" &>/dev/null; then + emit "ok" "go2rtc on port 11984" "{\"url\":\"http://localhost:11984\",\"port\":11984}" + return + fi + fi + + emit "miss" "go2rtc not found" +} + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- +main() { + detect_system + detect_docker + detect_compose + detect_frigate + detect_go2rtc + printf '{"type":"done","ok":true}\n' +} + +main