Delete test/autoXRAYselflConfRUbrEUxhttpTEST2.sh

This commit is contained in:
xVRVx
2026-01-31 18:59:42 +03:00
committed by GitHub
parent 0dc5eba779
commit 5f5e817df0

View File

@@ -1,852 +0,0 @@
#!/bin/bash
DOMAIN=$1
vless_url=$2
if [ -z "$DOMAIN" ]; then
echo "❌ Ошибка: домен не задан."
exit 1
fi
if [ -z "$vless_url" ]; then
echo "❌ Ошибка: конфиг vless не задан."
exit 1
fi
if [[ "$vless_url" != vless://* ]]; then
echo "❌ Ошибка: Неверный формат vless-ссылки."
exit 1
fi
# Функция URL-декодинга
urldecode() {
printf '%b' "${1//%/\\x}"
}
url_body="${vless_url#vless://}"
node_name_enc="${url_body##*#}"
node_nameVL="$(urldecode "$node_name_enc")"
url_body="${url_body%%#*}"
uuidVL="${url_body%@*}"
host_port_query="${url_body#*@}"
addressVL="${host_port_query%%:*}"
restVL="${host_port_query#*:}"
portVL="${restVL%%\?*}"
query_string="${restVL#*\?}"
# Разбор параметров в ассоциативный массив
declare -A params
IFS='&' read -ra pairs <<< "$query_string"
for pair in "${pairs[@]}"; do
key="${pair%%=*}"
value="${pair#*=}"
params["$key"]="$(urldecode "$value")"
done
# Вывод:
echo "== Основное =="
echo "UUID: $uuidVL"
echo "Address: $addressVL"
echo "Port: $portVL"
echo "Node Name: $node_nameVL"
echo ""
echo "== Параметры =="
SECURITY="${params[security]}"; echo "SECURITY=$SECURITY"
TYPE="${params[type]}"; echo "TYPE=$TYPE"
headerType="${params[headerType]}"; echo "headerType=$headerType"
path_url="${params[path]}"; echo "path=$path"
host="${params[host]}"; echo "host=$host"
mode="${params[mode]}"; echo "mode=$mode"
extra="${params[extra]}"; echo "extra=$extra"
SNI="${params[sni]}"; echo "SNI=$SNI"
FP="${params[fp]}"; echo "FP=$FP"
PBK="${params[pbk]}"; echo "PBK=$PBK"
SID="${params[sid]}"; echo "SID=$SID"
SPX="${params[spx]}"; echo "SPX=$SPX"
# FLOW="${params[flow]}"; echo "FLOW=$FLOW"
echo "Обновление и установка необходимых пакетов..."
apt update && apt install -y jq dnsutils
LOCAL_IP=$(hostname -I | awk '{print $1}')
DNS_IP=$(dig +short "$DOMAIN" | grep '^[0-9]')
if [ "$LOCAL_IP" != "$DNS_IP" ]; then
echo "❌ Внимание: IP-адрес ($LOCAL_IP) не совпадает с A-записью $DOMAIN ($DNS_IP)."
echo "Правильно укажите одну A-запись для вашего домена в ДНС - $LOCAL_IP"
read -p "Продолжить на ваш страх и риск? (y/N): " choice
if [[ ! "$choice" =~ ^[Yy]$ ]]; then
echo "Выполнение скрипта прервано."
exit 1
fi
echo "Продолжение выполнения скрипта..."
fi
apt install nginx -y
systemctl enable --now nginx
apt install certbot -y
certbot certonly --webroot -w /var/www/html -d $DOMAIN -m mail@$DOMAIN --agree-tos --non-interactive --deploy-hook "systemctl reload nginx"
CONFIG_PATH="/etc/nginx/sites-available/default"
echo "✅ Записываем конфигурацию в $CONFIG_PATH для домена $DOMAIN"
bash -c "cat > $CONFIG_PATH" <<EOF
server {
server_name $DOMAIN;
listen unix:/dev/shm/nginx.sock ssl http2 proxy_protocol;
set_real_ip_from unix:;
real_ip_header proxy_protocol;
root /var/www/$DOMAIN;
index index.php index.html;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_certificate "/etc/letsencrypt/live/$DOMAIN/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/$DOMAIN/privkey.pem";
add_header profile-title "base64:YXV0b1hSQVk=";
add_header routing "happ://routing/onadd/ewogICAgIk5hbWUiOiAiYXV0b1hSQVkiLAogICAgIkdsb2JhbFByb3h5IjogInRydWUiLAogICAgIlVzZUNodW5rRmlsZXMiOiAidHJ1ZSIsCiAgICAiUmVtb3RlRE5TVHlwZSI6ICJEb0giLAogICAgIlJlbW90ZUROU0RvbWFpbiI6ICIiLAogICAgIlJlbW90ZUROU0lQIjogIiIsCiAgICAiRG9tZXN0aWNETlNUeXBlIjogIkRvSCIsCiAgICAiRG9tZXN0aWNETlNEb21haW4iOiAiIiwKICAgICJEb21lc3RpY0ROU0lQIjogIiIsCiAgICAiR2VvaXB1cmwiOiAiIiwKICAgICJHZW9zaXRldXJsIjogIiIsCiAgICAiTGFzdFVwZGF0ZWQiOiAiIiwKICAgICJEbnNIb3N0cyI6IHt9LAogICAgIk9yZGVyUm91dGluZyI6ICJibG9jay1kaXJlY3QtcHJveHkiLAogICAgIkRpcmVjdFNpdGVzIjogWwogICAgICAgICJjYXRlZ29yeS1ydSIsCiAgICAgICAgImdlb3NpdGU6cHJpdmF0ZSIKICAgIF0sCiAgICAiRGlyZWN0SXAiOiBbCiAgICAgICAgImdlb2lwOnByaXZhdGUiCiAgICBdLAogICAgIlByb3h5U2l0ZXMiOiBbXSwKICAgICJQcm94eUlwIjogW10sCiAgICAiQmxvY2tTaXRlcyI6IFsKICAgICAgICAiZ2Vvc2l0ZTpjYXRlZ29yeS1hZHMiLAogICAgICAgICJnZW9zaXRlOndpbi1zcHkiCiAgICBdLAogICAgIkJsb2NrSXAiOiBbXSwKICAgICJEb21haW5TdHJhdGVneSI6ICJJUElmTm9uTWF0Y2giLAogICAgIkZha2VETlMiOiAiZmFsc2UiCn0=";
add_header routing-enable 0;
location ~ /\.ht {
deny all;
}
}
server {
listen 80;
server_name $DOMAIN;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://\$host\$request_uri;
}
}
EOF
echo "✅ Конфигурация nginx обновлена."
systemctl restart nginx
# Создание директории
WEB_PATH="/var/www/$DOMAIN"
mkdir -p "$WEB_PATH"
# Генерируем сайт маскировку
bash -c "$(curl -L https://github.com/xVRVx/autoXRAY/raw/refs/heads/main/test/gen_page.sh)" -- $WEB_PATH
# Установка Xray
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
# Определяем директорию скрипта
#SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)
SCRIPT_DIR=/usr/local/etc/xray
# Генерируем переменные
xray_uuid_vrv=$(xray uuid)
domains=(www.theregister.com www.20minutes.fr www.dealabs.com www.manomano.fr www.caradisiac.com www.techadvisor.com www.computerworld.com teamdocs.su wikiportal.su docscenter.su www.bing.com github.com tradingview.com)
xray_dest_vrv=${domains[$RANDOM % ${#domains[@]}]}
xray_dest_vrv222=${domains[$RANDOM % ${#domains[@]}]}
key_output=$(xray x25519)
xray_privateKey_vrv=$(echo "$key_output" | awk -F': ' '/PrivateKey/ {print $2}')
xray_publicKey_vrv=$(echo "$key_output" | awk -F': ' '/Password/ {print $2}')
key_mldsa65=$(xray mldsa65)
seed_mldsa65=$(echo "$key_mldsa65" | awk -F': ' '/Seed/ {print $2}')
verify_mldsa65=$(echo "$key_mldsa65" | awk -F': ' '/Verify/ {print $2}')
xray_shortIds_vrv=$(openssl rand -hex 8)
xray_sspasw_vrv=$(openssl rand -base64 15 | tr -dc 'A-Za-z0-9' | head -c 20)
path_subpage=$(openssl rand -base64 15 | tr -dc 'A-Za-z0-9' | head -c 20)
path_xhttp=$(openssl rand -base64 15 | tr -dc 'a-z0-9' | head -c 6)
ipserv=$(hostname -I | awk '{print $1}')
# Экспортируем переменные для envsubst
export xray_uuid_vrv xray_dest_vrv xray_dest_vrv222 xray_privateKey_vrv xray_publicKey_vrv xray_shortIds_vrv xray_sspasw_vrv DOMAIN path_subpage WEB_PATH TYPE FP SNI SPX PBK SECURITY FLOW SID mode uuidVL addressVL portVL path_xhttp path_url
# Создаем JSON конфигурацию сервера
cat << 'EOF' | envsubst > "$SCRIPT_DIR/config.json"
{
"log": {
"dnsLog": false,
"loglevel": "none"
},
"dns": {
"servers": [
"https+local://8.8.4.4/dns-query",
"https+local://8.8.8.8/dns-query",
"https+local://1.1.1.1/dns-query",
"localhost"
],
"queryStrategy": "UseIPv4"
},
"inbounds": [
{
"tag": "RUbrEU",
"port": ${portVL},
"listen": "0.0.0.0",
"protocol": "vless",
"settings": {
"clients": [
{
"id": "${xray_uuid_vrv}"
}
],
"decryption": "none"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
},
"streamSettings": {
"network": "xhttp",
"xhttpSettings": {
"mode": "${mode}",
"path": "/${path_xhttp}"
},
"security": "reality",
"realitySettings": {
"show": false,
"xver": 2,
"target": "/dev/shm/nginx.sock",
"spiderX": "/",
"shortIds": [
"${xray_shortIds_vrv}"
],
"privateKey": "${xray_privateKey_vrv}",
"serverNames": [
"$DOMAIN"
],
"limitFallbackUpload": {
"afterBytes": 0,
"bytesPerSec": 65536,
"burstBytesPerSec": 0
},
"limitFallbackDownload": {
"afterBytes": 5242880,
"bytesPerSec": 262144,
"burstBytesPerSec": 2097152
}
}
}
}
],
"outbounds": [
{
"mux": {
"concurrency": -1,
"enabled": false
},
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"port": ${portVL},
"users": [
{
"id": "$uuidVL",
"encryption": "none"
}
],
"address": "$addressVL"
}
]
},
"streamSettings": {
"network": "$TYPE",
"xhttpSettings": {
"extra": {
"headers": {
},
"noGRPCHeader": false,
"scMaxEachPostBytes": 1500000,
"scMinPostsIntervalMs": 20,
"scStreamUpServerSecs": "60-240",
"xPaddingBytes": "400-800",
"xmux": {
"cMaxReuseTimes": "1000-3000",
"hKeepAlivePeriod": 0,
"hMaxRequestTimes": "400-700",
"hMaxReusableSecs": "1200-1800",
"maxConcurrency": "3-5",
"maxConnections": 0
}
},
"mode": "${mode}",
"path": "${path_url}"
},
"security": "$SECURITY",
"realitySettings": {
"show": false,
"fingerprint": "$FP",
"serverName": "$SNI",
"password": "$PBK",
"shortId": "$SID",
"mldsa65Verify": "",
"spiderX": "$SPX"
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "ForceIPv4"
}
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"routing": {
"rules": [
{
"ip": [
"geoip:private"
],
"outboundTag": "block"
},
{
"protocol": [
"bittorrent"
],
"outboundTag": "block"
},
{
"domain": [
"geosite:category-ads",
"geosite:win-spy",
"geosite:private"
],
"outboundTag": "block"
},
{
"domain": [
"testipv6.net",
"geosite:apple",
"geosite:apple-pki",
"geosite:huawei",
"geosite:xiaomi",
"geosite:category-android-app-download",
"geosite:f-droid",
"geosite:yandex",
"geosite:vk",
"geosite:microsoft",
"geosite:win-update",
"geosite:win-extra",
"geosite:google-play",
"geosite:steam",
"geosite:category-ru"
],
"outboundTag": "direct"
},
{
"inboundTag": [
"RUbrEU"
],
"outboundTag": "proxy"
}
],
"domainStrategy": "IPIfNonMatch"
}
}
EOF
# Создаем JSON конфигурацию клиента
cat << 'EOF' | envsubst > "$WEB_PATH/$path_subpage.json"
[
{
"log": {
"loglevel": "warning"
},
"dns": {
"servers": [
"https://8.8.4.4/dns-query",
"https://8.8.8.8/dns-query",
"https://1.1.1.1/dns-query"
],
"queryStrategy": "UseIPv4"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"domain": [
"geosite:category-ads",
"geosite:win-spy"
],
"outboundTag": "block"
},
{
"protocol": [
"bittorrent"
],
"outboundTag": "direct"
},
{
"domain": [
"geosite:private",
"geosite:apple",
"geosite:apple-pki",
"geosite:huawei",
"geosite:xiaomi",
"geosite:category-android-app-download",
"geosite:f-droid",
"geosite:yandex",
"geosite:vk",
"geosite:microsoft",
"geosite:win-update",
"geosite:win-extra",
"geosite:google-play",
"geosite:steam",
"geosite:category-ru"
],
"outboundTag": "direct"
},
{
"ip": [
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:!ru"
],
"outboundTag": "proxy"
},
{
"domain": [
"geosite:discord",
"geosite:youtube",
"geosite:tiktok",
"geosite:signal"
],
"outboundTag": "proxy"
}
]
},
"inbounds": [
{
"tag": "socks-in",
"protocol": "socks",
"listen": "127.0.0.1",
"port": 10808,
"settings": {
"udp": true
}
},
{
"tag": "socks-sb",
"protocol": "socks",
"listen": "127.0.0.1",
"port": 2080,
"settings": {
"udp": true
}
},
{
"tag": "http-in",
"protocol": "http",
"listen": "127.0.0.1",
"port": 10809
}
],
"outbounds": [
{
"mux": {
"concurrency": -1,
"enabled": false
},
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "$DOMAIN",
"port": ${portVL},
"users": [
{
"id": "${xray_uuid_vrv}",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "$TYPE",
"xhttpSettings": {
"extra": {
"headers": {
},
"noGRPCHeader": false,
"scMaxEachPostBytes": 1500000,
"scMinPostsIntervalMs": 20,
"scStreamUpServerSecs": "60-240",
"xPaddingBytes": "400-800",
"xmux": {
"cMaxReuseTimes": "1000-3000",
"hKeepAlivePeriod": 0,
"hMaxRequestTimes": "400-700",
"hMaxReusableSecs": "1200-1800",
"maxConcurrency": "3-5",
"maxConnections": 0
}
},
"mode": "${mode}",
"path": "/${path_xhttp}"
},
"security": "reality",
"realitySettings": {
"show": false,
"fingerprint": "chrome",
"serverName": "$DOMAIN",
"password": "${xray_publicKey_vrv}",
"shortId": "${xray_shortIds_vrv}",
"mldsa65Verify": "",
"spiderX": "/"
}
}
},
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"remarks": "🇪🇺 Bridge RU-EU"
},
{
"log": {
"loglevel": "warning"
},
"dns": {
"servers": [
"https://8.8.4.4/dns-query",
"https://8.8.8.8/dns-query",
"https://1.1.1.1/dns-query"
],
"queryStrategy": "UseIPv4"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"domain": [
"geosite:category-ads",
"geosite:win-spy"
],
"outboundTag": "block"
},
{
"protocol": [
"bittorrent"
],
"outboundTag": "direct"
},
{
"domain": [
"geosite:private",
"geosite:apple",
"geosite:apple-pki",
"geosite:huawei",
"geosite:xiaomi",
"geosite:category-android-app-download",
"geosite:f-droid",
"geosite:yandex",
"geosite:vk",
"geosite:microsoft",
"geosite:win-update",
"geosite:win-extra",
"geosite:google-play",
"geosite:steam",
"geosite:category-ru"
],
"outboundTag": "direct"
},
{
"ip": [
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:!ru"
],
"outboundTag": "proxy"
},
{
"domain": [
"geosite:discord",
"geosite:youtube",
"geosite:tiktok",
"geosite:signal"
],
"outboundTag": "proxy"
}
]
},
"inbounds": [
{
"tag": "socks-in",
"protocol": "socks",
"listen": "127.0.0.1",
"port": 10808,
"settings": {
"udp": true
}
},
{
"tag": "socks-sb",
"protocol": "socks",
"listen": "127.0.0.1",
"port": 2080,
"settings": {
"udp": true
}
},
{
"tag": "http-in",
"protocol": "http",
"listen": "127.0.0.1",
"port": 10809
}
],
"outbounds": [
{
"mux": {
"concurrency": -1,
"enabled": false
},
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "$addressVL",
"port": ${portVL},
"users": [
{
"id": "${uuidVL}",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "$TYPE",
"xhttpSettings": {
"extra": {
"headers": {
},
"noGRPCHeader": false,
"scMaxEachPostBytes": 1500000,
"scMinPostsIntervalMs": 20,
"scStreamUpServerSecs": "60-240",
"xPaddingBytes": "400-800",
"xmux": {
"cMaxReuseTimes": "1000-3000",
"hKeepAlivePeriod": 0,
"hMaxRequestTimes": "400-700",
"hMaxReusableSecs": "1200-1800",
"maxConcurrency": "3-5",
"maxConnections": 0
}
},
"mode": "${mode}",
"path": "${path_url}"
},
"security": "$SECURITY",
"realitySettings": {
"show": false,
"fingerprint": "$FP",
"serverName": "$SNI",
"password": "$PBK",
"shortId": "$SID",
"mldsa65Verify": "",
"spiderX": "$SPX"
}
}
},
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"remarks": "🇪🇺 Direct EU"
}
]
EOF
# Перезапуск Xray
echo "Перезапуск Xray..."
systemctl restart xray
echo -e "Готово!\n"
# Формирование ссылок
subPageLink="https://$DOMAIN/$path_subpage.json"
# Формирование ссылок
link1="vless://${xray_uuid_vrv}@$DOMAIN:${portVL}?security=reality&type=xhttp&headerType=&path=%2F$path_xhttp&host=&mode=${mode}&extra=%7B%22xmux%22%3A%7B%22cMaxReuseTimes%22%3A%221000-3000%22%2C%22maxConcurrency%22%3A%223-5%22%2C%22maxConnections%22%3A0%2C%22hKeepAlivePeriod%22%3A0%2C%22hMaxRequestTimes%22%3A%22400-700%22%2C%22hMaxReusableSecs%22%3A%221200-1800%22%7D%2C%22headers%22%3A%7B%7D%2C%22noGRPCHeader%22%3Afalse%2C%22xPaddingBytes%22%3A%22400-800%22%2C%22scMaxEachPostBytes%22%3A1500000%2C%22scMinPostsIntervalMs%22%3A20%2C%22scStreamUpServerSecs%22%3A%2260-240%22%7D&sni=$DOMAIN&fp=chrome&pbk=${xray_publicKey_vrv}&sid=${xray_shortIds_vrv}&spx=%2F#vlsXHTTPrtyRUbrEU"
configListLink="https://$DOMAIN/$path_subpage.html"
CONFIGS_ARRAY=(
"VLESS XHTTP Reality XTLS RUbrEU|$link1"
"Напрямую через EU|$vless_url"
)
ALL_LINKS_TEXT=""
# --- ЗАПИСЬ HEAD (СТАТИКА, МИНИФИЦИРОВАННЫЕ СТИЛИ И JS) ---
cat > "$WEB_PATH/$path_subpage.html" <<'EOF'
<!DOCTYPE html><html lang="ru"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><meta name="robots" content="noindex,nofollow"><title>AutoXRAY configs</title><script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<style>
body{font-family:monospace;background:#121212;color:#e0e0e0;padding:10px;max-width:900px;margin:0 auto}h2{color:#c3e88d;border-top:2px solid #333;padding-top:20px;margin:15px 0 10px;font-size:18px}.config-row{background:#1e1e1e;border:1px solid #333;border-radius:6px;padding:5px;display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:8px}.config-label{background:#2c2c2c;color:#82aaff;padding:6px 10px;border-radius:4px;font-weight:700;font-size:13px;white-space:nowrap;min-width:140px;text-align:center}.config-code{flex:1;white-space:nowrap;overflow-x:auto;padding:8px;background:#121212;border-radius:4px;color:#c3e88d;font-size:12px;scrollbar-width:none}.config-code::-webkit-scrollbar{display:none}.btn-action{border:1px solid #555;padding:6px 12px;border-radius:4px;cursor:pointer;font-weight:700;font-size:12px;transition:all .2s;height:32px;display:flex;align-items:center;justify-content:center}.copy-btn{background:#333;color:#e0e0e0;min-width:60px}.copy-btn:hover{background:#c3e88d;color:#121212;border-color:#c3e88d}.qr-btn{background:#333;color:#82aaff;border-color:#82aaff;min-width:40px}.qr-btn:hover{background:#82aaff;color:#121212}.btn-group{display:flex;gap:10px;margin:10px 0 20px}.btn{flex:1;background:#2c2c2c;color:#c3e88d;border:1px solid #c3e88d;padding:10px;text-align:center;border-radius:6px;text-decoration:none;font-weight:700;font-size:14px}.btn:hover{background:#c3e88d;color:#121212}.btn.download{border-color:#82aaff;color:#82aaff}.btn.download:hover{background:#82aaff;color:#121212}.btn.tg{border-color:#2AABEE;color:#2AABEE}.btn.tg:hover{background:#2AABEE;color:#fff}.modal-overlay{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.85);z-index:999;justify-content:center;align-items:center;backdrop-filter:blur(3px)}.modal-content{background:#1e1e1e;padding:20px;border-radius:10px;border:1px solid #82aaff;text-align:center}#qrcode{background:#fff;padding:10px;border-radius:6px;margin-bottom:10px}.close-modal-btn{background:#c31e1e;color:#fff;border:none;padding:8px 20px;border-radius:4px;cursor:pointer}@media(max-width:600px){.config-label{width:100%;margin-bottom:2px}.config-code{min-width:100%;order:3}.btn-action{flex:1;order:2}}
</style>
<script>
function copyText(e,t){navigator.clipboard.writeText(document.getElementById(e).innerText).then(()=>{let o=t.innerText;t.innerText="OK",t.style.cssText="background:#c3e88d;color:#121212",setTimeout(()=>{t.innerText=o,t.style.cssText=""},1500)}).catch(e=>console.error(e))}function showQR(e){let t=document.getElementById(e).innerText,o=document.getElementById("qrModal"),n=document.getElementById("qrcode");n.innerHTML="",new QRCode(n,{text:t,width:256,height:256,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.L}),o.style.display="flex"}function closeModal(){document.getElementById("qrModal").style.display="none"}window.onclick=function(e){e.target==document.getElementById("qrModal")&&closeModal()};
</script>
</head><body>
EOF
# --- ЗАПИСЬ BODY (ДИНАМИЧЕСКИЕ ДАННЫЕ) ---
cat >> "$WEB_PATH/$path_subpage.html" <<EOF
<h2>📂 Ссылка на подписку (готовый конфиг клиента с роутингом)</h2>
<div class="config-row">
<div class="config-label">Subscription</div>
<div class="config-code" id="subLink">$subPageLink</div>
<button class="btn-action copy-btn" onclick="copyText('subLink', this)">Copy</button>
<button class="btn-action qr-btn" onclick="showQR('subLink')">QR</button>
</div>
<h2>📱 Приложение HAPP (Windows/Android/iOS/MAC/Linux)</h2>
<div class="btn-group">
<a href="happ://add/$subPageLink" class="btn">⚡ Add to HAPP</a>
<a href="https://www.happ.su/main/ru" target="_blank" class="btn download">⬇️ Download App</a>
</div>
<p>Маршрутизацию нужно выключить, она тут встроенная. По умолчанию она выключена - включается, если вы пользовались сторонними сервисами.</p>
<h2>➡️ Конфиги</h2>
EOF
# Цикл генерации строк конфигов
idx=1
for item in "${CONFIGS_ARRAY[@]}"; do
title="${item%%|*}"
link="${item#*|}"
if [ -z "$ALL_LINKS_TEXT" ]; then ALL_LINKS_TEXT="$link"; else ALL_LINKS_TEXT="$ALL_LINKS_TEXT<br>$link"; fi
cat >> "$WEB_PATH/$path_subpage.html" <<EOF
<div class="config-row">
<div class="config-label">$title</div>
<div class="config-code" id="c$idx">$link</div>
<button class="btn-action copy-btn" onclick="copyText('c$idx', this)">Copy</button>
<button class="btn-action qr-btn" onclick="showQR('c$idx')">QR</button>
</div>
EOF
((idx++))
done
# Дописываем Socks5, All links и подвал
cat >> "$WEB_PATH/$path_subpage.html" <<EOF
<h2>💠 Все конфиги вместе</h2>
<div class="config-row">
<div class="config-code" id="cAll" style="max-height:60px;white-space:pre-wrap;word-break:break-all">$ALL_LINKS_TEXT</div>
<button class="btn-action copy-btn" onclick="copyText('cAll', this)">Copy ALL</button>
<button class="btn-action qr-btn" onclick="showQR('cAll')">QR</button>
</div>
<div id="qrModal" class="modal-overlay"><div class="modal-content"><div id="qrcode"></div><button class="close-modal-btn" onclick="closeModal()">Close</button></div></div>
</body></html>
EOF
echo -e "
Скопируйте подписку в специализированное приложение:
- iOS: Happ или v2RayTun или v2rayN
- Android: Happ или v2RayTun или v2rayNG
- Windows: конфиги Happ или winLoadXRAY или v2rayN
для vless v2RayTun или Throne
Ваша страничка подписки:
\033[32m$subPageLink\033[0m
Ссылка на сохраненные конфиги:
\033[32m$configListLink\033[0m
Ваш конфиг для роутера:
$link1
Открыт локальный socks5 на порту 10808, 2080 и http на 10809.
Поддержать автора: https://github.com/xVRVx/autoXRAY
"