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

如何停止Discord按钮Collector以避免Unknown interaction错误?

解决Discord机器人按钮交互的Unknown interaction错误

当前遇到的错误为:

DiscordAPIError[10062]: Unknown interaction
 at handleErrors (C:\Users\user\Desktop\Discord Bot Version 1.0.0 (Beta)\node_modules\@discordjs\rest\dist\index.js:640:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async BurstHandler.runRequest (C:\Users\user\Desktop\Discord Bot Version 1.0.0 (Beta)\node_modules\@discordjs\rest\dist\index.js:736:23)
    at async REST.request (C:\Users\user\Desktop\Discord Bot Version 1.0.0 (Beta)\node_modules\@discordjs\rest\dist\index.js:1387:22)
    at async ButtonInteraction.update (C:\Users\user\Desktop\Discord Bot Version 1.0.0 (Beta)\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:233:5)
    at async InteractionCollector.<anonymous> (C:\Users\user\Desktop\Discord Bot Version 1.0.0 (Beta)\buttons\moderates\listRaiting.js:51:7) {
  requestBody: { files: [], json: { type: 7, data: [Object] } },
  rawError: { message: 'Unknown interaction', code: 10062 },
  code: 10062,
  status: 404,
  method: 'POST',
  url: 'https://discord.com/api/v10/interactions/1108982827606888478/aW50ZXJhY3Rpb246MTEwODk4MjgyNzYwNjg4ODQ3ODpWYW0wbnVoR2hpdDJxeHlhYjlzZ1FvaVZEVXJaQUhzaTNHWTF4Sm1rVW5FbnVTYjE0NjdETGZrUndZV1A2T3ExY0RYdWhYcEgwR2JOWHdIcXV4czJBTEF3aUkyQ281QnlhR3RsZUdIcktkRGRjV3hjNEY1OTdzS0tyUG5hU0doYw/callback'
}

问题根源

现有代码中collectors对象未实际存储新创建的收集器,导致循环停止旧收集器时无目标可操作,旧收集器持续运行并处理已过期的交互请求;同时存在按钮自定义ID拼写不一致的问题,可能引发无响应或错误。

修复方案

修复后的完整代码

const { SlashCommandBuilder } = require('@discordjs/builders');
const {
  ActionRowBuilder,
  ButtonBuilder,
  EmbedBuilder,
  ButtonStyle,
} = require('discord.js');

const muteButton = require('../../buttons/moderates/muteButton.js');
const unMuteButton = require('../../buttons/moderates/unMuteButton.js');
const warnButton = require('../../buttons/moderates/warnButton.js');
const unWarnButton = require('../../buttons/moderates/unWarnButton.js');
const listRaitingButton = require('../../buttons/moderates/listRaiting.js');
const infractionButton = require('../../buttons/moderates/infractionButton.js');
const raitingButton = require('../../buttons/moderates/raitingButton.js');
const unraitingButton = require('../../buttons/moderates/unraitingButton.js');

// 按用户ID存储收集器,避免跨用户干扰
const collectors = {};

module.exports = {
  data: new SlashCommandBuilder()
    .setName('moderate')
    .setDescription('Предоставляет модераторскую панель с действиями, такими как мут, размут, предупреждение и т.д.'),
  async execute(interaction) {
    const member = interaction.member;
    const moderatorRole = member.roles.cache.find(r => r.name === 'Модератор');
    if (!moderatorRole) {
      return interaction.reply({ content: 'Вы не являетесь Модератором, у вас нет прав для использования этой команды.', ephemeral: true });
    }

    // 停止当前用户的旧收集器并清理
    if (collectors[interaction.user.id]) {
      collectors[interaction.user.id].stop('new_command_triggered');
      delete collectors[interaction.user.id];
    }

    const filter = i => i.user.id === interaction.user.id;
    const collector = interaction.channel.createMessageComponentCollector({ filter, time: 30000 });
    // 将新收集器存入对象
    collectors[interaction.user.id] = collector;

    const row = new ActionRowBuilder()
      .addComponents(
        new ButtonBuilder()
          .setCustomId('mute')
          .setEmoji('🔇')
          .setStyle(ButtonStyle.Secondary),
        new ButtonBuilder()
          .setCustomId('unmute')
          .setEmoji('🔊')
          .setStyle(ButtonStyle.Secondary),
        new ButtonBuilder()
          .setCustomId('warn')
          .setEmoji('⚠️')
          .setStyle(ButtonStyle.Secondary),
        new ButtonBuilder()
          .setCustomId('unwarn')
          .setEmoji('❌')
          .setStyle(ButtonStyle.Secondary)
      );

    const row1 = new ActionRowBuilder()
      .addComponents(
        new ButtonBuilder()
          .setCustomId('raiting')
          .setEmoji('✅')
          .setStyle(ButtonStyle.Secondary),
        new ButtonBuilder()
          .setCustomId('unraiting')
          .setEmoji('❎')
          .setStyle(ButtonStyle.Secondary),
        new ButtonBuilder()
          .setCustomId('listraiting')
          .setEmoji('📃')
          .setStyle(ButtonStyle.Secondary),
        new ButtonBuilder()
          .setCustomId('infractions')
          .setEmoji('📋')
          .setStyle(ButtonStyle.Secondary)
      );

    const embed = new EmbedBuilder()
      .setColor(0x000000)
      .setTitle('Модераторская панель')
      .setDescription(`**Действия для управления порядком на сервере.**\n\n**1-ая строка кнопок:**\n\n🔇 — Выдать таймаут участнику\n🔊 — Снять таймаут с участника\n⚠️ — Выдать предупреждение участнику\n❌ — Снять предупреждение с участником\n📜 — Посмотреть предупреждения пользователя\n\n**2-ая строка кнопок:**\n\n✅ — Выдать роль рейтинга участнику\n❎ — Снять роль рейтинга участнику\n📃 — Список участников с ролью рейтинга\n📋 — История нарушений`);

    await interaction.deferReply();
    await interaction.followUp({ 
      embeds: [embed], components: [row, row1], ephemeral: false });

    collector.on('collect', async i => {
      switch (i.customId) {
        case 'mute':
          await muteButton.execute(i);
          break;
        case 'unmute':
          await unMuteButton.execute(i);
          break;
        case 'warn':
          await warnButton.execute(i);
          break;
        case 'unwarn':
          await unWarnButton.execute(i);
          break;
        case 'listraiting':
          await listRaitingButton.execute(i);
          break;
        case 'infractions':
          await infractionButton.execute(i);
          break;
        case 'raiting':
          await raitingButton.execute(i);
          break;
        case 'unraiting':
          await unraitingButton.execute(i);
          break;
      }
    });

    collector.on('end', (collected, reason) => {
      console.log(`Collector для пользователя ${interaction.user.id} завершен. Причина: ${reason}. Собрано ${collected.size} элементов.`);
      // 收集器结束后清理缓存
      if (collectors[interaction.user.id]) {
        delete collectors[interaction.user.id];
      }
    });
  },
};

关键修复点

  1. 按用户ID管理收集器:避免不同用户的收集器互相干扰,确保只停止当前用户的旧收集器
  2. 正确存储与清理收集器:新收集器创建后存入collectors对象,结束时从对象中移除
  3. 统一按钮自定义ID:修正infractions的拼写不一致问题,确保switch分支能正确匹配
  4. 移除冗余代码:删除未使用的createCollector函数

额外注意事项

  • 所有按钮的execute函数中,必须正确响应交互(如deferUpdate、update或reply),防止Discord判定交互超时
  • 若按钮操作耗时较长,需先调用await i.deferUpdate();延长交互有效期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:24:56