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

discord.py计算器机器人按钮交互提示This interaction failed修复求助

Discord计算器机器人交互失败修复方案

核心错误点

  • 事件名拼写错误:discord-components库的按钮点击事件名为button_click,原代码写为button click(空格错误)
  • 死循环阻塞逻辑:原代码写了独立的while True: res = await client.wait_for("button click")死循环,后续处理逻辑完全无法执行
  • 表达式替换逻辑错误:calculator函数中替换乘号后,第二次替换除号依然使用原始字符串,导致乘号替换失效
  • Embed标题缺少用户ID标识:原代码校验用户身份时尝试从Embed标题拆分|后的用户ID,但初始化Embed时根本没有写入该信息,会触发类型转换报错
  • 按钮输入逻辑错误:普通数字/运算符按钮点击后直接覆盖表达式,而非拼接内容,不符合计算器使用逻辑
  • 响应参数拼写错误:res.respond时传递的组件参数为component,正确参数名为components
  • 超时逻辑错误:原代码判断m.created_at < delta永远为真,循环不会自动超时退出,应该判断当前时间是否小于超时时间
  • 缺少消息内容意图配置:新版discord.py要求显式开启message_content意图,否则前缀命令无法触发
  • 未校验交互归属:没有判断当前点击的按钮是否属于当前计算器实例,也没有对非发起者的操作做单独响应,会触发交互超时

修正后完整代码

import discord
import os
from discord.ext import commands, tasks
from online import keep_alive
from discord_slash import SlashCommand
from itertools import cycle
from discord_components import *
import datetime

# 显式声明intents
intents = discord.Intents.default()
intents.message_content = True
client = commands.Bot(command_prefix="!", intents=intents)

slash = SlashCommand(client, sync_commands=True)

status = cycle([
    " Unanswered Question of Life", " Self - Referential Paradox",
    " Near-infinite density?", " Dark matter ?",
    " Measurement of the speed of light in one straight line",
    " Schrodinger's cat ???",
    "The light side of Discord is the path of many unnatural abilities"
])


@client.event
async def on_ready():
    print("I have logged in as {0.user}".format(client))
    status_swap.start()
    DiscordComponents(client)


buttons = [[
    Button(style=ButtonStyle.grey, label='1'),
    Button(style=ButtonStyle.grey, label='2'),
    Button(style=ButtonStyle.grey, label='3'),
    Button(style=ButtonStyle.blue, label='+'),
    Button(style=ButtonStyle.red, label='Clear')
],
[
    Button(style=ButtonStyle.grey, label='4'),
    Button(style=ButtonStyle.grey, label='5'),
    Button(style=ButtonStyle.grey, label='6'),
    Button(style=ButtonStyle.blue, label='-'),
    Button(style=ButtonStyle.red, label='Exit')
],
[
    Button(style=ButtonStyle.grey, label='7'),
    Button(style=ButtonStyle.grey, label='8'),
    Button(style=ButtonStyle.grey, label='9'),
    Button(style=ButtonStyle.blue, label='×'),
    Button(style=ButtonStyle.red, label='←')
],
[
    Button(style=ButtonStyle.grey, label='00'),
    Button(style=ButtonStyle.grey, label='0'),
    Button(style=ButtonStyle.grey, label='.'),
    Button(style=ButtonStyle.blue, label='÷'),
    Button(style=ButtonStyle.red, label='=')
]]


def calculator(exp):
  o = exp.replace('×', '*')
  o = o.replace('÷', '/')
  try:
    result = str(eval(o))
  except:
    result = "An error occurs"
  return result


@client.command()
async def operator(ctx):
  m = await ctx.send(content="Loading calculator")
  expression = ""
  delta = datetime.datetime.utcnow() + datetime.timedelta(minutes = 5)
  # 标题加入用户ID用于后续校验
  e = discord.Embed(title=f"Basic Operation Calculator | {ctx.author.id}",description=expression)
  await m.edit(content="", components=buttons, embed=e)
  # 合并循环逻辑,避免死循环
  while datetime.datetime.utcnow() < delta :
    res = await client.wait_for("button_click")
    # 先判断是否是当前计算器的点击
    if res.message.id != m.id:
      continue
    # 判断是否是发起者操作
    if res.author.id != ctx.author.id:
      await res.respond(content="你不是该计算器的发起者,无法操作", ephemeral=True)
      continue
    expression = res.message.embeds[0].description
    if expression == 'An error occurs':
      expression = ''
    if res.component.label == 'Exit':
      await res.respond(content='Calculator Closed. Thanks for using Basic Operation Calculator.',type=7, components=[])
      break
    elif res.component.label == "←":
      expression = expression[:-1]
    elif res.component.label == 'Clear':
      expression = ''
    elif res.component.label == '=':
      expression = calculator(expression)
    else:
      # 拼接输入内容而非覆盖
      expression += res.component.label
    f = discord.Embed(title=f'Basic Operation Calculator | {ctx.author.id}',description=expression)
    await res.respond(content='', embed = f, components=buttons, type=7)
  # 超时后禁用按钮
  else:
    await m.edit(components=[[Button(style=ButtonStyle.grey, label=b.label, disabled=True) for b in row] for row in buttons])
    await ctx.send("计算器已超时关闭")

@tasks.loop(minutes=5)
async def status_swap():
  await client.change_presence(activity=discord.Game(next(status)))


keep_alive()
client.run(os.getenv('MATH_VAR'))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:12:03