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才能被持久保存。 - 添加
quizTimersMap:存储每个用户的定时器,当用户主动取消或完成测验时,能及时清除定时器,避免不必要的消息发送。 - 修正语法错误:把代码里的中文逗号改成英文逗号,避免运行报错。
- 添加错误捕获:对
message.author.send添加try-catch,防止因用户关闭DM、Bot权限不足等情况导致的报错。 - 补充"cancel"指令处理:当用户输入cancel时,清理用户的测验状态,让逻辑更完整。
内容的提问来源于stack exchange,提问作者Itamar S
相关产品推荐
相关产品推荐

