如何在 Discord.py 中限制按钮仅由特定角色用户点击

本文详解如何在 discord.py 的 discord.ui.Button 中实现基于角色的访问控制,通过运行时检查用户角色权限来动态启用或禁用按钮交互,而非错误地使用命令装饰器。 本文详解如何在 discord.py 的 `discord.ui.button` 中实现基于角色的访问控制,通过运行时检查用户角色权限来动态启用或禁用按钮交互,而非错误地使用命令装饰器。在 Discord.py 的 UI 系统(discord.ui.View / discord.ui.Button)中,@commands.has_role() 这类装饰器完全不适用------它仅作用于 commands.Bot 的命令上下文(如 @bot.command()),而按钮回调函数属于异步事件处理器,运行在 Interaction 上下文中,无命令权限系统介入。若强行添加该装饰器,不仅无效,还会导致运行时异常或静默失败。? 正确做法是:在按钮回调内部主动检查用户是否拥有指定角色,并根据结果决定是否执行业务逻辑;若权限不足,则调用 interaction.response.defer(ephemeral=True) 向用户返回不可见的响应(避免"此交互已过期"错误),并可选发送私密提示。以下是修正后的完整示例(含关键注释与健壮性增强):import discordfrom discord import ui, Interactionfrom datetime import datetime, timedeltaimport pytzimport timeclass SimpleView(discord.ui.View): def init(self): self.start_time = None self.stop_time = None super().init(timeout=None) @discord.ui.button(label="?? ENTRATA", style=discord.ButtonStyle.green, custom_id="btn_entrata") async def entrata(self, interaction: Interaction, button: ui.Button): # ? 检查用户是否拥有 "??♂? FUORI SERVIZIO" 角色(请替换为实际角色ID) target_role_id = 123456789012345678 # ← 替换为你的角色ID(整数!) role = interaction.guild.get_role(target_role_id) if not role or role not in interaction.user.roles: await interaction.response.send_message( "? 你没有权限使用此按钮:需拥有 `??♂? FUORI SERVIZIO` 角色。", ephemeral=True ) return # ? 权限通过:执行业务逻辑 orario_it = datetime.now(pytz.timezone('Europe/Rome')) orario = orario_it.strftime('%H:%M') data = orario_it.strftime('%Y-%m-%d') # 补充缺失的 data 变量定义 SimpleView.start_time = time.time() channel = interaction.client.get_channel(1214495527924928522) if not channel: await interaction.response.send_message("?? 目标频道不可用,请联系管理员。", ephemeral=True) return embed = discord.Embed(color=0x23a559) embed.set_thumbnail(url="https://shft.cl/img/c/cdn.discordapp.com-101395680655364460.webp") embed.add_field(name="?? ENTRATA ??", value="", inline=False) embed.add_field(name="NOME:", value=f"{interaction.user.mention}", inline=True) embed.add_field(name="", value="", inline=True) embed.add_field(name="DATA:", value=f"{data}", inline=True) embed.add_field(name="ORARIO:", value=f"{orario}", inline=True) embed.set_footer(text="ARMERIA200") await channel.send(embed=embed) await interaction.response.send_message( f"***SEI ENTRATO IN SERVIZIO ALLE: {orario}.***", ephemeral=True ) @discord.ui.button(label="?? USCITA", style=discord.ButtonStyle.red, custom_id="btn_uscita") async def uscita(self, interaction: Interaction, button: ui.Button): # ? 检查 "??♂? IN SERVIZIO" 角色(同样替换为真实ID) target_role_id = 987654321098765432 # ← 替换为你的角色ID role = interaction.guild.get_role(target_role_id) if not role or role not in interaction.user.roles: await interaction.response.send_message( "? 你没有权限使用此按钮:需拥有 `??♂? IN SERVIZIO` 角色。", ephemeral=True ) return # ? 执行退出逻辑 orario_it = datetime.now(pytz.timezone('Europe/Rome')) orario = orario_it.strftime('%H:%M') data = orario_it.strftime('%Y-%m-%d') if SimpleView.start_time is None: await interaction.response.send_message( "?? 你尚未执行'ENTRATA'操作,无法计算服务时长。", ephemeral=True ) return SimpleView.stop_time = time.time() elapsed_time = SimpleView.stop_time - SimpleView.start_time time_d = timedelta(seconds=int(elapsed_time)) channel = interaction.client.get_channel(1215061241270374400) if not channel: await interaction.response.send_message("?? 目标频道不可用,请联系管理员。", ephemeral=True) return embed = discord.Embed(color=0xda373c) embed.set_thumbnail(url="https://shft.cl/img/c/cdn.discordapp.com-101395680655364460.webp") embed.add_field(name="?? USCITA ??", value="", inline=False) embed.add_field(name="NOME:", value=f"{interaction.user.mention}", inline=True) embed.add_field(name="DATA:", value=f"{data}", inline=True) embed.add_field(name="ORARIO:", value=f"{orario}", inline=True) embed.add_field(name="TEMPO IN SERVIZIO:", value=f"{time_d}", inline=True) embed.set_footer(text="ARMERIA200") await channel.send(embed=embed) await interaction.response.send_message( f"***SEI USCITO DI SERVIZIO ALLE: {orario}, DOPO: {time_d}***", ephemeral=True )? 关键注意事项: 稿定AI 拥有线稿上色优化、图片重绘、人物姿势检测、涂鸦完善等功能

相关推荐
wu8587734573 分钟前
向量数据库不是银弹:从枚举漏检到 ReACT 多轮召回的实践路径
前端·数据库·react.js
MageGojo5 分钟前
基于 API Zero 平台集成 TTS 语音合成服务的技术实践
python·语音合成·tts·restful api·api集成
YsyaaabB30 分钟前
LangChain作业二---多语言翻译Prompt
开发语言·python·langchain
HappyAcmen31 分钟前
2.PDF长文档完整读取
python·pdf·rag
装不满的克莱因瓶32 分钟前
掌握感知器的学习原理
人工智能·python·神经网络·算法·ai·卷积神经网络
py小王子36 分钟前
Nature 期刊图复现|Python 实现双轴高维直方图与重叠分布图
python·nature·期刊图复现
hsg7738 分钟前
简述:Jensen Huang‘s Footsteps网站全内容分析
前端·javascript·数据库
yuezhilangniao39 分钟前
MySQL 8.0.32 二进制安装脚本 和初始化 操作系统版本rocky86
数据库·mysql·adb
小熊Coding40 分钟前
从零打造一款回合制 RPG 游戏:基于 Pygame 的《塔影守卫》全解析
python·游戏·计算机专业·pygame·rpg·2d游戏
Trouvaille ~1 小时前
【Redis篇】Redis 主从复制:数据同步的原理与实现
数据库·redis·缓存·中间件·高可用·主从复制·后端开发