Cog-Creators / Red-DiscordBot

A multi-function Discord bot
https://docs.discord.red
GNU General Public License v3.0
4.81k stars 2.3k forks source link

[Config] Calling get_conf twice for the same instance corrupts the database #3136

Closed laggron42 closed 4 years ago

laggron42 commented 4 years ago

Other bugs

There is an issue when calling Config.get_conf two times for the same instance (from another cog or an eval). Both config instances will conflict, as I see, one isn't aware of what the other do, which means that if we do something with our second instance, the first one will be corrupted (didn't manage to recover my data after a restart).

What were you trying to do?

Edit a Config instance of a loaded cog with an eval command:

from redbot.core import Config
conf = Config.get_conf(None, 42, cog_name="whatever")
# here you can pretty much do anything, either reading or writing, the result will be the same
await conf.foo.set("no")
return await conf.bar()

What were you expecting to happen?

Read/write the value.

What actually happened?

The read/write is successful, but the cog's config instance will be corrupted, giving errors for pretty much anything related to config. Those errors are the most common:

Note: the key is the Red server's ID, trying to access conf.guild(ctx.guild) which was never called before (no data for that guild)

Traceback (most recent call last):
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\discord\ext\commands\core.py", line 79, in wrapped
    ret = await coro(*args, **kwargs)
  File "<string>", line 7, in readconf
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\redbot\core\config.py", line 477, in get_raw
    raw = await self.driver.get(identifier_data)
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\redbot\core\drivers\json.py", line 132, in get
    partial = partial[i]
KeyError: '363008468602454017'

Trying to get a random value

Traceback (most recent call last):
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\discord\ext\commands\core.py", line 79, in wrapped
    ret = await coro(*args, **kwargs)
  File "<string>", line 7, in readconf
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\redbot\core\config.py", line 477, in get_raw
    raw = await self.driver.get(identifier_data)
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\redbot\core\drivers\json.py", line 132, in get
    partial = partial[i]
KeyError: 'embed_description_user'

That one is probably the most common: attribute error on "Value" object

Traceback (most recent call last):
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\discord\ext\commands\core.py", line 79, in wrapped
    ret = await coro(*args, **kwargs)
  File "D:\OneDrive\Documents\Laggrons-Dumb-Cogs\warnsystem\settings.py", line 574, in warnset_settings
    modlog_channels = await self.api.get_modlog_channel(guild, "all")
  File "D:\OneDrive\Documents\Laggrons-Dumb-Cogs\warnsystem\api.py", line 518, in get_modlog_channel
    return await self.data.guild(guild).channels.all()
AttributeError: 'Value' object has no attribute 'all'

I got that one after calling conf.clear_all() with eval, then tried some commands

Traceback (most recent call last):
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\discord\ext\commands\core.py", line 79, in wrapped
    ret = await coro(*args, **kwargs)
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\redbot\cogs\customcom\customcom.py", line 347, in cc_list
    cc_dict = await CommandObj.get_commands(self.config.guild(ctx.guild))
  File "C:\Users\Laggron\AppData\Local\Programs\Python\Python37\lib\site-packages\redbot\cogs\customcom\customcom.py", line 48, in get_commands
    return {k: v for k, v in _commands.items() if _commands[k]}
AttributeError: 'NoneType' object has no attribute 'items'

Those errors occurs with future evals or the cog itself.

Most of those are from my WarnSystem cog. However, I tried with the core custom commands cog (see the steps I did below).

How can we reproduce this issue?

For breaking the core custom commands cog (tested on the dev build):

  1. Create a custom command and test it (did it on a fresh instance)

  2. Eval the following code:

    from redbot.core import Config
    c = Config.get_conf(None, 414589031223512, cog_name="CustomCommands")
    return await c.guild(guild).commands()

    Output on my side:

    {'hello': {'author': {'id': 348415857728159745, 'name': 'El Laggron#0260'}, 'command': 'hello', 'cooldowns': {}, 'created_at': '18/11/2019 09:18:21', 'editors': [], 'response': 'no'}}
  3. Try to invoke the custom command again, and see:

    Ignoring exception in on_message
    Traceback (most recent call last):
      File "c:\users\laggron\appdata\local\programs\python\python37\lib\site-packages\discord\client.py", line 270, in _run_event
        await coro(*args, **kwargs)
      File "c:\users\laggron\appdata\local\programs\python\python37\lib\site-packages\redbot\cogs\customcom\customcom.py", line 461, in on_message
        message=message, command=ctx.invoked_with
      File "c:\users\laggron\appdata\local\programs\python\python37\lib\site-packages\redbot\cogs\customcom\customcom.py", line 89, in get
        ccinfo = await self.db(message.guild).commands.get_raw(command, default=None)
    AttributeError: 'Value' object has no attribute 'get_raw'
Stonedestroyer commented 4 years ago

I can reproduce this on commit https://github.com/Cog-Creators/Red-DiscordBot/commit/b3363acf77e834a46e2948ea24feb38603a61ee2.

  1. a.customcom create laggron betterlaggron
  2. Eval command
    a.eval from redbot.core import Config
    c = Config.get_conf(None, 414589031223512, cog_name="CustomCommands")
    return await c.guild(guild).commands()
  3. Error
    Ignoring exception in on_message
    Traceback (most recent call last):
    File "/data/venv/lib/python3.7/site-packages/discord/client.py", line 270, in _run_event
    await coro(*args, **kwargs)
    File "/data/venv/lib/python3.7/site-packages/redbot/cogs/customcom/customcom.py", line 459, in on_message
    message=message, command=ctx.invoked_with
    File "/data/venv/lib/python3.7/site-packages/redbot/cogs/customcom/customcom.py", line 89, in get
    ccinfo = await self.db(message.guild).commands.get_raw(command, default=None)
    AttributeError: 'Value' object has no attribute 'get_raw'
PredaaA commented 4 years ago

Indeed I tested Laggron issue and I got exactly the same error. For context I am on same commit as @Stonedestroyer.