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

Discord.js Set集合失效问题:测验Bot无法阻止中途重启

问题根源分析

你遇到的核心问题是**midQuiz Set 被定义在了 message 事件的回调函数内部**——每次 Bot 收到一条消息,这个回调就会执行一次,同时创建一个全新的空 Set。这意味着你之前添加的用户 ID 根本不会被持久保存,所以判断 midQuiz.has(message.author.id) 永远返回 false,自然不会触发"正在测验中"的提示,用户也能无限制重启测验。

修复方案

把 midQuiz 的定义移到事件回调外面,让它成为一个全局(或模块级)的变量,这样它就能在多次消息事件之间保持状态。同时还要修正代码里的小错误,并补充"cancel"指令的处理逻辑,让功能更完整。

修正后的代码如下:

// 把Set定义在事件回调外面,确保它能持续保存状态
const midQuiz = new Set();
// 用Map存储每个用户的定时器,方便主动取消
const quizTimers = new Map();

client.on('message', async message => { 
  const filter = m => m.author.id === message.author.id; 
  let mistakes = 0; 

  if (message.content === 'start') { 
    if (message.channel.type === "dm") { 
      if (midQuiz.has(message.author.id)) { 
        console.log('hello');
        return message.author.send("You're currently mid-quiz! You may not restart it now."); 
      } else { 
        midQuiz.add(message.author.id);
        // 创建定时器并存储到Map中
        const timer = setTimeout(() => { 
          midQuiz.delete(message.author.id);
          quizTimers.delete(message.author.id);
          try {
            message.author.send("10 minutes have gone by and you have not completed the quiz, therefore you have failed.");
          } catch (err) {
            console.error(`无法给用户 ${message.author.id} 发送消息:`, err);
          }
        }, 600000);
        quizTimers.set(message.author.id, timer);

        const Embed = new Discord.MessageEmbed() 
          .setTitle("Verification Quiz") 
          .setDescription("Question #1: What is the owner's name?") 
          .setColor(3426654) 
          .setFooter("You may type 'cancel' at any time to stop the quiz.");
        // 修正中文逗号为英文逗号
        await message.author.send(Embed);

        // 补充收集回答的逻辑,包含cancel指令处理
        try {
          const response = await message.channel.awaitMessages(filter, { max: 1, time: 600000 });
          const userAnswer = response.first().content.toLowerCase();
          
          // 用户输入cancel时,提前结束测验
          if (userAnswer === 'cancel') {
            midQuiz.delete(message.author.id);
            clearTimeout(quizTimers.get(message.author.id));
            quizTimers.delete(message.author.id);
            return message.author.send("Quiz cancelled successfully.");
          }

          // 这里可以添加回答判断逻辑,示例:
          if (userAnswer !== 'correct-owner-name') {
            mistakes++;
            // 后续问题逻辑...
          }

          // 测验完成后清理状态
          midQuiz.delete(message.author.id);
          clearTimeout(quizTimers.get(message.author.id));
          quizTimers.delete(message.author.id);
          message.author.send("Quiz completed successfully!");
        } catch (err) {
          console.error("收集回答出错:", err);
        }
      }
    }
  }
});
关键修改点说明
  • 将 midQuiz 移到事件外部:确保Set在Bot运行期间只创建一次,所有消息事件共享同一个实例,用户ID才能被持久保存。
  • 添加 quizTimers Map:存储每个用户的定时器,当用户主动取消或完成测验时,能及时清除定时器,避免不必要的消息发送。
  • 修正语法错误:把代码里的中文逗号改成英文逗号,避免运行报错。
  • 添加错误捕获:对message.author.send添加try-catch,防止因用户关闭DM、Bot权限不足等情况导致的报错。
  • 补充"cancel"指令处理:当用户输入cancel时,清理用户的测验状态,让逻辑更完整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:25:40