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

discord.py使用discord_components做商店按钮触发interaction failed问题

问题根因

你遇到的两个问题核心原因有3个:

  • 未及时响应Discord交互:Discord要求按钮点击事件触发后3秒内必须回应用户交互,你当前代码只监听了点击事件修改页码,完全没有对交互做响应,超过3秒就会触发“This interaction failed”报错,部分情况下还会阻塞消息编辑流程导致耗时变长。
  • 全局页码变量冲突:使用全局变量position_in_shop_items存储当前页码,多个用户同时调用商店命令时会互相篡改页码,甚至会触发索引越界报错拖慢运行速度。
  • 页码边界计算错误:列表索引从0开始,你当前用len(shop_items)作为最大页码判断条件,会出现索引越界问题,异常捕获后静默失败也会拉长运行耗时。

修复方案

  1. 每次获取到按钮点击响应后第一时间调用await response.respond()完成交互校验,避免超时报错
  2. 移除全局页码变量,将页码存储在当前命令的上下文变量中,避免多用户冲突
  3. 修正页码边界计算逻辑,最大合法页码为len(shop_items) - 1,加减页码时做边界限制
  4. 移除冗余的YAML加载逻辑,减少不必要的资源消耗

修复后核心代码示例

import yaml
import discord
from discord.ext import commands
from discord_components import DiscordComponents, Button, ButtonStyle
from pymongo import MongoClient

# 优化后的物品加载逻辑,提前仅加载一次,不用每次调用命令重复加载
with open('items.yaml', 'r') as yaml_file:
    item_list_yaml = yaml.safe_load(yaml_file)
shop_items = []
for item_id, item_info in item_list_yaml.items():
    shop_items.append({
        'name': item_info['name'],
        'buy_price': item_info['buy_price'],
        'amount': item_info['amount'],
        'sell_price': item_info['sell_price'],
        'item_id': item_id,
        'emoji': item_info['emoji'],
    })

class Shop(commands.Cog):
    def __init__(self, client):
        self.client = client
        self.cluster = MongoClient(DB)
        self.collection = self.cluster.users.eco
        DiscordComponents(client)
    
    @commands.command(name="shop")
    async def main_shop(self, ctx):
        # 把页码存在当前命令的局部变量里,不全局共享
        current_page = 0
        max_page = len(shop_items) - 1

        # 生成embed的公共方法抽离,减少重复代码
        def generate_embed(page):
            item = shop_items[page]
            desc = f"{item['emoji']}**{item['name']}**\n"
            if item['buy_price'] is not None:
                desc += f"**Buy Price: `{item['buy_price']}`<:coins:872444592115568661>**\n"
            if item['sell_price'] is not None:
                desc += f"**Sell Price: `{item['sell_price']}`<:coins:872444592115568661>**"
            return discord.Embed(title="Shop", description=desc)
        
        # 生成按钮的公共方法
        def generate_buttons(page):
            buttons = []
            if page > 0:
                buttons.append(Button(style=ButtonStyle.grey, label="<-", custom_id="prev"))
            if page < max_page:
                buttons.append(Button(style=ButtonStyle.grey, label="->", custom_id="next"))
            return [buttons]
        
        # 首次发送商店消息
        current_embed = generate_embed(current_page)
        current_buttons = generate_buttons(current_page)
        shop_msg = await ctx.send(embed=current_embed, components=current_buttons)

        while True:
            # 只监听当前消息的按钮点击,避免其他用户的按钮点击触发当前逻辑
            try:
                response = await self.client.wait_for(
                    "button_click",
                    check=lambda i: i.message.id == shop_msg.id and i.user == ctx.author,
                    timeout=60 # 加超时自动退出,避免资源占用
                )
            except:
                # 超时后禁用按钮,结束逻辑
                await shop_msg.edit(components=[])
                return
            
            # 第一时间响应交互,避免超时报错
            await response.respond(type=6) # type=6是无感知响应,不会弹额外消息

            # 处理页码变更
            if response.custom_id == "next" and current_page < max_page:
                current_page += 1
            elif response.custom_id == "prev" and current_page > 0:
                current_page -= 1
            
            # 更新消息内容
            new_embed = generate_embed(current_page)
            new_buttons = generate_buttons(current_page)
            await shop_msg.edit(embed=new_embed, components=new_buttons)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 06:06:06