diff --git a/warp.sh b/warp.sh index aecc92b..e69de29 100644 --- a/warp.sh +++ b/warp.sh @@ -1,1023 +0,0 @@ -#!/bin/bash -set -o pipefail - -# ══════════════════════════════════════════════════════════════ -# WARP Manager v1.1 — Cloudflare WARP SOCKS5 Proxy for 3X-UI -# Telegram Bot · Status · Rekey · 3X-UI Config -# Channel: https://www.youtube.com/@antenkaru -# Line endings: LF only (Unix) for gowarp on Linux -# ══════════════════════════════════════════════════════════════ - -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 - -VALID_KEYS=( - "WARP-PRO-2026-ALPHA" - "WARP-PRO-2026-BETA" - "WARP-PRO-2026-GAMMA" -) - -RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m' -YELLOW='\033[1;33m'; MAGENTA='\033[0;35m'; WHITE='\033[1;37m' -BLUE='\033[0;34m'; NC='\033[0m' - -SOCKS_PORT="" -MY_IP="" -BOT_TOKEN="" -BOT_CHAT_ID="" -LICENSE_KEY="" - -# ─── Config ─────────────────────────────────────────────────── - -init_config() { - mkdir -p "$WARP_DIR" - if [ ! -f "$WARP_CONF" ]; then - cat > "$WARP_CONF" <<'CONF' -SOCKS_PORT="40000" -BOT_TOKEN="" -BOT_CHAT_ID="" -LICENSE_KEY="" -CONF - fi - source "$WARP_CONF" - SOCKS_PORT="${SOCKS_PORT:-$DEFAULT_PORT}" -} - -save_config_val() { - local key="$1" value="$2" - if grep -q "^${key}=" "$WARP_CONF" 2>/dev/null; then - sed -i "s|^${key}=.*|${key}=\"${value}\"|" "$WARP_CONF" - else - echo "${key}=\"${value}\"" >> "$WARP_CONF" - fi - source "$WARP_CONF" -} - -# ─── License ────────────────────────────────────────────────── - -is_valid_key() { - local k="$1" - for vk in "${VALID_KEYS[@]}"; do - [ "$k" = "$vk" ] && return 0 - done - return 1 -} - -check_license() { - local arg_key="${1:-}" - source "$WARP_CONF" 2>/dev/null - - if [ -n "${LICENSE_KEY:-}" ] && is_valid_key "$LICENSE_KEY"; then - return 0 - fi - - if [ -n "$arg_key" ] && is_valid_key "$arg_key"; then - save_config_val "LICENSE_KEY" "$arg_key" - LICENSE_KEY="$arg_key" - return 0 - fi - - echo "" - echo -e "${RED}╔══════════════════════════════════════════════════════════════╗${NC}" - echo -e "${RED}║ ⛔ ЛИЦЕНЗИОННЫЙ КЛЮЧ НЕДЕЙСТВИТЕЛЕН ║${NC}" - echo -e "${RED}╚══════════════════════════════════════════════════════════════╝${NC}" - echo "" - if [ -n "$arg_key" ]; then - echo -e " ${WHITE}Ключ ${YELLOW}${arg_key}${WHITE} не найден в базе.${NC}" - else - echo -e " ${WHITE}Для установки требуется лицензионный ключ.${NC}" - fi - echo "" - echo -e " ${CYAN}Использование:${NC}" - echo -e " ${WHITE}bash <(curl -sL ...) ${GREEN}ВАШ_КЛЮЧ${NC}" - echo "" - echo -e " ${WHITE}Получить ключ: ${CYAN}https://www.youtube.com/@antenkaru${NC}" - echo "" - exit 1 -} - -# ─── Logging ────────────────────────────────────────────────── - -log_action() { - echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$WARP_LOG" -} - -# ─── System ─────────────────────────────────────────────────── - -check_root() { - if [ "$EUID" -ne 0 ]; then - echo -e "${RED}[ERROR] Запустите скрипт с правами root!${NC}"; exit 1 - 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") -} - -get_warp_ip() { - local warp_ip - warp_ip=$(curl -s4 --max-time 5 --proxy socks5h://127.0.0.1:${SOCKS_PORT} ifconfig.me 2>/dev/null || echo "N/A") - echo "$warp_ip" -} - -detect_os() { - if [ -f /etc/os-release ]; then - . /etc/os-release - OS_ID="$ID" - OS_VERSION="$VERSION_ID" - OS_CODENAME="$VERSION_CODENAME" - else - OS_ID="unknown" - fi -} - -is_warp_installed() { - command -v warp-cli &>/dev/null -} - -is_warp_running() { - local st - st=$(warp-cli --accept-tos status 2>/dev/null) - echo "$st" | grep -qi "status.*connected" && ! echo "$st" | grep -qi "disconnected" -} - -get_warp_status_text() { - if ! is_warp_installed; then - echo "Не установлен" - return - fi - local status - status=$(warp-cli --accept-tos status 2>/dev/null | head -5) - if echo "$status" | grep -qi "disconnected"; then - echo "Отключён" - elif echo "$status" | grep -qi "connected"; then - echo "Подключён" - elif echo "$status" | grep -qi "registration missing"; then - echo "Нет регистрации" - else - echo "Неизвестно" - 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() { - clear - echo -e "\n${CYAN}━━━ Установка Cloudflare WARP ━━━${NC}\n" - - if is_warp_installed; then - echo -e "${YELLOW}WARP уже установлен.${NC}" - echo -e "Используйте меню для управления.\n" - read -p "Нажмите Enter..." - return - fi - - detect_os - if [[ "$OS_ID" != "ubuntu" && "$OS_ID" != "debian" ]]; then - echo -e "${RED}[ERROR] Поддерживаются только Ubuntu и Debian.${NC}" - echo -e "${WHITE}Ваша ОС: ${YELLOW}${OS_ID} ${OS_VERSION}${NC}" - read -p "Нажмите Enter..." - return - fi - - echo -e "${YELLOW}[1/6]${NC} Добавление GPG-ключа Cloudflare..." - curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | gpg --yes --dearmor -o /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg 2>/dev/null - if [ $? -ne 0 ]; then - echo -e "${RED}[ERROR] Не удалось добавить GPG-ключ.${NC}" - read -p "Нажмите Enter..."; return - fi - echo -e "${GREEN} ✓ GPG-ключ добавлен${NC}" - - echo -e "${YELLOW}[2/6]${NC} Добавление репозитория..." - local codename="$OS_CODENAME" - if [ -z "$codename" ]; then - codename=$(lsb_release -cs 2>/dev/null || echo "focal") - fi - echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ ${codename} main" \ - > /etc/apt/sources.list.d/cloudflare-client.list - echo -e "${GREEN} ✓ Репозиторий добавлен (${codename})${NC}" - - echo -e "${YELLOW}[3/6]${NC} Установка пакета cloudflare-warp..." - export DEBIAN_FRONTEND=noninteractive - apt-get update -y > /dev/null 2>&1 - apt-get install -y cloudflare-warp > /dev/null 2>&1 - if ! command -v warp-cli &>/dev/null; then - echo -e "${RED}[ERROR] Установка не удалась. Проверьте совместимость ОС.${NC}" - echo -e "${WHITE}Попробуйте: ${CYAN}apt-get install cloudflare-warp${NC}" - read -p "Нажмите Enter..."; return - fi - echo -e "${GREEN} ✓ cloudflare-warp установлен${NC}" - - echo -e "${YELLOW}[4/6]${NC} Регистрация аккаунта WARP..." - warp-cli --accept-tos registration new > /dev/null 2>&1 - if [ $? -ne 0 ]; then - echo -e "${RED}[ERROR] Регистрация не удалась.${NC}" - read -p "Нажмите Enter..."; return - fi - echo -e "${GREEN} ✓ Аккаунт зарегистрирован${NC}" - - echo -e "${YELLOW}[5/6]${NC} Настройка режима SOCKS5-прокси..." - warp-cli --accept-tos mode proxy > /dev/null 2>&1 - warp-cli --accept-tos proxy port "${SOCKS_PORT}" > /dev/null 2>&1 - save_config_val "SOCKS_PORT" "${SOCKS_PORT}" - echo -e "${GREEN} ✓ Режим: SOCKS5 на 127.0.0.1:${SOCKS_PORT}${NC}" - - echo -e "${YELLOW}[6/6]${NC} Подключение..." - warp-cli --accept-tos connect > /dev/null 2>&1 - sleep 3 - - if is_warp_running; then - local wip - wip=$(get_warp_ip) - echo -e "${GREEN} ✓ WARP подключён!${NC}" - echo -e " ${WHITE}WARP IP: ${GREEN}${wip}${NC}" - 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 --accept-tos connect${NC}" - log_action "INSTALL: WARP installed, connection unconfirmed" - fi - - echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - echo -e "${WHITE}Для интеграции с 3X-UI используйте пункт меню ${YELLOW}5${WHITE}.${NC}" - echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - read -p "Нажмите Enter..." -} - -# ─── Start / Stop ───────────────────────────────────────────── - -start_warp() { - if ! is_warp_installed; then - echo -e "\n${RED}WARP не установлен. Сначала выполните установку (п.1).${NC}" - read -p "Нажмите Enter..."; return - fi - if is_warp_running; then - echo -e "\n${YELLOW}WARP уже подключён.${NC}" - read -p "Нажмите Enter..."; return - fi - echo -e "\n${YELLOW}Подключение WARP...${NC}" - warp-cli --accept-tos connect > /dev/null 2>&1 - 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 --accept-tos status${NC}" - fi - read -p "Нажмите Enter..." -} - -stop_warp() { - if ! is_warp_installed; then - echo -e "\n${RED}WARP не установлен.${NC}" - read -p "Нажмите Enter..."; return - fi - if ! is_warp_running; then - echo -e "\n${YELLOW}WARP уже отключён.${NC}" - read -p "Нажмите Enter..."; return - fi - echo -e "\n${YELLOW}Отключение WARP...${NC}" - warp-cli --accept-tos disconnect > /dev/null 2>&1 - echo -e "${GREEN}[OK] WARP отключён.${NC}" - log_action "STOP: WARP disconnected" - read -p "Нажмите Enter..." -} - -# ─── Status ─────────────────────────────────────────────────── - -show_status() { - clear - echo -e "\n${CYAN}━━━ Статус WARP ━━━${NC}\n" - - if ! is_warp_installed; then - echo -e " ${WHITE}Статус: ${RED}Не установлен${NC}" - echo -e "\n ${WHITE}Установите WARP через пункт меню 1.${NC}" - echo "" - read -p "Нажмите Enter..."; return - fi - - local status_text warp_ip - status_text=$(get_warp_status_text) - - local status_color="$RED" - [[ "$status_text" == "Подключён" ]] && status_color="$GREEN" - [[ "$status_text" == "Отключён" ]] && status_color="$YELLOW" - - echo -e " ${WHITE}Статус: ${status_color}${status_text}${NC}" - echo -e " ${WHITE}Порт SOCKS5: ${CYAN}127.0.0.1:${SOCKS_PORT}${NC}" - echo -e " ${WHITE}Реальный IP: ${GREEN}${MY_IP}${NC}" - - if is_warp_running; then - warp_ip=$(get_warp_ip) - echo -e " ${WHITE}WARP IP: ${GREEN}${warp_ip}${NC}" - fi - - echo "" - echo -e " ${CYAN}── warp-cli status ──${NC}" - warp-cli --accept-tos status 2>/dev/null | while IFS= read -r line; do - echo -e " ${WHITE}$line${NC}" - done - - echo "" - read -p "Нажмите Enter..." -} - -# ─── 3X-UI JSON ────────────────────────────────────────────── - -show_xui_json() { - clear - echo -e "\n${CYAN}━━━ Конфигурация для 3X-UI ━━━${NC}\n" - echo -e "${WHITE}Добавьте в ${YELLOW}Xray Settings → Outbounds${WHITE} (JSON):${NC}\n" - - echo -e "${GREEN}── 1. Outbound (добавить в массив outbounds) ──${NC}\n" - cat < /dev/null 2>&1 - echo -e "${GREEN} ✓${NC}" - - echo -e "${YELLOW}[2/4] Удаление регистрации...${NC}" - warp-cli --accept-tos registration delete > /dev/null 2>&1 - echo -e "${GREEN} ✓${NC}" - - echo -e "${YELLOW}[3/4] Новая регистрация...${NC}" - warp-cli --accept-tos registration new > /dev/null 2>&1 - if [ $? -ne 0 ]; then - echo -e "${RED}[ERROR] Регистрация не удалась.${NC}" - read -p "Нажмите Enter..."; return - fi - echo -e "${GREEN} ✓${NC}" - - echo -e "${YELLOW}[4/4] Подключение...${NC}" - 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) - echo -e "${GREEN} ✓ Готово! Новый WARP IP: ${wip}${NC}" - log_action "REKEY: new registration, warp_ip=${wip}" - else - echo -e "${YELLOW} ⚠ Регистрация обновлена, подключение не подтверждено.${NC}" - log_action "REKEY: new registration, connection unconfirmed" - fi - read -p "Нажмите Enter..." -} - -# ─── Change port ────────────────────────────────────────────── - -change_port() { - if ! is_warp_installed; then - echo -e "\n${RED}WARP не установлен.${NC}" - read -p "Нажмите Enter..."; return - fi - - echo -e "\n${CYAN}━━━ Изменение порта SOCKS5 ━━━${NC}\n" - echo -e "${WHITE}Текущий порт: ${GREEN}${SOCKS_PORT}${NC}\n" - - local new_port - while true; do - echo -e "Введите новый порт (1024-65535):" - read -p "> " new_port - if [[ "$new_port" =~ ^[0-9]+$ ]] && (( new_port >= 1024 && new_port <= 65535 )); then - break - fi - echo -e "${RED}Ошибка: порт должен быть числом от 1024 до 65535.${NC}" - done - - warp-cli --accept-tos proxy port "$new_port" > /dev/null 2>&1 - save_config_val "SOCKS_PORT" "$new_port" - SOCKS_PORT="$new_port" - - echo -e "\n${GREEN}[OK] Порт изменён на ${new_port}.${NC}" - echo -e "${WHITE}SOCKS5: ${CYAN}127.0.0.1:${new_port}${NC}" - echo -e "\n${YELLOW}Не забудьте обновить порт в настройках 3X-UI!${NC}" - log_action "PORT: changed to ${new_port}" - read -p "Нажмите Enter..." -} - -# ─── Uninstall ──────────────────────────────────────────────── - -full_uninstall() { - clear - echo -e "\n${RED}╔══════════════════════════════════════════════════════════════╗${NC}" - echo -e "${RED}║ ⚠ ПОЛНОЕ УДАЛЕНИЕ WARP MANAGER ⚠ ║${NC}" - echo -e "${RED}╚══════════════════════════════════════════════════════════════╝${NC}" - echo "" - 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}" - echo "" - echo -e "${GREEN}НЕ будет затронуто:${NC}" - echo -e " ${GREEN}•${NC} 3X-UI и Xray (настройки outbound нужно убрать вручную)" - echo -e " ${GREEN}•${NC} Kaskad PRO" - echo -e " ${GREEN}•${NC} Системные пакеты" - echo "" - read -p "$(echo -e "${RED}Удалить WARP Manager полностью? (y/n): ${NC}")" confirm1 - [[ "$confirm1" != "y" ]] && { echo -e "\n${CYAN}Отменено.${NC}"; read -p "Нажмите Enter..."; return; } - - echo "" - echo -e "${YELLOW}Удаление WARP Manager...${NC}\n" - - 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 отключён" - - warp-cli --accept-tos registration delete > /dev/null 2>&1 - echo -e " ${GREEN}✓${NC} Регистрация удалена" - - apt-get remove -y cloudflare-warp > /dev/null 2>&1 - apt-get autoremove -y > /dev/null 2>&1 - echo -e " ${GREEN}✓${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} Репозиторий и ключ удалены" - - rm -rf "$WARP_DIR" - rm -f "$WARP_LOG" - echo -e " ${GREEN}✓${NC} Конфигурация и логи удалены" - - rm -f /usr/local/bin/gowarp - echo -e " ${GREEN}✓${NC} Команда gowarp удалена" - - echo "" - echo -e "${GREEN}══════════════════════════════════════════════════════════════${NC}" - echo -e "${GREEN} WARP Manager полностью удалён.${NC}" - echo -e "${WHITE} Не забудьте убрать outbound \"warp\" из настроек 3X-UI!${NC}" - echo -e "${GREEN}══════════════════════════════════════════════════════════════${NC}" - echo "" - log_action "UNINSTALL: full removal completed" - read -p "Нажмите Enter..." - 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 -# ═══════════════════════════════════════════════════════════════ - -show_promo() { - clear; echo "" - echo -e "${MAGENTA}╔══════════════════════════════════════════════════════════════╗${NC}" - echo -e "${MAGENTA}║ ХОСТИНГ СО СКИДКОЙ ДО -60% ║${NC}" - echo -e "${MAGENTA}╚══════════════════════════════════════════════════════════════╝${NC}" - echo -e "\n${CYAN}🌍 РФ И ЕВРОПА${NC}\n${WHITE} >>> https://vk.cc/ct29NQ${NC}" - printf " ${YELLOW}%-12s${NC} : ${WHITE}%s${NC}\n" "OFF60" "60% скидка" "antenka20" "+20% (3мес)" "antenka6" "+15% (6мес)" "antenka12" "+5% (12мес)" - echo -e "\n${CYAN}🇧🇾 БЕЛАРУСЬ${NC}\n${WHITE} >>> https://vk.cc/cUxAhj${NC}" - printf " ${YELLOW}%-12s${NC} : ${WHITE}%s${NC}\n" "OFF60" "60% скидка" - echo -e "\n${YELLOW}QR-код... (3с)${NC}"; for i in 3 2 1; do echo -ne "$i..."; sleep 1; done; echo "" - echo -e "\n${WHITE}"; command -v qrencode &>/dev/null && qrencode -t ANSIUTF8 "https://vk.cc/ct29NQ" || echo "Ссылки выше."; echo -e "${NC}" - read -p "Нажмите Enter..." -} - -# ═══════════════════════════════════════════════════════════════ -# INFO PAGE -# ═══════════════════════════════════════════════════════════════ - -show_info() { - clear; echo "" - echo -e "${MAGENTA}╔══════════════════════════════════════════════════════════════╗${NC}" - echo -e "${MAGENTA}║ 📚 WARP Manager v${WARP_VERSION} — Что это и как работает ║${NC}" - echo -e "${MAGENTA}╚══════════════════════════════════════════════════════════════╝${NC}" - echo "" - echo -e "${CYAN}═══ ЧТО ТАКОЕ CLOUDFLARE WARP ═══${NC}" - echo "" - echo -e "${WHITE} Cloudflare WARP — бесплатный сервис от Cloudflare, который" - echo -e " направляет трафик через глобальную сеть Cloudflare." - echo -e "" - echo -e " Ваш VPS получает «чистый» IP-адрес Cloudflare, который" - echo -e " не заблокирован популярными сервисами.${NC}" - echo "" - echo -e "${CYAN}═══ СХЕМА РАБОТЫ ═══${NC}" - echo "" - echo -e "${WHITE} Клиент → 3X-UI (Xray) → SOCKS5 (WARP) → Cloudflare → Интернет${NC}" - echo "" - echo -e "${GREEN} 1.${NC} Скрипт устанавливает ${YELLOW}cloudflare-warp${NC} на сервер" - echo -e "${GREEN} 2.${NC} WARP работает в режиме ${YELLOW}SOCKS5-прокси${NC} на 127.0.0.1:${SOCKS_PORT}" - echo -e "${GREEN} 3.${NC} В 3X-UI добавляется ${YELLOW}outbound${NC} типа SOCKS → warp" - echo -e "${GREEN} 4.${NC} В маршрутизации выбираете какие сайты идут через WARP" - echo "" - echo -e "${CYAN}═══ ЧТО ПОЛУЧАЕТЕ ═══${NC}" - echo "" - echo -e " ${GREEN}✓${NC} Разблокировка ChatGPT, Netflix, Disney+, Spotify" - echo -e " ${GREEN}✓${NC} Чистый IPv4/IPv6 от Cloudflare" - echo -e " ${GREEN}✓${NC} Стабильный маршрут через сеть Cloudflare" - echo -e " ${GREEN}✓${NC} Управление через Telegram-бот" - echo -e " ${GREEN}✓${NC} Бесплатно (Cloudflare WARP — бесплатный сервис)" - echo "" - echo -e "${MAGENTA}──────────────────────────────────────────────────────────────${NC}" - read -p "Нажмите Enter для продолжения..." -} - -# ═══════════════════════════════════════════════════════════════ -# MAIN MENU -# ═══════════════════════════════════════════════════════════════ - -show_menu() { - while true; do - clear - local status_text status_color - status_text=$(get_warp_status_text) - status_color="$RED" - [[ "$status_text" == "Подключён" ]] && status_color="$GREEN" - [[ "$status_text" == "Отключён" ]] && status_color="$YELLOW" - - echo -e "${MAGENTA}******************************************************" - echo " anten-ka · WARP Manager v${WARP_VERSION}" - echo " YouTube: https://www.youtube.com/@antenkaru" - echo -e "******************************************************${NC}" - echo -e "${WHITE}IP сервера: ${GREEN}${MY_IP}${NC} ${WHITE}WARP: ${status_color}${status_text}${NC}" - if is_warp_running; then - echo -e "${WHITE}SOCKS5: ${CYAN}127.0.0.1:${SOCKS_PORT}${NC}" - fi - echo -e "------------------------------------------------------" - echo -e " 1) ${GREEN}Установить WARP${NC}" - echo -e " 2) ${CYAN}Запустить WARP${NC}" - echo -e " 3) ${YELLOW}Остановить WARP${NC}" - echo -e " 4) 📊 ${WHITE}Статус и конфигурация${NC}" - echo -e " 5) 📋 ${CYAN}JSON для 3X-UI${NC}" - echo -e " 6) 🔑 ${YELLOW}Перевыпуск ключа${NC}" - echo -e " 7) 🔧 ${WHITE}Изменить порт SOCKS5${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 - case $ch in - 1) install_warp ;; - 2) start_warp ;; - 3) stop_warp ;; - 4) show_status ;; - 5) show_xui_json ;; - 6) rekey_warp ;; - 7) change_port ;; - 8) bot_menu ;; - 9) show_promo ;; - 10) show_info ;; - 11) full_uninstall ;; - 0) exit 0 ;; - esac - done -} - -# ═══════════════════════════════════════════════════════════════ -# STARTUP WITH PROGRESS -# ═══════════════════════════════════════════════════════════════ - -run_startup() { - local total=6 s=0 - - clear; echo "" - echo -e "${MAGENTA}╔══════════════════════════════════════════════════════════════╗${NC}" - echo -e "${MAGENTA}║ WARP Manager v${WARP_VERSION} — Загрузка ║${NC}" - echo -e "${MAGENTA}╚══════════════════════════════════════════════════════════════╝${NC}" - echo "" - - ((s++)) - printf " ${CYAN}[%d/%d]${NC} ${YELLOW}⏳${NC} Проверка прав root..." "$s" "$total" - check_root - printf "\r ${CYAN}[%d/%d]${NC} ${GREEN}✓${NC} Права root подтверждены \n" "$s" "$total" - - ((s++)) - printf " ${CYAN}[%d/%d]${NC} ${YELLOW}⏳${NC} Проверка лицензии..." "$s" "$total" - 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 - cp -f "$0" "/usr/local/bin/gowarp"; chmod +x "/usr/local/bin/gowarp" - fi - printf "\r ${CYAN}[%d/%d]${NC} ${GREEN}✓${NC} Команда gowarp \n" "$s" "$total" - - ((s++)) - printf " ${CYAN}[%d/%d]${NC} ${YELLOW}⏳${NC} Определение IP..." "$s" "$total" - get_my_ip - printf "\r ${CYAN}[%d/%d]${NC} ${GREEN}✓${NC} IP: %-25s \n" "$s" "$total" "$MY_IP" - - ((s++)) - printf " ${CYAN}[%d/%d]${NC} ${YELLOW}⏳${NC} Проверка WARP..." "$s" "$total" - local ws - ws=$(get_warp_status_text) - printf "\r ${CYAN}[%d/%d]${NC} ${GREEN}✓${NC} WARP: %-25s \n" "$s" "$total" "$ws" - - echo "" - local w=40 bar="" - for ((i=0; i