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
相关产品推荐
相关产品推荐

