diff --git a/src/commands/help.ts b/src/commands/help.ts index e5776bf..4fafd38 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,5 +1,5 @@ import { devMessage, embedColor } from "config/options.js" -import { InteractionContextType, SlashCommandBuilder } from "discord.js" +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ComponentType, InteractionContextType, SlashCommandBuilder } from "discord.js" import { ICommand } from "interfaces" export default { @@ -14,7 +14,7 @@ export default { .setContexts(InteractionContextType.Guild), async execute({ interaction, client }) { - await interaction.deferReply({ ephemeral: true }) + await interaction.deferReply() type CommandList = { name: string @@ -55,20 +55,145 @@ export default { } } + let page = 1 + const perPage = 25 + const maxPage = Math.ceil(commandList.length / perPage) + function getPage(page: number): CommandList[] { + const sliceStart = (page - 1) * perPage + const sliceEnd = page * perPage + return commandList.slice(sliceStart, sliceEnd) + } + function getFooter(page: number) { + const footer = { + icon_url: interaction.guild!.iconURL() || undefined, + text: interaction.guild!.name + " | " + devMessage + } + + if (maxPage === 1) { + return footer + } + + return { + icon_url: footer.icon_url, + text: `Page ${page} of ${maxPage} | ${footer.text}` + } + } + + const id = Math.random().toString(32).slice(2) + const previousId = `tempbutton-previous-${id}` + const nextId = `tempbutton-next-${id}` + + const prevButton = new ButtonBuilder() + .setCustomId(previousId) + .setLabel("Previous") + .setStyle(ButtonStyle.Primary) + const nextButton = new ButtonBuilder() + .setCustomId(nextId) + .setLabel("Next") + .setStyle(ButtonStyle.Primary) + + function buttonsArray(page: number) { + if (page === 1) { + return [] + } else { + return [ + new ActionRowBuilder().addComponents( + prevButton.setDisabled(true), + nextButton.setDisabled(false) + ) + ] + } + } + await interaction.editReply({ embeds: [{ title: "Commands", description: "List of commands", - fields: commandList, + fields: getPage(page), color: embedColor, thumbnail: { url: interaction.guild!.iconURL() || "" }, - footer: { - icon_url: interaction.guild!.iconURL() || undefined, - text: interaction.guild!.name + " | " + devMessage + footer: getFooter(page) + }], + components: buttonsArray(maxPage) + }).then(async (m) => { + if (maxPage === 1) return + + const collector = m.createMessageComponentCollector({ + componentType: ComponentType.Button, + filter: (i) => + (i.customId === previousId || i.customId === nextId) && + i.user.id === interaction.user.id, + time: 60 * 1000 + }) + + collector.on("end", async () => { + m.edit({ + components: [] + }) + }) + + collector.on("collect", async i => { + if (i.customId === previousId) { + if (page === 1) { + await i.reply({ + content: "You are already at the first page", + ephemeral: true + }) + return + } + page-- + + const isPageFirst = page === 1 + const embedContent = m.embeds[0].toJSON() + embedContent.fields = getPage(page) + embedContent.footer = getFooter(page) + await m.edit({ + embeds: [embedContent], + components: [ + new ActionRowBuilder().addComponents( + prevButton.setDisabled(isPageFirst), + nextButton.setDisabled(false) + ) + ] + }) + + await i.reply({ + content: "Page " + page, + ephemeral: true + }) } - }] + if (i.customId === nextId) { + if (page === maxPage) { + await i.reply({ + content: "You are already at the last page", + ephemeral: true + }) + return + } + page++ + + const isPageLast = page === maxPage + const embedContent = m.embeds[0].toJSON() + embedContent.fields = getPage(page) + embedContent.footer = getFooter(page) + await m.edit({ + embeds: [embedContent], + components: [ + new ActionRowBuilder().addComponents( + prevButton.setDisabled(false), + nextButton.setDisabled(isPageLast) + ) + ] + }) + + await i.reply({ + content: "Page " + page, + ephemeral: true + }) + } + }) }) } } as ICommand diff --git a/src/commands/staff/help.ts b/src/commands/staff/help.ts index 1462632..50772f5 100644 --- a/src/commands/staff/help.ts +++ b/src/commands/staff/help.ts @@ -1,9 +1,9 @@ import { devMessage, embedColor } from "config/options.js" -import { ChatInputCommandInteraction } from "discord.js" +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, ComponentType } from "discord.js" import { ExtendedClient as Client } from "utils/Client.js" export default async function help(interaction: ChatInputCommandInteraction, client: Client): Promise { - await interaction.deferReply({ ephemeral: true }) + await interaction.deferReply() type CommandList = { name: string @@ -42,19 +42,144 @@ export default async function help(interaction: ChatInputCommandInteraction, cli } } + let page = 1 + const perPage = 25 + const maxPage = Math.ceil(commandList.length / perPage) + function getPage(page: number): CommandList[] { + const sliceStart = (page - 1) * perPage + const sliceEnd = page * perPage + return commandList.slice(sliceStart, sliceEnd) + } + function getFooter(page: number) { + const footer = { + icon_url: interaction.guild!.iconURL() || undefined, + text: interaction.guild!.name + " | " + devMessage + } + + if (maxPage === 1) { + return footer + } + + return { + icon_url: footer.icon_url, + text: `Page ${page} of ${maxPage} | ${footer.text}` + } + } + + const id = Math.random().toString(32).slice(2) + const previousId = `tempbutton-previous-${id}` + const nextId = `tempbutton-next-${id}` + + const prevButton = new ButtonBuilder() + .setCustomId(previousId) + .setLabel("Previous") + .setStyle(ButtonStyle.Primary) + const nextButton = new ButtonBuilder() + .setCustomId(nextId) + .setLabel("Next") + .setStyle(ButtonStyle.Primary) + + function buttonsArray(page: number) { + if (page === 1) { + return [] + } else { + return [ + new ActionRowBuilder().addComponents( + prevButton.setDisabled(true), + nextButton.setDisabled(false) + ) + ] + } + } + await interaction.editReply({ embeds: [{ title: "Commands", description: "List of commands", - fields: commandList, + fields: getPage(page), color: embedColor, thumbnail: { url: interaction.guild!.iconURL() || "" }, - footer: { - icon_url: interaction.guild!.iconURL() || undefined, - text: interaction.guild?.name + " | " + devMessage + footer: getFooter(page) + }], + components: buttonsArray(maxPage) + }).then(async (m) => { + if (maxPage === 1) return + + const collector = m.createMessageComponentCollector({ + componentType: ComponentType.Button, + filter: (i) => + (i.customId === previousId || i.customId === nextId) && + i.user.id === interaction.user.id, + time: 60 * 1000 + }) + + collector.on("end", async () => { + m.edit({ + components: [] + }) + }) + + collector.on("collect", async i => { + if (i.customId === previousId) { + if (page === 1) { + await i.reply({ + content: "You are already at the first page", + ephemeral: true + }) + return + } + page-- + + const isPageFirst = page === 1 + const embedContent = m.embeds[0].toJSON() + embedContent.fields = getPage(page) + embedContent.footer = getFooter(page) + await m.edit({ + embeds: [embedContent], + components: [ + new ActionRowBuilder().addComponents( + prevButton.setDisabled(isPageFirst), + nextButton.setDisabled(false) + ) + ] + }) + + await i.reply({ + content: "Page " + page, + ephemeral: true + }) } - }] + if (i.customId === nextId) { + if (page === maxPage) { + await i.reply({ + content: "You are already at the last page", + ephemeral: true + }) + return + } + page++ + + const isPageLast = page === maxPage + const embedContent = m.embeds[0].toJSON() + embedContent.fields = getPage(page) + embedContent.footer = getFooter(page) + await m.edit({ + embeds: [embedContent], + components: [ + new ActionRowBuilder().addComponents( + prevButton.setDisabled(false), + nextButton.setDisabled(isPageLast) + ) + ] + }) + + await i.reply({ + content: "Page " + page, + ephemeral: true + }) + } + }) }) }