新闻中心
优化 Discord.py 视图中的交互检查逻辑

本文深入探讨了 `discord.py` 中 `discord.ui.View` 类的 `interaction_check` 方法的正确使用,以解决因过度限制导致部分按钮无法响应的问题。通过分析原始代码的逻辑缺陷,文章提供了一种分按钮定制交互检查的解决方案,确保不同功能按钮(如“确认”和“撤销”)能独立根据其业务逻辑(用户ID匹配或角色权限)进行权限验证,从而提升交互组件的灵活性和用户体验。
理解 discord.ui.View 和 interaction_check
在 discord.py 中,discord.ui.View 提供了一种构建交互式组件(如按钮、选择菜单)的方式,使其能够附加到消息上。View 类中的 interaction_check 方法是一个强大的工具,用于在任何组件的交互回调被触发之前,对交互进行全局性的预检查。如果 interaction_check 返回 False,则相应的组件回调将不会执行,并且可以向用户发送一条错误消息。
其基本作用是为视图中的所有组件定义一个通用的权限或条件。然而,不当的 interaction_check 逻辑可能导致某些按钮的功能被意外阻止,即使这些按钮在其自身的逻辑中包含了正确的权限检查。
遇到的问题:interaction_check 的过度限制
考虑以下场景:一个 View 包含“确认 (Acknowledge)”和“撤销 (Revoke)”两个按钮。
- “确认”按钮应仅由特定用户(通过 user_id 参数传入)点击。
- “撤销”按钮应仅由具有特定角色的用户点击。
原始的 interaction_check 实现如下:
async def interaction_check(self, interaction: discord.Interaction) -> bool:
userid = int(self.user_id)
if interaction.user.id == userid and interaction.data["custom_id"] == "acknowledge":
return True
else:
await interaction.response.send_message("你无权使用此按钮。", ephemeral=True)
return False此代码段的逻辑是:只有当交互用户ID与 self.user_id 匹配,并且 被点击的按钮 custom_id 为 "acknowledge" 时,才允许交互继续。否则,无论点击哪个按钮,都会发送一条错误消息并阻止交互。
Pinokio
Pinokio是一款开源的AI浏览器,可以安装运行各种AI模型和应用
232
查看详情
问题分析: 当用户点击“撤销”按钮时,interaction.data["custom_id"] 将是 "revoke"。此时,interaction.user.id == userid and interaction.data["custom_id"] == "acknowledge" 这个条件将评估为 False(因为 interaction.data["custom_id"] 不等于 "acknowledge")。因此,interaction_check 会立即返回 False,阻止“撤销”按钮的回调函数执行,即使“撤销”按钮内部有自己的角色检查逻辑。这就是导致“撤销”按钮无法工作的根本原因。
解决方案:分按钮定制 interaction_check 逻辑
为了解决这个问题,我们需要优化 interaction_check 的逻辑,使其能够区分不同的按钮,并应用相应的检查,或者在某些情况下允许交互通过,以便按钮自身的逻辑能够处理权限。
核心思想是:
- “确认”按钮: 仍然需要验证交互用户的ID是否与 self.user_id 匹配。
- “撤销”按钮: interaction_check 不应阻止它。它的角色权限验证应该在其自身的 @discord.ui.button 回调函数中处理。
以下是修改后的 MyView 类和 interaction_check 方法:
import discord from discord import Embed, app_commands from discord.app_commands import Choice class MyView(discord.ui.View): def __init__(self, user_id: str): super().__init__(timeout=None) # Consider adding a timeout self.user_id = user_id async def interaction_check(self, interaction: discord.Interaction) -> bool: """ 根据按钮的 custom_id 进行条件检查,以允许不同按钮执行其特定的权限逻辑。 """ button_custom_id = interaction.data.get("custom_id") # 对于 "acknowledge" 按钮,执行用户ID匹配检查 if button_custom_id == "acknowledge": if interaction.user.id == int(self.user_id): return True else: await interaction.response.send_message("你无权确认此消息。", ephemeral=True) return False # 对于 "revoke" 按钮,允许其通过 interaction_check, # 具体的角色权限检查将在其自身的异步回调函数中完成。 elif button_custom_id == "revoke": return True # 对于其他未明确处理的按钮,默认拒绝交互 else: await interaction.response.send_message("你无权使用此按钮。", ephemeral=True) return False @discord.ui.button(label="Acknowledge", emoji="<:check:1135773225423491122>", style=discord.ButtonStyle.grey, custom_id="acknowledge") async def menu1(self, interaction: discord.Interaction, button: discord.ui.Button): # 这里的 interaction_check 已经确保只有授权用户才能点击此按钮 new_embed = Embed.from_dict(interaction.message.embeds[0].to_dict()) new_embed.set_footer(text=f'Sent by {interaction.user.name} | Acknowledged: ✔') await interaction.response.edit_message(embed=new_embed) button.disabled = True await interaction.message.edit(view=self) @discord.ui.button(label="Revoke", emoji="<:Cross:1135773287880867900>", style=discord.ButtonStyle.grey, custom_id="revoke") async def menu2(self, interaction: discord.Interaction, button: discord.ui.Button): # interaction_check 允许此按钮的回调执行,现在在此处进行角色检查 user = interaction.guild.get_member(interaction.user.id) # 建议使用配置或环境变量存储角色ID,而非硬编码 role_headquarters_id = 994233392478560297 role_first_line_supervisors_id = 994233182532685825 role1 = discord.utils.get(interaction.guild.roles, id=role_headquarters_id) role2 = discord.utils.get(interaction.guild.roles, id=role_first_line_supervisors_id) # 确保角色存在,避免NoneType错误 if role1 and role2 and (role1 in user.roles or role2 in user.roles): await interaction.response.send_message(f"**惩罚已由 {interaction.user.mention} 撤销**", ephemeral=False) await interaction.message.delete() else: await interaction.response.send_message("你没有所需的角色来使用此按钮。", ephemeral=True) # 你的机器人命令部分 (保持不变) # @bot.tree.command(name="infract") # ... (省略,与问题内容相同)
代码解释:
- 在修改后的 interaction_check 中,我们首先获取被点击按钮的 custom_id。
- 如果 custom_id 是 "acknowledge",则执行原始的用户ID匹配逻辑。
- 如果 custom_id 是 "revoke",我们直接 return True。这意味着 interaction_check 不会阻止“
以上就是优化 Discord.py 视图中的交互检查逻辑的详细内容,更多请关注其它相关文章!
# 这就是
# 吉林电脑网站建设
# 花卉网站建设规划书
# seo推广如何做秒收录
# 南昌企业营销推广
# 四平网站优化软件
# 网站优化排名参数
# 网站优化设计色彩
# 企业网络营销推广成功的
# 东莞网站优化方法
# 丹东网站关键词推广
# 将是
# 相关文章
# 所需
# 编码
# 将在
# 是一个
# 自己的
# 使其
# 可用性
# 回调
# 权限验证
# 环境变量
# ai
# 工具
# 回调函数
# edge
# app
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
Pandas DataFrame 高效批量赋值:告别循环与笛卡尔积误区
2025俄罗斯Yandex最新入口 官方网站地址及浏览器下载指南
Angular Material 垂直步进器:实现底部到顶部排序的教程
Shopware订单对象中获取产品自定义字段的正确方法
React中useState与局部变量:理解组件状态管理与渲染机制
AO3中文官网链接_AO3网页版稳定镜像站
微信网页版官方入口直达 微信网页版网页版登录使用方法
漫蛙2网页版漫画入口 漫蛙漫画在线官方登录
Win11文件资源管理器卡顿怎么修 Win11重置资源管理器进程优化响应速度【修复方法】
文本文档写html代码怎么运行_文本文档html代码运行步骤【教程】
在Go Martini框架中高效服务动态生成图像的实践指南
优化HTML表单样式:解决输入框焦点跳动与元素间距问题
一加Ace 6T实拍样张首次公布!李杰:主摄实力完全看齐4K档性能旗舰
12306几点到几点不能订票? | 官方最新系统维护时间全解析
Golang并发任务中错误如何聚合_Golang goroutine error收集方式
Excel函数批量查找替换超快方法_Excel用REPLACE和FIND函数秒级替换
实现分段式页面滚动导航:CSS与J*aScript教程
win11如何卸载Windows更新补丁 Win11解决更新导致系统不稳定的问题【修复】
css子元素高度不一致导致布局错位怎么办_使用align-items:stretch解决高度差异
从J*aScript对象中精确提取指定属性的教程
微博网页版官方账号登录 微博网页版内容浏览使用指南
PPT平滑切换怎么做 PPT炫酷“平滑”切换动画制作教程【必学】
Go调试环境为何无法启动_Go调试器启动失败原因与解决策略
在Typer应用中优雅地处理和重组任意命令行参数
css卡片内容溢出如何处理_使用overflow隐藏或scroll显示内容
黑猫投诉统一入口官网 消费者权益保护投诉平台
Safari浏览器输入栏卡顿如何解决 Safari搜索建议与缓存清理
sublime如何优雅地处理行尾空格_sublime自动清理多余空白字符配置
痛风发作了怎么办? 快速止痛和后期饮食调理
夸克AO3官网入口_AO3镜像网站2025推荐
如何在Python中使用Optional类型处理可变对象并避免Pylint警告
《噬血代码2》新预告片发布 展示游戏剧情
网易大神账号申诉需要多久_网易大神账号申诉流程说明
sublime如何配置Go语言开发环境_sublime搭建Golang编译运行系统
msn官网入口地址手机版 msn官方网站手机最新链接
谷歌浏览器一键优化方案_谷歌浏览器直达主页极速不卡版
sublime怎么预览Markdown渲染效果_Markdown Preview插件 for sublime教程
Win11网速慢怎么解决 Win11网络设置优化解除限速
XML中包含HTML标签导致解析错误? 正确嵌入非XML数据的两种方法
飞书妙记怎样用语音转文字速记_飞书妙记用语音转文字速记【速记方法】
必由学登录入口 必由学官方网站在线访问链接
sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置
QQ邮箱登录首页官网地址2026 QQ邮箱官方网页入口
J*aScript类型检查_j*ascript代码规范
Golang如何使用new_Go new分配内存机制讲解
Windows电脑怎么截图最方便_系统自带截图工具的5种神仙用法【技巧】
KFC早餐时段怎么领特惠代码_KFC早餐订餐优惠代码获取与使用说明
天猫双十一预售商品怎么退款_天猫双十一预售退款操作指南
EMS快递官网app_中国邮政速递物流手机客户端
Eclipse怎么运行工程_Eclipse工程运行配置说明


2025-10-28
浏览次数:次
返回列表
i.View):
def __init__(self, user_id: str):
super().__init__(timeout=None) # Consider adding a timeout
self.user_id = user_id
async def interaction_check(self, interaction: discord.Interaction) -> bool:
"""
根据按钮的 custom_id 进行条件检查,以允许不同按钮执行其特定的权限逻辑。
"""
button_custom_id = interaction.data.get("custom_id")
# 对于 "acknowledge" 按钮,执行用户ID匹配检查
if button_custom_id == "acknowledge":
if interaction.user.id == int(self.user_id):
return True
else:
await interaction.response.send_message("你无权确认此消息。", ephemeral=True)
return False
# 对于 "revoke" 按钮,允许其通过 interaction_check,
# 具体的角色权限检查将在其自身的异步回调函数中完成。
elif button_custom_id == "revoke":
return True
# 对于其他未明确处理的按钮,默认拒绝交互
else:
await interaction.response.send_message("你无权使用此按钮。", ephemeral=True)
return False
@discord.ui.button(label="Acknowledge", emoji="<:check:1135773225423491122>", style=discord.ButtonStyle.grey, custom_id="acknowledge")
async def menu1(self, interaction: discord.Interaction, button: discord.ui.Button):
# 这里的 interaction_check 已经确保只有授权用户才能点击此按钮
new_embed = Embed.from_dict(interaction.message.embeds[0].to_dict())
new_embed.set_footer(text=f'Sent by {interaction.user.name} | Acknowledged: ✔')
await interaction.response.edit_message(embed=new_embed)
button.disabled = True
await interaction.message.edit(view=self)
@discord.ui.button(label="Revoke", emoji="<:Cross:1135773287880867900>", style=discord.ButtonStyle.grey, custom_id="revoke")
async def menu2(self, interaction: discord.Interaction, button: discord.ui.Button):
# interaction_check 允许此按钮的回调执行,现在在此处进行角色检查
user = interaction.guild.get_member(interaction.user.id)
# 建议使用配置或环境变量存储角色ID,而非硬编码
role_headquarters_id = 994233392478560297
role_first_line_supervisors_id = 994233182532685825
role1 = discord.utils.get(interaction.guild.roles, id=role_headquarters_id)
role2 = discord.utils.get(interaction.guild.roles, id=role_first_line_supervisors_id)
# 确保角色存在,避免NoneType错误
if role1 and role2 and (role1 in user.roles or role2 in user.roles):
await interaction.response.send_message(f"**惩罚已由 {interaction.user.mention} 撤销**", ephemeral=False)
await interaction.message.delete()
else:
await interaction.response.send_message("你没有所需的角色来使用此按钮。", ephemeral=True)
# 你的机器人命令部分 (保持不变)
# @bot.tree.command(name="infract")
# ... (省略,与问题内容相同)