@user1324

Почему обработчик команды в discordpy срабатывает перед on_ready?

код
import discord
from discord.ext import commands
from discord.utils import get
from config import settings
import json
import sys
import random
import asyncio
import sqlite3
import random
from random import randint
import requests
from PIL import Image, ImageFont, ImageDraw
import io
import pandas
import interaction

client = commands.Bot(command_prefix=settings['PREFIX'], intents=discord.Intents.all())
client.remove_command('help')

connection = sqlite3.connect('server.db')
cursor = connection.cursor()
last_work_time = 0


@client.event
async def on_ready():
    cursor.execute("""CREATE TABLE IF NOT EXISTS users (
 name TEXT,
 id INT,
 cash BIGINT,
 rep INT,
        lvl INT,
        server_id INT
    )""")

    cursor.execute("""CREATE TABLE IF NOT EXISTS shop (
        role_id INT,
        id INT,
        cost BIGINT
    )""")

    for guild in client.guilds:
        for member in guild.members:
            if cursor.execute(f"SELECT id FROM users WHERE id = {member.id}").fetchone() is None:
                cursor.execute(f"INSERT INTO users VALUES ('{member}', {member.id}, 0, 0, 1, {guild.id})")
            else:
                pass

    connection.commit()
    print('client connected')


@client.event
async def on_member_join(member):
    if cursor.execute(f"SELECT id FROM users WHERE id = {member.id}").fetchone() is None:
        cursor.execute(f"INSERT INTO users VALUES ('{member}', {member.id}, 0, 0, 1, {member.guild.id})")
        connection.commit()
    else:
        pass
@client.command(aliases=['leaderboard', 'lb'])
async def __leaderboard(ctx):
    img = Image.new('RGBA', (680, 745), '#FFD700')
    embed = discord.Embed(title='Топ 10 сервера')
    counter = 0
    x = 0
    for row in cursor.execute("SELECT user_id, lvl FROM users WHERE server_id = {} ORDER BY cash DESC LIMIT 10".format(ctx.guild.id)):
        counter += 1
        member = ctx.guild.get_member(row[0])
        url = str(member.avatar_url)
        response = requests.get(url, stream=True)
        response = Image.open(io.BytesIO(response.content))
        response = response.convert('RGBA')
        response = response.resize((68, 68), Image.ANTIALIAS)

        img.paste(response, (0, x))

        idraw = ImageDraw.Draw(img)
        name = f'# {counter} | {member.display_name}'
        undertext = ImageFont.truetype('arial.ttf', size=20)

        idraw.text((75, x+20), f'{name}', font=undertext)
        x += 68

    img.save("user_card.png")

    await ctx.send(file=discord.File('user_card.png'))
client.run(settings['TOKEN'])

ошибка:
Traceback (most recent call last):
  File "C:\Users\dubey\PycharmProjects\pythonProject2\venv\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped
    ret = await coro(*args, **kwargs)
  File "c:\Users\dubey\PycharmProjects\pythonProject2\main.py", line 212, in __leaderboard
    for row in cursor.execute("SELECT user_id, lvl FROM users WHERE server_id = {} ORDER BY cash DESC LIMIT 10".format(ctx.guild.id)):
sqlite3.OperationalError: no such table: users

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

Traceback (most recent call last):
  File "C:\Users\dubey\PycharmProjects\pythonProject2\venv\lib\site-packages\discord\ext\commands\bot.py", line 1350, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\dubey\PycharmProjects\pythonProject2\venv\lib\site-packages\discord\ext\commands\core.py", line 1023, in invoke
    await injected(*ctx.args, **ctx.kwargs)  # type: ignore
  File "C:\Users\dubey\PycharmProjects\pythonProject2\venv\lib\site-packages\discord\ext\commands\core.py", line 238, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: OperationalError: no such table: users

я переустановил базу данных и тут такое. что не так?
  • Вопрос задан
  • 116 просмотров
Пригласить эксперта
Ответы на вопрос 1
Видимо метод __leaderboard, который обращается к таблице users был вызван до того, как был вызван метод on_ready.

Вот цитата из документации, в которой говорится, что не гарантируется, что этот метод будет вызван раньше всех:
https://discordpy.readthedocs.io/en/stable/api.htm...

This function is not guaranteed to be the first event called. Likewise, this function is not guaranteed to only be called once. This library implements reconnection logic and thus will end up calling this event whenever a RESUME request fails.


Как вариант решения - инициализируй базу данных до того как бот будет запущен.
Например объяви функцию prepare_database с вот таким кодом:
@client.event
async def on_ready():
    prepare_database()

    for guild in client.guilds:
        for member in guild.members:
            if cursor.execute(f"SELECT id FROM users WHERE id = {member.id}").fetchone() is None:
                cursor.execute(f"INSERT INTO users VALUES ('{member}', {member.id}, 0, 0, 1, {guild.id})")
            else:
                pass

    connection.commit()
    print('client connected')

def prepare_database():
    cursor.execute("""CREATE TABLE IF NOT EXISTS users (
 name TEXT,
 id INT,
 cash BIGINT,
 rep INT,
        lvl INT,
        server_id INT
    )""")

    cursor.execute("""CREATE TABLE IF NOT EXISTS shop (
        role_id INT,
        id INT,
        cost BIGINT
    )""")


И вызывай её перед запуском бота:
prepare_database()
client.run(settings['TOKEN'])
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы