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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:03:22