Convert join/leave interaction commands to PlatformUser, PlatformGroup, and PlatformMessageRef. Persist and look up participants by platform identity while keeping Telegram callbacks intact. Add V017 migration and TDD coverage. Bump version to 2.1.1.
🎲 GM-Relay: TTRPG Session Scheduling Bot & Web Dashboard
GM-Relay — это комплексное решение для Мастеров Подземелий (ГМов), состоящее из высокопроизводительного Telegram-бота и удобного веб-интерфейса. Предназначено для автоматизации записи игроков на сессии, управления расписанием и проведения игр.
Проект разработан с упором на производительность, архитектуру Vertical Slice, Native AOT (для бота) и удобство развертывания с использованием .NET Aspire.
Текущая версия: v2.0.1.
✨ Key Features
🤖 Telegram Bot
- 📅 Создание расписаний (Batch Sessions): Создавайте сразу несколько игр одним сообщением изменения (на недельный месяц в перед).
- 🖼 Обложки расписаний: И batch-посту можно прикрепить фото к
/newsessionили указать строкуКартинка: https://...; бот отправит обложку перед сообщением записи. - ⚡ Быстрые повторы расписания: Для регулярной кампании можно указать одну дату, количество игр и интервал, а бот сам развернёт повторяющийся batch.
- ✋ Интерактивная запись и выход: Игроки записываются на конкретные даты и самостоятельно снимают запись нажатием одной кнопки.
- 👥 Лимит мест и лист ожидания: ГМ задаёт максимальный состав, бот не переполняет сессию, автоматически ведёт очередь ожидания и освобождённое место отдаёт первому ожидающему.
- 📁 Поддержка Форумов (Telegram Topics): Если
/newsessionзапущен в теме форума Telegram, расписание и групповые уведомления остаются в этой теме; при запуске из корня форума бот создает отдельную тему и сообщает о необходимости прав admin/Manage Topics, если их не хватает. - ❌ Управление сессиями: Owner и назначенные co-GM могут создавать, отменять, удалять и переносить игры из Telegram через
/listsessions; публичный пост записи показывает только кнопки игроков. - 🔄 Голосование за перенос: Быстрый поиск свободного места с через свободное недель и кнопками новых времени и дедлайном.
- 🔔 Уведомления: Игрок получают за 24 часа, напоминание за 1 час, ссылку перед игрой, отмены и переносы; групповые уведомления при этом остаются.
- 🕐 Режим уведомлений batch: Для каждой пачки можно выбрать
В группе и в личкуилиТолько в группе. - ⬆️ Управление очередью: Веб-интерфейс показывает заполненность, лист ожидания и позволяет ГМу поднять первого игрока из очереди.
- 🔄 Автоматическая синхронизация: Любые изменения в веб-интерфейсе мгновенно обновляют сообщения с расписанием в Telegram-чатах игроков.
🌐 Web Dashboard (Blazor Server)
- 🔐 Авторизация через Telegram: Telegram Login Widget с HMAC-SHA256 валидацией.
- 📱 Telegram Mini App Dashboard: Мобильная панель открывается из Telegram, проверяет
initDataна сервере, учитывает safe-area телефона и верхнюю панель Telegram. - ✏️ Редактирование: Детальное изменение дат, названий и статусов сессий.
- 🤝 Co-GM и делегирование: Owner назначает помощников по Telegram ID; co-GM управляет расписанием, но не может назначать других co-GM.
- 📋 Шаблоны кампаний: Вкладка
Шаблоныотдельно от страницы группы: сохранение типовых параметров и запуск нового batch из шаблона. - 📦 Bulk-операции для Batch Sessions:
- обновить общий
title/linkу всей пачки; - перенести пачку на фиксированный шаг в днях;
- клонировать batch на следующую неделю или месяц.
- обновить общий
- ⬆️ Управление очередью: Заполненность, лист ожидания и ручное повышение игрока из очереди.
- 📜 История изменений сессий: Страница
/session/{id}/historyпоказывает аудит-лог всех значимых изменений (время, ссылка, название, участники, статус) с указанием акторов и дат. - 📊 Статистика посещаемости: Страница
/group/{id}/statsпоказывает долю присутствия, количество пропусков и среднюю явку по каждому игроку группы. - 🔄 Автосинхронизация: Изменения в вебе мгновенно перерисовывают Telegram-сообщения расписания.
🛠 Технологический стек
| Компонент | Технология |
|---|---|
| Язык | C# 14 (.NET 10) |
| Архитектура | Vertical Slice + общая библиотека GmRelay.Shared |
| Бот | Telegram.Bot, Native AOT |
| Веб | Blazor Server |
| Оркестрация | .NET Aspire (GmRelay.AppHost) |
| БД | PostgreSQL |
| ORM | Dapper + Dapper.AOT (source generators) |
| Миграции | DbUp |
| Развёртывание | Docker Compose, Multi-arch (AMD64/ARM64) |
Note
При использовании Dapper в режиме Native AOT все SQL-запросы используют строго типизированные DTO; динамические типы (
dynamic) не поддерживаются.
🚀 Быстрый старт (Docker Compose)
Требования: Docker и Docker Compose.
1. Настройка окружения
cp .env.example .env
Ключевые переменные .env:
# Токен от @BotFather (используется ботом и как секретный ключ веб-авторизации)
TELEGRAM_BOT_TOKEN=ваш_токен_здесь
# Имя бота без @ (для Telegram Login Widget)
TELEGRAM_BOT_USERNAME=ваше_имя_бота_здесь
# HTTPS URL Mini App, например https://your-domain.example/miniapp
TELEGRAM_MINI_APP_URL=https://your-domain.example/miniapp
POSTGRES_PASSWORD=ваш_надежный_пароль
GMRELAY_WEB_PORT=8080
Настройка в @BotFather:
- Команда
/setdomainдля работы виджета авторизации на вашем домене. - Для Mini App настройте домен Web Dashboard и menu button на URL из
TELEGRAM_MINI_APP_URL. - Начиная с v1.9.3 дополнительных действий для фикса входа не требуется: fallback выполняется внутри активного Telegram WebView по тому же HTTPS-адресу
/miniapp.
2. Запуск
docker compose up -d
Автоматически выполняется:
- создание Docker-сети и volume PostgreSQL;
- подъём PostgreSQL (
db:5432); - запуск бота с плавной миграцией (DbUp);
- запуск веб-приложения с подключением к БД и Telegram API.
3. Первоначальная настройка
- Напишите боту
/start. - Создайте группу через
/newgroup. - Откройте Mini App или Web Dashboard для расширенного управления.
💾 Backup и восстановление
Проект включает автоматический ежедневный backup PostgreSQL через сервис db-backup в Docker Compose.
Как это работает
- Каждый день в 03:00 выполняется
pg_dumpбазыgmrelay_db. - Дампы сжимаются (
gzip) и сохраняются в volumepgbackups(/backups). - Формат имени:
gmrelay_db_YYYYMMDD_HHMMSS.sql.gz. - Ротация: по умолчанию хранятся последние 7 дней (настраивается через
BACKUP_RETENTION_DAYS).
Проверка бэкапов
docker compose exec db-backup ls -la /backups
Ручное создание дампа
docker compose exec db-backup sh -c "pg_dump -h db -U gmrelay -d gmrelay_db | gzip > /backups/gmrelay_db_manual.sql.gz"
Восстановление из бэкапа
# Использовать последний автоматический бэкап
./scripts/restore.sh
# Или указать конкретный файл
./scripts/restore.sh backups/gmrelay_db_20260512_030000.sql.gz
Warning
Восстановление перезаписывает текущую базу данных. Убедитесь, что вы понимаете последствия, прежде чем запускать
restore.sh.
Переменные окружения (опциональные)
BACKUP_RETENTION_DAYS=7
BACKUP_VOLUME_NAME=game_pgbackups
🗂 Структура репозитория
├── src/
│ ├── GmRelay.AppHost/ # .NET Aspire orchestrator
│ ├── GmRelay.Bot/ # Telegram-бот (Native AOT)
│ ├── GmRelay.Migrator/ # DbUp-миграции
│ ├── GmRelay.ServiceDefaults/ # Aspire service defaults
│ ├── GmRelay.Shared/ # Общие доменные модели
│ ├── GmRelay.Web/ # Blazor Server dashboard
│ └── GmRelay.Worker/ # Background workers
├── tests/
│ └── GmRelay.Bot.Tests/ # xUnit + NSubstitute
├── compose.yaml # Docker Compose (AMD64 + ARM64)
└── .env.example # Шаблон переменных окружения
📜 Лицензия
MIT License. См. LICENSE.
Построено с ❤️ для TTRPG-сообщества.