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

如何实现Discord Bot按钮在程序重启后保持正常交互响应

问题根因

你当前使用的channel.createMessageComponentCollector创建的是进程级临时监听器,生命周期和Bot运行进程强绑定,仅在监听器创建后的当前进程运行阶段生效。Bot重启后内存中所有临时注册的collector会被全部回收,重启前发送的按钮消息没有对应的交互处理逻辑,点击后Discord收不到Bot的合法响应,就会提示interaction failed。

修复方案

移除命令回调内的临时collector逻辑,改用全局持久化的interactionCreate事件统一处理所有按钮交互,该监听需要在Bot启动阶段就完成注册,保证重启后能第一时间接收所有交互事件。
注意:所有交互必须在触发后3秒内返回响应,否则Discord会自动判定交互失败

第一步:注册全局交互监听

把以下代码放到Bot客户端初始化完成的入口位置,确保Bot启动就会加载这段逻辑:

// client为你初始化的discord.js客户端实例
client.on('interactionCreate', async (interaction) => {
    // 过滤非按钮类型交互,避免和斜杠命令、下拉菜单等其他逻辑冲突
    if (!interaction.isButton()) return

    const { customId } = interaction
    // 匹配对应按钮的自定义ID做分支处理
    switch(customId) {
        case 'Accept':
        case 'Tenative':
            console.log(`Button with id: ${customId} was pressed by ${interaction.user.username}`)
            await interaction.reply({
                content: `Button with id: ${customId} was pressed by ${interaction.user.username}`,
                ephemeral: true
            })
            break
        // 后续新增按钮直接在这里加case分支即可
    }
})

第二步:简化原斜杠命令逻辑

删除原命令里所有和collector相关的代码,仅保留发送按钮消息的逻辑即可,修改后代码如下:

import { MessageActionRow, MessageButton } from "discord.js";
import { ICommand } from "wokcommands";

export default {
    category: 'testing',
    description: 'Returns a Button',
    slash: true,
    testOnly: true,

    callback: async ({interaction:msgInt}) =>{
        const row = new MessageActionRow()
        .addComponents(
            new MessageButton()
            .setCustomId('Accept')
            .setEmoji('👍')
            .setLabel('ACCEPT')
            .setStyle('SUCCESS')
        )
        .addComponents(
            new MessageButton()
            .setCustomId('Tenative')
            .setEmoji('🤷‍♂️')
            .setLabel('TENATIVE')
            .setStyle('PRIMARY')
        )

        await msgInt.reply({
            content: 'Are you sure?',
            components: [row],
        })
    },
} as ICommand
避坑说明
  • 之前自行编写interactionCreate.ts不生效,优先检查两个点:一是监听事件是否绑定到了正确初始化完成的client实例上,不要在client实例创建完成前注册事件;二是是否缺少交互类型判断,把其他类型的交互(比如斜杠命令)误放到按钮逻辑里处理,导致代码抛错中断。
  • 如果按钮点击后的业务逻辑处理时间超过3秒,需要先调用await interaction.deferReply({ ephemeral: true })做响应占位,等逻辑处理完成后再用editReply发送最终内容,避免触发交互超时报错。
  • 如果担心不同功能的按钮customId冲突,可以给ID加前缀做命名空间,比如testing_Accept、testing_Tenative,监听时用前缀匹配对应功能模块的处理逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:54:26