Add Telegram bot support v1.1

This commit is contained in:
anten-ka
2026-03-08 13:13:04 +03:00
parent 92604e79c9
commit d97345d8c9

402
warp.sh
View File

@@ -2,14 +2,16 @@
set -o pipefail 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 # Channel: https://www.youtube.com/@antenkaru
# ══════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════
WARP_VERSION="1.0" WARP_VERSION="1.1"
WARP_DIR="/etc/warp-manager" WARP_DIR="/etc/warp-manager"
WARP_CONF="$WARP_DIR/config" WARP_CONF="$WARP_DIR/config"
WARP_LOG="/var/log/warp-manager.log" WARP_LOG="/var/log/warp-manager.log"
BOT_PID_FILE="/var/run/warp_bot.pid"
DEFAULT_PORT=40000 DEFAULT_PORT=40000
RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m' 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="" SOCKS_PORT=""
MY_IP="" MY_IP=""
BOT_TOKEN=""
BOT_CHAT_ID=""
# ─── Config ─────────────────────────────────────────────────── # ─── Config ───────────────────────────────────────────────────
@@ -26,6 +30,8 @@ init_config() {
if [ ! -f "$WARP_CONF" ]; then if [ ! -f "$WARP_CONF" ]; then
cat > "$WARP_CONF" <<'CONF' cat > "$WARP_CONF" <<'CONF'
SOCKS_PORT="40000" SOCKS_PORT="40000"
BOT_TOKEN=""
BOT_CHAT_ID=""
CONF CONF
fi fi
source "$WARP_CONF" source "$WARP_CONF"
@@ -56,6 +62,17 @@ check_root() {
fi 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() { get_my_ip() {
MY_IP=$(curl -s4 --max-time 5 ifconfig.me 2>/dev/null || echo "N/A") MY_IP=$(curl -s4 --max-time 5 ifconfig.me 2>/dev/null || echo "N/A")
} }
@@ -105,6 +122,24 @@ get_warp_status_text() {
fi 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+="<b>📊 Системная информация</b>\n\n"
r+="<b>Uptime:</b> ${uptime_str}\n"
r+="<b>CPU:</b> ${cpu_line} ядер | ${cpu_usage}%\n"
r+="<b>Load:</b> ${load_avg}\n"
r+="<b>RAM:</b> ${mem_info}\n"
r+="<b>Disk /:</b> ${disk_info}\n"
echo "$r"
}
# ─── Install ────────────────────────────────────────────────── # ─── Install ──────────────────────────────────────────────────
install_warp() { install_warp() {
@@ -170,7 +205,7 @@ install_warp() {
echo -e "${YELLOW}[6/6]${NC} Подключение..." echo -e "${YELLOW}[6/6]${NC} Подключение..."
warp-cli --accept-tos connect > /dev/null 2>&1 warp-cli --accept-tos connect > /dev/null 2>&1
sleep 2 sleep 3
if is_warp_running; then if is_warp_running; then
local wip local wip
@@ -180,7 +215,7 @@ install_warp() {
log_action "INSTALL: WARP installed and connected, port=${SOCKS_PORT}, warp_ip=${wip}" log_action "INSTALL: WARP installed and connected, port=${SOCKS_PORT}, warp_ip=${wip}"
else else
echo -e "${YELLOW} ⚠ WARP установлен, но подключение не подтверждено.${NC}" 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" log_action "INSTALL: WARP installed, connection unconfirmed"
fi fi
@@ -203,12 +238,12 @@ start_warp() {
fi fi
echo -e "\n${YELLOW}Подключение WARP...${NC}" echo -e "\n${YELLOW}Подключение WARP...${NC}"
warp-cli --accept-tos connect > /dev/null 2>&1 warp-cli --accept-tos connect > /dev/null 2>&1
sleep 2 sleep 3
if is_warp_running; then if is_warp_running; then
echo -e "${GREEN}[OK] WARP подключён.${NC}" echo -e "${GREEN}[OK] WARP подключён.${NC}"
log_action "START: WARP connected" log_action "START: WARP connected"
else else
echo -e "${RED}[ERROR] Не удалось подключить. Проверьте: warp-cli status${NC}" echo -e "${RED}[ERROR] Не удалось подключить. Проверьте: warp-cli --accept-tos status${NC}"
fi fi
read -p "Нажмите Enter..." read -p "Нажмите Enter..."
} }
@@ -264,12 +299,6 @@ show_status() {
echo -e " ${WHITE}$line${NC}" echo -e " ${WHITE}$line${NC}"
done 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 "" echo ""
read -p "Нажмите Enter..." read -p "Нажмите Enter..."
} }
@@ -298,11 +327,6 @@ show_xui_json() {
EOF EOF
echo -e "\n${GREEN}── 2. Routing Rule (примеры маршрутов через WARP) ──${NC}\n" 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" echo -e "${WHITE}Только определённые сайты через WARP (JSON routing rule):${NC}\n"
cat <<EOF cat <<EOF
{ {
@@ -364,7 +388,7 @@ rekey_warp() {
warp-cli --accept-tos mode proxy > /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 proxy port "${SOCKS_PORT}" > /dev/null 2>&1
warp-cli --accept-tos connect > /dev/null 2>&1 warp-cli --accept-tos connect > /dev/null 2>&1
sleep 2 sleep 3
if is_warp_running; then if is_warp_running; then
local wip local wip
@@ -421,6 +445,7 @@ full_uninstall() {
echo -e "${WHITE}Будут удалены:${NC}" echo -e "${WHITE}Будут удалены:${NC}"
echo -e " ${RED}${NC} Пакет cloudflare-warp" echo -e " ${RED}${NC} Пакет cloudflare-warp"
echo -e " ${RED}${NC} Репозиторий и GPG-ключ Cloudflare" 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}/etc/warp-manager/${NC}"
echo -e " ${RED}${NC} Команда ${WHITE}gowarp${NC}" echo -e " ${RED}${NC} Команда ${WHITE}gowarp${NC}"
echo -e " ${RED}${NC} Логи ${WHITE}/var/log/warp-manager.log${NC}" echo -e " ${RED}${NC} Логи ${WHITE}/var/log/warp-manager.log${NC}"
@@ -436,30 +461,32 @@ full_uninstall() {
echo "" echo ""
echo -e "${YELLOW}Удаление WARP Manager...${NC}\n" 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 warp-cli --accept-tos disconnect > /dev/null 2>&1
echo -e " ${GREEN}${NC} WARP отключён" echo -e " ${GREEN}${NC} WARP отключён"
echo -e " ${YELLOW}[2/6]${NC} Удаление регистрации..."
warp-cli --accept-tos registration delete > /dev/null 2>&1 warp-cli --accept-tos registration delete > /dev/null 2>&1
echo -e " ${GREEN}${NC} Регистрация удалена" echo -e " ${GREEN}${NC} Регистрация удалена"
echo -e " ${YELLOW}[3/6]${NC} Удаление пакета..."
apt-get remove -y cloudflare-warp > /dev/null 2>&1 apt-get remove -y cloudflare-warp > /dev/null 2>&1
apt-get autoremove -y > /dev/null 2>&1 apt-get autoremove -y > /dev/null 2>&1
echo -e " ${GREEN}${NC} Пакет удалён" echo -e " ${GREEN}${NC} Пакет удалён"
echo -e " ${YELLOW}[4/6]${NC} Удаление репозитория и ключа..."
rm -f /etc/apt/sources.list.d/cloudflare-client.list rm -f /etc/apt/sources.list.d/cloudflare-client.list
rm -f /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg rm -f /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
echo -e " ${GREEN}${NC} Репозиторий и ключ удалены" echo -e " ${GREEN}${NC} Репозиторий и ключ удалены"
echo -e " ${YELLOW}[5/6]${NC} Удаление конфигурации..."
rm -rf "$WARP_DIR" rm -rf "$WARP_DIR"
rm -f "$WARP_LOG" rm -f "$WARP_LOG"
echo -e " ${GREEN}${NC} Конфигурация и логи удалены" echo -e " ${GREEN}${NC} Конфигурация и логи удалены"
echo -e " ${YELLOW}[6/6]${NC} Удаление команды gowarp..."
rm -f /usr/local/bin/gowarp rm -f /usr/local/bin/gowarp
echo -e " ${GREEN}${NC} Команда gowarp удалена" echo -e " ${GREEN}${NC} Команда gowarp удалена"
@@ -474,6 +501,297 @@ full_uninstall() {
exit 0 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="<b>WARP Manager v${WARP_VERSION}</b>\nСервер: <code>${MY_IP:-N/A}</code>\nСтатус: <b>${ws}</b>${wip}\nSOCKS5: <code>127.0.0.1:${SOCKS_PORT}</code>\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: <code>$(get_warp_ip)</code>"
local raw
raw=$(warp-cli --accept-tos status 2>/dev/null | head -3)
local text="📊 <b>Статус WARP</b>\n\nСтатус: <b>${ws}</b>\nSOCKS5: <code>127.0.0.1:${SOCKS_PORT}</code>\nСервер: <code>${MY_IP:-N/A}</code>${wip}\n\n<pre>${raw}</pre>"
tg_edit "$chat_id" "$msg_id" "$text" "$(kbd_back)" ;;
ip)
local wip="N/A"
is_warp_running && wip=$(get_warp_ip)
local text="🌐 <b>IP адреса</b>\n\n<b>Реальный IP:</b> <code>${MY_IP:-N/A}</code>\n<b>WARP IP:</b> <code>${wip}</code>\n<b>SOCKS5:</b> <code>127.0.0.1:${SOCKS_PORT}</code>"
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" "✅ <b>WARP подключён</b>\nWARP IP: <code>${wip}</code>" "$(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" "⏹ <b>WARP отключён.</b>" "$(kbd_back)" ;;
rk)
tg_edit "$chat_id" "$msg_id" "🔑 <b>Перевыпуск ключа</b>\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" "✅ <b>Ключ перевыпущен</b>\nНовый WARP IP: <code>${wip}</code>" "$(kbd_back)"
else
tg_edit "$chat_id" "$msg_id" "⚠️ Ключ перевыпущен, подключение не подтверждено." "$(kbd_back)"
fi ;;
js)
local text="📋 <b>Конфигурация для 3X-UI</b>\n\n<b>Outbound:</b>\n<pre>{\n \"tag\": \"warp\",\n \"protocol\": \"socks\",\n \"settings\": {\n \"servers\": [{\n \"address\": \"127.0.0.1\",\n \"port\": ${SOCKS_PORT}\n }]\n }\n}</pre>\n\n<b>Routing rule:</b>\n<pre>{\n \"outboundTag\": \"warp\",\n \"domain\": [\n \"geosite:openai\",\n \"geosite:netflix\"\n ]\n}</pre>"
tg_edit "$chat_id" "$msg_id" "$text" "$(kbd_back)" ;;
sys)
local s
s=$(get_system_stats)
local ws
ws=$(get_warp_status_text)
s+="\n<b>WARP:</b> ${ws}"
s+="\n<b>SOCKS5:</b> 127.0.0.1:${SOCKS_PORT}"
tg_edit "$chat_id" "$msg_id" "$s" "$(kbd_back)" ;;
promo)
local pt="<b>🏢 Хостинг, который работает</b>\n\n<b>🌍 РФ и Европа</b>\n👉 https://vk.cc/ct29NQ\n\n<code>OFF60</code> — 60% скидка\n<code>antenka20</code> — +20% (ес)\n<code>antenka6</code> — +15% (ес)\n<code>antenka12</code> — +5% (12мес)\n\n<b>🇧🇾 Беларусь</b>\n👉 https://vk.cc/cUxAhj\n<code>OFF60</code> — 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<cnt; i++ )); do
local upd
upd=$(echo "$response" | jq ".result[$i]")
local uid
uid=$(echo "$upd" | jq -r '.update_id')
offset=$((uid + 1))
local cbd
cbd=$(echo "$upd" | jq -r '.callback_query.data // empty')
if [ -n "$cbd" ]; then
local cbi cci cmi
cbi=$(echo "$upd" | jq -r '.callback_query.id')
cci=$(echo "$upd" | jq -r '.callback_query.message.chat.id')
cmi=$(echo "$upd" | jq -r '.callback_query.message.message_id')
[ -n "$BOT_CHAT_ID" ] && [ "$cci" != "$BOT_CHAT_ID" ] && tg_answer_cb "$cbi" "Unauthorized" > /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: <code>$mci</code>" "" > /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 <<EOF
[Unit]
Description=WARP Manager Telegram Bot
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/gowarp --bot-daemon
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable warp-bot > /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 # PROMO
# ═══════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════
@@ -510,14 +828,6 @@ show_info() {
echo -e " Ваш VPS получает «чистый» IP-адрес Cloudflare, который" echo -e " Ваш VPS получает «чистый» IP-адрес Cloudflare, который"
echo -e " не заблокирован популярными сервисами.${NC}" echo -e " не заблокирован популярными сервисами.${NC}"
echo "" 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 -e "${CYAN}═══ СХЕМА РАБОТЫ ═══${NC}"
echo "" echo ""
echo -e "${WHITE} Клиент → 3X-UI (Xray) → SOCKS5 (WARP) → Cloudflare → Интернет${NC}" 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} Разблокировка ChatGPT, Netflix, Disney+, Spotify"
echo -e " ${GREEN}${NC} Чистый IPv4/IPv6 от Cloudflare" echo -e " ${GREEN}${NC} Чистый IPv4/IPv6 от Cloudflare"
echo -e " ${GREEN}${NC} Стабильный маршрут через сеть Cloudflare" echo -e " ${GREEN}${NC} Стабильный маршрут через сеть Cloudflare"
echo -e " ${GREEN}${NC} Гибкая маршрутизация: часть сайтов через WARP, остальные напрямую" echo -e " ${GREEN}${NC} Управление через Telegram-бот"
echo -e " ${GREEN}${NC} Бесплатно (Cloudflare WARP — бесплатный сервис)" echo -e " ${GREEN}${NC} Бесплатно (Cloudflare WARP — бесплатный сервис)"
echo "" echo ""
echo -e "${MAGENTA}──────────────────────────────────────────────────────────────${NC}" echo -e "${MAGENTA}──────────────────────────────────────────────────────────────${NC}"
@@ -568,9 +878,10 @@ show_menu() {
echo -e " 5) 📋 ${CYAN}JSON для 3X-UI${NC}" echo -e " 5) 📋 ${CYAN}JSON для 3X-UI${NC}"
echo -e " 6) 🔑 ${YELLOW}Перевыпуск ключа${NC}" echo -e " 6) 🔑 ${YELLOW}Перевыпуск ключа${NC}"
echo -e " 7) 🔧 ${WHITE}Изменить порт SOCKS5${NC}" echo -e " 7) 🔧 ${WHITE}Изменить порт SOCKS5${NC}"
echo -e " 8) ${YELLOW}PROMO${NC}" echo -e " 8) 🤖 ${CYAN}Telegram Bot${NC}"
echo -e " 9) ${MAGENTA}📚 Инструкция${NC}" echo -e " 9) ${YELLOW}PROMO${NC}"
echo -e "10) ${RED}⚠ Полное удаление${NC}" echo -e "10) ${MAGENTA}📚 Инструкция${NC}"
echo -e "11) ${RED}⚠ Полное удаление${NC}"
echo -e " 0) Выход" echo -e " 0) Выход"
echo -e "------------------------------------------------------" echo -e "------------------------------------------------------"
read -p "Выбор: " ch read -p "Выбор: " ch
@@ -582,9 +893,10 @@ show_menu() {
5) show_xui_json ;; 5) show_xui_json ;;
6) rekey_warp ;; 6) rekey_warp ;;
7) change_port ;; 7) change_port ;;
8) show_promo ;; 8) bot_menu ;;
9) show_info ;; 9) show_promo ;;
10) full_uninstall ;; 10) show_info ;;
11) full_uninstall ;;
0) exit 0 ;; 0) exit 0 ;;
esac esac
done done
@@ -595,7 +907,7 @@ show_menu() {
# ═══════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════
run_startup() { run_startup() {
local total=5 s=0 local total=6 s=0
clear; echo "" clear; echo ""
echo -e "${MAGENTA}╔══════════════════════════════════════════════════════════════╗${NC}" echo -e "${MAGENTA}╔══════════════════════════════════════════════════════════════╗${NC}"
@@ -613,6 +925,11 @@ run_startup() {
init_config init_config
printf "\r ${CYAN}[%d/%d]${NC} ${GREEN}${NC} Конфигурация загружена \n" "$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++)) ((s++))
printf " ${CYAN}[%d/%d]${NC} ${YELLOW}${NC} Установка gowarp..." "$s" "$total" printf " ${CYAN}[%d/%d]${NC} ${YELLOW}${NC} Установка gowarp..." "$s" "$total"
if [ "$(readlink -f "$0" 2>/dev/null)" != "/usr/local/bin/gowarp" ]; then if [ "$(readlink -f "$0" 2>/dev/null)" != "/usr/local/bin/gowarp" ]; then
@@ -649,4 +966,7 @@ run_startup() {
# ENTRY POINT # ENTRY POINT
# ═══════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════
run_startup case "${1:-}" in
--bot-daemon) init_config; bot_daemon ;;
*) run_startup ;;
esac