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

Discord.py 问题:答案逐步展示期间无法接收用户回答

Discord机器人问题:答案展示期间无法接收用户回答

我开发了一个简易Discord机器人,做了个功能:每隔2秒逐个字母展示答案,但现在有个问题——在答案完全展示完之前,机器人没法接收用户的回答。

完整代码

await ctx.send(a) # 发送问题
respuestas = b # 答案列表
# 逐个展示字母
string = respuestas[0]
blanked_string = [x if x.isspace() else "-" for x in string]
nonspace_indexes = [i for i, _ in enumerate(string)]
random.shuffle(nonspace_indexes)
for i in nonspace_indexes:
    blanked_string[i] = string[i]
    await ctx.send(''.join(blanked_string))
    await asyncio.sleep(2)
# 检查用户回答
def check(msg=discord.Message) -> True:
    return msg.content.lower() in respuestas and msg.channel == ctx.message.channel
try:
    guess = await bot.wait_for('message', timeout=6, check=check)
    return await ctx.send(f"{guess.author.mention} 第一个答对!")
except asyncio.TimeoutError:
    await ctx.send("时间到!")

问题原因

当前代码是同步执行的:先把整个字母展示循环跑完(每个步骤都等待2秒),才会执行bot.wait_for('message')开始监听用户输入。这就导致展示过程中用户发送的消息完全不会被机器人处理。

解决方案

用asyncio.create_task把字母展示逻辑做成异步任务,让它和用户输入监听逻辑并行运行,这样机器人在展示字母的同时,也能实时接收用户回答。

修改后的代码

import asyncio
import discord
import random

async def your_command(ctx, bot):
    await ctx.send(a)  # 发送问题
    respuestas = b  # 答案列表
    string = respuestas[0]
    blanked_string = [x if x.isspace() else "-" for x in string]
    nonspace_indexes = [i for i, _ in enumerate(string)]
    random.shuffle(nonspace_indexes)

    # 封装字母展示的异步函数
    async def reveal_letters():
        for i in nonspace_indexes:
            blanked_string[i] = string[i]
            await ctx.send(''.join(blanked_string))
            await asyncio.sleep(2)
        await ctx.send("字母展示完毕,最后6秒答题时间!")

    # 检查用户回答的函数,排除机器人自身消息
    def check(msg):
        return (msg.content.lower() in respuestas 
                and msg.channel == ctx.message.channel 
                and msg.author != bot.user)

    # 启动后台展示任务
    reveal_task = asyncio.create_task(reveal_letters())

    try:
        # 超时时间设为展示总时长 + 额外答题时间
        total_timeout = 2 * len(nonspace_indexes) + 6
        guess = await bot.wait_for('message', timeout=total_timeout, check=check)
        
        # 用户答对后立即终止展示任务
        reveal_task.cancel()
        await ctx.send(f"{guess.author.mention} 第一个答对!")
    except asyncio.TimeoutError:
        # 超时后终止未完成的展示任务
        if not reveal_task.done():
            reveal_task.cancel()
        await ctx.send("时间到!")
    finally:
        # 处理任务取消的异常,避免控制台报错
        try:
            await reveal_task
        except asyncio.CancelledError:
            pass

关键修改说明

  1. 异步任务并行:用asyncio.create_task启动字母展示任务,让它在后台独立运行,不阻塞用户输入监听
  2. 超时时间调整:把wait_for的超时时间设为展示总时长(2秒×字母数量)加上额外答题时间,覆盖整个交互流程
  3. 任务终止逻辑:用户答对或超时后,主动取消展示任务,避免机器人继续发送多余的字母消息
  4. 排除自身消息:检查函数中新增msg.author != bot.user,防止机器人把自己发送的展示消息误判为用户回答

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:08:31