feat(discord): step-by-step game/pool creation wizard (issue #112) #122
Reference in New Issue
Block a user
Delete Branch "feat/issue-112-wizard-refactor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the Discord side of the platform-neutral game/pool creation wizard, mirroring the Telegram wizard shipped in 3.8.0 (issue #111). See deliverable.md and docs/review-report.md for details.
VERDICT from verifier (D:\Projects\Game\docs\review-report.md): REQUEST_CHANGES — wizard was functionally broken at runtime. ## Critical C-1. Choice-button customId was missing the 'choice:' segment. ButtonCustomId emitted 'wizard:btn:<step>:<value>' but the dispatcher's switch matches parts[1] == 'choice'. Every choice button (D&D 5e, Pathfinder, Waitlist, Publish, Confirm) fell into the default branch and showed 'Unknown button'. Fix: split into 3 customId helpers: ChoiceButtonCustomId(step, value) -> 'wizard:btn:choice:<step>:<value>' ControlButtonCustomId(action) -> 'wizard:btn:<action>:1' (back/cancel/skip/create) ModalTriggerButtonCustomId(modalStep) -> 'wizard:btn:modal:<modalStep>' Bulk-rewrote all 66 Btn() call sites in DiscordWizardStep.cs. C-2. "Другое…" modal-trigger buttons were unrouted in dispatcher. Added 'parts[1] == "modal"' branch that opens the modal via InteractionCallback.Modal(BuildModal(parts[2], draft.ChatId)). C-3. DiscordWizardSubmitter was leaking ex.Message from CreateSessionHandler to the user-visible draft embed. Postgres exceptions expose schema/constraint names. Replaced with generic user-facing error; full exception still logged server-side on the existing catch block. ## I-3 — parser-roundtrip tests (the gap that let C-1/C-2 through) Added two real behavioural tests (not string-grep) to DiscordWizardInteractionModuleSourceTests: - Renderer_And_Dispatcher_Agree_On_Wire_Format - ControlButtons_Are_Parsed_As_Control_Not_Choice These mirror NetCord's [ComponentInteraction("wizard")] prefix strip, run the parser, and assert the dispatcher would route to the right branch. Catches the entire class of 'renderer and dispatcher disagree on the wire format' regressions. ## I-6 — BuildResumeRow (cascading fix from C-1) After C-1, BuildResumeRow's ButtonCustomId('cancel', '1') would emit the wrong format. Switched to direct format strings ('wizard:btn:cancel:1', 'wizard:btn:resume:continue', etc.) which match the dispatcher's 'back'/'cancel'/'create'/'resume' cases directly, not the 'choice' prefix. ## Version sync (3.8.0 -> 3.9.0) Directory.Build.props: <Version>3.9.0</Version> compose.yaml: all 3 image tags -> 3.9.0 Version_ShouldBeSynchronizedForDiscordFeatureRelease test now green. ## Stats build: 0 warnings, 0 errors format: 0 of 279 files need changes tests: 583 passed, 2 skipped (pre-existing), 0 failed files: 7 changed, 226 +, 79 -