Я сделал код для системы уровней с картинками, и конечно надо было сделать систему оповещений о поднятии уровня.
Как я только не пробовал, сообщение бот не отправляет, хотя имеет все разрешения и права.
Код:
# УРОВНИ --------------------------------------------------------------------
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)