PluralKit/PluralKit.Bot/Interactive/BaseInteractive.cs

124 lines
3.4 KiB
C#
Raw Permalink Normal View History

2021-05-30 14:45:29 +00:00
using Autofac;
using Myriad.Rest.Types;
2021-05-30 14:45:29 +00:00
using Myriad.Rest.Types.Requests;
using Myriad.Types;
using NodaTime;
namespace PluralKit.Bot.Interactive;
public abstract class BaseInteractive
2021-05-30 14:45:29 +00:00
{
protected readonly List<Button> _buttons = new();
protected readonly Context _ctx;
protected readonly TaskCompletionSource _tcs = new();
protected bool _running;
protected BaseInteractive(Context ctx)
2021-05-30 14:45:29 +00:00
{
_ctx = ctx;
}
2021-08-27 15:03:47 +00:00
protected Message _message { get; private set; }
2021-05-30 14:45:29 +00:00
public Duration Timeout { get; set; } = Duration.FromMinutes(5);
2021-05-30 14:45:29 +00:00
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
2021-05-30 14:45:29 +00:00
{
Label = label,
Style = style,
Disabled = disabled,
CustomId = customId,
};
_buttons.Add(button);
return button;
}
2021-08-27 15:03:47 +00:00
protected async Task Update(InteractionContext ctx)
{
await ctx.Respond(InteractionResponse.ResponseType.UpdateMessage,
new InteractionApplicationCommandCallbackData { Components = GetComponents() });
}
2021-05-30 14:45:29 +00:00
protected async Task Finish(InteractionContext? ctx = null)
{
foreach (var button in _buttons)
button.Disabled = true;
2021-05-30 14:45:29 +00:00
if (ctx != null)
await Update(ctx);
else
await _ctx.Rest.EditMessage(_message.ChannelId, _message.Id,
new MessageEditRequest { Components = GetComponents() });
2021-05-30 14:45:29 +00:00
_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
2021-05-30 14:45:29 +00:00
{
Content = content,
2022-02-26 21:28:20 +00:00
Embeds = embed != null ? new[] { embed } : null,
AllowedMentions = mentions,
2021-05-30 14:45:29 +00:00
Components = GetComponents()
});
}
2021-05-30 14:45:29 +00:00
public MessageComponent[] GetComponents()
{
return new MessageComponent[]
2021-05-30 14:45:29 +00:00
{
new()
2021-05-30 14:45:29 +00:00
{
Type = ComponentType.ActionRow,
Components = _buttons.Select(b => b.ToMessageComponent()).ToArray()
}
};
}
2021-05-30 14:45:29 +00:00
public void Setup(Context ctx)
{
var dispatch = ctx.Services.Resolve<InteractionDispatchService>();
foreach (var button in _buttons)
button.CustomId = dispatch.Register(button.Handler, Timeout);
}
2021-05-30 14:45:29 +00:00
public abstract Task Start();
2021-08-27 15:03:47 +00:00
public async Task Run()
{
if (_running)
throw new InvalidOperationException("Action is already running");
_running = true;
2021-05-30 14:45:29 +00:00
await Start();
2021-08-27 15:03:47 +00:00
var cts = new CancellationTokenSource(Timeout.ToTimeSpan());
cts.Token.Register(() => _tcs.TrySetException(new TimeoutException("Action timed out")));
2021-05-30 14:45:29 +00:00
try
{
await _tcs.Task;
2021-05-30 14:45:29 +00:00
}
finally
2021-05-30 14:45:29 +00:00
{
Cleanup();
2021-05-30 14:45:29 +00:00
}
}
protected void Cleanup()
{
var dispatch = _ctx.Services.Resolve<InteractionDispatchService>();
foreach (var button in _buttons)
dispatch.Unregister(button.CustomId!);
}
2021-05-30 14:45:29 +00:00
}