Discord.py如何在pre-invoke钩子中阻止命令执行
Discord.py前置检查终止命令执行方案
discord.py的before_invoke钩子默认会忽略所有返回值,仅当钩子抛出继承自commands.CommandError的异常时,才会中断后续命令的执行流程,这是框架的设计行为,不属于bug。
自定义错误实现方案
你不需要只能使用内置错误类型,可以自定义专属的检查失败错误类,同时搭配全局错误处理钩子实现友好的用户提示,完整实现逻辑如下:
- 首先定义继承自
commands.CommandError的自定义错误类
from discord.ext import commands class PreCheckFailed(commands.CommandError): """自定义前置检查失败错误""" def __init__(self, message: str = "权限校验未通过,命令已终止"): super().__init__(message)
- 在
before_invoke钩子中按需求添加检查逻辑,未通过时直接抛出自定义错误即可终止命令
@client.before_invoke async def global_pre_check(ctx): # 示例检查:禁止黑名单用户调用命令 if ctx.author.id in [123456789, 987654321]: raise PreCheckFailed("你已被禁止使用 bot 命令") # 示例检查:仅允许在指定频道调用命令 if ctx.channel.id not in [1122334455, 5544332211]: raise PreCheckFailed("当前频道不允许使用 bot 命令")
- 在
on_command_error全局事件中捕获自定义错误,返回对应提示给用户
@client.event async def on_command_error(ctx, error): if isinstance(error, PreCheckFailed): await ctx.send(f"操作失败:{str(error)}", delete_after=5) # 跳过后续其他错误处理逻辑 return # 原有其他错误处理逻辑保留
单命令检查的轻量方案
如果你的检查逻辑仅针对单个/部分命令,不需要全局生效,可以直接使用commands.check()装饰器,装饰器返回False时会自动抛出CheckFailure错误终止命令执行:
# 自定义检查装饰器:仅管理员可调用 def admin_only(): async def predicate(ctx): return ctx.author.guild_permissions.administrator return commands.check(predicate) # 绑定到指定命令 @client.command() @admin_only() async def clear(ctx, num: int): await ctx.channel.purge(limit=num + 1) await ctx.send(f"已删除{num}条消息", delete_after=3)
Cog 内局部前置检查
如果使用Cog模块化管理命令,可以在Cog内定义cog_before_invoke钩子,作用范围仅限当前Cog内的命令,终止逻辑和全局钩子完全一致,抛出CommandError子类即可。
内容的提问来源于stack exchange,提问作者ConchDev
相关产品推荐
相关产品推荐

