From 4ad1ac497e0c547c1b186220b4cb7f295d06e94c Mon Sep 17 00:00:00 2001 From: anten-ka Date: Fri, 20 Mar 2026 16:42:15 +0300 Subject: [PATCH] v2.1: 3X-UI submenu with JSON guide and port, toggle clients with ok confirm and container restart Made-with: Cursor --- warp.sh | 244 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 168 insertions(+), 76 deletions(-) diff --git a/warp.sh b/warp.sh index dae5f5c..de0524d 100644 --- a/warp.sh +++ b/warp.sh @@ -2,12 +2,12 @@ set -o pipefail # ══════════════════════════════════════════════════════════════ -# WARP Manager v2.0 — Unified 3X-UI + AmneziaWG +# WARP Manager v2.1 — Unified 3X-UI + AmneziaWG # Cloudflare WARP · Telegram Bot · Auto-detect mode # Channel: https://www.youtube.com/@antenkaru # ══════════════════════════════════════════════════════════════ -WARP_VERSION="2.0" +WARP_VERSION="2.1" WARP_DIR="/etc/warp-manager" WARP_CONF="$WARP_DIR/config" WARP_LOG="/var/log/warp-manager.log" @@ -283,7 +283,7 @@ install_warp_3xui() { else echo -e "${YELLOW} ⚠ Подключение не подтверждено.${NC}" fi - echo -e "\n${WHITE}Настройки SOCKS5 и JSON: пункт меню ${YELLOW}6${NC}" + echo -e "\n${WHITE}Настройка 3X-UI: п.${YELLOW}6${WHITE} (JSON, инструкция, порт)${NC}" read -p "Enter..." } @@ -341,27 +341,105 @@ change_port_3xui() { log_action "3XUI PORT: ${np}"; read -p "Enter..." } -show_xui_json() { - clear; echo -e "\n${CYAN}━━━ Конфигурация для 3X-UI ━━━${NC}\n" - echo -e "${GREEN}── Outbound ──${NC}\n" +show_3xui_menu() { + while true; do + clear + echo -e "\n${CYAN}━━━ Настройки SOCKS5 для 3X-UI ━━━${NC}\n" + echo -e " ${WHITE}SOCKS5-прокси:${NC} ${GREEN}127.0.0.1:${SOCKS_PORT}${NC}" + if is_warp_running_3xui; then + echo -e " ${WHITE}WARP IP:${NC} ${GREEN}$(get_warp_ip_3xui)${NC}" + fi + echo -e "\n 1) 📋 Показать JSON Outbound и Routing" + echo -e " 2) 📖 Пошаговая инструкция для 3X-UI" + echo -e " 3) 🔧 Изменить порт SOCKS5 (сейчас: ${SOCKS_PORT})" + echo -e " 0) ⬅️ Назад" + echo "" + read -p " Выбор: " ch + case $ch in + 1) show_3xui_json ;; + 2) show_3xui_guide ;; + 3) change_port_3xui ;; + 0) return ;; + esac + done +} + +show_3xui_json() { + clear; echo -e "\n${CYAN}━━━ JSON для 3X-UI ━━━${NC}\n" + echo -e "${WHITE}Добавьте в ${YELLOW}Xray Settings → Outbounds${WHITE} (JSON):${NC}\n" + echo -e "${GREEN}── 1. Outbound (добавить в массив outbounds) ──${NC}\n" cat < " answer - [ -z "$answer" ] || [ "$answer" = "0" ] && return - - local changed=0 - if [ "$answer" = "all" ]; then - AWG_SELECTED_IPS=("${AWG_CLIENT_IPS[@]}") - changed=1 - elif [ "$answer" = "none" ]; then - AWG_SELECTED_IPS=() - changed=1 - else - IFS=',' read -ra parts <<< "$answer" - for p in "${parts[@]}"; do - p=$(echo "$p" | xargs) - if [[ "$p" =~ ^[0-9]+$ ]] && (( p >= 1 && p <= ${#AWG_CLIENT_IPS[@]} )); then - local ip="${AWG_CLIENT_IPS[$((p-1))]}" - if [[ "$warp_set" == *" $ip "* ]]; then - local -a tmp=() - for eip in "${AWG_SELECTED_IPS[@]}"; do - [ "$eip" != "$ip" ] && tmp+=("$eip") - done - AWG_SELECTED_IPS=("${tmp[@]+"${tmp[@]}"}") - else - AWG_SELECTED_IPS+=("$ip") - fi - changed=1 + case "$answer" in + 0|"") + return ;; + all) + pending_ips=("${AWG_CLIENT_IPS[@]}") ;; + none) + pending_ips=() ;; + ok) + AWG_SELECTED_IPS=("${pending_ips[@]+"${pending_ips[@]}"}") + echo -e "\n${YELLOW} Применяю правила...${NC}" + awg_save_clients; awg_apply_rules; awg_patch_start_sh + echo -e "${GREEN} ✓ Правила сохранены${NC}" + echo -e "\n${YELLOW} Перезапуск контейнера ${CONTAINER}...${NC}" + docker restart "$CONTAINER" >/dev/null 2>&1 + local a=0 + while [ "$a" -lt 15 ]; do + docker exec "$CONTAINER" sh -c "true" 2>/dev/null && break + sleep 1; ((a++)) + done + if docker exec "$CONTAINER" sh -c "true" 2>/dev/null; then + echo -e "${GREEN} ✓ Контейнер перезапущен${NC}" + else + echo -e "${RED} ⚠ Контейнер не отвечает${NC}" fi - done - fi - - if [ "$changed" -eq 1 ]; then - awg_save_clients; awg_apply_rules; awg_patch_start_sh - log_action "AWG TOGGLE: ${#AWG_SELECTED_IPS[@]} clients in WARP" - fi + log_action "AWG CLIENTS APPLIED: ${#AWG_SELECTED_IPS[@]} in WARP, container restarted" + read -p " Enter..."; return ;; + *) + IFS=',' read -ra parts <<< "$answer" + for p in "${parts[@]}"; do + p=$(echo "$p" | xargs) + if [[ "$p" =~ ^[0-9]+$ ]] && (( p >= 1 && p <= ${#AWG_CLIENT_IPS[@]} )); then + local ip="${AWG_CLIENT_IPS[$((p-1))]}" + if [[ "$pending_set" == *" $ip "* ]]; then + local -a tmp=() + for eip in "${pending_ips[@]}"; do + [ "$eip" != "$ip" ] && tmp+=("$eip") + done + pending_ips=("${tmp[@]+"${tmp[@]}"}") + else + pending_ips+=("$ip") + fi + fi + done ;; + esac done } @@ -1080,8 +1173,7 @@ kbd_main_awg() { [{"text":"📊 Статус","callback_data":"st"},{"text":"🌐 IP","callback_data":"ip"}], [{"text":"▶️ Запустить","callback_data":"on"},{"text":"⏹ Остановить","callback_data":"off"}], [{"text":"🔑 Перевыпуск","callback_data":"rk"}], - [{"text":"👥 Клиенты WARP","callback_data":"cl"}], - [{"text":"🔄 Контейнер","callback_data":"rc"}], + [{"text":"👥 Клиенты WARP","callback_data":"cl"},{"text":"🔄 Контейнер","callback_data":"rc"}], [{"text":"💻 Система","callback_data":"sys"}], [{"text":"🏢 Хостинг","callback_data":"promo"}] ] @@ -1274,7 +1366,10 @@ bot_handle_callback() { fi fi awg_save_clients; awg_apply_rules; awg_patch_start_sh - log_action "BOT AWG TOGGLE: ${#AWG_SELECTED_IPS[@]}" + tg_edit "$chat_id" "$msg_id" "⏳ Применяю и перезапускаю контейнер..." "" + docker restart "$CONTAINER" >/dev/null 2>&1 + local _a=0; while [ "$_a" -lt 15 ]; do docker exec "$CONTAINER" sh -c "true" 2>/dev/null && break; sleep 1; ((_a++)); done + log_action "BOT AWG TOGGLE: ${#AWG_SELECTED_IPS[@]}, container restarted" bot_handle_callback "$chat_id" "$msg_id" "" "cl" ;; rc) @@ -1530,23 +1625,21 @@ show_menu() { if [ "$MODE" = "3xui" ]; then echo -e "\n${CYAN}── 3X-UI ──────────────────────────────────────────────${NC}" - echo -e " 6) 📋 ${CYAN}Настройки SOCKS5 / JSON для 3X-UI${NC}" - echo -e " 7) 🔧 ${WHITE}Изменить порт SOCKS5${NC}" + echo -e " 6) 📋 ${CYAN}Настройки SOCKS5 / JSON / Инструкция${NC}" fi if [ "$MODE" = "amnezia" ]; then echo -e "\n${CYAN}── AmneziaWG ──────────────────────────────────────────${NC}" echo -e " 6) 👥 ${GREEN}Управление клиентами WARP${NC}" - echo -e " 7) 🔄 ${CYAN}Перезапуск контейнера${NC}" fi echo -e "\n${CYAN}── Telegram-бот ───────────────────────────────────────${NC}" - echo -e " 8) 🤖 ${CYAN}Настройка и управление ботом${NC}" + echo -e " 7) 🤖 ${CYAN}Настройка и управление ботом${NC}" echo -e "\n${CYAN}── Прочее ─────────────────────────────────────────────${NC}" - echo -e " 9) ${YELLOW}PROMO${NC}" - echo -e " 10) ${MAGENTA}📚 Инструкция${NC}" - echo -e " 11) ${RED}⚠ Полное удаление${NC}" + echo -e " 8) ${YELLOW}PROMO${NC}" + echo -e " 9) ${MAGENTA}📚 Инструкция${NC}" + echo -e " 10) ${RED}⚠ Полное удаление${NC}" echo -e " 0) Выход" echo -e "${CYAN}──────────────────────────────────────────────────────${NC}" read -p " Выбор: " ch @@ -1557,12 +1650,11 @@ show_menu() { 3) if [ "$MODE" = "3xui" ]; then stop_warp_3xui; else stop_warp_awg; fi ;; 4) if [ "$MODE" = "3xui" ]; then show_status_3xui; else show_status_awg; fi ;; 5) if [ "$MODE" = "3xui" ]; then rekey_warp_3xui; else rekey_warp_awg; fi ;; - 6) if [ "$MODE" = "3xui" ]; then show_xui_json; else awg_toggle_clients_ssh; fi ;; - 7) if [ "$MODE" = "3xui" ]; then change_port_3xui; else awg_restart_container; fi ;; - 8) bot_menu ;; - 9) show_promo ;; - 10) show_info ;; - 11) full_uninstall ;; + 6) if [ "$MODE" = "3xui" ]; then show_3xui_menu; else awg_toggle_clients_ssh; fi ;; + 7) bot_menu ;; + 8) show_promo ;; + 9) show_info ;; + 10) full_uninstall ;; 0) exit 0 ;; esac done