如何修复Discord机器人测验命令中的Embed字段必填报错("Ghost" Bug)
解决Discord科学测验机器人的Embed报错与无输出问题
错误原因分析
从你的报错信息和代码来看,问题出在两个核心点:
- 未处理所有问题场景:你的
questions1列表里只有第一个元素是有效问题,其他都是无效的名字字符串。当随机到索引1-6的元素时,questionNum != 0,导致你没有进入赋值answer、wrongAnswer1等变量的代码块,这些变量保持初始的空字符串""。更糟的是,只有questionNum == 0时你才会发送Embed,其他情况直接跳到等待用户输入的逻辑,所以用户完全看不到任何问题消息,误以为命令没输出。 - Embed字段空值问题:即使偶然进入
questionNum == 0的分支,若变量赋值逻辑出现空值(比如初始的空字符串),Discord API会拒绝请求,因为Embed的字段value不允许为空字符串——这就是你看到Invalid Form Body报错的原因。
修复方案与代码优化
我帮你重构了代码,解决了上述问题,同时让代码更易扩展和维护:
完整修复代码
import random import asyncio import discord from discord.ext import commands @client.command() async def quizintsci(ctx,*, unit): unit = int(unit) if unit == 1: # 结构化存储问题与答案,方便后续扩展更多题目 questions = [ { "question": "Which of these observations are qualitative observations?", "correct_answers": ["Luster", "Color", "Brightness", "Smoothness"], "wrong_answers": ["Time", "Price", "Height", "Weight", "Volume", "Density", "Percentage", "Ratio", "Money", "Statistics", "John weighs 90 pounds", "The volume of a sphere is 200cm^3", "There are 100 people living in this town", "Each class has 16 students", "Age", "Temperature"], "obviously_wrong": ["Dog", "X+Y=13", "I have a pencil case", "The camera took a picture", "I love english class", "Popcorn", "Microphone"] } # 在这里添加更多问题,格式和上面一致即可 ] # 随机选择一个问题 selected_question = random.choice(questions) question_text = selected_question["question"] # 随机抽取答案选项 correct = random.choice(selected_question["correct_answers"]) wrong1 = random.choice(selected_question["wrong_answers"]) wrong2 = random.choice(selected_question["wrong_answers"]) obv_wrong = random.choice(selected_question["obviously_wrong"]) # 构建选项列表并打乱顺序,避免固定正确选项位置 options = [("A", correct), ("B", wrong1), ("C", wrong2), ("D", obv_wrong)] random.shuffle(options) # 找到正确选项对应的字母 correct_letter = next(letter for letter, ans in options if ans == correct) # 创建Embed,用零宽空格(\u200b)代替空白字符串,避免空值报错 embed = discord.Embed(title="", description="", color=0xFFFFFF) embed.set_author(name="Science Question", url="https://youtube.com/fairopshotgun", icon_url="https://cdn.discordapp.com/emojis/859474000145154098.png?v=1") embed.add_field(name=question_text, value="\u200b", inline=False) # 循环添加选项字段,消除重复代码 for letter, answer in options: embed.add_field(name=f"{letter}: ", value=answer, inline=False) embed.set_footer(text='https://youtube.com/fairopshotgun', icon_url="https://media.discordapp.net/attachments/861325953191116813/895753939276931082/download.jpeg") # 发送问题Embed await ctx.reply(embed=embed, mention_author=False) # 定义检查函数:只接受命令发起者在当前频道输入的A/B/C/D def valid_response(msg): return msg.author == ctx.author and msg.channel == ctx.channel and msg.content.upper() in ["A", "B", "C", "D"] try: # 等待用户回答,超时时间30秒 user_response = await client.wait_for("message", check=valid_response, timeout=30.0) except asyncio.TimeoutError: await ctx.send(f"Time's up {ctx.author.display_name}! The correct answer was *{correct}* ({correct_letter}).") return # 判断答案是否正确并反馈 if user_response.content.upper() == correct_letter: await ctx.send(f"NO WAY! You got the question correct, {ctx.author.display_name}!") else: await ctx.send(f"RIP!! {ctx.author.display_name}, you got the question wrong! The correct answer was *{correct}* ({correct_letter}).")
关键修复点总结
- 结构化数据:把问题和对应的答案集合整理成字典,让逻辑更清晰,后续添加新题目只需复制字典格式即可。
- 避免空值:用零宽空格
\u200b代替空白字符串,既保持视觉空白,又符合Discord API对字段value非空的要求。 - 消除冗余代码:用
random.shuffle和循环代替大量重复的if-elif分支,降低出错概率,代码更易维护。 - 输入校验与超时:添加检查函数确保只有有效输入被处理,同时设置超时逻辑,避免机器人无限等待无效输入。
内容的提问来源于stack exchange,提问作者Ethan Twu Questioner
相关产品推荐
相关产品推荐

