mirror of
https://github.com/anten-ka/go_warp_pro.git
synced 2026-05-20 08:36:10 +00:00
v2.2: multi-admin bot, improved chat ID detect, multi-container AWG v1+v2, container check menu
Made-with: Cursor
This commit is contained in:
266
warp.sh
266
warp.sh
@@ -2,12 +2,12 @@
|
|||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
# ══════════════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════════════
|
||||||
# WARP Manager v2.1 — Unified 3X-UI + AmneziaWG
|
# WARP Manager v2.2 — Unified 3X-UI + AmneziaWG
|
||||||
# Cloudflare WARP · Telegram Bot · Auto-detect mode
|
# Cloudflare WARP · Telegram Bot · Auto-detect mode
|
||||||
# Channel: https://www.youtube.com/@antenkaru
|
# Channel: https://www.youtube.com/@antenkaru
|
||||||
# ══════════════════════════════════════════════════════════════
|
# ══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
WARP_VERSION="2.1"
|
WARP_VERSION="2.2"
|
||||||
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"
|
||||||
@@ -43,6 +43,7 @@ LICENSE_KEY=""
|
|||||||
MODE=""
|
MODE=""
|
||||||
|
|
||||||
CONTAINER=""
|
CONTAINER=""
|
||||||
|
CONTAINERS=""
|
||||||
AWG_VPN_CONF=""
|
AWG_VPN_CONF=""
|
||||||
AWG_VPN_IF=""
|
AWG_VPN_IF=""
|
||||||
AWG_VPN_QUICK_CMD=""
|
AWG_VPN_QUICK_CMD=""
|
||||||
@@ -53,6 +54,7 @@ AWG_WARP_EXIT_IP=""
|
|||||||
declare -a AWG_SELECTED_IPS=()
|
declare -a AWG_SELECTED_IPS=()
|
||||||
declare -a AWG_CLIENT_IPS=()
|
declare -a AWG_CLIENT_IPS=()
|
||||||
declare -A AWG_CLIENT_NAMES=()
|
declare -A AWG_CLIENT_NAMES=()
|
||||||
|
declare -a AWG_ALL_CONTAINERS=()
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════
|
||||||
# CONFIG
|
# CONFIG
|
||||||
@@ -68,6 +70,7 @@ BOT_CHAT_ID=""
|
|||||||
LICENSE_KEY=""
|
LICENSE_KEY=""
|
||||||
MODE=""
|
MODE=""
|
||||||
CONTAINER=""
|
CONTAINER=""
|
||||||
|
CONTAINERS=""
|
||||||
CONF
|
CONF
|
||||||
fi
|
fi
|
||||||
source "$WARP_CONF"
|
source "$WARP_CONF"
|
||||||
@@ -522,40 +525,63 @@ uninstall_3xui() {
|
|||||||
# AMNEZIA BACKEND — WARP via wgcf (WireGuard inside Docker)
|
# AMNEZIA BACKEND — WARP via wgcf (WireGuard inside Docker)
|
||||||
# ═══════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
awg_discover_containers() {
|
||||||
|
AWG_ALL_CONTAINERS=()
|
||||||
|
mapfile -t AWG_ALL_CONTAINERS < <(docker ps --format '{{.Names}}' 2>/dev/null | grep -E '^amnezia-awg2$|^amnezia-awg$' || true)
|
||||||
|
if [ ${#AWG_ALL_CONTAINERS[@]} -eq 0 ]; then
|
||||||
|
mapfile -t AWG_ALL_CONTAINERS < <(docker ps --format '{{.Names}}' 2>/dev/null | grep -i "amnezia" || true)
|
||||||
|
fi
|
||||||
|
if [ ${#AWG_ALL_CONTAINERS[@]} -eq 0 ]; then
|
||||||
|
echo -e "${RED}Контейнеры amnezia-awg / amnezia-awg2 не найдены.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
CONTAINERS="${AWG_ALL_CONTAINERS[*]}"
|
||||||
|
save_config_val "CONTAINERS" "$CONTAINERS"
|
||||||
|
CONTAINER="${AWG_ALL_CONTAINERS[0]}"
|
||||||
|
save_config_val "CONTAINER" "$CONTAINER"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
awg_pick_container() {
|
awg_pick_container() {
|
||||||
if [ -n "${CONTAINER:-}" ]; then
|
if [ -n "${CONTAINER:-}" ]; then
|
||||||
docker exec "$CONTAINER" sh -c "true" 2>/dev/null && return 0
|
docker exec "$CONTAINER" sh -c "true" 2>/dev/null && return 0
|
||||||
CONTAINER=""
|
CONTAINER=""
|
||||||
fi
|
fi
|
||||||
|
awg_discover_containers || return 1
|
||||||
local -a containers=()
|
if [ ${#AWG_ALL_CONTAINERS[@]} -eq 1 ]; then
|
||||||
mapfile -t containers < <(docker ps --format '{{.Names}}' | grep -E '^amnezia-awg2$|^amnezia-awg$' 2>/dev/null || true)
|
CONTAINER="${AWG_ALL_CONTAINERS[0]}"
|
||||||
|
|
||||||
if [ ${#containers[@]} -eq 0 ]; then
|
|
||||||
mapfile -t containers < <(docker ps --format '{{.Names}}' 2>/dev/null | grep -i "amnezia" || true)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ${#containers[@]} -eq 0 ]; then
|
|
||||||
echo -e "${RED}Контейнеры amnezia-awg / amnezia-awg2 не найдены.${NC}"
|
|
||||||
echo -e "${WHITE}Убедитесь, что AmneziaWG запущен через Docker.${NC}"
|
|
||||||
return 1
|
|
||||||
elif [ ${#containers[@]} -eq 1 ]; then
|
|
||||||
CONTAINER="${containers[0]}"
|
|
||||||
else
|
|
||||||
echo -e "\n${CYAN}Доступные контейнеры:${NC}"
|
|
||||||
local i=1
|
|
||||||
for c in "${containers[@]}"; do echo -e " ${GREEN}$i)${NC} $c"; ((i++)); done
|
|
||||||
echo -e " ${DIM}0) Отмена${NC}"
|
|
||||||
while true; do
|
|
||||||
read -p "Выберите контейнер: " ch
|
|
||||||
[ "$ch" = "0" ] && return 1
|
|
||||||
[[ "$ch" =~ ^[0-9]+$ ]] && (( ch >= 1 && ch <= ${#containers[@]} )) && { CONTAINER="${containers[$((ch-1))]}"; break; }
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
save_config_val "CONTAINER" "$CONTAINER"
|
save_config_val "CONTAINER" "$CONTAINER"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
awg_select_container() {
|
||||||
|
awg_discover_containers 2>/dev/null
|
||||||
|
if [ ${#AWG_ALL_CONTAINERS[@]} -le 1 ]; then
|
||||||
|
CONTAINER="${AWG_ALL_CONTAINERS[0]:-}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo -e "\n${CYAN}Выберите контейнер:${NC}"
|
||||||
|
local i=1
|
||||||
|
for c in "${AWG_ALL_CONTAINERS[@]}"; do
|
||||||
|
local has_warp="нет"
|
||||||
|
docker exec "$c" sh -c "[ -f '/opt/warp/warp.conf' ]" 2>/dev/null && has_warp="${GREEN}да${NC}"
|
||||||
|
echo -e " ${GREEN}$i)${NC} $c [WARP: $has_warp]"
|
||||||
|
((i++))
|
||||||
|
done
|
||||||
|
echo -e " ${DIM}0) Отмена${NC}"
|
||||||
|
while true; do
|
||||||
|
read -p " > " ch
|
||||||
|
[ "$ch" = "0" ] && return 1
|
||||||
|
if [[ "$ch" =~ ^[0-9]+$ ]] && (( ch >= 1 && ch <= ${#AWG_ALL_CONTAINERS[@]} )); then
|
||||||
|
CONTAINER="${AWG_ALL_CONTAINERS[$((ch-1))]}"
|
||||||
|
save_config_val "CONTAINER" "$CONTAINER"
|
||||||
|
awg_load_container_data
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
awg_load_container_data() {
|
awg_load_container_data() {
|
||||||
if [ "$CONTAINER" = "amnezia-awg2" ]; then
|
if [ "$CONTAINER" = "amnezia-awg2" ]; then
|
||||||
AWG_VPN_CONF="/opt/amnezia/awg/awg0.conf"
|
AWG_VPN_CONF="/opt/amnezia/awg/awg0.conf"
|
||||||
@@ -818,6 +844,44 @@ uninstall_awg() {
|
|||||||
echo -e " ${GREEN}✓${NC} wgcf и профили удалены"
|
echo -e " ${GREEN}✓${NC} wgcf и профили удалены"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
awg_check_containers() {
|
||||||
|
clear; echo -e "\n${CYAN}━━━ Контейнеры AmneziaWG ━━━${NC}\n"
|
||||||
|
local saved_container="${CONTAINER:-}"
|
||||||
|
awg_discover_containers 2>/dev/null
|
||||||
|
# discover persists CONTAINER=first match; restore user's choice (or "") on disk
|
||||||
|
CONTAINER="$saved_container"
|
||||||
|
save_config_val "CONTAINER" "$saved_container"
|
||||||
|
if [ ${#AWG_ALL_CONTAINERS[@]} -eq 0 ]; then
|
||||||
|
echo -e " ${RED}Контейнеры не найдены.${NC}"
|
||||||
|
read -p " Enter..."; return
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf " ${WHITE}%-20s %-10s %-10s %-12s${NC}\n" "Контейнер" "Статус" "WARP" "Клиентов"
|
||||||
|
echo -e " ${CYAN}────────────────────────────────────────────────────${NC}"
|
||||||
|
for c in "${AWG_ALL_CONTAINERS[@]}"; do
|
||||||
|
local status="Running"
|
||||||
|
docker exec "$c" sh -c "true" 2>/dev/null || status="${RED}Down${NC}"
|
||||||
|
[ "$status" = "Running" ] && status="${GREEN}Running${NC}"
|
||||||
|
|
||||||
|
local has_warp="${DIM}Нет${NC}"
|
||||||
|
local client_info="—"
|
||||||
|
if docker exec "$c" sh -c "[ -f '/opt/warp/warp.conf' ]" 2>/dev/null; then
|
||||||
|
local warp_up="${YELLOW}Выкл${NC}"
|
||||||
|
docker exec "$c" sh -c "ip addr show warp >/dev/null 2>&1" 2>/dev/null && warp_up="${GREEN}Вкл${NC}"
|
||||||
|
has_warp="$warp_up"
|
||||||
|
local cnt; cnt=$(docker exec "$c" sh -c "cat /opt/warp/clients.list 2>/dev/null | grep -c '.' || echo 0" | tr -d '\r')
|
||||||
|
client_info="${cnt}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local marker=""
|
||||||
|
[ "$c" = "${CONTAINER:-}" ] && marker=" ${CYAN}*${NC}"
|
||||||
|
printf " %-20s %-22b %-22b %-12s%b\n" "$c" "$status" "$has_warp" "$client_info" "$marker"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "\n ${DIM}* = текущий контейнер${NC}"
|
||||||
|
echo ""; read -p " Enter..."
|
||||||
|
}
|
||||||
|
|
||||||
awg_restart_container() {
|
awg_restart_container() {
|
||||||
echo -e "\n${YELLOW}Перезапуск контейнера ${CONTAINER}...${NC}"
|
echo -e "\n${YELLOW}Перезапуск контейнера ${CONTAINER}...${NC}"
|
||||||
docker restart "$CONTAINER" >/dev/null
|
docker restart "$CONTAINER" >/dev/null
|
||||||
@@ -938,6 +1002,9 @@ awg_get_client_ips() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
awg_toggle_clients_ssh() {
|
awg_toggle_clients_ssh() {
|
||||||
|
if [ ${#AWG_ALL_CONTAINERS[@]} -gt 1 ]; then
|
||||||
|
awg_select_container || return
|
||||||
|
fi
|
||||||
awg_get_client_ips; awg_parse_clients_table; awg_load_clients
|
awg_get_client_ips; awg_parse_clients_table; awg_load_clients
|
||||||
|
|
||||||
if [ ${#AWG_CLIENT_IPS[@]} -eq 0 ]; then
|
if [ ${#AWG_CLIENT_IPS[@]} -eq 0 ]; then
|
||||||
@@ -950,7 +1017,8 @@ awg_toggle_clients_ssh() {
|
|||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
local pending_set=" ${pending_ips[*]+"${pending_ips[*]}"} "
|
local pending_set=" ${pending_ips[*]+"${pending_ips[*]}"} "
|
||||||
clear; echo -e "\n${CYAN}━━━ Управление клиентами WARP ━━━${NC}\n"
|
clear; echo -e "\n${CYAN}━━━ Управление клиентами WARP ━━━${NC}"
|
||||||
|
[ ${#AWG_ALL_CONTAINERS[@]} -gt 1 ] && echo -e " ${DIM}Контейнер: ${CONTAINER}${NC}"
|
||||||
echo -e " ${DIM}Нажмите номер чтобы вкл/выкл WARP для клиента${NC}\n"
|
echo -e " ${DIM}Нажмите номер чтобы вкл/выкл WARP для клиента${NC}\n"
|
||||||
|
|
||||||
local i=1 warp_count=0
|
local i=1 warp_count=0
|
||||||
@@ -1502,14 +1570,14 @@ bot_daemon() {
|
|||||||
cbi=$(echo "$upd" | jq -r '.callback_query.id')
|
cbi=$(echo "$upd" | jq -r '.callback_query.id')
|
||||||
cci=$(echo "$upd" | jq -r '.callback_query.message.chat.id')
|
cci=$(echo "$upd" | jq -r '.callback_query.message.chat.id')
|
||||||
cmi=$(echo "$upd" | jq -r '.callback_query.message.message_id')
|
cmi=$(echo "$upd" | jq -r '.callback_query.message.message_id')
|
||||||
[ -n "$BOT_CHAT_ID" ] && [ "$cci" != "$BOT_CHAT_ID" ] && { tg_answer_cb "$cbi" "Нет доступа" > /dev/null; continue; }
|
if ! is_bot_admin "$cci"; then tg_answer_cb "$cbi" "Нет доступа" > /dev/null; continue; fi
|
||||||
bot_handle_callback "$cci" "$cmi" "$cbi" "$cbd"
|
bot_handle_callback "$cci" "$cmi" "$cbi" "$cbd"
|
||||||
else
|
else
|
||||||
local mci mtx
|
local mci mtx
|
||||||
mci=$(echo "$upd" | jq -r '.message.chat.id // empty')
|
mci=$(echo "$upd" | jq -r '.message.chat.id // empty')
|
||||||
mtx=$(echo "$upd" | jq -r '.message.text // empty')
|
mtx=$(echo "$upd" | jq -r '.message.text // empty')
|
||||||
if [ -n "$mci" ] && [ -n "$mtx" ]; then
|
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 ! is_bot_admin "$mci"; then tg_send "$mci" "⛔ Нет доступа.\nChat ID: <code>$mci</code>" "" > /dev/null; continue; fi
|
||||||
if [[ "$mtx" == "/start" || "$mtx" == "/menu" ]]; then
|
if [[ "$mtx" == "/start" || "$mtx" == "/menu" ]]; then
|
||||||
bot_main_menu "$mci"
|
bot_main_menu "$mci"
|
||||||
else
|
else
|
||||||
@@ -1552,16 +1620,66 @@ stop_bot() {
|
|||||||
echo -e "${GREEN}[OK] Бот остановлен.${NC}"; log_action "Bot stopped"
|
echo -e "${GREEN}[OK] Бот остановлен.${NC}"; log_action "Bot stopped"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_bot_admin() {
|
||||||
|
local id="$1"
|
||||||
|
[ -z "${BOT_CHAT_ID:-}" ] && return 0
|
||||||
|
local admin
|
||||||
|
for admin in $BOT_CHAT_ID; do
|
||||||
|
[ "$admin" = "$id" ] && return 0
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
bot_add_admin() {
|
||||||
|
local new_id="$1"
|
||||||
|
[ -z "$new_id" ] && return 1
|
||||||
|
if ! is_bot_admin "$new_id"; then
|
||||||
|
if [ -n "${BOT_CHAT_ID:-}" ]; then
|
||||||
|
BOT_CHAT_ID="${BOT_CHAT_ID} ${new_id}"
|
||||||
|
else
|
||||||
|
BOT_CHAT_ID="$new_id"
|
||||||
|
fi
|
||||||
|
save_config_val "BOT_CHAT_ID" "$BOT_CHAT_ID"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
bot_remove_admin() {
|
||||||
|
local rm_id="$1"
|
||||||
|
local -a new_list=()
|
||||||
|
for admin in $BOT_CHAT_ID; do
|
||||||
|
[ "$admin" != "$rm_id" ] && new_list+=("$admin")
|
||||||
|
done
|
||||||
|
BOT_CHAT_ID="${new_list[*]+"${new_list[*]}"}"
|
||||||
|
save_config_val "BOT_CHAT_ID" "$BOT_CHAT_ID"
|
||||||
|
}
|
||||||
|
|
||||||
bot_auto_chatid() {
|
bot_auto_chatid() {
|
||||||
echo -e "${YELLOW} Отправьте боту любое сообщение в Telegram, затем нажмите Enter.${NC}"
|
systemctl stop warp-bot 2>/dev/null
|
||||||
|
sleep 1
|
||||||
|
local flush_resp last_uid
|
||||||
|
flush_resp=$(curl -s "https://api.telegram.org/bot${BOT_TOKEN}/getUpdates?offset=-1&limit=1")
|
||||||
|
last_uid=$(echo "$flush_resp" | jq -r '.result[-1].update_id // empty' 2>/dev/null)
|
||||||
|
if [ -n "$last_uid" ]; then
|
||||||
|
curl -s "https://api.telegram.org/bot${BOT_TOKEN}/getUpdates?offset=$((last_uid + 1))&limit=1" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
echo -e "${YELLOW} Отправьте боту 3 любых сообщения в Telegram.${NC}"
|
||||||
|
echo -e "${YELLOW} Затем нажмите Enter.${NC}"
|
||||||
read -p " > " _
|
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')
|
local resp; resp=$(curl -s --max-time 10 "https://api.telegram.org/bot${BOT_TOKEN}/getUpdates?limit=10")
|
||||||
if [ -n "$c" ]; then
|
local c; c=$(echo "$resp" | jq -r '[.result[].message.chat.id // empty] | map(select(. != "")) | unique | first // empty' 2>/dev/null)
|
||||||
save_config_val "BOT_CHAT_ID" "$c"; BOT_CHAT_ID="$c"
|
if [ -n "$c" ] && [[ "$c" =~ ^[0-9-]+$ ]]; then
|
||||||
echo -e " ${GREEN}✓ Chat ID: $c${NC}"
|
bot_add_admin "$c"
|
||||||
|
echo -e " ${GREEN}✓ Chat ID: $c (добавлен как админ)${NC}"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo -e " ${RED}✗ Не удалось определить Chat ID.${NC}"
|
echo -e " ${RED}✗ Не удалось определить Chat ID.${NC}"
|
||||||
|
echo -e ""
|
||||||
|
echo -e " ${WHITE}Получите Chat ID вручную:${NC}"
|
||||||
|
echo -e " ${CYAN}1.${NC} Откройте ${GREEN}@userinfobot${NC} в Telegram"
|
||||||
|
echo -e " ${CYAN}2.${NC} Нажмите /start"
|
||||||
|
echo -e " ${CYAN}3.${NC} Скопируйте число ${WHITE}Id: XXXXXXXX${NC}"
|
||||||
|
echo -e " ${CYAN}4.${NC} Впишите через меню бота (п. Добавить админа)"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -1600,6 +1718,20 @@ bot_wizard() {
|
|||||||
read -p " Enter..."
|
read -p " Enter..."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bot_show_admins() {
|
||||||
|
echo -e "\n ${CYAN}Администраторы бота:${NC}"
|
||||||
|
if [ -z "${BOT_CHAT_ID:-}" ]; then
|
||||||
|
echo -e " ${YELLOW}Нет (бот доступен всем)${NC}"
|
||||||
|
else
|
||||||
|
local i=1
|
||||||
|
for admin in $BOT_CHAT_ID; do
|
||||||
|
echo -e " ${GREEN}$i)${NC} $admin"
|
||||||
|
((i++))
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
bot_menu() {
|
bot_menu() {
|
||||||
source "$WARP_CONF" 2>/dev/null
|
source "$WARP_CONF" 2>/dev/null
|
||||||
if [ -z "${BOT_TOKEN:-}" ]; then
|
if [ -z "${BOT_TOKEN:-}" ]; then
|
||||||
@@ -1612,28 +1744,60 @@ bot_menu() {
|
|||||||
local bs="${RED}Выкл${NC}"
|
local bs="${RED}Выкл${NC}"
|
||||||
systemctl is-active warp-bot &>/dev/null && bs="${GREEN}Вкл${NC}"
|
systemctl is-active warp-bot &>/dev/null && bs="${GREEN}Вкл${NC}"
|
||||||
local td="***${BOT_TOKEN: -6}"
|
local td="***${BOT_TOKEN: -6}"
|
||||||
|
local admin_count=0
|
||||||
|
[ -n "${BOT_CHAT_ID:-}" ] && admin_count=$(echo "$BOT_CHAT_ID" | wc -w)
|
||||||
|
|
||||||
echo -e "\n${CYAN}━━━ Telegram Bot ━━━${NC}\n"
|
echo -e "\n${CYAN}━━━ Telegram Bot ━━━${NC}\n"
|
||||||
echo -e " Статус: $bs"
|
echo -e " Статус: $bs"
|
||||||
echo -e " Токен: ${YELLOW}$td${NC}"
|
echo -e " Токен: ${YELLOW}$td${NC}"
|
||||||
echo -e " Chat ID: ${YELLOW}${BOT_CHAT_ID:-нет}${NC}\n"
|
echo -e " Админов: ${YELLOW}${admin_count}${NC}\n"
|
||||||
echo -e " 1) Изменить токен"
|
|
||||||
echo -e " 2) Chat ID (авто)"
|
echo -e " ${CYAN}── Управление ──${NC}"
|
||||||
echo -e " 3) Chat ID (вручную)"
|
echo -e " 1) ${GREEN}Запустить${NC}"
|
||||||
echo -e " 4) ${GREEN}Запустить${NC}"
|
echo -e " 2) ${RED}Остановить${NC}"
|
||||||
echo -e " 5) ${RED}Остановить${NC}"
|
echo -e " 3) Изменить токен"
|
||||||
echo -e " 0) Назад"
|
|
||||||
|
echo -e "\n ${CYAN}── Администраторы ──${NC}"
|
||||||
|
echo -e " 4) Показать админов"
|
||||||
|
echo -e " 5) Добавить админа (авто — по сообщению)"
|
||||||
|
echo -e " 6) Добавить админа (вручную — Chat ID)"
|
||||||
|
echo -e " 7) Убрать админа"
|
||||||
|
|
||||||
|
echo -e "\n 0) Назад"
|
||||||
echo ""
|
echo ""
|
||||||
read -p " Выбор: " ch
|
read -p " Выбор: " ch
|
||||||
case $ch in
|
case $ch in
|
||||||
1) echo " Токен:"; read -p " > " t
|
1) start_bot; read -p " Enter..." ;;
|
||||||
|
2) stop_bot; read -p " Enter..." ;;
|
||||||
|
3) echo " Токен:"; read -p " > " t
|
||||||
[ -n "$t" ] && save_config_val "BOT_TOKEN" "$t" && BOT_TOKEN="$t" && echo -e " ${GREEN}OK${NC}"
|
[ -n "$t" ] && save_config_val "BOT_TOKEN" "$t" && BOT_TOKEN="$t" && echo -e " ${GREEN}OK${NC}"
|
||||||
read -p " Enter..." ;;
|
read -p " Enter..." ;;
|
||||||
2) bot_auto_chatid; read -p " Enter..." ;;
|
4) bot_show_admins; read -p " Enter..." ;;
|
||||||
3) echo " Chat ID:"; read -p " > " c
|
5) bot_auto_chatid; read -p " Enter..." ;;
|
||||||
[ -n "$c" ] && save_config_val "BOT_CHAT_ID" "$c" && BOT_CHAT_ID="$c" && echo -e " ${GREEN}OK${NC}"
|
6) echo -e "\n ${WHITE}Как узнать Chat ID: откройте ${GREEN}@userinfobot${WHITE} → /start → скопируйте Id${NC}"
|
||||||
|
echo " Chat ID:"; read -p " > " c
|
||||||
|
if [ -n "$c" ] && [[ "$c" =~ ^[0-9-]+$ ]]; then
|
||||||
|
bot_add_admin "$c"
|
||||||
|
echo -e " ${GREEN}✓ Админ $c добавлен${NC}"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}Некорректный ID${NC}"
|
||||||
|
fi
|
||||||
|
read -p " Enter..." ;;
|
||||||
|
7) if [ -z "${BOT_CHAT_ID:-}" ]; then
|
||||||
|
echo -e "\n ${YELLOW}Нет админов.${NC}"; read -p " Enter..."; continue
|
||||||
|
fi
|
||||||
|
bot_show_admins
|
||||||
|
echo " Номер для удаления (0 — отмена):"
|
||||||
|
read -p " > " num
|
||||||
|
if [ "$num" != "0" ] && [[ "$num" =~ ^[0-9]+$ ]]; then
|
||||||
|
local -a admins=($BOT_CHAT_ID)
|
||||||
|
if (( num >= 1 && num <= ${#admins[@]} )); then
|
||||||
|
local rm_id="${admins[$((num-1))]}"
|
||||||
|
bot_remove_admin "$rm_id"
|
||||||
|
echo -e " ${GREEN}✓ Админ $rm_id удалён${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
read -p " Enter..." ;;
|
read -p " Enter..." ;;
|
||||||
4) start_bot; read -p " Enter..." ;;
|
|
||||||
5) stop_bot; read -p " Enter..." ;;
|
|
||||||
0) return ;;
|
0) return ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@@ -1767,7 +1931,10 @@ show_menu() {
|
|||||||
echo -e "\n${CYAN}── Прочее ─────────────────────────────────────────────${NC}"
|
echo -e "\n${CYAN}── Прочее ─────────────────────────────────────────────${NC}"
|
||||||
echo -e " 9) ${YELLOW}PROMO${NC}"
|
echo -e " 9) ${YELLOW}PROMO${NC}"
|
||||||
echo -e " 10) ${MAGENTA}📚 Инструкция${NC}"
|
echo -e " 10) ${MAGENTA}📚 Инструкция${NC}"
|
||||||
echo -e " 11) ${RED}⚠ Полное удаление${NC}"
|
if has_awg_mode; then
|
||||||
|
echo -e " 11) 🔍 ${WHITE}Проверить контейнеры${NC}"
|
||||||
|
fi
|
||||||
|
echo -e " 12) ${RED}⚠ Полное удаление${NC}"
|
||||||
echo -e " 0) Выход"
|
echo -e " 0) Выход"
|
||||||
echo -e "${CYAN}──────────────────────────────────────────────────────${NC}"
|
echo -e "${CYAN}──────────────────────────────────────────────────────${NC}"
|
||||||
read -p " Выбор: " ch
|
read -p " Выбор: " ch
|
||||||
@@ -1788,7 +1955,8 @@ show_menu() {
|
|||||||
8) bot_menu ;;
|
8) bot_menu ;;
|
||||||
9) show_promo ;;
|
9) show_promo ;;
|
||||||
10) show_info ;;
|
10) show_info ;;
|
||||||
11) full_uninstall ;;
|
11) has_awg_mode && awg_check_containers ;;
|
||||||
|
12) full_uninstall ;;
|
||||||
0) exit 0 ;;
|
0) exit 0 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user