180 lines
14 KiB
Markdown
180 lines
14 KiB
Markdown
# 🎲 GM-Relay: TTRPG Session Scheduling Bot & Web Dashboard
|
||
|
||
**GM-Relay** — это комплексное решение для Мастеров Подземелий (ГМов), состоящее из высокопроизводительного Telegram-бота и удобного веб-интерфейса. Предназначено для автоматизации записи игроков на сессии, управления расписанием и проведения игр.
|
||
|
||
Проект разработан с упором на производительность, архитектуру Vertical Slice, Native AOT (для бота) и удобство развертывания с использованием .NET Aspire.
|
||
|
||
**Текущая версия:** `v1.7.0`.
|
||
|
||
---
|
||
|
||
## ✨ Ключевые возможности
|
||
|
||
### 🤖 Telegram Бот
|
||
- **📅 Создание расписаний (Batch Sessions)**: Создавайте сразу несколько игр одним сообщением (на неделю или месяц вперед).
|
||
- **✋ Интерактивная запись и выход**: Игроки записываются на конкретные даты и самостоятельно снимают запись нажатием одной кнопки.
|
||
- **👥 Лимит мест и лист ожидания**: ГМ задаёт максимальный состав, бот не переполняет сессию, автоматически ведёт очередь ожидания и освобождённое место отдаёт первому ожидающему.
|
||
- **📁 Поддержка Форумов (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 валидация).
|
||
- **📝 Удобное редактирование**: Веб-интерфейс для детального редактирования сессий, изменения дат, названий и статусов.
|
||
- **🤝 Co-GM и делегирование**: Owner группы назначает помощников по Telegram ID, а co-GM получает доступ к управлению расписанием в Telegram и Web Dashboard.
|
||
- **🧩 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. Настройка окружения
|
||
Скопируйте файл-шаблон и заполните его значениями:
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
Отредактируйте `.env`:
|
||
|
||
```env
|
||
# Токен вашего бота от @BotFather (используется и для бота, и как секретный ключ для веб-авторизации)
|
||
TELEGRAM_BOT_TOKEN=ваш_токен_здесь
|
||
|
||
# Имя вашего бота в Telegram (без @), например: GmRelayBot.
|
||
# Найти его можно в информации о боте у @BotFather.
|
||
# Используется для работы виджета авторизации (Telegram Login Widget).
|
||
TELEGRAM_BOT_USERNAME=ваше_имя_бота_здесь
|
||
|
||
# Пароль для базы данных PostgreSQL
|
||
POSTGRES_PASSWORD=ваш_надежный_пароль
|
||
|
||
# Локальный порт веб-интерфейса GM-Relay
|
||
GMRELAY_WEB_PORT=8080
|
||
```
|
||
|
||
*(Опционально)* Настройте домен Telegram бота в @BotFather командой `/setdomain` для работы виджета авторизации на вашем сайте.
|
||
|
||
### 3. Запуск
|
||
Выполните команду:
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
Инфраструктура автоматически:
|
||
- Создаст локальную Docker-сеть и volume PostgreSQL, если их ещё нет.
|
||
- Поднимет PostgreSQL, доступный для контейнеров как `db:5432`.
|
||
- Запустит бота (применив миграции БД).
|
||
- Запустит веб-интерфейс на `http://localhost:8080` или другом порту из `GMRELAY_WEB_PORT`.
|
||
|
||
---
|
||
|
||
## ⚙️ Настройка бота в Telegram
|
||
|
||
Чтобы бот работал корректно:
|
||
1. **Добавьте бота в группу** (или Супергруппу/Форум).
|
||
2. **Назначьте бота Администратором**.
|
||
3. **Необходимые права**:
|
||
* `Выбор тем` (Managed Topics) — **обязательно** для Форумов.
|
||
* `Отправка сообщений`.
|
||
* `Закрепление сообщений` — рекомендуется.
|
||
|
||
> [!TIP]
|
||
> Owner группы определяется по первому человеку, который создал сессию в этой группе. Owner может назначать co-GM в Web Dashboard; owner и co-GM могут управлять сессиями через кнопки бота и веб-интерфейс.
|
||
|
||
---
|
||
|
||
## 📝 Инструкция для Мастера
|
||
|
||
### Создание расписания игр
|
||
Используйте команду `/newsession` с описанием в следующем формате:
|
||
|
||
```text
|
||
/newsession
|
||
Название: Легенды Берега Мечей (D&D 5e)
|
||
Время: 15.05.2024 19:30
|
||
Время: 22.05.2024 19:00
|
||
Мест: 4
|
||
Ссылка: https://discord.gg/invite-link
|
||
```
|
||
|
||
Строка `Мест:` необязательна. Если она указана, игроки сверх лимита попадут в лист ожидания, а ГМ сможет повысить первого ожидающего через кнопку в Telegram или Web Dashboard.
|
||
|
||
Игрок может самостоятельно снять запись кнопкой `🚪 Выйти` в сообщении расписания. Если он был в основном составе и в листе ожидания есть игроки, бот автоматически переводит первого ожидающего в основной состав и обновляет сообщение пачки.
|
||
|
||
### Делегирование управления
|
||
На странице группы Web Dashboard показывает owner и список co-GM. Owner может добавить помощника по Telegram ID, имени и username, а также снять роль co-GM. Назначенный co-GM видит группу в панели управления и может редактировать сессии, управлять batch-операциями, очередью, переносами и удалением игр, но не может назначать других co-GM.
|
||
|
||
### Перенос сессии голосованием
|
||
Owner или co-GM нажимает кнопку `⏰ Перенести` у нужной сессии и отправляет в чат 2-3 варианта нового времени вместе с дедлайном:
|
||
|
||
```text
|
||
25.04.2026 19:30
|
||
26.04.2026 18:00
|
||
Дедлайн: 25.04.2026 12:00
|
||
```
|
||
|
||
Дедлайн должен быть в будущем и раньше первого предложенного времени. Участники выбирают один вариант кнопкой в Telegram, могут изменить голос до дедлайна и видят текущие результаты в сообщении голосования. По дедлайну бот выбирает вариант с наибольшим числом голосов, переносит сессию, сбрасывает RSVP и обновляет batch-сообщение. Если голосов нет или есть ничья, перенос отклоняется, а время сессии остаётся прежним.
|
||
|
||
### Bulk-операции в Web Dashboard
|
||
На странице группы Web Dashboard показывает отдельный блок для каждой пачки игр. Owner и co-GM могут:
|
||
- обновить общий `title` и `link` сразу у всех сессий batch;
|
||
- выбрать режим уведомлений: дублировать важные сообщения игрокам в личку или оставить только групповые уведомления;
|
||
- перенести пачку, задав новую первую дату и фиксированный шаг между играми в днях;
|
||
- клонировать batch на следующую неделю или следующий календарный месяц.
|
||
|
||
После редактирования или переноса исходное Telegram-сообщение расписания перерисовывается. При клонировании создаётся новая пачка с новым Telegram-сообщением и пустым составом игроков.
|
||
|
||
Если включён режим `В группе и в личку`, бот дополнительно отправляет игрокам персональные сообщения о RSVP за 24 часа, напоминание за 1 час, ссылку перед стартом, отмену и перенос. Если Telegram не позволяет написать игроку в ЛС, бот логирует ошибку и продолжает отправку остальным участникам.
|
||
|
||
### Другие команды
|
||
- `/listsessions` — Показать список всех актуальных игр в этой группе.
|
||
- `⏰ Перенести` в сообщении расписания — Запустить голосование по 2-3 вариантам нового времени.
|
||
- `/deletesession` — Удалить сессию.
|
||
- `/exportcalendar` — Получить `.ics` файл с играми.
|
||
- `/help` — Справка по формату.
|
||
|
||
---
|
||
|
||
## 🏗 Разработка и запуск локально (.NET Aspire)
|
||
|
||
Для локальной разработки проще всего использовать .NET Aspire:
|
||
|
||
1. Установите [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) и workload Aspire.
|
||
2. Откройте решение `GM-Relay.slnx`.
|
||
3. Установите переменные окружения (или user secrets) для `GmRelay.AppHost`.
|
||
4. Запустите проект `GmRelay.AppHost`. Aspire Dashboard запустится автоматически, предоставляя удобный мониторинг БД, бота и веб-интерфейса.
|
||
|
||
> [!NOTE]
|
||
> При использовании **Dapper** в режиме Native AOT, все SQL-запросы используют строго типизированные DTO. Динамические типы (`dynamic`) не поддерживаются.
|
||
|
||
---
|
||
|
||
## 📜 Лицензия
|
||
Проект распространяется под лицензией MIT. Использование в некоммерческих целях приветствуется.
|