如何使嵌入反应菜单从.json文件加载其元素?

时间:2019-06-15 19:15:54

标签: javascript arrays node.js json discord.js

我正在尝试制作一个显示我的公会自定义表情符号列表的菜单(请参阅 图片)。

picture

我有一个.json文件,上面存储了表情符号和表情符号代码,我正在使用它来获得将来存储更多表情符号的功能。

enter image description here

这是我用来嵌入的代码:

execute(message) {
        const Discord = require('discord.js');
        const Emojis = require('./emojis.json');
        const keys = Object.keys(Emojis);
        var i = 0
        const embed = {
            "title": "Server emojis list:",
            "color": 1056085,
            "timestamp": new Date(),
            "footer": {
                "icon_url": "https://cdn.discordapp.com/icons/469276415746113568/f86e89f362f1df6dc1f996818ef49e7a.png?size=1024",
                "text": "Dz Gamers Community"
            },
            "fields": [{
                "name": "Emoji:",
                "value": `${Emojis[keys[i+0]]}\n${Emojis[keys[i+1]]}\n${Emojis[keys[i+2]]}\n${Emojis[keys[i+3]]}\n${Emojis[keys[i+4]]}\n`,
                "inline": true
            }, {
                "name": "Emoji code:",
                "value": `**${keys[i+0]}\n${keys[i+1]}\n${keys[i+2]}\n${keys[i+3]}\n${keys[i+4]}\n**`,
                "inline": true
            }]
        };

我为此使用了反应收集器,但是我不确定如何编辑嵌入字段。

message.channel.send({embed})
    .then(async embedMessage => {
        await embedMessage.react('◀')
        await embedMessage.react('▶')
        const emoji = {
            NEXT_PAGE: '▶',
            PREV_PAGE: '◀',
        }
        const collector = new Discord.ReactionCollector(embedMessage, (reaction, user) => Object.values(emoji).includes(reaction.emoji.name) && !user.bot, {});
        collector.on('collect', (reaction, user) => {
            switch (reaction.emoji.name) {
                case emoji.NEXT_PAGE:
                    {
                        //Edit embed here (Next page)
                        embedMessage.reactions.get(emoji.PREV_PAGE).remove(message.author)
                        break;
                    }
                case emoji.PREV_PAGE:
                    {
                        //Edit embed here (Previous page)
                        embedMessage.reactions.get(emoji.PREV_PAGE).remove(message.author)
                        break;
                    }
            };
        });
        collector.on('end', () => embedMessage.delete());
    })
}

所以现在,我想要一种使机器人编辑嵌入内容的方法,以便在每个菜单页面上依次加载5个表情符号,因此我认为它应该是var,var值将是页码,那么我将可以在keys[]上使用它。

1 个答案:

答案 0 :(得分:2)

您可以创建一个简洁的小功能来帮助您解决此问题。它将遍历json文件的条目,并将指定页面上所需的条目添加到嵌入中。然后,它将收集反应,并再次调用自身以显示另一个页面。

通过示例更容易显示。复制并粘贴代码之前,请务必先了解其代码。

// Require json file.
const emojis = require('./emojis.json');

// Define our function.
async function list(listMsg, page, increment) {
  const entries = Object.entries(emojis);

  // Set up base embed.
  var embed = new Discord.RichEmbed()
    .setColor(1056085)
    .setTitle('**Server Emojis**')
    .setDescription(`Page **${page}** of ${Math.ceil(entries.length/increment)}`)
    .setFooter('Dz Gamers Community', 'https://cdn.discordapp.com/icons/469276415746113568/f86e89f362f1df6dc1f996818ef49e7a.png?size=1024')
    .setTimestamp(listMsg ? listMsg.createdAt : undefined);

  // Add fields to embed.
  const emojiField = [];
  const stringField = [];

  for (let [emoji, string] of entries.slice((page - 1) * increment, (page * increment) + 1)) {
    emojiField.push(emoji);
    stringField.push(string);
  }

  embed.addField('Emoji:', emojiField.join('\n'), true);
  embed.addField('String:', stringField.join('\n'), true);

  // Edit/send embed.
  if (listMsg) await listMsg.edit(embed);
  else listMsg = await message.channel.send(embed);

  // Set up page reactions.
  const lFilter = (reaction, user) => reaction.emoji.name === '◀' && page !== 1 && user.id === message.author.id;
  const lCollector = listMsg.createReactionCollector(lFilter, { max: 1 });

  lCollector.on('collect', async () => {
    rCollector.stop();
    await listMsg.clearReactions();
    list(listMsg, page - 1, increment);
  });

  const rFilter = (reaction, user) => reaction.emoji.name === '▶' && entries.length > page * increment && user.id === message.author.id;
  const rCollector = listMsg.createReactionCollector(rFilter, { max: 1 });

  rCollector.on('collect', async () => {
    lCollector.stop();
    await listMsg.clearReactions();
    list(listMsg, page + 1, increment);
  });

  if (page !== 1) await listMsg.react('◀');
  if (entries.length > page * increment) await listMsg.react('▶');
}

// Send the list; page 1, and 5 shown on each page.
list(undefined, 1, 5)
  .catch(console.error);

由于某些部分可能看起来令人迷惑并且很难通过外观来理解,因此这里有一些进一步的解释:

  • Math.ceil(entries.length / increment)
    • entries的长度除以每页上显示的元素数量(increment)可以得出总共应该​​有多少页。我们之所以ceil,是因为如果还有剩余,我们需要为其提供另一页。
  • embed.setTimestamp(listMsg ? listMsg.createdAt : undefined)
    • 如果我们每次编辑邮件时都设置嵌入的时间戳,那么这不是发送邮件的时间。因此,如果我们正在编辑一条消息,则将其设置为该消息的时间戳;如果要发送新的时间戳,则使用新的时间戳(RichEmbed.setTimestamp()使用未提供任何值的当前时间)。
  • const [emoji, string] of entries.slice(...)
    • [emoji, string]提取条目的键和值并分别分配它们。
  • entries.slice((page - 1) * increment, (page * increment) + 1)
    • (page - 1) * increment是切片的起始索引。 page不是基于零的,因此我们必须从中减去1。然后,将其乘以每页应显示的元素数量,因为所有这些元素均已显示。
    • (page * increment) + 1是要切片到的结尾索引。这次我们不从page中减去,因为那会回到起点-increment元素已经显示。我们必须向其中添加一个,因为end索引中的元素未包含在Array.slice()中。
  • entries.length > page * increment
    • 我们可以通过测试entries的长度是否比显示的最后一个元素的位置长来检查是否还有其他条目。