From 067eb80f76a5b7dece8c6bd8e89213cb8706f41a Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Wed, 5 Jun 2024 00:20:25 -0400
Subject: [PATCH 01/10] Implementing Pagination Helper function
---
docs/COMMAND-WIKI.md | 7 ++
.../miscellaneous/pagination-test.ts | 67 +++++++++++
src/commands/miscellaneous/pagination-test.ts | 16 +++
src/utils/pagination.ts | 113 ++++++++++++++++++
4 files changed, 203 insertions(+)
create mode 100644 src/commandDetails/miscellaneous/pagination-test.ts
create mode 100644 src/commands/miscellaneous/pagination-test.ts
create mode 100644 src/utils/pagination.ts
diff --git a/docs/COMMAND-WIKI.md b/docs/COMMAND-WIKI.md
index c2cc7eca..410edfad 100644
--- a/docs/COMMAND-WIKI.md
+++ b/docs/COMMAND-WIKI.md
@@ -258,6 +258,13 @@
- ``uwid``: The Quest ID of the user.
- **Subcommands:** None
+## pg
+- **Aliases:** `pagination`, `paginationtest`, `pgtest`
+- **Description:** Test the pagination feature.
+- **Examples:**
`.pg`
`.pagination`
`.pagination`
`.pgtest`
+- **Options:** None
+- **Subcommands:** None
+
## ping
- **Aliases:** `pong`
- **Description:** Ping the bot to see if it is alive. :ping_pong:
diff --git a/src/commandDetails/miscellaneous/pagination-test.ts b/src/commandDetails/miscellaneous/pagination-test.ts
new file mode 100644
index 00000000..bb92c81b
--- /dev/null
+++ b/src/commandDetails/miscellaneous/pagination-test.ts
@@ -0,0 +1,67 @@
+import { container, SapphireClient } from '@sapphire/framework';
+import { CodeyCommandDetails, getUserFromMessage } from '../../codeyCommand';
+import { EmbedBuilder, ButtonInteraction, ComponentType } from 'discord.js';
+import { PaginationBuilder } from '../../utils/pagination';
+import { Command as SapphireCommand } from '@sapphire/framework';
+import { SapphireMessageExecuteType, SapphireMessageResponse } from '../../codeyCommand';
+import {
+ Colors,
+ ButtonBuilder,
+ ButtonStyle,
+ ActionRowBuilder,
+ Message
+ } from 'discord.js';
+const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
+ _client,
+ messageFromUser,
+ _args,
+ ): Promise => {
+ const message = messageFromUser;
+ const author = getUserFromMessage(message).id;
+
+ const embedData = [
+ { title: 'Page 1', description: 'Content of Page 1 💙', color: 0xFF0000 },
+ { title: 'Page 2', description: 'Content of Page 2 🎉', color: 0x00FF00 },
+ { title: 'Page 3', description: 'Content of Page 3 👽', color: 0x0000FF }
+ ];
+
+ const embeds = embedData.map(data =>
+ new EmbedBuilder()
+ .setColor(Colors.Blue)
+ .setTitle(data.title)
+ .setDescription(data.description)
+ .setColor(data.color)
+ );
+ const msg = await message.reply({
+ embeds: [embeds[0]],
+ fetchReply: true
+ });
+
+ const reactFilter = (reaction: ButtonInteraction) => {
+ return reaction.user.id === author;
+ };
+
+ try {
+ await PaginationBuilder(msg, reactFilter, embeds);
+ } catch (error) {
+ await message.reply('Error or timeout occurred during navigation.');
+ }
+};
+
+export const paginationTestCommandDetails: CodeyCommandDetails = {
+ name: 'pg',
+ aliases: ['pagination', 'paginationtest', 'pgtest'],
+ description: 'Test the pagination feature.',
+ detailedDescription: `**Examples:**
+ \`${container.botPrefix}pg\`
+ \`${container.botPrefix}pagination\`
+ \`${container.botPrefix}pagination\`
+ \`${container.botPrefix}pgtest\``,
+
+ isCommandResponseEphemeral: false,
+ messageWhenExecutingCommand: 'Testing pagination...',
+ executeCommand: PaginationTestExecuteCommand,
+ messageIfFailure: 'Could not test pagination.',
+ options: [],
+ subcommandDetails: {},
+};
diff --git a/src/commands/miscellaneous/pagination-test.ts b/src/commands/miscellaneous/pagination-test.ts
new file mode 100644
index 00000000..a0d3e7dc
--- /dev/null
+++ b/src/commands/miscellaneous/pagination-test.ts
@@ -0,0 +1,16 @@
+import { Command } from '@sapphire/framework';
+import { CodeyCommand } from '../../codeyCommand';
+import { paginationTestCommandDetails } from '../../commandDetails/miscellaneous/pagination-test';
+
+export class MiscellaneousPaginationTestCommand extends CodeyCommand {
+ details = paginationTestCommandDetails;
+
+ public constructor(context: Command.Context, options: Command.Options) {
+ super(context, {
+ ...options,
+ aliases: paginationTestCommandDetails.aliases,
+ description: paginationTestCommandDetails.description,
+ detailedDescription: paginationTestCommandDetails.detailedDescription,
+ });
+ }
+}
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
new file mode 100644
index 00000000..a3c1db31
--- /dev/null
+++ b/src/utils/pagination.ts
@@ -0,0 +1,113 @@
+import {
+ Colors,
+ EmbedBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ ActionRowBuilder,
+ ButtonInteraction,
+ ComponentType,
+ Message
+} from 'discord.js';
+
+const COLLECTOR_TIMEOUT = 60000;
+
+export const PaginationBuilder = async (
+ message: Message,
+ reactFilter: (reaction: ButtonInteraction) => boolean,
+ embedPages: EmbedBuilder[],
+): Promise | undefined> => {
+ try {
+ if (!message || !embedPages || !embedPages.length) return;
+
+ var currentPage = 0;
+ const firstButton = new ButtonBuilder()
+ .setCustomId('first')
+ .setEmoji('⏮️')
+ .setLabel('First')
+ .setStyle(ButtonStyle.Primary)
+ .setDisabled(true);
+ const previousButton = new ButtonBuilder()
+ .setCustomId('previous')
+ .setEmoji('⬅️')
+ .setLabel('Previous')
+ .setStyle(ButtonStyle.Primary)
+ .setDisabled(true);
+ const pageCount = new ButtonBuilder()
+ .setCustomId('pagecount')
+ .setLabel(`${currentPage + 1}/${embedPages.length}`)
+ .setStyle(ButtonStyle.Secondary)
+ .setDisabled(true);
+ const nextButton = new ButtonBuilder()
+ .setCustomId('next')
+ .setEmoji('➡️')
+ .setLabel('Next')
+ .setStyle(ButtonStyle.Primary);
+ const lastButton = new ButtonBuilder()
+ .setCustomId('last')
+ .setEmoji('⏭️')
+ .setLabel('Last')
+ .setStyle(ButtonStyle.Primary);
+ const actionRow = new ActionRowBuilder().addComponents(
+ firstButton,
+ previousButton,
+ pageCount,
+ nextButton,
+ lastButton,
+ );
+
+ await message.edit({
+ embeds: [embedPages[currentPage]],
+ components: [actionRow],
+ });
+
+ const collector = message.createMessageComponentCollector({
+ filter: reactFilter,
+ componentType: ComponentType.Button,
+ time: COLLECTOR_TIMEOUT,
+ });
+
+ collector.on('collect', async (buttonInteraction: ButtonInteraction) => {
+ await buttonInteraction.deferUpdate();
+
+ switch (buttonInteraction.customId) {
+ case 'first':
+ currentPage = 0;
+ break;
+ case 'previous':
+ currentPage = Math.max(0, currentPage - 1);
+ break;
+ case 'next':
+ currentPage = Math.min(embedPages.length - 1, currentPage + 1);
+ break;
+ case 'last':
+ currentPage = embedPages.length - 1;
+ break;
+ }
+
+ // Update button states based on the current page
+ firstButton.setDisabled(currentPage === 0);
+ previousButton.setDisabled(currentPage === 0);
+ nextButton.setDisabled(currentPage === embedPages.length - 1);
+ lastButton.setDisabled(currentPage === embedPages.length - 1);
+ pageCount.setLabel(`${currentPage + 1}/${embedPages.length}`);
+
+ // Update the message with the new embed and button states
+ await message.edit({
+ embeds: [embedPages[currentPage]],
+ components: [actionRow],
+ });
+ });
+
+ collector.on('end', async () => {
+ await message.edit({
+ components: []
+ });
+ });
+
+ return message;
+ } catch (error) {
+ console.error('An error occurred:', error);
+ return undefined;
+ }
+};
+
\ No newline at end of file
From f139092593c86bab9295ebe0365c2fe3fe565d1f Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Wed, 5 Jun 2024 00:50:04 -0400
Subject: [PATCH 02/10] Testing and minor improvements
---
.../miscellaneous/pagination-test.ts | 93 +++++++++++--------
src/utils/pagination.ts | 17 ++--
2 files changed, 63 insertions(+), 47 deletions(-)
diff --git a/src/commandDetails/miscellaneous/pagination-test.ts b/src/commandDetails/miscellaneous/pagination-test.ts
index bb92c81b..8d280247 100644
--- a/src/commandDetails/miscellaneous/pagination-test.ts
+++ b/src/commandDetails/miscellaneous/pagination-test.ts
@@ -2,50 +2,67 @@ import { container, SapphireClient } from '@sapphire/framework';
import { CodeyCommandDetails, getUserFromMessage } from '../../codeyCommand';
import { EmbedBuilder, ButtonInteraction, ComponentType } from 'discord.js';
import { PaginationBuilder } from '../../utils/pagination';
-import { Command as SapphireCommand } from '@sapphire/framework';
import { SapphireMessageExecuteType, SapphireMessageResponse } from '../../codeyCommand';
-import {
- Colors,
- ButtonBuilder,
- ButtonStyle,
- ActionRowBuilder,
- Message
- } from 'discord.js';
+import { Colors } from 'discord.js';
+
const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
- _client,
- messageFromUser,
- _args,
- ): Promise => {
- const message = messageFromUser;
- const author = getUserFromMessage(message).id;
+ _client,
+ messageFromUser,
+ _args,
+): Promise => {
+ const message = messageFromUser;
+ const author = getUserFromMessage(message).id;
- const embedData = [
- { title: 'Page 1', description: 'Content of Page 1 💙', color: 0xFF0000 },
- { title: 'Page 2', description: 'Content of Page 2 🎉', color: 0x00FF00 },
- { title: 'Page 3', description: 'Content of Page 3 👽', color: 0x0000FF }
- ];
+ const embedData: { title: string; description: string; color: number }[] = [
+ {
+ title: 'Page 1',
+ description: 'Hey there! This is the content of Page 1 💙',
+ color: 0xFF0000
+ },
+ {
+ title: 'Page 2',
+ description: 'Hey there! This is the content of Page 2 🎉',
+ color: 0x00FF00
+ },
+ {
+ title: 'Page 3',
+ description: 'Hey there! This is the content of Page 3 👽',
+ color: 0x0000FF
+ },
+ {
+ title: 'Page 4',
+ description: 'Hey there! This is the content of Page 4 🎃',
+ color: 0xFF00FF
+ },
+ {
+ title: 'Page 5',
+ description: 'Hey there! This is the content of Page 5 🎄',
+ color: 0xFFFF00
+ },
+ ];
- const embeds = embedData.map(data =>
- new EmbedBuilder()
- .setColor(Colors.Blue)
- .setTitle(data.title)
- .setDescription(data.description)
- .setColor(data.color)
- );
- const msg = await message.reply({
- embeds: [embeds[0]],
- fetchReply: true
- });
+ const embeds: EmbedBuilder[] = embedData.map((data) =>
+ new EmbedBuilder()
+ .setColor(Colors.Blue)
+ .setTitle(data.title)
+ .setDescription(data.description)
+ .setColor(data.color)
+ );
+
+ const msg = await message.reply({
+ embeds: (embeds.length > 0) ? [embeds[0]] : [new EmbedBuilder().setColor(Colors.Red).setDescription('No pages to display.')],
+ fetchReply: true
+ });
- const reactFilter = (reaction: ButtonInteraction) => {
- return reaction.user.id === author;
- };
+ const reactFilter = (reaction: ButtonInteraction) => {
+ return reaction.user.id === author;
+ };
- try {
- await PaginationBuilder(msg, reactFilter, embeds);
- } catch (error) {
- await message.reply('Error or timeout occurred during navigation.');
- }
+ try {
+ await PaginationBuilder(msg, reactFilter, embeds);
+ } catch (error) {
+ await message.reply('Error or timeout occurred during navigation.');
+ }
};
export const paginationTestCommandDetails: CodeyCommandDetails = {
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index a3c1db31..2069f862 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -1,5 +1,4 @@
import {
- Colors,
EmbedBuilder,
ButtonBuilder,
ButtonStyle,
@@ -23,13 +22,13 @@ export const PaginationBuilder = async (
const firstButton = new ButtonBuilder()
.setCustomId('first')
.setEmoji('⏮️')
- .setLabel('First')
+ // .setLabel('First')
.setStyle(ButtonStyle.Primary)
.setDisabled(true);
const previousButton = new ButtonBuilder()
.setCustomId('previous')
.setEmoji('⬅️')
- .setLabel('Previous')
+ // .setLabel('Previous')
.setStyle(ButtonStyle.Primary)
.setDisabled(true);
const pageCount = new ButtonBuilder()
@@ -40,13 +39,15 @@ export const PaginationBuilder = async (
const nextButton = new ButtonBuilder()
.setCustomId('next')
.setEmoji('➡️')
- .setLabel('Next')
- .setStyle(ButtonStyle.Primary);
+ // .setLabel('Next')
+ .setStyle(ButtonStyle.Primary)
+ .setDisabled(embedPages.length <= 1);
const lastButton = new ButtonBuilder()
.setCustomId('last')
.setEmoji('⏭️')
- .setLabel('Last')
- .setStyle(ButtonStyle.Primary);
+ // .setLabel('Last')
+ .setStyle(ButtonStyle.Primary)
+ .setDisabled(embedPages.length <= 1);
const actionRow = new ActionRowBuilder().addComponents(
firstButton,
previousButton,
@@ -84,14 +85,12 @@ export const PaginationBuilder = async (
break;
}
- // Update button states based on the current page
firstButton.setDisabled(currentPage === 0);
previousButton.setDisabled(currentPage === 0);
nextButton.setDisabled(currentPage === embedPages.length - 1);
lastButton.setDisabled(currentPage === embedPages.length - 1);
pageCount.setLabel(`${currentPage + 1}/${embedPages.length}`);
- // Update the message with the new embed and button states
await message.edit({
embeds: [embedPages[currentPage]],
components: [actionRow],
From c004157ddcb28fcfd7606d847f12d5d343cf429d Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Wed, 5 Jun 2024 01:20:21 -0400
Subject: [PATCH 03/10] Cleaning up code
---
.../miscellaneous/pagination-test.ts | 51 ++++++++-----------
src/utils/pagination.ts | 36 ++++++++-----
2 files changed, 44 insertions(+), 43 deletions(-)
diff --git a/src/commandDetails/miscellaneous/pagination-test.ts b/src/commandDetails/miscellaneous/pagination-test.ts
index 8d280247..4ddf7820 100644
--- a/src/commandDetails/miscellaneous/pagination-test.ts
+++ b/src/commandDetails/miscellaneous/pagination-test.ts
@@ -1,8 +1,8 @@
-import { container, SapphireClient } from '@sapphire/framework';
+import { container } from '@sapphire/framework';
import { CodeyCommandDetails, getUserFromMessage } from '../../codeyCommand';
-import { EmbedBuilder, ButtonInteraction, ComponentType } from 'discord.js';
+import { EmbedBuilder } from 'discord.js';
import { PaginationBuilder } from '../../utils/pagination';
-import { SapphireMessageExecuteType, SapphireMessageResponse } from '../../codeyCommand';
+import { SapphireMessageExecuteType, SapphireMessageResponse } from '../../codeyCommand';
import { Colors } from 'discord.js';
const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
@@ -12,32 +12,32 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
): Promise => {
const message = messageFromUser;
const author = getUserFromMessage(message).id;
-
+
const embedData: { title: string; description: string; color: number }[] = [
{
- title: 'Page 1',
- description: 'Hey there! This is the content of Page 1 💙',
- color: 0xFF0000
+ title: 'Page 1',
+ description: 'Hey there! This is the content of Page 1 💙',
+ color: 0xff0000,
},
{
- title: 'Page 2',
- description: 'Hey there! This is the content of Page 2 🎉',
- color: 0x00FF00
+ title: 'Page 2',
+ description: 'Hey there! This is the content of Page 2 🎉',
+ color: 0x00ff00,
},
{
- title: 'Page 3',
- description: 'Hey there! This is the content of Page 3 👽',
- color: 0x0000FF
+ title: 'Page 3',
+ description: 'Hey there! This is the content of Page 3 👽',
+ color: 0x0000ff,
},
{
- title: 'Page 4',
- description: 'Hey there! This is the content of Page 4 🎃',
- color: 0xFF00FF
+ title: 'Page 4',
+ description: 'Hey there! This is the content of Page 4 🎃',
+ color: 0xff00ff,
},
{
- title: 'Page 5',
- description: 'Hey there! This is the content of Page 5 🎄',
- color: 0xFFFF00
+ title: 'Page 5',
+ description: 'Hey there! This is the content of Page 5 🎄',
+ color: 0xffff00,
},
];
@@ -46,20 +46,11 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
.setColor(Colors.Blue)
.setTitle(data.title)
.setDescription(data.description)
- .setColor(data.color)
+ .setColor(data.color),
);
-
- const msg = await message.reply({
- embeds: (embeds.length > 0) ? [embeds[0]] : [new EmbedBuilder().setColor(Colors.Red).setDescription('No pages to display.')],
- fetchReply: true
- });
-
- const reactFilter = (reaction: ButtonInteraction) => {
- return reaction.user.id === author;
- };
try {
- await PaginationBuilder(msg, reactFilter, embeds);
+ await PaginationBuilder(message, author, embeds);
} catch (error) {
await message.reply('Error or timeout occurred during navigation.');
}
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index 2069f862..8f5a2398 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -5,20 +5,26 @@ import {
ActionRowBuilder,
ButtonInteraction,
ComponentType,
- Message
+ Message,
+ ChatInputCommandInteraction,
+ CacheType,
} from 'discord.js';
-
-const COLLECTOR_TIMEOUT = 60000;
-
+
+const COLLECTOR_TIMEOUT = 120000;
+
export const PaginationBuilder = async (
- message: Message,
- reactFilter: (reaction: ButtonInteraction) => boolean,
+ originalMessage: Message | ChatInputCommandInteraction,
+ author: string,
embedPages: EmbedBuilder[],
): Promise | undefined> => {
try {
- if (!message || !embedPages || !embedPages.length) return;
-
- var currentPage = 0;
+ if (!embedPages || !embedPages.length) {
+ await originalMessage.reply({
+ embeds: [new EmbedBuilder().setColor(0xff0000).setDescription('No pages to display.')],
+ });
+ return;
+ }
+ let currentPage = 0;
const firstButton = new ButtonBuilder()
.setCustomId('first')
.setEmoji('⏮️')
@@ -56,13 +62,19 @@ export const PaginationBuilder = async (
lastButton,
);
+ const message = await originalMessage.reply({
+ embeds: [embedPages[currentPage]],
+ components: [actionRow],
+ fetchReply: true,
+ });
+
await message.edit({
embeds: [embedPages[currentPage]],
components: [actionRow],
});
const collector = message.createMessageComponentCollector({
- filter: reactFilter,
+ filter: (interaction) => interaction.user.id === author,
componentType: ComponentType.Button,
time: COLLECTOR_TIMEOUT,
});
@@ -99,14 +111,12 @@ export const PaginationBuilder = async (
collector.on('end', async () => {
await message.edit({
- components: []
+ components: [],
});
});
return message;
} catch (error) {
- console.error('An error occurred:', error);
return undefined;
}
};
-
\ No newline at end of file
From aa41e6a0076b400867624ab37acdd4ab7ff8aea8 Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Wed, 5 Jun 2024 20:09:19 -0400
Subject: [PATCH 04/10] Allow optional custom timeout
---
src/commandDetails/miscellaneous/pagination-test.ts | 2 +-
src/utils/pagination.ts | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/commandDetails/miscellaneous/pagination-test.ts b/src/commandDetails/miscellaneous/pagination-test.ts
index 4ddf7820..c7d2ab81 100644
--- a/src/commandDetails/miscellaneous/pagination-test.ts
+++ b/src/commandDetails/miscellaneous/pagination-test.ts
@@ -50,7 +50,7 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
);
try {
- await PaginationBuilder(message, author, embeds);
+ await PaginationBuilder(message, author, embeds, 10000);
} catch (error) {
await message.reply('Error or timeout occurred during navigation.');
}
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index 8f5a2398..16985518 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -16,6 +16,7 @@ export const PaginationBuilder = async (
originalMessage: Message | ChatInputCommandInteraction,
author: string,
embedPages: EmbedBuilder[],
+ timeout: number = COLLECTOR_TIMEOUT
): Promise | undefined> => {
try {
if (!embedPages || !embedPages.length) {
@@ -76,7 +77,7 @@ export const PaginationBuilder = async (
const collector = message.createMessageComponentCollector({
filter: (interaction) => interaction.user.id === author,
componentType: ComponentType.Button,
- time: COLLECTOR_TIMEOUT,
+ idle: timeout,
});
collector.on('collect', async (buttonInteraction: ButtonInteraction) => {
From 317f12b296a7ae7cfc633c68b44c9ea4bf9e7d96 Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Wed, 5 Jun 2024 20:10:38 -0400
Subject: [PATCH 05/10] Formatting files
---
src/utils/pagination.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index 16985518..f36db67b 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -16,7 +16,7 @@ export const PaginationBuilder = async (
originalMessage: Message | ChatInputCommandInteraction,
author: string,
embedPages: EmbedBuilder[],
- timeout: number = COLLECTOR_TIMEOUT
+ timeout: number = COLLECTOR_TIMEOUT,
): Promise | undefined> => {
try {
if (!embedPages || !embedPages.length) {
From 440e698615f0bfe4b6b4bfb60dd6770f2010df47 Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Tue, 18 Jun 2024 21:55:49 -0400
Subject: [PATCH 06/10] Adding paragraph input to pagination and pages limit
---
.../miscellaneous/pagination-test.ts | 53 +++++++++++++-
src/utils/pagination.ts | 72 ++++++++++++++++++-
2 files changed, 121 insertions(+), 4 deletions(-)
diff --git a/src/commandDetails/miscellaneous/pagination-test.ts b/src/commandDetails/miscellaneous/pagination-test.ts
index c7d2ab81..529894bd 100644
--- a/src/commandDetails/miscellaneous/pagination-test.ts
+++ b/src/commandDetails/miscellaneous/pagination-test.ts
@@ -1,7 +1,7 @@
import { container } from '@sapphire/framework';
import { CodeyCommandDetails, getUserFromMessage } from '../../codeyCommand';
import { EmbedBuilder } from 'discord.js';
-import { PaginationBuilder } from '../../utils/pagination';
+import { PaginationBuilder, PaginationBuilderFromText } from '../../utils/pagination';
import { SapphireMessageExecuteType, SapphireMessageResponse } from '../../codeyCommand';
import { Colors } from 'discord.js';
@@ -50,7 +50,56 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
);
try {
- await PaginationBuilder(message, author, embeds, 10000);
+ //await PaginationBuilder(message, author, embeds);
+
+ // await PaginationBuilderFromText(
+ // message,
+ // author,
+ // `Lorem Ipsum is simply dummy text of the printing and typesetting industry. \
+ // Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make \
+ // a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, \
+ // remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ // of Lorem Ipsum. Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, \
+ // consectetur, from a \
+ // Lorem \
+ // Ipsum passage, and going through the cites of the word in classical literature, \
+ // discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and \
+ // 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, \
+ // written in 45 BC. This book is a treatise on the theory of ethics, \
+ // very popular \
+ // during the Renaissance. The first \
+ // line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.`,
+ // );
+
+ // await PaginationBuilderFromText(message, author, "") // no content test case
+
+ // too much content test case, spaces are necessary after slash!!
+ await PaginationBuilderFromText(message, author, `Lorem Ipsum is simply dummy text of the printing and typesetting industry. \
+ Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make \
+ a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ of Lorem Ipsum. Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, \
+ consectetur, from a \
+ Lorem \
+ Ipsum passage, and going through the cites of the word in classical literature, \
+ discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and \
+ 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, \
+ written in 45 BC. This book is a treatise on the theory of ethics, \
+ very popular \
+ during the Renaissance. The first \
+ line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.`);
} catch (error) {
await message.reply('Error or timeout occurred during navigation.');
}
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index f36db67b..1e838ae3 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -10,7 +10,31 @@ import {
CacheType,
} from 'discord.js';
-const COLLECTOR_TIMEOUT = 120000;
+const COLLECTOR_TIMEOUT = 300000;
+const MAX_CHARS_PER_PAGE = 2048;
+const MAX_PAGES = 25;
+const getRandomColor = (): number => Math.floor(Math.random() * 16777215);
+
+const textToPages = (text: string, maxChars: number): string[] => {
+ const pages: string[] = [];
+ let currentPage = '';
+ let charCount = 0;
+
+ for (let i = 0; i < text.length; i++) {
+ currentPage += text[i];
+ charCount++;
+ if (text[i] === '\n' || charCount >= maxChars) {
+ pages.push(currentPage.trim());
+ currentPage = '';
+ charCount = 0;
+ }
+ }
+
+ if (currentPage.trim()) {
+ pages.push(currentPage.trim());
+ }
+ return pages;
+};
export const PaginationBuilder = async (
originalMessage: Message | ChatInputCommandInteraction,
@@ -25,6 +49,16 @@ export const PaginationBuilder = async (
});
return;
}
+ if (embedPages.length > MAX_PAGES) {
+ await originalMessage.reply({
+ embeds: [
+ new EmbedBuilder().setColor(0xff0000).setDescription(
+ `Too much content to display. Limit is ${MAX_PAGES} pages. \nCurrent content produces ${embedPages.length} pages.`,
+ ),
+ ],
+ });
+ return;
+ }
let currentPage = 0;
const firstButton = new ButtonBuilder()
.setCustomId('first')
@@ -111,9 +145,21 @@ export const PaginationBuilder = async (
});
collector.on('end', async () => {
+ firstButton.setDisabled(true);
+ previousButton.setDisabled(true);
+ nextButton.setDisabled(true);
+ lastButton.setDisabled(true);
+ pageCount.setDisabled(true);
+
await message.edit({
- components: [],
+ components: [actionRow],
});
+
+ setTimeout(async () => {
+ await message.edit({
+ components: [],
+ });
+ }, 3000);
});
return message;
@@ -121,3 +167,25 @@ export const PaginationBuilder = async (
return undefined;
}
};
+
+export const PaginationBuilderFromText = async (
+ originalMessage: Message | ChatInputCommandInteraction,
+ author: string,
+ text: string,
+ textPageSize: number = MAX_CHARS_PER_PAGE,
+ timeout: number = COLLECTOR_TIMEOUT,
+): Promise | undefined> => {
+ try {
+ const textPages = textToPages(text, textPageSize);
+ const embedPages = textPages.map((text, index) =>
+ new EmbedBuilder()
+ .setColor(getRandomColor())
+ .setTitle('Page ' + (index + 1))
+ .setDescription(text),
+ );
+
+ return PaginationBuilder(originalMessage, author, embedPages, timeout);
+ } catch (error) {
+ return undefined;
+ }
+};
From 01fa80b0935523a94827c5fe093fd5efc01846a2 Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Tue, 18 Jun 2024 21:57:18 -0400
Subject: [PATCH 07/10] Linting and formatting fixes!
---
.../miscellaneous/pagination-test.ts | 36 ++++++++++---------
src/utils/pagination.ts | 4 ++-
2 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/src/commandDetails/miscellaneous/pagination-test.ts b/src/commandDetails/miscellaneous/pagination-test.ts
index 529894bd..96590769 100644
--- a/src/commandDetails/miscellaneous/pagination-test.ts
+++ b/src/commandDetails/miscellaneous/pagination-test.ts
@@ -50,31 +50,34 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
);
try {
- //await PaginationBuilder(message, author, embeds);
+ await PaginationBuilder(message, author, embeds);
// await PaginationBuilderFromText(
// message,
// author,
- // `Lorem Ipsum is simply dummy text of the printing and typesetting industry. \
- // Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make \
- // a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, \
- // remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
- // of Lorem Ipsum. Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, \
- // consectetur, from a \
- // Lorem \
- // Ipsum passage, and going through the cites of the word in classical literature, \
- // discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and \
- // 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, \
- // written in 45 BC. This book is a treatise on the theory of ethics, \
- // very popular \
- // during the Renaissance. The first \
+ // `Lorem Ipsum is simply dummy text of the printing and typesetting industry. \
+ // Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make \
+ // a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, \
+ // remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ // of Lorem Ipsum. Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, \
+ // consectetur, from a \
+ // Lorem \
+ // Ipsum passage, and going through the cites of the word in classical literature, \
+ // discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and \
+ // 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, \
+ // written in 45 BC. This book is a treatise on the theory of ethics, \
+ // very popular \
+ // during the Renaissance. The first \
// line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.`,
// );
// await PaginationBuilderFromText(message, author, "") // no content test case
// too much content test case, spaces are necessary after slash!!
- await PaginationBuilderFromText(message, author, `Lorem Ipsum is simply dummy text of the printing and typesetting industry. \
+ await PaginationBuilderFromText(
+ message,
+ author,
+ `Lorem Ipsum is simply dummy text of the printing and typesetting industry. \
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make \
a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, \
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
@@ -99,7 +102,8 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
written in 45 BC. This book is a treatise on the theory of ethics, \
very popular \
during the Renaissance. The first \
- line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.`);
+ line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.`,
+ );
} catch (error) {
await message.reply('Error or timeout occurred during navigation.');
}
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index 1e838ae3..c8a346ec 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -52,7 +52,9 @@ export const PaginationBuilder = async (
if (embedPages.length > MAX_PAGES) {
await originalMessage.reply({
embeds: [
- new EmbedBuilder().setColor(0xff0000).setDescription(
+ new EmbedBuilder()
+ .setColor(0xff0000)
+ .setDescription(
`Too much content to display. Limit is ${MAX_PAGES} pages. \nCurrent content produces ${embedPages.length} pages.`,
),
],
From 4c78b8bbc40b4249bc364a507d54f1d22a4b7599 Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Tue, 18 Jun 2024 22:00:36 -0400
Subject: [PATCH 08/10] Adding better test case to demonstrate functionality
---
src/commandDetails/miscellaneous/pagination-test.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/commandDetails/miscellaneous/pagination-test.ts b/src/commandDetails/miscellaneous/pagination-test.ts
index 96590769..9ba1b1d9 100644
--- a/src/commandDetails/miscellaneous/pagination-test.ts
+++ b/src/commandDetails/miscellaneous/pagination-test.ts
@@ -82,9 +82,7 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, \
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
- remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
- remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
- remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
+ remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions \
From 5edac6c348843b46d0bd0b339115dc30b0866c44 Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Tue, 18 Jun 2024 22:25:07 -0400
Subject: [PATCH 09/10] Adding better leaderboard pagination support, ignore
newline option, and max line height
---
.../miscellaneous/pagination-test.ts | 37 ++++++++++++++++++-
src/utils/pagination.ts | 18 +++++++--
2 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/src/commandDetails/miscellaneous/pagination-test.ts b/src/commandDetails/miscellaneous/pagination-test.ts
index 9ba1b1d9..08214ce1 100644
--- a/src/commandDetails/miscellaneous/pagination-test.ts
+++ b/src/commandDetails/miscellaneous/pagination-test.ts
@@ -50,8 +50,9 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
);
try {
- await PaginationBuilder(message, author, embeds);
+ await PaginationBuilder(message, author, embeds); // 1. Test Embed List Pagination
+ // 2. Test Large Text Pagination
// await PaginationBuilderFromText(
// message,
// author,
@@ -71,9 +72,10 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
// line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.`,
// );
+ // 3. Test Empty String Case
// await PaginationBuilderFromText(message, author, "") // no content test case
- // too much content test case, spaces are necessary after slash!!
+ // 4. Test Large Text Pagination without ignoreNewLines (Spaces needed after \)
await PaginationBuilderFromText(
message,
author,
@@ -102,6 +104,37 @@ const PaginationTestExecuteCommand: SapphireMessageExecuteType = async (
during the Renaissance. The first \
line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.`,
);
+
+ // 5. Test Leaderboard Text Pagination with ignoreNewLines
+ await PaginationBuilderFromText(
+ message,
+ author,
+ `1. palepinkroses#0 - 69749 :codey_coin: \
+2. cho_c0.#0 - 49700 :codey_coin: \
+3. infinit3e#0 - 47952 :codey_coin: \
+4. picowchew#0 - 29696 :codey_coin: \
+5. redapple410#0 - 20237 :codey_coin: \
+6. mcpenguin6194#0 - 19240 :codey_coin: \
+7. fylixz#0 - 18580 :codey_coin: \
+8. antangelo#0 - 16037 :codey_coin: \
+9. elegy2333#0 - 15842 :codey_coin: \
+10. icanc#0 - 15828 :codey_coin: \
+11. sagar1#0 - 15700 :codey_coin: \
+12. sagar2#0 - 15600 :codey_coin: \
+13. sagar3#0 - 15500 :codey_coin: \
+14. sagar4#0 - 15400 :codey_coin: \
+15. sagar5#0 - 15300 :codey_coin: \
+16. sagar6#0 - 15200 :codey_coin: \
+17. sagar7#0 - 15100 :codey_coin: \
+18. sagar8#0 - 15000 :codey_coin: \
+19. sagar9#0 - 14900 :codey_coin: \
+20. sagar10#0 - 14800 :codey_coin: \
+21. sagar11#0 - 14700 :codey_coin: \
+22. sagar12#0 - 14600 :codey_coin: \
+Your Position \
+You are currently #213 in the leaderboard with 553 :codey_coin:.`,
+ true,
+ );
} catch (error) {
await message.reply('Error or timeout occurred during navigation.');
}
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index c8a346ec..ada75aad 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -13,20 +13,31 @@ import {
const COLLECTOR_TIMEOUT = 300000;
const MAX_CHARS_PER_PAGE = 2048;
const MAX_PAGES = 25;
+const MAX_NEWLINES_PER_PAGE = 10;
const getRandomColor = (): number => Math.floor(Math.random() * 16777215);
-const textToPages = (text: string, maxChars: number): string[] => {
+const textToPages = (text: string, maxChars: number, ignoreNewLines: boolean = false): string[] => {
const pages: string[] = [];
let currentPage = '';
+ let newLineCount = 0;
let charCount = 0;
for (let i = 0; i < text.length; i++) {
currentPage += text[i];
charCount++;
- if (text[i] === '\n' || charCount >= maxChars) {
+ if (text[i] === '\n') {
+ newLineCount++;
+ }
+
+ if (
+ (text[i] === '\n' && !ignoreNewLines) ||
+ charCount >= maxChars ||
+ newLineCount === MAX_NEWLINES_PER_PAGE
+ ) {
pages.push(currentPage.trim());
currentPage = '';
charCount = 0;
+ newLineCount = 0;
}
}
@@ -174,11 +185,12 @@ export const PaginationBuilderFromText = async (
originalMessage: Message | ChatInputCommandInteraction,
author: string,
text: string,
+ ignoreNewLines: boolean = false,
textPageSize: number = MAX_CHARS_PER_PAGE,
timeout: number = COLLECTOR_TIMEOUT,
): Promise | undefined> => {
try {
- const textPages = textToPages(text, textPageSize);
+ const textPages = textToPages(text, textPageSize, ignoreNewLines);
const embedPages = textPages.map((text, index) =>
new EmbedBuilder()
.setColor(getRandomColor())
From 2e7504a921f785de2a840d415fe2baf964af7614 Mon Sep 17 00:00:00 2001
From: Sagar Patel <2sagarpatel2@gmail.com>
Date: Tue, 18 Jun 2024 22:31:14 -0400
Subject: [PATCH 10/10] Fixing linting issue...
---
src/utils/pagination.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts
index ada75aad..3c9399a9 100644
--- a/src/utils/pagination.ts
+++ b/src/utils/pagination.ts
@@ -16,7 +16,7 @@ const MAX_PAGES = 25;
const MAX_NEWLINES_PER_PAGE = 10;
const getRandomColor = (): number => Math.floor(Math.random() * 16777215);
-const textToPages = (text: string, maxChars: number, ignoreNewLines: boolean = false): string[] => {
+const textToPages = (text: string, maxChars: number, ignoreNewLines: boolean): string[] => {
const pages: string[] = [];
let currentPage = '';
let newLineCount = 0;
@@ -185,7 +185,7 @@ export const PaginationBuilderFromText = async (
originalMessage: Message | ChatInputCommandInteraction,
author: string,
text: string,
- ignoreNewLines: boolean = false,
+ ignoreNewLines = false,
textPageSize: number = MAX_CHARS_PER_PAGE,
timeout: number = COLLECTOR_TIMEOUT,
): Promise | undefined> => {