Files
zapret-discord-youtube-linux/sync_from_upstream.sh
OpenCode Agent 62ec6c5749 fix(core): critical fixes for service menu, autotest, strategy runner, dependencies
- service.sh: split service_remove into internal (no prompts) and interactive
  versions to prevent 'eternal wait' when installing new strategy.
  Install now calls service_remove_internal > /dev/null instead of service_remove.
  Also filter strategy list to general*.sh only to avoid clutter.
  Systemd ExecStart now points to run_strategy.sh <name> consistently.

- run_strategy.sh: add SIGTERM/SIGINT trap cleanup_strategy() that kills nfqws
  and cleans up firewall. Prevents stale nfqws/firewall rules after autotest kill.
  Also handles nfqws exit gracefully with final cleanup.

- autotest.sh: rewritten to test strategies by config name (not wrapper filename).
  Stop now sends SIGTERM to wrapper (which triggers trap cleanup) instead of
  bare kill. Added extra sleep after stop to let trap fire.
  Auto-install ExecStart fixed to run_strategy.sh <strategy>.

- setup.sh: added libmnl-dev and zlib1g-dev to Ubuntu/Debian dependency install
  to prevent build failures (missing libmnl/libmnl.h and zlib.h).

- general*.sh: removed UTF-8 BOM (0xEF 0xBB 0xBF) that caused 'exec format error'
  when running scripts on Linux. All 19 wrappers cleaned.

- ensure_wrappers.sh: always rewrite wrappers to ensure no stale BOM or paths.

Fixes: eternal wait on menu option 1, nfqws build failure, stale processes after test.
2026-05-10 22:47:48 +04:00

227 lines
7.1 KiB
Bash
Executable File

#!/bin/bash
# sync_from_upstream.sh - Merge upstream Flowseal changes into Linux version
# Handles: proxy (HTTPS_PROXY), offline bundle, lists, .service/hosts, .service/version
# Works even if GitHub blocked (with proxy or offline bundle)
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib/download_helper.sh"
UPSTREAM_REPO="https://github.com/Flowseal/zapret-discord-youtube.git"
TMP_DIR="/tmp/zapret-upstream-$$"
LOCAL_VERSION_FILE="$SCRIPT_DIR/.service/version.txt"
STRATEGIES_DIR="$SCRIPT_DIR/strategies"
echo ""
echo "=============================================="
echo " Upstream Sync"
echo " Source: $UPSTREAM_REPO"
echo "=============================================="
echo ""
mkdir -p "$STRATEGIES_DIR"
# Load proxy settings
load_proxy
# Detect if offline mode requested
OFFLINE_MODE=0
if [[ "${1:-}" == "--offline" ]]; then
OFFLINE_MODE=1
echo "[*] OFFLINE MODE: skipping network, using local files only"
fi
REBUILD_FLAG=0
UPDATE_COUNT=0
NEW_COUNT=0
# Attempt to clone/update upstream
if [[ "$OFFLINE_MODE" -eq 0 ]]; then
echo "[*] Cloning upstream (with fallback)..."
if ! clone_repo_fallback "Flowseal/zapret-discord-youtube" "main" "$TMP_DIR"; then
echo ""
echo "[WARN] Cannot reach upstream GitHub."
echo " Check proxy, VPN, or prepare_offline_bundle.sh"
echo ""
read -rp "Continue in offline mode (skip sync)? [Y/n]: " ans
if [[ "${ans:-Y}" == [yY]* ]]; then
OFFLINE_MODE=1
else
exit 1
fi
fi
fi
# Read versions
LOCAL_VER=$(cat "$LOCAL_VERSION_FILE" 2>/dev/null | tr -d '[:space:]')
UPSTREAM_VER=$(cat "$TMP_DIR/.service/version.txt" 2>/dev/null | tr -d '[:space:]')
[[ -z "$LOCAL_VER" ]] && LOCAL_VER="unknown"
[[ -z "$UPSTREAM_VER" ]] && UPSTREAM_VER="unknown"
echo "Local version: $LOCAL_VER"
echo "Upstream version: $UPSTREAM_VER"
if [[ "$UPSTREAM_VER" != "$LOCAL_VER" ]]; then
REBUILD_FLAG=1
echo "[*] Version changed: $LOCAL_VER$UPSTREAM_VER"
fi
# ======================
# MERGE LISTS
# ======================
echo "[*] Merging upstream lists..."
merge_list() {
local file="$1"
local src=""
if [[ -d "$TMP_DIR" ]] && [[ -f "$TMP_DIR/lists/$file" ]]; then
src="$TMP_DIR/lists/$file"
elif [[ -f "$SCRIPT_DIR/.bundle/$file" ]]; then
src="$SCRIPT_DIR/.bundle/$file"
echo " [CACHED] lists/$file (from offline bundle)"
else
echo " [SKIP] lists/$file (not available)"
return
fi
cp "$src" "$SCRIPT_DIR/lists/$file"
echo " [OK] lists/$file"
}
merge_list "list-general.txt"
merge_list "list-google.txt"
merge_list "list-exclude.txt"
merge_list "ipset-exclude.txt"
if [[ -f "$SCRIPT_DIR/.service/ipset_filter_loaded" ]] || [[ -f "$SCRIPT_DIR/.service/ipset_filter_any" ]]; then
merge_list "ipset-all.txt" 2>/dev/null || true
fi
# ======================
# MERGE .service/hosts + version
# ======================
echo "[*] Merging .service files..."
if [[ -d "$TMP_DIR" ]] && [[ -f "$TMP_DIR/.service/hosts" ]]; then
cp "$TMP_DIR/.service/hosts" "$SCRIPT_DIR/.service/hosts"
echo " [OK] .service/hosts (GitHub, Telegram, Discord static IPs)"
REBUILD_FLAG=1
elif [[ -f "$SCRIPT_DIR/.bundle/hosts" ]]; then
cp "$SCRIPT_DIR/.bundle/hosts" "$SCRIPT_DIR/.service/hosts"
echo " [OK] .service/hosts (from offline bundle)"
REBUILD_FLAG=1
else
echo " [SKIP] .service/hosts (not available)"
fi
if [[ -d "$TMP_DIR" ]] && [[ -f "$TMP_DIR/.service/version.txt" ]]; then
echo "$UPSTREAM_VER-linux" > "$LOCAL_VERSION_FILE"
echo " [OK] .service/version.txt → $UPSTREAM_VER-linux"
REBUILD_FLAG=1
fi
# ======================
# PARSE NEW .bat STRATEGIES → .conf
# ======================
echo "[*] Checking for new upstream strategies..."
parse_bat_to_conf() {
local src="$1"
local name_raw
name_raw=$(basename "$src" .bat)
local name
name=$(echo "$name_raw" | sed -E 's/general[[:space:]]*//; s/\(|\)//g; s/^[[:space:]]+|[[:space:]]+$//g; s/ /_/g')
[[ -z "$name" ]] && name="general"
local conf_name="$STRATEGIES_DIR/${name}.conf"
local raw_args
# Join lines ending with ^, find winws.exe block
raw_args=$(cat "$src" | tr '\n' ' ' | \
sed 's/\^/ /g' | \
sed -E 's/start[^"]*"[^"]*"[^"]*"[^"*]*"//i; s/ *\/min //i; s/\^//g')
# Extract after winws.exe
raw_args=$(echo "$raw_args" | sed -n 's/.*winws\.exe[^"]*"\?//pi')
# Remove --wf-* (Windows-only)
raw_args=$(echo "$raw_args" | sed -E 's/--wf-tcp=[^ "]+//g; s/--wf-udp=[^ "]+//g')
# Normalize paths
raw_args=$(echo "$raw_args" | sed 's|\\|/|g')
raw_args=$(echo "$raw_args" | sed -E 's|"?%BIN%/|"%BIN%/|g; s|"?%LISTS%/|"%LISTS%/|g')
# Replace vars
raw_args=$(echo "$raw_args" | sed 's/%GameFilterTCP%/%GAME_TCP%/g; s/%GameFilterUDP%/%GAME_UDP%/g')
# Split by --new into RULE1=... RULEN=...
echo "# Strategy: $name" > "$conf_name"
echo "# Auto-converted from upstream: $name_raw.bat" >> "$conf_name"
echo "# Version: ${UPSTREAM_VER:-unknown}" >> "$conf_name"
echo "" >> "$conf_name"
local i=1
local rule
while IFS= read -r rule; do
rule=$(echo "$rule" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
[[ -z "$rule" ]] && continue
echo "RULE${i}=${rule}" >> "$conf_name"
i=$((i + 1))
done <<< "$(echo "$raw_args" | awk 'BEGIN{RS="--new"; ORS="\n"}{print}')"
}
# Only scan if upstream cloned
if [[ -d "$TMP_DIR" ]]; then
for bat in "$TMP_DIR"/general*.bat; do
[[ -f "$bat" ]] || continue
bat_name=$(basename "$bat")
[[ "$bat_name" == "service.bat" ]] && continue
strategy_name=$(echo "$bat_name" | sed -E 's/^general[[:space:]]*//; s/\(|\)//g; s/\.bat$//; s/ /_/g')
[[ -z "$strategy_name" ]] && strategy_name="general"
conf_file="$STRATEGIES_DIR/${strategy_name}.conf"
if [[ -f "$conf_file" ]]; then
# Simple update: mark for manual review
parse_bat_to_conf "$bat"
UPDATE_COUNT=$((UPDATE_COUNT + 1))
echo " [CHANGED] Strategy updated: $bat_name$strategy_name.conf"
REBUILD_FLAG=1
else
parse_bat_to_conf "$bat"
NEW_COUNT=$((NEW_COUNT + 1))
echo " [NEW] Strategy detected: $bat_name$strategy_name.conf"
REBUILD_FLAG=1
fi
done
fi
if [[ $NEW_COUNT -gt 0 ]]; then
echo " [INFO] $NEW_COUNT new strategy(ies) auto-converted."
echo " [WARN] Please verify new strategies manually before using."
fi
if [[ $UPDATE_COUNT -gt 0 ]]; then
echo " [INFO] $UPDATE_COUNT strategy(ies) updated from upstream."
fi
if [[ $NEW_COUNT -eq 0 ]] && [[ $UPDATE_COUNT -eq 0 ]]; then
echo " [OK] All strategies up to date."
fi
# Cleanup upstream clone
rm -rf "$TMP_DIR"
# ======================
# ENSURE WRAPPERS
# ======================
echo "[*] Checking strategy wrappers (general*.sh)..."
bash "$SCRIPT_DIR/ensure_wrappers.sh" 2>/dev/null || true
# ======================
# REPORT
# ======================
echo "[*] Sync complete."
if [[ "$REBUILD_FLAG" -eq 1 ]]; then
echo "[*] REBUILD NEEDED: run ./update.sh or ./install.sh"
exit 2
else
echo "[*] No changes detected."
exit 0
fi