Final beta for tonight

This commit is contained in:
root
2025-04-20 01:22:48 +02:00
parent 8c1e86cb53
commit 1474de77c4
11 changed files with 105 additions and 30 deletions

BIN
.bot.py.swp Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
arbre.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 493 KiB

After

Width:  |  Height:  |  Size: 614 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

34
bot.py
View File

@ -74,14 +74,20 @@ async def enregistrer(interaction: discord.Interaction):
async def adopter(interaction: discord.Interaction, enfant: discord.Member):
parent = interaction.user
# Debug
parent_gen = family.get_generation(str(parent.id))
enfant_gen = family.get_generation(str(enfant.id))
print(f"Adoption: {parent.display_name} (gen {parent_gen}) → {enfant.display_name} (gen {enfant_gen})")
# 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)):
# Nouvelle condition plus permissive
if enfant_gen > parent_gen:
await interaction.response.send_message(
"Structure familiale invalide !",
"Impossible d'adopter quelqu'un de plus ancien que vous !",
ephemeral=True
)
return
@ -111,14 +117,14 @@ async def adopter(interaction: discord.Interaction, enfant: discord.Member):
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(
@ -131,6 +137,16 @@ async def adopter(interaction: discord.Interaction, enfant: discord.Member):
ephemeral=True
)
@bot.tree.command(name="racine", description="Définir un membre comme racine")
@commands.has_permissions(administrator=True)
async def racine(interaction: discord.Interaction, membre: discord.Member, est_racine: bool):
success = family.set_as_root(str(membre.id), est_racine)
await interaction.response.send_message(
f"{membre.mention} est maintenant {'une racine' if est_racine else 'plus une racine'} !"
if success else "❌ Erreur",
ephemeral=True
)
@bot.tree.command(name="couple", description="Officialiser une relation")
async def couple(interaction: discord.Interaction, partenaire: discord.Member):
membre = interaction.user
@ -170,7 +186,7 @@ async def renier(interaction: discord.Interaction, enfant: discord.Member):
"PETIT_ENFANT" if generation == 2 else
"ARRIERE_PETIT_ENFANT"
)
if role_id:
role = interaction.guild.get_role(role_id)
if role:
@ -191,7 +207,7 @@ async def renier(interaction: discord.Interaction, enfant: discord.Member):
@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:
@ -203,7 +219,7 @@ async def arbre(interaction: discord.Interaction):
# 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"))
@ -238,7 +254,7 @@ async def init(ctx):
for member in ctx.guild.members:
await update_member(member)
count += 1
await ctx.send(f"{count} membres initialisés !")
bot.run(TOKEN)

View File

@ -29,7 +29,8 @@
"id": "901473267104223232",
"name": "Partenaire"
}
]
],
"avatar": "https://cdn.discordapp.com/avatars/436978132105560064/1d711ba4fea8d707903df35ea859a86c.png?size=1024"
},
"567371662165803009": {
"name": "Je suis g\u00e9niale.ment on fire",
@ -120,6 +121,21 @@
"name": "NYM N'EST PAS UN CODE BARRE"
}
]
},
"565561317189091328": {
"name": "BardimeduSAFF Hamilton ofthemind",
"avatar": "https://cdn.discordapp.com/avatars/565561317189091328/c77280ab4a455cd482f73a2ef38d72f8.png?size=1024",
"parents": []
},
"582633859967877133": {
"name": "L'incarn\u00e9 zzz",
"avatar": "https://cdn.discordapp.com/avatars/582633859967877133/89c60709a5e4c47ee16001844f0d51ad.png?size=1024",
"parents": []
},
"1334641803059793940": {
"name": "Epic The Ticketal",
"avatar": "https://cdn.discordapp.com/avatars/1334641803059793940/e36465f33fa4c2cd35a9de212e6832fc.png?size=1024",
"parents": []
}
},
"couples": [
@ -130,6 +146,10 @@
[
"506016482300395520",
"769178722838118400"
],
[
"565561317189091328",
"582633859967877133"
]
]
}

View File

@ -13,7 +13,8 @@ class FamilyManager:
with open(self.file_path, "w") as f:
json.dump({
"members": {},
"couples": []
"couples": [],
"roots": []
}, f, indent=2)
def _load(self) -> Dict:
@ -26,6 +27,23 @@ class FamilyManager:
with open(self.file_path, "w") as f:
json.dump(data, f, indent=2)
def set_as_root(self, member_id: str, is_root: bool = True) -> bool:
"""Définit un membre comme racine ou non"""
data = self._load()
if str(member_id) not in data["members"]:
return False
if "roots" not in data:
data["roots"] = []
if is_root and str(member_id) not in data["roots"]:
data["roots"].append(str(member_id))
elif not is_root and str(member_id) in data["roots"]:
data["roots"].remove(str(member_id))
self._save(data)
return True
def add_member(self, member_id: str, member_name: str, avatar_url: str = None):
"""
Ajoute ou met à jour un membre
@ -34,7 +52,7 @@ class FamilyManager:
:param avatar_url: URL de l'avatar (optionnel)
"""
data = self._load()
if str(member_id) not in data["members"]:
data["members"][str(member_id)] = {
"name": member_name,
@ -46,17 +64,18 @@ class FamilyManager:
data["members"][str(member_id)]["name"] = member_name
if avatar_url:
data["members"][str(member_id)]["avatar"] = avatar_url
self._save(data)
def add_child(self, parent_id: str, child_id: str):
def add_child(self, parent_id: str, child_id: str) -> bool:
"""
Ajoute un lien parent-enfant
:param parent_id: ID du parent
:param child_id: ID de l'enfant
:return: True si succès, False si échec
"""
data = self._load()
# Vérifie que les membres existent
if str(child_id) not in data["members"] or str(parent_id) not in data["members"]:
return False
@ -69,7 +88,7 @@ class FamilyManager:
})
# Ajoute le partenaire comme parent secondaire si existe
partner_id = self.get_partner(parent_id)
partner_id = self.get_partner(str(parent_id))
if partner_id:
partner_name = data["members"].get(partner_id, {}).get("name", "Partenaire")
data["members"][str(child_id)]["parents"].append({
@ -87,7 +106,7 @@ class FamilyManager:
"""
data = self._load()
couple = sorted([str(member1_id), str(member2_id)])
if couple not in data["couples"]:
data["couples"].append(couple)
self._save(data)
@ -109,15 +128,15 @@ class FamilyManager:
"""
data = self._load()
changed = False
if str(child_id) in data["members"]:
original_count = len(data["members"][str(child_id)]["parents"])
data["members"][str(child_id)]["parents"] = [
p for p in data["members"][str(child_id)]["parents"]
p for p in data["members"][str(child_id)]["parents"]
if p["id"] != str(parent_id)
]
changed = len(data["members"][str(child_id)]["parents"]) < original_count
if changed:
self._save(data)
return changed
@ -143,20 +162,33 @@ class FamilyManager:
def get_generation(self, member_id: str) -> int:
"""
Calcule la génération d'un membre
:return: 0 pour la racine, 1 pour ses enfants, etc.
:return: 0 pour les racines, 1 pour leurs enfants, etc.
"""
data = self._load()
generation = 0
current_id = str(member_id)
while current_id in data["members"] and data["members"][current_id].get("parents"):
current_id = data["members"][current_id]["parents"][0]["id"]
generation += 1
if generation > 10: # Sécurité contre les boucles infinies
break
return generation
# Si c'est une racine explicite
if str(member_id) in data.get("roots", []):
return 0
parents = data["members"].get(str(member_id), {}).get("parents", [])
# Si pas de parents => nouvelle racine (gen 0)
if not parents:
return 0
# Calcul basé sur les parents
return 1 + min(
self.get_generation(p["id"])
for p in parents
if p["id"] in data["members"]
)
def get_all_members(self) -> List[str]:
"""Liste tous les IDs des membres enregistrés"""
data = self._load()
return list(data["members"].keys())
def get_roots(self) -> List[str]:
"""Liste toutes les racines"""
data = self._load()
return data.get("roots", [])

View File

@ -37,7 +37,14 @@ def create_avatar_with_name(user_id, name, avatar_path, output_path):
print(f"Erreur création avatar+texte {user_id}: {e}")
return False
def generate_tree(input_file, output_file, root_id):
def generate_tree(input_file, output_file, root_id=None): # root_id devient optionnel
with open(input_file) as f:
data = json.load(f)
roots = data.get("roots", [root_id] if root_id else [])
if not roots:
roots = [mid for mid, m in data["members"].items() if not m.get("parents")]
with open(input_file) as f:
data = json.load(f)