0

I am trying to create a discord bot in python, and do an xp simulator like MEE6 or something. However, when I try and use what I currently have, I get an error. My current code is:

#A ton of imports
def unload_cache(file: str):
    return open("cache/" + file, "r").read()

def reload_cache(file: str, new):
    cache = open("cache/" + file, "w")
    cache.write(str(new))
    cache.close()

def add_xp(server_id, user_id, xp: int):
    dicts = unload_cache("server_xp.txt")
    try:
        data = dicts[server_id]
        try:
            data[user_id] = data[user_id] + xp
            dicts[server_id] = data
        except KeyError:
            data[user_id] = xp
            dicts[server_id] = data
    except:
        dicts[server_id] = {user_id:xp}
    reload_cache("server_xp.txt", dicts)

@bot.event
async def on_message(message):
    server_id = int(message.server.id)
    add_xp(server_id, message.author.id, 1)
    print(message.author.name + " gaind 1 xp at " + message.server.id)

To summerize this, it basically opens a file which has the dictionary {ServerID:{Player1ID:xp, Player2ID:xp, etc}, etc} and adds 1 xp every time someone talks. I have the multiple server ids for multi-server support. For some reason I get this exact error:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python36-32\lib\site-packages\discord\client.py", line 307, in _run_event
    yield from getattr(self, event)(*args, **kwargs)
  File "C:\Users\User\Python\Confusion Bot\bot.py", line 83, in on_message
    add_xp(server_id, message.author.id, 1)
  File "C:\Users\User\Python\Confusion Bot\bot.py", line 43, in add_xp
    dicts[server_id] = {user_id:xp}
IndexError: cannot fit 'int' into an index-sized integer
Ignoring exception in on_message
Traceback (most recent call last):
  File "C:\Users\User\Python\Confusion Bot\bot.py", line 35, in add_xp
    data = dicts[server_id]
IndexError: cannot fit 'int' into an index-sized integer
Orlando
  • 23
  • 1
  • 4
  • From what I can tell, your files contains a string representation of a dictionary. When you load it, you're getting a string. You need to parse that string in order to be able to index it as a dictionary, otherwise you're just indexing the string (to get a single character, though it sounds like your `server_id` int is too large). You might be able to fix the issue with `eval` (or better, `ast.literal_eval`), but a better fix would probably involve a better data format (like `json`, yaml, pickle or something). – Blckknght Aug 02 '18 at 18:15
  • @Blckknght what do you mean by `eval` or `ast.literal_eval` and I did switch it to json but get the same issue. I'm trying not to use pickle because I would like to be able to easily read the file and make changes within the normal editor. – Orlando Aug 02 '18 at 19:01
  • When you do `open("cache/" + file, "r").read()`, you get a string, not a dictionary. To convert the string to a dict, you could use `eval` (but `ast.literal_eval` is safer). – Blckknght Aug 02 '18 at 19:53
  • @Blckknght Thanks so much! This worked perfectly – Orlando Aug 02 '18 at 20:04
  • You should use `json.load` and `json.dump` and rework your dicts to use strings as keys. Have a look at what I'm doing [here](https://stackoverflow.com/questions/51146015/typeerror-object-of-type-textiowrapper-is-not-json-serializable/51146069#51146069). By only loading the dict once, during `on_ready` we avoid the situation of reading a potentially large file into a dict that is identical to a dict we already have. – Patrick Haugh Aug 02 '18 at 20:46

0 Answers0