Discord.js如何在InteractionCreate事件中传参,实现按钮触发注册命令传递赛事名称
你要的功能完全可以实现,以下是具体修改方案:
方案1:按钮ID携带参数(推荐,实现简单)
Discord按钮的customId支持自定义字符串,你可以直接把赛事名称编码后拼接在ID中,点击触发交互时拆分ID即可拿到对应参数。
第一步:修改VIEW命令中按钮的customId配置
找到VIEW命令内创建各类按钮的代码段,将固定的customId改为「标识前缀+赛事名」的动态格式,示例如下:
// 注册按钮修改 const registerBTN = new Discord.MessageButton() // 用下划线作为分隔符,建议选择不会出现在赛事名称中的字符作为分隔符 .setCustomId(`registerBTN_${encodeURIComponent(tournament.name)}`) .setLabel('Register') .setStyle('PRIMARY'); // 其他需要关联赛事的按钮(取消注册、管理、删除按钮)都按这个规则修改customId const unregisterBTN = new Discord.MessageButton() .setCustomId(`unregisterBTN_${encodeURIComponent(tournament.name)}`) .setLabel('Unregister') .setStyle('DANGER');
用encodeURIComponent编码赛事名是为了避免赛事名里的特殊字符(如下划线、空格)影响后续拆分逻辑。
第二步:修改InteractionCreate事件代码
修正原有代码的错误,拆分customId获取赛事参数:
const BaseEvent = require('../utils/structures/BaseEvent'); module.exports = class InteractionCreate extends BaseEvent { constructor() { super('interactionCreate'); } async run(client, interaction) { if (!interaction.isButton() && !interaction.isSelectMenu()) return; // 拆分customId,获取操作类型和编码后的赛事名 const [action, encodedTournamentName] = interaction.customId.split('_'); const tournamentName = decodeURIComponent(encodedTournamentName); switch (action) { case 'registerBTN': const cmd = client.commands.get('register'); // interaction.message就是按钮所在的原消息,直接传给run方法的message参数 await cmd.run(client, interaction.message, [tournamentName]); // 如果你的REGISTER命令需要给点击按钮的用户返回提示,建议用interaction.reply,避免按钮交互超时 break; // 其他按钮的逻辑同理,根据action判断后执行对应命令即可 } } }
方案2:全局映射存储(适合参数过长场景)
如果需要传递的参数很多,超出了customId最多100字符的限制,可以用客户端全局对象存储消息ID和赛事信息的映射:
- 在VIEW命令发送完带按钮的消息后添加存储逻辑:
const sentMsg = await message.channel.send({embeds: [embed], components: [row]}); // 初始化全局映射表 client.tournamentMsgMap = client.tournamentMsgMap || new Map(); // 关联消息ID和赛事名 client.tournamentMsgMap.set(sentMsg.id, tournament.name);
- 在InteractionCreate事件中通过消息ID获取赛事名:
case 'registerBTN': const tournamentName = client.tournamentMsgMap.get(interaction.message.id); const cmd = client.commands.get('register'); await cmd.run(client, interaction.message, [tournamentName]); break;
如果需要机器人重启后映射依然有效,可以把映射关系存入数据库,关联消息ID和赛事信息即可。
注意:如果你的REGISTER命令需要获取点击按钮的用户身份,原有
message.author会返回调用VIEW命令的用户,而非点击按钮的用户,你可以修改REGISTER命令的run方法入参,增加interaction参数,或者直接把interaction.user作为补充参数传入即可。
内容的提问来源于stack exchange,提问作者Svartorm
相关产品推荐
相关产品推荐

