124 lines
3.4 KiB
C#
124 lines
3.4 KiB
C#
using Autofac;
|
|
|
|
using Myriad.Rest.Types;
|
|
using Myriad.Rest.Types.Requests;
|
|
using Myriad.Types;
|
|
|
|
using NodaTime;
|
|
|
|
namespace PluralKit.Bot.Interactive;
|
|
|
|
public abstract class BaseInteractive
|
|
{
|
|
protected readonly List<Button> _buttons = new();
|
|
protected readonly Context _ctx;
|
|
protected readonly TaskCompletionSource _tcs = new();
|
|
protected bool _running;
|
|
|
|
protected BaseInteractive(Context ctx)
|
|
{
|
|
_ctx = ctx;
|
|
}
|
|
|
|
protected Message _message { get; private set; }
|
|
|
|
public Duration Timeout { get; set; } = Duration.FromMinutes(5);
|
|
|
|
protected Button AddButton(Func<InteractionContext, Task> handler, string? label = null,
|
|
ButtonStyle style = ButtonStyle.Secondary, bool disabled = false)
|
|
{
|
|
var dispatch = _ctx.Services.Resolve<InteractionDispatchService>();
|
|
var customId = dispatch.Register(handler, Timeout);
|
|
|
|
var button = new Button
|
|
{
|
|
Label = label,
|
|
Style = style,
|
|
Disabled = disabled,
|
|
CustomId = customId,
|
|
};
|
|
_buttons.Add(button);
|
|
return button;
|
|
}
|
|
|
|
protected async Task Update(InteractionContext ctx)
|
|
{
|
|
await ctx.Respond(InteractionResponse.ResponseType.UpdateMessage,
|
|
new InteractionApplicationCommandCallbackData { Components = GetComponents() });
|
|
}
|
|
|
|
protected async Task Finish(InteractionContext? ctx = null)
|
|
{
|
|
foreach (var button in _buttons)
|
|
button.Disabled = true;
|
|
|
|
if (ctx != null)
|
|
await Update(ctx);
|
|
else
|
|
await _ctx.Rest.EditMessage(_message.ChannelId, _message.Id,
|
|
new MessageEditRequest { Components = GetComponents() });
|
|
|
|
_tcs.TrySetResult();
|
|
}
|
|
|
|
protected async Task Send(string? content = null, Embed? embed = null, AllowedMentions? mentions = null)
|
|
{
|
|
_message = await _ctx.Rest.CreateMessage(_ctx.Channel.Id,
|
|
new MessageRequest
|
|
{
|
|
Content = content,
|
|
Embeds = embed != null ? new[] { embed } : null,
|
|
AllowedMentions = mentions,
|
|
Components = GetComponents()
|
|
});
|
|
}
|
|
|
|
public MessageComponent[] GetComponents()
|
|
{
|
|
return new MessageComponent[]
|
|
{
|
|
new()
|
|
{
|
|
Type = ComponentType.ActionRow,
|
|
Components = _buttons.Select(b => b.ToMessageComponent()).ToArray()
|
|
}
|
|
};
|
|
}
|
|
|
|
public void Setup(Context ctx)
|
|
{
|
|
var dispatch = ctx.Services.Resolve<InteractionDispatchService>();
|
|
foreach (var button in _buttons)
|
|
button.CustomId = dispatch.Register(button.Handler, Timeout);
|
|
}
|
|
|
|
public abstract Task Start();
|
|
|
|
public async Task Run()
|
|
{
|
|
if (_running)
|
|
throw new InvalidOperationException("Action is already running");
|
|
_running = true;
|
|
|
|
await Start();
|
|
|
|
var cts = new CancellationTokenSource(Timeout.ToTimeSpan());
|
|
cts.Token.Register(() => _tcs.TrySetException(new TimeoutException("Action timed out")));
|
|
|
|
try
|
|
{
|
|
await _tcs.Task;
|
|
}
|
|
finally
|
|
{
|
|
Cleanup();
|
|
}
|
|
}
|
|
|
|
protected void Cleanup()
|
|
{
|
|
var dispatch = _ctx.Services.Resolve<InteractionDispatchService>();
|
|
foreach (var button in _buttons)
|
|
dispatch.Unregister(button.CustomId!);
|
|
}
|
|
} |