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

Discord机器人wait_for与按钮功能失效问题排查求助

问题修复方案

核心错误点

  • 重复创建客户端实例:你在main.py中同时创建了bot = commands.Bot(...)和client = discord.Client()两个独立的客户端实例,实际调用bot.run()启动的是bot实例,但halloween.py中监听按钮事件用的是从未启动的main.client,自然收不到任何按钮点击事件。
  • 未初始化discord-components库:discord-components需要绑定到运行的bot实例才能接收组件事件,你没有做初始化操作。
  • 使用同步阻塞的sleep:time.sleep是同步方法,会阻塞整个异步事件循环,导致后续的事件监听逻辑无法正常运行,应该替换为异步的asyncio.sleep。
  • 存在未定义变量:代码中发送消息时引用了未定义的there_embed变量,会直接抛出异常导致逻辑中断。
  • wait_for逻辑的check规则不合理:你当前的check只判断了频道,没有判断按钮ID,可能会捕获到其他同频道的按钮点击事件,同时死循环的逻辑也没有退出条件,会导致内存泄漏。

具体修复步骤

1. 修改main.py

删除多余的client实例声明,初始化discord-components绑定到bot实例

import json
import random
import discord
from discord.ext import commands
from discord_components import DiscordComponents

INITIAL_EXTENSIONS = [
    "cogs.default",
    "cogs.halloween"
]

bot = commands.Bot(command_prefix="can ")
bot.remove_command("help")

# 初始化discord-components,绑定到运行的bot实例
@bot.event
async def on_ready():
    DiscordComponents(bot)
    print(f"登录成功:{bot.user}")

def percentage(percentage):
    raw = []
    for x in range(percentage):
        raw.append(1)
    for y in range(100 - percentage):
        raw.append(0)
    selected = random.choice(raw)
    return selected == 1

def read_JSON(filename):
    with open(filename, "r") as f:
        return json.load(f)

for extension in INITIAL_EXTENSIONS:
    try:
        bot.load_extension(extension)
    except Exception as e:
        print('Failed to load extension {}\n{}: {}'.format(extension, type(e).__name__, e))

if __name__ == '__main__':
    bot.run(read_JSON("data.json")["TOKEN"])

2. 修改halloween.py

替换事件监听实例,修复阻塞问题,补全缺失变量,优化事件逻辑

import random
import asyncio
import discord
from discord.ext import commands
from discord_components import *

import main

class Halloween(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def checkdoor(self, ctx):
        someonethere = main.percentage(100)
        await ctx.channel.send("Seeing if anyone is at the door...")
        # 替换为异步sleep避免阻塞事件循环
        await asyncio.sleep(random.randint(1, 2))
        if someonethere:
            give = Button(style=ButtonStyle.blue, label="Give", id="result")
            # 补充定义缺失的there_embed变量
            there_embed = discord.Embed(title="有人在门口!", description="点击下方Give按钮送出礼物", colour=discord.Colour.green())
            result = discord.Embed(title=f"You gave!", description="Description", colour=discord.Colour.blue())

            await ctx.reply(
                embed=there_embed,
                components=[
                    [give]
                ]
            )

            buttons = {
                "result": result
            }
            # 优化check规则,同时校验频道和按钮ID
            def check(interaction):
                return interaction.channel == ctx.channel and interaction.component.id in buttons.keys()

            try:
                # 添加60秒超时,避免一直等待占用资源
                event = await self.bot.wait_for("button_click", check=check, timeout=60)
                response = buttons.get(event.component.id)
                await event.respond(
                    type=4,
                    embed=response
                )
            except asyncio.TimeoutError:
                await ctx.send("操作超时,按钮已失效,请重新执行命令")
                return

        else:
            embed = discord.Embed(
                title="Nope",
                description="No one's there at your door. Try again later..."
            )
            return await ctx.reply(embed=embed)

def setup(bot):
    bot.add_cog(Halloween(bot))

额外建议

discord-components库已经停止维护,如果你使用的是discord.py v2.0及以上版本,框架原生已经支持按钮、下拉菜单等交互组件,可以直接使用原生接口实现功能,无需额外依赖第三方库,稳定性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:15:03