Skip to content

Commit 741f99a

Browse files
committed
Replace release-based update with commit SHA tracking
- check_update_sha_bg(): background SHA fetch on TUI startup, sets badge file when new commits are available on main - Main menu shows update banner when badge exists - self_update(): download from main, SHA256 compare, backup, install, auto-regenerate + restart Telegram service after update - Works without GitHub releases — every push to main is detectable
1 parent 65ad3c8 commit 741f99a

1 file changed

Lines changed: 140 additions & 102 deletions

File tree

mtproxymax.sh

Lines changed: 140 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,126 +2493,159 @@ auto_recover() {
24932493

24942494
# ── Section 13: Auto-Update ─────────────────────────────────
24952495

2496-
check_for_updates() {
2497-
local latest
2498-
latest=$(curl -sL --max-time 10 \
2499-
"https://api.github.com/repos/${GITHUB_REPO}/releases/latest" \
2500-
2>/dev/null | grep '"tag_name"' | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
2496+
_UPDATE_SHA_FILE="${INSTALL_DIR}/.update_sha"
2497+
_UPDATE_BADGE="/tmp/.mtproxymax_update_available"
2498+
2499+
# Background SHA check — non-blocking, ~40 bytes over the wire
2500+
check_update_sha_bg() {
2501+
{
2502+
local _remote_sha
2503+
_remote_sha=$(curl -fsSL --connect-timeout 5 --max-time 10 \
2504+
"https://api.github.com/repos/${GITHUB_REPO}/commits/main" \
2505+
-H "Accept: application/vnd.github.sha" 2>/dev/null) || true
2506+
2507+
# Must be 40 lowercase hex chars
2508+
if [ -n "$_remote_sha" ] && [ ${#_remote_sha} -ge 40 ]; then
2509+
_remote_sha="${_remote_sha:0:40}"
2510+
case "$_remote_sha" in *[!a-f0-9]*) exit 0 ;; esac
2511+
2512+
local _stored=""
2513+
[ -f "$_UPDATE_SHA_FILE" ] && _stored=$(<"$_UPDATE_SHA_FILE")
2514+
2515+
if [ -z "$_stored" ]; then
2516+
# First run — save baseline, no badge
2517+
echo "$_remote_sha" > "$_UPDATE_SHA_FILE" 2>/dev/null || true
2518+
rm -f "$_UPDATE_BADGE" 2>/dev/null
2519+
elif [ "$_remote_sha" != "$_stored" ]; then
2520+
echo "new" > "$_UPDATE_BADGE" 2>/dev/null
2521+
else
2522+
rm -f "$_UPDATE_BADGE" 2>/dev/null
2523+
fi
2524+
fi
2525+
# API unreachable — do nothing; badge stays as-is (no false positives)
2526+
} &
2527+
}
2528+
2529+
self_update() {
2530+
# Prevent concurrent updates
2531+
if command -v flock &>/dev/null; then
2532+
local _lfd
2533+
exec {_lfd}>/tmp/.mtproxymax_update.lock
2534+
if ! flock -n "$_lfd" 2>/dev/null; then
2535+
log_warn "Another update is already running."
2536+
return 1
2537+
fi
2538+
fi
2539+
2540+
local _script_updated=false
2541+
local _url="https://raw.githubusercontent.com/${GITHUB_REPO}/main/mtproxymax.sh"
2542+
2543+
echo ""
2544+
log_info "Checking for script updates..."
2545+
2546+
local _tmp
2547+
_tmp=$(_mktemp) || return 1
2548+
2549+
if curl -fsSL --max-time 60 --max-filesize 5242880 -o "$_tmp" "$_url" 2>/dev/null; then
2550+
# Validate: bash syntax + sanity check
2551+
if ! bash -n "$_tmp" 2>/dev/null; then
2552+
log_error "Downloaded script has syntax errors — aborting"
2553+
rm -f "$_tmp"; return 1
2554+
fi
2555+
if ! grep -q "GITHUB_REPO=\"SamNet-dev/MTProxyMax\"" "$_tmp" 2>/dev/null; then
2556+
log_error "Downloaded file doesn't look like MTProxyMax — aborting"
2557+
rm -f "$_tmp"; return 1
2558+
fi
2559+
local _dl_size
2560+
_dl_size=$(wc -c < "$_tmp")
2561+
if [ "$_dl_size" -lt 10000 ]; then
2562+
log_error "Downloaded file too small (${_dl_size} bytes) — possible truncated download"
2563+
rm -f "$_tmp"; return 1
2564+
fi
2565+
2566+
local _new_ver
2567+
_new_ver=$(grep -m1 '^VERSION="' "$_tmp" | cut -d'"' -f2)
25012568

2502-
if [ -z "$latest" ]; then
2569+
# Compare SHA256 — if identical, already up to date
2570+
local _local_hash _remote_hash
2571+
_local_hash=$(sha256sum "${INSTALL_DIR}/mtproxymax" 2>/dev/null | cut -d' ' -f1)
2572+
_remote_hash=$(sha256sum "$_tmp" | cut -d' ' -f1)
2573+
2574+
if [ "$_local_hash" = "$_remote_hash" ]; then
2575+
log_success "Script is already up to date (v${_new_ver:-${VERSION}})"
2576+
rm -f "$_tmp" "$_UPDATE_BADGE"
2577+
else
2578+
log_info "Update found: v${_new_ver:-?} (installed: v${VERSION})"
2579+
echo -en " ${BOLD}Update now? [y/N]:${NC} "
2580+
local _confirm; read -r _confirm
2581+
if [ "$_confirm" != "y" ] && [ "$_confirm" != "Y" ]; then
2582+
log_info "Skipped"
2583+
rm -f "$_tmp"
2584+
else
2585+
mkdir -p "$BACKUP_DIR"
2586+
cp "${INSTALL_DIR}/mtproxymax" \
2587+
"${BACKUP_DIR}/mtproxymax.v${VERSION}.$(date +%s)" 2>/dev/null || true
2588+
chmod +x "$_tmp"
2589+
mv "$_tmp" "${INSTALL_DIR}/mtproxymax"
2590+
log_success "Script updated to v${_new_ver:-?}"
2591+
_script_updated=true
2592+
rm -f "$_UPDATE_BADGE"
2593+
2594+
# Save new commit SHA as baseline
2595+
local _new_sha
2596+
_new_sha=$(curl -fsSL --connect-timeout 5 --max-time 10 \
2597+
"https://api.github.com/repos/${GITHUB_REPO}/commits/main" \
2598+
-H "Accept: application/vnd.github.sha" 2>/dev/null) || true
2599+
if [ -n "$_new_sha" ] && [ ${#_new_sha} -ge 40 ]; then
2600+
_new_sha="${_new_sha:0:40}"
2601+
case "$_new_sha" in
2602+
*[!a-f0-9]*) : ;;
2603+
*) echo "$_new_sha" > "$_UPDATE_SHA_FILE" 2>/dev/null || true ;;
2604+
esac
2605+
fi
2606+
fi
2607+
fi
2608+
else
2609+
log_error "Download failed — check your internet connection"
2610+
rm -f "$_tmp"
25032611
return 1
25042612
fi
25052613

2506-
# Update available if current version is older than latest
2507-
if ! version_gte "$VERSION" "$latest"; then
2508-
echo "$latest"
2509-
return 0
2614+
# Regenerate + restart Telegram bot service if script was updated
2615+
if [ "$_script_updated" = true ] && [ "${TELEGRAM_ENABLED:-}" = "true" ]; then
2616+
log_info "Regenerating Telegram bot service..."
2617+
telegram_generate_service_script
2618+
if command -v systemctl &>/dev/null; then
2619+
systemctl restart mtproxymax-telegram.service 2>/dev/null \
2620+
&& log_success "Telegram bot service restarted" \
2621+
|| log_warn "Telegram restart failed — run: systemctl restart mtproxymax-telegram.service"
2622+
fi
25102623
fi
2511-
return 1
2512-
}
25132624

2514-
self_update() {
2515-
log_info "Checking for updates..."
2516-
2517-
# Check telemt engine update
2518-
local telemt_latest
2519-
telemt_latest=$(check_telemt_update 2>/dev/null) && {
2520-
local telemt_current
2521-
telemt_current=$(get_telemt_version)
2522-
log_info "Telemt engine update: v${telemt_current} -> v${telemt_latest}"
2625+
# Telemt engine update check
2626+
echo ""
2627+
local _telemt_latest
2628+
_telemt_latest=$(check_telemt_update 2>/dev/null) && {
2629+
local _telemt_cur
2630+
_telemt_cur=$(get_telemt_version)
2631+
log_info "Telemt engine update available: v${_telemt_cur} -> v${_telemt_latest}"
25232632
echo -en " ${BOLD}Update telemt engine? [y/N]:${NC} "
2524-
local tconfirm
2525-
read -r tconfirm
2526-
if [ "$tconfirm" = "y" ] || [ "$tconfirm" = "Y" ]; then
2633+
local _tconfirm; read -r _tconfirm
2634+
if [ "$_tconfirm" = "y" ] || [ "$_tconfirm" = "Y" ]; then
25272635
build_telemt_image true
25282636
if is_proxy_running; then
25292637
load_secrets
25302638
restart_proxy_container
25312639
fi
25322640
fi
25332641
} || {
2534-
local tver
2535-
tver=$(get_telemt_version)
2536-
if [ "$tver" = "unknown" ]; then
2642+
local _tver; _tver=$(get_telemt_version)
2643+
if [ "$_tver" = "unknown" ]; then
25372644
log_warn "Telemt version unknown — try rebuilding with: mtproxymax rebuild"
25382645
else
2539-
log_success "Telemt engine is up to date (v${tver})"
2646+
log_success "Telemt engine is up to date (v${_tver})"
25402647
fi
25412648
}
2542-
2543-
# Check script update
2544-
local latest
2545-
latest=$(check_for_updates 2>/dev/null)
2546-
local rc=$?
2547-
if [ $rc -ne 0 ] && [ -z "$latest" ]; then
2548-
log_info "Script update check unavailable (no releases found)"
2549-
return 0
2550-
fi
2551-
if [ -z "$latest" ]; then
2552-
log_success "Script is up to date (v${VERSION})"
2553-
return 0
2554-
fi
2555-
2556-
log_info "New version available: v${latest} (current: v${VERSION})"
2557-
echo -en " ${BOLD}Update now? [y/N]:${NC} "
2558-
local confirm
2559-
read -r confirm
2560-
[ "$confirm" != "y" ] && [ "$confirm" != "Y" ] && { log_info "Skipped"; return 0; }
2561-
2562-
# Backup current script
2563-
mkdir -p "$BACKUP_DIR"
2564-
cp "${INSTALL_DIR}/mtproxymax" "${BACKUP_DIR}/mtproxymax.v${VERSION}.$(date +%s)" 2>/dev/null
2565-
2566-
# Download new version
2567-
local tmp
2568-
tmp=$(_mktemp) || return 1
2569-
if curl -sL --max-time 60 \
2570-
"https://raw.githubusercontent.com/${GITHUB_REPO}/main/mtproxymax.sh" \
2571-
-o "$tmp" 2>/dev/null; then
2572-
2573-
# Validate: must be a bash script, > 1KB, and contain the expected version
2574-
local dl_size
2575-
dl_size=$(wc -c < "$tmp")
2576-
if ! head -1 "$tmp" | grep -q '^#!/bin/bash'; then
2577-
log_error "Downloaded file is not a valid script"
2578-
return 1
2579-
fi
2580-
if [ "$dl_size" -lt 1000 ]; then
2581-
log_error "Downloaded file too small (${dl_size} bytes) — possible truncated download"
2582-
return 1
2583-
fi
2584-
local dl_version
2585-
dl_version=$(grep -oE '^VERSION="[0-9]+\.[0-9]+\.[0-9]+"' "$tmp" | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
2586-
if [ -n "$dl_version" ] && [ "$dl_version" != "$latest" ]; then
2587-
log_error "Version mismatch: expected v${latest}, got v${dl_version}"
2588-
return 1
2589-
fi
2590-
# Verify SHA256 integrity (download hash from repo if available)
2591-
local sha_expect
2592-
sha_expect=$(curl -sL --max-time 10 \
2593-
"https://raw.githubusercontent.com/${GITHUB_REPO}/main/mtproxymax.sh.sha256" 2>/dev/null \
2594-
| grep -oE '^[0-9a-f]{64}' | head -1)
2595-
if [ -n "$sha_expect" ]; then
2596-
local sha_actual
2597-
sha_actual=$(sha256sum "$tmp" | cut -d' ' -f1)
2598-
if [ "$sha_actual" != "$sha_expect" ]; then
2599-
log_error "SHA256 mismatch — download may be corrupted or tampered"
2600-
return 1
2601-
fi
2602-
log_info "SHA256 verified"
2603-
fi
2604-
chmod +x "$tmp"
2605-
mv "$tmp" "${INSTALL_DIR}/mtproxymax"
2606-
log_success "Updated to v${latest}"
2607-
2608-
# Regenerate telegram service if needed
2609-
if [ "$TELEGRAM_ENABLED" = "true" ]; then
2610-
telegram_generate_service_script
2611-
fi
2612-
else
2613-
log_error "Download failed"
2614-
return 1
2615-
fi
26162649
}
26172650

26182651
# ── Section 14: Telegram Integration ────────────────────────
@@ -3986,6 +4019,7 @@ cli_main() {
39864019
if [ -f "$SETTINGS_FILE" ]; then
39874020
load_settings
39884021
load_secrets
4022+
check_update_sha_bg # non-blocking background SHA check
39894023
show_main_menu
39904024
else
39914025
run_installer
@@ -4633,6 +4667,10 @@ show_main_menu() {
46334667
draw_box_line " ${BOLD}Secrets:${NC} ${active} active / ${disabled} disabled" "$w"
46344668

46354669
draw_box_sep "$w"
4670+
if [ -f "$_UPDATE_BADGE" ]; then
4671+
draw_box_line " ${YELLOW}${BOLD}⬆ Update available — select [9] to update${NC}" "$w"
4672+
draw_box_sep "$w"
4673+
fi
46364674
draw_box_empty "$w"
46374675
draw_box_line " ${BRIGHT_CYAN}[1]${NC} Proxy Management" "$w"
46384676
draw_box_line " ${BRIGHT_CYAN}[2]${NC} Secret Management" "$w"

0 commit comments

Comments
 (0)