List indices must be integers or slices, not str but the indices are integers

Question:

I am writing a script in python (with discord.py) to check if a user owns a gamepass on Roblox. This uses a simple API call, and JSON processes the response.

When I try to run the code, it gives me this error:

discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: list indices must be integers or slices, not str

I put int() around the things it’s mad about for not being a str, but no avail. Does anyone know what I’m doing wrong?

Sample API Call

{"previousPageCursor":null,"nextPageCursor":null,"data":[{"type":"GamePass","id":1234567,"name":"foo","instanceId":null}]}

Traceback

<Response [200]>
Ignoring exception in command foo:
Traceback (most recent call last):
  File "C:UsersREDAppDataLocalProgramsPythonPython310libsite-packagesdiscordextcommandscore.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "C:UsersREDDocumentsProgramsPythonfoo.py", line 110, in robux
    if int(response['data']['id']) == int(gamepassid):
TypeError: list indices must be integers or slices, not str

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:UsersREDAppDataLocalProgramsPythonPython310libsite-packagesdiscordextcommandsbot.py", line 939, in invoke
    await ctx.command.invoke(ctx)
  File "C:UsersREDAppDataLocalProgramsPythonPython310libsite-packagesdiscordextcommandscore.py", line 863, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:UsersREDAppDataLocalProgramsPythonPython310libsite-packagesdiscordextcommandscore.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: list indices must be integers or slices, not str

Full Code

#send a get request to https://users.roblox.com/v1/users/{robloxid} and set the response code to a variable
    response = requests.get(f'https://users.roblox.com/v1/users/{robloxid}')
    #if the response code is 200, set the response to a variable
    if response.status_code == 200:
        response = response.json()
        #send an embed to the channel with the response
        embed = discord.Embed(title=f'Welcome {response["name"]}.', description=f'We are now checking if you own the target gamepass, please wait...', color=discord.Color.from_rgb(125,165,101))
        await ctx.send(embed=embed)
        #get the gamepassid from products.json which equals the productid
        with open('products.json') as f:
            data = json.load(f)
            print("Loaded products.json")
        #create a list of products
        products = data['products']
        print (products)
        #for each product in the list of products
        for product in products:
            print("for loop")
            #if the productid equals the productid in the product
            if product['productid'] == int(productid):
                print ("if statement")
                #set the gamepassid to the gamepassid in the product
                gamepassid = product['gamepassid']
                print (gamepassid)
                #send a get request to https://inventory.roblox.com/v1/users/{robloxid}/items/GamePass/{gamepassid} and set the response code to a variable
                response = requests.get(f'https://inventory.roblox.com/v1/users/{robloxid}/items/GamePass/{gamepassid}')
                print (response)
                #if the response code is 200, set the response to a variable
                if response.status_code == 200:
                    response = response.json()
                    #if the response is true, send an embed to the channel that says you own the product
                    
                    #if id is in data[] equals gamepassid
                    if int(response['data']['id']) == int(gamepassid):
                        embed = discord.Embed(title=f'You own the product!', color=discord.Color.from_rgb(125,165,101))
                        await ctx.send(embed=embed)

                    #if the response is false, send an embed to the channel that says you do not own the product
                    else:
                        embed = discord.Embed(title=f'You do not own the product', color=discord.Color.from_rgb(255,0,0))
                        await ctx.send(embed=embed)
                #if the response code is not 200, send an embed to the channel that says there was an error
                else:
                    embed = discord.Embed(title=f'There was an error', color=discord.Color.from_rgb(255,0,0))
                    await ctx.send(embed=embed)
    #if the response code is 404, set the response to a variable
    elif response.status_code == 404:
        #user does not exist
        embed = discord.Embed(title='User does not exist', color=discord.Color.red())
        await ctx.send(embed=embed)
    else:
        #tell the user an error has occurred
        embed = discord.Embed(title='An error has occurred', color=discord.Color.red())
        await ctx.send(embed=embed)
Asked By: Stature Official

||

Answers:

Per the provided data, response["data"] is a list:

{
    "previousPageCursor": null,
    "nextPageCursor": null,
    "data": [
        {"type": "GamePass", "id": 1234567, "name": "foo", "instanceId": null}
    ]
}

So you should use response["data"][0]["id"] (which evaluates to an int, so using the int() call is superfluous).

Answered By: Jacob Lee
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.