Галингер Р.С. 0f674f8832 refactor: review fixes and code improvements
- Add shared proxy module (bot/utils/proxy.py) to eliminate duplicate SOCKS5 parsing
- Fix AI client: escape HTML before Markdown→HTML conversion, unify timeouts,
  make health check optional and disabled by default, handle 429 retries
- Fix ai.py: correct forwarded message handling (aiogram 3.x forward_origin),
  pass relevant summaries via extra_system_content
- Fix dialogue.py: only respond to Astra's messages, use system context instead
  of prompt injection, answer on the limit message before phase transition
- Fix voice.py: load Whisper model in thread pool, safe WAV path generation
- Improve database.py: composite indexes, Boolean is_active, upsert file_id cache,
  add context cleanup helper
- Update weather.py and yadisk_download.py to use shared proxy connector
- Update yadisk.py: validate URL before cache clear, add download size limit,
  wrap sync file ops in to_thread
- Reuse S3 client via lru_cache
- Update setup_commands with /aiclear and /aiuser
- Update README, Dockerfile (Python 3.11), docker-compose (mount models)
- Pin dependency versions, remove unused httpx[socks]
- Add basic pytest tests for layout converter and voice normalization
2026-07-07 18:42:10 +07:00
2026-07-07 18:30:17 +07:00
2026-07-07 18:30:17 +07:00
2026-07-07 18:30:17 +07:00

UMB — Telegram Bot

Бот для модерации стикеров/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    # настройка логирования

Установка

cd umb
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Настройка

Откройте .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

Для включения прокси установите PROXY_ENABLED=true и укажите корректный PROXY_URL.

Запуск

source .venv/bin/activate
python main.py

Запуск в Docker

docker compose up -d --build

Модели Whisper сохраняются в ./models, база данных и логи — в ./bot/data.

Команды

Команда Описание
/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 создаётся краткая выжимка, которая затем подбирается по смыслу к новым вопросам.
  • Стиль: отвечает кратко и по делу, если не просят развёрнуто.
  • Потеря контекста: говорит что-то милое ("я потеряла мысль", "смотри, какая птичка!")
S
Description
UMB Telegram Bot
Readme
109 KiB
Languages
Python 99.7%
Dockerfile 0.3%