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

Discord.js v14 反应收集器异常及计分系统实现咨询

Discord 反应收集器问题与计分系统实现方案

问题1:重复收集反应的原因及修复

原因

你在client.on("messageCreate")事件内部嵌套绑定了多层同类型事件监听器:

  • 每次用户发送prefix + "m"触发外层messageCreate时,都会新增一个client.on("messageCreate")监听器
  • 当机器人发送彩蛋消息后,所有已绑定的messageCreate监听器都会同时触发,各自创建独立的反应收集器
  • 用户一次反应会被多个收集器同时捕获,导致控制台显示的收集次数远多于实际操作次数

修复方案

移除嵌套的事件绑定,直接在机器人发送彩蛋消息后创建收集器,不需要额外监听自身发送的消息:

client.on("messageCreate", async message => {
  // 处理发送彩蛋消息的指令
  if (message.content === prefix + "m") {
    const eggMessage = await message.channel.send("Voici un oeuf de Pâques! Vite! Réagis avant qu'il ne disparaisse! :)");
    await eggMessage.react('🥚');

    const filter = (reaction, user) => {
      return reaction.emoji.name === '🥚' && user.id !== client.user.id;
    };

    const collector = eggMessage.createReactionCollector({ filter, time: 5000 });

    collector.on('collect', (reaction, user) => {
      console.log(`Collected ${reaction.emoji.name} from ${user.tag}`);
      // 调用后续实现的计分更新函数
      updateUserScore(user.id);
    });

    collector.on('end', collected => {
      console.log(`Collected ${collected.size} items`);
    });
  }

  // 处理查询分数的指令,单独放在外层
  if (message.content === prefix + "c") {
    const userScore = getUserDailyScore(message.author.id);
    const infoEmbed = new EmbedBuilder()
      .setColor('Random')
      .setTitle(`Inventory`)
      .setDescription("Check how many Easter Eggs you collected!")
      .addFields({ name: 'Easter Eggs', value: `${userScore}` });

    message.channel.send({ embeds: [infoEmbed] });
  }
});

问题2:单日用户反应次数计分系统实现

核心逻辑

  • 用结构化数据存储每日分数(开发阶段用全局对象,生产环境建议用数据库持久化)
  • 每次用户反应时,基于当前日期更新对应用户的计数
  • 查询时读取当日的用户分数数据

具体实现代码

// 全局存储每日分数,结构:{ "YYYY-MM-DD": { "用户ID": 累计次数 } }
let dailyScores = {};

// 获取格式化的当前日期(YYYY-MM-DD)
function getCurrentDate() {
  const now = new Date();
  return `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
}

// 更新用户当日反应次数
function updateUserScore(userId) {
  const currentDate = getCurrentDate();
  // 如果当日分数记录不存在,初始化空对象
  if (!dailyScores[currentDate]) {
    dailyScores[currentDate] = {};
  }
  // 累加用户次数,无记录则初始化为1
  dailyScores[currentDate][userId] = (dailyScores[currentDate][userId] || 0) + 1;
}

// 获取用户当日累计反应次数
function getUserDailyScore(userId) {
  const currentDate = getCurrentDate();
  return dailyScores[currentDate]?.[userId] || 0;
}

生产环境优化提示

  • 全局对象在机器人重启后会丢失数据,建议使用轻量数据库(如quick.db或sqlite3)实现持久化存储
  • 可添加定时任务,每日自动清理过期的历史分数,降低内存占用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 20:44:56