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
相关产品推荐
相关产品推荐

