如何在 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 拥有线稿上色优化、图片重绘、人物姿势检测、涂鸦完善等功能

相关推荐
三84410 分钟前
redis防御加固与安全基线
数据库·redis·安全·应急响应·防御
lhldsg10 分钟前
全民健身解决方案小程序开发:从0到1的技术实战
java·数据库·需求分析
泡海椒25 分钟前
内置SPI函数库详解:JQuick-Java Builtin工具类实战用法
java·开发语言·python
hqyjzsb34 分钟前
零 AI 项目经验,学 Python 转型 AI 的正确顺序是什么?
开发语言·人工智能·python·算法·职场和发展·数据挖掘·数据分析
IT大白鼠1 小时前
MySQL 分布式集群系列 · 第四篇——实操部署指南:从零搭建生产级 MySQL NDB 集群
数据库·分布式·mysql
IT大白鼠1 小时前
MySQL 分布式集群系列 · 第三篇——核心原理精讲:NDB 自动分片、多主写入与数据同步
数据库·分布式·mysql
Elastic 中国社区官方博客1 小时前
教程:使用 ES|QL 进行威胁狩猎
大数据·运维·数据库·elasticsearch·搜索引擎·全文检索·安全威胁分析
sanjiaomao3331 小时前
从论文公式到Python实现:用单元测试校验滑动平均算法
python·算法·单元测试
斑马1393 小时前
Linux软件编程学习笔记(十三)——数据库
数据库·oracle
初願致夕霞3 小时前
MySQL_索引
数据库·mysql