You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord机器人interaction_check致Revoke按钮失效问题求助

问题与解决方案

问题现象

启用interaction_check时,Revoke按钮完全无法工作;关闭该检查后,Revoke功能恢复正常。

需求:

  • Acknowledge按钮仅允许slash命令指定的违规用户(userid参数)触发
  • Revoke按钮仅允许拥有"Headquarters"或"First Line Supervisors"角色的用户触发

问题根源

原代码的interaction_check逻辑存在缺陷:仅当用户是指定违规用户且点击的是Acknowledge按钮时才返回True,所有其他情况直接返回False并发送统一的未授权提示。这导致点击Revoke按钮时,还没走到按钮自身的逻辑就被check拦截,直接返回未授权,自然无法正常工作。

修复方案

修改interaction_check,针对不同按钮的custom_id分别做权限校验,避免一刀切的拦截逻辑。同时可以把Revoke按钮的角色校验移到check中,让权限逻辑更集中:

class MyView(discord.ui.View):
    def __init__(self, user_id: str):
        super().__init__()
        self.user_id = user_id
        # 提前定义角色ID,避免重复查询
        self.role_ids = {994233392478560297, 994233182532685825}

    async def interaction_check(self, interaction: discord.Interaction) -> bool:
        custom_id = interaction.data.get("custom_id")
        # 处理Acknowledge按钮权限
        if custom_id == "acknowledge":
            target_user_id = int(self.user_id)
            if interaction.user.id == target_user_id:
                return True
            await interaction.response.send_message("你无权使用此按钮", ephemeral=True)
            return False
        # 处理Revoke按钮权限
        elif custom_id == "revoke":
            # 检查用户是否拥有指定角色
            user_roles = {role.id for role in interaction.user.roles}
            if self.role_ids & user_roles:
                return True
            await interaction.response.send_message("你没有使用此按钮的权限", ephemeral=True)
            return False
        # 其他未知按钮直接拦截
        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):
        new_embed = Embed.from_dict(interaction.message.embeds[0].to_dict())
        new_embed.set_footer(text=f'发送者: {interaction.user.name}     |     已确认: ✔')
        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完成,这里直接执行逻辑
        await interaction.channel.send(f"**处罚已被 {interaction.user.mention} 撤销**")
        await interaction.message.delete()

# 以下slash命令代码保持不变
@bot.tree.command(name="infract")
@app_commands.describe(userid = "被处罚用户ID")
@app_commands.describe(reason = "处罚原因")
@app_commands.describe(type = "选择处罚类型")
@app_commands.choices(type=[
    Choice(name='开除', value=1),
    Choice(name='降级', value=2),
    Choice(name='警告', value=3),
    Choice(name="拉黑", value=4),
    Choice(name="调查中", value=5)
])
@app_commands.describe(note = "备注信息(无则填N/A)")
@app_commands.describe(acknowledge = "是否添加确认按钮?")
@app_commands.choices(acknowledge=[
    Choice(name='是', value=1),
    Choice(name='否', value=2)
])
# 补充slash命令执行逻辑示例
async def infract(interaction: discord.Interaction, userid: str, reason: str, type: Choice[int], note: str, acknowledge: Choice[int]):
    embed = discord.Embed(title="处罚通知", description=f"用户ID: {userid}\n原因: {reason}\n类型: {type.name}\n备注: {note}", color=discord.Color.red())
    view = MyView(userid) if acknowledge.value == 1 else None
    await interaction.response.send_message(embed=embed, view=view)

关键修改点

  1. 拆分权限校验逻辑:针对两个按钮的custom_id分别做权限判断,避免统一拦截
  2. 集中权限逻辑:将Revoke按钮的角色校验移到interaction_check中,让代码更清晰,避免重复校验
  3. 避免重复响应:每个分支只在权限不通过时发送一次ephemeral消息,确保不会出现响应冲突
  4. 优化角色查询:提前定义角色ID集合,用集合交集判断用户是否拥有权限,比逐个遍历更高效

内容的提问来源于stack exchange,提问作者sac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:25:14