141 lines
8.4 KiB
Markdown
141 lines
8.4 KiB
Markdown
# 🎲 GM-Relay: TTRPG Session Scheduling Bot & Web Dashboard
|
||
|
||
**GM-Relay** — это комплексное решение для Мастеров Подземелий (ГМов), состоящее из высокопроизводительного Telegram-бота и удобного веб-интерфейса. Предназначено для автоматизации записи игроков на сессии, управления расписанием и проведения игр.
|
||
|
||
Проект разработан с упором на производительность, архитектуру Vertical Slice, Native AOT (для бота) и удобство развертывания с использованием .NET Aspire.
|
||
|
||
---
|
||
|
||
## ✨ Ключевые возможности
|
||
|
||
### 🤖 Telegram Бот
|
||
- **📅 Создание расписаний (Batch Sessions)**: Создавайте сразу несколько игр одним сообщением (на неделю или месяц вперед).
|
||
- **✋ Интерактивная запись**: Игроки записываются на конкретные даты нажатием одной кнопки.
|
||
- **📁 Поддержка Форумов (Telegram Topics)**: Бот автоматически создает тему во вложенных чатах Telegram под каждую новую пачку игр.
|
||
- **❌ Управление сессиями**: Мастер может отменять отдельные игры прямо в общем сообщении расписания.
|
||
- **🗓 Экспорт в Календарь**: Генерация файла `.ics` для добавления всех игр в Google, Apple или Яндекс Календарь одной командой.
|
||
- **🚀 Native AOT**: Скомпилирован в нативный бинарный файл. Мгновенный запуск и минимальное потребление памяти. Идеально для **Raspberry Pi**.
|
||
|
||
### 🌐 Web Dashboard (Blazor Server)
|
||
- **🔐 Авторизация через Telegram**: Безопасный вход с использованием Telegram Login Widget (HMAC-SHA256 валидация).
|
||
- **📝 Удобное редактирование**: Веб-интерфейс для детального редактирования сессий, изменения дат, названий и статусов.
|
||
- **🔄 Автоматическая синхронизация**: Любые изменения в веб-интерфейсе мгновенно обновляют сообщения с расписанием в 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]
|
||
> Колонку "Мастер" (GM) бот определяет по первому человеку, который создал сессию в этой группе. Только этот пользователь сможет отменять игры через кнопки бота и редактировать их в веб-интерфейсе.
|
||
|
||
---
|
||
|
||
## 📝 Инструкция для Мастера
|
||
|
||
### Создание расписания игр
|
||
Используйте команду `/newsession` с описанием в следующем формате:
|
||
|
||
```text
|
||
/newsession
|
||
Название: Легенды Берега Мечей (D&D 5e)
|
||
Время: 15.05.2024 19:30
|
||
Время: 22.05.2024 19:00
|
||
Ссылка: https://discord.gg/invite-link
|
||
```
|
||
|
||
### Другие команды
|
||
- `/listsessions` — Показать список всех актуальных игр в этой группе.
|
||
- `/reschedulesession` — Перенести сессию на другое время с голосованием игроков.
|
||
- `/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. Использование в некоммерческих целях приветствуется.
|