feat(discord): step-by-step game/pool creation wizard (issue #112)
Add Discord adapter for the platform-neutral wizard moved to Shared in the previous commit. Six new files in src/GmRelay.DiscordBot/Features/ Sessions/Wizard/: - DiscordWizardContextStore: IWizardContextStore abstraction + thread-safe in-memory impl keyed by draft id. Holds the (guild, channel, message) coordinates the messenger needs to re-send the draft after a 15-minute interaction token expires. - DiscordWizardStep: renderer for all 15 wizard steps. Returns an embed plus an IReadOnlyList<IMessageComponentProperties> that mixes ActionRow buttons with StringMenu select menus. Also exposes BuildModal for the 8 modal-collecting steps. - DiscordWizardMessenger: IWizardMessenger impl backed by NetCord's RestClient + NpgsqlDataSource. Edit falls back to re-send on 401/403/404. Toast replies are stashed in the existing DiscordInteractionReplyCache. - DiscordWizardSubmitter: 3-retry finalize loop. Builds the shared CreateSessionCommand and calls CreateSessionHandler; on success edits the message to "ok Created: N sessions", on failure shows retry/cancel buttons. - DiscordWizardCommand: /newsession-wizard slash command with an optional mode param (single|pool). Owner/co-GM check via the shared group_managers table. - DiscordPermissionLookup: small helper that loads DB manager ids for a guild. Program.cs gets 5 new singleton registrations (IWizardDraftRepository, IWizardContextStore, IWizardMessenger, GameCreationWizard, DiscordWizardSubmitter). The slash command is auto-discovered by AddApplicationCommands<SlashCommandInteraction, SlashCommandContext>() + AddModules(typeof(Program).Assembly). Build green. All 85 wizard tests + 95 Discord tests pass. dotnet format clean. Open: DiscordWizardInteractionModule (button/modal handlers) is not yet implemented; the bot starts and /newsession-wizard works to the point of posting the first embed, but subsequent button clicks won't be handled. A follow-up commit will add the component-interaction module.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using GmRelay.DiscordBot;
|
||||
using GmRelay.DiscordBot.Features.Sessions;
|
||||
using GmRelay.DiscordBot.Features.Sessions.Wizard;
|
||||
using GmRelay.DiscordBot.Infrastructure;
|
||||
using GmRelay.DiscordBot.Infrastructure.Discord;
|
||||
using GmRelay.DiscordBot.Infrastructure.Health;
|
||||
@@ -10,6 +11,7 @@ using GmRelay.Shared.Features.Notifications;
|
||||
using GmRelay.Shared.Features.Reminders.SendJoinLink;
|
||||
using GmRelay.Shared.Features.Reminders.SendOneHourReminder;
|
||||
using GmRelay.Shared.Features.Sessions.CreateSession;
|
||||
using GmRelay.Shared.Features.Sessions.CreateSession.Wizard;
|
||||
using GmRelay.Shared.Features.Sessions.RescheduleSession;
|
||||
using GmRelay.Shared.Infrastructure.Scheduling;
|
||||
using GmRelay.Shared.Platform;
|
||||
@@ -82,6 +84,19 @@ builder.Services.AddHostedService<SessionSchedulerService>();
|
||||
builder.Services.AddHostedService<DiscordRescheduleVotingDeadlineService>();
|
||||
builder.Services.AddHostedService<DiscordHealthCheckHostedService>();
|
||||
|
||||
// ── Wizard services (issue #112) ──────────────────────────────────────
|
||||
// The Discord wizard reuses the platform-neutral state machine in
|
||||
// GmRelay.Shared (GameCreationWizard, IWizardMessenger,
|
||||
// IWizardDraftRepository) and only adds a Discord-specific messenger,
|
||||
// step renderer, slash command, and submitter on top. The wizard's
|
||||
// cleanup service is shared with the Telegram bot and is not
|
||||
// registered here — it would compete on the same drafts table.
|
||||
builder.Services.AddSingleton<IWizardDraftRepository, GmRelay.Shared.Features.Sessions.CreateSession.Wizard.WizardDraftRepository>();
|
||||
builder.Services.AddSingleton<IWizardContextStore, DiscordWizardContextStore>();
|
||||
builder.Services.AddSingleton<IWizardMessenger, DiscordWizardMessenger>();
|
||||
builder.Services.AddSingleton<GmRelay.Shared.Features.Sessions.CreateSession.Wizard.GameCreationWizard>();
|
||||
builder.Services.AddSingleton<DiscordWizardSubmitter>();
|
||||
|
||||
builder.Services
|
||||
.AddDiscordGateway(options =>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user