listen for text response in YesNoPrompt interactive

This commit is contained in:
spiral 2021-07-02 06:35:25 -04:00
parent af801e2b01
commit 2b15815825
No known key found for this signature in database
GPG Key ID: A6059F0CA0E1BD31
3 changed files with 88 additions and 10 deletions

View File

@ -18,5 +18,8 @@ namespace Myriad.Rest.Types.Requests
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<AllowedMentions> AllowedMentions { get; init; } public Optional<AllowedMentions> AllowedMentions { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Optional<MessageComponent[]?> Components { get; init; }
} }
} }

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Autofac; using Autofac;
using Myriad.Rest.Types;
using Myriad.Rest.Types.Requests; using Myriad.Rest.Types.Requests;
using Myriad.Types; using Myriad.Types;
@ -15,10 +16,11 @@ namespace PluralKit.Bot.Interactive
{ {
public abstract class BaseInteractive public abstract class BaseInteractive
{ {
private readonly Context _ctx; protected readonly Context _ctx;
private readonly List<Button> _buttons = new(); protected readonly List<Button> _buttons = new();
private readonly TaskCompletionSource _tcs = new(); protected readonly TaskCompletionSource _tcs = new();
private bool _running; protected Message _message { get; private set; }
protected bool _running;
protected BaseInteractive(Context ctx) protected BaseInteractive(Context ctx)
{ {
@ -52,21 +54,28 @@ namespace PluralKit.Bot.Interactive
}); });
} }
protected async Task Finish(InteractionContext ctx) protected async Task Finish(InteractionContext? ctx = null)
{ {
foreach (var button in _buttons) foreach (var button in _buttons)
button.Disabled = true; button.Disabled = true;
if (ctx != null)
await Update(ctx); await Update(ctx);
else
await _ctx.Rest.EditMessage(_message.ChannelId, _message.Id, new MessageEditRequest {
Components = GetComponents()
});
_tcs.TrySetResult(); _tcs.TrySetResult();
} }
protected async Task<Message> Send(string? content = null, Embed? embed = null) protected async Task Send(string? content = null, Embed? embed = null, AllowedMentions? mentions = null)
{ {
return await _ctx.Rest.CreateMessage(_ctx.Channel.Id, new MessageRequest _message = await _ctx.Rest.CreateMessage(_ctx.Channel.Id, new MessageRequest
{ {
Content = content, Content = content,
Embed = embed, Embed = embed,
AllowedMentions = mentions,
Components = GetComponents() Components = GetComponents()
}); });
} }
@ -113,7 +122,7 @@ namespace PluralKit.Bot.Interactive
} }
} }
private void Cleanup() protected void Cleanup()
{ {
var dispatch = _ctx.Services.Resolve<InteractionDispatchService>(); var dispatch = _ctx.Services.Resolve<InteractionDispatchService>();
foreach (var button in _buttons) foreach (var button in _buttons)

View File

@ -1,7 +1,15 @@
using System;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Myriad.Gateway;
using Myriad.Rest.Types;
using Myriad.Types; using Myriad.Types;
using PluralKit.Core;
using Autofac;
namespace PluralKit.Bot.Interactive namespace PluralKit.Bot.Interactive
{ {
public class YesNoPrompt: BaseInteractive public class YesNoPrompt: BaseInteractive
@ -20,7 +28,13 @@ namespace PluralKit.Bot.Interactive
{ {
AddButton(ctx => OnButtonClick(ctx, true), AcceptLabel, AcceptStyle); AddButton(ctx => OnButtonClick(ctx, true), AcceptLabel, AcceptStyle);
AddButton(ctx => OnButtonClick(ctx, false), CancelLabel, CancelStyle); AddButton(ctx => OnButtonClick(ctx, false), CancelLabel, CancelStyle);
await Send(Message);
AllowedMentions mentions = null;
if (User != _ctx.Author.Id)
mentions = new AllowedMentions {Users = new[] {User!.Value}};
await Send(Message, mentions: mentions);
} }
private async Task OnButtonClick(InteractionContext ctx, bool result) private async Task OnButtonClick(InteractionContext ctx, bool result)
@ -35,6 +49,58 @@ namespace PluralKit.Bot.Interactive
await Finish(ctx); await Finish(ctx);
} }
private bool MessagePredicate(MessageCreateEvent e)
{
if (e.ChannelId != _ctx.Channel.Id) return false;
if (e.Author.Id != User) return false;
var response = e.Content.ToLowerInvariant();
if (response == "y" || response == "yes")
{
Result = true;
return true;
}
if (response == "n" || response == "no")
{
Result = false;
return true;
}
return false;
}
public new async Task Run()
{
// todo: can we split this up somehow so it doesn't need to be *completely* copied from BaseInteractive?
var cts = new CancellationTokenSource(Timeout.ToTimeSpan());
if (_running)
throw new InvalidOperationException("Action is already running");
_running = true;
var queue = _ctx.Services.Resolve<HandlerQueue<MessageCreateEvent>>();
var messageDispatch = queue.WaitFor(MessagePredicate, Timeout, cts.Token);
await Start();
cts.Token.Register(() => _tcs.TrySetException(new TimeoutException("Action timed out")));
try
{
var doneTask = await Task.WhenAny(_tcs.Task, messageDispatch);
if (doneTask == messageDispatch)
await Finish();
}
finally
{
Cleanup();
}
}
public YesNoPrompt(Context ctx): base(ctx) public YesNoPrompt(Context ctx): base(ctx)
{ {
User = ctx.Author.Id; User = ctx.Author.Id;