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

discord.py如何为按钮添加权限,has_role装饰器对按钮不生效有什么替代方案?

失效原因

你现在用的@buttons.has_role是面向普通文本指令/Slash指令设计的权限装饰器,discord.py的按钮交互上下文和指令上下文结构不同,这类装饰器默认无法适配按钮场景,所以不会触发校验。

解决方案

方案1:直接在回调内校验(适合少量按钮场景)

直接在按钮回调函数开头加角色校验逻辑,写法简单无需额外封装:

import asyncio

@buttons.click
async def btn_close_yes(ctx):
    # 校验用户是否持有Admin角色
    is_admin = any(role.name == "Admin" for role in ctx.author.roles)
    if not is_admin:
        # ephemeral=True表示仅操作按钮的用户可见提示
        await ctx.reply("你没有权限执行该操作", ephemeral=True)
        return
    # 原有业务逻辑
    channel_close = ctx.channel
    await ctx.reply(":wastebasket: 频道将在3秒后删除 :wastebasket:")
    await asyncio.sleep(3)
    await channel_close.delete()

方案2:封装通用装饰器(适合大量按钮需要权限校验的场景)

你可以自己封装一个适配按钮交互的权限装饰器,后续用起来和原来的has_role用法完全一致:

# 先封装装饰器
def button_has_role(role_name: str):
    def decorator(func):
        async def wrapper(ctx, *args, **kwargs):
            if not any(role.name == role_name for role in ctx.author.roles):
                await ctx.reply("权限不足,无法操作", ephemeral=True)
                return
            return await func(ctx, *args, **kwargs)
        return wrapper
    return decorator

# 装饰器使用示例
@buttons.click
@button_has_role("Admin")
async def btn_close_yes(ctx):
    channel_close = ctx.channel
    await ctx.reply(":wastebasket: 频道将在3秒后删除 :wastebasket:")
    await asyncio.sleep(3)
    await channel_close.delete()

优化提示

如果要更高的稳定性,建议用角色ID代替角色名称做校验,避免后续角色改名导致校验失效,只需要把判断条件里的role.name == "Admin"替换成role.id == 你的角色数字ID即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 05:12:03