You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py如何在pre-invoke钩子中阻止命令执行

Discord.py前置检查终止命令执行方案

discord.py的before_invoke钩子默认会忽略所有返回值,仅当钩子抛出继承自commands.CommandError的异常时,才会中断后续命令的执行流程,这是框架的设计行为,不属于bug。

自定义错误实现方案

你不需要只能使用内置错误类型,可以自定义专属的检查失败错误类,同时搭配全局错误处理钩子实现友好的用户提示,完整实现逻辑如下:

  1. 首先定义继承自commands.CommandError的自定义错误类
from discord.ext import commands

class PreCheckFailed(commands.CommandError):
    """自定义前置检查失败错误"""
    def __init__(self, message: str = "权限校验未通过,命令已终止"):
        super().__init__(message)
  1. 在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 命令")
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 19:39:02