Search code examples
databasediscorddiscord.pytinydb

How to send only 1 variable from a set of 3 in TinyDB


[DISCORD.PY and TINYDB]

I have set up a warning system for Discord. If someone gets warned, the data is saved like so:

{'userid': 264452325945376768, 'warnid': 37996302, 'reason': "some reason"}

Problem of this: I want the command "!warnings" to display these warnings, but I don't want it to have this ugly formatting of a JSON, instead I want it to display like so:

{member} has {amount} warnings.
WARN-ID: {warning id here}
REASON: {reason here}

To do this, I need to somehow call only one variable at a time instead of having all 3 (as of above JSON) instantly.

My code is as follows:

@Ralf.command()
async def warnings(ctx, *, member: discord.Member=None):
    if member is None:
        member = Ralf.get_user(ctx.author.id)
        member_id = ctx.author.id
    else:
        member = Ralf.get_user(member.id)
        member_id = member.id
    WarnList = Query()
    Result = warndb.search(WarnList.userid == member_id)
    warnAmt = len(Result)
    if warnAmt == 1:
        await ctx.send(f"**{member}** has `{warnAmt}` warning.")
    else:
        await ctx.send(f"**{member}** has `{warnAmt}` warnings.")
        for item in Result:
            await ctx.send(item)

This code is working, but it shows the ugly {'userid': 264452325945376768, 'warnid': 37996302, 'reason': "some reason"} as output.

MAIN QUESTION: How do I call only userid without having warnid and reason displayed?

EDIT 1: Trying to use dicts results in following:

For that I get the following:

Ignoring exception in command warnings:
Traceback (most recent call last):
  File "C:\Users\entity2k3\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "c:\Users\entity2k3\Desktop\Discord Bots All\Entity2k3's Moderation\main.py", line 201, in warnings
    await ctx.send(f"WARN-ID: `{Result['warnid']}` REASON: {Result['reason']}")
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:\Users\entity2k3\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 903, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\entity2k3\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 859, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:\Users\entity2k3\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.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

Solution

  • You are getting the TypeError because your Result is a list of dictionaries.
    Make sure to iterate through Result and process each dictionary separately.
    Your Result object is like this [{}, {}, {} ...]

    Also you shouldn't capitalize the first letter of your variable. You should name it results, because it may contain more than 1 result.

    for item in results:
        user_id = item.get("userid")
        warn_id = item.get("warnid")
        reason = item.get("reason")
        # do stuff with those