mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
add: Added .quteedit command
add: Added an edit button to .quoteshow and .exprshow commands that opens a modal which lets you edit the quote or expr in question
This commit is contained in:
@@ -2,22 +2,30 @@
|
||||
|
||||
public interface INadekoInteractionService
|
||||
{
|
||||
public NadekoInteraction Create(
|
||||
public NadekoInteractionBase Create(
|
||||
ulong userId,
|
||||
ButtonBuilder button,
|
||||
Func<SocketMessageComponent, Task> onTrigger,
|
||||
bool singleUse = true);
|
||||
|
||||
public NadekoInteraction Create<T>(
|
||||
public NadekoInteractionBase Create<T>(
|
||||
ulong userId,
|
||||
ButtonBuilder button,
|
||||
Func<SocketMessageComponent, T, Task> onTrigger,
|
||||
in T state,
|
||||
bool singleUse = true);
|
||||
|
||||
NadekoInteraction Create(
|
||||
NadekoInteractionBase Create(
|
||||
ulong userId,
|
||||
SelectMenuBuilder menu,
|
||||
Func<SocketMessageComponent, Task> onTrigger,
|
||||
bool singleUse = true);
|
||||
|
||||
NadekoInteractionBase Create(
|
||||
ulong userId,
|
||||
ButtonBuilder button,
|
||||
ModalBuilder modal,
|
||||
Func<SocketModal, Task> onTrigger,
|
||||
bool singleUse = true);
|
||||
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
public sealed class NadekoButtonInteraction : NadekoInteraction
|
||||
public sealed class NadekoButtonInteractionHandler : NadekoInteractionBase
|
||||
{
|
||||
public NadekoButtonInteraction(
|
||||
public NadekoButtonInteractionHandler(
|
||||
DiscordSocketClient client,
|
||||
ulong authorId,
|
||||
ButtonBuilder button,
|
||||
|
@@ -3,12 +3,12 @@
|
||||
public static class NadekoInteractionExtensions
|
||||
{
|
||||
public static MessageComponent CreateComponent(
|
||||
this NadekoInteraction nadekoInteraction
|
||||
this NadekoInteractionBase nadekoInteractionBase
|
||||
)
|
||||
{
|
||||
var cb = new ComponentBuilder();
|
||||
|
||||
nadekoInteraction.AddTo(cb);
|
||||
nadekoInteractionBase.AddTo(cb);
|
||||
|
||||
return cb.Build();
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
public sealed class NadekoSelectInteraction : NadekoInteraction
|
||||
public sealed class NadekoButtonSelectInteractionHandler : NadekoInteractionBase
|
||||
{
|
||||
public NadekoSelectInteraction(
|
||||
public NadekoButtonSelectInteractionHandler(
|
||||
DiscordSocketClient client,
|
||||
ulong authorId,
|
||||
SelectMenuBuilder menu,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
namespace NadekoBot;
|
||||
|
||||
public abstract class NadekoInteraction
|
||||
public abstract class NadekoInteractionBase
|
||||
{
|
||||
private readonly ulong _authorId;
|
||||
private readonly Func<SocketMessageComponent, Task> _onAction;
|
||||
@@ -13,7 +13,7 @@ public abstract class NadekoInteraction
|
||||
private readonly string _customId;
|
||||
private readonly bool _singleUse;
|
||||
|
||||
public NadekoInteraction(
|
||||
public NadekoInteractionBase(
|
||||
DiscordSocketClient client,
|
||||
ulong authorId,
|
||||
string customId,
|
||||
@@ -85,4 +85,80 @@ public abstract class NadekoInteraction
|
||||
|
||||
public Task ExecuteOnActionAsync(SocketMessageComponent smc)
|
||||
=> _onAction(smc);
|
||||
}
|
||||
|
||||
public sealed class NadekoModalSubmitHandler
|
||||
{
|
||||
private readonly ulong _authorId;
|
||||
private readonly Func<SocketModal, Task> _onAction;
|
||||
private readonly bool _onlyAuthor;
|
||||
public DiscordSocketClient Client { get; }
|
||||
|
||||
private readonly TaskCompletionSource<bool> _interactionCompletedSource;
|
||||
|
||||
private IUserMessage message = null!;
|
||||
private readonly string _customId;
|
||||
|
||||
public NadekoModalSubmitHandler(
|
||||
DiscordSocketClient client,
|
||||
ulong authorId,
|
||||
string customId,
|
||||
Func<SocketModal, Task> onAction,
|
||||
bool onlyAuthor)
|
||||
{
|
||||
_authorId = authorId;
|
||||
_customId = customId;
|
||||
_onAction = onAction;
|
||||
_onlyAuthor = onlyAuthor;
|
||||
_interactionCompletedSource = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
Client = client;
|
||||
}
|
||||
|
||||
public async Task RunAsync(IUserMessage msg)
|
||||
{
|
||||
message = msg;
|
||||
|
||||
Client.ModalSubmitted += OnInteraction;
|
||||
await Task.WhenAny(Task.Delay(300_000), _interactionCompletedSource.Task);
|
||||
Client.ModalSubmitted -= OnInteraction;
|
||||
|
||||
await msg.ModifyAsync(m => m.Components = new ComponentBuilder().Build());
|
||||
}
|
||||
|
||||
private Task OnInteraction(SocketModal sm)
|
||||
{
|
||||
if (sm.Message.Id != message.Id)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (_onlyAuthor && sm.User.Id != _authorId)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (sm.Data.CustomId != _customId)
|
||||
return Task.CompletedTask;
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_interactionCompletedSource.TrySetResult(true);
|
||||
await ExecuteOnActionAsync(sm);
|
||||
|
||||
if (!sm.HasResponded)
|
||||
{
|
||||
await sm.DeferAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "An exception occured while handling a: {Message}", ex.Message);
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
public Task ExecuteOnActionAsync(SocketModal smd)
|
||||
=> _onAction(smd);
|
||||
}
|
@@ -9,19 +9,19 @@ public class NadekoInteractionService : INadekoInteractionService, INService
|
||||
_client = client;
|
||||
}
|
||||
|
||||
public NadekoInteraction Create(
|
||||
public NadekoInteractionBase Create(
|
||||
ulong userId,
|
||||
ButtonBuilder button,
|
||||
Func<SocketMessageComponent, Task> onTrigger,
|
||||
bool singleUse = true)
|
||||
=> new NadekoButtonInteraction(_client,
|
||||
=> new NadekoButtonInteractionHandler(_client,
|
||||
userId,
|
||||
button,
|
||||
onTrigger,
|
||||
onlyAuthor: true,
|
||||
singleUse: singleUse);
|
||||
|
||||
public NadekoInteraction Create<T>(
|
||||
public NadekoInteractionBase Create<T>(
|
||||
ulong userId,
|
||||
ButtonBuilder button,
|
||||
Func<SocketMessageComponent, T, Task> onTrigger,
|
||||
@@ -32,16 +32,46 @@ public class NadekoInteractionService : INadekoInteractionService, INService
|
||||
((Func<T, Func<SocketMessageComponent, Task>>)((data)
|
||||
=> smc => onTrigger(smc, data)))(state),
|
||||
singleUse);
|
||||
|
||||
public NadekoInteraction Create(
|
||||
|
||||
public NadekoInteractionBase Create(
|
||||
ulong userId,
|
||||
SelectMenuBuilder menu,
|
||||
Func<SocketMessageComponent, Task> onTrigger,
|
||||
bool singleUse = true)
|
||||
=> new NadekoSelectInteraction(_client,
|
||||
=> new NadekoButtonSelectInteractionHandler(_client,
|
||||
userId,
|
||||
menu,
|
||||
onTrigger,
|
||||
onlyAuthor: true,
|
||||
singleUse: singleUse);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create an interaction which opens a modal
|
||||
/// </summary>
|
||||
/// <param name="userId">Id of the author</param>
|
||||
/// <param name="button">Button builder for the button that will open the modal</param>
|
||||
/// <param name="modal">Modal</param>
|
||||
/// <param name="onTrigger">The function that will be called when the modal is submitted</param>
|
||||
/// <param name="singleUse">Whether the button is single use</param>
|
||||
/// <returns></returns>
|
||||
public NadekoInteractionBase Create(
|
||||
ulong userId,
|
||||
ButtonBuilder button,
|
||||
ModalBuilder modal,
|
||||
Func<SocketModal, Task> onTrigger,
|
||||
bool singleUse = true)
|
||||
=> Create(userId,
|
||||
button,
|
||||
async (smc) =>
|
||||
{
|
||||
await smc.RespondWithModalAsync(modal.Build());
|
||||
var modalHandler = new NadekoModalSubmitHandler(_client,
|
||||
userId,
|
||||
modal.CustomId,
|
||||
onTrigger,
|
||||
true);
|
||||
await modalHandler.RunAsync(smc.Message);
|
||||
},
|
||||
singleUse: singleUse);
|
||||
}
|
@@ -34,11 +34,11 @@ public partial class ResponseBuilder
|
||||
if (_paginationBuilder.AddPaginatedFooter)
|
||||
embed.AddPaginatedFooter(currentPage, lastPage);
|
||||
|
||||
NadekoInteraction? maybeInter = null;
|
||||
NadekoInteractionBase? maybeInter = null;
|
||||
|
||||
var model = await _builder.BuildAsync(ephemeral);
|
||||
|
||||
async Task<(NadekoButtonInteraction left, NadekoInteraction? extra, NadekoButtonInteraction right)>
|
||||
async Task<(NadekoButtonInteractionHandler left, NadekoInteractionBase? extra, NadekoButtonInteractionHandler right)>
|
||||
GetInteractions()
|
||||
{
|
||||
var leftButton = new ButtonBuilder()
|
||||
@@ -47,7 +47,7 @@ public partial class ResponseBuilder
|
||||
.WithEmote(InteractionHelpers.ArrowLeft)
|
||||
.WithDisabled(lastPage == 0 || currentPage <= 0);
|
||||
|
||||
var leftBtnInter = new NadekoButtonInteraction(_client,
|
||||
var leftBtnInter = new NadekoButtonInteractionHandler(_client,
|
||||
model.User?.Id ?? 0,
|
||||
leftButton,
|
||||
(smc) =>
|
||||
@@ -80,7 +80,7 @@ public partial class ResponseBuilder
|
||||
.WithEmote(InteractionHelpers.ArrowRight)
|
||||
.WithDisabled(lastPage == 0 || currentPage >= lastPage);
|
||||
|
||||
var rightBtnInter = new NadekoButtonInteraction(_client,
|
||||
var rightBtnInter = new NadekoButtonInteractionHandler(_client,
|
||||
model.User?.Id ?? 0,
|
||||
rightButton,
|
||||
(smc) =>
|
||||
|
@@ -19,7 +19,7 @@ public sealed partial class ResponseBuilder
|
||||
private readonly IBotStrings _bs;
|
||||
private readonly BotConfigService _bcs;
|
||||
private EmbedBuilder? embedBuilder;
|
||||
private NadekoInteraction? inter;
|
||||
private NadekoInteractionBase? inter;
|
||||
private Stream? fileStream;
|
||||
private string? fileName;
|
||||
private EmbedColor color = EmbedColor.Ok;
|
||||
@@ -340,7 +340,7 @@ public sealed partial class ResponseBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResponseBuilder Interaction(NadekoInteraction? interaction)
|
||||
public ResponseBuilder Interaction(NadekoInteractionBase? interaction)
|
||||
{
|
||||
inter = interaction;
|
||||
return this;
|
||||
@@ -395,7 +395,7 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
|
||||
return Task.FromResult<IReadOnlyCollection<T>>(ReadOnlyCollection<T>.Empty);
|
||||
};
|
||||
|
||||
public Func<int, Task<NadekoInteraction>>? InteractionFunc { get; private set; }
|
||||
public Func<int, Task<NadekoInteractionBase>>? InteractionFunc { get; private set; }
|
||||
|
||||
public int? Elems { get; private set; } = 1;
|
||||
public int ItemsPerPage { get; private set; } = 9;
|
||||
@@ -478,13 +478,13 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
|
||||
return paginationSender.SendAsync(IsEphemeral);
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Interaction(Func<int, Task<NadekoInteraction>> func)
|
||||
public SourcedPaginatedResponseBuilder<T> Interaction(Func<int, Task<NadekoInteractionBase>> func)
|
||||
{
|
||||
InteractionFunc = func; //async (i) => await func(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Interaction(NadekoInteraction inter)
|
||||
public SourcedPaginatedResponseBuilder<T> Interaction(NadekoInteractionBase inter)
|
||||
{
|
||||
InteractionFunc = _ => Task.FromResult(inter);
|
||||
return this;
|
||||
|
@@ -8,5 +8,5 @@
|
||||
public required AllowedMentions SanitizeMentions { get; set; }
|
||||
public IUser? User { get; set; }
|
||||
public bool Ephemeral { get; set; }
|
||||
public NadekoInteraction? Interaction { get; set; }
|
||||
public NadekoInteractionBase? Interaction { get; set; }
|
||||
}
|
Reference in New Issue
Block a user