# 🤖 UMB — Telegram Bot **Универсальный бот-модератор с AI-ассистентом "Астра"** [![License: MIT](https://img.shields.io/badge/license-MIT-lightgrey.svg)](LICENSE) [![Python 3.11](https://img.shields.io/badge/python-3.11-blue.svg)](https://www.python.org/) [![aiogram 3.x](https://img.shields.io/badge/aiogram-3.x-2CA5E0.svg)](https://docs.aiogram.dev/) [![SQLite](https://img.shields.io/badge/sqlite-async-003B57.svg)](https://www.sqlite.org/) [![Docker](https://img.shields.io/badge/docker-ready-2496ED.svg)](https://www.docker.com/) [![Tests](https://img.shields.io/badge/tests-pytest-brightgreen.svg)](tests/) [![SOCKS5 Proxy](https://img.shields.io/badge/proxy-SOCKS5-orange.svg)](#настройка)
--- UMB — это Telegram-бот для модерации стикеров/GIF, восстановления раскладки, получения погоды и общения с AI-ассистентом **Астра**. ## ✨ Функции - **🛡️ Модерация стикеров и GIF** — если пользователь отправляет 25+ стикеров/GIF за 60 секунд, бот удаляет все последующие стикеры и GIF от этого пользователя в течение 5 минут. Текстовые сообщения не затрагиваются. - **⌨️ Восстановление раскладки (`/res`)** — ответьте командой `/res` на сообщение с текстом в неправильной раскладке, и бот переведёт его (например, `gbdj` → `пиво`). - **🌤️ Погода (`/weather`)** — покажет подробную погоду в указанном городе через OpenWeatherMap API. - **🤖 AI-ассистент "Астра" (`/ai`)** — задайте вопрос, ответьте командой `/ai` на сообщение или перешлите сообщение, и Astra проанализирует его с учётом контекста и ранее сохранённых выжимок диалогов. - **💬 Диалог с Астрой** — после `/ai` без вопроса начинается диалог. Отвечайте на сообщения бота, чтобы продолжать. - Фаза 1: до 50 сообщений. - Фаза 2: дополнительно до 20 сообщений. - После исчерпания лимита — перерыв 1 час. - **🔒 Управление AI (`/aino`, `/aiyes`)** — владелец чата может заблокировать/разблокировать пользователя от AI. - **🧦 Поддержка SOCKS5 прокси** — настраивается через `.env`. ## 🏗️ Структура проекта ``` umb/ ├── .env # настройки: токен, прокси, API ключи ├── .gitignore ├── requirements.txt ├── main.py # точка входа ├── config.py # конфигурация ├── Dockerfile ├── docker-compose.yml └── bot/ ├── __init__.py ├── bot.py # инициализация бота и сессии ├── setup_commands.py # меню команд ├── routers/ │ ├── __init__.py │ ├── moderation.py # роутер модерации стикеров/GIF │ ├── layout.py # роутер /start, /res │ ├── weather.py # роутер /weather │ ├── ai.py # роутер /ai, /aino, /aiyes, /aiclear, /aiuser │ ├── dialogue.py # диалоговый режим с Астрой │ ├── voice.py # распознавание голосовых сообщений │ └── yadisk.py # скачивание с Яндекс.Диска └── utils/ ├── __init__.py ├── proxy.py # общий SOCKS5-коннектор ├── layout_converter.py # конвертер раскладки en→ru ├── weather.py # функция получения погоды ├── ai_client.py # OpenRouter/RouterAI клиент ├── memory.py # саммари и эмбеддинги ├── database.py # SQLAlchemy модели и функции БД ├── voice.py # загрузка и транскрибация голоса ├── yadisk_download.py # загрузка файлов с Яндекс.Диска ├── s3_client.py # загрузка больших файлов в S3 └── logging_config.py # настройка логирования ``` ## 📊 Системные требования ### Память (RAM) | Компонент | Расход | |-----------|--------| | Whisper `base` (int8) в памяти | ~600–900 МБ | | Whisper пик при транскрибации | дополнительно ~200–400 МБ | | aiogram + SQLAlchemy + aiohttp | ~100–200 МБ | | SQLite | ~10–50 МБ | | ffmpeg (пиково) | ~50–100 МБ | | **Рекомендуемый минимум** | **2 ГБ** | | **Без распознавания голоса** | **~512 МБ** | ### Процессор | Параметр | Значение | |----------|----------| | Количество ядер | минимум 2, рекомендовано **4+** | | Нагрузка при транскрибации | ~80–100% на 4 ядрах на 2–8 сек | | Нагрузка в простое | ~1–5% | | Архитектура | x86_64 / ARM64 | > Без голосовых сообщений достаточно **1 ядра**. ### Диск | Данные | Размер | |--------|--------| | Whisper `base` модель | ~500 МБ на диске | | SQLite база | ~50–200 МБ (растёт со временем) | | Голосовые файлы (временно) | ~1–5 МБ на сообщение, удаляются сразу | | Логи (ротация 5×10 МБ) | ~50–100 МБ | | **Рекомендуемое свободное место** | **5–10 ГБ** | ### Сеть - Пропускная способность: минимальная (несколько КБ/с в среднем). - Все API-запросы могут идти через SOCKS5-прокси. - Для скачивания Whisper-модели через прокси: ~150 МБ одним файлом, нужна стабильность. ### Итого | Ресурс | Минимум | Рекомендовано | |--------|---------|---------------| | **RAM** | 2 ГБ | 4 ГБ | | **CPU** | 2 ядра | 4+ ядра | | **Disk** | 5 ГБ | 10 ГБ | | **ОС** | Linux (x86_64) | то же, Python 3.11 | ## 🚀 Установка ```bash cd umb python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ## ⚙️ Настройка Откройте `.env` и укажите необходимые ключи: ```env BOT_TOKEN=your_bot_token_here PROXY_ENABLED=false PROXY_URL=socks5://user:pass@host:port API_WEATHER=your_openweather_api_key OPENROUTER_API_KEY=your_openrouter_api_key ROUTERAI_API_KEY=your_routerai_api_key ROUTERAI_BASE_URL=https://routerai.ru/api/v1 # Опционально: периодическая проверка работоспособности бесплатных моделей. # Внимание: проверка расходует токены API. По умолчанию отключена. AI_HEALTH_CHECK_ENABLED=false AI_HEALTH_CHECK_INTERVAL=600 # Настройки модели Whisper для распознавания голоса. WHISPER_MODEL_SIZE=base WHISPER_MIN_FREE_SPACE_BYTES=5368709120 ``` Для включения прокси установите `PROXY_ENABLED=true` и укажите корректный `PROXY_URL`. ## ▶️ Запуск ```bash source .venv/bin/activate python main.py ``` ## 🐳 Запуск в Docker ```bash docker compose up -d --build ``` Модели Whisper сохраняются в `./models`, база данных и логи — в `./bot/data`. ## 🎙️ Распознавание голосовых сообщений Бот автоматически распознаёт все голосовые сообщения с помощью локальной модели [faster-whisper](https://github.com/SYSTRAN/faster-whisper). ### Поведение загрузки модели - При запуске бота проверяется наличие модели в `./models/faster-whisper//`. - Если модель уже скачана — бот сразу готов к работе. - Если модели нет — бот проверяет свободное место на диске и **скачивает модель автоматически** перед началом polling. - Для скачивания используется прокси из `.env`, если `PROXY_ENABLED=true`. ### Требования к месту | Модель | Размер модели | Рекомендуемое свободное место | |--------|---------------|-------------------------------| | `base` | ~150 MB архив, ~500 MB на диске | 5 GB (`WHISPER_MIN_FREE_SPACE_BYTES=5368709120`) | | `small` | ~500 MB архив, ~1.5 GB на диске | 5 GB+ | | `medium` | ~1.5 GB архив, ~5 GB на диске | 10 GB+ | > 💡 По умолчанию используется модель `base`. Для смены модели измените `WHISPER_MODEL_SIZE` в `.env`. ### Логирование В логах будет видно: ``` Free disk space: 45.23 GB, required: 5.00 GB Whisper model 'base' found locally at /app/models/faster-whisper/base Whisper model 'base' is ready ``` или при скачивании: ``` Whisper model 'base' not found locally. Starting download to /app/models/faster-whisper... Whisper model 'base' downloaded and loaded in 125.4s Whisper model 'base' is ready ``` ## 🧪 Тесты ```bash source .venv/bin/activate pytest tests/ -v ``` ## 📋 Команды | Команда | Описание | |---------|----------| | `/start` | Приветствие и информация о боте | | `/res` | Восстановить раскладку (ответить на сообщение) | | `/weather <город>` | Погода в указанном городе | | `/ai <вопрос>` | Задать вопрос Астре | | `/ai` (ответом/пересылкой) | Проанализировать сообщение | | `/ai` (без вопроса) | Начать диалоговый режим | | `/aiclear` | Очистить диалог и сохранить выжимку | | `/aiuser` | Список пользователей чата (только creator) | | `/aino @username` | Заблокировать пользователя от AI (только creator, 24ч) | | `/aiyes @username` | Разблокировать пользователя от AI (только creator) | | `/ydf <ссылка>` | Скачать файл с Яндекс.Диска | | `/ydf (new) <ссылка>` | Скачать файл, игнорируя кеш Telegram | ## ⚖️ Настройки модерации Изменяются в `config.py`: - `MODERATION_LIMIT = 25` — количество стикеров/GIF за окно - `MODERATION_WINDOW = 60` — окно подсчёта в секундах - `MODERATION_BAN_DURATION = 300` — длительность бана в секундах ## 🧠 AI-ассистент "Астра" - **Бесплатные модели** (OpenRouter): пробует по очереди доступные модели с суффиксом `:free`. При rate-limit автоматически переключается на следующую. - **Платный fallback** (RouterAI): если все бесплатные модели недоступны, используется `deepseek/deepseek-v4-flash` через `routerai.ru`. В ответе добавляется уведомление `⚡ Обработано через платный API`. - **Контекст**: хранит последние 10 сообщений каждого пользователя в SQLite. - **Долгосрочная память**: при переходе между фазами диалога и при `/aiclear` создаётся краткая выжимка, которая затем подбирается по смыслу к новым вопросам. - **Стиль**: отвечает кратко и по делу, если не просят развёрнуто. - **Потеря контекста**: говорит что-то милое ("я потеряла мысль", "смотри, какая птичка!") ---
Сделано с помощью [aiogram](https://docs.aiogram.dev/) · [SQLAlchemy](https://www.sqlalchemy.org/) · [faster-whisper](https://github.com/SYSTRAN/faster-whisper)