如何根据Discord.js中的响应来编辑消息(创建列表和切换页面)

时间:2019-08-02 10:35:41

标签: discord discord.js

我希望Discord机器人发送一条消息,然后在人们做出反应时对其进行编辑(例如,创建列表,然后单击向右或向左箭头将编辑消息并显示列表的下一个/上一个部分)。

示例:
反应前:
enter image description here

反应后:
enter image description here

3 个答案:

答案 0 :(得分:3)

如何处理消息反应?

有3种方式来响应消息反应:

  1. 使用功能awaitReactions(基于承诺)
  2. 使用ReactionCollector
  3. 使用messageReactionAdd事件

差异:

messageReactionAdd是链接到Client的事件:

  

每当将响应添加到缓存的消息时发出。

ReactionCollectorawaitReactions链接到特定消息时,如果将响应添加到另一条消息中,则不会执行任何操作。

如果将响应添加到缓存的消息(旧消息),则不会触发

messageReactionAdd。 Discord.js指南中有一个guide for listening on old messages,其中给出了此警告

  

本节描述如何使用一些未公开的API将不支持的功能添加到discord.js中,因此,您在此处应格外小心。这里的任何内容都随时可能更改,恕不另行通知,并且可能会破坏您的漫游器中的其他功能。

awaitReactions是基于promise的,并且仅在promise满足时(添加X个反应之后,Y秒之后,等等)才返回所有添加的反应的集合。没有专门的支持来处理每个增加的反应。您可以将函数放在filter函数中,以获取添加的所有响应,但这不是一个小技巧。 ReactionCollector有一个collect事件。

那我该怎么用?

您要编辑您的漫游器发送的消息(因为您无法编辑其他用户的消息)。因此,ReactionCollectorawaitReactions

如果要在满足特定条件后编辑消息(X个人已投票,Y反应已添加,则在15分钟后...)(例如:投票,您将允许用户投票)在15分钟内),您可以同时使用awaitReactionsReactionCollector

但是,如果您要基于特定反应来编辑消息(例如,在示例中对箭头表情符号做出反应时),则必须使用ReactionCollector

如果未缓存邮件,则可以使用messageReactionAdd,但会更加复杂,因为您基本上必须重写表情符号收集器,但必须重写每个表情符号。

注意:如果机器人重新启动,ReactionCollectorawaitReactions将被删除,而messageReactionAdd将照常运行(但您将丢失声明的变量,因此如果已存储您要收听的消息,它们也会消失)。

该怎么办?

您将需要其他东西:

  • 将触发功能的表情符号列表(您可以选择对每个表情符号做出反应)
  • 停止收听消息反应的条件(如果您想使用messageReactionAdd收听每条消息,则不适用
  • 接收消息并对其进行编辑的功能
  • 一个过滤器函数,它将返回一个布尔值:true我想对此表情符号作出反应,false我不想作出反应。此功能将基于表情符号列表,但也可以过滤用户的反应或您需要的任何其他条件
  • 编辑消息的逻辑。例如:对于列表,它将基于结果数,当前索引和添加的反应

示例:用户列表

表情符号列表:

const emojiNext = '➡'; // unicode emoji are identified by the emoji itself
const emojiPrevious = '⬅';
const reactionArrow = [emojiPrevious, emojiNext];

停止条件

const time = 60000; // time limit: 1 min

编辑功能

这里的功能非常简单,消息是预先生成的(时间戳和页脚除外)。

const first = () => new Discord.RichEmbed()
      .setAuthor('TOTO', "https://i.imgur.com/ezC66kZ.png")
      .setColor('#AAA')
      .setTitle('First')
      .setDescription('First');

const second = () => new Discord.RichEmbed()
      .setAuthor('TOTO', "https://i.imgur.com/ezC66kZ.png")
      .setColor('#548')
      .setTitle('Second')
      .setDescription('Second');

const third = () => new Discord.RichEmbed()
      .setAuthor('TOTO', "https://i.imgur.com/ezC66kZ.png")
      .setColor('#35D')
      .setTitle('Third')
      .setDescription('Third');

const list = [first, second, third];

function getList(i) {
  return list[i]().setTimestamp().setFooter(`Page ${i+1}`); // i+1 because we start at 0
}

过滤器功能

function filter(reaction, user){
  return (!user.bot) && (reactionArrow.includes(reaction.emoji.name)); // check if the emoji is inside the list of emojis, and if the user is not a bot
}

逻辑

function onCollect(emoji, message, i, getList) {
  if ((emoji.name === emojiPrevious) && (i > 0)) {
    message.edit(getList(--i));
  } else if ((emoji.name === emojiNext) && (i < list.length-1)) {
    message.edit(getList(++i));
  }
  return i;
}

构建构造函数

示例与问题中的示例相同,使用箭头功能编辑消息。

我们将使用收集器:

function createCollectorMessage(message, getList) {
  let i = 0;
  const collector = message.createReactionCollector(filter, { time });
  collector.on('collect', r => {
    i = onCollect(r.emoji, message, i, getList);
  });
  collector.on('end', collected => message.clearReactions());
}

接收我们想听的信息。您还可以给它一个内容列表//消息//任何东西。在这里,编辑功能是全局定义的,但更有可能作为收集器到逻辑功能的自变量给出。

发送消息并添加收集器

function sendList(channel, getList){
  channel.send(getList(0))
    .then(msg => msg.react(emojiPrevious))
    .then(msgReaction => msgReaction.message.react(emojiNext))
    .then(msgReaction => createCollectorMessage(msgReaction.message, getList));
}

答案 1 :(得分:2)

根据OP的要求撰写此答案

由于这是一件很常见的事情,因此,我编写了一个库来帮助完成这一工作:discord-dynamic-messages 请注意,discord-dynamic-messages是仅用于打字稿的库。 / em>

这是使用动态消息解决问题的方法。

定义分页消息

import { RichEmbed } from 'discord.js';
import { DynamicMessage, OnReaction } from 'discord-dynamic-messages';

const clamp = (num, min, max) => Math.min(Math.max(num, min), max);

export class PaginationMessage extends DynamicMessage {
  constructor(private embeds: Array<() => RichEmbed>, private embedIndex = 0) {
    super();
  }

  @OnReaction(':arrow_left:')
  public previousEmbed() {
    this.embedIndex = clamp(this.embedIndex - 1, 0, this.embeds.length - 1);
  }

  @OnReaction(':arrow_right:')
  public nextEmbed() {
    this.embedIndex = clamp(this.embedIndex + 1, 0, this.embeds.length - 1);
  }

  public render() {
    return this.embeds[this.embedIndex]()
      .setTimestamp()
      .setFooter(`Page ${this.embedIndex + 1}`);
  }
}

使用您定义的分页消息

import { Client, RichEmbed } from 'discord.js';
import { PaginationMessage } from '...'

const first = () => new RichEmbed()
  .setAuthor('TOTO', 'https://i.imgur.com/ezC66kZ.png')
  .setColor('#AAA')
  .setTitle('First')
  .setDescription('First');

const second = () => new RichEmbed()
  .setAuthor('TOTO', 'https://i.imgur.com/ezC66kZ.png')
  .setColor('#548')
  .setTitle('Second')
  .setDescription('Second');

const third = () => new RichEmbed()
  .setAuthor('TOTO', 'https://i.imgur.com/ezC66kZ.png')
  .setColor('#35D')
  .setTitle('Third')
  .setDescription('Third');

const pages = [first, second, third];

const client = new Client();
client.on('ready', () => {
  client.on('message', (message) => {
    new PaginationMessage(pages).sendTo(message.channel);
  });
});
client.login(discord_secret);

答案 2 :(得分:0)

您可以像这样使用awaitReactions()方法。

const { MessageEmbed } = require('discord.js');

const messageEmbed1 = new MessageEmbed()
//Add the methods you want (customize the embed to how you want)

const messageEmbed2 = new MessageEmbed()
//Add the methods you want (customize the embed to how you want)

const msg = await message.channel.send(messageEmbed1);
msg.react("️️⬅️");
msg.react("➡️");

let react;
react = await msg.awaitReactions(
    (reaction, user) => reaction.emoji.name === '➡️' && user.id === message.author.id,
    { max: 1, time: Infinity, errors: ['time'] }
);

if (react && react.first()) msg.edit(messageEmbed2);

let react2;
react2 = await msg.awaitReactions(
    (reaction, user) => reaction.emoji.name === '⬅️' && user.id === message.author.id,
    { max: 1, time: Infinity, errors: ['time'] }
);

if (react2 && react2.first()) msg.edit(messageEmbed1);