当前位置: 首页 > news >正文

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

http://www.jsqmd.com/news/679956/

相关文章:

  • 隐写术渗透攻防全谱系解析:从 LSB 像素隐写到 AI 生成式隐写,原理・实战・防御・未来趋势
  • 别再只用summary-method算总计了!手把手教你用Element UI的el-table实现多行动态统计(含后端数据绑定)
  • 【独家首发】微软Build 2026内部泄露PPT节选:C# 14 AOT对Dify客户端冷启动耗时的影响建模(含真实POC数据集)
  • 手把手教你用Docker Compose在Ubuntu 22.04上部署LangSmith监控平台(含PostgreSQL+Redis+ClickHouse配置)
  • 2026冰袋生产厂家选购维度深度解析:冰袋生产厂家/大号加厚泡沫箱/生物医用泡沫箱/干冰配送/泡沫箱生产厂家/选择指南 - 优质品牌商家
  • iLQR vs DDP实战选型指南:自动驾驶场景下,到底该用哪个?
  • 2026 保姆级教程:4GB 显存微调 7B 大模型 LoRA 与 QLoRA 原理 + 完整代码 + 工业级部署
  • Python操作Minio避坑指南:从‘ImportError’到生产环境部署的8个常见问题
  • 企业AI转型最大的障碍是什么?
  • STM32F407上,用CubeMX和HAL库搞定FreeRTOS+FreeModbus从机(附环形队列优化串口)
  • 保姆级教程:用‘差分计数’这道题,彻底搞懂算法竞赛中的‘桶’与哈希表优化
  • AI 时代程序员必备:提示词工程高级技巧与实战模板全攻略(2026.4最新)
  • 如何分析enq- TM - contention_外键未建索引导致的表级锁阻塞
  • 从天线设计到声学分析:手把手教你用Python贝塞尔函数解决5个经典工程问题
  • 微积分基本定理实战:5个常见积分上限函数求导案例解析
  • 2026金属舵机选购指南:航模车模舵机/舵机云台/舵机公司/舵机厂家/舵机定制/舵机精度/转台舵机/转向能机/金属舵机/选择指南 - 优质品牌商家
  • 告别混乱提示!用SE91消息类统一管理你的SAP Fiori/ABAP程序用户交互
  • 海康iSC平台API对接门禁权限,别再乱调接口了!四种场景保姆级调用流程与避坑指南
  • 智能茅台预约系统:解放双手的自动化解决方案完全指南
  • 如何在响应式网页中精准居中表单(CSS绝对定位 + transform技巧)
  • 兔抗MLL1抗体亲和纯化,批次间稳定,低背景,高信噪比
  • 从战场到物流:多无人机路径规划中的A*、RRT和MPC到底该怎么选?
  • 从Victim Cache到CAM:深入ARM A78 CPU,看现代处理器如何‘抢救’Cache Miss
  • RTKLIB数据处理全流程实战:从观测文件下载到RTKPOST解算出图
  • 如何在 Go 方法中正确修改切片类型
  • 兔抗ASH2抗体亲和纯化,四平台验证,满足表观遗传学全流程需求
  • 别再乱设random.seed了!PyTorch模型可复现性实战指南(附完整代码)
  • 2026养虫室选型技术分享:低温型人工气候室、保鲜库、催芽室、全天候智能人工气候室、医药冷库、培养架型气候室、恒温恒湿库选择指南 - 优质品牌商家
  • Android应用保活完整指南:突破系统限制实现永久后台运行
  • 5分钟掌握:Blender 3MF格式完整导入导出终极指南