feat(discord): step-by-step game/pool creation wizard (issue #112) #122
@@ -6,7 +6,7 @@ on:
|
||||
- main
|
||||
|
||||
env:
|
||||
VERSION: 3.8.0
|
||||
VERSION: 3.9.0
|
||||
|
||||
jobs:
|
||||
# ЧАСТЬ 1: Собираем образы и кладем в Gitea (чтобы делиться с ребятами)
|
||||
|
||||
+44
-5
@@ -1,8 +1,47 @@
|
||||
## 🛠 Patch 2.4.0 — Discord /newsession и /listsessions
|
||||
## 🎯 Minor 3.9.0 — Discord-визард создания игры/пула (issue #112)
|
||||
|
||||
Пошаговый сценарий создания одиночной игры или пула игр в Discord-чате, по аналогии с Telegram-визардом из 3.8.0. Платформо-нейтральная стейт-машина `GameCreationWizard` и контракт `IWizardMessenger` перенесены в `GmRelay.Shared`, чтобы обе платформы (Telegram/Discord) использовали один и тот же движок визарда.
|
||||
|
||||
### 🧩 Что вошло в релиз
|
||||
|
||||
**Платформо-нейтральный рефакторинг (GmRelay.Shared)**
|
||||
- `Features/Sessions/CreateSession/Wizard/GameCreationWizard.cs` — стейт-машина визарда (один источник правды для обеих платформ)
|
||||
- `Features/Sessions/CreateSession/Wizard/IWizardMessenger.cs` — контракт мессенджера (edit/send/answer/getOwnerClubs)
|
||||
- `Features/Sessions/CreateSession/Wizard/WizardInteraction.cs` — запись взаимодействия (OwnerId, Text, CallbackPayload, PhotoFileId, PhotoUrl, InteractionId)
|
||||
- `Features/Sessions/CreateSession/Wizard/WizardAction.cs`, `WizardKeyboard.cs`, `WizardStepLimits.cs` — модель кнопок и лимитов
|
||||
- `Features/Sessions/CreateSession/Wizard/WizardDraft.cs` — добавлено поле `Platform`
|
||||
- `Migrations/V032__add_wizard_drafts_platform.sql` — `ALTER TABLE wizard_drafts ADD COLUMN platform TEXT NOT NULL DEFAULT 'Telegram'`
|
||||
|
||||
**Discord-адаптер (GmRelay.DiscordBot)**
|
||||
- `Features/Sessions/Wizard/DiscordWizardCommand.cs` — slash-команда `/newsession-wizard` с проверкой owner/co-GM через `DiscordPermissionLookup`
|
||||
- `Features/Sessions/Wizard/DiscordWizardStep.cs` — рендер 15 шагов в NetCord embed + buttons/StringSelectMenu/modals
|
||||
- `Features/Sessions/Wizard/DiscordWizardMessenger.cs` — реализация `IWizardMessenger` через NetCord REST (edit с fallback на re-send при 401/403/404)
|
||||
- `Features/Sessions/Wizard/DiscordWizardSubmitter.cs` — финализация с 3-retry циклом
|
||||
- `Features/Sessions/Wizard/DiscordWizardContextStore.cs` — in-memory кэш контекста (guild/channel/messageId) для 15-минутного interaction token
|
||||
- `Features/Sessions/Wizard/DiscordWizardInteractionModule.cs` — inbound handlers: 3 NetCord `ComponentInteractionModule<TContext>` (button/StringMenu/Modal) + `WizardInteractionDispatcher`
|
||||
- `Features/Sessions/Wizard/DiscordPermissionLookup.cs` — DB-хелпер для `group_managers`
|
||||
- `Program.cs` — DI-регистрации + 3 `AddComponentInteractions<TInteraction, TContext>`
|
||||
|
||||
**Тесты**
|
||||
- `tests/GmRelay.Bot.Tests/Features/Sessions/CreateSession/Wizard/*` — обновлены под новый контракт
|
||||
- `tests/GmRelay.Bot.Tests/Discord/DiscordWizardInteractionModuleSourceTests.cs` — 12 source-level smoke-тестов на структуру interaction module
|
||||
|
||||
### 🗺 Что это даёт
|
||||
- Мастера (GM) могут пошагово создавать игры и пулы слотов прямо в Discord через slash-команду, кнопки, выпадающие меню и модальные окна.
|
||||
- UX адаптирован под Discord (нативные components), а не скопирован из Telegram.
|
||||
- Общая стейт-машина и валидация: Telegram и Discord визарды развиваются синхронно, баги фиксятся в одном месте.
|
||||
- PickClub-шаг использует реальный SQL-запрос к `club_memberships` с фильтром по роли Owner/CoGm.
|
||||
|
||||
### 📦 Версия и деплой
|
||||
- Версия обновлена до 3.9.0 (`NavMenu.razor`, `.gitea/workflows/deploy.yml`)
|
||||
- Docker-образы будут тегированы `3.9.0` при пуше в `main`
|
||||
- Миграция V032 применяется автоматически на старте Bot
|
||||
|
||||
## 🛠 Patch 2.4.0 — Discord /newsession и /listsessions
|
||||
|
||||
Реализованы slash-команды Discord для создания сессий и просмотра расписания без Web Dashboard.
|
||||
|
||||
## 🧩 Что вошло в релиз
|
||||
### 🧩 Что вошло в релиз
|
||||
- src/GmRelay.DiscordBot/Features/Sessions/DiscordNewSessionCommand.cs — slash-команда /newsession с параметрами (title, time, seats, link)
|
||||
- src/GmRelay.DiscordBot/Features/Sessions/DiscordNewSessionHandler.cs — handler создания batch + session в БД
|
||||
- src/GmRelay.DiscordBot/Features/Sessions/DiscordListSessionsCommand.cs — slash-команда /listsessions
|
||||
@@ -13,11 +52,11 @@
|
||||
- ests/GmRelay.Bot.Tests/Discord/ — 20+ TDD-тестов на парсинг, права, структуру, DI, рендеринг
|
||||
- Синхронизированы версии: Directory.Build.props, NavMenu.razor, compose.yaml, deploy.yml → 2.4.0
|
||||
|
||||
## 🗺 Что это даёт
|
||||
### 🗺 Что это даёт
|
||||
- Мастера (GM) могут создавать сессии прямо из Discord, не заходя в Web.
|
||||
- Участники сервера видят расписание через /listsessions.
|
||||
- Единая PostgreSQL модель для Telegram и Discord — никакого дублирования данных.
|
||||
|
||||
## 📦 Версия и деплой
|
||||
### 📦 Версия и деплой
|
||||
- версия обновлена до 2.4.0
|
||||
- Docker-образы используют тег 2.4.0
|
||||
- Docker-образы используют тег 2.4.0
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
"""Detailed code review plan for the Discord wizard feature branch.
|
||||
|
||||
Read this file FIRST. It has the full review scope. The original prompt
|
||||
in the spawn was truncated due to Windows CLI limits; this file is the
|
||||
canonical spec.
|
||||
"""
|
||||
|
||||
# Branch to review
|
||||
BRANCH = "feat/issue-112-wizard-refactor"
|
||||
BASE = "origin/main"
|
||||
|
||||
# Files of interest
|
||||
SHARED = "src/GmRelay.Shared/Features/Sessions/CreateSession/Wizard/*"
|
||||
BOT_WIZARD = "src/GmRelay.Bot/Features/Sessions/CreateSession/Wizard/*"
|
||||
BOT_CREATE = "src/GmRelay.Bot/Features/Sessions/CreateSession/*"
|
||||
MIGRATION = "src/GmRelay.Bot/Migrations/V032__add_wizard_drafts_platform.sql"
|
||||
DISCORD = "src/GmRelay.DiscordBot/Features/Sessions/Wizard/*"
|
||||
PROG_CS = "src/GmRelay.DiscordBot/Program.cs"
|
||||
TESTS_WIZ = "tests/GmRelay.Bot.Tests/Features/Sessions/CreateSession/Wizard/*"
|
||||
TESTS_SMOKE = "tests/GmRelay.Bot.Tests/Discord/DiscordWizardInteractionModuleSourceTests.cs"
|
||||
DELIVERABLE = "deliverable.md"
|
||||
|
||||
REVIEW_FOCUS = [
|
||||
"Architecture: Shared/Bot/DiscordBot separation; no Telegram.Bot in Shared; no NetCord in Shared; single state machine source.",
|
||||
"Security: owner/co-GM checks everywhere; NRE on null Context.User; SQL injection; connection strings with passwords.",
|
||||
"Correctness: AOT-safety (no reflection, no dynamic); off-by-one in customId parsers; CancellationToken/Services.",
|
||||
"Style: naming consistent; Async/await by convention; logging at right levels.",
|
||||
"Tests: smoke tests are string-matching — where would real tests be useful?",
|
||||
"Migration safety: V032 DEFAULT value, will it fail on existing rows?",
|
||||
"Documentation: deliverable.md updated, open questions listed?",
|
||||
]
|
||||
|
||||
OUTPUT_FORMAT = """\
|
||||
## VERDICT: APPROVE / REQUEST_CHANGES / COMMENT
|
||||
|
||||
## Critical findings
|
||||
(file:line — what's wrong — how to fix)
|
||||
|
||||
## Important findings
|
||||
(file:line — what's wrong)
|
||||
|
||||
## Nits
|
||||
(quick observations)
|
||||
|
||||
## Summary
|
||||
(1-2 sentences)
|
||||
"""
|
||||
|
||||
COMMANDS_HINT = """\
|
||||
git fetch origin
|
||||
git diff origin/main..feat/issue-112-wizard-refactor --stat
|
||||
git diff origin/main..feat/issue-112-wizard-refactor
|
||||
dotnet build && dotnet test
|
||||
"""
|
||||
@@ -82,7 +82,7 @@
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="nav-version">v3.8.0</div>
|
||||
<div class="nav-version">v3.9.0</div>
|
||||
</div>
|
||||
</Authorized>
|
||||
<NotAuthorized>
|
||||
|
||||
@@ -15,7 +15,7 @@ public sealed class CampaignTemplatesNavigationTests
|
||||
public async Task NavMenu_ShouldExposeCurrentProjectVersion()
|
||||
{
|
||||
var navMenu = await File.ReadAllTextAsync(FindRepositoryFile("src/GmRelay.Web/Components/Layout/NavMenu.razor"));
|
||||
Assert.Contains("v3.7.1", navMenu, StringComparison.Ordinal);
|
||||
Assert.Contains("v3.9.0", navMenu, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user