pythonmongodbdiscord.pymotordriver

TypeError: '_asyncio.Future' object is not subscriptable, using async motor driver for mongodb


I have a code where I try to update a user's data whenever he posts a new message:

@bot.event
async def on_message(message):
    if isinstance(message.channel, discord.DMChannel):
        return
    collection = db[f"{message.guild.id}"]
    coll = db.guilds
    if message.author.bot:
        return
    else:
        if message.channel.id != 796145301013397544:
            if not await coll.count_documents({"_id": message.guild.id}):
                await coll.insert_one({"_id": message.guild.id, "suggest_channel": "None", "message_coins": 0.5, "log_channel": "None", 'prefix': '.', 'ignore_channel': 'None', 'likes': 0})
            message_coins = await coll.find_one({"_id": message.guild.id})["message_coins"]
            if not await collection.count_documents({"_id": message.author.id}):
                await collection.insert_one({"_id": message.author.id, "msg": 0, "happy": 0, "coins": 0, "badge": "Нет", "cookie": 0, "minvoice": 0, "color": 0xFFFFFF, "osebe": "Отсутствует", "age": "Неизвестно"})
            await collection.update_one({"_id": message.author.id}, {"$inc": {"msg": 1}})
            await collection.update_one({"_id": message.author.id}, {"$inc": {"coins": message_coins}})
        else:
            pass
    await bot.process_commands(message)
    asyncio.get_event_loop().run_until_complete(on_message(message))

but, when it is activated, I get an TypeError:

Ignoring exception in on_message
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.9/site-packages/discord/client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "/app/bot.py", line 187, in on_message
message_coins = await coll.find_one({"_id": message.guild.id})["message_coins"]
TypeError: '_asyncio.Future' object is not subscriptable

how can this TypeError be fixed?


Solution

  • Your issue here is in the nature that python will interpret this line of code

    message_coins = await coll.find_one({"_id": message.guild.id})["message_coins"]
    

    It will see as call the find_one method on the coll object, use subscript to get the "message_coins" element, then pass that object to await. However this is not what you actually want.

    message_coins = (await coll.find_one({"_id": message.guild.id}))["message_coins"]
    

    You need to use perenthesis to force the order of operations here. So by wrapping the await and the method call it tells python to pass that to await then once you get the final result back from the await call you then use subscript to locate the "message_coins" element.