Nextcord机器人开发:JSON存储读取怪物信息并生成Embed命令问题求解
Nextcord机器人怪物信息管理功能修复方案
现有代码存在的问题
- 变量未定义:
addskillset命令中判断怪物是否存在时使用的monster_name变量未提前声明,应该使用存储用户输入的answers[0]作为怪物名 - JSON写入逻辑错误:新增怪物时错误地先给内层字段
monster_name赋值空字典,正确写法是先给外层怪物名对应的键赋值空字典 - 反应校验逻辑错误:校验用户反应的
check函数判断条件写错误,原写法会让任意非作者用户的❌反应也能通过校验 - 数据读取逻辑错误:
skilltest命令中命中怪物后直接从外层JSON字典取属性,正确应该从对应怪物名的内层字典中读取属性 - 字段名不统一:预期JSON结构的描述、图片字段首字母大写,代码中使用的是全小写,会导致读取时找不到对应字段
- 文件操作不规范:
skilltest中读取文件后未主动关闭,缺少JSON文件不存在时的兜底处理
修复后的完整代码
前置依赖与工具函数
import nextcord from nextcord.ext import commands import json import asyncio client = commands.Bot(command_prefix="!", intents=nextcord.Intents.all()) # 修复工具函数,增加文件不存在的兜底处理 async def get_skillsets_data(): try: with open('skillsets.json','r', encoding='utf-8') as f: monsters = json.load(f) except FileNotFoundError: # 文件不存在时返回空字典 monsters = {} return monsters
新增怪物信息命令
@client.command() async def addskillset(ctx): await ctx.send("Let's add this skillset!") questions = ["What is the monster name?","What is the monster description?","what is the monster image link?"] answers = [] # 补充收集用户回答的逻辑(原代码缺失部分) for q in questions: await ctx.send(q) def check_msg(m): return m.author == ctx.author and m.channel == ctx.channel try: msg = await client.wait_for('message', timeout=120.0, check=check_msg) answers.append(msg.content) except asyncio.TimeoutError: await ctx.send("操作超时,已取消添加") return embedkra = nextcord.Embed(title = f"{answers[0]}", description = f"{answers[1]}",color=ctx.author.color) embedkra.set_image(url = f"{answers[2]}") mess = await ctx.reply(embed=embedkra,mention_author=False) await mess.add_reaction('✅') await mess.add_reaction('❌') # 修复反应校验逻辑 def check(reaction, user): return user == ctx.author and str(reaction.emoji) in ["✅", "❌"] try: reaction, user = await client.wait_for('reaction_add', timeout=1000.0, check=check) except asyncio.TimeoutError: await ctx.send("确认超时,已取消添加") else: if reaction.emoji == "✅": monsters = await get_skillsets_data() monster_name = answers[0].lower() # 统一用小写作为键,避免大小写不同导致重复添加 if monster_name in monsters: await ctx.reply("该怪物已存在") else: # 修复JSON写入逻辑,先给外层键赋值空字典 monsters[monster_name] = {} monsters[monster_name]["monster_name"] = answers[0] monsters[monster_name]["monster_description"] = answers[1] monsters[monster_name]["monster_image"] = answers[2] with open('skillsets.json','w', encoding='utf-8') as f: json.dump(monsters,f, ensure_ascii=False, indent=2) await mess.delete() await ctx.reply(f"{answers[0]} 已成功添加到列表") else: await mess.delete() await ctx.send("已取消添加操作")
查询怪物信息命令
@client.command() async def skilltest(ctx,*,monster_name): monsters = await get_skillsets_data() search_key = monster_name.lower() if search_key in monsters: # 修复取值逻辑,从对应怪物的内层字典取属性 monster_data = monsters[search_key] name = monster_data["monster_name"] description = monster_data["monster_description"] link = monster_data["monster_image"] embedkra = nextcord.Embed(title = f"{name}", description = f"{description}",color=ctx.author.color) embedkra.set_image(url = f"{link}") await ctx.reply(embed=embedkra,mention_author=False) else: await ctx.reply("未找到该怪物",mention_author=False)
额外优化说明
- 统一使用怪物名的小写形式作为JSON的键,避免用户输入大小写不同导致重复添加同一怪物
- 增加了JSON读写时的UTF-8编码指定,避免中文乱码
- 补充了原代码缺失的用户回答收集逻辑
- 增加了JSON文件不存在时的兜底处理,首次运行无需手动创建空文件
- 写入JSON时增加了缩进格式化,方便手动查看修改文件内容
内容的提问来源于stack exchange,提问作者RainbowGuy
相关产品推荐
相关产品推荐

