8f0f2ef7e7
Moves the game-creation wizard state machine, view builder, and platform-neutral contracts (callback data, step names, storage exception, club option, step limits) from GmRelay.Bot to GmRelay.Shared. Telegram continues to work through a new TelegramWizardMessenger implementing IWizardMessenger and a WizardInteractionMapper that converts Update → WizardInteraction. Wires the new platform column on wizard_drafts (V032 migration) and switches chat/owner/thread/message ids to TEXT so the same table can hold Discord snowflakes later. - GameCreationWizard: now in Shared, takes IWizardMessenger + IWizardDraftRepository, dispatches on WizardInteraction. - New IWizardMessenger contract with Edit/Send/Answer/GetOwnerClubs (returns string ids so Telegram longs and Discord snowflakes both fit). - New WizardStepViewBuilder in Shared returns (text, IReadOnlyList<WizardAction>); TelegramWizardMessenger renders actions into InlineKeyboardMarkup via a new Bot-side ToInlineKeyboard helper. - New WizardInteractionMapper in Bot (5-case test) converts Telegram Update to WizardInteraction. - WizardDraft gains a Platform column; ChatId/MessageThreadId/OwnerId/ DraftMessageId switched to string. V032 migrates existing rows and rebuilds the owner lookup index on (platform, owner_id). - All existing wizard / create-session tests updated to the new contract (HandleInteractionAsync + WizardInteraction). Wizard callback-data format preserved. - dotnet build clean, dotnet format --verify-no-changes clean, all 101 wizard tests pass.
66 lines
2.6 KiB
C#
66 lines
2.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using GmRelay.Shared.Features.Sessions.CreateSession.Wizard;
|
|
using Telegram.Bot.Types.ReplyMarkups;
|
|
|
|
namespace GmRelay.Bot.Features.Sessions.CreateSession.Wizard;
|
|
|
|
/// <summary>
|
|
/// Telegram-side renderer for wizard keyboards. Acts as the adapter
|
|
/// between the platform-neutral <see cref="WizardAction"/> list
|
|
/// produced by <see cref="WizardStepViewBuilder"/> and Telegram's
|
|
/// <see cref="InlineKeyboardMarkup"/>. Each <see cref="WizardAction"/>
|
|
/// becomes its own row (matching the pre-refactor Telegram layout).
|
|
/// <see cref="WizardActionStyle"/> is currently ignored by Telegram
|
|
/// because the platform has no native primary/danger/success button
|
|
/// colours.
|
|
/// </summary>
|
|
public static class WizardStep
|
|
{
|
|
public const int MaxTitleLength = WizardStepLimits.MaxTitleLength;
|
|
public const int MaxDescriptionLength = WizardStepLimits.MaxDescriptionLength;
|
|
public const int MaxSystemLength = WizardStepLimits.MaxSystemLength;
|
|
public const int MaxCapacity = WizardStepLimits.MaxCapacity;
|
|
public const int MinCapacity = WizardStepLimits.MinCapacity;
|
|
public const int MinDurationHours = WizardStepLimits.MinDurationHours;
|
|
public const int MaxDurationHours = WizardStepLimits.MaxDurationHours;
|
|
|
|
/// <summary>
|
|
/// Render the platform-neutral view into a (text, Telegram keyboard)
|
|
/// pair. Used by the wizard's surrounding code (router, create
|
|
/// handler) when it needs to send a fresh draft message or render
|
|
/// the resume/reset menu.
|
|
/// </summary>
|
|
public static (string Text, InlineKeyboardMarkup Keyboard) Render(
|
|
WizardDraft draft,
|
|
WizardPayload payload,
|
|
IReadOnlyList<WizardClubOption>? clubs = null)
|
|
{
|
|
var (text, actions) = WizardStepViewBuilder.Build(draft, payload, clubs);
|
|
return (text, ToInlineKeyboard(actions));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a flat list of <see cref="WizardAction"/>s into a
|
|
/// Telegram keyboard. Each action is placed in its own row to
|
|
/// preserve the pre-refactor visual layout.
|
|
/// </summary>
|
|
public static InlineKeyboardMarkup ToInlineKeyboard(IReadOnlyList<WizardAction> actions)
|
|
{
|
|
if (actions.Count == 0)
|
|
{
|
|
return new InlineKeyboardMarkup(Array.Empty<InlineKeyboardButton[]>());
|
|
}
|
|
var rows = new InlineKeyboardButton[actions.Count][];
|
|
for (var i = 0; i < actions.Count; i++)
|
|
{
|
|
rows[i] = new[]
|
|
{
|
|
InlineKeyboardButton.WithCallbackData(actions[i].Label, actions[i].Payload),
|
|
};
|
|
}
|
|
return new InlineKeyboardMarkup(rows);
|
|
}
|
|
}
|