0

I'm writing a twitch chat bot in python with TwtichIO, then i decided to add some pokemon functionality after i found out there's a pokemon databse with a nice API and ended up using PokePy wrapper for PokeAPI. I have been hard-coding all my lookups(not sure that's the correct word) Like this for example:

@bot.command(name="type", aliases=['t'])
async def types2(ctx, *, msg):
    pokemon = pokepy.V2Client().get_pokemon(msg.lower())
    pokemon_type = ""
    for x in range(len(pokemon[0].types)):
        pokemon_type += pokemon[0].types[x].type.name
        pokemon_type += " "
    await ctx.channel.send(str(pokemon_type))

But when i got to finding out pokemon's weaknesses based on types, i found myself 3 layers deep into nested for loops and ifs, and knew i had to do more, just because i was hard-coding it. So i decided to try and find out how i can fetch the JSON file and parse it to a dict for easier access. I found out about the requests library. I think i have successfully used it but cannot manage to select the keys as needed. (i have used pprint() here to make reading easier) I will post like the first bit of the printed content because it's too long. (Full output is here: https://pastebin.com/tkYKRcqY)

@bot.command(name="weak", aliases=['t'])
async def weakness(ctx, *, msg):
    deals = {'4x': [], '2x': [], '1x': [], '0.5x': [], '0.25x': [], '0x': []}
    response = requests.get('https://pokeapi.co/api/v2/type/fire')
    pprint(response)
    fetch = response.json()
    pprint(fetch)
    # test = fetch[damage_relations][double_damage_from]

Output:

{'damage_relations': {'double_damage_from': [{'name': 'ground',
                                              'url': 'https://pokeapi.co/api/v2/type/5/'},
                                             {'name': 'rock',
                                              'url': 'https://pokeapi.co/api/v2/type/6/'},
                                             {'name': 'water',
                                              'url': 'https://pokeapi.co/api/v2/type/11/'}],

So essentially what i want is, to grab only the names from damage_relations-> double_damage_from -> and store each name as 2x in my dict. Same for damage_relations -> half_damage_from -> name etc.... The idea is to return to chat what is the pokemon weak to, which will be the information stored in the dict. (There is also about 95% of the data that this fetches that i do not need for this)

I have also tried using json.loads(fetch) as i was desperate, but it returned an error saying it doesn't expect dict as argument. Essentially my end goal is to put the correct damage values in the correct keys that i've created in the deals dictionary. Also there are some pokemon with multiple types, so for example if a pokemon has fire, ground as types i want to see if both of them will put the same type in the 2x key in deal dictionary, if they attempt to do so, i need to take out that type from 2x and place it in the 4x key.

I'm working blindly here, and it's possible that the answer is very simple, i honestly do not understand it and am trying to bruteforce my way though, since i really do not understand what's going wrong. If there is anything else that i need to provide as information please let me know.

YeYeeeeee
  • 17
  • 6

3 Answers3

1
  1. Let's clean up type2. Note that it still has a space at the very end. Either manually remove it or look into str.join.

    @bot.command(name="type", aliases=['t'])
    async def types2(ctx, *, msg):
        pokemon = pokepy.V2Client().get_pokemon(msg.lower())
        pokemon_type = ""
        for p_type in pokemon[0].types:
            pokemon_type += f"{p_type.name} "
        await ctx.channel.send(pokemon_type) # already a string
    
  2. Just stick with fetch. It's already the dict you want. You could use json.loads(response.text), but that's redundant.

  3. Also there are some pokemon with multiple types, so for example if a pokemon has fire, ground as types i want to see if both of them will put the same type in the 2x key in deal dictionary, if they attempt to do so, i need to take out that type from 2x and place it in the 4x key.

I suggest storing a pokemon's type(s) as a list (e.g. [fire], [fire, flying]). Let's say a pokemon's types are flying and rock. It'd have a 2x weakness and a 1/2 resistance against electric attacks. All you need to do is 2 * 1/2 == 1. If the attacking type is not present in the dict, just represent it as 1 (for no type shenanigans). To set the default, I suggest using dict.get.

HelixAchaos
  • 131
  • 1
  • 3
  • Thank you very much for the clarification on the first point, it's well appreciated! As far as 2 goes, the problem is (and i updated my original post as i realized i hadn't mentioned it) that i only need to fetch the 'names' key from 'double_damage_from', 'half_damage_from' and 'no_damage_from' from withing 'damage_relations'. That is what i'm unable to do. 3. The database provides the damage relations on a single type at a time, so i'm trying to fetch each type, and then store the weaknesses in my personal dict, and go from there for calculating 4x or 0.25x. – YeYeeeeee Aug 25 '21 at 19:18
  • So, you want `{'damage_relations': {'double_damage_from': ['ground', 'rock', 'water']}}`? `for effect, types in response['damage_relations'].items(): response['damage_relations'][effect] = [type['name'] for type in types]` – HelixAchaos Aug 26 '21 at 00:05
  • Not exactly, but it did lead me down the correct path of selecting the keys so i can store them in my own dictionary that i will be able to use for calculation and then can send back to the users in chat. Thank you very much @HelixAchaos – YeYeeeeee Aug 26 '21 at 12:14
0

What about using json module and json.loads(response.json()) You can review Python documentation or stackoverflow String to Dictionary in Python https://docs.python.org/3/library/json.html

Farfax
  • 3
  • 1
  • As i said in the beggning of the last paragraph, i have already trying to use json.loads(). I just tried it again, exactly as you suggested it, and this is the result: ```TypeError: the JSON object must be str, bytes or bytearray, not dict``` – YeYeeeeee Aug 25 '21 at 19:04
0

Here's a few answers for you that should work in terms of getting the JSON as you want it, starting at response.json():

import json
json.dump(response.json(), open('outfile.json', 'w+'), indent=4)

Additionally, if you wanted to just print the prettified JSON, you could do so by doing the following:

import json
print(json.dumps(response.json(), indent=4))

In terms of why json.load/loads doesn't work is because that is for loading JSON dicts from files or strings, so you're essentially trying to pull a dict object out of a dict object in your code. Hope this was helpful!