discord.js实现可正常运行的Q&A问答命令方案
discord.js quest问答命令实现方案
基础配置
- 主命令名:
quest - 命令别名:
q - 冷却时间:
12s - 已解决三类常见代码问题:冗余重复定义
MessageEmbed、quiz题库嵌套错误无法读取题目答案、awaitMessages/消息收集器答案匹配逻辑取值异常 - 所有discord.js原生API、技术术语保留原名不做翻译
第一步:正确格式的quiz题库配置
使用一维对象数组存储题库,禁止多层数组嵌套,每个题目对象固定包含题干、可接受答案列表、奖励值三个字段,可直接追加题目:
// 题库配置,直接按格式追加题目即可,不要修改外层数组结构 const quizBank = [ { question: "这里写第一道题的题干内容", // 所有可接受答案统一存入数组,匹配时自动忽略大小写、前后空格 acceptableAnswers: ["正确答案1", "正确答案一", "correct ans1"], reward: 10 }, { question: "这里写第二道题的题干内容", acceptableAnswers: ["正确答案2", "正确答案二", "correct ans2"], reward: 15 } // 后续题目继续往后追加即可 ]
第二步:完整可运行命令代码
代码基于discord.js v14编写,复用同一个EmbedBuilder实例避免冗余定义,冷却逻辑基于Collection实现,答案匹配做了格式容错:
const { SlashCommandBuilder, EmbedBuilder, Collection } = require('discord.js'); // 初始化冷却存储集合 const cooldowns = new Collection(); module.exports = { data: new SlashCommandBuilder() .setName('quest') .setDescription('参与问答任务领取奖励'), // 配置命令别名,适配prefix模式时可直接读取该字段 aliases: ['q'], cooldown: 12, async execute(interaction) { // 12秒冷却判断逻辑 if (!cooldowns.has('quest')) cooldowns.set('quest', new Collection()); const now = Date.now(); const timestamps = cooldowns.get('quest'); const cooldownAmount = this.cooldown * 1000; if (timestamps.has(interaction.user.id)) { const expireTime = timestamps.get(interaction.user.id) + cooldownAmount; if (now < expireTime) { const remainTime = (expireTime - now) / 1000; return interaction.reply({ content: `请等待${remainTime.toFixed(1)}秒后再使用该命令`, ephemeral: true }); } } timestamps.set(interaction.user.id, now); setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount); // 随机抽取一道题目 const targetQuiz = quizBank[Math.floor(Math.random() * quizBank.length)]; // 复用同一个Embed实例,避免重复定义冗余结构 const quizEmbed = new EmbedBuilder() .setColor('#2f9eec') .setTitle('📝 Quest问答任务') .setDescription(targetQuiz.question) .setFooter({ text: '你有15秒的答题时间,答案不区分大小写' }); await interaction.reply({ embeds: [quizEmbed] }); // 消息收集器配置,仅监听触发命令用户在当前频道发送的消息 const msgFilter = msg => msg.author.id === interaction.user.id && !msg.author.bot; const collector = interaction.channel.createMessageCollector({ filter: msgFilter, time: 15000, max: 1 }); collector.on('collect', async (userMsg) => { // 对用户输入做格式化处理,避免前后空格、大小写差异导致匹配失败 const userInput = userMsg.content.trim().toLowerCase(); const isPass = targetQuiz.acceptableAnswers.some(ans => ans.toLowerCase() === userInput); if (isPass) { quizEmbed.setColor('#2ecc71') .setDescription(`✅ 回答正确!\n题目:${targetQuiz.question}\n可接受答案:${targetQuiz.acceptableAnswers.join('、')}\n获得奖励:${targetQuiz.reward}积分`) .setFooter({ text: '答题完成' }); // 在此处添加你的奖励发放逻辑,比如更新数据库用户积分 } else { quizEmbed.setColor('#e74c3c') .setDescription(`❌ 回答错误!\n题目:${targetQuiz.question}\n可接受答案:${targetQuiz.acceptableAnswers.join('、')}`) .setFooter({ text: '答题失败' }); } await interaction.editReply({ embeds: [quizEmbed] }); collector.stop(); }); collector.on('end', (_, reason) => { if (reason === 'time') { quizEmbed.setColor('#f39c12') .setDescription(`⏰ 答题超时!\n题目:${targetQuiz.question}\n可接受答案:${targetQuiz.acceptableAnswers.join('、')}`) .setFooter({ text: '答题超时' }); interaction.editReply({ embeds: [quizEmbed] }); } }); } };
如果你使用的是prefix消息命令而非slash命令,只需要把代码中interaction相关的逻辑替换为message对象逻辑即可,核心答题、冷却、匹配逻辑完全通用。
问题排查指引
- 无法读取题目/答案:检查
quizBank是否为一维对象数组,禁止在数组内嵌套额外数组存储题目 - 答案匹配失效:确认
acceptableAnswers数组内的答案值无多余空格,匹配逻辑会自动处理用户输入的大小写、前后空格问题 - 消息收集器无响应:检查
msgFilter过滤规则,确保没有多余的权限、频道限制条件拦截用户消息 - 冷却逻辑失效:确认
cooldowns集合定义在命令文件全局作用域,不要定义在execute函数内部
内容的提问来源于stack exchange,提问作者Diesel4137
相关产品推荐
相关产品推荐

