From b7fa5ff53eaee162110ccf4d2e9d5abeec2060fb Mon Sep 17 00:00:00 2001 From: psibean Date: Tue, 13 Sep 2022 21:17:32 +0930 Subject: [PATCH 1/3] WIP: update to discordjs v14 --- .gitignore | 3 +- README.md | 20 +++---- example/config.js | 6 +- example/package.json | 9 +-- example/src/commands/ActionRowPagination.js | 57 +++++++++++-------- example/src/commands/AdvancedPagination.js | 52 ++++++++++------- .../src/commands/CustomButtonPagination.js | 7 ++- .../src/commands/DynamicButtonPagination.js | 12 ++-- example/src/index.js | 31 +++++----- example/src/util/Constants.js | 25 ++++---- example/src/util/PokeAPI.js | 10 +++- example/src/util/interaction-checks.js | 8 +++ package.json | 4 +- src/structures/ActionRowPaginator.js | 17 +++--- src/structures/BasePaginator.js | 2 +- src/structures/ButtonPaginator.js | 9 +-- src/structures/ReactionPaginator.js | 6 +- src/structures/SelectPaginator.js | 6 +- src/util/ActionRowPaginatorOptions.js | 11 ++-- src/util/BaseOptions.js | 2 +- src/util/ButtonPaginatorOptions.js | 2 +- src/util/ReactionPaginatorOptions.js | 6 +- src/util/SelectPaginatorOptions.js | 5 +- 23 files changed, 180 insertions(+), 130 deletions(-) create mode 100644 example/src/util/interaction-checks.js diff --git a/.gitignore b/.gitignore index 90d0ef3..b6c2f1a 100644 --- a/.gitignore +++ b/.gitignore @@ -64,4 +64,5 @@ typings/ .vscode/ # Autogenerated -src/index.mjs \ No newline at end of file +src/index.mjs +package-lock.json diff --git a/README.md b/README.md index ecab256..43037c7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # discord.js-pagination -A simple utility (or advanced - it's your choice) to paginate discord embeds. Built on discord.js@^13.0.0. +A simple utility (or advanced - it's your choice) to paginate discord embeds. Built on discord.js@^14.0.0 and discord-api-types@^0.37.9. To see how the example paginations look, checkout the [example bot](example/README.md) (the readme has gifs)! @@ -48,7 +48,7 @@ For the below examples, the pages can be constructed as per the [example bot](ex ```js const pages = []; for (let i = 0; i 10; i++) { - const pageEmbed = new MessageEmbed(); + const pageEmbed = new EmbedBuilder(); pageEmbed .setTitle(`This embed is index ${i}!`) .setDescription(`That means it is page #${i + 1}`); @@ -65,7 +65,7 @@ You will of course want to construct your own pages. This allows pages to be navigated by reacting to a message. ```js -const { PaginatorEvents, ReactionPaginator } = require('@psibean/discord.js-pagination'); +import { PaginatorEvents, ReactionPaginator } from '@psibean/discord.js-pagination'; const reactionPaginator = new ReactionPaginator(interaction, { pages }) .on(PaginatorEvents.COLLECT_ERROR, ({ error }) => console.log(error)); @@ -77,7 +77,7 @@ await reactionPaginator.send(); This allows pages to be navigated by clicking buttons. ```js -const { ButtonPaginator } = require('@psibean/discord.js-pagination'); +import { ButtonPaginator } from '@psibean/discord.js-pagination'; const buttonPaginator = new ButtonPaginator(interaction, { pages }); await buttonPaginator.send(); @@ -90,7 +90,7 @@ This allows pages to be navigated using a select menu. For the select pagination embed you'll need to supply an array of [MessageSelectOptions](https://discord.js.org/#/docs/main/stable/typedef/MessageSelectOption) to the pagination options via `selectOptions`. By default the pagination will map the value of the provided options to your pages index based on their ordering. Then the page change will be determined by the selected value and this mapping. If you want to map your select options and pages differently you can provide the `pagesMap` ({ selectOptions, paginator }) function which should return a dictionary. You'll then want to provide a custom `pageIndexResolver`. ```js -const { SelectPaginator } = require('@psibean/discord.js-pagination'); +import { SelectPaginator } from '@psibean/discord.js-pagination'; // The default pagesMap will map these option values to the index const selectOptions = []; @@ -245,7 +245,7 @@ For the ActionRowPaginator, ButtonPaginator and SelectPaginator, defaults to: { idle: 6e4, filter: ({ interaction, paginator }) => - interaction.isMessageComponent() && + interaction.type === InteractionType.MessageComponent; && interaction.component.customId.startsWith(paginator.customIdPrefix) && interaction.user === paginator.user && !interaction.user.bot, @@ -328,7 +328,7 @@ Defaults to: This is the function used to set the footer of each page. If not provided the embeds will use whatever footers were originally set on them. -(paginator): Promise<string> | string +(paginator): Promise<EmbedFooterOptions> | EmbedFooterOptions - **paginator** : This is a reference to the paginator instance. Defaults to undefined. Optional. @@ -353,14 +353,14 @@ These options are common to the `ActionRowPaginator`, `ButtonPaginator`, and `Se ### messageActionRows -An array of messageActionRows (they will have their type set to ACTION_ROW). +An array of messageActionRows (they will have their type set to ComponentType.ActionRow). Any components provided up front will have their customId generated. Defaults to: ``` [ { - type: 'ACTION_ROW', + type: ComponentType.ActionRow, components: [], }, ], @@ -427,7 +427,7 @@ If a function: Events can be imported by: ``` -const { PaginatorEvents } = require('@psibean/discord.js-pagination'); +import { PaginatorEvents } from '@psibean/discord.js-pagination'; ``` And accessed by `PaginatorEvents#EventName` diff --git a/example/config.js b/example/config.js index 8a81891..c54ec80 100644 --- a/example/config.js +++ b/example/config.js @@ -1,7 +1,7 @@ 'use strict'; module.exports = { - BOT_TOKEN: 'YOUR BOT_TOKEN HERE', - CLIENT_ID: 'YOUR CLIENT ID HERE', - GUILD_ID: 'YOUR GUILD ID HERE', + BOT_TOKEN: 'BOT_TOKEN_HERE', + CLIENT_ID: 'CLIENT_ID_HERE', + GUILD_ID: 'GUILD_ID_HERE', }; diff --git a/example/package.json b/example/package.json index 5a3c98f..790c144 100644 --- a/example/package.json +++ b/example/package.json @@ -1,13 +1,14 @@ { "main": "src/index.js", + "type": "commonjs", "scripts": { "start": "node ." }, "dependencies": { - "@discordjs/builders": "^0.4.0", + "@discordjs/builders": "^1.0.0", "@discordjs/rest": "*", - "discord-api-types": "^0.22.0", - "discord.js": "13.2.0", - "node-fetch": "^2.6.1" + "discord-api-types": "^0.37.9", + "discord.js": "^14.3.0", + "node-fetch": "^2.6.7" } } diff --git a/example/src/commands/ActionRowPagination.js b/example/src/commands/ActionRowPagination.js index 73ac89a..cc2ed5f 100644 --- a/example/src/commands/ActionRowPagination.js +++ b/example/src/commands/ActionRowPagination.js @@ -1,10 +1,10 @@ 'use strict'; -const { SlashCommandBuilder } = require('@discordjs/builders'); -const { Collection, MessageEmbed } = require('discord.js'); -const { PaginatorEvents, ActionRowPaginator } = require('../../../src'); -const { basicEndHandler, basicErrorHandler } = require('../util/Constants'); -const { constructPokemonOptions, PokeAPI } = require('../util/PokeAPI'); +const{ SlashCommandBuilder } = require('@discordjs/builders'); +const{ Collection, EmbedBuilder, ComponentType, ButtonStyle } = require('discord.js'); +const{ PaginatorEvents, ActionRowPaginator } = require('../../../src'); +const{ basicEndHandler, basicErrorHandler } = require('../util/Constants'); +const{ constructPokemonOptions, PokeAPI } = require('../util/PokeAPI'); module.exports = { data: new SlashCommandBuilder() @@ -18,33 +18,33 @@ module.exports = { { components: [ { - type: 'BUTTON', + type: ComponentType.Button, emoji: '⏪', label: 'start', - style: 'SECONDARY', + style: ButtonStyle.Secondary, }, { - type: 'BUTTON', + type: ComponentType.Button, label: `-${SELECT_LIMIT}`, - style: 'PRIMARY', + style: ButtonStyle.Primary, }, { - type: 'BUTTON', + type: ComponentType.Button, label: `+${SELECT_LIMIT}`, - style: 'PRIMARY', + style: ButtonStyle.Primary, }, { - type: 'BUTTON', + type: ComponentType.Button, emoji: '⏩', label: 'end', - style: 'SECONDARY', + style: ButtonStyle.Secondary, }, ], }, { components: [ { - type: 'SELECT_MENU', + type: ComponentType.SelectMenu, placeholder: 'Currently viewing #001 - #025', }, ], @@ -61,7 +61,7 @@ module.exports = { // eslint-disable-next-line no-shadow const identifiersResolver = async ({ interaction, paginator }) => { - if (interaction.componentType === 'BUTTON') { + if (interaction.componentType === ComponentType.Button) { let { selectOptionsIdentifier } = paginator.currentIdentifiers; switch (interaction.component.label) { case 'start': @@ -94,7 +94,7 @@ module.exports = { ...paginator.currentIdentifiers, selectOptionsIdentifier, }; - } else if (interaction.componentType === 'SELECT_MENU') { + } else if (interaction.componentType === ComponentType.SelectMenu) { return { ...paginator.currentIdentifiers, pageIdentifier: interaction.values[0], @@ -109,19 +109,28 @@ module.exports = { if (newPageIdentifier !== currentPageIdentifier) { // Pokemon name const pokemonResult = await PokeAPI.getPokemon(newPageIdentifier); - const newEmbed = new MessageEmbed() + const newEmbed = new EmbedBuilder() .setTitle(`Pokedex #${`${pokemonResult.id}`.padStart(3, '0')} - ${newPageIdentifier}`) .setDescription(`Viewing ${newPageIdentifier}`) .setThumbnail(pokemonResult.sprites.front_default) - .addField('Types', pokemonResult.types.map(typeObject => typeObject.type.name).join(', '), true) - .addField( - 'Abilities', - pokemonResult.abilities.map(abilityObject => abilityObject.ability.name).join(', '), - false, - ); + .addFields([ + { + name: 'Types', + value: pokemonResult.types.map(typeObject => typeObject.type.name).join(', '), + inline: true, + }, + { + name: 'Abilities', + value: pokemonResult.abilities.map(abilityObject => abilityObject.ability.name).join(', '), + inline: false, + }, + ]); + const pokemonEmbedFields = []; pokemonResult.stats.forEach(statObject => { - newEmbed.addField(statObject.stat.name, `${statObject.base_stat}`, true); + + newEmbed.push({ name: statObject.stat.name, value: `${statObject.base_stat}`, inline: true}); }); + newEmbed.addFields(pokemonEmbedFields); return newEmbed; } return paginator.currentPage; diff --git a/example/src/commands/AdvancedPagination.js b/example/src/commands/AdvancedPagination.js index 5fc0a27..6622117 100644 --- a/example/src/commands/AdvancedPagination.js +++ b/example/src/commands/AdvancedPagination.js @@ -1,7 +1,7 @@ 'use strict'; const { SlashCommandBuilder } = require('@discordjs/builders'); -const { Collection, MessageEmbed } = require('discord.js'); +const { Collection, EmbedBuilder, ComponentType, ButtonStyle, SelectMenuOptionBuilder } = require('discord.js'); const { PaginatorEvents, ActionRowPaginator } = require('../../../src'); const { basicEndHandler, basicErrorHandler } = require('../util/Constants'); const { constructPokemonOptions, PokeAPI } = require('../util/PokeAPI'); @@ -40,7 +40,7 @@ module.exports = { { components: [ { - type: 'SELECT_MENU', + type: ComponentType.SelectMenu, placeholder: 'Select a type to filter the Pokemon', options: pokemonTypeSelectOptions, customId: 'pokemon-type', @@ -52,7 +52,7 @@ module.exports = { { components: [ { - type: 'SELECT_MENU', + type: ComponentType.SelectMenu, placeholder: `Currently viewing #001 - #025 of ${totalPokemonOfType}`, options: pokemonSelectOptions.get(INITIAL_SELECT_IDENTIFIER), customId: 'pokemon-select', @@ -64,26 +64,26 @@ module.exports = { { components: [ { - type: 'BUTTON', + type: ComponentType.Button, emoji: '⏪', label: 'start', - style: 'SECONDARY', + style: ButtonStyle.Secondary, }, { - type: 'BUTTON', + type: ComponentType.Button, label: `-${SELECT_LIMIT}`, - style: 'PRIMARY', + style: ButtonStyle.Primary, }, { - type: 'BUTTON', + type: ComponentType.Button, label: `+${SELECT_LIMIT}`, - style: 'PRIMARY', + style: ButtonStyle.Primary, }, { - type: 'BUTTON', + type: ComponentType.Button, emoji: '⏩', label: 'end', - style: 'SECONDARY', + style: ButtonStyle.Secondary, }, ], }, @@ -171,9 +171,9 @@ module.exports = { // eslint-disable-next-line no-shadow const identifiersResolver = async ({ interaction, paginator }) => { let newIdentifiers = {}; - if (interaction.componentType === 'BUTTON') { + if (interaction.componentType === ComponentType.Button) { newIdentifiers = await handleButtonIdentifier(interaction.component.label, paginator); - } else if (interaction.componentType === 'SELECT_MENU') { + } else if (interaction.componentType === ComponentType.SelectMenu) { if (interaction.component.customId.includes('pokemon-type')) { const { pokemonTypeIdentifier: currentPokemonType } = paginator.currentIdentifiers; const newPokemonType = interaction.values[0]; @@ -196,20 +196,28 @@ module.exports = { try { // Pokemon name const pokemonResult = await PokeAPI.getPokemon(newPageIdentifier); - const newEmbed = new MessageEmbed() + const newEmbed = new EmbedBuilder() .setTitle(`Pokedex #${`${pokemonResult.id}`.padStart(3, '0')} - ${newPageIdentifier}`) .setDescription(`Viewing ${newPageIdentifier}`) .setThumbnail(pokemonResult.sprites.front_default) - .setFooter('Information fetched from https://pokeapi.co/') - .addField('Types', pokemonResult.types.map(typeObject => typeObject.type.name).join(', '), true) - .addField( - 'Abilities', - pokemonResult.abilities.map(abilityObject => abilityObject.ability.name).join(', '), - false, - ); + .setFooter({ text: 'Information fetched from https://pokeapi.co/' }) + .addFields([ + { + name: 'Types', + value: pokemonResult.types.map(typeObject => typeObject.type.name).join(', '), + inline: true, + }, + { + name: 'Abilities', + value: pokemonResult.abilities.map(abilityObject => abilityObject.ability.name).join(', '), + inline: false, + }, + ]); + const pokemonEmbedFields = []; pokemonResult.stats.forEach(statObject => { - newEmbed.addField(statObject.stat.name, `${statObject.base_stat}`, true); + pokemonEmbedFields.push({ name: statObject.stat.name, value: `${statObject.base_stat}`, inline: true}); }); + newEmbed.addFields(pokemonEmbedFields); return newEmbed; } catch (error) { console.log(`Error in pageEmbedResolver\n${error}`); diff --git a/example/src/commands/CustomButtonPagination.js b/example/src/commands/CustomButtonPagination.js index a2de2d1..829e6e7 100644 --- a/example/src/commands/CustomButtonPagination.js +++ b/example/src/commands/CustomButtonPagination.js @@ -1,6 +1,7 @@ 'use strict'; const { SlashCommandBuilder } = require('@discordjs/builders'); +const { ButtonStyle } = require('discord.js'); const { PaginatorEvents, ButtonPaginator } = require('../../../src'); const { basicEndHandler, basicErrorHandler, pages } = require('../util/Constants'); @@ -13,7 +14,7 @@ module.exports = { { label: 'First', emoji: '⏪', - style: 'SECONDARY', + style: ButtonStyle.Secondary, disabled: true, }, { @@ -22,7 +23,7 @@ module.exports = { }, { label: 'Delete', - style: 'DANGER', + style: ButtonStyle.Danger, disabled: true, }, { @@ -32,7 +33,7 @@ module.exports = { { label: 'Last', emoji: '⏩', - style: 'SECONDARY', + style: ButtonStyle.Secondary, disabled: true, }, ]; diff --git a/example/src/commands/DynamicButtonPagination.js b/example/src/commands/DynamicButtonPagination.js index 999ef71..c1a00d2 100644 --- a/example/src/commands/DynamicButtonPagination.js +++ b/example/src/commands/DynamicButtonPagination.js @@ -1,7 +1,7 @@ 'use strict'; const { SlashCommandBuilder } = require('@discordjs/builders'); -const { MessageEmbed } = require('discord.js'); +const { EmbedBuilder, ButtonStyle } = require('discord.js'); const { PaginatorEvents, ButtonPaginator } = require('../../../src'); const { basicEndHandler, basicErrorHandler } = require('../util/Constants'); @@ -14,7 +14,7 @@ module.exports = { { label: 'First', emoji: '⏪', - style: 'SECONDARY', + style: ButtonStyle.Secondary, disabled: true, }, { @@ -23,7 +23,7 @@ module.exports = { }, { label: 'Delete', - style: 'DANGER', + style: ButtonStyle.Danger, disabled: true, }, { @@ -33,7 +33,7 @@ module.exports = { { label: 'Last', emoji: '⏩', - style: 'SECONDARY', + style: ButtonStyle.Secondary, disabled: true, }, ]; @@ -67,11 +67,11 @@ module.exports = { }; const pageEmbedResolver = ({ newIdentifiers, paginator }) => { - const newPageEmbed = new MessageEmbed(); + const newPageEmbed = new EmbedBuilder(); newPageEmbed .setTitle(`This embed is index ${newIdentifiers.pageIdentifier}!`) .setDescription(`That means it is page #${newIdentifiers.pageIdentifier + 1}`); - newPageEmbed.setFooter(`Page ${newIdentifiers.pageIdentifier + 1} / ${paginator.maxNumberOfPages}`); + newPageEmbed.setFooter({ text: `Page ${newIdentifiers.pageIdentifier + 1} / ${paginator.maxNumberOfPages}` }); return newPageEmbed; }; diff --git a/example/src/index.js b/example/src/index.js index 58fd1b7..3a14a9e 100644 --- a/example/src/index.js +++ b/example/src/index.js @@ -2,8 +2,10 @@ const fs = require('fs'); const path = require('path'); -const { Client, Intents, Collection } = require('discord.js'); -const config = require('../config'); +const{ Client, GatewayIntentBits, Collection } = require('discord.js'); +const { isInteractionCommand } = require('./util/interaction-checks.js') +const config = require('../config.js'); + process.on('uncaughtException', err => { console.log('UNCAUGHT EXCEPTION:\n'); @@ -11,7 +13,7 @@ process.on('uncaughtException', err => { }); const client = new Client({ - intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MESSAGE_REACTIONS], + intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions], }); client.commands = new Collection(); @@ -19,17 +21,16 @@ const commandsPath = path.join(__dirname, 'commands'); const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); const commands = []; -for (const file of commandFiles) { - const command = require(path.join(commandsPath, file)); - // Set a new item in the Collection - // with the key as the command name and the value as the exported module - client.commands.set(command.data.name, command); - commands.push(command.data.toJSON()); -} - client.once('ready', () => { console.log('Ready!'); try { + for (const file of commandFiles) { + const command = require(path.join(commandsPath, file)); + // Set a new item in the Collection + // with the key as the command name and the value as the exported module + client.commands.set(command.data.name, command); + commands.push(command.data.toJSON()); + } console.log('Started refreshing application (/) commands.'); for (const guild of client.guilds.cache.values()) { guild.commands @@ -62,7 +63,7 @@ client.once('ready', () => { }); client.on('interactionCreate', async interaction => { - if (!interaction.isCommand()) return; + if (!isInteractionCommand(interaction)) return; const { commandName } = interaction; @@ -73,7 +74,11 @@ client.on('interactionCreate', async interaction => { await client.commands.get(commandName).execute(interaction); } catch (error) { console.error(error); - await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); + const errorMessage = { content: 'There was an error while executing this command!', ephemeral: true } + if (interaction.isRepliable) + await interaction.reply(errorMessage); + else + await interaction.followUp(errorMessage); } }); diff --git a/example/src/util/Constants.js b/example/src/util/Constants.js index 1432834..839a9e2 100644 --- a/example/src/util/Constants.js +++ b/example/src/util/Constants.js @@ -1,19 +1,18 @@ 'use strict'; -const { MessageEmbed } = require('discord.js'); +const { EmbedBuilder } = require('discord.js'); -const myPages = []; +const pages = []; for (let i = 0; i < 10; i++) { - const pageEmbed = new MessageEmbed(); - pageEmbed.setTitle(`This embed is index ${i}!`).setDescription(`That means it is page #${i + 1}`); - pageEmbed.setFooter(`Page ${i + 1} / 10`); - myPages.push(pageEmbed); + const pageEmbed = new EmbedBuilder() + .setTitle(`This embed is index ${i}!`) + .setDescription(`That means it is page #${i + 1}`) + .setFooter({ text: `Page ${i + 1} / 10` }); + pages.push(pageEmbed); } +const basicErrorHandler = ({ error }) => console.log(error); -module.exports.pages = myPages; - -module.exports.basicErrorHandler = ({ error }) => console.log(error); -module.exports.basicEndHandler = async ({ reason, paginator }) => { +const basicEndHandler = async ({ reason, paginator }) => { // This is a basic handler that will delete the message containing the pagination. try { console.log(`The pagination has ended: ${reason}`); @@ -23,3 +22,9 @@ module.exports.basicEndHandler = async ({ reason, paginator }) => { console.log(error); } }; + +module.exports = { + basicEndHandler, + basicErrorHandler, + pages +} diff --git a/example/src/util/PokeAPI.js b/example/src/util/PokeAPI.js index 57de5bf..f7ec65e 100644 --- a/example/src/util/PokeAPI.js +++ b/example/src/util/PokeAPI.js @@ -1,8 +1,10 @@ 'use strict'; +const { SelectMenuOptionBuilder } = require('discord.js'); const fetch = require('node-fetch'); + const pokeApiUrl = 'https://pokeapi.co/api/v2/'; -module.exports.constructPokemonOptions = pokemonApiResponse => { +const constructPokemonOptions = pokemonApiResponse => { const pokemonOptions = []; pokemonApiResponse.forEach(pokemon => { const splitPokemonUrl = pokemon.url.split('/'); @@ -15,7 +17,9 @@ module.exports.constructPokemonOptions = pokemonApiResponse => { return pokemonOptions; }; -module.exports.PokeAPI = { + + +const PokeAPI = { getType: type => fetch(`${pokeApiUrl}type/${type}`).then(res => res.json()), getTypes: () => fetch(`${pokeApiUrl}type/`) @@ -33,3 +37,5 @@ module.exports.PokeAPI = { .then(res => res.json()) .then(jsonData => jsonData.results), }; + +module.exports = { constructPokemonOptions, PokeAPI } \ No newline at end of file diff --git a/example/src/util/interaction-checks.js b/example/src/util/interaction-checks.js new file mode 100644 index 0000000..f8670b1 --- /dev/null +++ b/example/src/util/interaction-checks.js @@ -0,0 +1,8 @@ +const { InteractionType } = require('discord.js'); + +const isInteractionCommand = interaction => + interaction.type === InteractionType.ApplicationCommand; + + module.exports = { + isInteractionCommand + }; \ No newline at end of file diff --git a/package.json b/package.json index 5fb2768..bff4be5 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "type": "git", "url": "git+https://github.com/psibean/discord.js-pagination.git" }, + "keywords": [ "discord.js", "pagination" @@ -37,7 +38,8 @@ }, "homepage": "https://github.com/psibean/discord.js-pagination#readme", "devDependencies": { - "discord.js": "^13.6.0", + "discord.js": "^14.3.0", + "discord-api-types": "^0.37.9", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.23.4", diff --git a/src/structures/ActionRowPaginator.js b/src/structures/ActionRowPaginator.js index 015a1bc..84381fa 100644 --- a/src/structures/ActionRowPaginator.js +++ b/src/structures/ActionRowPaginator.js @@ -1,11 +1,12 @@ 'use strict'; -const { MessageActionRow, Util } = require('discord.js'); +const { ActionRowBuilder, mergeDefault, ButtonStyle } = require('discord.js'); +const { ComponentType } = require('discord-api-types/v10'); const BasePaginator = require('./BasePaginator'); const ActionRowPaginatorOptions = require('../util/ActionRowPaginatorOptions'); class ActionRowPaginator extends BasePaginator { constructor(interaction, options) { - super(interaction, Util.mergeDefault(ActionRowPaginatorOptions.createDefault(), options)); + super(interaction, mergeDefault(ActionRowPaginatorOptions.createDefault(), options)); if (typeof options.messageActionRows !== 'object' || options.messageActionRows.length === 0) { throw new Error('messageActionRows is not defined or is empty'); @@ -16,26 +17,26 @@ class ActionRowPaginator extends BasePaginator { Object.defineProperty(this, 'messageActionRows', { value: [] }); options.messageActionRows.forEach((messageActionRowData, messageRowIndex) => { - messageActionRowData.type = 'ACTION_ROW'; + messageActionRowData.type = ComponentType.ActionRow; if (messageActionRowData.components) { messageActionRowData.components.forEach(component => { const { type, customId } = component; switch (type) { - case 'SELECT_MENU': + case ComponentType.SelectMenu: component.customId = component.customId ? this._generateCustomId(component.customId) : this._generateCustomId(`select-menu-${messageRowIndex}`); break; - case 'BUTTON': + case ComponentType.Button: component.customId = component.customId ? this._generateCustomId(customId) : this._generateCustomId(component.label); - if (!component.style) component.style = 'PRIMARY'; + if (!component.style) component.style = ButtonStyle.Primary; break; } }); } - this.messageActionRows.push(new MessageActionRow(messageActionRowData)); + this.messageActionRows.push(new ActionRowBuilder(messageActionRowData)); }); if (this.useCache) { @@ -104,4 +105,4 @@ class ActionRowPaginator extends BasePaginator { } } -module.exports = ActionRowPaginator; +module.exports = ActionRowPaginator; \ No newline at end of file diff --git a/src/structures/BasePaginator.js b/src/structures/BasePaginator.js index 99de955..e2358a5 100644 --- a/src/structures/BasePaginator.js +++ b/src/structures/BasePaginator.js @@ -257,4 +257,4 @@ class BasePaginator extends EventEmitter { } } -module.exports = BasePaginator; +module.exports = BasePaginator; \ No newline at end of file diff --git a/src/structures/ButtonPaginator.js b/src/structures/ButtonPaginator.js index c4f9e0a..de9f725 100644 --- a/src/structures/ButtonPaginator.js +++ b/src/structures/ButtonPaginator.js @@ -1,17 +1,18 @@ 'use strict'; -const { Util } = require('discord.js'); +const { mergeDefault } = require('discord.js'); +const { ComponentType } = require('discord-api-types/v10'); const ActionRowPaginator = require('./ActionRowPaginator'); const ButtonPaginatorOptions = require('../util/ButtonPaginatorOptions'); class ButtonPaginator extends ActionRowPaginator { constructor(interaction, options) { - super(interaction, Util.mergeDefault(ButtonPaginatorOptions.createDefault(), options)); + super(interaction, mergeDefault(ButtonPaginatorOptions.createDefault(), options)); // Buttons may also be set via the messageActionRows prop. if (this.options.buttons) { const buttonRows = [[]]; for (const button of this.options.buttons) { - button.type = 'BUTTON'; + button.type = ComponentType.Button; const isLink = button.url !== undefined; if (!isLink) { button.customId = button.customId @@ -33,4 +34,4 @@ class ButtonPaginator extends ActionRowPaginator { } } -module.exports = ButtonPaginator; +module.exports = ButtonPaginator; \ No newline at end of file diff --git a/src/structures/ReactionPaginator.js b/src/structures/ReactionPaginator.js index 797fe8c..f99508b 100644 --- a/src/structures/ReactionPaginator.js +++ b/src/structures/ReactionPaginator.js @@ -1,12 +1,12 @@ 'use strict'; -const { Util } = require('discord.js'); +const { mergeDefault } = require('discord.js'); const BasePaginator = require('./BasePaginator'); const ReactionPaginatorOptions = require('../util/ReactionPaginatorOptions'); class ReactionPaginator extends BasePaginator { constructor(interaction, options) { - super(interaction, Util.mergeDefault(ReactionPaginatorOptions.createDefault(), options)); + super(interaction, mergeDefault(ReactionPaginatorOptions.createDefault(), options)); if (typeof options.emojiList === 'undefined' || options.emojiList.length === 0) { throw new Error('emojiList is undefined or empty, must be a list of EmojiResolvables'); @@ -36,4 +36,4 @@ class ReactionPaginator extends BasePaginator { } } -module.exports = ReactionPaginator; +module.exports = ReactionPaginator; \ No newline at end of file diff --git a/src/structures/SelectPaginator.js b/src/structures/SelectPaginator.js index 1bddc37..1b93231 100644 --- a/src/structures/SelectPaginator.js +++ b/src/structures/SelectPaginator.js @@ -1,12 +1,12 @@ 'use strict'; -const { Util } = require('discord.js'); +const { mergeDefault } = require('discord.js'); const ActionRowPaginator = require('./ActionRowPaginator'); const SelectPaginatorOptions = require('../util/SelectPaginatorOptions'); class SelectPaginator extends ActionRowPaginator { constructor(interaction, options) { - super(interaction, Util.mergeDefault(SelectPaginatorOptions.createDefault(), options)); + super(interaction, mergeDefault(SelectPaginatorOptions.createDefault(), options)); if (this.options.selectOptions) { const actionRows = [[]]; this.options.selectOptions.forEach(selectOption => { @@ -28,4 +28,4 @@ class SelectPaginator extends ActionRowPaginator { } } -module.exports = SelectPaginator; +module.exports = SelectPaginator; \ No newline at end of file diff --git a/src/util/ActionRowPaginatorOptions.js b/src/util/ActionRowPaginatorOptions.js index c0bdf6e..7fe7934 100644 --- a/src/util/ActionRowPaginatorOptions.js +++ b/src/util/ActionRowPaginatorOptions.js @@ -1,21 +1,22 @@ 'use strict'; -const { Util } = require('discord.js'); +const { mergeDefault, InteractionType } = require('discord.js'); +const { ComponentType } = require('discord-api-types/v10'); const BaseOptions = require('./BaseOptions'); class ActionRowPaginatorOptions extends BaseOptions { static createDefault() { - return Util.mergeDefault(BaseOptions.createDefault(), { + return mergeDefault(BaseOptions.createDefault(), { customIdPrefix: 'paginator', messageActionRows: [ { - type: 'ACTION_ROW', + type: ComponentType.ActionRow, components: [], }, ], collectorOptions: { filter: ({ interaction, paginator }) => - interaction.isMessageComponent() && + interaction.type === InteractionType.MessageComponent && interaction.component.customId.startsWith(paginator.customIdPrefix) && interaction.user === paginator.user && !interaction.user.bot, @@ -24,4 +25,4 @@ class ActionRowPaginatorOptions extends BaseOptions { } } -module.exports = ActionRowPaginatorOptions; +module.exports = ActionRowPaginatorOptions; \ No newline at end of file diff --git a/src/util/BaseOptions.js b/src/util/BaseOptions.js index 78be8f4..d7724f1 100644 --- a/src/util/BaseOptions.js +++ b/src/util/BaseOptions.js @@ -17,4 +17,4 @@ class BaseOptions extends null { } } -module.exports = BaseOptions; +module.exports = BaseOptions; \ No newline at end of file diff --git a/src/util/ButtonPaginatorOptions.js b/src/util/ButtonPaginatorOptions.js index b66dbaf..90774f5 100644 --- a/src/util/ButtonPaginatorOptions.js +++ b/src/util/ButtonPaginatorOptions.js @@ -31,4 +31,4 @@ class ButtonPaginatorOptions extends ActionRowPaginatorOptions { } } -module.exports = ButtonPaginatorOptions; +module.exports = ButtonPaginatorOptions; \ No newline at end of file diff --git a/src/util/ReactionPaginatorOptions.js b/src/util/ReactionPaginatorOptions.js index fb7e236..2c27162 100644 --- a/src/util/ReactionPaginatorOptions.js +++ b/src/util/ReactionPaginatorOptions.js @@ -1,11 +1,11 @@ 'use strict'; -const { Util } = require('discord.js'); +const { mergeDefault } = require('discord.js'); const BaseOptions = require('./BaseOptions'); class ReactionPaginatorOptions extends BaseOptions { static createDefault() { - return Util.mergeDefault(BaseOptions.createDefault(), { + return mergeDefault(BaseOptions.createDefault(), { emojiList: ['⏪', '⏩'], collectorOptions: { filter: ({ reaction, user, paginator }) => @@ -33,4 +33,4 @@ class ReactionPaginatorOptions extends BaseOptions { } } -module.exports = ReactionPaginatorOptions; +module.exports = ReactionPaginatorOptions; \ No newline at end of file diff --git a/src/util/SelectPaginatorOptions.js b/src/util/SelectPaginatorOptions.js index 991f045..10048a8 100644 --- a/src/util/SelectPaginatorOptions.js +++ b/src/util/SelectPaginatorOptions.js @@ -1,5 +1,6 @@ 'use strict'; +const { ComponentType } = require('discord-api-types/v10'); const ActionRowPaginatorOptions = require('./ActionRowPaginatorOptions'); class SelectPaginatorOptions extends ActionRowPaginatorOptions { @@ -9,7 +10,7 @@ class SelectPaginatorOptions extends ActionRowPaginatorOptions { { components: [ { - type: 'SELECT_MENU', + type: ComponentType.SelectMenu, }, ], }, @@ -22,4 +23,4 @@ class SelectPaginatorOptions extends ActionRowPaginatorOptions { } } -module.exports = SelectPaginatorOptions; +module.exports = ActionRowPaginatorOptions; \ No newline at end of file From c0a5cc16e4ee5a20650305ebad3d935e9aacbd95 Mon Sep 17 00:00:00 2001 From: psibean Date: Fri, 30 Sep 2022 08:32:57 +0930 Subject: [PATCH 2/3] WIP update ButtonPaginator to use builders --- src/structures/ButtonPaginator.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structures/ButtonPaginator.js b/src/structures/ButtonPaginator.js index de9f725..a6b4ad8 100644 --- a/src/structures/ButtonPaginator.js +++ b/src/structures/ButtonPaginator.js @@ -1,6 +1,6 @@ 'use strict'; -const { mergeDefault } = require('discord.js'); +const { mergeDefault, ButtonBuilder } = require('discord.js'); const { ComponentType } = require('discord-api-types/v10'); const ActionRowPaginator = require('./ActionRowPaginator'); const ButtonPaginatorOptions = require('../util/ButtonPaginatorOptions'); @@ -22,9 +22,9 @@ class ButtonPaginator extends ActionRowPaginator { // LINK : PRIMARY - MessageButtonStyles doesn't work. if (!button.style) button.style = isLink ? 5 : 1; if (button.row > 0 && button.row < buttonRows.length) { - buttonRows[button.row].push(button); + buttonRows[button.row].push(ButtonBuilder.from(button)); } else { - buttonRows[0].push(button); + buttonRows[0].push(ButtonBuilder.from(button)); } } buttonRows.forEach((row, index) => { From bdffe993a72091352350ee1f9ba39eeed190e3a7 Mon Sep 17 00:00:00 2001 From: psibean Date: Fri, 30 Sep 2022 08:33:23 +0930 Subject: [PATCH 3/3] Tweak AdvancedPagination example --- example/src/commands/AdvancedPagination.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/src/commands/AdvancedPagination.js b/example/src/commands/AdvancedPagination.js index 6622117..f7364b2 100644 --- a/example/src/commands/AdvancedPagination.js +++ b/example/src/commands/AdvancedPagination.js @@ -159,7 +159,7 @@ module.exports = { isAll ? pokemonList : pokemonList.slice(INITIAL_SELECT_IDENTIFIER, SELECT_LIMIT).map(pokemonEntry => pokemonEntry.pokemon), - ), + ).map(option => option), ); return { selectOptionsIdentifier: INITIAL_SELECT_IDENTIFIER, pokemonTypeIdentifier: pokemonType }; } catch (error) { @@ -245,7 +245,7 @@ module.exports = { newSelectOptionsIdentifier !== currentSelectOptionsIdentifier || newPokemonTypeIdentifier !== currentPokemonTypeIdentifier ) { - paginator.getComponent(1, 0).options = pokemonSelectOptions.get(newSelectOptionsIdentifier); + paginator.getComponent(1, 0).setOptions(pokemonSelectOptions.get(newSelectOptionsIdentifier)); const endOffset = newSelectOptionsIdentifier * SELECT_LIMIT + SELECT_LIMIT; paginator.getComponent(1, 0).placeholder = `Currently viewing #${`${ newSelectOptionsIdentifier * SELECT_LIMIT + 1