Home > Net >  Trying to make a command to store and retreat info from a json file
Trying to make a command to store and retreat info from a json file

Time:11-24

Im trying to make a command that will store name,description and image of a character and another command to retrieve that data in an embed,but i have trouble working with json files

this is my code to add them:

    @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 = []

        #code checking the questions results

        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) == "✅" or "❌")
        try:
          reaction, user = await client.wait_for('reaction_add', timeout=1000.0, check=check)
        except asyncio.TimeoutError:
           #giving a message that the time is over
        else:
          if reaction.emoji == "✅":
            monsters = await get_skillsets_data() #this data is added at the end

            if str(monster_name) in monsters:
                await ctx.reply("the monster is already added")
            else:
                monsters[str(monster_name)]["monster_name"] = {}
                monsters[str(monster_name)]["monster_name"] = answers[0]
                monsters[str(monster_name)]["monster_description"] = answers[1]
                monsters[str(monster_name)]["monster_image"] = answers[2]

                with open('skillsets.json','w') as f:
                    json.dump(monsters,f)

                await mess.delete()
                await ctx.reply(f"{answers[0]} successfully added to the list")

Code to get the embed with the asked info:

            
    @client.command()
    async def skilltest(ctx,*,monster_name):
        data = open('skillsets.json').read()
        data = json.loads(data)
        if str(monster_name) in data:
          name = data["monster_name"]
          description = data["monster_description"]
          link = 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:
          # otherwise, it is still None meaning we didn't find it
          await ctx.reply("monster not found",mention_author=False)

and my json should look like this:

{"katufo": {"monster_name": "Katufo","Monster_description":"Katufo is the best","Monster_image":"#image_link"},
"armor claw":{"monster_name": "Armor Claw","Monster_description":"Armor claw is the best","Monster_image":#image_link}}

The get_skillsets_data used in first command:

async def get_skillsets_data():
    with open('skillsets.json','r') as f:
        monsters = json.load(f)

    return monsters

CodePudding user response:

Well, When you are trying to retrieve data from your json file try using name = data["katufo"]["monster_name"] now here it will only retrieve monster_name of key katufo. If You want to retrieve data for armor claw code must go like this name = data["armor claw"]["monster_name"]. So try this code :

@client.command()
async def skilltest(ctx,*,monster):
    data = open('skillsets.json').read()
    data = json.loads(data)
    if str(monster) in data:
      name = data[f"monster"]["monster_name"]
      description = data[f"monster"]["Monster_description"]
      link = data[f"monster"]["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:
      # otherwise, it is still None meaning we didn't find it
      await ctx.reply("monster not found",mention_author=False)

Hope this works for you :)

CodePudding user response:

If your json looks like what you showed above,

{
   "katufo":{
      "monster_name":"Katufo",
      "Monster_description":"Katufo is the best",
      "Monster_image":"#image_link"
   },
   "armor claw":{
      "monster_name":"Armor Claw",
      "Monster_description":"Armor claw is the best",
      "Monster_image":"#image_link"
   }
}

then there is no data["monster_name"] the two objects inside of your JSON are named katufo and armor_claw. To get one of them you can simply write data['katufo']['monster_name'] or data.katufo.monster_name.

Your problem stems from looking up the monster name like this:

 if str(monster_name) in data:
          name = data["monster_name"]
          description = data["monster_description"]
          link = data["monster_image"]

What you could do instead is loop through data, as it contains several monsters and then on each object, to the check that you do:

for monster in data:
    if str(monster_name) in monster.values():
        name = monster.monster_name
        description = monster.Monster_description
        link = monster.Monster_image

One thing to think about, the way the variables are named is not something I personally recommend. Don't be afraid of adding longer descriptive names so things make more sense for you in the code. Also, in the JSON you provided, there are certain attributes starting with a capital letter, something you should think about.

Edit: Dicts in python are the equivalent of objects in Javascript and are initialized using the same syntax which we can see below:

monster_data = {}

But since you want a specific structure on these monsters we can go further and create a function called add_monster_object():

def add_monster_object(original_dict, new_monster):
    
    new_monster = {
        "monster_name": '',
        "monster_description": '',
        "monster_image": '' 
    }

    #Now we have a new empty object with the correct names.
    
    return original_dict.update(new_monster)

Now every time you run this function with a given name, in the dict there will be an object with that name. Example is if user writes armor_sword as the monster_name attribute, then we can call the function above as add_monster_object(original_dict, monster_name). This will, if we take your initial dict as an example, return this:

{
   "katufo":{
      "monster_name":"Katufo",
      "Monster_description":"Katufo is the best",
      "Monster_image":"#image_link"
   },
   "armor claw":{
      "monster_name":"Armor Claw",
      "Monster_description":"Armor claw is the best",
      "Monster_image":"#image_link"
   },
   "armor sword":{
       "monster_name":"",
       "monster_description":"",
       "monster_image":""
   }
}

Then you can populate them as you want, or update the function to take more parameters. The important part here is that you take a minute and figure out what you want to keep saved. Then make sure that you can read and write from file and you should have a somewhat simple structure going. Warning: This isn't a slap and dry method, you will also have to think about special cases, such as adding an object that already exists and soforth.

If you decide to go with Replit you could use their database to create similar functionality but you wouldn't have to worry about reading and writing to a file.

As it is right now, I still think you need to proceed with your bot, add some of the changes that I mentioned before the next actual problem arrives as there are many things that arent quite right. I also suggest you break everything into managing parts, 1 would be to read from a file. 2 would be to write. 3 to write a dict to a file. 4 to update a dict and soforth. Good luck!

  • Related