Задать вопрос
@Nikky_Coding

Почему бот не отправляет сообщение в определенный канал?

Я сделал код для системы уровней с картинками, и конечно надо было сделать систему оповещений о поднятии уровня.
Как я только не пробовал, сообщение бот не отправляет, хотя имеет все разрешения и права.

Код:

# УРОВНИ --------------------------------------------------------------------
DATABASE_FILE = 'users.db'

# Подключаемся к базе данных
conn = sqlite3.connect('users.db')
cursor = conn.cursor()

def get_experience_needed_for_level(level):
    return 5 * (level ** 2) + 50 * level + 100


async def add_experience(message, experience):
    user = message.author
    user_id = user.id
    cursor.execute(
        "SELECT experience, level, channel_id FROM users WHERE user_id = ?", (user_id,))
    result = cursor.fetchone()
    if result is None:
        level = 1
        cursor.execute(
            "INSERT INTO users(user_id, username, discriminator, experience, level, channel_id) "
            "VALUES (?, ?, ?, ?, ?, ?)", (user_id, user.name, user.discriminator, experience, level, 0))
    else:
        experience, level, channel_id = result
    next_level_exp = get_experience_needed_for_level(level + 1)
    new_experience = experience + experience
    if new_experience >= next_level_exp:
        level += 1
        cursor.execute(
            "UPDATE users SET level = ?, channel_id = ? WHERE user_id = ?", (level, message.channel.id, user_id))
        conn.commit()
        await send_level_up_message(user, level, channel_id)

    cursor.execute(
        "UPDATE users SET experience = ? WHERE user_id = ?", (new_experience, user_id))
    conn.commit()

async def show_ranking(message):
    conn = sqlite3.connect(DATABASE_FILE)
    cursor = conn.cursor()
    cursor.execute(
        "SELECT user_id, username, discriminator, level, experience FROM users ORDER BY level DESC, experience DESC LIMIT 10")
    rows = cursor.fetchall()
    if len(rows) == 0:
        await message.channel.send("Нет данных о пользователях.")
        return
    response = "Топ-10 пользователей:\n\n"
    for i, row in enumerate(rows):
        response += f"{i + 1}. {row[1]}#{row[2]} - Уровень {row[3]}, Опыт {row[4]}\n"
    await message.channel.send(response)
    conn.close()

channel_id = 1112637002802790490
async def send_level_up_message(user, level, channel_id):
    print("channel_id:", channel_id)
    channel = await client.fetch_channel(channel_id)
    message = f"Поздравляем, {user.mention}, вы достигли нового уровня {level}!"
    await channel.send(message)

async def clear_database(message):
    conn = sqlite3.connect(DATABASE_FILE)
    cursor = conn.cursor()
    cursor.execute("DELETE FROM users")
    conn.commit()
    await message.channel.send("База данных успешно очищена.")
    conn.close()
background_image = Image.open(
  'background.png')  # замените на ваше изображение фона

# Константы для системы уровней
EXPERIENCE_PER_MESSAGE = 50
EXPERIENCE_LEVEL_FACTOR = 500


# Функция для получения количества опыта, необходимого для достижения определенного уровня
def get_experience_needed_for_level(level):
  return level * EXPERIENCE_LEVEL_FACTOR


# Генерация изображения профиля пользователя
def create_profile_image(member, experience, level):
    # Определение размера и наполнения изображения для профиля пользователя (background image)
    width, height = 400, 400  # здесь вы можете изменить размер изображения профиля
    image = Image.new('RGBA', (width, height), (255, 255, 255, 255))
    image.paste(background_image, (0, 0))

    # Получение изображения для уровня пользователя
    level_image_path = os.path.join(os.getcwd(), "level.png")
    level_image = Image.open(level_image_path)

    level_image = level_image.resize(
        (100, 100)
    )  # здесь мы уменьшаем размер изображения уровня до 100x100 пикселей
    image.paste(level_image, (10, 10))

    # Получение изображения аватарки пользователя, если оно существует
    if member.avatar:
        asset = member.avatar.with_format('png')
    else:
        asset = member.default_avatar.with_format('png')
    avatar_url = asset.url
    response = requests.get(avatar_url)
    avatar_image = Image.open(BytesIO(response.content))
    avatar_image = avatar_image.resize((
        100,
        100
    ))  # здесь мы уменьшаем размер изображения аватарки до 100x100 пикселей

    # Добавление на изображение аватарки пользователя в левый верхний угол
    image.paste(avatar_image, (10, 10))

    # Добавление на изображение изображения уровня пользователя в правый верхний угол
    level_image = level_image.resize(
        (100, 100)
    )  # здесь мы уменьшаем размер изображения уровня до 100x100 пикселей
    image.paste(level_image, (width - 110, 10))

    # Добавление на изображение текста с именем пользователя, дискриминатором и уровнем
    text = f'{member.name}#{member.discriminator}\nLevel {level}\nExperience {experience}'
    font = ImageFont.truetype('Ageo ExtraBold.otf', 40)
    # здесь вы можете изменить шрифт и размер текста
    draw = ImageDraw.Draw(image)
    text_width, text_height = draw.textsize(text, font)
    x = (width - text_width) // 10
    y = height // 2 + 10  # здесь мы используем смещение, чтобы текст был ниже центра изображения
    draw.text((x, y), text, (0, 0, 0), font=font)
    # Сохранение изображения на диск
    filename = f'{member.name}_{member.discriminator}.png'
    image.save(filename)

  
    return filename



level_image_path = os.path.join(os.getcwd(), 'level.png')
level_image = Image.open(level_image_path)
level_image = level_image.resize((100, 100))
filename = 'level.png'
level_image.save(filename)

# Определение переменной level_images с использованием изображения уровня, сохраненного на диск
level_images = {1: filename, 2: filename, 3: filename}


# Команда для отображения профиля пользователя в виде изображения
@bot.command(name='profile')
async def profile(ctx):
  # Получение информации о пользователе
  user = ctx.author
  user_id = user.id

  if 3 in level_images:
    level_image = level_images[3]
  else:
    print('Ключ 3 отсутствует в level_images')

  # Получение опыта и уровня пользователя из базы данных
  cursor.execute('SELECT experience, level FROM users WHERE user_id = ?',
                 (user_id, ))
  result = cursor.fetchone()
  if result is None:
    experience, level = 0, 1  # если информации о пользователе нет в базе данных, создаем данные по умолчанию (0 опыта, 1 уровень)
    cursor.execute(
      'INSERT INTO users(user_id, username, discriminator, experience, level) VALUES (?, ?, ?, ?, ?)',
      (user_id, user.name, user.discriminator, experience, level))
  else:
    experience, level = result

  # Определение количества опыта, необходимого для следующего уровня
  next_level_experience = get_experience_needed_for_level(level + 1)

  # Обновление значения опыта в базе данных
  new_experience = experience + EXPERIENCE_PER_MESSAGE
  if new_experience >= next_level_experience:
    level += 1
    next_level_experience = get_experience_needed_for_level(
      level + 1
    )  # вычисление нового значения необходимого количества опыта для следующего уровня

  cursor.execute(
    'UPDATE users SET experience = ?, level = ? WHERE user_id = ?',
    (new_experience, level, user_id))
  conn.commit()

  # Создание изображения профиля пользователя
  avatar_url = user.avatar.url
  if not avatar_url:
    avatar_url = user.default_avatar_url  # если у пользователя нет аватарки, используем альтернативную аватарку

  response = requests.get(avatar_url)
  avatar_image = Image.open(BytesIO(response.content))
  create_profile_image(user, experience, level)

  # Отправка изображения профиля пользователю
  filename = f'{user.name}_{user.discriminator}.png'
  await ctx.send(file=discord.File(filename))
  # Обновление значения опыта в базе данных
  new_experience = experience + EXPERIENCE_PER_PROFILE_VIEW
  if new_experience >= next_level_experience:
    level += 1

  cursor.execute(
    'UPDATE users SET experience = ?, level = ? WHERE user_id = ?',
    (new_experience, level, user_id))

  conn.commit()


@bot.event
async def on_message(message):
  # Игнорируем сообщения от ботов
  if message.author.bot:
    return

  # Получение информации о пользователе и опыта из базы данных
  user = message.author
  user_id = user.id
  cursor.execute('SELECT experience, level FROM users WHERE user_id = ?',
                 (user_id, ))
  result = cursor.fetchone()
  if result is None:
    experience, level = 0, 1  # если пользователь новый, создаем данные по умолчанию (0 опыта, 1 уровень)
    cursor.execute(
      'INSERT INTO users(user_id, username, discriminator, experience, level) VALUES (?, ?, ?, ?, ?)',
      (user_id, user.name, user.discriminator, experience, level))
  else:
    experience, level = result

  # Определение количества опыта, необходимого для следующего уровня
  next_level_experience = get_experience_needed_for_level(level + 1)

  # Обновление значения опыта в базе данных
  new_experience = experience + EXPERIENCE_PER_MESSAGE
  if new_experience >= next_level_experience:
    level += 1
  cursor.execute(
    'UPDATE users SET experience = ?, level = ? WHERE user_id = ?',
    (new_experience, level, user_id))
  conn.commit()

  await bot.process_commands(message)


EXPERIENCE_PER_PROFILE_VIEW = 10  # здесь вы можете изменить количество опыта, которое получает пользователь за каждый просмотр своего профиля

# Определение уровней и соответствующих им изображений и сохранение изображения уровня на диск
level_image_path = os.path.join(os.getcwd(), 'level.png')
level_image = Image.open(level_image_path)
level_image = level_image.resize((100, 100))
filename = 'level.png'
level_image.save(filename)
  • Вопрос задан
  • 82 просмотра
Подписаться 1 Простой 2 комментария
Пригласить эксперта
Ответы на вопрос 1
fenrir1121
@fenrir1121 Куратор тега discord.py
Начни с документации
Функция add_experience нигде не вызывается.
Соответственно опыт не начисляется, соответственно уровни не выдаются.

Ставьте принты или дебажте, смотрите какие функции у вас вообще вызываются.

Так же соблюдайте правила ресурса, публикуйте код в спойлере и присылайте код, который относится к вопросу, а не гигантскую портянку со всем подряд.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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