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

Discord.js v13 Bot无法处理同一频道内多用户同时触发的按钮交互问题

Discord带按钮的冒险系统多用户同频道使用方案

原问题描述

有没有办法让带按钮的命令支持两名用户在同一频道内同时使用?

我开发了一个冒险系统,目前进展顺利,但发现同一频道内仅支持单用户使用该系统。若其他用户在同频道触发,点击按钮时会立刻抛出"DiscordAPIError: Unknown Interaction"错误。我尝试过在按钮的custom ID末尾添加消息作者ID适配,但不知为何并未生效,目前完全没有头绪。

根据我的判断,问题应该和多按钮实例无关,但我想不到其他可能的诱因。我的过滤器代码如下:

const filter = async (interaction) => {
        if (interaction.user.id === message.author.id) return true;
        await interaction.deferReply()
        await interaction.editReply({ content: `**${interaction.user.username}**, You can't use this button!`, ephemeral: true})
        return false
    }

按钮点击监听代码大致如下:

GameCollect.on('collect', async ButtonInteraction => {
            ButtonInteraction.deferUpdate()
            // My code
})

我已经尝试过的解决方案:

  • 删除所有点击收集器中的ButtonInteraction.deferUpdate()代码。
  • 将按钮的custom ID末尾拼接消息作者ID,并适配了对应的业务逻辑。
  • (调侃:急得头撞键盘,也没用... 开玩笑的)

如果有需要,我可以把完整代码上传到repl方便定位问题,我认为其他逻辑不会影响这部分功能,应该只需要添加少量代码/微调就能支持同频道两人同时使用。

编辑补充:我已上传完整源码方便定位问题,也可以查看最新回答下的评论了解我的测试详情,找到解决方案我会同步更新。

声明:我花了一个多月都没找到可行解决方案,现在基本决定放弃用按钮实现该功能了,还是感谢所有提供帮助的人。

问题根因

报错的核心诱因有两个:

  1. 你使用了全局共享的GameCollect收集器监听,每次新用户触发冒险时,新的收集器配置会覆盖旧的监听逻辑,导致先触发的冒险实例的按钮交互找不到对应的处理逻辑,直接抛出未知交互错误。
  2. 交互处理逻辑没有添加await关键字,异步操作未完成就结束了交互生命周期,同时filter内对非允许用户的交互响应逻辑存在时序问题,未完成回复就直接返回false导致交互未被正确消费。

修复方案

1. 为每一场冒险独立创建专属收集器

不要复用全局收集器,每次用户触发冒险命令、生成带按钮的游戏消息后,单独为这条消息创建独立的组件收集器,不同冒险实例的收集器互相隔离,互不干扰:

// 每次用户触发冒险、生成游戏消息后执行
const gameMessage = await channel.send({ /* 你的消息内容+按钮配置 */ })
// 为当前这条游戏消息创建专属收集器
const currentGameCollector = gameMessage.createMessageComponentCollector({
  time: 7200000, // 自定义游戏超时时间
  filter: generateFilter(message.author.id, secondUserId) // 传入允许参与的两个用户ID
})

// 仅监听当前这场冒险的按钮交互
currentGameCollector.on('collect', async interaction => {
  // 必须加await等待defer完成,避免交互提前过期
  await interaction.deferUpdate()
  // 你的游戏业务逻辑
})

// 游戏结束后销毁收集器,避免残留监听
currentGameCollector.on('end', () => {
  // 可选:将游戏消息的按钮设为禁用状态
})

2. 修正过滤器逻辑

调整filter的判断条件和响应逻辑,确保所有交互都被正确响应:

// 生成适配当前冒险的过滤器,传入两个允许参与的用户ID
const generateFilter = (hostId, guestId) => async (interaction) => {
  if (interaction.user.id === hostId || interaction.user.id === guestId) return true
  // 直接用reply不用deferReply+editReply,减少异步层级
  await interaction.reply({ 
    content: `**${interaction.user.username}**, 你不能使用这个按钮!`, 
    ephemeral: true 
  })
  return false
}

3. 可选优化:custom ID 适配规则

如果你依然要使用custom ID区分用户,格式建议统一为[动作类型]_[用户ID],在全局交互监听中先拆分custom ID,匹配到对应的游戏实例再处理,也可以解决多实例冲突问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 12:36:02