Discord二十一点机器人代码问题:重复弹窗与交互错误求助
Discord Blackjack Bot问题修复方案
问题1:重复发送Hit/Stand弹窗
常见原因
- Slash命令重复注册(全局+服务器级重复添加),导致命令触发时多次执行发送逻辑
- 命令处理函数中存在循环或重复调用发送Embed的代码
- 交互响应逻辑错误,比如多次调用
followUp()而非单次reply()
修复步骤
- 检查命令注册代码,确保只在全局或单个服务器注册一次,避免重复:
// 错误示例:重复注册会导致命令多次触发 await client.application.commands.create(blackjackCommand); // 全局注册 await guild.commands.create(blackjackCommand); // 服务器级注册,需移除其中一个
- 在命令处理中确保仅发送一次交互响应:
client.on('interactionCreate', async (interaction) => { if (!interaction.isChatInputCommand() || interaction.commandName !== 'blackjack') return; const hitStandEmbed = new Embed().setTitle('选择操作').setDescription('Hit 拿牌 / Stand 停牌'); const actionRow = new ActionRowBuilder().addComponents( new ButtonBuilder().setCustomId('blackjack_hit').setLabel('Hit').setStyle(ButtonStyle.Primary), new ButtonBuilder().setCustomId('blackjack_stand').setLabel('Stand').setStyle(ButtonStyle.Secondary) ); // 仅用一次reply发送初始弹窗,避免重复发送 await interaction.reply({ embeds: [hitStandEmbed], components: [actionRow] }); });
问题2:点击按钮报错「Cannot read properties of undefined (reading 'id')」
常见原因
- 按钮交互中访问了未定义的对象属性(比如
interaction.user未获取到,或游戏会话中玩家数据不存在) - 卡片生成逻辑返回
undefined,后续访问卡片id时出错 - 按钮自定义ID未正确绑定,导致处理逻辑中找不到对应数据
修复步骤
- 在按钮交互处理中添加对象存在性校验,使用可选链避免报错:
client.on('interactionCreate', async (interaction) => { if (!interaction.isButton()) return; // 先校验用户是否存在 const userId = interaction.user?.id; if (!userId) { return await interaction.reply({ content: '无法获取用户信息', ephemeral: true }); } // 校验游戏会话是否存在 const playerSession = blackjackSessions.get(userId); if (!playerSession) { return await interaction.reply({ content: '未找到你的游戏会话,请重新开始游戏', ephemeral: true }); } switch (interaction.customId) { case 'blackjack_hit': const newCard = drawCard(); // 校验卡片是否有效 if (!newCard?.id) { return await interaction.reply({ content: '发牌出错,请重试', ephemeral: true }); } playerSession.hand.push(newCard); // 更新弹窗内容 const updatedEmbed = new Embed().setDescription(`你的手牌:${playerSession.hand.map(c => `${c.rank}${c.suit}`).join(', ')}`); await interaction.update({ embeds: [updatedEmbed] }); break; case 'blackjack_stand': await interaction.update({ content: '已选择停牌,正在结算结果...', components: [] }); // 执行结算逻辑 break; } });
- 检查
drawCard()函数,确保返回包含id属性的有效卡片对象:
function drawCard() { const suits = ['♠', '♥', '♦', '♣']; const ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']; const randomSuit = suits[Math.floor(Math.random() * suits.length)]; const randomRank = ranks[Math.floor(Math.random() * ranks.length)]; // 确保返回包含唯一ID的对象 return { id: `${randomRank}-${randomSuit}-${Date.now()}`, rank: randomRank, suit: randomSuit }; }
内容的提问来源于stack exchange,提问作者Brennan Dean
相关产品推荐
相关产品推荐

