Skip to content

Commit

Permalink
Merge pull request #5 from j4asper/3-refactor-to-get-rid-of-sendiniti…
Browse files Browse the repository at this point in the history
…alresponseasync

Refactor to get rid of sendinitialresponseasync
  • Loading branch information
j4asper authored Nov 27, 2024
2 parents 51530c7 + e48a69e commit 67a0a2b
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 70 deletions.
144 changes: 74 additions & 70 deletions DSharpPlus.BetterPagination/Extensions/CommandContextExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DSharpPlus.BetterPagination.Helpers;
using DSharpPlus.BetterPagination.Handlers;
using DSharpPlus.Commands;
using DSharpPlus.Commands.Processors.SlashCommands;
using DSharpPlus.Entities;
Expand Down Expand Up @@ -32,95 +32,99 @@ public static async Task SendBetterPaginatedMessageAsync(
bool allowUsageByAnyone = false)
{
var context = commandContext as SlashCommandContext
?? throw new InvalidCastException("CommandContext is not a SlashCommandContext.");

var pageCount = pages.Count;

var currentPage = 1;

var components = CreatePaginationComponents(currentPage, pageCount);
?? throw new InvalidCastException("CommandContext is not a SlashCommandContext.");

var message = await SendInitialResponseAsync(context, pages, components, additionalComponents, asEphemeral);
var paginationHandler = new PaginationHandler(pages);

var timedOut = false;
var initialResponse = await SendPaginatedMessageAsync(
context,
paginationHandler.GetCurrentPage(),
paginationHandler.GetPaginationButtons(),
additionalComponents,
asEphemeral,
isInitialMessage: true);

while (!timedOut)
var isTimedOut = false;

while (!isTimedOut)
{
var response =
await message.WaitForButtonAsync(c =>
c.Id == components[0].CustomId || c.Id == components[2].CustomId);
var interactionResponse = await initialResponse!.WaitForButtonAsync(c =>
paginationHandler.GetPaginationButtons().Any(x => x.CustomId == c.Id));

if (response.TimedOut)
if (interactionResponse.TimedOut)
{
await SendTimeoutResponseAsync(message, pages, pageCount, components, additionalComponents);

timedOut = true;
await SendPaginatedMessageAsync(
context,
paginationHandler.GetCurrentPage(),
paginationHandler.GetPaginationButtons(),
additionalComponents,
originalMessage: initialResponse,
isTimeoutMessage: true);

isTimedOut = true;
}
else
{
if (!allowUsageByAnyone && response.Result.User.Id != context.User.Id)
if (!allowUsageByAnyone && interactionResponse.Result.User.Id != context.User.Id)
continue;

if (response.Result.Id == components[0].CustomId)
currentPage--;

if (response.Result.Id == components[2].CustomId)
currentPage++;

var updatedComponents = CreatePaginationComponents(currentPage, pageCount, components[2].CustomId, components[0].CustomId);

var interactionResponse = new DiscordInteractionResponseBuilder()
.AddComponents(updatedComponents)
.WithPageContent(pages[currentPage - 1])
.WithPaginationArgs(additionalComponents, asEphemeral);

await response.Result.Interaction.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, interactionResponse);
Page? pageToShow = null;

if (interactionResponse.Result.Id == paginationHandler.BackButton.CustomId)
pageToShow = paginationHandler.GetPreviousPage();

if (interactionResponse.Result.Id == paginationHandler.ForwardButton.CustomId)
pageToShow = paginationHandler.GetNextPage();

await SendPaginatedMessageAsync(
context,
pageToShow!,
paginationHandler.GetPaginationButtons(),
additionalComponents,
asEphemeral,
interaction: interactionResponse.Result.Interaction);
}
}
}

private static IReadOnlyList<DiscordComponent> CreatePaginationComponents(int currentPage, int pageCount, string? forwardButtonId = null, string? backButtonId = null)
{
forwardButtonId ??= Guid.NewGuid().ToString();
backButtonId ??= Guid.NewGuid().ToString();

var backBtn = ButtonHelpers.CreateBackButton(backButtonId, currentPage);
var forwardBtn = ButtonHelpers.CreateForwardButton(forwardButtonId, currentPage, pageCount);
var pageLabel = ButtonHelpers.CreatePageLabel(Guid.NewGuid().ToString(), currentPage, pageCount);

return [backBtn, pageLabel, forwardBtn];
}

private static async Task<DiscordMessage> SendInitialResponseAsync(
private static async Task<DiscordMessage?> SendPaginatedMessageAsync(
SlashCommandContext context,
IReadOnlyList<Page> pages,
IReadOnlyList<DiscordComponent> components,
Page currentPage,
IReadOnlyList<DiscordComponent> paginationComponents,
IReadOnlyList<DiscordComponent>? additionalComponents = null,
bool asEphemeral = false)
bool asEphemeral = false,
DiscordInteraction? interaction = null,
bool isInitialMessage = false,
bool isTimeoutMessage = false,
DiscordMessage? originalMessage = null)
{
var interactionResponse = new DiscordInteractionResponseBuilder()
.AddComponents(components)
.WithPageContent(pages[0])
.WithPaginationArgs(additionalComponents, asEphemeral);

await context.Interaction.CreateResponseAsync(DiscordInteractionResponseType.ChannelMessageWithSource, interactionResponse);
if (isTimeoutMessage && originalMessage is not null)
{
var response = new DiscordMessageBuilder()
.AddComponents(paginationComponents)
.WithPaginationArgs(currentPage, additionalComponents);

var message = await context.Interaction.GetOriginalResponseAsync();
await originalMessage.ModifyAsync(response);
}
else
{
var response = new DiscordInteractionResponseBuilder()
.AddComponents(paginationComponents)
.WithPageContent(currentPage)
.WithPaginationArgs(additionalComponents, asEphemeral);

return message;
}
if (isInitialMessage)
{
await context.Interaction.CreateResponseAsync(DiscordInteractionResponseType.ChannelMessageWithSource, response);

private static async Task SendTimeoutResponseAsync(
DiscordMessage message,
IReadOnlyList<Page> pages,
int currentPage,
IReadOnlyList<DiscordComponent> components,
IReadOnlyList<DiscordComponent>? additionalComponents = null)
{
var timedOutResponse = new DiscordMessageBuilder()
.AddComponents(components)
.WithPaginationArgs(pages[currentPage - 1], additionalComponents);
var message = await context.Interaction.GetOriginalResponseAsync();

await message.ModifyAsync(timedOutResponse);
return message;
}

await interaction!.CreateResponseAsync(DiscordInteractionResponseType.UpdateMessage, response);
}

return null;
}
}
}
45 changes: 45 additions & 0 deletions DSharpPlus.BetterPagination/Handlers/PaginationHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using DSharpPlus.BetterPagination.Helpers;
using DSharpPlus.Entities;
using DSharpPlus.Interactivity;

namespace DSharpPlus.BetterPagination.Handlers;

internal class PaginationHandler
{
internal DiscordButtonComponent BackButton => ButtonHelpers.CreateBackButton(_backButtonId, _currentPageNumber);
internal DiscordButtonComponent PageLabel => ButtonHelpers.CreatePageLabel(nameof(PageLabel), _currentPageNumber, PageCount);
internal DiscordButtonComponent ForwardButton => ButtonHelpers.CreateForwardButton(_forwardButtonId, _currentPageNumber, PageCount);

private int PageCount => _pages.Count;

private int _currentPageNumber = 1;
private readonly IReadOnlyList<Page> _pages;
private readonly string _backButtonId;
private readonly string _forwardButtonId;

public PaginationHandler(IReadOnlyList<Page> pages)
{
_pages = pages;
_backButtonId = Guid.NewGuid().ToString();
_forwardButtonId = Guid.NewGuid().ToString();
}


internal Page GetCurrentPage() => _pages[_currentPageNumber - 1];

internal Page GetNextPage()
{
_currentPageNumber++;

return GetCurrentPage();
}

internal Page GetPreviousPage()
{
_currentPageNumber--;

return GetCurrentPage();
}

internal IReadOnlyList<DiscordButtonComponent> GetPaginationButtons() => [BackButton, PageLabel, ForwardButton];
}

0 comments on commit 67a0a2b

Please sign in to comment.