如何停止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]; } }); }, };
关键修复点
- 按用户ID管理收集器:避免不同用户的收集器互相干扰,确保只停止当前用户的旧收集器
- 正确存储与清理收集器:新收集器创建后存入
collectors对象,结束时从对象中移除 - 统一按钮自定义ID:修正
infractions的拼写不一致问题,确保switch分支能正确匹配 - 移除冗余代码:删除未使用的
createCollector函数
额外注意事项
- 所有按钮的
execute函数中,必须正确响应交互(如deferUpdate、update或reply),防止Discord判定交互超时 - 若按钮操作耗时较长,需先调用
await i.deferUpdate();延长交互有效期
内容的提问来源于stack exchange,提问作者Flipdanger
相关产品推荐
相关产品推荐

