Go to file
MpakobecEx 6338a47333
Build and push Docker image / tests (push) Successful in 14s Details
Build and push Docker image / docker (push) Successful in 10s Details
Настройки Krea2: Q4/Q6 и 12 шагов
Добавил /settings с галочкой выбора и хранением generation_quality в users. Очередь подставляет Q4 или Q6 в unet_name. Krea2: 12 шагов dpmpp_2m/karras.
2026-10-20 01:18:14 +05:00
.gitea/workflows Переход на PostgreSQL 2026-10-19 02:41:04 +05:00
scripts Админ-панель и очистка ComfyUI 2026-10-19 20:39:12 +05:00
tests Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
web Админ-панель и очистка ComfyUI 2026-10-19 20:39:12 +05:00
workflows Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
.dockerignore Первая версия бота 2026-10-08 20:14:00 +05:00
.env.example Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
.gitattributes Первая версия бота 2026-10-08 20:14:00 +05:00
.gitignore Первая версия бота 2026-10-08 20:14:00 +05:00
Dockerfile Первая версия бота 2026-10-08 20:14:00 +05:00
README.md Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
bot.py Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
checklist.md Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
comfy_client.py Админ-панель и очистка ComfyUI 2026-10-19 20:39:12 +05:00
config.py Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
db.py Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
docker-compose.yml Переход на PostgreSQL 2026-10-19 02:41:04 +05:00
moderation.py Сборка без OpenCV 2026-10-14 19:48:00 +05:00
plan.md Переход на PostgreSQL 2026-10-19 02:41:04 +05:00
prompt_enhancer.py Контекст между сообщениями 2026-10-19 19:08:16 +05:00
pytest.ini Починил запуск тестов в CI 2026-10-19 02:44:51 +05:00
queue_manager.py Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00
requirements-dev.txt Переход на PostgreSQL 2026-10-19 02:41:04 +05:00
requirements.txt Защита от зависания Telegram polling 2026-10-19 18:36:08 +05:00
web.py Админ-панель и очистка ComfyUI 2026-10-19 20:39:12 +05:00
workflows.py Настройки Krea2: Q4/Q6 и 12 шагов 2026-10-20 01:18:14 +05:00

README.md

MpakoImageAIbot

Telegram-бот для генерации и редактирования изображений через удалённый ComfyUI API.

Что умеет

  • Text-to-image: текст → изображение (Z-Image Turbo, 1024×1024).
  • Image-to-image: фото + подпись → редактирование (Krea2 edit).
  • Reply-to-image: ответ текстом на готовую картинку бота → редактирование этой картинки.
  • Веб-история: просмотр запросов с фильтрами по user_id, статусу и режиму, просмотр изображений.
  • Улучшение промптов: перевод и переписывание запроса на английский через TextGenerate + qwen3vl_4b в ComfyUI.
  • Фильтрация промптов: блокировка CSAM, зоофилии, NSFW с публичными людьми и обходных вариантов для не-админов.
  • Оплата: 5 Telegram Stars за обычную очередь, 15 за премиум; админам бесплатно, возврат при ошибке.
  • Премиум-очередь: чередуется с обычной (одна премиум, одна обычная); если одна пуста — работает другая.
  • Баланс и рефералы: 3 стартовые генерации, +1 ежедневно в 00:00 МСК, +3 за первую оплату друга.
  • Управление пользователями: в веб-интерфейсе можно выдавать админку, менять баланс и блокировать.
  • Подтверждение 18+: без подтверждения возраста бот не принимает запросы.
  • Контекст: следующий текстовый запрос продолжает предыдущую сцену; /restart начинает новую.
  • Настройки Krea2: /settings переключает стандартную (Q4) и улучшенную (Q6) модель.
  • Глобальная очередь с одной активной задачей на пользователя.
  • Позиция в очереди и прогресс генерации через WebSocket ComfyUI.
  • PostgreSQL: запросы, статусы, seed, пути к файлам.

Требования

  • Python 3.10+ (проверено на 3.13).
  • ComfyUI с доступом по сети, например:
    python main.py --listen 0.0.0.0 --port 8188
    
  • Установленные кастомные ноды для текущих workflow: Krea2ModelLoader, TextEncodeQwenImageEdit, UnetLoaderGGUF, CLIPLoaderGGUF.
  • Модели, указанные в workflows/txt2img.json и workflows/img2img.json.

Настройка

Copy-Item .env.example .env

Заполнить .env:

  • BOT_TOKEN — токен от @BotFather.
  • TELEGRAM_PROXY — прокси для Telegram API (пусто — напрямую).
  • COMFY_BASE_URL — например http://192.168.31.113:8188.
  • DATABASE_URL — строка подключения PostgreSQL. В Docker хост db, при локальном запуске — localhost.
  • Остальные параметры можно оставить по умолчанию.

Прокси для Telegram

Если сервер не имеет прямого доступа к Telegram, укажи прокси V2RayA/HTTP/SOCKS5:

# Docker на Linux, рекомендуется SOCKS5
TELEGRAM_PROXY=socks5h://host.docker.internal:20170

# HTTP-вариант
# TELEGRAM_PROXY=http://host.docker.internal:20171

# Запуск без Docker, на том же хосте
# TELEGRAM_PROXY=socks5h://127.0.0.1:20170

SOCKS5 стабильнее держит long polling; зависимость socksio уже включена в requirements.txt.

Запуск

py -3 -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python bot.py

Бот работает в приватных чатах. Пользователь отправляет текст или фото с подписью.

Для локального запуска нужен PostgreSQL и DATABASE_URL с хостом localhost.

Docker

docker compose up -d --build

Compose поднимает PostgreSQL, бота и веб. Каталог ./storage монтируется в контейнеры, данные PostgreSQL лежат в ./data/postgres. Для ComfyUI на другой машине используйте её LAN-IP, а не localhost.

PostgreSQL

POSTGRES_DB=mpakoimageaibot
POSTGRES_USER=mpako
POSTGRES_PASSWORD=change-me
DATABASE_URL=postgresql://mpako:change-me@db:5432/mpakoimageaibot
DB_POOL_MIN_SIZE=1
DB_POOL_MAX_SIZE=10

Пароль в DATABASE_URL должен совпадать с POSTGRES_PASSWORD; спецсимволы в пароле нужно URL-кодировать.

Перенос старой SQLite-базы

python scripts/migrate_sqlite_to_postgres.py `
  --sqlite data/bot.db `
  --database-url "postgresql://mpako:change-me@localhost:5432/mpakoimageaibot"

Перед миграцией останови старый бот, чтобы SQLite закрылась и данные были консистентны. Скрипт создаёт схему, переносит данные и пропускает уже существующие записи.

CI

При push в main или master Gitea Actions сначала запускает тесты на PostgreSQL, затем собирает образ на сервере, где запущен runner, и пушит его в Gitea Registry:

  • git.mpakosrv.ru/mpakobecex/mpakoimageaibot:latest
  • git.mpakosrv.ru/mpakobecex/mpakoimageaibot:<sha>
  • локально: mpakoimageaibot:latest

Workflow: .gitea/workflows/docker-build.yml. Runner использует label ubuntu-latest и смонтированный Docker socket. Для входа в registry нужны секреты REGISTRY_USER и REGISTRY_TOKEN.

  • WORKFLOW_PROMPT — workflow улучшения промптов (по умолчанию workflows/prompt_enhance.json).
  • PROMPT_ENHANCE_ENABLED — включить улучшение промптов.
  • PROMPT_ENHANCE_TIMEOUT — таймаут генерации промпта в секундах.

Улучшение промптов

Перед генерацией исходный текст проходит через ComfyUI TextGenerate с уже установленной моделью qwen3vl_4b_fp8_scaled.safetensors:

  • T2I: перевод и переписывание в английский промпт для генерации.
  • I2I: перевод и переписывание инструкции для редактирования.
  • Исходный и улучшенный промпты сохраняются в БД и видны в веб-истории.
  • При ошибке или таймауте используется исходный промпт.

Отдельную модель скачивать не нужно, используется существующий CLIP-файл ComfyUI.

Фильтрация промптов

Фильтр работает для всех, кроме пользователей из ADMIN_USER_IDS:

MODERATION_ENABLED=true
ADMIN_USER_IDS=7467236616
BLOCKED_PUBLIC_FIGURES=

BLOCKED_PUBLIC_FIGURES добавляет имена к встроенному списку (через запятую).

Что блокируется:

  • CSAM: child/kid/minor/teen/young/loli/shota/school/underage + NSFW;
  • зоофилия: sex/nude + animal/dog/cat/horse/beast;
  • публичные люди + nude/naked/sex/undress/deepfake;
  • undress/nude/naked + photo/real/person/woman/man;
  • насилие + NSFW;
  • экстремизм + инструкции/символика;
  • обходные написания (n_u_d_e, l0li, ch1ld и т.п.).

Для i2i: если установлен OpenCV, проверяется наличие лица/человека. В базовом образе OpenCV нет, поэтому NSFW-промпты в i2i блокируются консервативно — как если бы на фото был человек.

При блокировке пользователь получает «Запрос нарушает правила. Звёзды не списаны.», а запись с user_id, временем, промптом и причиной сохраняется в таблицу blocked_requests.

Управление пользователями

В админ-панели есть раздел «Пользователи» (/admin/users):

  • поиск по ID или username;
  • установка точного баланса генераций;
  • назначение/снятие админа;
  • блокировка/разблокировка.

Заблокированный пользователь не может отправлять запросы, получать счета и оплачивать. Админ-флаг из веб-интерфейса действует сразу.

ADMIN_USER_IDS используется только для первичной инициализации админов; после первого запуска админы хранятся в БД и управляются через веб.

Надёжность Telegram

TELEGRAM_RETRY_ATTEMPTS=0
TELEGRAM_RETRY_MAX_DELAY=30
TELEGRAM_HEALTH_INTERVAL=60
  • TELEGRAM_RETRY_ATTEMPTS=0 — повторять операции до успеха.
  • Backoff растёт до TELEGRAM_RETRY_MAX_DELAY.
  • Критичные отправки (результат, счёт, подтверждение) повторяются бесконечно; обновления статуса — ограниченно, чтобы не плодить зависшие задачи.
  • Раз в TELEGRAM_HEALTH_INTERVAL выполняется getMe; при сбое проверка повторяется с backoff, пока Telegram не ответит.
  • Watchdog проверяет pending updates: если они не обрабатываются 5 минут, polling перезапускается, а при неудаче контейнер перезапускается автоматически.

Подтверждение возраста

Перед использованием бота нужно подтвердить 18+:

  • в /start показываются кнопки «Мне 18+» и «Мне меньше 18»;
  • без подтверждения текстовые и фото-запросы отклоняются;
  • отказ «мне меньше 18» сохраняется в БД и блокирует доступ;
  • статус 18+ виден в веб-разделе «Пользователи».

Существующие пользователи проходят подтверждение один раз после обновления.

Баланс и рефералы

  • Новому пользователю начисляется 3 генерации.
  • Каждый день в 00:00 МСК — ещё 1 генерация.
  • Обычная генерация может быть оплачена 1 генерацией с баланса или 5 звёздами.
  • Премиум-очередь всегда оплачивается 15 звёздами; баланс при этом не расходуется.
  • /balance — текущий баланс.
  • /invite — реферальная ссылка.
  • /restart — сбросить контекст и начать новую сцену (алиас /reset).
  • /settings — выбор модели Krea2: стандартная Q4 или улучшенная Q6.
  • За первую оплату приглашённого друга начисляется +3 генерации, реферер получает уведомление.

Баланс и рефералы хранятся в таблице users. Пропущенные дни начисляются при следующем запуске/полуночи.

Контекст

  • Первый текстовый запрос создаёт контекст: базовую сцену и текущий улучшенный промпт.
  • Следующий текст обрабатывается вместе с предыдущим промптом: бот сохраняет сцену и применяет только запрошенное изменение.
  • /restart очищает контекст; следующий запрос начнёт новую сцену.
  • Новое фото с подписью автоматически начинает новую цепочку.
  • Для точного редактирования конкретной картинки ответь на сообщение бота с изображением.
  • /restart не отменяет уже запущенную генерацию: она завершится со своим снимком контекста.

Контекст хранится в таблице user_contexts и обновляется только после успешной отправки результата.

Оплата

Генерация стоит 5 Telegram Stars в обычной очереди и 15 звёзд в премиум-очереди:

PAYMENTS_ENABLED=true
STARS_PRICE=5
PREMIUM_STARS_PRICE=15
  • Перед оплатой бот показывает количество людей в обычной и премиум-очередях.
  • Пользователь выбирает очередь кнопкой, после чего получает счёт.
  • Премиум- и обычные задачи чередуются: одна премиум, одна обычная; если одна очередь пуста, берётся из другой.
  • Админы из ADMIN_USER_IDS генерируют бесплатно в обычной очереди.
  • Не-админу выставляется счёт через Telegram Stars (XTR).
  • Фильтрация промпта выполняется до выставления счёта.
  • Если поставить задачу в очередь не удалось, звёзды возвращаются.
  • При ошибке генерации звёзды также возвращаются.
  • Оплата и telegram_payment_charge_id сохраняются в pending_payments и requests.

Веб-история

После docker compose up -d доступна страница:

http://192.168.31.158:8099

Возможности:

Публичная страница / показывает только историю:

  • фильтр по Telegram user_id (с подсказкой известных пользователей);
  • в списке показывается @username, если он известен, иначе Telegram ID;
  • фильтр по статусу и режиму (t2i/i2i);
  • пагинация;
  • превью результата в списке (кэшируются в storage/.thumbnails);
  • карточка запроса с полным промптом, ошибкой, seed и изображениями.

Админ-панель находится на /admin и защищена HTTP Basic:

  • /admin — история, включая скрытые запросы;
  • /admin/users — управление пользователями;
  • скрытие/показ запроса из публичной истории;
  • скрытые запросы не видны в публичном списке, их карточки и медиа отдают 404.
WEB_BIND_IP=192.168.31.158
WEB_PAGE_SIZE=50
WEB_ADMIN_USERNAME=admin
WEB_ADMIN_PASSWORD=change-me

Если WEB_ADMIN_PASSWORD пустой, админ-панель отключена. Basic Auth передаёт пароль без шифрования, поэтому используй только LAN или VPN; не публикуй порт 8099 наружу.

После успешной сборки обновление контейнера:

docker compose up -d

Без --build: Compose возьмёт готовый образ mpakoimageaibot:latest.

Workflow

  • workflows/txt2img.json — Z-Image Turbo: EmptySD3LatentImage → KSampler → VAEDecode → SaveImage.
  • workflows/img2img.json — Krea2 edit: LoadImage → TextEncodeQwenImageEdit → KSamplerAdvanced → VAEDecode → SaveImage.
  • workflows/mapping.json — ID узлов, в которые подставляются prompt, negative, seed, входное изображение и размер латента.
  • workflows/Krea2.json и workflows/ZImage.json — исходные экспорты.
  • Krea2 edit: VAE подключён к TextEncodeQwenImageEdit, латент подгоняется под пропорции входного изображения; 12 шагов, dpmpp_2m/karras.
  • /settings переключает модель Krea2: стандартная Q4_K_M или улучшенная Q6_K. Настройки сэмплера и латента одинаковые.
  • Файлы моделей должны быть в models/diffusion_models; имена задаются KREA2_Q4_MODEL и KREA2_Q6_MODEL.

Если меняются workflow, обновите mapping.json. При старте бот проверяет, что все узлы и поля существуют.

Очистка ComfyUI

После успешного скачивания результата бот удаляет запись истории ComfyUI по prompt_id:

POST /history
{"delete": ["<prompt_id>"]}

Это убирает запрос и его ассеты из истории ComfyUI, но не удаляет файлы с диска. Для файлов output/ и temp/ есть скрипт для машины с ComfyUI:

.\scripts\cleanup_comfy_assets.ps1 -ComfyRoot "C:\ComfyUI" -RetentionHours 6

Запускай его по расписанию, например раз в час. Сначала можно проверить без удаления:

.\scripts\cleanup_comfy_assets.ps1 -ComfyRoot "C:\ComfyUI" -RetentionHours 6 -WhatIf

Тесты

pip install -r requirements-dev.txt
pytest

Ограничения текущей версии

  • Один воркер и одна активная задача на пользователя.
  • Нет /cancel и удаления задачи из очереди.
  • Нет автоочистки storage/ и data/.
  • Прогресс в процентах зависит от WebSocket; при его недоступности используется polling без процентов.
  • При рестарте задача в статусе running помечается failed.