You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级discord.js v13后awaitReactions过滤器不生效问题

过滤器失效根因
  • 核心配置缺失:discord.js v13及以上版本要求显式开启GuildMessageReactions网关意图,同时配置Reaction、User类部分结构(Partial)解析,否则客户端无法获取完整的反应事件、操作人信息,传入filter的参数为残缺占位对象,过滤逻辑完全不生效,会直接放行缓存内已存在的反应(包括机器人自己添加的反应)。
  • 逻辑漏洞:原代码未在filter中排除机器人账号操作,靠3秒延迟规避自反应属于治标不治本;收集到反应后没有做二次校验,直接走分支判断,导致绕过filter的非法表情、非授权用户操作都会触发业务逻辑。
  • 语法问题:原代码回调中引用的user、reaction变量未定义,属于作用域错误,会导致逻辑判断异常;同时未给反应监听设置超时时间,会造成内存泄漏;旧版delete({timeout: xxx})写法在新版discord.js中已废弃,会直接报错。
前置配置修复

首先在客户端初始化时补全必需的意图和部分结构配置,否则过滤逻辑永远无法正常生效:

const { Client, GatewayIntentBits, Partials } = require('discord.js');
const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.GuildMessageReactions, // 必须开启,否则收不到用户的反应事件
    GatewayIntentBits.MessageContent
  ],
  partials: [
    Partials.Message,
    Partials.Channel,
    Partials.Reaction, // 必须配置,否则无法处理非缓存的反应
    Partials.User // 必须配置,否则无法拿到非缓存的用户信息
  ]
});
修复后的业务代码
getRedCardChannel.send({ embeds: [cardEmbed] })
  .then(async message => {
    console.log('Message sent to Channel');
    // 等待两个反应添加完成后再启动监听,从流程上避免把自加反应纳入收集范围
    await message.react('✅');
    await message.react('❌');
    console.log('Confirmation buttons added');

    const confirmFilter = (reaction, user) => {
      // 按优先级过滤:先排除所有机器人操作,再校验表情合法性,最后校验用户权限
      if (user.bot) return false;
      if (!['✅', '❌'].includes(reaction.emoji.name)) return false;
      return user.id === getAdminId || user.id === getApproverId;
    };

    message.awaitReactions({ 
      filter: confirmFilter, 
      max: 1, 
      time: 15 * 60 * 1000, // 设置15分钟审批超时,避免监听器永久驻留
      errors: ['time'] 
    })
    .then(collected => {
      const approvalReaction = collected.first();
      // 二次兜底校验,防止异常场景下非法反应绕过filter
      if (!['✅', '❌'].includes(approvalReaction.emoji.name)) return;
      const operator = approvalReaction.users.cache.last();
      if (operator.bot || (operator.id !== getAdminId && operator.id !== getApproverId)) return;

      if (approvalReaction.emoji.name === '✅') {
        message.react('🟥');
        console.log('Approved');
        console.log(`${message.author.tag}'s message "${message.content}" gained a confirmed red card!`);
      } else {
        console.log('Rejected');
        // 替换已废弃的timeout参数写法
        setTimeout(() => {
          message.delete()
            .then(() => {
              getRedCardChannel.send('Provisional card removed')
                .then(deleteMessage => {
                  setTimeout(() => deleteMessage.delete(), 3000);
                });
            });
        }, 1000);
      }
    })
    .catch(() => {
      console.log('Approval timed out');
    });
  });
修复点说明
  • 移除了不必要的3秒延迟:通过await确保机器人自身的反应添加完成后再启动监听,同时在filter第一层直接拦截所有机器人账号的操作,彻底解决自反应误触发问题。
  • 优化filter判断顺序:按照「排除机器人→校验表情→校验权限」的顺序过滤,不符合任意条件的反应直接拦截,不会进入收集队列。
  • 增加二次兜底校验:在拿到收集到的反应后再次校验表情和操作人权限,哪怕出现缓存异常导致非法反应绕过filter,也不会触发后续审批逻辑。
  • 修复语法兼容问题:替换了新版discord.js已废弃的delete超时参数写法,修正了未定义变量的作用域错误,增加监听超时逻辑避免内存泄漏。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 16:18:20