Discord TS机器人点击按钮后禁用双按钮的实现问题
在TypeScript的Discord机器人中点击任意按钮后禁用所有按钮的实现方法
问题原因
你之前尝试的interaction.component.disabled;只是读取组件的禁用状态,并非修改操作。而且Discord组件的状态变更不能直接修改本地引用,必须通过更新消息的组件结构同步到Discord服务器端,所以这个语句不会生效。
解决思路
不管点击两个按钮中的哪一个,都需要执行以下步骤:
- 获取当前消息中的所有组件行(ActionRow)
- 遍历每个组件,将所有按钮类型的组件设置为
disabled: true - 调用
interaction.update()方法,把修改后的组件重新应用到消息上
具体实现代码
1. 按钮创建(warn.ts)
确保创建按钮时设置唯一的自定义ID,方便后续路由处理:
import { ButtonBuilder, ButtonStyle, ActionRowBuilder, SlashCommandBuilder, CommandInteraction } from 'discord.js'; export async function execute(interaction: CommandInteraction) { // 创建确认警告按钮 const confirmBtn = new ButtonBuilder() .setCustomId('warn_confirm') .setLabel('确认警告') .setStyle(ButtonStyle.Danger); // 创建取消按钮 const cancelBtn = new ButtonBuilder() .setCustomId('warn_cancel') .setLabel('取消') .setStyle(ButtonStyle.Secondary); // 组装成组件行 const buttonRow = new ActionRowBuilder<ButtonBuilder>().addComponents(confirmBtn, cancelBtn); // 发送带按钮的回复 await interaction.reply({ content: '确定要对该用户执行警告操作吗?', components: [buttonRow], ephemeral: true }); } export const data = new SlashCommandBuilder() .setName('warn') .setDescription('警告指定用户');
2. 取消按钮处理(cancel.ts)
在取消按钮的处理函数中实现禁用所有按钮的逻辑:
import { ButtonInteraction, ComponentType } from 'discord.js'; export async function handleCancelBtn(interaction: ButtonInteraction) { // 获取当前消息的所有组件 const originalComponents = interaction.message.components; // 遍历组件,禁用所有按钮 const updatedComponents = originalComponents.map(row => { return { ...row.toJSON(), components: row.components.map(component => { // 只处理按钮类型的组件 if (component.type === ComponentType.Button) { return { ...component.toJSON(), disabled: true }; } return component.toJSON(); }) }; }); // 更新消息,应用禁用后的组件 await interaction.update({ components: updatedComponents }); // 发送操作提示(可选) await interaction.followUp({ content: '操作已取消,所有按钮已禁用', ephemeral: true }); }
3. 确认按钮处理(可单独创建文件或整合到warn相关逻辑中)
在确认按钮的处理逻辑中,同样执行禁用所有按钮的操作:
import { ButtonInteraction, ComponentType } from 'discord.js'; export async function handleConfirmBtn(interaction: ButtonInteraction) { // 先禁用所有按钮 const originalComponents = interaction.message.components; const updatedComponents = originalComponents.map(row => { return { ...row.toJSON(), components: row.components.map(component => { if (component.type === ComponentType.Button) { return { ...component.toJSON(), disabled: true }; } return component.toJSON(); }) }; }); await interaction.update({ components: updatedComponents }); // 执行你的警告逻辑(比如添加警告记录、发送提示等) await interaction.followUp({ content: '已成功警告该用户', ephemeral: true }); }
4. 交互路由(interactionCreate.ts)
在主交互处理文件中,根据按钮自定义ID分发到对应处理函数:
import { Client, Interaction } from 'discord.js'; import { handleCancelBtn } from './cancel'; import { handleConfirmBtn } from './warn-confirm'; export function setupInteractionHandlers(client: Client) { client.on('interactionCreate', async (interaction: Interaction) => { // 只处理按钮交互 if (!interaction.isButton()) return; switch (interaction.customId) { case 'warn_cancel': await handleCancelBtn(interaction); break; case 'warn_confirm': await handleConfirmBtn(interaction); break; // 其他按钮的处理逻辑可添加在这里 } }); }
关键说明
- 必须使用
interaction.update()更新消息组件,而非直接修改本地组件对象,因为Discord的组件状态由服务器维护,本地修改无法同步过去。 - 如果是通过
interaction.followUp()发送的消息,需要改用interaction.editReply()来更新组件,具体需根据消息发送方式调整。
内容的提问来源于stack exchange,提问作者Zefut
相关产品推荐
相关产品推荐

