56b6c046ef
Desktop Exec=grok-bot has no TTY, so interactive sudo cannot prompt and auto-update is skipped. Try sudo -n, then pkexec of a grok-bot-bin-only helper (auth_admin, not NOPASSWD), then interactive sudo on a TTY. Cancel or deny still launches the installed binary. #16
104 lines
3.3 KiB
Bash
Executable File
104 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Launch shim for grok-bot-bin: optionally auto-update from Gitea releases, then
|
|
# exec the real binary under /opt/Grok Bot/. Fail soft on network/API errors.
|
|
set -u
|
|
|
|
REAL_DIR="/opt/Grok Bot"
|
|
API_URL='https://git.s1d3sw1ped.com/api/v1/repos/s1d3sw1ped/grok-bot-bin/releases?limit=1'
|
|
PKEXEC_HELPER=/usr/lib/grok-bot-bin/pkexec-pacman-u
|
|
|
|
# Privilege order for pacman -U:
|
|
# 1. sudo -n (NOPASSWD, e.g. lab CT113)
|
|
# 2. pkexec (graphical polkit; desktop Exec=grok-bot has no TTY)
|
|
# 3. interactive sudo (terminal TTY)
|
|
# Never default to passwordless sudo. Cancel/deny still launches the installed binary.
|
|
_install_update_pkg() {
|
|
local pkg=$1
|
|
|
|
if sudo -n true 2>/dev/null; then
|
|
if sudo -n pacman -U --noconfirm "$pkg"; then
|
|
return 0
|
|
fi
|
|
echo "grok-bot: pacman -U failed; launching installed version" >&2
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -t 0 ]] && command -v pkexec >/dev/null 2>&1 && [[ -x "$PKEXEC_HELPER" ]] \
|
|
&& [[ -n "${DISPLAY:-}${WAYLAND_DISPLAY:-}" ]]; then
|
|
if pkexec --disable-internal-agent "$PKEXEC_HELPER" "$pkg"; then
|
|
return 0
|
|
fi
|
|
echo "grok-bot: polkit auth failed or cancelled; launching installed version" >&2
|
|
return 1
|
|
fi
|
|
|
|
if [[ -t 0 ]]; then
|
|
if sudo pacman -U --noconfirm "$pkg"; then
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
echo "grok-bot: need sudo or polkit to auto-update; run: sudo pacman -U <pkg> or launch /usr/bin/grok-bot from a terminal" >&2
|
|
echo "grok-bot: pacman -U failed; launching installed version" >&2
|
|
return 1
|
|
}
|
|
|
|
_maybe_update() {
|
|
[[ "${GROK_BOT_NO_UPDATE:-}" == "1" ]] && return 0
|
|
command -v curl >/dev/null 2>&1 || return 0
|
|
command -v pacman >/dev/null 2>&1 || return 0
|
|
command -v vercmp >/dev/null 2>&1 || return 0
|
|
|
|
local installed
|
|
installed=$(pacman -Q grok-bot-bin 2>/dev/null | awk '{print $2}') || return 0
|
|
[[ -n "$installed" ]] || return 0
|
|
|
|
local json
|
|
json=$(curl -fsSL --connect-timeout 3 --max-time 10 "$API_URL" 2>/dev/null) || return 0
|
|
[[ -n "$json" ]] || return 0
|
|
|
|
local asset_url asset_name remote_ver
|
|
asset_url=$(grep -oE 'https://[^"[:space:]\\]+grok-bot-bin-[^"[:space:]\\]+\.pkg\.tar\.zst' <<<"$json" | head -1) || true
|
|
[[ -n "$asset_url" ]] || return 0
|
|
asset_name=$(basename "$asset_url")
|
|
if [[ "$asset_name" =~ ^grok-bot-bin-(.+)-x86_64\.pkg\.tar\.zst$ ]]; then
|
|
remote_ver="${BASH_REMATCH[1]}"
|
|
else
|
|
return 0
|
|
fi
|
|
|
|
# Only upgrade when remote is strictly newer (vercmp: 1 means a > b).
|
|
local cmp
|
|
cmp=$(vercmp "$remote_ver" "$installed" 2>/dev/null) || return 0
|
|
[[ "$cmp" =~ ^-?[0-9]+$ ]] || return 0
|
|
if (( cmp <= 0 )); then
|
|
return 0
|
|
fi
|
|
|
|
local tmpdir pkg
|
|
tmpdir=$(mktemp -d 2>/dev/null) || return 0
|
|
# shellcheck disable=SC2064
|
|
trap "rm -rf '$tmpdir'" RETURN
|
|
pkg="$tmpdir/$asset_name"
|
|
|
|
echo "grok-bot: updating grok-bot-bin ${installed} -> ${remote_ver}" >&2
|
|
if ! curl -fL --connect-timeout 5 --max-time 600 -o "$pkg" "$asset_url" 2>/dev/null; then
|
|
echo "grok-bot: download failed; launching installed version" >&2
|
|
return 0
|
|
fi
|
|
|
|
_install_update_pkg "$pkg" || return 0
|
|
}
|
|
|
|
_maybe_update || true
|
|
trap - RETURN
|
|
|
|
if [[ -x "${REAL_DIR}/grok-bot" ]]; then
|
|
exec "${REAL_DIR}/grok-bot" "$@"
|
|
elif [[ -x "${REAL_DIR}/sand" ]]; then
|
|
exec "${REAL_DIR}/sand" "$@"
|
|
else
|
|
echo "grok-bot: real binary not found under ${REAL_DIR}" >&2
|
|
exit 127
|
|
fi
|