docs: update wiki for 1.7.0 reschedule voting

2026-04-27 14:58:56 +03:00
parent e668e4756b
commit 5e33e3bbae
7 changed files with 49 additions and 23 deletions
@@ -19,7 +19,7 @@ GM-Relay состоит из нескольких .NET-проектов и об
- сценариев немного, отдельный Clean Architecture слой был бы лишним; - сценариев немного, отдельный Clean Architecture слой был бы лишним;
- зависимости Npgsql и Telegram.Bot стабильны; - зависимости Npgsql и Telegram.Bot стабильны;
- Native AOT требует явной регистрации зависимостей и аккуратного SQL-маппинга; - Native AOT требует явной регистрации зависимостей и аккуратного SQL-маппинга;
- BackgroundService + PeriodicTimer проще и надёжнее Quartz.NET для двух периодических проверок. - BackgroundService + PeriodicTimer проще и надёжнее Quartz.NET для периодических проверок расписания и дедлайнов голосования.
## Поток Telegram updates ## Поток Telegram updates
@@ -33,9 +33,9 @@ GM-Relay состоит из нескольких .NET-проектов и об
- callback `cancel_session:<sessionId>`; - callback `cancel_session:<sessionId>`;
- callback `delete_session:<sessionId>`; - callback `delete_session:<sessionId>`;
- callback `reschedule_session:<sessionId>`; - callback `reschedule_session:<sessionId>`;
- callback `reschedule_vote:<yes|no>:<proposalId>`; - callback `reschedule_vote:<optionId>`;
- callback `rsvp:<confirm|decline>:<sessionId>`; - callback `rsvp:<confirm|decline>:<sessionId>`;
- обычные текстовые сообщения ГМа как ввод нового времени для активного переноса. - обычные текстовые сообщения ГМа как ввод 2-3 вариантов времени и дедлайна для активного переноса.
Маршрутизация не использует reflection или assembly scanning. Маршрутизация не использует reflection или assembly scanning.
@@ -52,6 +52,8 @@ GM-Relay состоит из нескольких .NET-проектов и об
Состояние хранится в PostgreSQL, поэтому после рестарта сервис продолжает работу без in-memory очередей. Состояние хранится в PostgreSQL, поэтому после рестарта сервис продолжает работу без in-memory очередей.
`RescheduleVotingDeadlineService` — отдельный stateless background service. Он раз в минуту ищет `reschedule_proposals` в статусе `Voting`, у которых `voting_deadline_at <= now()`, выбирает вариант с наибольшим числом голосов, применяет перенос или отклоняет голосование при ничьей/нуле голосов, обновляет Telegram-сообщения и сбрасывает RSVP при успешном переносе.
## Web UI ## Web UI
Blazor Server-приложение использует cookie auth и Telegram Login Widget. Blazor Server-приложение использует cookie auth и Telegram Login Widget.
@@ -1,6 +1,6 @@
# База данных # База данных
GM-Relay **v1.6.0** использует PostgreSQL. Изменения схемы управляются DbUp-миграциями, встроенными в `GmRelay.Bot` как embedded resources. GM-Relay **v1.7.0** использует PostgreSQL. Изменения схемы управляются DbUp-миграциями, встроенными в `GmRelay.Bot` как embedded resources.
## Миграции ## Миграции
@@ -14,6 +14,7 @@ GM-Relay **v1.6.0** использует PostgreSQL. Изменения схем
- `V006__add_session_capacity_waitlist.sql` — лимит мест `sessions.max_players`, статус участника `session_participants.registration_status`, время постановки в очередь `session_participants.created_at` и индексы для waitlist. - `V006__add_session_capacity_waitlist.sql` — лимит мест `sessions.max_players`, статус участника `session_participants.registration_status`, время постановки в очередь `session_participants.created_at` и индексы для waitlist.
- `V007__add_session_notification_mode.sql` — режим уведомлений `sessions.notification_mode`, отметка обработки T-1h reminder `sessions.one_hour_reminder_processed_at` и индекс для одночасовых напоминаний. - `V007__add_session_notification_mode.sql` — режим уведомлений `sessions.notification_mode`, отметка обработки T-1h reminder `sessions.one_hour_reminder_processed_at` и индекс для одночасовых напоминаний.
- `V008__add_group_managers.sql` — таблица `group_managers` для ролей `Owner` и `CoGm`; миграция переносит текущих GM из `game_groups.gm_telegram_id` в owner-записи. - `V008__add_group_managers.sql` — таблица `group_managers` для ролей `Owner` и `CoGm`; миграция переносит текущих GM из `game_groups.gm_telegram_id` в owner-записи.
- `V009__add_multi_option_reschedule_votes.sql` — дедлайн и выбранный вариант в `reschedule_proposals`, таблицы `reschedule_options` и `reschedule_option_votes` для голосования по нескольким слотам.
## Основные таблицы ## Основные таблицы
@@ -113,9 +114,22 @@ Bulk-операции Web не требуют новых таблиц: общи
- `Approved` — перенос принят. - `Approved` — перенос принят.
- `Rejected` — перенос отклонён. - `Rejected` — перенос отклонён.
Важные поля:
- `voting_deadline_at` — дедлайн голосования по вариантам.
- `selected_option_id` — победивший вариант после финализации, если перенос принят.
### reschedule_options
Варианты нового времени для активного предложения переноса. Для одного предложения хранится 2-3 строки с `display_order` и `proposed_at`.
### reschedule_option_votes
Голоса активных участников по вариантам переноса. Уникальная пара `proposal_id + player_id` не даёт одному участнику проголосовать несколько раз; повторный голос обновляет `option_id` и время `voted_at`.
### reschedule_votes ### reschedule_votes
Голоса активных участников по предложению переноса. Уникальная пара `proposal_id + player_id` не даёт одному участнику проголосовать несколько раз; повторный голос обновляет значение. Старая таблица голосов `yes/no` из версии одиночного переноса. Новые голосования используют `reschedule_option_votes`.
## Модель статусов ## Модель статусов
@@ -1,6 +1,6 @@
# Быстрый старт # Быстрый старт
Эта страница описывает минимальный запуск текущей версии GM-Relay **v1.6.0**. Эта страница описывает минимальный запуск текущей версии GM-Relay **v1.7.0**.
## Требования ## Требования
@@ -41,8 +41,8 @@ docker compose up -d
Compose поднимает: Compose поднимает:
- `db`: PostgreSQL 17 Alpine, БД `gmrelay_db`, пользователь `gmrelay`. - `db`: PostgreSQL 17 Alpine, БД `gmrelay_db`, пользователь `gmrelay`.
- `bot`: образ `git.codeanddice.ru/toutsu/gmrelay-bot:1.6.0`. - `bot`: образ `git.codeanddice.ru/toutsu/gmrelay-bot:1.7.0`.
- `web`: образ `git.codeanddice.ru/toutsu/gmrelay-web:1.6.0`. - `web`: образ `git.codeanddice.ru/toutsu/gmrelay-web:1.7.0`.
Web UI будет доступен на `http://localhost:8080`, если `GMRELAY_WEB_PORT` не переопределён. Web UI будет доступен на `http://localhost:8080`, если `GMRELAY_WEB_PORT` не переопределён.
@@ -72,6 +72,7 @@ dotnet run --project src/GmRelay.AppHost
- `/start` должен ответить `GM-Relay Bot ready. Use /help for commands.` - `/start` должен ответить `GM-Relay Bot ready. Use /help for commands.`
- `/help` должен показать формат `/newsession`, включая необязательную строку `Мест:`. - `/help` должен показать формат `/newsession`, включая необязательную строку `Мест:`.
- В сообщении расписания у активной сессии должны быть кнопки записи и `Выйти`. - В сообщении расписания у активной сессии должны быть кнопки записи и `Выйти`.
- Owner/co-GM может нажать `⏰ Перенести`, отправить 2-3 варианта времени и дедлайн; бот создаст голосование и применит победивший вариант по дедлайну.
- Web-панель должна перенаправлять неавторизованного пользователя на `/login`. - Web-панель должна перенаправлять неавторизованного пользователя на `/login`.
- После входа через Telegram пользователь видит группы, где он назначен owner или co-GM. - После входа через Telegram пользователь видит группы, где он назначен owner или co-GM.
- На странице группы owner видит блок управления co-GM, а owner/co-GM видят batch-операции: общий title/link, режим уведомлений, перенос всей пачки и клонирование batch. - На странице группы owner видит блок управления co-GM, а owner/co-GM видят batch-операции: общий title/link, режим уведомлений, перенос всей пачки и клонирование batch.
@@ -1,6 +1,6 @@
# Развёртывание # Развёртывание
Текущий production-like способ запуска GM-Relay **v1.6.0** — Docker Compose из `compose.yaml`. Текущий production-like способ запуска GM-Relay **v1.7.0** — Docker Compose из `compose.yaml`.
## Сервисы Docker Compose ## Сервисы Docker Compose
@@ -15,13 +15,13 @@
`bot`: `bot`:
- образ: `git.codeanddice.ru/toutsu/gmrelay-bot:1.6.0`; - образ: `git.codeanddice.ru/toutsu/gmrelay-bot:1.7.0`;
- запускается после успешного healthcheck сервиса `db`; - запускается после успешного healthcheck сервиса `db`;
- переменные окружения: `ConnectionStrings__gmrelaydb`, `Telegram__BotToken`. - переменные окружения: `ConnectionStrings__gmrelaydb`, `Telegram__BotToken`.
`web`: `web`:
- образ: `git.codeanddice.ru/toutsu/gmrelay-web:1.6.0`; - образ: `git.codeanddice.ru/toutsu/gmrelay-web:1.7.0`;
- запускается после успешного healthcheck сервиса `db`; - запускается после успешного healthcheck сервиса `db`;
- переменные окружения: `ConnectionStrings__gmrelaydb`, `Telegram__BotToken`, `Telegram__BotUsername`; - переменные окружения: `ConnectionStrings__gmrelaydb`, `Telegram__BotToken`, `Telegram__BotUsername`;
- порт: `${GMRELAY_WEB_PORT:-8080}:8080`; - порт: `${GMRELAY_WEB_PORT:-8080}:8080`;
@@ -92,7 +92,7 @@ docker compose down -v
## Поведение миграций ## Поведение миграций
Бот применяет DbUp-миграции при старте до обработки Telegram updates. В версии `1.6.0` добавлена миграция `V008__add_group_managers.sql`: она создаёт `group_managers` и переносит текущих GM в роль `Owner`. После обновления стоит проверить логи `bot`, чтобы убедиться, что миграции применились без ошибок. Бот применяет DbUp-миграции при старте до обработки Telegram updates. В версии `1.7.0` добавлена миграция `V009__add_multi_option_reschedule_votes.sql`: она создаёт таблицы вариантов и голосов для переноса сессии, а также дедлайн и выбранный вариант в `reschedule_proposals`. После обновления стоит проверить логи `bot`, чтобы убедиться, что миграции применились без ошибок.
## Безопасность ## Безопасность
@@ -26,7 +26,7 @@ dotnet run --project src/GmRelay.AppHost
`Directory.Build.props` задаёт: `Directory.Build.props` задаёт:
- `Version`: `1.6.0`. - `Version`: `1.7.0`.
- `TargetFramework`: `net10.0`. - `TargetFramework`: `net10.0`.
- `LangVersion`: `preview`. - `LangVersion`: `preview`.
- `Nullable`: `enable`. - `Nullable`: `enable`.
@@ -72,7 +72,7 @@ V006__add_example_column.sql
- domain/status helpers; - domain/status helpers;
- parser `/newsession`; - parser `/newsession`;
- RSVP flow rules; - RSVP flow rules;
- reschedule time input и vote rules; - reschedule voting input, multi-option vote rendering и deadline winner rules;
- rendering batch-сообщений; - rendering batch-сообщений;
- Telegram polling service behavior; - Telegram polling service behavior;
- secret redaction; - secret redaction;
@@ -1,6 +1,6 @@
# Руководство ГМа # Руководство ГМа
Руководство описывает пользовательские сценарии бота и Web-панели для GM-Relay **v1.6.0**. Руководство описывает пользовательские сценарии бота и Web-панели для GM-Relay **v1.7.0**.
## Кто управляет группой ## Кто управляет группой
@@ -95,11 +95,20 @@ Owner или co-GM может поднять первого игрока из о
1. Бот проверяет, что кнопку нажал owner или co-GM. 1. Бот проверяет, что кнопку нажал owner или co-GM.
2. Создаётся `reschedule_proposals` со статусом `AwaitingTime`. 2. Создаётся `reschedule_proposals` со статусом `AwaitingTime`.
3. Инициатор переноса пишет новое время обычным сообщением в чат. 3. Инициатор переноса пишет 2-3 варианта нового времени и дедлайн обычным сообщением в чат.
4. Если активных участников нет, бот переносит сессию сразу. 4. Если активных участников нет, бот переносит сессию сразу на первый предложенный вариант.
5. Если активные участники есть, бот создаёт голосование. 5. Если активные участники есть, бот создаёт голосование с кнопкой для каждого варианта.
6. Любой голос `Против` отклоняет перенос. 6. Участники видят текущие результаты в Telegram-сообщении и могут менять голос до дедлайна.
7. Если все активные участники согласились, бот переносит сессию, сбрасывает RSVP активных участников в `Pending`, очищает `confirmation_message_id` и `link_message_id`. 7. По дедлайну побеждает вариант с наибольшим числом голосов. Если голосов нет или есть ничья, перенос отклоняется.
8. При успешном переносе бот сбрасывает RSVP активных участников в `Pending`, очищает `confirmation_message_id` и `link_message_id`, обновляет batch-сообщение и отправляет результат в ЛС при включённом DM-режиме.
Формат ввода:
```text
25.04.2026 19:30
26.04.2026 18:00
Дедлайн: 25.04.2026 12:00
```
## RSVP и ссылка на игру ## RSVP и ссылка на игру
+3 -3
@@ -1,10 +1,10 @@
# Главная # Главная
GM-Relay — Telegram-бот и Blazor-панель для организации TTRPG-сессий. Текущее состояние документации соответствует репозиторию `Toutsu/GmRelayBot` и релизу **v1.6.0**. GM-Relay — Telegram-бот и Blazor-панель для организации TTRPG-сессий. Текущее состояние документации соответствует репозиторию `Toutsu/GmRelayBot` и релизу **v1.7.0**.
## Текущий стек ## Текущий стек
- Версия проекта: `1.6.0`. - Версия проекта: `1.7.0`.
- Платформа: `.NET 10`, C# preview, nullable reference types, warnings as errors. - Платформа: `.NET 10`, C# preview, nullable reference types, warnings as errors.
- Оркестрация разработки: `.NET Aspire 13` через `src/GmRelay.AppHost`. - Оркестрация разработки: `.NET Aspire 13` через `src/GmRelay.AppHost`.
- Runtime бота: `Worker Service`, Telegram long polling, Native AOT. - Runtime бота: `Worker Service`, Telegram long polling, Native AOT.
@@ -25,7 +25,7 @@ GM-Relay — Telegram-бот и Blazor-панель для организаци
- Автоматическое создание Telegram forum topic для пачки игр, если группа является форумом. - Автоматическое создание Telegram forum topic для пачки игр, если группа является форумом.
- Отмена отдельной сессии owner/co-GM из основного сообщения расписания. - Отмена отдельной сессии owner/co-GM из основного сообщения расписания.
- Управление сессиями через `/listsessions` с отображением мест и очереди ожидания. - Управление сессиями через `/listsessions` с отображением мест и очереди ожидания.
- Перенос сессии через кнопку owner/co-GM и голосование активных участников. - Перенос сессии через кнопку owner/co-GM: GM предлагает 2-3 времени и дедлайн, участники голосуют за варианты, бот показывает текущие результаты и применяет победителя по дедлайну.
- RSVP-подтверждение за 24 часа до игры только для основного состава. - RSVP-подтверждение за 24 часа до игры только для основного состава.
- Персональные DM-уведомления игрокам о RSVP за 24 часа, напоминание за 1 час, ссылке перед стартом, отмене и переносе. - Персональные DM-уведомления игрокам о RSVP за 24 часа, напоминание за 1 час, ссылке перед стартом, отмене и переносе.
- Отправка ссылки на подключение за 5 минут до подтверждённой игры. - Отправка ссылки на подключение за 5 минут до подтверждённой игры.