Discord.py:用户无ban权限时发送提示而非报错的实现方案
解决Discord机器人Ban指令的权限错误提示问题
你当前用的@commands.has_permissions装饰器会直接抛出MissingPermissions异常,根本走不到你写的except逻辑里——因为异常是在命令执行前就触发的。要实现自定义提示,有两种实用思路,分情况给你说明:
一、手动检查权限(更灵活可控)
直接放弃@commands.has_permissions装饰器,在命令内部逐一检查所有权限场景,这样能精准控制每种情况的提示内容:
@bot.tree.command(name='ban', description='Ban a user. (w/ perms only)') async def ban(ctx, member: discord.Member, *, reason: str = "No reason provided"): # 检查发起命令的用户有没有ban权限 if not ctx.user.guild_permissions.ban_members: await ctx.response.send_message("你没有封禁成员的权限!", ephemeral=True) return # 检查机器人自己有没有ban权限 if not ctx.guild.me.guild_permissions.ban_members: await ctx.response.send_message("我没有封禁成员的权限,请给我分配对应权限!", ephemeral=True) return # 检查目标是不是管理员,或者权限等级比机器人高 if member.guild_permissions.administrator: await ctx.response.send_message("无法封禁管理员成员!", ephemeral=True) return if member.top_role >= ctx.guild.me.top_role: await ctx.response.send_message("我的权限等级不够,封不了这个成员!", ephemeral=True) return # 所有检查通过,执行封禁 try: await member.ban(reason=reason) await ctx.response.send_message(f"{member.name} 已被封禁,原因:{reason}") except Exception as e: await ctx.response.send_message(f"封禁失败:{str(e)}")
二、全局错误处理器(适合多命令场景)
如果想保留装饰器,可以给机器人加个全局错误捕获器,统一处理所有命令的权限异常:
# 全局错误处理函数 @bot.tree.error async def on_app_command_error(interaction: discord.Interaction, error: discord.app_commands.AppCommandError): if isinstance(error, discord.app_commands.MissingPermissions): await interaction.response.send_message("你没有执行这个命令的权限!", ephemeral=True) elif isinstance(error, discord.app_commands.BotMissingPermissions): await interaction.response.send_message("我权限不够,干不了这事!", ephemeral=True) elif isinstance(error, discord.Forbidden): await interaction.response.send_message("封不了这人,要么对方是管理员,要么我权限不够!", ephemeral=True) else: # 未知错误打日志,同时给用户提示 print(f"未知错误:{error}") await interaction.response.send_message("执行命令时出问题了!", ephemeral=True) # 带装饰器的原命令 @bot.tree.command(name='ban', description='Ban a user. (w/ perms only)') @discord.app_commands.checks.has_permissions(ban_members=True) @discord.app_commands.checks.bot_has_permissions(ban_members=True) async def ban(ctx, member: discord.Member, *, reason: str = "No reason provided"): try: await member.ban(reason=reason) await ctx.response.send_message(f"{member.name} 已被封禁,原因:{reason}") except discord.Forbidden: await ctx.response.send_message("无法封禁该成员,可能对方是管理员或我的权限不足!", ephemeral=True)
小提示
ephemeral=True:设置消息仅命令发起者能看到,避免打扰其他人- 手动检查时要按顺序来:先查用户权限,再查机器人权限,最后查目标成员的权限等级,确保所有边界情况都覆盖到
内容的提问来源于stack exchange,提问作者As2Bax
相关产品推荐
相关产品推荐

