using Discord.WebSocket;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Discord.Interactions
{
///
/// Utility class containing helper methods for interacting with Discord Interactions.
///
public static class InteractionUtility
{
///
/// Wait for an Interaction event for a given amount of time as an asynchronous opration.
///
/// Client that should be listened to for the event.
/// Timeout duration for this operation.
/// Delegate for cheking whether an Interaction meets the requirements.
/// Token for canceling the wait operation.
///
/// A Task representing the asyncronous waiting operation. If the user responded in the given amount of time, Task result contains the user response,
/// otherwise the Task result is .
///
public static async Task WaitForInteractionAsync (BaseSocketClient client, TimeSpan timeout,
Predicate predicate, CancellationToken cancellationToken = default)
{
var tcs = new TaskCompletionSource();
var waitCancelSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
Task wait = Task.Delay(timeout, waitCancelSource.Token)
.ContinueWith((t) =>
{
if (!t.IsCanceled)
tcs.SetResult(null);
});
cancellationToken.Register(( ) => tcs.SetCanceled());
client.InteractionCreated += HandleInteraction;
var result = await tcs.Task.ConfigureAwait(false);
client.InteractionCreated -= HandleInteraction;
return result;
Task HandleInteraction (SocketInteraction interaction)
{
if (predicate(interaction))
{
waitCancelSource.Cancel();
tcs.SetResult(interaction);
}
return Task.CompletedTask;
}
}
///
/// Wait for an Message Component Interaction event for a given amount of time as an asynchronous opration .
///
/// Client that should be listened to for the event.
/// The message that or should originate from.
/// Timeout duration for this operation.
/// Token for canceling the wait operation.
///
/// A Task representing the asyncronous waiting operation with a result,
/// the result is null if the process timed out before receiving a valid Interaction.
///
public static Task WaitForMessageComponentAsync(BaseSocketClient client, IUserMessage fromMessage, TimeSpan timeout,
CancellationToken cancellationToken = default)
{
bool Predicate (SocketInteraction interaction) => interaction is SocketMessageComponent component &&
component.Message.Id == fromMessage.Id;
return WaitForInteractionAsync(client, timeout, Predicate, cancellationToken);
}
///
/// Create a confirmation dialog and wait for user input asynchronously.
///
/// Client that should be listened to for the event.
/// Send the confirmation prompt to this channel.
/// Timeout duration of this operation.
/// Optional custom prompt message.
/// Token for canceling the wait operation.
///
/// A Task representing the asyncronous waiting operation with a result,
/// the result is if the user declined the prompt or didnt answer in time, if the user confirmed the prompt.
///
public static async Task ConfirmAsync (BaseSocketClient client, IMessageChannel channel, TimeSpan timeout, string message = null,
CancellationToken cancellationToken = default)
{
message ??= "Would you like to continue?";
var confirmId = $"confirm";
var declineId = $"decline";
var component = new ComponentBuilder()
.WithButton("Confirm", confirmId, ButtonStyle.Success)
.WithButton("Cancel", declineId, ButtonStyle.Danger)
.Build();
var prompt = await channel.SendMessageAsync(message, components: component).ConfigureAwait(false);
var response = await WaitForMessageComponentAsync(client, prompt, timeout, cancellationToken).ConfigureAwait(false) as SocketMessageComponent;
await prompt.DeleteAsync().ConfigureAwait(false);
if (response != null && response.Data.CustomId == confirmId)
return true;
else
return false;
}
}
}