diff --git a/warp.sh b/warp.sh index 81d4d54..318e47c 100644 --- a/warp.sh +++ b/warp.sh @@ -2,14 +2,16 @@ set -o pipefail # ══════════════════════════════════════════════════════════════ -# WARP Manager v1.0 — Cloudflare WARP SOCKS5 Proxy for 3X-UI +# WARP Manager v1.1 — Cloudflare WARP SOCKS5 Proxy for 3X-UI +# Telegram Bot · Status · Rekey · 3X-UI Config # Channel: https://www.youtube.com/@antenkaru # ══════════════════════════════════════════════════════════════ -WARP_VERSION="1.0" +WARP_VERSION="1.1" WARP_DIR="/etc/warp-manager" WARP_CONF="$WARP_DIR/config" WARP_LOG="/var/log/warp-manager.log" +BOT_PID_FILE="/var/run/warp_bot.pid" DEFAULT_PORT=40000 RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m' @@ -18,6 +20,8 @@ BLUE='\033[0;34m'; NC='\033[0m' SOCKS_PORT="" MY_IP="" +BOT_TOKEN="" +BOT_CHAT_ID="" # ─── Config ─────────────────────────────────────────────────── @@ -26,6 +30,8 @@ init_config() { if [ ! -f "$WARP_CONF" ]; then cat > "$WARP_CONF" <<'CONF' SOCKS_PORT="40000" +BOT_TOKEN="" +BOT_CHAT_ID="" CONF fi source "$WARP_CONF" @@ -56,6 +62,17 @@ check_root() { fi } +check_deps() { + for cmd in jq curl; do + if ! command -v "$cmd" &>/dev/null; then + export DEBIAN_FRONTEND=noninteractive + apt-get update -y > /dev/null 2>&1 + apt-get install -y jq curl > /dev/null 2>&1 + break + fi + done +} + get_my_ip() { MY_IP=$(curl -s4 --max-time 5 ifconfig.me 2>/dev/null || echo "N/A") } @@ -105,6 +122,24 @@ get_warp_status_text() { fi } +get_system_stats() { + local cpu_line load_avg mem_info disk_info uptime_str cpu_usage + cpu_line=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || echo "?") + load_avg=$(cat /proc/loadavg 2>/dev/null | awk '{print $1, $2, $3}') + mem_info=$(free -m 2>/dev/null | awk '/^Mem:/ {printf "%d/%dMB (%.1f%%)", $3, $2, $3/$2*100}') + disk_info=$(df -h / 2>/dev/null | awk 'NR==2 {printf "%s/%s (%s)", $3, $2, $5}') + uptime_str=$(uptime -p 2>/dev/null || uptime | sed 's/.*up /up /' | sed 's/,.*load.*//') + cpu_usage=$(awk '/^cpu / {u=$2+$4; t=$2+$3+$4+$5+$6+$7+$8; if(t>0) printf "%.1f", u/t*100; else print "0"}' /proc/stat 2>/dev/null) + local r="" + r+="📊 Системная информация\n\n" + r+="Uptime: ${uptime_str}\n" + r+="CPU: ${cpu_line} ядер | ${cpu_usage}%\n" + r+="Load: ${load_avg}\n" + r+="RAM: ${mem_info}\n" + r+="Disk /: ${disk_info}\n" + echo "$r" +} + # ─── Install ────────────────────────────────────────────────── install_warp() { @@ -170,7 +205,7 @@ install_warp() { echo -e "${YELLOW}[6/6]${NC} Подключение..." warp-cli --accept-tos connect > /dev/null 2>&1 - sleep 2 + sleep 3 if is_warp_running; then local wip @@ -180,7 +215,7 @@ install_warp() { log_action "INSTALL: WARP installed and connected, port=${SOCKS_PORT}, warp_ip=${wip}" else echo -e "${YELLOW} ⚠ WARP установлен, но подключение не подтверждено.${NC}" - echo -e " ${WHITE}Попробуйте: ${CYAN}warp-cli connect${NC}" + echo -e " ${WHITE}Попробуйте: ${CYAN}warp-cli --accept-tos connect${NC}" log_action "INSTALL: WARP installed, connection unconfirmed" fi @@ -203,12 +238,12 @@ start_warp() { fi echo -e "\n${YELLOW}Подключение WARP...${NC}" warp-cli --accept-tos connect > /dev/null 2>&1 - sleep 2 + sleep 3 if is_warp_running; then echo -e "${GREEN}[OK] WARP подключён.${NC}" log_action "START: WARP connected" else - echo -e "${RED}[ERROR] Не удалось подключить. Проверьте: warp-cli status${NC}" + echo -e "${RED}[ERROR] Не удалось подключить. Проверьте: warp-cli --accept-tos status${NC}" fi read -p "Нажмите Enter..." } @@ -264,12 +299,6 @@ show_status() { echo -e " ${WHITE}$line${NC}" done - echo "" - echo -e " ${CYAN}── warp-cli settings ──${NC}" - warp-cli --accept-tos settings 2>/dev/null | head -10 | while IFS= read -r line; do - echo -e " ${WHITE}$line${NC}" - done - echo "" read -p "Нажмите Enter..." } @@ -298,11 +327,6 @@ show_xui_json() { EOF echo -e "\n${GREEN}── 2. Routing Rule (примеры маршрутов через WARP) ──${NC}\n" - echo -e "${WHITE}Весь трафик через WARP:${NC}" - echo -e "${YELLOW} В 3X-UI → Настройки Xray → Routing → добавить правило:${NC}" - echo -e "${YELLOW} Outbound Tag: ${WHITE}warp${NC}" - echo -e "${YELLOW} Весь трафик (или конкретные домены)${NC}\n" - echo -e "${WHITE}Только определённые сайты через WARP (JSON routing rule):${NC}\n" cat < /dev/null 2>&1 warp-cli --accept-tos proxy port "${SOCKS_PORT}" > /dev/null 2>&1 warp-cli --accept-tos connect > /dev/null 2>&1 - sleep 2 + sleep 3 if is_warp_running; then local wip @@ -421,6 +445,7 @@ full_uninstall() { echo -e "${WHITE}Будут удалены:${NC}" echo -e " ${RED}•${NC} Пакет cloudflare-warp" echo -e " ${RED}•${NC} Репозиторий и GPG-ключ Cloudflare" + echo -e " ${RED}•${NC} Telegram-бот" echo -e " ${RED}•${NC} Конфигурация ${WHITE}/etc/warp-manager/${NC}" echo -e " ${RED}•${NC} Команда ${WHITE}gowarp${NC}" echo -e " ${RED}•${NC} Логи ${WHITE}/var/log/warp-manager.log${NC}" @@ -436,30 +461,32 @@ full_uninstall() { echo "" echo -e "${YELLOW}Удаление WARP Manager...${NC}\n" - echo -e " ${YELLOW}[1/6]${NC} Отключение WARP..." + if systemctl is-active warp-bot &>/dev/null; then + systemctl stop warp-bot 2>/dev/null; systemctl disable warp-bot 2>/dev/null + fi + [ -f "$BOT_PID_FILE" ] && { kill "$(cat "$BOT_PID_FILE")" 2>/dev/null; rm -f "$BOT_PID_FILE"; } + rm -f /etc/systemd/system/warp-bot.service + systemctl daemon-reload 2>/dev/null + echo -e " ${GREEN}✓${NC} Telegram-бот остановлен" + warp-cli --accept-tos disconnect > /dev/null 2>&1 echo -e " ${GREEN}✓${NC} WARP отключён" - echo -e " ${YELLOW}[2/6]${NC} Удаление регистрации..." warp-cli --accept-tos registration delete > /dev/null 2>&1 echo -e " ${GREEN}✓${NC} Регистрация удалена" - echo -e " ${YELLOW}[3/6]${NC} Удаление пакета..." apt-get remove -y cloudflare-warp > /dev/null 2>&1 apt-get autoremove -y > /dev/null 2>&1 echo -e " ${GREEN}✓${NC} Пакет удалён" - echo -e " ${YELLOW}[4/6]${NC} Удаление репозитория и ключа..." rm -f /etc/apt/sources.list.d/cloudflare-client.list rm -f /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg echo -e " ${GREEN}✓${NC} Репозиторий и ключ удалены" - echo -e " ${YELLOW}[5/6]${NC} Удаление конфигурации..." rm -rf "$WARP_DIR" rm -f "$WARP_LOG" echo -e " ${GREEN}✓${NC} Конфигурация и логи удалены" - echo -e " ${YELLOW}[6/6]${NC} Удаление команды gowarp..." rm -f /usr/local/bin/gowarp echo -e " ${GREEN}✓${NC} Команда gowarp удалена" @@ -474,6 +501,297 @@ full_uninstall() { exit 0 } +# ═══════════════════════════════════════════════════════════════ +# TELEGRAM BOT +# ═══════════════════════════════════════════════════════════════ + +tg_api() { + curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/$1" \ + -H "Content-Type: application/json" -d "$2" 2>/dev/null +} + +tg_send() { + local chat_id="$1" text keyboard="${3:-}" + text=$(printf '%b' "$2") + local payload + if [ -n "$keyboard" ]; then + payload=$(jq -n --arg c "$chat_id" --arg t "$text" --argjson k "$keyboard" \ + '{chat_id:$c, text:$t, parse_mode:"HTML", reply_markup:{inline_keyboard:$k}}') + else + payload=$(jq -n --arg c "$chat_id" --arg t "$text" \ + '{chat_id:$c, text:$t, parse_mode:"HTML"}') + fi + tg_api "sendMessage" "$payload" +} + +tg_edit() { + local chat_id="$1" msg_id="$2" text keyboard="${4:-}" + text=$(printf '%b' "$3") + local payload + if [ -n "$keyboard" ]; then + payload=$(jq -n --arg c "$chat_id" --argjson m "$msg_id" --arg t "$text" --argjson k "$keyboard" \ + '{chat_id:$c, message_id:$m, text:$t, parse_mode:"HTML", reply_markup:{inline_keyboard:$k}}') + else + payload=$(jq -n --arg c "$chat_id" --argjson m "$msg_id" --arg t "$text" \ + '{chat_id:$c, message_id:$m, text:$t, parse_mode:"HTML"}') + fi + tg_api "editMessageText" "$payload" +} + +tg_answer_cb() { + tg_api "answerCallbackQuery" "{\"callback_query_id\":\"$1\",\"text\":\"${2:-}\"}" +} + +# ─── Bot keyboards ─────────────────────────────────────────── + +kbd_main() { + cat <<'JSON' +[ + [{"text":"📊 Статус","callback_data":"st"},{"text":"🌐 IP адреса","callback_data":"ip"}], + [{"text":"▶️ Запустить","callback_data":"on"},{"text":"⏹ Остановить","callback_data":"off"}], + [{"text":"🔑 Перевыпуск ключа","callback_data":"rk"}], + [{"text":"📋 JSON для 3X-UI","callback_data":"js"}], + [{"text":"💻 Система","callback_data":"sys"}], + [{"text":"🏢 Хостинг","callback_data":"promo"}] +] +JSON +} + +kbd_back() { echo '[[{"text":"⬅️ Меню","callback_data":"m"}]]'; } + +kbd_rekey_confirm() { echo '[[{"text":"✅ Да, перевыпустить","callback_data":"rk_y"}],[{"text":"⬅️ Отмена","callback_data":"m"}]]'; } + +# ─── Bot handlers ──────────────────────────────────────────── + +bot_main_menu() { + local chat_id="$1" msg_id="${2:-}" + local ws wip="" + ws=$(get_warp_status_text) + is_warp_running && wip=" | WARP IP: $(get_warp_ip)" + local text="WARP Manager v${WARP_VERSION}\nСервер: ${MY_IP:-N/A}\nСтатус: ${ws}${wip}\nSOCKS5: 127.0.0.1:${SOCKS_PORT}\n\nВыберите действие:" + local kbd + kbd=$(kbd_main) + if [ -n "$msg_id" ]; then + tg_edit "$chat_id" "$msg_id" "$text" "$kbd" + else + tg_send "$chat_id" "$text" "$kbd" + fi +} + +bot_handle_callback() { + local chat_id="$1" msg_id="$2" cb_id="$3" data="$4" + [ -n "$cb_id" ] && tg_answer_cb "$cb_id" > /dev/null + + case "$data" in + m) bot_main_menu "$chat_id" "$msg_id" ;; + + st) + local ws wip="" + ws=$(get_warp_status_text) + is_warp_running && wip="\nWARP IP: $(get_warp_ip)" + local raw + raw=$(warp-cli --accept-tos status 2>/dev/null | head -3) + local text="📊 Статус WARP\n\nСтатус: ${ws}\nSOCKS5: 127.0.0.1:${SOCKS_PORT}\nСервер: ${MY_IP:-N/A}${wip}\n\n
${raw}
" + tg_edit "$chat_id" "$msg_id" "$text" "$(kbd_back)" ;; + + ip) + local wip="N/A" + is_warp_running && wip=$(get_warp_ip) + local text="🌐 IP адреса\n\nРеальный IP: ${MY_IP:-N/A}\nWARP IP: ${wip}\nSOCKS5: 127.0.0.1:${SOCKS_PORT}" + tg_edit "$chat_id" "$msg_id" "$text" "$(kbd_back)" ;; + + on) + if ! is_warp_installed; then + tg_edit "$chat_id" "$msg_id" "❌ WARP не установлен." "$(kbd_back)"; return + fi + if is_warp_running; then + tg_edit "$chat_id" "$msg_id" "✅ WARP уже подключён." "$(kbd_back)"; return + fi + tg_edit "$chat_id" "$msg_id" "⏳ Подключение WARP..." "" + warp-cli --accept-tos connect > /dev/null 2>&1 + sleep 3 + if is_warp_running; then + local wip + wip=$(get_warp_ip) + log_action "BOT: WARP connected" + tg_edit "$chat_id" "$msg_id" "✅ WARP подключён\nWARP IP: ${wip}" "$(kbd_back)" + else + tg_edit "$chat_id" "$msg_id" "❌ Не удалось подключить WARP." "$(kbd_back)" + fi ;; + + off) + if ! is_warp_running; then + tg_edit "$chat_id" "$msg_id" "ℹ️ WARP уже отключён." "$(kbd_back)"; return + fi + warp-cli --accept-tos disconnect > /dev/null 2>&1 + log_action "BOT: WARP disconnected" + tg_edit "$chat_id" "$msg_id" "⏹ WARP отключён." "$(kbd_back)" ;; + + rk) + tg_edit "$chat_id" "$msg_id" "🔑 Перевыпуск ключа\n\nТекущая регистрация будет удалена и создана новая.\nWARP будет временно отключён.\n\nПродолжить?" "$(kbd_rekey_confirm)" ;; + + rk_y) + tg_edit "$chat_id" "$msg_id" "⏳ Перевыпуск ключа..." "" + warp-cli --accept-tos disconnect > /dev/null 2>&1 + warp-cli --accept-tos registration delete > /dev/null 2>&1 + warp-cli --accept-tos registration new > /dev/null 2>&1 + warp-cli --accept-tos mode proxy > /dev/null 2>&1 + warp-cli --accept-tos proxy port "${SOCKS_PORT}" > /dev/null 2>&1 + warp-cli --accept-tos connect > /dev/null 2>&1 + sleep 3 + if is_warp_running; then + local wip + wip=$(get_warp_ip) + log_action "BOT REKEY: warp_ip=${wip}" + tg_edit "$chat_id" "$msg_id" "✅ Ключ перевыпущен\nНовый WARP IP: ${wip}" "$(kbd_back)" + else + tg_edit "$chat_id" "$msg_id" "⚠️ Ключ перевыпущен, подключение не подтверждено." "$(kbd_back)" + fi ;; + + js) + local text="📋 Конфигурация для 3X-UI\n\nOutbound:\n
{\n  \"tag\": \"warp\",\n  \"protocol\": \"socks\",\n  \"settings\": {\n    \"servers\": [{\n      \"address\": \"127.0.0.1\",\n      \"port\": ${SOCKS_PORT}\n    }]\n  }\n}
\n\nRouting rule:\n
{\n  \"outboundTag\": \"warp\",\n  \"domain\": [\n    \"geosite:openai\",\n    \"geosite:netflix\"\n  ]\n}
" + tg_edit "$chat_id" "$msg_id" "$text" "$(kbd_back)" ;; + + sys) + local s + s=$(get_system_stats) + local ws + ws=$(get_warp_status_text) + s+="\nWARP: ${ws}" + s+="\nSOCKS5: 127.0.0.1:${SOCKS_PORT}" + tg_edit "$chat_id" "$msg_id" "$s" "$(kbd_back)" ;; + + promo) + local pt="🏢 Хостинг, который работает\n\n🌍 РФ и Европа\n👉 https://vk.cc/ct29NQ\n\nOFF60 — 60% скидка\nantenka20 — +20% (3мес)\nantenka6 — +15% (6мес)\nantenka12 — +5% (12мес)\n\n🇧🇾 Беларусь\n👉 https://vk.cc/cUxAhj\nOFF60 — 60% скидка" + tg_edit "$chat_id" "$msg_id" "$pt" "$(kbd_back)" ;; + esac +} + +# ─── Bot daemon ─────────────────────────────────────────────── + +bot_daemon() { + log_action "Bot daemon started (PID $$)"; echo $$ > "$BOT_PID_FILE" + source "$WARP_CONF" + [ -z "$BOT_TOKEN" ] && log_action "BOT ERROR: no token" && exit 1 + get_my_ip + local offset=0 + while true; do + local response + response=$(curl -s --max-time 35 \ + "https://api.telegram.org/bot${BOT_TOKEN}/getUpdates?offset=${offset}&timeout=30" 2>/dev/null) + [ -z "$response" ] && sleep 2 && continue + local ok + ok=$(echo "$response" | jq -r '.ok // "false"') + [ "$ok" != "true" ] && sleep 5 && continue + local cnt + cnt=$(echo "$response" | jq '.result | length') + for (( i=0; i /dev/null && continue + bot_handle_callback "$cci" "$cmi" "$cbi" "$cbd" + else + local mci mtx + mci=$(echo "$upd" | jq -r '.message.chat.id // empty') + mtx=$(echo "$upd" | jq -r '.message.text // empty') + if [ -n "$mci" ] && [ -n "$mtx" ]; then + [ -n "$BOT_CHAT_ID" ] && [ "$mci" != "$BOT_CHAT_ID" ] && \ + tg_send "$mci" "⛔ Нет доступа.\nChat ID: $mci" "" > /dev/null && continue + if [ "$mtx" = "/start" ] || [ "$mtx" = "/menu" ]; then + bot_main_menu "$mci" + else + tg_send "$mci" "Используйте /start или /menu" "" > /dev/null + fi + fi + fi + done + done +} + +start_bot() { + source "$WARP_CONF" + [ -z "$BOT_TOKEN" ] && echo -e "${RED}Задайте BOT_TOKEN!${NC}" && return + [ -f "$BOT_PID_FILE" ] && kill -0 "$(cat "$BOT_PID_FILE")" 2>/dev/null && echo -e "${YELLOW}Уже запущен.${NC}" && return + cat > /etc/systemd/system/warp-bot.service < /dev/null 2>&1 + systemctl start warp-bot + sleep 1 + systemctl is-active warp-bot &>/dev/null && echo -e "${GREEN}[OK] Бот запущен.${NC}" && log_action "Bot started" \ + || echo -e "${RED}[ERROR] journalctl -u warp-bot${NC}" +} + +stop_bot() { + systemctl stop warp-bot 2>/dev/null + systemctl disable warp-bot 2>/dev/null + rm -f "$BOT_PID_FILE" + echo -e "${GREEN}[OK] Бот остановлен.${NC}" + log_action "Bot stopped" +} + +bot_menu() { + while true; do + clear; source "$WARP_CONF" 2>/dev/null + local bs="${RED}Выкл${NC}" + [ -f "$BOT_PID_FILE" ] && kill -0 "$(cat "$BOT_PID_FILE" 2>/dev/null)" 2>/dev/null && bs="${GREEN}Вкл ($(cat "$BOT_PID_FILE"))${NC}" + local td="нет" + [ -n "${BOT_TOKEN:-}" ] && td="***${BOT_TOKEN: -6}" + + echo -e "${CYAN}━━━ Telegram Bot ━━━${NC}" + echo -e "Статус: $bs" + echo -e "Токен: ${YELLOW}$td${NC}" + echo -e "Chat ID: ${YELLOW}${BOT_CHAT_ID:-нет}${NC}" + echo "" + echo -e "1) Токен бота" + echo -e "2) Chat ID (авто)" + echo -e "3) Chat ID (вручную)" + echo -e "4) ${GREEN}Запустить${NC}" + echo -e "5) ${RED}Остановить${NC}" + echo -e "0) Назад" + read -p "Выбор: " ch + case $ch in + 1) echo "Токен:"; read -p "> " t + [ -n "$t" ] && save_config_val "BOT_TOKEN" "$t" && BOT_TOKEN="$t" && echo -e "${GREEN}OK${NC}" + read -p "Enter..." ;; + 2) [ -z "${BOT_TOKEN:-}" ] && echo -e "${RED}Сначала задайте токен!${NC}" && read -p "" && continue + echo -e "${YELLOW}Отправьте боту сообщение, затем нажмите Enter.${NC}"; read -p "" + local c + c=$(curl -s "https://api.telegram.org/bot${BOT_TOKEN}/getUpdates?limit=1&offset=-1" | \ + jq -r '.result[0].message.chat.id // empty') + [ -n "$c" ] && save_config_val "BOT_CHAT_ID" "$c" && BOT_CHAT_ID="$c" && echo -e "${GREEN}Chat ID: $c${NC}" \ + || echo -e "${RED}Не удалось получить Chat ID.${NC}" + read -p "Enter..." ;; + 3) echo "Chat ID:"; read -p "> " c + [ -n "$c" ] && save_config_val "BOT_CHAT_ID" "$c" && BOT_CHAT_ID="$c" && echo -e "${GREEN}OK${NC}" + read -p "Enter..." ;; + 4) start_bot; read -p "Enter..." ;; + 5) stop_bot; read -p "Enter..." ;; + 0) return ;; + esac + done +} + # ═══════════════════════════════════════════════════════════════ # PROMO # ═══════════════════════════════════════════════════════════════ @@ -510,14 +828,6 @@ show_info() { echo -e " Ваш VPS получает «чистый» IP-адрес Cloudflare, который" echo -e " не заблокирован популярными сервисами.${NC}" echo "" - echo -e "${CYAN}═══ ЗАЧЕМ НУЖЕН WARP + 3X-UI ═══${NC}" - echo "" - echo -e "${WHITE} Многие сайты блокируют IP дешёвых VPS:" - echo -e " ChatGPT, Netflix, Disney+, Spotify и другие." - echo -e "" - echo -e " WARP решает эту проблему: трафик из 3X-UI идёт через" - echo -e " Cloudflare и получает доверенный IP.${NC}" - echo "" echo -e "${CYAN}═══ СХЕМА РАБОТЫ ═══${NC}" echo "" echo -e "${WHITE} Клиент → 3X-UI (Xray) → SOCKS5 (WARP) → Cloudflare → Интернет${NC}" @@ -532,7 +842,7 @@ show_info() { echo -e " ${GREEN}✓${NC} Разблокировка ChatGPT, Netflix, Disney+, Spotify" echo -e " ${GREEN}✓${NC} Чистый IPv4/IPv6 от Cloudflare" echo -e " ${GREEN}✓${NC} Стабильный маршрут через сеть Cloudflare" - echo -e " ${GREEN}✓${NC} Гибкая маршрутизация: часть сайтов через WARP, остальные напрямую" + echo -e " ${GREEN}✓${NC} Управление через Telegram-бот" echo -e " ${GREEN}✓${NC} Бесплатно (Cloudflare WARP — бесплатный сервис)" echo "" echo -e "${MAGENTA}──────────────────────────────────────────────────────────────${NC}" @@ -568,9 +878,10 @@ show_menu() { echo -e " 5) 📋 ${CYAN}JSON для 3X-UI${NC}" echo -e " 6) 🔑 ${YELLOW}Перевыпуск ключа${NC}" echo -e " 7) 🔧 ${WHITE}Изменить порт SOCKS5${NC}" - echo -e " 8) ${YELLOW}PROMO${NC}" - echo -e " 9) ${MAGENTA}📚 Инструкция${NC}" - echo -e "10) ${RED}⚠ Полное удаление${NC}" + echo -e " 8) 🤖 ${CYAN}Telegram Bot${NC}" + echo -e " 9) ${YELLOW}PROMO${NC}" + echo -e "10) ${MAGENTA}📚 Инструкция${NC}" + echo -e "11) ${RED}⚠ Полное удаление${NC}" echo -e " 0) Выход" echo -e "------------------------------------------------------" read -p "Выбор: " ch @@ -582,9 +893,10 @@ show_menu() { 5) show_xui_json ;; 6) rekey_warp ;; 7) change_port ;; - 8) show_promo ;; - 9) show_info ;; - 10) full_uninstall ;; + 8) bot_menu ;; + 9) show_promo ;; + 10) show_info ;; + 11) full_uninstall ;; 0) exit 0 ;; esac done @@ -595,11 +907,11 @@ show_menu() { # ═══════════════════════════════════════════════════════════════ run_startup() { - local total=5 s=0 + local total=6 s=0 clear; echo "" echo -e "${MAGENTA}╔══════════════════════════════════════════════════════════════╗${NC}" - echo -e "${MAGENTA}║ WARP Manager v${WARP_VERSION} — Загрузка ║${NC}" + echo -e "${MAGENTA}║ WARP Manager v${WARP_VERSION} — Загрузка ║${NC}" echo -e "${MAGENTA}╚══════════════════════════════════════════════════════════════╝${NC}" echo "" @@ -613,6 +925,11 @@ run_startup() { init_config printf "\r ${CYAN}[%d/%d]${NC} ${GREEN}✓${NC} Конфигурация загружена \n" "$s" "$total" + ((s++)) + printf " ${CYAN}[%d/%d]${NC} ${YELLOW}⏳${NC} Проверка зависимостей..." "$s" "$total" + check_deps + printf "\r ${CYAN}[%d/%d]${NC} ${GREEN}✓${NC} Зависимости на месте \n" "$s" "$total" + ((s++)) printf " ${CYAN}[%d/%d]${NC} ${YELLOW}⏳${NC} Установка gowarp..." "$s" "$total" if [ "$(readlink -f "$0" 2>/dev/null)" != "/usr/local/bin/gowarp" ]; then @@ -649,4 +966,7 @@ run_startup() { # ENTRY POINT # ═══════════════════════════════════════════════════════════════ -run_startup +case "${1:-}" in + --bot-daemon) init_config; bot_daemon ;; + *) run_startup ;; +esac