如何让我的机器人获取已经从频道中的用户发送的随机消息,并在触发自动响应时发送该随机消息

Posted

技术标签:

【中文标题】如何让我的机器人获取已经从频道中的用户发送的随机消息,并在触发自动响应时发送该随机消息【英文标题】:How to get my bot to get random messages that are already sent from users in a channel and send that random message when an autoresponse is triggered 【发布时间】:2020-03-17 06:40:59 【问题描述】:

正如标题所说,我尝试使用 fetchMessages 来检查某个频道发送的消息,但是当我试图弄乱这个时,它只会在控制台中给我提供无穷无尽的信息块。

我尝试阅读它,但其中似乎没有实际消息,只是给了我有关服务器的信息,例如频道 ID、会员 ID、他们的权限等。

起初我认为使用这种方法会给我随机消息,所以我可以让机器人直接将消息发送到一个频道,但它给了我一个错误,所以我只是使用 console.log 来获取更多信息。不过好像不是这样,还是我用错了……

这是我正在尝试的代码:

    bot.on('message', msg =>

    if(msg.author.bot) return;
    lowerCase = msg.content.toLowerCase();

    if(lowerCase.includes ("fetch")) 
        msg.channel.fetchMessages(limit: 1).then(console.log);
    
)

显然它无法跟踪旧消息,因为当我尝试使用用户 ID 过滤掉消息时,它显示他们发送了 0 条消息,即使他们以前一直在发送消息?我正在努力实现它仍然可以读取非常旧的消息,并且在我使用自动回复消息时仍然可以发送这些消息。

【问题讨论】:

【参考方案1】:

TextChannel.fetchMessages() 一次最多只能获取 100 条消息

简答:

虽然docs 中没有显示,但如果您获取超过 100 个,您将收到 API 错误:

DiscordAPIError: Invalid Form Body
limit: int value should be less than or equal to 100.

控制台记录Message 对象确实会为您提供有关Guild 和其中所有其他内容的大量信息。您可能只想控制台记录消息的内容和作者 ID/用户标签

因此,如果您想搜索超过过去的 100 条消息,则必须在每个连续的 TextChannel.fetchMessages() 调用中使用 ChannelLogsQueryOptionsbefore 参数中最旧消息的 ID 连续获取 100 条消息,然后使用Collection.concat() 将每个Collection 连接在一起。


长答案:

例如,如果您想获取过去的 200 条消息,您可以编写如下内容:

// using .then()
await channel.fetchMessages(limit: 100)
.then(first100 => 
  let next100 = await channel.fetchMessages(limit: 100, before: first100.lastKey())
  .then(next100 => 
    let all200 = first100.concat(next100);
  );
);
// in async function
let first100 = await channel.fetchMessages(limit: 100);
let next100 = await channel.fetchMessages(limit: 100, before: first100.last().id);
let all200 = first100.concat(next100);

查看this answer,了解将过去消息存储在数组中的异步函数。

我制作了自己的版本,它会给你一个 Collection 并将它作为正确的 Promise 返回:

const fetchManyMessages = (channel, limit = 200) => 
  return new Promise((resolve, reject) => 
    channel.fetchMessages(limit: limit < 100 ? limit : 100)
    .then(collection => 
      const nextBatch = () => 
        console.log(collection.size);
        let remaining = limit - collection.size;

        channel.fetchMessages(limit: remaining<100 ? remaining : 100, before: collection.lastKey())
        .then(next => 
          let concatenated = collection.concat(next);

          // resolve when limit is met or when no new msgs were added (reached beginning of channel)
          if (collection.size >= limit || collection.size == concatenated.size) return resolve(concatenated);

          collection = concatenated;
          nextBatch();
        )
        .catch(error => reject(error));
      

      nextBatch();
    )
    .catch(error => reject(error));
  );

示例用法:

fetchManyMessages(message.channel, 1500)
.then(msgs => console.log(msgs.size))
.catch(err => console.log(err));

在这里,我还制作了一个prototype 版本,我认为它非常适合一些语法上的精彩:

Discord.TextChannel.prototype.fetchManyMessages = function (limit = 200) 
  return new Promise((resolve, reject) => 
    this.fetchMessages(limit: limit < 100 ? limit : 100)
    .then(collection => 
      const nextBatch = () => 
        console.log(collection.size);
        let remaining = limit - collection.size;

        this.fetchMessages(limit: remaining<100 ? remaining : 100, before: collection.lastKey())
        .then(next => 
          let concatenated = collection.concat(next);

          // resolve when limit is met or when no new msgs were added (reached beginning of channel)
          if (collection.size >= limit || collection.size == concatenated.size) return resolve(concatenated);

          collection = concatenated;
          nextBatch();
        )
        .catch(error => reject(error));
      

      nextBatch();
    )
    .catch(error => reject(error));
  );

示例用法:

message.channel.fetchManyMessages(1500)
.then(msgs => console.log(msgs.size))
.catch(err => console.log(err));

【讨论】:

感谢它可以工作,但是当我尝试生成消息时,控制台只会给我一条未定义的消息,或者当我尝试在频道中发送它时,它会给出不和谐的 api 错误,无法发送空消息.

以上是关于如何让我的机器人获取已经从频道中的用户发送的随机消息,并在触发自动响应时发送该随机消息的主要内容,如果未能解决你的问题,请参考以下文章

如何让我的不和谐机器人只读取某个频道中的内容

如何向特定频道发送加入/离开消息

如何使用 Telegram Bot API 获取 Telegram 频道用户列表

让我的 discord.js 机器人从我的计算机中的一组图像中发送一张随机图片

如何让我的机器人在特定频道中发送消息,然后在一段时间后将其删除

如何使用 dhooks 查找频道中发送的最新消息