refactor: module-based strategy architecture
- Add sync_from_upstream.sh: clones Flowseal repo, merges lists/hosts, auto-detects new .bat strategies - Add strategies/*.conf config files (extracted from .bat) - Rewrite run_strategy.sh: loads .conf, substitutes %BIN%/%LISTS%/%GAME_*% using sed (no envsubst) - Rewrite update.sh: pipeline is now sync→rebuild→test→install - Add ensure_wrappers.sh: auto-creates general_*.sh wrappers from .conf - Fix all 'local outside function' runtime bugs - install.sh now calls sync_from_upstream.sh first
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
#!/bin/bash
|
||||
# update.sh - Auto-update, auto-build, auto-test, auto-install pipeline
|
||||
# Full automation: download updates → rebuild nfqws → test strategies → install working one
|
||||
# update.sh - Full auto-pipeline: sync upstream → update → build → test → install
|
||||
# Version: 2.0
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/lib/functions.sh"
|
||||
|
||||
GITHUB_REPO="Flowseal/zapret-discord-youtube"
|
||||
GITHUB_RAW="https://raw.githubusercontent.com/$GITHUB_REPO/main"
|
||||
GITHUB_RELEASES="https://github.com/$GITHUB_REPO/releases"
|
||||
LOCAL_VERSION_FILE="$SCRIPT_DIR/.service/version.txt"
|
||||
UPDATE_LOG="$SCRIPT_DIR/.service/update.log"
|
||||
|
||||
@@ -19,100 +16,51 @@ log_msg() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$UPDATE_LOG"
|
||||
}
|
||||
|
||||
# Check remote version
|
||||
check_remote_version() {
|
||||
local remote_ver
|
||||
remote_ver=$(curl -sfL "$GITHUB_RAW/.service/version.txt" 2>/dev/null | head -n1 | tr -d '[:space:]')
|
||||
if [[ -z "$remote_ver" ]]; then
|
||||
log_msg "ERROR: Failed to fetch remote version"
|
||||
# Check if nfqws binary is healthy
|
||||
verify_nfqws() {
|
||||
local bin="$BIN_DIR/nfqws"
|
||||
if [[ ! -x "$bin" ]]; then
|
||||
log_msg "[FAIL] nfqws binary missing or not executable: $bin"
|
||||
return 1
|
||||
fi
|
||||
echo "$remote_ver"
|
||||
}
|
||||
|
||||
# Update lists and scripts (non-destructive)
|
||||
update_files() {
|
||||
log_msg "[*] Updating lists and scripts from GitHub..."
|
||||
|
||||
for file in list-general.txt list-google.txt list-exclude.txt ipset-exclude.txt; do
|
||||
local url="$GITHUB_RAW/lists/$file"
|
||||
local dest="$SCRIPT_DIR/lists/$file"
|
||||
if curl -sfL "$url" -o "$dest.tmp" 2>/dev/null; then
|
||||
mv "$dest.tmp" "$dest"
|
||||
log_msg " [OK] Updated lists/$file"
|
||||
else
|
||||
log_msg " [SKIP] lists/$file (unavailable)"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -f "$SCRIPT_DIR/.service/ipset_filter_loaded" ]] || [[ -f "$SCRIPT_DIR/.service/ipset_filter_any" ]]; then
|
||||
local url="$GITHUB_RAW/.service/ipset-all.txt"
|
||||
local dest="$SCRIPT_DIR/lists/ipset-all.txt"
|
||||
if curl -sfL "$url" -o "$dest.tmp" 2>/dev/null; then
|
||||
mv "$dest.tmp" "$dest"
|
||||
log_msg " [OK] Updated lists/ipset-all.txt"
|
||||
fi
|
||||
fi
|
||||
|
||||
for file in lib/functions.sh utils/test_zapret.sh utils/targets.txt; do
|
||||
local url="$GITHUB_RAW/$file"
|
||||
local dest="$SCRIPT_DIR/$file"
|
||||
if curl -sfL "$url" -o "$dest.tmp" 2>/dev/null; then
|
||||
mv "$dest.tmp" "$dest"
|
||||
log_msg " [OK] Updated $file"
|
||||
fi
|
||||
done
|
||||
|
||||
log_msg "[*] File update complete."
|
||||
}
|
||||
|
||||
# Rebuild nfqws with verification
|
||||
rebuild_nfqws() {
|
||||
log_msg "[*] Rebuilding nfqws..."
|
||||
|
||||
if ! bash "$SCRIPT_DIR/install_nfqws.sh"; then
|
||||
log_msg "[FAIL] nfqws build script failed."
|
||||
if ! "$bin" --help >/dev/null 2>&1; then
|
||||
log_msg "[FAIL] nfqws binary does not run (segfault?)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Verify binary exists
|
||||
if [[ ! -x "$BIN_DIR/nfqws" ]]; then
|
||||
log_msg "[FAIL] nfqws binary not found after build."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Verify binary can start (quick help check)
|
||||
if ! "$BIN_DIR/nfqws" --help >/dev/null 2>&1; then
|
||||
log_msg "[FAIL] nfqws binary built but does not execute."
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_msg "[OK] nfqws rebuilt and verified."
|
||||
log_msg "[OK] nfqws binary verified."
|
||||
return 0
|
||||
}
|
||||
|
||||
# Run autotest to find working strategy and install it
|
||||
run_autotest_pipeline() {
|
||||
log_msg "[*] Running auto-test pipeline to find working strategy..."
|
||||
# Rebuild nfqws
|
||||
rebuild_nfqws() {
|
||||
log_msg "[*] Rebuilding nfqws..."
|
||||
if bash "$SCRIPT_DIR/install_nfqws.sh"; then
|
||||
verify_nfqws
|
||||
else
|
||||
log_msg "[FAIL] Build script failed."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Stop any existing service first
|
||||
# Run autotest pipeline
|
||||
run_pipeline_autotest() {
|
||||
log_msg "[*] Running auto-test pipeline..."
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl stop zapret.service 2>/dev/null || true
|
||||
fi
|
||||
cleanup_firewall >/dev/null 2>&1 || true
|
||||
sleep 2
|
||||
|
||||
# Run autotest in auto mode
|
||||
if bash "$SCRIPT_DIR/autotest.sh" --auto; then
|
||||
log_msg "[OK] Auto-test found working strategy and installed it."
|
||||
bash "$SCRIPT_DIR/autotest.sh" --auto && {
|
||||
log_msg "[OK] Auto-test: working strategy found and installed."
|
||||
return 0
|
||||
else
|
||||
log_msg "[FAIL] Auto-test did not find any working strategy."
|
||||
} || {
|
||||
log_msg "[WARN] Auto-test: no working strategy found."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
# Restart service if installed
|
||||
# Restart systemd service
|
||||
restart_service() {
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
if systemctl is-enabled zapret.service >/dev/null 2>&1; then
|
||||
@@ -123,120 +71,111 @@ restart_service() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Full pipeline: update → build → test → install
|
||||
# Step 0: Sync upstream
|
||||
do_sync() {
|
||||
log_msg "[*] Step 0: Syncing upstream strategies, lists, hosts..."
|
||||
bash "$SCRIPT_DIR/sync_from_upstream.sh" 2>&1 | tee -a "$UPDATE_LOG"
|
||||
local sync_status=${PIPESTATUS[0]}
|
||||
|
||||
case "$sync_status" in
|
||||
0) log_msg "[OK] Sync complete, no rebuild needed."
|
||||
SYNC_REBUILD=0
|
||||
;;
|
||||
2) log_msg "[OK] Sync complete, REBUILD FLAGGED (new version or lists changed)."
|
||||
SYNC_REBUILD=1
|
||||
;;
|
||||
*) log_msg "[WARN] Sync encountered errors (exit $sync_status). Continue anyway."
|
||||
SYNC_REBUILD=0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Step 1-4: Main pipeline
|
||||
full_pipeline() {
|
||||
local mode="${1:-interactive}"
|
||||
local force="${2:-no}"
|
||||
|
||||
if [[ "$mode" == "interactive" ]]; then
|
||||
[[ "$mode" == "interactive" ]] && {
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " Zapret Full Auto Pipeline"
|
||||
echo " Zapret Full Auto Pipeline v2.0"
|
||||
echo " Current: $LOCAL_VERSION"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Step 1: Check remote version
|
||||
log_msg "[*] Step 1/4: Checking for updates..."
|
||||
local remote_version
|
||||
remote_version=$(check_remote_version) || {
|
||||
log_msg "Could not check remote version."
|
||||
if [[ "$mode" == "interactive" ]]; then
|
||||
read -rp "Continue with local rebuild anyway? [y/N]: " ans
|
||||
[[ "$ans" == [yY]* ]] || exit 1
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
remote_version="$LOCAL_VERSION"
|
||||
}
|
||||
|
||||
if [[ "$mode" == "interactive" ]]; then
|
||||
echo "Remote version: $remote_version"
|
||||
echo "Local version: $LOCAL_VERSION"
|
||||
echo ""
|
||||
# Step 0: Always sync upstream first
|
||||
do_sync
|
||||
|
||||
# Determine if we need to rebuild
|
||||
local need_rebuild=0
|
||||
if [[ "$force" == "yes" ]]; then
|
||||
log_msg "[*] Force rebuild requested."
|
||||
need_rebuild=1
|
||||
elif [[ "${SYNC_REBUILD:-0}" -eq 1 ]]; then
|
||||
log_msg "[*] Rebuild flagged by sync."
|
||||
need_rebuild=1
|
||||
fi
|
||||
|
||||
# Decide whether to update
|
||||
local do_update=0
|
||||
if [[ "$remote_version" != "$LOCAL_VERSION" ]]; then
|
||||
do_update=1
|
||||
log_msg "New version available: $remote_version"
|
||||
elif [[ "$force" == "yes" ]]; then
|
||||
log_msg "Force rebuild requested."
|
||||
do_update=1
|
||||
if [[ "$need_rebuild" -eq 0 ]] && [[ "$mode" == "interactive" ]]; then
|
||||
read -rp "No upstream changes detected. Force rebuild + re-test? [y/N]: " ans
|
||||
[[ "$ans" == [yY]* ]] && need_rebuild=1
|
||||
fi
|
||||
|
||||
if [[ "$do_update" -eq 0 ]]; then
|
||||
log_msg "No update needed."
|
||||
if [[ "$mode" == "interactive" ]]; then
|
||||
read -rp "Rebuild nfqws and re-test anyway? [y/N]: " ans
|
||||
[[ "$ans" == [yY]* ]] || {
|
||||
echo "[*] Nothing to do. Exiting."
|
||||
exit 0
|
||||
}
|
||||
else
|
||||
log_msg "Exiting (no update, no force)."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Step 2: Update files
|
||||
if [[ "$remote_version" != "$LOCAL_VERSION" ]]; then
|
||||
log_msg "[*] Step 2/4: Updating files from GitHub..."
|
||||
update_files
|
||||
echo "LOCAL_VERSION=\"$remote_version-linux\"" > "$LOCAL_VERSION_FILE"
|
||||
else
|
||||
log_msg "[*] Step 2/4: Skipping file update (same version, force mode)."
|
||||
fi
|
||||
|
||||
# Step 3: Rebuild nfqws with verification
|
||||
log_msg "[*] Step 3/4: Rebuilding nfqws..."
|
||||
if ! rebuild_nfqws; then
|
||||
log_msg "[CRITICAL] Build failed. Aborting."
|
||||
if [[ "$mode" == "interactive" ]]; then
|
||||
read -rp "Press Enter to exit..."
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 4: Auto-test and install
|
||||
log_msg "[*] Step 4/4: Auto-testing strategies..."
|
||||
if run_autotest_pipeline; then
|
||||
log_msg "[SUCCESS] Pipeline complete: updated, built, tested, installed."
|
||||
else
|
||||
log_msg "[WARNING] Build OK, but no working strategy found."
|
||||
log_msg " You may need to adjust parameters manually."
|
||||
fi
|
||||
|
||||
if [[ "$mode" == "interactive" ]]; then
|
||||
echo ""
|
||||
print_green "=============================================="
|
||||
print_green " Full Pipeline Complete!"
|
||||
print_green " Version: $(cat "$LOCAL_VERSION_FILE" 2>/dev/null || echo $LOCAL_VERSION)"
|
||||
print_green "=============================================="
|
||||
echo ""
|
||||
systemctl status zapret --no-pager 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Auto mode (for cron/systemd timers)
|
||||
auto_mode() {
|
||||
log_msg "Auto-update started..."
|
||||
|
||||
local remote_version
|
||||
remote_version=$(check_remote_version) || {
|
||||
log_msg "Update check failed. Exiting."
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ "$remote_version" == "$LOCAL_VERSION" ]]; then
|
||||
log_msg "No update needed."
|
||||
if [[ "$need_rebuild" -eq 0 ]]; then
|
||||
log_msg "[*] No rebuild needed. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log_msg "New version found: $remote_version"
|
||||
full_pipeline auto no
|
||||
# Step 1: Update version marker
|
||||
log_msg "[*] Step 1: Updating version marker..."
|
||||
local upstream_ver
|
||||
upstream_ver=$(cat "$LOCAL_VERSION_FILE" 2>/dev/null || echo "$LOCAL_VERSION")
|
||||
echo "$upstream_ver" > "$LOCAL_VERSION_FILE"
|
||||
|
||||
# Step 2: Rebuild nfqws
|
||||
log_msg "[*] Step 2: Rebuilding nfqws..."
|
||||
if ! rebuild_nfqws; then
|
||||
log_msg "[CRITICAL] Build failed. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 3: Auto-test
|
||||
log_msg "[*] Step 3: Auto-testing strategies..."
|
||||
run_pipeline_autotest || true
|
||||
|
||||
# Step 4: Restart
|
||||
log_msg "[*] Step 4: Restarting service..."
|
||||
restart_service
|
||||
|
||||
log_msg "[SUCCESS] Full pipeline complete."
|
||||
|
||||
[[ "$mode" == "interactive" ]] && {
|
||||
echo ""
|
||||
print_green "=============================================="
|
||||
print_green " Pipeline Complete!"
|
||||
print_green " Version: $(cat "$LOCAL_VERSION_FILE" 2>/dev/null || echo "$LOCAL_VERSION")"
|
||||
print_green "=============================================="
|
||||
systemctl status zapret --no-pager 2>/dev/null || true
|
||||
}
|
||||
}
|
||||
|
||||
# Non-interactive cron mode
|
||||
auto_mode() {
|
||||
log_msg "Auto-update started..."
|
||||
log_msg "[*] Syncing upstream..."
|
||||
bash "$SCRIPT_DIR/sync_from_upstream.sh" --auto 2>&1 | tee -a "$UPDATE_LOG"
|
||||
local sync_status=${PIPESTATUS[0]}
|
||||
|
||||
if [[ "$sync_status" -ne 2 ]]; then
|
||||
log_msg "No update needed or sync failed. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log_msg "Update detected, running full pipeline..."
|
||||
rebuild_nfqws || { log_msg "[FAIL] Rebuild failed."; exit 1; }
|
||||
run_pipeline_autotest || true
|
||||
restart_service
|
||||
log_msg "Auto-update finished."
|
||||
}
|
||||
|
||||
@@ -246,48 +185,29 @@ FORCE="no"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--auto|-a)
|
||||
MODE="auto"
|
||||
shift
|
||||
;;
|
||||
--force|-f)
|
||||
FORCE="yes"
|
||||
shift
|
||||
;;
|
||||
--full-auto)
|
||||
# Fully non-interactive: even if same version, rebuild and re-test
|
||||
MODE="auto"
|
||||
FORCE="yes"
|
||||
shift
|
||||
;;
|
||||
--auto|-a) MODE="auto"; shift ;;
|
||||
--force|-f) FORCE="yes"; shift ;;
|
||||
--full-auto) MODE="auto"; FORCE="yes"; shift ;;
|
||||
--help|-h)
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
Usage: sudo ./update.sh [OPTIONS]
|
||||
|
||||
Zapret Update Pipeline: checks version → updates files → rebuilds nfqws → auto-tests → installs.
|
||||
Full pipeline: sync upstream lists/hosts/version → rebuild nfqws → test → install.
|
||||
|
||||
Options:
|
||||
--auto, -a Non-interactive mode (for cron/systemd timers)
|
||||
--auto, -a Non-interactive (for cron/systemd timers)
|
||||
--force, -f Force rebuild even if versions match
|
||||
--full-auto Same as --auto --force (rebuild + re-test always)
|
||||
--full-auto Same as --auto --force (always rebuild + re-test)
|
||||
--help, -h Show this help
|
||||
|
||||
Interactive mode (default):
|
||||
sudo ./update.sh
|
||||
|
||||
Full automation (no questions, always rebuilds and re-tests):
|
||||
sudo ./update.sh --full-auto
|
||||
|
||||
For systemd timer (daily auto-update):
|
||||
sudo ./update.sh --auto
|
||||
Examples:
|
||||
sudo ./update.sh # interactive prompt
|
||||
sudo ./update.sh --full-auto # headless, always rebuild
|
||||
sudo ./update.sh --auto # headless, only if upstream changed
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Use --help for usage."
|
||||
exit 1
|
||||
;;
|
||||
*) echo "Unknown: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user