diff --git a/install.sh b/install.sh index 37f22e4..f161a92 100644 --- a/install.sh +++ b/install.sh @@ -12,6 +12,53 @@ BLUE='\033[0;34m' WHITE='\033[1;37m' NC='\033[0m' +# ── Спиннер и прогресс-бар ──────────────────────────────────────────────────── +spin_pid="" +spinner_start() { + local msg="${1:-Подождите...}" + ( + local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏') + local i=0 + while true; do + printf "\r ${CYAN}${frames[$i]}${NC} ${msg}" >&2 + i=$(( (i+1) % ${#frames[@]} )) + sleep 0.12 + done + ) & + spin_pid=$! +} +spinner_stop() { + [ -n "$spin_pid" ] && kill "$spin_pid" 2>/dev/null && wait "$spin_pid" 2>/dev/null + spin_pid="" + printf "\r\033[K" >&2 +} + +progress_bar() { + local current="$1" total="$2" label="${3:-}" + local pct=$(( current * 100 / total )) + local filled=$(( pct / 2 )) + local empty=$(( 50 - filled )) + local bar="" + for ((i=0; i&2 + [ "$current" -eq "$total" ] && echo "" >&2 +} + +run_with_progress() { + local label="$1"; shift + spinner_start "$label" + "$@" >/dev/null 2>&1 + local rc=$? + spinner_stop + if [ $rc -eq 0 ]; then + echo -e " ${GREEN}✓${NC} $label" + else + echo -e " ${RED}✗${NC} $label ${RED}(ошибка)${NC}" + fi + return $rc +} + # ── Конфиг ─────────────────────────────────────────────────────────────────── CONTAINER_NAME="mtproto-proxy" BOT_DIR="/opt/gotelegram-bot" @@ -37,24 +84,34 @@ install_pkg() { } install_base_deps() { - for cmd in curl docker; do - if ! command -v $cmd &>/dev/null; then - echo -e "${YELLOW}[*] Установка $cmd...${NC}" - if [ "$cmd" = "docker" ]; then - curl -fsSL https://get.docker.com | sh - systemctl enable --now docker - else - install_pkg $cmd - fi - fi - done - if ! command -v qrencode &>/dev/null; then - install_pkg qrencode 2>/dev/null || true + local steps=0 total=4 # curl, docker, qrencode, docker-start + + progress_bar $steps $total "Проверка зависимостей..." + if ! command -v curl &>/dev/null; then + run_with_progress "Установка curl" install_pkg curl fi + steps=$((steps+1)); progress_bar $steps $total "curl" + + if ! command -v docker &>/dev/null; then + spinner_start "Установка Docker (это может занять 1-2 минуты)..." + curl -fsSL https://get.docker.com | sh >/dev/null 2>&1 + systemctl enable --now docker >/dev/null 2>&1 + spinner_stop + echo -e " ${GREEN}✓${NC} Docker установлен" + fi + steps=$((steps+1)); progress_bar $steps $total "docker" + + if ! command -v qrencode &>/dev/null; then + run_with_progress "Установка qrencode" install_pkg qrencode + fi + steps=$((steps+1)); progress_bar $steps $total "qrencode" + if ! docker info &>/dev/null 2>&1; then systemctl start docker 2>/dev/null || true sleep 2 fi + steps=$((steps+1)); progress_bar $steps $total "Готово" + echo "" } # ── Утилиты ────────────────────────────────────────────────────────────────── @@ -225,6 +282,7 @@ menu_install() { echo "" echo -e "${YELLOW}[*] Настройка прокси (домен: $DOMAIN, порт: $PORT)...${NC}" + echo "" # Docker проверка if ! docker info &>/dev/null 2>&1; then @@ -233,43 +291,65 @@ menu_install() { return fi - # Генерация secret - echo -e "${GREEN}[*] Генерация secret...${NC}" - local SECRET + local SECRET install_steps=5 install_cur=0 + + # Шаг 1: pull образа (если нет) + install_cur=$((install_cur+1)); progress_bar $install_cur $install_steps "Загрузка образа mtg..." + if ! docker images --format '{{.Repository}}:{{.Tag}}' | grep -q "nineseconds/mtg:2"; then + spinner_start "Загрузка Docker-образа mtg (первый раз — до 1 мин)..." + docker pull nineseconds/mtg:2 >/dev/null 2>&1 + spinner_stop + fi + echo -e " ${GREEN}✓${NC} Образ mtg готов" + + # Шаг 2: генерация secret + install_cur=$((install_cur+1)); progress_bar $install_cur $install_steps "Генерация secret..." + spinner_start "Генерация secret для $DOMAIN..." SECRET=$(docker run --rm nineseconds/mtg:2 generate-secret --hex "$DOMAIN" 2>/dev/null) + spinner_stop if [ -z "$SECRET" ]; then - echo -e "${RED}Ошибка генерации secret.${NC}" + echo -e " ${RED}✗${NC} Ошибка генерации secret." read -p "Нажмите Enter..." return fi + echo -e " ${GREEN}✓${NC} Secret сгенерирован" - # Остановка старого + # Шаг 3: остановка старого + install_cur=$((install_cur+1)); progress_bar $install_cur $install_steps "Очистка..." docker stop "$CONTAINER_NAME" &>/dev/null docker rm "$CONTAINER_NAME" &>/dev/null + echo -e " ${GREEN}✓${NC} Старый контейнер удалён" - # Запуск с TCP + UDP (UDP для звонков) - echo -e "${GREEN}[*] Запуск контейнера (TCP + UDP)...${NC}" + # Шаг 4: запуск нового + install_cur=$((install_cur+1)); progress_bar $install_cur $install_steps "Запуск контейнера..." + spinner_start "Запуск MTProxy (TCP + UDP)..." docker run -d --name "$CONTAINER_NAME" --restart always \ -p "$PORT":"$PORT"/tcp \ -p "$PORT":"$PORT"/udp \ nineseconds/mtg:2 simple-run \ -n 1.1.1.1 -i prefer-ipv4 \ 0.0.0.0:"$PORT" "$SECRET" > /dev/null 2>&1 + sleep 2 + spinner_stop if ! proxy_is_running; then - echo -e "${RED}Контейнер не запустился. Проверьте: docker logs $CONTAINER_NAME${NC}" + echo -e " ${RED}✗${NC} Контейнер не запустился. Проверьте: docker logs $CONTAINER_NAME" read -p "Нажмите Enter..." return fi + echo -e " ${GREEN}✓${NC} Контейнер запущен" - # Сохраняем конфиг + # Шаг 5: сохранение + install_cur=$((install_cur+1)); progress_bar $install_cur $install_steps "Готово!" mkdir -p "$BOT_DIR" cat > "$BOT_DIR/proxy.json" << CFGEOF {"domain": "$DOMAIN", "port": "$PORT", "secret": "$SECRET"} CFGEOF - clear - echo -e "${GREEN}Прокси установлен! (TCP + UDP, звонки поддержаны)${NC}" + echo "" + echo -e "${GREEN}══════════════════════════════════════════════════${NC}" + echo -e "${GREEN} Прокси установлен! (TCP + UDP, звонки поддержаны)${NC}" + echo -e "${GREEN}══════════════════════════════════════════════════${NC}" show_config read -p "Нажмите Enter для возврата в меню..." } @@ -817,13 +897,36 @@ BOTEOF } install_bot_deps() { - echo -e "${GREEN}[*] Настройка Python venv...${NC}" + local bot_steps=3 bot_cur=0 + + bot_cur=$((bot_cur+1)); progress_bar $bot_cur $bot_steps "Создание venv..." if [ ! -d "$BOT_DIR/venv" ]; then - python3 -m venv "$BOT_DIR/venv" || { echo -e "${RED}Ошибка создания venv.${NC}"; return 1; } + spinner_start "Создание Python venv..." + python3 -m venv "$BOT_DIR/venv" 2>/dev/null + spinner_stop + if [ ! -d "$BOT_DIR/venv" ]; then + echo -e " ${RED}✗${NC} Ошибка создания venv." + return 1 + fi fi - echo -e "${GREEN}[*] Установка зависимостей (pip)...${NC}" - "$BOT_DIR/venv/bin/pip" install --upgrade pip -q 2>/dev/null || true - "$BOT_DIR/venv/bin/pip" install -r "$BOT_DIR/requirements.txt" -q || { echo -e "${RED}pip install не удался.${NC}"; return 1; } + echo -e " ${GREEN}✓${NC} Python venv готов" + + bot_cur=$((bot_cur+1)); progress_bar $bot_cur $bot_steps "Обновление pip..." + spinner_start "Обновление pip..." + "$BOT_DIR/venv/bin/pip" install --upgrade pip -q 2>/dev/null + spinner_stop + echo -e " ${GREEN}✓${NC} pip обновлён" + + bot_cur=$((bot_cur+1)); progress_bar $bot_cur $bot_steps "Установка зависимостей..." + spinner_start "Установка python-telegram-bot (до 1 мин)..." + "$BOT_DIR/venv/bin/pip" install -r "$BOT_DIR/requirements.txt" -q 2>/dev/null + local rc=$? + spinner_stop + if [ $rc -ne 0 ]; then + echo -e " ${RED}✗${NC} pip install не удался." + return 1 + fi + echo -e " ${GREEN}✓${NC} Зависимости установлены" } # ── Выход ────────────────────────────────────────────────────────────────────