Discord.js ban命令异常 交互报错与权限校验失效问题排查
问题排查结论
代码报错和逻辑失效全部来自以下编写错误:
- 校验逻辑未终止执行流:权限不足、封禁自身、目标用户无效三个校验分支触发后,没有加
return退出函数,代码会继续往下执行封禁逻辑,这也是无权限账号能封禁自己的核心原因 - 重复回复交互:因为校验分支没有return,多个分支都会调用
interaction.reply(),同一个交互只能回复一次,直接触发DiscordAPIError: Interaction has already been acknowledged报错 - 校验顺序错误:先判断
member === interaction.member,再判断member是否存在,当传入的用户不在服务器内时member为null,访问属性会直接抛错 - 缺少机器人权限校验:没有提前判断机器人自身是否拥有
BAN_MEMBERS权限,会触发missing permissions报错 - 空值访问风险:catch块里直接访问
member.user.tag,如果member为null会触发额外的JS运行时错误
修正后代码
const { Client, CommandInteraction, Message, MessageEmbed, MessageActionRow, MessageButton } = require('discord.js'); module.exports = { name: 'ban', description: 'Ban a user', options: [ { name: "user", description: "Choose the user to ban.", type: "USER", required: true }, { name: "reason", description: "reason for punishment", type: "STRING", required: false } ], run: async (client, interaction, options) => { const member = interaction.options.getMember("user") const reason = interaction.options.getString("reason") || "No reason given" // 校验执行用户权限 if(!interaction.member.permissions.has("BAN_MEMBERS")) { const embed = new MessageEmbed() .setColor("RED") .setDescription("❌ | You can't ban a user from the guild!") return interaction.reply({ embeds: [embed], ephemeral: true }) } // 校验目标用户是否存在 if (!member) { const embed = new MessageEmbed() .setColor("RED") .setDescription("❌ | Invalid Member") return interaction.reply({ embeds: [embed], ephemeral: true }) } // 校验是否封禁自己 if(member.id === interaction.member.id) { const embed = new MessageEmbed() .setColor("RED") .setDescription("❌ | You can't ban yourself") return interaction.reply({ embeds: [embed], ephemeral: true }) } // 校验机器人自身权限 if(!interaction.guild.me.permissions.has("BAN_MEMBERS")) { const embed = new MessageEmbed() .setColor("RED") .setDescription("❌ | I don't have permission to ban members!") return interaction.reply({ embeds: [embed], ephemeral: true }) } // 校验目标用户是否可被封禁(角色位阶高于机器人的情况) if(!member.bannable) { const embed = new MessageEmbed() .setColor("RED") .setDescription("❌ | I can't ban this user, please check my role position!") return interaction.reply({ embeds: [embed], ephemeral: true }) } try { await interaction.guild.bans.create(member, { reason }) const embed = new MessageEmbed() .setColor("GREEN") .setDescription(`✅ | ${member.user.tag} was banned for: ${reason}`) return interaction.reply({ embeds: [embed] }) } catch(err){ console.error(err) const embed = new MessageEmbed() .setColor("RED") .setDescription(`❌ | Failed to ban ${member.user.tag}`) // 兜底判断交互状态,避免重复回复报错 if(interaction.replied || interaction.deferred) { return interaction.followUp({ embeds: [embed], ephemeral: true }) } return interaction.reply({ embeds: [embed], ephemeral: true }) } } }
内容的提问来源于stack exchange,提问作者tryfyfu
相关产品推荐
相关产品推荐

