feat(ru): full Russia/offline support (#RF)
- Add lib/download_helper.sh: proxy detection, GitHub mirrors, offline cache, tarball fallback - Rewrite install_nfqws.sh: offline bundle support, bol-van/zapret via git clone + tarball + mirror fallback - Rewrite sync_from_upstream.sh: proxy aware, --offline flag, graceful degradation - Add prepare_offline_bundle.sh: create tar.gz with sources + lists + fake bins on machine WITH internet - Add .env.example: GITHUB_PROXY, HTTPS_PROXY configuration - Update install.sh: check GitHub reachability, suggest proxy/offline, --offline flag - Update README: Russia section at top, Offline section, VPN/proxy examples, .env guide
This commit is contained in:
10
.env.example
Normal file
10
.env.example
Normal file
@@ -0,0 +1,10 @@
|
||||
# Zapret for Linux — Environment Configuration
|
||||
# Copy this to .env and set your proxy/mirror
|
||||
|
||||
# HTTP/HTTPS proxy for GitHub access in Russia
|
||||
# GITHUB_PROXY=http://proxy.local:8080
|
||||
# GITHUB_PROXY=socks5://127.0.0.1:1080
|
||||
|
||||
# Alternative: set system-wide proxy
|
||||
# HTTP_PROXY=http://proxy.local:8080
|
||||
# HTTPS_PROXY=http://proxy.local:8080
|
||||
125
README.md
125
README.md
@@ -6,6 +6,39 @@ Linux-аналог популярного репозитория [Flowseal/zapre
|
||||
|
||||
---
|
||||
|
||||
## Важно для пользователей из России
|
||||
|
||||
GitHub заблокирован в РФ. Установщик **автоматически использует** прокси/зеркала, но рекомендуется:
|
||||
|
||||
1. **Если есть VPN/прокси** — самый простой способ:
|
||||
```bash
|
||||
# Вариант A: системный прокси
|
||||
export HTTPS_PROXY=socks5://127.0.0.1:1080
|
||||
sudo ./install.sh
|
||||
|
||||
# Вариант B: proxychains
|
||||
proxychains ./install.sh
|
||||
```
|
||||
|
||||
2. **Если нет VPN на целевой машине** — подготовьте офлайн-пакет:
|
||||
```bash
|
||||
# На машине С интернетом (с VPN):
|
||||
cd /opt/zapret
|
||||
proxychains ./prepare_offline_bundle.sh
|
||||
|
||||
# Перенесите zapret-discord-youtube-linux-bundle.tar.gz
|
||||
# на целевую машину, распакуйте и:
|
||||
sudo ./install.sh --offline
|
||||
```
|
||||
|
||||
3. **Если установка падает на скачивании**:
|
||||
- Проверьте `.env.example` → создайте `.env` с `GITHUB_PROXY=...`
|
||||
- Или передайте прокси через переменную окружения
|
||||
|
||||
Подробнее: раздел **Offline / РФ** внизу.
|
||||
|
||||
---
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
```bash
|
||||
@@ -369,6 +402,98 @@ sudo ./update.sh --full-auto
|
||||
|
||||
---
|
||||
|
||||
## Работа в России / Offline-режим
|
||||
|
||||
### Почему нужен прокси или offline-бандл
|
||||
|
||||
- `github.com` заблокирован в РФ
|
||||
- Оригинальный репозиторий лежит на GitHub (Flowseal/zapret-discord-youtube)
|
||||
- Исходники `nfqws` тоже на GitHub (bol-van/zapret)
|
||||
- Наш проект на **Gitea**, поэтому клонирование работает, но внутренние скачивания (lists, hosts, bol-van/zapret) — используют GitHub
|
||||
|
||||
### Вариант 1: Установка с VPN/прокси (рекомендуется)
|
||||
|
||||
```bash
|
||||
# Системный прокси
|
||||
export HTTPS_PROXY=socks5://127.0.0.1:1080
|
||||
export HTTP_PROXY=socks5://127.0.0.1:1080
|
||||
sudo ./install.sh
|
||||
|
||||
# Или proxychains
|
||||
proxychains ./install.sh
|
||||
```
|
||||
|
||||
Также можно настроить `~/.bashrc`:
|
||||
```bash
|
||||
echo 'export HTTPS_PROXY=socks5://127.0.0.1:1080' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
### Вариант 2: Offline-бандл (без интернета на целевой машине)
|
||||
|
||||
На машине **с интернетом** (например, у друга, или с VPN на работе):
|
||||
|
||||
```bash
|
||||
cd /opt/zapret
|
||||
proxychains ./prepare_offline_bundle.sh
|
||||
```
|
||||
|
||||
Получите файл: `zapret-discord-youtube-linux-bundle.tar.gz`
|
||||
|
||||
На машине **без интернета**:
|
||||
```bash
|
||||
cd /opt
|
||||
sudo tar -xzf zapret-discord-youtube-linux-bundle.tar.gz
|
||||
cd zapret-bundle-*/installed-scripts
|
||||
sudo ./install.sh --offline
|
||||
```
|
||||
|
||||
Бандл содержит:
|
||||
- Исходники `bol-van/zapret` (для сборки nfqws)
|
||||
- `lists/*.txt` (свежие домены)
|
||||
- `.service/hosts` (статичные IP)
|
||||
- Все скрипты и стратегии
|
||||
|
||||
### Вариант 3: Установка на Windows и перенос в Linux
|
||||
|
||||
1. Скачать репозиторий на Windows (где VPN работает)
|
||||
2. Перенести на Linux через флешку/сеть
|
||||
3. На Linux запустить `sudo ./install.sh --offline`
|
||||
|
||||
### Если GitHub заблокирован — поведение скриптов
|
||||
|
||||
| Скрипт | Поведение при отсутствии интернета |
|
||||
|--------|-----------------------------------|
|
||||
| `install.sh` | Предупреждает, спрашивает, можно запустить `--offline` |
|
||||
| `sync_from_upstream.sh` | Переключается в offline-режим, использует `.bundle/` |
|
||||
| `update.sh` | Если sync не удался — сообщает и выходит |
|
||||
| `install_nfqws.sh` | Предлагает proxychains, `--offline`, или `prepare_offline_bundle.sh` |
|
||||
|
||||
### Настройка прокси через .env
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
```
|
||||
GITHUB_PROXY=socks5://127.0.0.1:1080
|
||||
```
|
||||
|
||||
Скрипты автоматически прочитают `.env` при запуске.
|
||||
|
||||
### Обновление при заблокированном GitHub
|
||||
|
||||
```bash
|
||||
# С VPN/proxy на целевой машине:
|
||||
sudo ./update.sh --full-auto
|
||||
|
||||
# Или через proxychains:
|
||||
proxychains ./update.sh --full-auto
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Лицензия
|
||||
|
||||
MIT License.
|
||||
|
||||
126
install.sh
126
install.sh
@@ -1,55 +1,120 @@
|
||||
#!/bin/bash
|
||||
# install.sh - One-shot installer: setup + build + autotest + systemd install
|
||||
# Run once after cloning the repository.
|
||||
# Works in Russia (GitHub blocked): supports HTTPS_PROXY, offline bundle, mirrors
|
||||
# Usage:
|
||||
# sudo ./install.sh # normal (with proxy/VPN)
|
||||
# sudo ./install.sh --offline # use pre-downloaded bundle
|
||||
# HTTPS_PROXY=socks5://127.0.0.1:1080 sudo ./install.sh
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/lib/functions.sh"
|
||||
source "$SCRIPT_DIR/lib/download_helper.sh"
|
||||
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
print_red "[!] This script must be run as root (or with sudo)"
|
||||
print_red "[!] Run as root (or sudo)"
|
||||
echo " sudo ./install.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for offline flag
|
||||
OFFLINE_MODE=0
|
||||
if [[ "${1:-}" == "--offline" ]]; then
|
||||
OFFLINE_MODE=1
|
||||
echo ""
|
||||
echo "[*] OFFLINE MODE: skipping network, using local bundle only"
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# Load proxy
|
||||
load_proxy
|
||||
|
||||
# Check if proxy is set
|
||||
if [[ -n "${HTTPS_PROXY:-}" ]]; then
|
||||
echo "[OK] Proxy detected: $HTTPS_PROXY"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " Zapret for Linux - Full Installer"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo " This will:"
|
||||
echo " 1. Install dependencies (git, make, gcc, curl)"
|
||||
echo " 2. Build nfqws binary from source"
|
||||
echo " 3. Run autotest to find working strategy"
|
||||
echo " 4. Install systemd service for auto-start"
|
||||
echo " 1. Sync upstream lists & strategies"
|
||||
echo " 2. Install dependencies"
|
||||
echo " 3. Build nfqws from source"
|
||||
echo " 4. Auto-test strategies"
|
||||
echo " 5. Install systemd service"
|
||||
echo ""
|
||||
read -rp "Continue? [Y/n]: " ans
|
||||
if [[ "${ans:-Y}" != [yY]* ]]; then
|
||||
echo "Aborted."
|
||||
exit 0
|
||||
|
||||
if [[ "$OFFLINE_MODE" -eq 1 ]]; then
|
||||
echo " Mode: OFFLINE (no internet required)"
|
||||
else
|
||||
echo " Mode: ONLINE (needs internet or proxy/VPN)"
|
||||
if ! curl -sfL --max-time 5 "https://github.com" >/dev/null 2>&1; then
|
||||
print_yellow "[!] GitHub NOT reachable."
|
||||
echo " Options:"
|
||||
echo " a) Set proxy: HTTPS_PROXY=socks5://127.0.0.1:1080 sudo ./install.sh"
|
||||
echo " b) Use VPN and re-run"
|
||||
echo " c) Run offline: sudo ./install.sh --offline"
|
||||
echo " d) Or prepare offline bundle first: proxychains ./prepare_offline_bundle.sh"
|
||||
echo ""
|
||||
read -rp "Continue anyway? [y/N]: " ans
|
||||
[[ "$ans" == [yY]* ]] || exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Step 0: Sync upstream lists and strategies
|
||||
bash "$SCRIPT_DIR/sync_from_upstream.sh" || true
|
||||
read -rp "Continue? [Y/n]: " ans
|
||||
[[ "${ans:-Y}" == [yY]* ]] || { echo "Aborted."; exit 0; }
|
||||
|
||||
# Step 0: Sync upstream (lists, hosts, new .bat strategies)
|
||||
if [[ "$OFFLINE_MODE" -eq 0 ]]; then
|
||||
echo ""
|
||||
echo "[*] Step 0: Syncing upstream lists/strategies..."
|
||||
bash "$SCRIPT_DIR/sync_from_upstream.sh" 2>&1 || {
|
||||
print_yellow "[!] Sync failed. Continuing with local files..."
|
||||
}
|
||||
else
|
||||
echo ""
|
||||
echo "[*] Step 0: OFFLINE — skipping upstream sync"
|
||||
fi
|
||||
|
||||
# Step 1: Setup
|
||||
echo ""
|
||||
echo "[*] Step 1/4: Running setup..."
|
||||
bash "$SCRIPT_DIR/setup.sh"
|
||||
echo "[*] Step 1/4: Installing dependencies..."
|
||||
bash "$SCRIPT_DIR/setup.sh" || {
|
||||
print_red "[!] Setup failed. Check dependencies."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Step 2: Build (done inside setup, but verify)
|
||||
# Step 2: Build nfqws
|
||||
echo ""
|
||||
echo "[*] Step 2/4: Verifying build..."
|
||||
echo "[*] Step 2/4: Building nfqws..."
|
||||
check_nfqws || {
|
||||
print_red "[!] nfqws not found after setup. Trying to rebuild..."
|
||||
bash "$SCRIPT_DIR/install_nfqws.sh"
|
||||
bash "$SCRIPT_DIR/install_nfqws.sh" || {
|
||||
print_red "[!] Build failed."
|
||||
echo ""
|
||||
echo "Common causes:"
|
||||
echo " - GitHub blocked (set HTTPS_PROXY or use --offline)"
|
||||
echo " - Missing build tools (gcc, make)"
|
||||
echo " - libnetfilter_queue not installed"
|
||||
echo ""
|
||||
echo "Try:"
|
||||
echo " HTTPS_PROXY=socks5://127.0.0.1:1080 sudo ./install.sh"
|
||||
echo " OR"
|
||||
echo " sudo ./install.sh --offline"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Step 3: Auto-test
|
||||
echo ""
|
||||
echo "[*] Step 3/4: Auto-testing strategies..."
|
||||
bash "$SCRIPT_DIR/autotest.sh" --auto
|
||||
bash "$SCRIPT_DIR/autotest.sh" --auto || {
|
||||
print_yellow "[!] Auto-test: no strategy worked automatically."
|
||||
echo " Try manually: sudo ./general.sh, sudo ./general_ALT.sh, ..."
|
||||
}
|
||||
|
||||
# Step 4: Done
|
||||
echo ""
|
||||
@@ -59,22 +124,25 @@ print_green "=============================================="
|
||||
echo ""
|
||||
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
echo "[*] Service status:"
|
||||
systemctl status zapret --no-pager 2>/dev/null || true
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " sudo systemctl status zapret # check status"
|
||||
echo " sudo systemctl stop zapret # stop"
|
||||
echo " sudo systemctl start zapret # start"
|
||||
echo " sudo systemctl restart zapret # restart"
|
||||
echo " sudo journalctl -u zapret -f # view logs"
|
||||
echo " sudo systemctl status zapret"
|
||||
echo " sudo systemctl stop zapret"
|
||||
echo " sudo systemctl start zapret"
|
||||
echo " sudo systemctl restart zapret"
|
||||
echo " sudo journalctl -u zapret -f"
|
||||
else
|
||||
echo "[*] systemd not found. To start manually:"
|
||||
echo " sudo ./general.sh (or any other strategy)"
|
||||
echo " sudo ./general.sh"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[*] To update in the future:"
|
||||
echo " sudo ./update.sh # check for new version + rebuild"
|
||||
echo " sudo ./update.sh --full-auto # force rebuild + re-test"
|
||||
echo "[*] To update in future:"
|
||||
if [[ "$OFFLINE_MODE" -eq 1 ]]; then
|
||||
echo " Re-run with VPN/proxy: sudo ./install.sh"
|
||||
else
|
||||
echo " sudo ./update.sh # auto sync + rebuild"
|
||||
echo " sudo ./update.sh --full-auto # force rebuild"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
#!/bin/bash
|
||||
# install_nfqws.sh - Build nfqws with fallback for РФ (GitHub blocked)
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BIN_DIR="$SCRIPT_DIR/bin"
|
||||
BUILD_DIR="/tmp/zapret-build-$$"
|
||||
|
||||
source "$SCRIPT_DIR/lib/download_helper.sh"
|
||||
|
||||
echo "=============================================="
|
||||
echo " Zapret Builder for Linux"
|
||||
echo " Target: nfqws binary"
|
||||
echo " Zapret Builder for Linux (v2 — РФ-ready)"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
|
||||
# Load proxy
|
||||
load_proxy
|
||||
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
DISTRO="$ID"
|
||||
@@ -19,8 +24,17 @@ else
|
||||
fi
|
||||
|
||||
echo "[*] Detected distro: $DISTRO"
|
||||
echo "[*] Installing build dependencies..."
|
||||
|
||||
# Check if offline bundle exists (pre-downloaded)
|
||||
OFFLINE_SOURCES=""
|
||||
if [[ -d "$SCRIPT_DIR/.bundle/sources/zapret" ]]; then
|
||||
OFFLINE_SOURCES="$SCRIPT_DIR/.bundle/sources/zapret"
|
||||
echo "[OK] Using offline source: $OFFLINE_SOURCES"
|
||||
else
|
||||
echo "[*] No offline bundle found. Will try to download..."
|
||||
fi
|
||||
|
||||
echo "[*] Installing build dependencies..."
|
||||
install_deps() {
|
||||
case "$DISTRO" in
|
||||
ubuntu|debian|linuxmint|pop|zorin|kubuntu|xubuntu|lubuntu)
|
||||
@@ -43,38 +57,50 @@ install_deps() {
|
||||
sudo apk add --no-cache git make gcc curl iptables nftables libnetfilter_queue-dev libcap-dev linux-headers
|
||||
;;
|
||||
*)
|
||||
echo "[!] Unknown/unsupported distro: $DISTRO"
|
||||
echo " Required packages: git, make, gcc, libnetfilter_queue (dev), curl"
|
||||
echo "[!] Unknown distro: $DISTRO"
|
||||
echo " Required: git, make, gcc, curl, iptables/nftables, libnetfilter_queue"
|
||||
read -rp "Continue anyway? [y/N]: " ans
|
||||
if [[ "$ans" != [yY]* ]]; then
|
||||
exit 1
|
||||
fi
|
||||
[[ "$ans" == [yY]* ]] || exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
install_deps
|
||||
|
||||
echo ""
|
||||
echo "[*] Cloning bol-van/zapret..."
|
||||
echo "[*] Preparing zapret sources..."
|
||||
mkdir -p "$BUILD_DIR"
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
if ! git clone --depth=1 https://github.com/bol-van/zapret.git; then
|
||||
echo "[!] Failed to clone repository. Check your internet connection."
|
||||
exit 1
|
||||
if [[ -n "$OFFLINE_SOURCES" ]]; then
|
||||
echo " Copying offline sources..."
|
||||
cp -r "$OFFLINE_SOURCES" "$BUILD_DIR/zapret"
|
||||
else
|
||||
echo "[*] Downloading bol-van/zapret (with fallback)..."
|
||||
if ! clone_repo_fallback "bol-van/zapret" "master" "$BUILD_DIR/zapret"; then
|
||||
echo ""
|
||||
echo "[CRITICAL] Failed to download zapret sources."
|
||||
echo ""
|
||||
echo "Solutions:"
|
||||
echo " 1. Set proxy: export HTTPS_PROXY=socks5://127.0.0.1:1080"
|
||||
echo " 2. Use VPN and re-run"
|
||||
echo " 3. Pre-download with prepare_offline_bundle.sh (on machine WITH internet)"
|
||||
echo " tar -xzf bundle.tar.gz"
|
||||
echo " mv bundle/* /opt/zapret"
|
||||
echo " 4. Manual: git clone https://github.com/bol-van/zapret.git"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
cd zapret
|
||||
cd "$BUILD_DIR/zapret"
|
||||
|
||||
echo "[*] Building nfqws..."
|
||||
if ! make -C nfq; then
|
||||
echo "[!] Build failed!"
|
||||
echo " Check that you have all dependencies installed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$BUILD_DIR/zapret/nfq/nfqws" ]; then
|
||||
echo "[!] Build failed: nfqws not found after compilation"
|
||||
echo "[!] nfqws binary not found after build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -88,31 +114,34 @@ FAKE_BIN_URL="https://github.com/bol-van/zapret/raw/master/files/fake"
|
||||
|
||||
for f in quic_initial_www_google_com.bin quic_initial_dbankcloud_ru.bin tls_clienthello_www_google_com.bin tls_clienthello_4pda_to.bin tls_clienthello_max_ru.bin stun.bin; do
|
||||
if curl -sfL "$FAKE_BIN_URL/$f" -o "$BIN_DIR/$f" 2>/dev/null; then
|
||||
echo " [OK] $f"
|
||||
echo " [OK] $f"
|
||||
else
|
||||
echo " [SKIP] $f (will try to find local alternatives)"
|
||||
echo " [SKIP] $f (will try local/offline)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Try offline bundle fallback for fake bins
|
||||
if [[ -d "$SCRIPT_DIR/.bundle" ]]; then
|
||||
for f in quic_initial_www_google_com.bin quic_initial_dbankcloud_ru.bin tls_clienthello_www_google_com.bin tls_clienthello_4pda_to.bin tls_clienthello_max_ru.bin stun.bin; do
|
||||
if [[ -f "$SCRIPT_DIR/.bundle/$f" ]] && [[ ! -f "$BIN_DIR/$f" ]]; then
|
||||
cp "$SCRIPT_DIR/.bundle/$f" "$BIN_DIR/$f"
|
||||
echo " [OK] $f (from offline bundle)"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[*] Setting capabilities (optional, allows running without root)..."
|
||||
echo "[*] Setting capabilities..."
|
||||
if command -v setcap >/dev/null 2>&1; then
|
||||
sudo setcap cap_net_admin,cap_net_raw+eip "$BIN_DIR/nfqws" 2>/dev/null || true
|
||||
echo " [OK] cap_net_admin,cap_net_raw set on nfqws"
|
||||
echo " [OK] cap_net_admin,cap_net_raw set"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "[*] Cleanup..."
|
||||
cd "$SCRIPT_DIR"
|
||||
rm -rf "$BUILD_DIR"
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " Build complete!"
|
||||
echo " Binary: $BIN_DIR/nfqws"
|
||||
echo " Build complete! Binary: $BIN_DIR/nfqws"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Run './service.sh' to manage strategies"
|
||||
echo " 2. Or run any './general*.sh' script directly"
|
||||
echo ""
|
||||
|
||||
154
lib/download_helper.sh
Normal file
154
lib/download_helper.sh
Normal file
@@ -0,0 +1,154 @@
|
||||
#!/bin/bash
|
||||
# download_helper.sh - Универсальный загрузчик с fallback для РФ
|
||||
# Поддерживает: HTTPS_PROXY, зеркала GitHub, локальные кэши, raw.githubusercontent.com
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"
|
||||
CACHE_DIR="$SCRIPT_DIR/.cache"
|
||||
mkdir -p "$CACHE_DIR"
|
||||
|
||||
# Read proxy from environment or .env file
|
||||
load_proxy() {
|
||||
if [[ -f "$SCRIPT_DIR/.env" ]]; then
|
||||
source "$SCRIPT_DIR/.env"
|
||||
fi
|
||||
# Priority: runtime env > .env > system env
|
||||
if [[ -n "${GITHUB_PROXY:-}" ]]; then
|
||||
HTTPS_PROXY="$GITHUB_PROXY"
|
||||
fi
|
||||
if [[ -n "${HTTPS_PROXY:-}" ]]; then
|
||||
export HTTPS_PROXY="$HTTPS_PROXY"
|
||||
fi
|
||||
if [[ -n "${HTTP_PROXY:-}" ]]; then
|
||||
export HTTP_PROXY="$HTTP_PROXY"
|
||||
fi
|
||||
}
|
||||
|
||||
# Detect available download tool
|
||||
detect_curl() {
|
||||
local cmd="curl -sfL --max-time 15 --retry 2"
|
||||
if [[ -n "${HTTPS_PROXY:-}" ]]; then
|
||||
cmd="curl -sfL --max-time 15 --retry 2 --proxy '$HTTPS_PROXY'"
|
||||
fi
|
||||
echo "$cmd"
|
||||
}
|
||||
|
||||
# Try downloading multiple sources, use cache, log failures
|
||||
download_with_fallback() {
|
||||
local output="$1"
|
||||
shift
|
||||
local sources=("$@")
|
||||
local curl_cmd
|
||||
curl_cmd=$(detect_curl)
|
||||
|
||||
load_proxy
|
||||
|
||||
# Try local cache first
|
||||
local cache_file="$CACHE_DIR/$(echo "$output" | tr '/\\' '_')"
|
||||
if [[ -f "$cache_file" ]] && [[ -s "$cache_file" ]]; then
|
||||
echo "[OK] Using cached: $(basename "$cache_file")"
|
||||
cp "$cache_file" "$output"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Try each source
|
||||
local success=0
|
||||
for src in "${sources[@]}"; do
|
||||
echo "[*] Trying: $src"
|
||||
if $curl_cmd "$src" -o "$output.tmp" 2>/dev/null; then
|
||||
if [[ -s "$output.tmp" ]]; then
|
||||
mv "$output.tmp" "$output"
|
||||
cp "$output" "$cache_file"
|
||||
echo "[OK] Downloaded from: $src"
|
||||
success=1
|
||||
break
|
||||
fi
|
||||
fi
|
||||
rm -f "$output.tmp"
|
||||
done
|
||||
|
||||
if [[ "$success" -eq 0 ]]; then
|
||||
echo "[FAIL] All download sources exhausted."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Download GitHub repository as tarball (faster than clone for read-only)
|
||||
clone_repo_fallback() {
|
||||
local repo="$1" # e.g., Flowseal/zapret-discord-youtube
|
||||
local branch="${2:-main}"
|
||||
local output_dir="$3"
|
||||
|
||||
local curl_cmd
|
||||
curl_cmd=$(detect_curl)
|
||||
|
||||
# Try git clone with proxy
|
||||
local git_env=""
|
||||
if [[ -n "${HTTPS_PROXY:-}" ]]; then
|
||||
git_env="GIT_SSL_NO_VERIFY=1"
|
||||
fi
|
||||
|
||||
# Try direct git clone
|
||||
if GIT_SSL_NO_VERIFY=1 git clone --depth=1 --single-branch --branch "$branch" "https://github.com/$repo.git" "$output_dir" 2>/dev/null; then
|
||||
echo "[OK] git clone success"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Try tarball download (often works when git blocked)
|
||||
local tarball="/tmp/repo-$$.tar.gz"
|
||||
echo "[*] Trying tarball download..."
|
||||
if $curl_cmd "https://api.github.com/repos/$repo/tarball/$branch" -o "$tarball" 2>/dev/null; then
|
||||
if [[ -s "$tarball" ]]; then
|
||||
mkdir -p "$output_dir"
|
||||
tar -xzf "$tarball" -C "$output_dir" --strip-components=1
|
||||
rm -f "$tarball"
|
||||
echo "[OK] Downloaded tarball"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
rm -f "$tarball"
|
||||
|
||||
# Try ZIP download
|
||||
local zipfile="/tmp/repo-$$.zip"
|
||||
echo "[*] Trying ZIP download..."
|
||||
if $curl_cmd "https://api.github.com/repos/$repo/zipball/$branch" -o "$zipfile" 2>/dev/null; then
|
||||
if [[ -s "$zipfile" ]]; then
|
||||
mkdir -p "$output_dir"
|
||||
unzip -q "$zipfile" -d "/tmp/repo-$$-extract"
|
||||
mv "/tmp/repo-$$-extract"/*/ "$output_dir" 2>/dev/null || true
|
||||
rm -rf "$zipfile" "/tmp/repo-$$-extract"
|
||||
echo "[OK] Downloaded ZIP"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
rm -f "$zipfile"
|
||||
|
||||
# Try mirror: gitea / gitlab / codeberg
|
||||
local mirrors=(
|
||||
"https://ghproxy.com/https://github.com/$repo.git"
|
||||
"https://hub.fastgit.xyz/$repo.git"
|
||||
)
|
||||
for mirror in "${mirrors[@]}"; do
|
||||
echo "[*] Trying mirror: $mirror"
|
||||
if GIT_SSL_NO_VERIFY=1 git clone --depth=1 --single-branch --branch "$branch" "$mirror" "$output_dir" 2>/dev/null; then
|
||||
echo "[OK] Clone from mirror"
|
||||
return 0
|
||||
fi
|
||||
rm -rf "$output_dir"
|
||||
done
|
||||
|
||||
echo "[FAIL] Cannot clone repository. Check proxy or use prepare_offline_bundle.sh"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Generic file download from remote with mirrors
|
||||
download_file_fallback() {
|
||||
local output="$1"
|
||||
local primary_url="$2"
|
||||
local mirrors=(
|
||||
"https://ghproxy.com/$primary_url"
|
||||
"https://raw.fastgit.xyz/${primary_url#https://raw.githubusercontent.com/}"
|
||||
)
|
||||
|
||||
local all_sources=("$primary_url" "${mirrors[@]}")
|
||||
download_with_fallback "$output" "${all_sources[@]}"
|
||||
}
|
||||
109
prepare_offline_bundle.sh
Normal file
109
prepare_offline_bundle.sh
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# prepare_offline_bundle.sh - Создание офлайн-пакета (с подключённым VPN)
|
||||
# Запустите с VPN: proxychains ./prepare_offline_bundle.sh
|
||||
# Получите bundle.tar.gz для переноса на компьютер без доступа к GitHub
|
||||
|
||||
set -e
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BUNDLE_DIR="/tmp/zapret-bundle-$$"
|
||||
BUNDLE_FILE="$SCRIPT_DIR/zapret-discord-youtube-linux-bundle.tar.gz"
|
||||
|
||||
echo "================================================"
|
||||
echo " Offline Bundle Preparation"
|
||||
echo " Run this WITH VPN/proxy enabled"
|
||||
echo "================================================"
|
||||
echo ""
|
||||
|
||||
# Check for GitHub access
|
||||
echo "[*] Testing GitHub connectivity..."
|
||||
if ! curl -sfL --max-time 10 "https://github.com" >/dev/null 2>&1; then
|
||||
echo "[WARN] GitHub not reachable."
|
||||
echo " Proxychains or VPN needed!"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " proxychains ./prepare_offline_bundle.sh"
|
||||
echo " HTTPS_PROXY=socks5://localhost:1080 ./prepare_offline_bundle.sh"
|
||||
read -rp "Continue anyway? [y/N]: " ans
|
||||
[[ "$ans" == [yY]* ]] || exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$BUNDLE_DIR/sources"
|
||||
mkdir -p "$BUNDLE_DIR/upstream"
|
||||
|
||||
# Step 1: Download zapret source
|
||||
echo ""
|
||||
echo "[*] Step 1/3: Downloading bol-van/zapret..."
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
git clone --depth=1 https://github.com/bol-van/zapret.git "$BUNDLE_DIR/sources/zapret"
|
||||
else
|
||||
echo " git not found. Using HTTPS:"
|
||||
curl -sfL -o "/tmp/zapret.tar.gz" "https://api.github.com/repos/bol-van/zapret/tarball/master" 2>/dev/null || {
|
||||
echo "[FAIL] Could not download zapret. Try with proxychains."
|
||||
exit 1
|
||||
}
|
||||
mkdir -p "$BUNDLE_DIR/sources/zapret"
|
||||
tar -xzf "/tmp/zapret.tar.gz" -C "$BUNDLE_DIR/sources/zapret" --strip-components=1
|
||||
rm -f "/tmp/zapret.tar.gz"
|
||||
fi
|
||||
echo " [OK] zapret source downloaded"
|
||||
|
||||
# Step 2: Download upstream Flowseal lists
|
||||
echo ""
|
||||
echo "[*] Step 2/3: Downloading upstream lists/strategies..."
|
||||
UPSTREAM_TMP="/tmp/upstream-$$"
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
git clone --depth=1 https://github.com/Flowseal/zapret-discord-youtube.git "$UPSTREAM_TMP"
|
||||
else
|
||||
(cd "$BUNDLE_DIR" && curl -sfL -o "zapret-win.tar.gz" "https://api.github.com/repos/Flowseal/zapret-discord-youtube/tarball/main" && \
|
||||
mkdir -p "$UPSTREAM_TMP" && tar -xzf zapret-win.tar.gz -C "$UPSTREAM_TMP" --strip-components=1)
|
||||
fi
|
||||
|
||||
# Copy needed files
|
||||
cp "$UPSTREAM_TMP/.service/hosts" "$BUNDLE_DIR/hosts" 2>/dev/null || true
|
||||
cp "$UPSTREAM_TMP/.service/version.txt" "$BUNDLE_DIR/version.txt" 2>/dev/null || true
|
||||
cp "$UPSTREAM_TMP/lists/"*.txt "$BUNDLE_DIR/" 2>/dev/null || true
|
||||
cp "$UPSTREAM_TMP/general"*.bat "$BUNDLE_DIR/" 2>/dev/null || true
|
||||
|
||||
echo " [OK] Upstream content downloaded: lists, bat files, hosts, version"
|
||||
|
||||
# Step 3: Download fake .bin files
|
||||
echo ""
|
||||
echo "[*] Step 3/3: Downloading fake packet binaries..."
|
||||
FAKE_URL="https://github.com/bol-van/zapret/raw/master/files/fake"
|
||||
for f in quic_initial_www_google_com.bin quic_initial_dbankcloud_ru.bin tls_clienthello_www_google_com.bin tls_clienthello_4pda_to.bin tls_clienthello_max_ru.bin stun.bin; do
|
||||
if curl -sfL "$FAKE_URL/$f" -o "$BUNDLE_DIR/$f" 2>/dev/null; then
|
||||
echo " [OK] $f"
|
||||
else
|
||||
echo " [SKIP] $f (will build at install time)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Package everything
|
||||
echo ""
|
||||
echo "[*] Packaging..."
|
||||
mkdir -p "$BUNDLE_DIR/installed-scripts"
|
||||
cp "$SCRIPT_DIR"/*.sh "$BUNDLE_DIR/installed-scripts/" 2>/dev/null || true
|
||||
cp "$SCRIPT_DIR/lib/"*.sh "$BUNDLE_DIR/installed-scripts/lib/" 2>/dev/null || true
|
||||
cp "$SCRIPT_DIR/strategies/"*.conf "$BUNDLE_DIR/installed-scripts/strategies/" 2>/dev/null || true
|
||||
cp "$SCRIPT_DIR/systemd/"*.service "$BUNDLE_DIR/installed-scripts/systemd/" 2>/dev/null || true
|
||||
cp "$SCRIPT_DIR/systemd/"*.timer "$BUNDLE_DIR/installed-scripts/systemd/" 2>/dev/null || true
|
||||
|
||||
tar -czf "$BUNDLE_FILE" -C "/tmp" "$(basename "$BUNDLE_DIR")"
|
||||
rm -rf "$BUNDLE_DIR" "$UPSTREAM_TMP"
|
||||
|
||||
echo ""
|
||||
echo "================================================"
|
||||
echo " BUNDLE READY"
|
||||
echo " File: $BUNDLE_FILE"
|
||||
echo "================================================"
|
||||
echo ""
|
||||
echo "To install on target machine without internet:"
|
||||
echo " cd /opt"
|
||||
echo " tar -xzf zapret-discord-youtube-linux-bundle.tar.gz"
|
||||
echo " cd zapret-bundle-*/installed-scripts"
|
||||
echo " sudo ./install.sh --offline"
|
||||
echo ""
|
||||
echo "Or if you have proxy on target:"
|
||||
echo " export HTTP_PROXY=http://proxy:port"
|
||||
echo " sudo ./install.sh"
|
||||
echo ""
|
||||
@@ -1,27 +1,56 @@
|
||||
#!/bin/bash
|
||||
# sync_from_upstream.sh - Merge upstream Flowseal changes into Linux version
|
||||
# Handles: lists, .service/hosts, .service/version, auto-detection of NEW .bat strategies
|
||||
# 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"
|
||||
|
||||
log_msg() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||
}
|
||||
# Load proxy settings
|
||||
load_proxy
|
||||
|
||||
# Clone upstream with 60s timeout
|
||||
log_msg "[*] Cloning upstream Flowseal/zapret-discord-youtube..."
|
||||
if ! git clone --depth=1 --single-branch --branch main "$UPSTREAM_REPO" "$TMP_DIR" 2>/dev/null; then
|
||||
log_msg "[FAIL] Could not clone upstream. Check internet/DNS."
|
||||
rm -rf "$TMP_DIR"
|
||||
exit 1
|
||||
# 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
|
||||
@@ -30,36 +59,38 @@ 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"
|
||||
|
||||
log_msg "Local version: $LOCAL_VER"
|
||||
log_msg "Upstream version: $UPSTREAM_VER"
|
||||
echo "Local version: $LOCAL_VER"
|
||||
echo "Upstream version: $UPSTREAM_VER"
|
||||
|
||||
REBUILD_FLAG=0
|
||||
if [[ "$UPSTREAM_VER" != "$LOCAL_VER" ]]; then
|
||||
REBUILD_FLAG=1
|
||||
log_msg "[*] Version changed: $LOCAL_VER → $UPSTREAM_VER"
|
||||
echo "[*] Version changed: $LOCAL_VER → $UPSTREAM_VER"
|
||||
fi
|
||||
|
||||
# ======================
|
||||
# MERGE LISTS
|
||||
# ======================
|
||||
log_msg "[*] Merging upstream lists..."
|
||||
echo "[*] Merging upstream lists..."
|
||||
merge_list() {
|
||||
local file="$1"
|
||||
local src="$TMP_DIR/lists/$file"
|
||||
local dst="$SCRIPT_DIR/lists/$file"
|
||||
if [[ ! -f "$src" ]]; then
|
||||
log_msg " [SKIP] Upstream missing: lists/$file"
|
||||
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" "$dst"
|
||||
log_msg " [OK] lists/$file"
|
||||
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"
|
||||
|
||||
# Only update ipset-all if placeholder or enabled
|
||||
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
|
||||
@@ -67,25 +98,30 @@ fi
|
||||
# ======================
|
||||
# MERGE .service/hosts + version
|
||||
# ======================
|
||||
log_msg "[*] Merging .service files..."
|
||||
if [[ -f "$TMP_DIR/.service/hosts" ]]; then
|
||||
echo "[*] Merging .service files..."
|
||||
|
||||
if [[ -d "$TMP_DIR" ]] && [[ -f "$TMP_DIR/.service/hosts" ]]; then
|
||||
cp "$TMP_DIR/.service/hosts" "$SCRIPT_DIR/.service/hosts"
|
||||
log_msg " [OK] .service/hosts (GitHub, Telegram, Discord static IPs)"
|
||||
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 [[ -f "$TMP_DIR/.service/version.txt" ]]; then
|
||||
if [[ -d "$TMP_DIR" ]] && [[ -f "$TMP_DIR/.service/version.txt" ]]; then
|
||||
echo "$UPSTREAM_VER-linux" > "$LOCAL_VERSION_FILE"
|
||||
log_msg " [OK] .service/version.txt → $UPSTREAM_VER-linux"
|
||||
echo " [OK] .service/version.txt → $UPSTREAM_VER-linux"
|
||||
REBUILD_FLAG=1
|
||||
fi
|
||||
|
||||
# ======================
|
||||
# PARSE NEW .bat STRATEGIES → .conf
|
||||
# ======================
|
||||
log_msg "[*] Checking for new upstream strategies..."
|
||||
NEW_COUNT=0
|
||||
UPDATE_COUNT=0
|
||||
echo "[*] Checking for new upstream strategies..."
|
||||
|
||||
parse_bat_to_conf() {
|
||||
local src="$1"
|
||||
@@ -96,125 +132,95 @@ parse_bat_to_conf() {
|
||||
[[ -z "$name" ]] && name="general"
|
||||
local conf_name="$STRATEGIES_DIR/${name}.conf"
|
||||
|
||||
# Extract winws arguments after "winws.exe ...parameters..."
|
||||
# Step 1: Find all lines after winws.exe, clean line continuations (^) and quotes
|
||||
local raw_args
|
||||
raw_args=$(sed -n '/winws\.exe/I,${ p }' "$src" | \
|
||||
sed 's/\^//g' | \
|
||||
tr '\n' ' ' | \
|
||||
sed -E 's/start[^"]*"[^"]*"[^"]*"[^"]*"//i; s/ *\/min //i')
|
||||
# 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')
|
||||
|
||||
# Step 2: Remove the winws.exe binary path and WF filters (Windows-only --wf-*)
|
||||
raw_args=$(echo "$raw_args" | sed -E 's/[^ ]*winws\.exe//i; s/--wf-tcp=[^ ]+//; s/--wf-udp=[^ ]+//')
|
||||
|
||||
# Step 3: Fix Windows paths to placeholders
|
||||
# "...bin\file.bin" → %BIN%/file.bin
|
||||
raw_args=$(echo "$raw_args" | sed -E 's/"%BIN%\\([^"]*)"/\%BIN%\/\1/g')
|
||||
raw_args=$(echo "$raw_args" | sed -E 's/%BIN%\\([^ ]*)/\%BIN%\/\1/g')
|
||||
raw_args=$(echo "$raw_args" | sed -E 's/"%LISTS%\\([^"]*)"/\%LISTS%\/\1/g')
|
||||
raw_args=$(echo "$raw_args" | sed -E 's/%LISTS%\\([^ ]*)/\%LISTS%\/\1/g')
|
||||
|
||||
# Remove stray quotes
|
||||
raw_args=$(echo "$raw_args" | tr -d '\"')
|
||||
|
||||
# Step 4: Replace Windows variables with Linux placeholders
|
||||
# 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')
|
||||
|
||||
# Step 5: Split by --new into RULE1..9
|
||||
local rule_num=1
|
||||
local current_rule=""
|
||||
|
||||
# Convert --new separated rules into lines
|
||||
# Split by --new into RULE1=... RULEN=...
|
||||
echo "# Strategy: $name" > "$conf_name"
|
||||
echo "# Auto-generated from upstream: $name_raw.bat" >> "$conf_name"
|
||||
echo "# Version: $UPSTREAM_VER" >> "$conf_name"
|
||||
echo "# Auto-converted from upstream: $name_raw.bat" >> "$conf_name"
|
||||
echo "# Version: ${UPSTREAM_VER:-unknown}" >> "$conf_name"
|
||||
echo "" >> "$conf_name"
|
||||
|
||||
# Use awk to split by --new
|
||||
echo "$raw_args" | awk '{
|
||||
split($0, parts, " --new");
|
||||
for (i=1; i<=length(parts); i++) {
|
||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", parts[i]);
|
||||
if (parts[i] != "") {
|
||||
print "RULE" i "=" parts[i];
|
||||
}
|
||||
}
|
||||
}' >> "$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}')"
|
||||
}
|
||||
|
||||
for bat in "$TMP_DIR"/general*.bat; do
|
||||
[[ -f "$bat" ]] || continue
|
||||
bat_name=$(basename "$bat")
|
||||
[[ "$bat_name" == "service.bat" ]] && continue
|
||||
# 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
|
||||
|
||||
# Normalize conf name
|
||||
strategy_name=$(echo "$bat_name" | sed -E 's/^general[[:space:]]*//; s/\(|\)//g; s/\.bat$//')
|
||||
[[ -z "$strategy_name" ]] && strategy_name="general"
|
||||
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"
|
||||
|
||||
conf_file="$STRATEGIES_DIR/${strategy_name}.conf"
|
||||
|
||||
if [[ -f "$conf_file" ]]; then
|
||||
# Check if upstream strategy changed (compare hash)
|
||||
remote_hash=$(md5sum "$bat" 2>/dev/null | awk '{print $1}')
|
||||
local_hash=$(md5sum "$conf_file" 2>/dev/null | awk '{print $1}')
|
||||
if [[ "$remote_hash" != "$(grep '^# hash:' "$conf_file" 2>/dev/null | awk '{print $3}')" ]]; then
|
||||
log_msg " [CHANGED] Strategy updated: $bat_name → $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
|
||||
else
|
||||
log_msg " [NEW] Detected upstream strategy: $bat_name → $strategy_name.conf"
|
||||
parse_bat_to_conf "$bat"
|
||||
NEW_COUNT=$((NEW_COUNT + 1))
|
||||
REBUILD_FLAG=1
|
||||
fi
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ $NEW_COUNT -gt 0 ]]; then
|
||||
log_msg " [INFO] $NEW_COUNT new strategy(ies) auto-converted."
|
||||
log_msg " [WARN] Please verify new strategies manually before using."
|
||||
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
|
||||
log_msg " [INFO] $UPDATE_COUNT strategy(ies) updated from upstream."
|
||||
echo " [INFO] $UPDATE_COUNT strategy(ies) updated from upstream."
|
||||
fi
|
||||
if [[ $NEW_COUNT -eq 0 ]] && [[ $UPDATE_COUNT -eq 0 ]]; then
|
||||
log_msg " [OK] All strategies up to date."
|
||||
echo " [OK] All strategies up to date."
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
# Cleanup upstream clone
|
||||
rm -rf "$TMP_DIR"
|
||||
|
||||
# ======================
|
||||
# CHECK if general*.sh wrappers exist for all .conf
|
||||
# ENSURE WRAPPERS
|
||||
# ======================
|
||||
log_msg "[*] Checking strategy wrappers (general*.sh)..."
|
||||
for conf in "$STRATEGIES_DIR"/*.conf; do
|
||||
[[ -f "$conf" ]] || continue
|
||||
local name
|
||||
name=$(basename "$conf" .conf)
|
||||
local wrapper="$SCRIPT_DIR/general_${name}.sh"
|
||||
if [[ ! -f "$wrapper" ]]; then
|
||||
# Create wrapper
|
||||
cat > "$wrapper" <<EOF
|
||||
#!/bin/bash
|
||||
# Auto-generated wrapper for strategy: $name
|
||||
SCRIPT_DIR="\$(cd "\$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
|
||||
exec "\$SCRIPT_DIR/run_strategy.sh" "$name"
|
||||
EOF
|
||||
chmod +x "$wrapper"
|
||||
log_msg " [OK] Created wrapper: $(basename "$wrapper")"
|
||||
fi
|
||||
done
|
||||
echo "[*] Checking strategy wrappers (general*.sh)..."
|
||||
bash "$SCRIPT_DIR/ensure_wrappers.sh" 2>/dev/null || true
|
||||
|
||||
# ======================
|
||||
# REPORT
|
||||
# ======================
|
||||
log_msg "[*] Sync complete."
|
||||
echo "[*] Sync complete."
|
||||
if [[ "$REBUILD_FLAG" -eq 1 ]]; then
|
||||
log_msg "[*] REBUILD NEEDED: run ./update.sh or ./install.sh"
|
||||
echo "[*] REBUILD NEEDED: run ./update.sh or ./install.sh"
|
||||
exit 2
|
||||
else
|
||||
log_msg "[*] No changes detected."
|
||||
echo "[*] No changes detected."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user