Kuby/commandes/welcome.py

224 lines
11 KiB
Python
Raw Normal View History

2026-01-01 18:48:25 +01:00
import discord
from discord.ext import commands
from discord import app_commands
import sqlite3
import aiohttp
import io
import os
import logging
from PIL import Image, ImageDraw, ImageFont
kuby_logger = logging.getLogger("KubyBot")
2026-01-01 18:48:25 +01:00
class Welcome(commands.Cog):
def __init__(self, bot):
self.bot = bot
# Base de données à la racine
self.db_path = os.path.join(os.path.dirname(__file__), "..", "config.db")
self._init_db()
def _init_db(self):
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS server_configs (
server_id INTEGER PRIMARY KEY,
welcome_channel INTEGER,
goodbye_channel INTEGER,
welcome_dm_message TEXT,
welcome_server_name TEXT,
welcome_banner_background TEXT,
welcome_channel_message TEXT
2026-01-01 18:48:25 +01:00
)
''')
# Migration pour ajouter les colonnes si elles n'existent pas
cursor.execute("PRAGMA table_info(server_configs)")
columns = [col[1] for col in cursor.fetchall()]
if 'welcome_server_name' not in columns:
cursor.execute('ALTER TABLE server_configs ADD COLUMN welcome_server_name TEXT')
if 'welcome_banner_background' not in columns:
cursor.execute('ALTER TABLE server_configs ADD COLUMN welcome_banner_background TEXT')
if 'welcome_channel_message' not in columns:
cursor.execute('ALTER TABLE server_configs ADD COLUMN welcome_channel_message TEXT')
2026-01-01 18:48:25 +01:00
conn.commit()
conn.close()
async def create_welcome_image(self, username, avatar_url, server_name=None, banner_background=None):
2026-01-01 18:48:25 +01:00
current_dir = os.path.dirname(__file__)
base_dir = os.path.abspath(os.path.join(current_dir, ".."))
try:
async with aiohttp.ClientSession() as session:
async with session.get(avatar_url) as resp:
avatar_bytes = await resp.read()
# Utiliser le fond personnalisé ou celui par défaut
if banner_background and os.path.exists(banner_background):
background = Image.open(banner_background)
else:
background = Image.open(os.path.join(base_dir, 'background_template.png'))
2026-01-01 18:48:25 +01:00
draw = ImageDraw.Draw(background)
font_large = ImageFont.truetype(os.path.join(base_dir, 'custom_font_large.otf'), 70)
font_small = ImageFont.truetype(os.path.join(base_dir, 'custom_font_small.otf'), 50)
draw.text((325, 70), "Bienvenue", font=font_large, fill=(255,255,255))
draw.text((325, 135), f"{username}", font=font_small, fill=(255,255,255))
# Afficher le nom du serveur uniquement si configuré
if server_name:
font_server = ImageFont.truetype(os.path.join(base_dir, 'custom_font_large.otf'), 55)
draw.text((325, 195), server_name, font=font_server, fill=(255,255,255))
2026-01-01 18:48:25 +01:00
avatar = Image.open(io.BytesIO(avatar_bytes)).convert("RGBA").resize((224, 224), Image.LANCZOS)
mask = Image.new('L', avatar.size, 0)
mask_draw = ImageDraw.Draw(mask)
mask_draw.ellipse((12, 12, 212, 212), fill=255)
background.paste(avatar, (40, 40), mask)
img_byte_arr = io.BytesIO()
background.save(img_byte_arr, format='PNG')
img_byte_arr.seek(0)
return img_byte_arr
except Exception as e:
logging.error(f"Erreur image: {e}")
return None
@commands.Cog.listener()
async def on_member_join(self, member):
kuby_logger.info(f"📥 [Welcome] Événement on_member_join reçu pour {member.name} (ID: {member.id}) sur {member.guild.name}")
2026-01-01 18:48:25 +01:00
try:
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('SELECT welcome_channel, welcome_dm_message, welcome_server_name, welcome_banner_background, welcome_channel_message FROM server_configs WHERE server_id = ?', (member.guild.id,))
result = cursor.fetchone()
conn.close()
if not result:
kuby_logger.warning(f"⚠️ [Welcome] Aucune configuration trouvée dans la base de données pour le serveur {member.guild.id}")
return
welcome_channel = result[0]
welcome_dm_text = result[1]
server_name = result[2]
banner_background = result[3]
welcome_channel_message = result[4]
kuby_logger.debug(f"🔍 [Welcome] Config récupérée: DM={bool(welcome_dm_text)}, Channel={welcome_channel}")
# 1. Gestion du DM
if welcome_dm_text:
kuby_logger.info(f"✉️ [Welcome] Tentative d'envoi de DM à {member.name}")
try:
formatted_message = welcome_dm_text.format(
username=member.name,
servername=member.guild.name,
member_count=member.guild.member_count
)
await member.send(formatted_message)
await member.send("https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExNXV1NW02NTk0bGF2ZHcyMGFna2F6amRrbGpobGpsMHowOW5xa2E5eCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ZtFuW4rsUbfrRzPauJ/giphy.gif")
kuby_logger.info(f"✅ [Welcome] DM envoyé avec succès à {member.name}")
except discord.Forbidden:
kuby_logger.warning(f"🚫 [Welcome] Impossible d'envoyer le DM à {member.name} (DMs fermés)")
except Exception as e:
kuby_logger.error(f"❌ [Welcome] Erreur lors de l'envoi du DM à {member.name}: {e}", exc_info=True)
else:
kuby_logger.info(f" [Welcome] Aucun message de DM configuré pour le serveur {member.guild.id}")
except Exception as e:
kuby_logger.error(f"❌ [Welcome] Erreur critique dans on_member_join: {e}", exc_info=True)
2026-01-01 18:48:25 +01:00
# 2. Gestion du salon de bienvenue
if welcome_channel:
channel = member.guild.get_channel(welcome_channel)
2026-01-01 18:48:25 +01:00
if channel:
img = await self.create_welcome_image(
member.name,
member.avatar.url if member.avatar else member.default_avatar.url,
server_name=server_name,
banner_background=banner_background
)
2026-01-01 18:48:25 +01:00
if img:
# Utiliser le message personnalisé ou un message par défaut
channel_description = welcome_channel_message.format(
username=member.name,
servername=member.guild.name,
member_count=member.guild.member_count
) if welcome_channel_message else "Bienvenue dans le serveur !\nSi vous cherchez des RolePlay de qualité,\nVous êtes au bon endroit. <a:sip:1316891821858619452>"
2026-01-01 18:48:25 +01:00
embed = discord.Embed(title=f"Merci d'accueillir {member} 🤝",
description=channel_description,
2026-01-01 18:48:25 +01:00
color=discord.Color.dark_purple())
embed.set_image(url="attachment://welcome.png")
await channel.send(content=member.mention, embed=embed, file=discord.File(img, filename="welcome.png"))
async def save_banner_attachment(self, attachment: discord.Attachment, guild_id: int) -> str:
"""Sauvegarde l'attachment et retourne le chemin du fichier"""
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "banners"))
os.makedirs(base_dir, exist_ok=True)
# Vérifier que c'est une image
if not attachment.content_type or not attachment.content_type.startswith('image/'):
raise ValueError("Le fichier doit être une image.")
# Vérifier le format PNG
if not attachment.filename.lower().endswith('.png'):
raise ValueError("Le fichier doit être au format PNG.")
# Vérifier les dimensions
banner_path = os.path.join(base_dir, f"banner_{guild_id}.png")
async with aiohttp.ClientSession() as session:
async with session.get(attachment.url) as resp:
if resp.status == 200:
# Vérifier les dimensions avant de sauvegarder
img_data = await resp.read()
from io import BytesIO
with Image.open(BytesIO(img_data)) as img:
width, height = img.size
if width != 1000 or height != 300:
raise ValueError(f"Les dimensions doivent être 1000x300 pixels (votre image: {width}x{height})")
with open(banner_path, 'wb') as f:
f.write(img_data)
return banner_path
@app_commands.command(name="setwelcome", description="Définit le salon, les messages de bienvenue et le fond de la bannière")
2026-01-01 18:48:25 +01:00
@app_commands.checks.has_permissions(administrator=True)
async def set_welcome(self, interaction: discord.Interaction, channel: discord.TextChannel, message_dm: str, message_salon: str, server_name: str, banner_file: discord.Attachment = None):
banner_path = None
# Si un fichier est uploadé, le sauvegarder
if banner_file:
try:
banner_path = await self.save_banner_attachment(banner_file, interaction.guild_id)
except Exception as e:
await interaction.response.send_message(f"❌ Erreur avec le fichier: {e}", ephemeral=True)
return
2026-01-01 18:48:25 +01:00
conn = sqlite3.connect(self.db_path)
cursor = conn.cursor()
cursor.execute('''INSERT INTO server_configs (server_id, welcome_channel, welcome_dm_message, welcome_server_name, welcome_banner_background, welcome_channel_message)
VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(server_id)
2026-01-01 18:48:25 +01:00
DO UPDATE SET welcome_channel=excluded.welcome_channel,
welcome_dm_message=excluded.welcome_dm_message,
welcome_server_name=excluded.welcome_server_name,
welcome_banner_background=COALESCE(excluded.welcome_banner_background, welcome_banner_background),
welcome_channel_message=excluded.welcome_channel_message''',
(interaction.guild_id, channel.id, message_dm, server_name, banner_path, message_salon))
2026-01-01 18:48:25 +01:00
conn.commit()
conn.close()
bg_used = "background_template.png" if not banner_path else (banner_path.split('/')[-1])
await interaction.response.send_message(f"✅ Configuration de bienvenida enregistrée !\nFond utilisé: {bg_used}", ephemeral=True)
2026-01-01 18:48:25 +01:00
async def setup(bot):
await bot.add_cog(Welcome(bot))