19 KiB
🎲 GM-Relay: TTRPG Session Scheduling Bot & Web Dashboard
GM-Relay — это комплексное решение для Мастеров Подземелий (ГМов), состоящее из высокопроизводительного Telegram-бота и удобного веб-интерфейса. Предназначено для автоматизации записи игроков на сессии, управления расписанием и проведения игр.
Проект разработан с упором на производительность, архитектуру Vertical Slice, Native AOT (для бота) и удобство развертывания с использованием .NET Aspire.
Текущая версия: v1.9.3.
✨ Ключевые возможности
🤖 Telegram Бот
- 📅 Создание расписаний (Batch Sessions): Создавайте сразу несколько игр одним сообщением (на неделю или месяц вперед).
- ⚡ Быстрые повторы расписания: Для регулярной кампании можно указать одну дату, количество игр и интервал, а бот сам развернёт повторяющийся batch.
- ✋ Интерактивная запись и выход: Игроки записываются на конкретные даты и самостоятельно снимают запись нажатием одной кнопки.
- 👥 Лимит мест и лист ожидания: ГМ задаёт максимальный состав, бот не переполняет сессию, автоматически ведёт очередь ожидания и освобождённое место отдаёт первому ожидающему.
- 📁 Поддержка Форумов (Telegram Topics): Бот автоматически создает тему во вложенных чатах Telegram под каждую новую пачку игр.
- ❌ Управление сессиями: Owner и назначенные co-GM могут создавать, отменять, удалять и переносить игры прямо из Telegram.
- 🔄 Голосование за перенос: При переносе сессии GM предлагает 2-3 новых времени и дедлайн, игроки голосуют кнопками, а бот показывает текущие результаты и применяет победивший вариант.
- 🔔 Персональные уведомления: Игроки получают DM о RSVP за 24 часа, напоминание за 1 час, ссылку перед игрой, отмены и переносы; групповые уведомления при этом остаются.
- 🗓 Экспорт в Календарь: Генерация файла
.icsдля добавления всех игр в Google, Apple или Яндекс Календарь одной командой. - 🚀 Native AOT: Скомпилирован в нативный бинарный файл. Мгновенный запуск и минимальное потребление памяти. Идеально для Raspberry Pi.
🌐 Web Dashboard (Blazor Server)
- 🔐 Авторизация через Telegram: Безопасный вход с использованием Telegram Login Widget (HMAC-SHA256 валидация).
- 📱 Telegram Mini App Dashboard: Мобильная версия dashboard открывается прямо из Telegram, проверяет WebApp
initDataна сервере и использует те же права owner/co-GM, что и обычный Web Dashboard. Если Mini App попадает в fallback-вход, Telegram Login Widget авторизует пользователя callback-запросом внутри текущего WebView, а интерфейс учитывает safe-area телефона и верхнюю панель Telegram. - 📝 Удобное редактирование: Веб-интерфейс для детального редактирования сессий, изменения дат, названий и статусов.
- 🤝 Co-GM и делегирование: Owner группы назначает помощников по Telegram ID, а co-GM получает доступ к управлению расписанием в Telegram и Web Dashboard.
- 📋 Шаблоны кампаний: Owner и co-GM управляют типовыми параметрами кампаний в отдельной вкладке
Шаблоны, а на странице группы запускают новый повторяющийся batch из выбранного шаблона. - 🧩 Bulk-операции для Batch Sessions: ГМ может обновить общий title/link, перенести всю пачку на фиксированный шаг и клонировать batch на следующую неделю или месяц.
- 🔕 Режим уведомлений batch: Для каждой пачки можно выбрать
В группе и в личкуилиТолько в группе. - ⬆️ Управление очередью: Веб-интерфейс показывает заполненность, лист ожидания и позволяет ГМу поднять первого игрока из очереди.
- 🔄 Автоматическая синхронизация: Любые изменения в веб-интерфейсе мгновенно обновляют сообщения с расписанием в Telegram-чатах игроков.
- 🕒 Управление временем: UI адаптирован под московское время (UTC+3), в то время как база данных работает в UTC.
🛠 Технологический стек
- Язык: C# 14 (.NET 10)
- Архитектура: Vertical Slice Architecture, общая библиотека (
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).
🚀 Быстрый старт (Docker Compose)
Проект использует Docker Compose для одновременного запуска базы данных, бота и веб-интерфейса.
1. Подготовка
Убедитесь, что у вас установлены Docker и Docker Compose.
2. Настройка окружения
Скопируйте файл-шаблон и заполните его значениями:
cp .env.example .env
Отредактируйте .env:
# Токен вашего бота от @BotFather (используется и для бота, и как секретный ключ для веб-авторизации)
TELEGRAM_BOT_TOKEN=ваш_токен_здесь
# Имя вашего бота в Telegram (без @), например: GmRelayBot.
# Найти его можно в информации о боте у @BotFather.
# Используется для работы виджета авторизации (Telegram Login Widget).
TELEGRAM_BOT_USERNAME=ваше_имя_бота_здесь
# HTTPS URL Mini App dashboard, например: https://your-domain.example/miniapp.
# Используется кнопкой меню Telegram и кнопкой /start.
TELEGRAM_MINI_APP_URL=https://your-domain.example/miniapp
# Пароль для базы данных PostgreSQL
POSTGRES_PASSWORD=ваш_надежный_пароль
# Локальный порт веб-интерфейса GM-Relay
GMRELAY_WEB_PORT=8080
(Опционально) Настройте домен Telegram бота в @BotFather командой /setdomain для работы виджета авторизации на вашем сайте.
Для Telegram Mini App настройте в @BotFather домен Web Dashboard и menu button на URL из TELEGRAM_MINI_APP_URL. Бот также показывает кнопку Открыть dashboard в ответе на /start, если переменная задана. Начиная с v1.9.3 дополнительных действий в BotFather для фикса входа не требуется: URL остаётся тем же HTTPS-адресом /miniapp, а fallback-вход выполняется внутри активного Telegram WebView.
3. Запуск
Выполните команду:
docker compose up -d
Инфраструктура автоматически:
- Создаст локальную Docker-сеть и volume PostgreSQL, если их ещё нет.
- Поднимет PostgreSQL, доступный для контейнеров как
db:5432. - Запустит бота (применив миграции БД).
- Запустит веб-интерфейс на
http://localhost:8080или другом порту изGMRELAY_WEB_PORT.
⚙️ Настройка бота в Telegram
Чтобы бот работал корректно:
- Добавьте бота в группу (или Супергруппу/Форум).
- Назначьте бота Администратором.
- Необходимые права:
Выбор тем(Managed Topics) — обязательно для Форумов.Отправка сообщений.Закрепление сообщений— рекомендуется.
Tip
Owner группы определяется по первому человеку, который создал сессию в этой группе. Owner может назначать co-GM в Web Dashboard; owner и co-GM могут управлять сессиями через кнопки бота и веб-интерфейс.
📝 Инструкция для Мастера
Создание расписания игр
Используйте команду /newsession с описанием в следующем формате:
/newsession
Название: Легенды Берега Мечей (D&D 5e)
Время: 15.05.2024 19:30
Время: 22.05.2024 19:00
Мест: 4
Ссылка: https://discord.gg/invite-link
Строка Мест: необязательна. Если она указана, игроки сверх лимита попадут в лист ожидания, а ГМ сможет повысить первого ожидающего через кнопку в Telegram или Web Dashboard.
Для регулярной кампании можно не перечислять все даты вручную. Укажите одну строку Время:, количество игр и интервал в днях:
/newsession
Название: Kingmaker
Время: 30.04.2026 19:30
Игр: 6
Интервал: 7
Мест: 5
Ссылка: https://discord.gg/invite-link
Бот создаст 6 игр с недельным шагом. Вместо Игр: также принимается Сессий: или Повторов:, вместо Интервал: — Шаг:.
Игрок может самостоятельно снять запись кнопкой 🚪 Выйти в сообщении расписания. Если он был в основном составе и в листе ожидания есть игроки, бот автоматически переводит первого ожидающего в основной состав и обновляет сообщение пачки.
Делегирование управления
На странице группы Web Dashboard показывает owner и список co-GM. Owner может добавить помощника по Telegram ID, имени и username, а также снять роль co-GM. Назначенный co-GM видит группу в панели управления и может редактировать сессии, управлять batch-операциями, очередью, переносами и удалением игр, но не может назначать других co-GM.
Перенос сессии голосованием
Owner или co-GM нажимает кнопку ⏰ Перенести у нужной сессии и отправляет в чат 2-3 варианта нового времени вместе с дедлайном:
25.04.2026 19:30
26.04.2026 18:00
Дедлайн: 25.04.2026 12:00
Дедлайн должен быть в будущем и раньше первого предложенного времени. Участники выбирают один вариант кнопкой в Telegram, могут изменить голос до дедлайна и видят текущие результаты в сообщении голосования. По дедлайну бот выбирает вариант с наибольшим числом голосов, переносит сессию, сбрасывает RSVP и обновляет batch-сообщение. Если голосов нет или есть ничья, перенос отклоняется, а время сессии остаётся прежним.
Шаблоны и bulk-операции в Web Dashboard
Вкладка Шаблоны в левом меню вынесена отдельно от страницы группы. Owner и co-GM выбирают группу, сохраняют шаблон кампании с названием, ссылкой, количеством игр, интервалом, лимитом мест и режимом уведомлений, а также удаляют устаревшие шаблоны.
На странице группы Web Dashboard показывает только применение сохранённых шаблонов и отдельный блок для каждой пачки игр. Owner и co-GM могут:
- создать новый batch из шаблона, выбрав только первую дату расписания;
- обновить общий
titleиlinkсразу у всех сессий batch; - выбрать режим уведомлений: дублировать важные сообщения игрокам в личку или оставить только групповые уведомления;
- перенести пачку, задав новую первую дату и фиксированный шаг между играми в днях;
- клонировать batch на следующую неделю или следующий календарный месяц.
После создания из шаблона или клонирования появляется новая пачка с новым Telegram-сообщением и пустым составом игроков. После редактирования или переноса исходное Telegram-сообщение расписания перерисовывается.
Если включён режим В группе и в личку, бот дополнительно отправляет игрокам персональные сообщения о RSVP за 24 часа, напоминание за 1 час, ссылку перед стартом, отмену и перенос. Если Telegram не позволяет написать игроку в ЛС, бот логирует ошибку и продолжает отправку остальным участникам.
Telegram Mini App Dashboard
Owner и co-GM могут открыть мобильный dashboard прямо из Telegram через кнопку меню бота или кнопку Открыть dashboard после /start. Страница /miniapp получает Telegram.WebApp.initData, отправляет его на серверный endpoint /auth/telegram-webapp, проходит HMAC-проверку токеном бота и выдаёт обычную cookie-сессию dashboard.
После входа Mini App использует те же страницы, что и Web Dashboard: список групп, карточки сессий, редактирование игры, повышение игрока из листа ожидания, применение шаблонов и bulk-операции batch. Доступ к чужим группам не появляется: все данные по-прежнему фильтруются через AuthorizedSessionService по роли owner/co-GM.
Если Telegram.WebApp.initData недоступен или серверная проверка Mini App не прошла, /miniapp показывает диагностичное состояние и fallback-кнопку входа. Fallback больше не зависит от внешнего redirect: Telegram Login Widget вызывает callback на странице, отправляет payload на /auth/telegram-login, получает cookie в текущем WebView и сразу возвращает пользователя в dashboard.
Другие команды
/listsessions— Показать список всех актуальных игр в этой группе.⏰ Перенестив сообщении расписания — Запустить голосование по 2-3 вариантам нового времени./deletesession— Удалить сессию./exportcalendar— Получить.icsфайл с играми./help— Справка по формату.
🏗 Разработка и запуск локально (.NET Aspire)
Для локальной разработки проще всего использовать .NET Aspire:
- Установите .NET 10 SDK и workload Aspire.
- Откройте решение
GM-Relay.slnx. - Установите переменные окружения (или user secrets) для
GmRelay.AppHost. - Запустите проект
GmRelay.AppHost. Aspire Dashboard запустится автоматически, предоставляя удобный мониторинг БД, бота и веб-интерфейса.
Note
При использовании Dapper в режиме Native AOT, все SQL-запросы используют строго типизированные DTO. Динамические типы (
dynamic) не поддерживаются.
📜 Лицензия
Проект распространяется под лицензией MIT. Использование в некоммерческих целях приветствуется.