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

discord.py中使用@commands.has_role无法限制机器人命令权限的问题

为什么@commands.has_role()在on_message事件里失效?

问题出在你用错了装饰器的适用场景——@commands.has_role()这类权限装饰器是discord.py专门为**命令框架(Command Framework)**设计的,也就是那些用@client.command()装饰的命令函数,它根本不会对on_message这种事件监听函数生效。

当你把它加在on_message上时,discord.py完全不会执行这个装饰器里的权限检查逻辑,自然不管用户有没有xrole,只要发了!set就能触发命令。

两种解决办法

方法1:改用discord.py命令框架(推荐)

这是最规范的写法,discord.py会帮你处理权限检查、参数解析、错误提示等一堆杂事,代码更简洁可靠:

@client.command()
@commands.has_role('xrole')  # 这里的装饰器会正常生效!
async def set(ctx, user_name: str, credit_add_amount: int):
    # 直接用框架解析好的参数,不用自己split了
    db[user_name] = credit_add_amount
    await ctx.send(f"{user_name} has been set with {credit_add_amount}. For further credit adjustment use !add")
  • 这里用户输入!set 用户名 100时,框架会自动把用户名和100解析成函数参数,还会自动检查参数类型(比如credit_add_amount必须是整数,否则会给用户发错误提示)。
  • 如果用户没有xrole,框架会自动返回权限不足的提示,不用你手动写逻辑。

方法2:坚持用on_message?手动检查角色

如果你一定要用on_message来监听命令,那就得自己手动实现角色检查逻辑:

@client.event
async def on_message(message):
    # 别忘了加这句,不然命令框架的其他命令会失效(如果有的话)
    await client.process_commands(message)
    
    if message.content.startswith("!set"):
        # 手动遍历用户的所有角色,检查是否存在xrole
        has_permission = any(role.name == 'xrole' for role in message.author.roles)
        if not has_permission:
            await message.channel.send("你没有执行这个命令的权限!")
            return
        
        # 处理参数(记得加异常判断,防止用户输入错误)
        credits_message = message.content.split(" ", 2)
        if len(credits_message) < 3:
            await message.channel.send("用法错误!请输入:!set <用户名> <积分数量>")
            return
        
        user_name = credits_message[1]
        try:
            credit_add_amount = int(credits_message[2])
        except ValueError:
            await message.channel.send("积分数量必须是整数哦!")
            return
        
        db[user_name] = credit_add_amount
        await message.channel.send(f"{user_name} has been set with {credit_add_amount}. For further credit adjustment use !add")
  • 注意:用角色名称检查可能会有大小写问题,比如服务器里的角色是XRole而不是xrole,就会检查失败。更可靠的方式是用角色ID检查:把role.name == 'xrole'改成role.id == 123456789012345678(换成你实际的角色ID)。

内容的提问来源于stack exchange,提问作者Yuvanesh Anand

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 07:04:11