#!/bin/bash
# nchan publisher for the Unraid MCP dashboard widget.
#
# monitor_nchan runs this only while the dashboard has a subscriber. It publishes
# the service status to nginx's local Nchan socket every three seconds.

socket="/var/run/nginx.socket"
chan="http://localhost/pub/unraid_mcp?buffer_length=1"
pidfile="/var/run/unraid-mcp.pid"
interval=3
export LC_ALL=C

json_escape() {
    printf '%s' "$1" | tr -d '\000-\037' | sed 's/\\/\\\\/g; s/"/\\"/g'
}

pid_matches() {
    local pid="$1"
    [[ "${pid}" =~ ^[0-9]+$ ]] && [ -d "/proc/${pid}" ] || return 1
    tr '\0' ' ' <"/proc/${pid}/cmdline" 2>/dev/null | grep -qE '(^|[ /])runraid +serve( |$)'
}

numeric_or_zero() {
    if [[ "$1" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
        printf '%s' "$1"
    else
        printf '0'
    fi
}

status_json() {
    local pid running=false cpu=0 rss=0 mem=0 uptime=0 version
    pid="$(tr -dc '0-9' <"${pidfile}" 2>/dev/null)"
    if pid_matches "${pid}"; then
        running=true
        read -r cpu rss uptime < <(ps -o %cpu=,rss=,etimes= -p "${pid}" 2>/dev/null | awk 'NR == 1 {print $1, $2, $3}')
        cpu="$(numeric_or_zero "${cpu:-0}")"
        rss="$(numeric_or_zero "${rss:-0}")"
        uptime="$(numeric_or_zero "${uptime:-0}")"
        # RSS and elapsed time are integer fields; reject any unexpected decimal.
        [[ "${rss}" =~ ^[0-9]+$ ]] || rss=0
        [[ "${uptime}" =~ ^[0-9]+$ ]] || uptime=0
        mem=$((rss / 1024))
    else
        pid=0
    fi

    version="$(timeout 5 /usr/local/emhttp/plugins/unraid-mcp/scripts/unraid-mcp-update.sh installed 2>/dev/null || true)"
    printf '{"running":%s,"pid":%s,"cpu":%s,"memMB":%s,"uptime":%s,"version":"%s"}' \
        "${running}" "${pid}" "${cpu}" "${mem}" "${uptime}" \
        "$(json_escape "${version:-unknown}")"
}

while :; do
    curl -s --max-time 2 --unix-socket "${socket}" --data-raw "$(status_json)" "${chan}" >/dev/null 2>&1
    sleep "${interval}"
done
