# 🎲 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. Использование в некоммерческих целях приветствуется.