#!/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 # ══════════════════════════════════════════════════════════════ 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