#!/usr/bin/env bash # # Register AutoFirmer to start at login and keep itself updated. Linux/Pi # counterpart of install-autostart.ps1 - the same two mechanisms, expressed the # way this desktop does them: # # * a ~/.config/autostart entry runs scripts/start-all.sh at login # * PM2's own cron restart drives the update checks # # No sudo, nothing system-wide. Everything runs inside the graphical login # session, which is not incidental: the clicker synthesises real X11 input and # needs a desktop with DISPLAY set. A systemd system service has neither. # # ./scripts/install-autostart.sh [--interval-minutes 5] [--skip-clicker] set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" INTERVAL=5 SKIP_CLICKER=0 while [ $# -gt 0 ]; do case "$1" in --interval-minutes) INTERVAL="$2"; shift 2 ;; --skip-clicker) SKIP_CLICKER=1; shift ;; *) echo "unknown option: $1" >&2; exit 1 ;; esac done info() { printf ' %s\n' "$1"; } warn() { printf ' ! %s\n' "$1" >&2; } info "project root: $ROOT" # ── PM2 ───────────────────────────────────────────────────────────────────── if ! command -v pm2 >/dev/null 2>&1; then info 'installing PM2 globally...' npm install -g pm2 command -v pm2 >/dev/null 2>&1 || { echo "PM2 installed but not on PATH" >&2; exit 1; } fi info "pm2: $(command -v pm2)" cd "$ROOT" # Run Next directly rather than through `npm start`, so PM2 supervises the # server itself instead of an npm wrapper that spawns it. NEXT_BIN="$ROOT/node_modules/next/dist/bin/next" [ -f "$NEXT_BIN" ] || { echo "next not found at $NEXT_BIN - run npm install first" >&2; exit 1; } pm2 delete autofirmer >/dev/null 2>&1 || true pm2 start "$NEXT_BIN" --name autofirmer --interpreter node -- start info 'pm2: autofirmer registered' if [ "$SKIP_CLICKER" -eq 0 ]; then PY_CMD_FILE="$ROOT/scripts/.python-cmd" PY_CMD="$( [ -f "$PY_CMD_FILE" ] && cat "$PY_CMD_FILE" || echo python3 )" PY_EXE="$($PY_CMD -c 'import sys;print(sys.executable)' 2>/dev/null || true)" if [ -n "$PY_EXE" ] && [ -x "$PY_EXE" ]; then pm2 delete clicker >/dev/null 2>&1 || true if pm2 start "$ROOT/clicker/runner.py" --name clicker --interpreter "$PY_EXE"; then info "pm2: clicker registered ($PY_EXE)" else warn 'pm2 start clicker failed - the dashboard is unaffected' fi else warn 'python not found - skipping the clicker' fi fi # ── Update checks (PM2 cron) ──────────────────────────────────────────────── pm2 delete autofirmer-update >/dev/null 2>&1 || true if pm2 start "$ROOT/scripts/update-check.mjs" --name autofirmer-update \ --no-autorestart --cron-restart "*/$INTERVAL * * * *"; then info "update checks: every $INTERVAL minutes (*/$INTERVAL * * * *)" else warn 'could not register the update checker - run scripts/update-check.mjs by hand' fi pm2 save >/dev/null info 'pm2: process list saved' # ── Start at login (XDG autostart) ────────────────────────────────────────── # The desktop equivalent of the Windows Startup folder: runs inside the # graphical session, so DISPLAY is set and the clicker can reach the X server. AUTOSTART_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/autostart" DESKTOP_FILE="$AUTOSTART_DIR/autofirmer.desktop" mkdir -p "$AUTOSTART_DIR" cat > "$DESKTOP_FILE" < Advanced Options -> Wayland -> X11, then reboot.' fi echo info 'Done. No sudo was needed and nothing system-wide was changed.' info 'Running now, and again at every login.' info "Updates checked every $INTERVAL minutes; see scripts/update.log" info 'Useful: pm2 list | pm2 logs autofirmer | pm2 logs clicker' info "To disable autostart: rm $DESKTOP_FILE"