first commit
This commit is contained in:
244
bot.py
Normal file
244
bot.py
Normal file
@ -0,0 +1,244 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
import json
|
||||
import aiohttp
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from family import FamilyManager
|
||||
from tree import generate_tree
|
||||
from typing import Optional
|
||||
|
||||
# Configuration initiale
|
||||
load_dotenv()
|
||||
TOKEN = os.getenv("DISCORD_TOKEN")
|
||||
|
||||
with open("config.json") as f:
|
||||
config = json.load(f)
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.members = True
|
||||
intents.message_content = True
|
||||
|
||||
bot = commands.Bot(command_prefix="!", intents=intents)
|
||||
family = FamilyManager("family.json")
|
||||
|
||||
async def download_avatar(member: discord.Member) -> Optional[str]:
|
||||
"""Télécharge et enregistre l'avatar d'un membre"""
|
||||
if not member.avatar:
|
||||
return None
|
||||
|
||||
avatar_dir = "avatars"
|
||||
os.makedirs(avatar_dir, exist_ok=True)
|
||||
avatar_path = f"{avatar_dir}/{member.id}.png"
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(str(member.avatar.url)) as resp:
|
||||
if resp.status == 200:
|
||||
with open(avatar_path, "wb") as f:
|
||||
f.write(await resp.read())
|
||||
return avatar_path
|
||||
except Exception as e:
|
||||
print(f"Erreur de téléchargement avatar {member.id}: {e}")
|
||||
return None
|
||||
|
||||
async def update_member(member: discord.Member):
|
||||
"""Met à jour les infos d'un membre dans la famille"""
|
||||
avatar_url = str(member.avatar.url) if member.avatar else None
|
||||
family.add_member(
|
||||
str(member.id),
|
||||
member.display_name,
|
||||
avatar_url
|
||||
)
|
||||
await download_avatar(member)
|
||||
|
||||
@bot.event
|
||||
async def on_ready():
|
||||
print(f"Connecté en tant que {bot.user} (ID: {bot.user.id})")
|
||||
try:
|
||||
synced = await bot.tree.sync()
|
||||
print(f"Commandes synchronisées ({len(synced)}): {[c.name for c in synced]}")
|
||||
except Exception as e:
|
||||
print(f"Erreur synchronisation commandes: {e}")
|
||||
|
||||
@bot.tree.command(name="enregistrer", description="Enregistre ou met à jour son profil")
|
||||
async def enregistrer(interaction: discord.Interaction):
|
||||
"""Commande pour que les membres enregistrent leurs infos"""
|
||||
await update_member(interaction.user)
|
||||
await interaction.response.send_message(
|
||||
"✅ Profil mis à jour avec succès !",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
@bot.tree.command(name="adopter", description="Adopter un membre")
|
||||
async def adopter(interaction: discord.Interaction, enfant: discord.Member):
|
||||
parent = interaction.user
|
||||
|
||||
# Validations
|
||||
if parent.id == enfant.id:
|
||||
await interaction.response.send_message("❌ Auto-adoption impossible !", ephemeral=True)
|
||||
return
|
||||
|
||||
if family.get_generation(str(enfant.id)) < family.get_generation(str(parent.id)):
|
||||
await interaction.response.send_message(
|
||||
"❌ Structure familiale invalide !",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
# Met à jour les infos des membres
|
||||
await update_member(parent)
|
||||
await update_member(enfant)
|
||||
|
||||
# Crée le lien familial
|
||||
if not family.add_child(str(parent.id), str(enfant.id)):
|
||||
await interaction.response.send_message(
|
||||
"❌ Erreur lors de l'adoption",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
# Attribue le rôle approprié
|
||||
generation = family.get_generation(str(enfant.id))
|
||||
role_id = config["ROLE_IDS"].get(
|
||||
"ENFANT" if generation == 1 else
|
||||
"PETIT_ENFANT" if generation == 2 else
|
||||
"ARRIERE_PETIT_ENFANT"
|
||||
)
|
||||
|
||||
role = interaction.guild.get_role(role_id)
|
||||
if role:
|
||||
try:
|
||||
await enfant.add_roles(role)
|
||||
message = f"✅ {parent.mention} a adopté {enfant.mention} !"
|
||||
|
||||
# Mentionne le partenaire si existe
|
||||
partner_id = family.get_partner(str(parent.id))
|
||||
if partner_id:
|
||||
partner = interaction.guild.get_member(int(partner_id))
|
||||
if partner:
|
||||
message += f"\n👫 Partenaire : {partner.mention}"
|
||||
|
||||
await interaction.response.send_message(message)
|
||||
except discord.Forbidden:
|
||||
await interaction.response.send_message(
|
||||
"❌ Permission refusée pour attribuer le rôle !",
|
||||
ephemeral=True
|
||||
)
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
"❌ Rôle introuvable ! Contactez un administrateur.",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
@bot.tree.command(name="couple", description="Officialiser une relation")
|
||||
async def couple(interaction: discord.Interaction, partenaire: discord.Member):
|
||||
membre = interaction.user
|
||||
|
||||
# Validations
|
||||
if membre.id == partenaire.id:
|
||||
await interaction.response.send_message(
|
||||
"❌ Impossible de former un couple avec soi-même !",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
# Met à jour les infos
|
||||
await update_member(membre)
|
||||
await update_member(partenaire)
|
||||
|
||||
if family.add_couple(str(membre.id), str(partenaire.id)):
|
||||
await interaction.response.send_message(
|
||||
f"💑 {membre.mention} et {partenaire.mention} sont maintenant partenaires !"
|
||||
)
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
"❌ Ces membres sont déjà en couple !",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
@bot.tree.command(name="renier", description="Renier un enfant")
|
||||
async def renier(interaction: discord.Interaction, enfant: discord.Member):
|
||||
parent = interaction.user
|
||||
success = family.remove_child(str(parent.id), str(enfant.id))
|
||||
|
||||
if success:
|
||||
# Retire le rôle
|
||||
generation = family.get_generation(str(enfant.id))
|
||||
role_id = config["ROLE_IDS"].get(
|
||||
"ENFANT" if generation == 1 else
|
||||
"PETIT_ENFANT" if generation == 2 else
|
||||
"ARRIERE_PETIT_ENFANT"
|
||||
)
|
||||
|
||||
if role_id:
|
||||
role = interaction.guild.get_role(role_id)
|
||||
if role:
|
||||
try:
|
||||
await enfant.remove_roles(role)
|
||||
except discord.Forbidden:
|
||||
pass # On continue même si échec du retrait de rôle
|
||||
|
||||
await interaction.response.send_message(
|
||||
f"❌ {parent.mention} a renié {enfant.mention} !"
|
||||
)
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
"❌ Aucun lien parental trouvé.",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
@bot.tree.command(name="arbre", description="Afficher l'arbre généalogique")
|
||||
async def arbre(interaction: discord.Interaction):
|
||||
await interaction.response.defer()
|
||||
|
||||
# Télécharge les avatars des membres
|
||||
members = family.get_all_members()
|
||||
for member_id in members:
|
||||
try:
|
||||
member = await interaction.guild.fetch_member(int(member_id))
|
||||
await download_avatar(member)
|
||||
except:
|
||||
continue
|
||||
|
||||
# Génère l'arbre
|
||||
generate_tree("family.json", "arbre.png", config["ROOT_MEMBER_ID"])
|
||||
|
||||
# Envoie le résultat
|
||||
try:
|
||||
await interaction.followup.send(file=discord.File("arbre.png"))
|
||||
except:
|
||||
await interaction.followup.send(
|
||||
"❌ Erreur lors de la génération de l'arbre",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
@bot.tree.command(name="parent", description="Voir les parents d'un membre")
|
||||
async def parent(interaction: discord.Interaction, membre: Optional[discord.Member] = None):
|
||||
target = membre or interaction.user
|
||||
parents = family.get_parents(str(target.id))
|
||||
|
||||
if not parents:
|
||||
await interaction.response.send_message(
|
||||
f"ℹ️ {target.display_name} n'a pas de parent enregistré.",
|
||||
ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
parent_mentions = [f"<@{p['id']}>" for p in parents]
|
||||
await interaction.response.send_message(
|
||||
f"👪 Parents de {target.mention} : {' '.join(parent_mentions)}"
|
||||
)
|
||||
|
||||
@bot.command()
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def init(ctx):
|
||||
"""Initialise tous les membres du serveur (admin seulement)"""
|
||||
count = 0
|
||||
for member in ctx.guild.members:
|
||||
await update_member(member)
|
||||
count += 1
|
||||
|
||||
await ctx.send(f"✅ {count} membres initialisés !")
|
||||
|
||||
bot.run(TOKEN)
|
Reference in New Issue
Block a user