Skip to content

Instantly share code, notes, and snippets.

@peakh
Last active January 22, 2023 06:15
Show Gist options
  • Save peakh/128c7645be4f200c77fba5335fc63ee5 to your computer and use it in GitHub Desktop.
Save peakh/128c7645be4f200c77fba5335fc63ee5 to your computer and use it in GitHub Desktop.
Pagination with first page, previous, next, and last page buttons; includes automatic splicing within the other file.
import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';
import colors from '../util/colors';
/**
*
* @param {ChatInputCommandInteraction} interaction
* @param {EmbedBuilder} embeds
* @param {ButtonBuilder} buttons
* @returns
*/
const pagination = async(interaction: ChatInputCommandInteraction, embeds: any, buttons: Array<any>, time: number = 15000, ephemeral: boolean = false, footerText?: string) => {
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(buttons);
if(!embeds || embeds.length === 0) {
throw new Error(`No embeds were provided.`);
}
if(!buttons) {
throw new Error(`No buttons were provided.`);
}
if(buttons.length < 4 || buttons.length > 4) {
throw new Error(`The minimum and maximum amount of buttons are 4.`);
}
if(buttons[0].style === 'LINK' || buttons[1].style === 'LINK' || buttons[2].style === 'LINK' || buttons[3].style === 'LINK') {
throw new Error(`Buttons are not intended to be link-styled.`);
}
let page = 0;
if(interaction.deferred === false) {
await interaction.deferReply({ ephemeral: ephemeral || false });
}
embeds.length === 1 ? buttons[0].setDisabled(true) && buttons[1].setDisabled(true) && buttons[2].setDisabled(true) && buttons[3].setDisabled(true) : buttons[0].setDisabled(true) && buttons[1].setDisabled(true) && buttons[2].setDisabled(false) && buttons[3].setDisabled(false);
const currentPage = await interaction.editReply({
embeds: [
embeds[page].setFooter({ text: `${footerText?.length > 0 ? `${footerText} ` + '|' : ''} Page ${page + 1} of ${embeds.length}`})
],
components: [
row
]
});
// ? Maybe filter IDs.
const filter = (int: ButtonInteraction) => {
if(int.customId === buttons[0].data.custom_id || int.customId === buttons[1].data.custom_id || int.customId === buttons[2].data.custom_id ||int.customId === buttons[3].data.custom_id) {
return true;
}
int.reply({
embeds: [
new EmbedBuilder()
.setColor(colors.discord)
.setDescription(`Unknown interaction.`)
],
ephemeral: true
});
};
const collector = currentPage.createMessageComponentCollector({ filter: filter, time: time });
collector.on('collect', async (int: ButtonInteraction) => {
switch(int.customId) {
case buttons[0].data.custom_id:
page = page + 1 < embeds.length ? page = embeds.length - embeds.length : 0;
page === 0 ? buttons[0].setDisabled(true) && buttons[1].setDisabled(true) && buttons[2].setDisabled(false) && buttons[3].setDisabled(false) : buttons[0].setDisabled(false) && buttons[1].setDisabled(false);
break;
case buttons[1].data.custom_id:
page = page > 0 ? --page : embeds.length - 1;
page === 0 ? buttons[0].setDisabled(true) && buttons[1].setDisabled(true) && buttons[2].setDisabled(false) && buttons[3].setDisabled(false) : buttons[0].setDisabled(false) && buttons[1].setDisabled(false) && buttons[2].setDisabled(false) && buttons[3].setDisabled(false);
break;
case buttons[2].data.custom_id:
page = page + 1 < embeds.length ? ++page : 0;
page === embeds.length - 1 ? buttons[2].setDisabled(true) && buttons[3].setDisabled(true) && buttons[0].setDisabled(false) && buttons[1].setDisabled(false) : buttons[2].setDisabled(false) && buttons[3].setDisabled(false) && buttons[0].setDisabled(false) && buttons[1].setDisabled(false);
break;
case buttons[3].data.custom_id:
page = page + 1 < embeds.length ? page = embeds.length - 1 : 0;
page === embeds.length - 1 ? buttons[2].setDisabled(true) && buttons[3].setDisabled(true) && buttons[0].setDisabled(false) && buttons[1].setDisabled(false) : buttons[2].setDisabled(false) && buttons[3].setDisabled(false);
default:
break;
}
await int.deferUpdate();
await int.editReply({
embeds: [
embeds[page].setFooter({ text: `${footerText?.length > 0 ? `${footerText} ` + '|' : ''} Page ${page + 1} of ${embeds.length}`})
],
components: [
row
]
});
collector.resetTimer();
});
collector.on('end', async (collected, reason) => {
if(reason === 'time' && interaction.ephemeral === true) {
if(!currentPage) {
return;
}
const row = new ActionRowBuilder<ButtonBuilder>().setComponents(
ButtonBuilder.from(buttons[0])
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
ButtonBuilder.from(buttons[1])
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
ButtonBuilder.from(buttons[2])
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
ButtonBuilder.from(buttons[3])
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
)
await interaction.editReply({
embeds: [embeds[page].setFooter({ text: `${footerText?.length > 0 ? `${footerText} ` + '|' : ''} Page ${page + 1} of ${embeds.length}`})],
components: [row],
});
} else if(reason === 'time' && interaction.ephemeral === false) {
if(!currentPage) {
return;
}
const row = new ActionRowBuilder<ButtonBuilder>().setComponents(
ButtonBuilder.from(buttons[0])
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
ButtonBuilder.from(buttons[1])
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
ButtonBuilder.from(buttons[2])
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
ButtonBuilder.from(buttons[3])
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
);
await interaction.editReply({
embeds: [embeds[page].setFooter({ text: `${footerText?.length > 0 ? `${footerText} ` + '|' : ''} Page ${page + 1} of ${embeds.length}`})],
components: [row],
});
}
});
return currentPage;
}
export default pagination;
import pagination from './pagination';
import { ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';
import colors from '../util/colors';
import emojis from '../util/emojis';
const splitContent = async (interaction: ChatInputCommandInteraction, content: string[], displayAmount: number, title?: string, paginationTime: number = 15000, paginationEphemeral: boolean = false, footerText?: string) => {
let embed: Object = {};
let embeds: Array<any> = [];
let i, j, temp, chunk = displayAmount;
for(i = 0, j = content.length; i < j; i += chunk) {
temp = content.slice(i, i + chunk);
embed[`${i / displayAmount}`] = new EmbedBuilder()
.setTitle(title || null)
.setColor(colors.discord)
.setDescription(`${temp.join('\n')}`);
}
for(let i = 0; i < (Object.keys(embed).length); i++) {
embeds.push(embed[i]);
}
const first = new ButtonBuilder()
.setCustomId('first')
.setEmoji(emojis.arrows.skipLeft)
.setStyle(ButtonStyle.Secondary)
const previous = new ButtonBuilder()
.setCustomId('previous')
.setEmoji(emojis.arrows.left)
.setStyle(ButtonStyle.Secondary)
const next = new ButtonBuilder()
.setCustomId('next')
.setEmoji(emojis.arrows.right)
.setStyle(ButtonStyle.Secondary)
const last = new ButtonBuilder()
.setCustomId('last')
.setEmoji(emojis.arrows.skipRight)
.setStyle(ButtonStyle.Secondary)
let buttons: Array<any> = [];
buttons.push(
first,
previous,
next,
last
);
pagination(interaction, embeds, buttons, paginationTime, paginationEphemeral, footerText);
}
export default splitContent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment