Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
473 views
in Technique[技术] by (71.8m points)

javascript - How do you make embed pages in discord.js


 message.channel.send(bot.guilds.cache.map(g=> "*Name:* **"+g.name +'** *ID:* **'+g.id+"** *Owner:* **"+g.owner.user.tag+"**"))

I have this code to send all guilds, the name id and owner name, however how can I make this so that the fisrt 10 are displayed on an embed page, then a reaction arrow takes you to the next page showing other guilds and then the back reaction takes you back a page

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Discord.js v13

You could do this using Discord's relatively new buttons:

import {MessageActionRow, MessageButton, MessageEmbed} from 'discord.js'

// Constants

const backId = 'back'
const forwardId = 'forward'
const backButton = new MessageButton({
  style: 'SECONDARY',
  label: 'Back',
  emoji: '??',
  customId: backId
})
const forwardButton = new MessageButton({
  style: 'SECONDARY',
  label: 'Forward',
  emoji: '??',
  customId: forwardId
})

// Put the following code wherever you want to send the embed pages:

const {author, channel} = message
const guilds = [...client.guilds.cache.values()]

/**
 * Creates an embed with guilds starting from an index.
 * @param {number} start The index to start from.
 * @returns {Promise<MessageEmbed>}
 */
const generateEmbed = async start => {
  const current = guilds.slice(start, start + 10)

  // You can of course customise this embed however you want
  return new MessageEmbed({
    title: `Showing guilds ${start + 1}-${start + current.length} out of ${
      guilds.length
    }`,
    fields: await Promise.all(
      current.map(async guild => ({
        name: guild.name,
        value: `**ID:** ${guild.id}
**Owner:** ${(await guild.fetchOwner()).user.tag}`
      }))
    )
  })
}

// Send the embed with the first 10 guilds
const canFitOnOnePage = guilds.length <= 10
const embedMessage = await channel.send({
  embeds: [await generateEmbed(0)],
  components: canFitOnOnePage
    ? []
    : [new MessageActionRow({components: [forwardButton]})]
})
// Exit if there is only one page of guilds (no need for all of this)
if (canFitOnOnePage) return

// Collect button interactions (when a user clicks a button),
// but only when the button as clicked by the original message author
const collector = embedMessage.createMessageComponentCollector({
  filter: ({user}) => user.id === author.id
})

let currentIndex = 0
collector.on('collect', async interaction => {
  // Increase/decrease index
  interaction.customId === backId ? (currentIndex -= 10) : (currentIndex += 10)
  // Respond to interaction by updating message with new embed
  await interaction.update({
    embeds: [await generateEmbed(currentIndex)],
    components: [
      new MessageActionRow({
        components: [
          // back button if it isn't the start
          ...(currentIndex ? [backButton] : []),
          // forward button if it isn't the end
          ...(currentIndex + 10 < guilds.length ? [forwardButton] : [])
        ]
      })
    ]
  })
})

Here's a preview (with rubbish fields to show the pagination):

Preview of embed pages with buttons

Discord.js v12

This is the original version I posted using reactions. This code only works for Discord.js v12.

const guilds = bot.guilds.cache.array()

/**
 * Creates an embed with guilds starting from an index.
 * @param {number} start The index to start from.
 */
const generateEmbed = start => {
  const current = guilds.slice(start, start + 10)

  // you can of course customise this embed however you want
  return new MessageEmbed({
    title: `Showing guilds ${start + 1}-${start + current.length} out of ${guilds.length}`,
    fields: current.map(guild => ({
      name: guild.name,
      value: `**ID:** ${guild.id}
**Owner:** ${guild.owner.user.tag}`
    }))
  })
}

const {author, channel} = message.author

// send the embed with the first 10 guilds
channel.send(generateEmbed(0)).then(message => {

  // exit if there is only one page of guilds (no need for all of this)
  if (guilds.length <= 10) return
  // react with the right arrow (so that the user can click it) (left arrow isn't needed because it is the start)
  message.react('??')
  const collector = message.createReactionCollector(
    // only collect left and right arrow reactions from the message author
    (reaction, user) => ['??', '??'].includes(reaction.emoji.name) && user.id === author.id,
    // time out after a minute
    {time: 60000}
  )

  let currentIndex = 0
  collector.on('collect', async reaction => {
    // remove the existing reactions
    await message.reactions.removeAll()
    // increase/decrease index
    reaction.emoji.name === '??' ? currentIndex -= 10 : currentIndex += 10
    // edit message with new embed
    await message.edit(generateEmbed(currentIndex))
    // react with left arrow if it isn't the start
    if (currentIndex !== 0) await message.react('??')
    // react with right arrow if it isn't the end
    if (currentIndex + 10 < guilds.length) await message.react('??')
  })
})

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...