From 343eecb4d887fd5e1b27c831c3eabb6da200fd11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anselme=20FRAN=C3=87OIS?= Date: Fri, 10 Jul 2026 16:03:59 +0200 Subject: [PATCH] most fouras commands are now using discord slash commands --- fouras.py | 288 ++++++++++++++++++++++++++++-------------------------- main.py | 9 +- rhymes.py | 14 +-- 3 files changed, 158 insertions(+), 153 deletions(-) diff --git a/fouras.py b/fouras.py index 505b68b..4f02cc4 100644 --- a/fouras.py +++ b/fouras.py @@ -1,20 +1,16 @@ # Remplacez les imports globaux et initialisations import json +import os import random import re -from typing import Any, Dict +from typing import Any, Dict, Optional import discord +from discord import app_commands from unidecode import unidecode import database -# Supprimez ces lignes globales : -# ongoing_riddles = {} -# riddles = [] -# answers = [] - -# Gardez seulement le chargement riddles = [] answers = [] @@ -67,7 +63,7 @@ def new_riddle_state(index: int) -> Dict[str, Any]: } -async def finish_riddle(channel, client) -> None: +async def finish_riddle(channel, client: discord.Client) -> None: """Supprimer l'énigme active de la DB et supprimer le suivi en mémoire.""" removed = database.remove_active_riddle(str(channel.id)) @@ -108,7 +104,6 @@ def format_riddle_message( nb_clues = current_riddle.get("nbClues", -1) answer = current_riddle.get("answer", "") - # Si l'énigme est résolue, on récupère le solver depuis l'ID solver = None if solved and solver_mention: solver = type("obj", (object,), {"mention": solver_mention})() @@ -138,7 +133,7 @@ def format_riddle_message( ) -async def get_channel_name(channel, client) -> str: +async def get_channel_name(channel, client: discord.Client) -> str: if isinstance(channel, discord.DMChannel): dm_channel = await client.fetch_channel(channel.id) return "[DM={0}]".format(dm_channel.recipient.name) @@ -146,7 +141,7 @@ async def get_channel_name(channel, client) -> str: return "[Server={0}] => [Channel={1}]".format(channel.guild.name, channel.name) -async def handle_debug_commands(message, client) -> bool: +async def handle_debug_commands(message, client: discord.Client) -> bool: """Handle debug commands (debug, save, load, broadcast). Returns True if handled.""" message_content = message.content.lower() @@ -209,88 +204,31 @@ async def handle_debug_commands(message, client) -> bool: return False -async def handle_riddle_commands(message, client) -> bool: - """Handle /fouras commands. Returns True if command was processed.""" - message_content = message.content.lower() - - fouras_match = re.match(r"^fouras\s+(\d+)$", message_content) - if fouras_match: - index = int(fouras_match.group(1)) - 1 - if 0 <= index < len(riddles): - if random.random() <= 0.03: - await message.channel.send("Non") - else: - riddle_state = new_riddle_state(index) - - msg = await message.channel.send( - format_riddle_message({**riddle_state, "index": index}) - ) - - database.save_active_riddle( - channel_id=str(message.channel.id), - riddle_index=index, - nb_clues=-1, - message_id=msg.id, - solver_id=None, - ) - else: - await message.channel.send(INVALID_ID.format(len=len(riddles))) - return True - - if message_content == "fouras": - if random.random() <= 0.03: - await message.channel.send("Non") - elif len(riddles) > 0: - index = random.randint(0, len(riddles) - 1) - riddle_state = new_riddle_state(index) - - msg = await message.channel.send( - format_riddle_message({**riddle_state, "index": index}) - ) - - database.save_active_riddle( - channel_id=str(message.channel.id), - riddle_index=index, - nb_clues=-1, - message_id=msg.id, - solver_id=None, - ) - else: - print(f'riddles : "{len(riddles)}"') - return True - - if message_content == "about fouras": - author_user = await client.fetch_user(MAINTAINER_ID) - await message.channel.send(ABOUT.format(user=author_user.mention, url=API_URL)) - return True - - return False - - -async def handle_riddle_solving(message, client) -> bool: - """Handle riddle solving logic. Returns True if riddle was solved or modified.""" - # Vérification via la DB au lieu de la variable globale - riddle_data = database.get_active_riddle(str(message.channel.id)) +def get_current_riddle(channel_id): + riddle_data = database.get_active_riddle(str(channel_id)) if not riddle_data: - return False + return None # Reconstruire l'état de l'énigme if 0 <= riddle_data["riddle_index"] < len(riddles): - current_riddle = { + return { "index": riddle_data["riddle_index"], "nbClues": riddle_data["nb_clues"], "riddle": riddles[riddle_data["riddle_index"]].strip(), "answer": answers[riddle_data["riddle_index"]], + "data": riddle_data } else: - return False + return None - # Si aucun message n'est associé, on ne peut pas éditer - if not riddle_data["message_id"]: - return False +async def handle_riddle_solving(message, client: discord.Client) -> bool: + current_riddle = get_current_riddle(message.channel.id) + if(not current_riddle): + return False answer = current_riddle["answer"] + riddle_data = current_riddle["data"] # Check if message contains the answer if unidecode(answer.lower()) in unidecode(message.content.lower()): @@ -326,65 +264,10 @@ async def handle_riddle_solving(message, client) -> bool: await finish_riddle(message.channel, client) return True - # Repeat riddle command - if message.content.lower() in ["repete", "répète", "repeat"]: - try: - original_msg = await message.channel.fetch_message( - riddle_data["message_id"] - ) - # msg = await message.channel.send(format_riddle_message(current_riddle)) - # database.save_active_riddle( - # channel_id=str(message.channel.id), - # riddle_index=index, - # nb_clues=-1, - # message_id=msg.id, - # solver_id=None, - # ) - except discord.errors.NotFound: - pass - return True - - # Clue command - if message.content.lower() in ["indice", "aide", "help", "clue"]: - nb_clues = current_riddle["nbClues"] + 1 - current_riddle["nbClues"] = nb_clues - - if nb_clues >= len(answer): - await message.channel.send( - "Perdu ! La réponse était : `{0}`".format(answer) - ) - # Mark as unsolved/revealed in DB - database.save_active_riddle( - channel_id=str(message.channel.id), - riddle_index=riddle_data["riddle_index"], - nb_clues=nb_clues, - message_id=riddle_data["message_id"], - solver_id="revealed", # Marqueur spécial - ) - await finish_riddle(message.channel, client) - else: - # Mise à jour du nombre d'indices en DB - database.save_active_riddle( - channel_id=str(message.channel.id), - riddle_index=riddle_data["riddle_index"], - nb_clues=nb_clues, - message_id=riddle_data["message_id"], - solver_id=riddle_data["solver_id"], - ) - - try: - original_msg = await message.channel.fetch_message( - riddle_data["message_id"] - ) - await original_msg.edit(content=format_riddle_message(current_riddle)) - except discord.errors.NotFound: - pass - return True - return False -async def handle_bug_report(message, client) -> bool: +async def handle_bug_report(message, client: discord.Client) -> bool: """Handle bug report command. Returns True if bug report was sent.""" if not message.content.lower().startswith("bug"): return False @@ -424,7 +307,7 @@ async def handle_bug_report(message, client) -> bool: return True -async def handle_message(message, client) -> bool: +async def handle_message(message, client: discord.Client) -> bool: """Main entry point for message handling.""" database.ensure_db() @@ -432,10 +315,6 @@ async def handle_message(message, client) -> bool: if await handle_debug_commands(message, client): return True - # Handle riddle commands - if await handle_riddle_commands(message, client): - return True - # Handle bug reports if await handle_bug_report(message, client): return True @@ -445,3 +324,132 @@ async def handle_message(message, client) -> bool: return True return False + + +async def new_riddle(interaction, index: int) -> None: + if random.random() <= 0.03: + await interaction.response.send_message("Non") + else: + riddle_state = new_riddle_state(index) + await interaction.response.send_message("Nouvelle énigme !") + msg = await interaction.channel.send( + format_riddle_message({**riddle_state, "index": index}) + ) + database.save_active_riddle( + channel_id=str(interaction.channel.id), + riddle_index=index, + nb_clues=-1, + message_id=msg.id, + solver_id=None + ) + + +async def update_riddle_message(channel, current_riddle): + try: + original_msg = await channel.fetch_message(current_riddle["data"]["message_id"]) + await original_msg.edit(content=format_riddle_message(current_riddle)) + return True + except discord.errors.NotFound: + return False + + +def setup_commands(client: discord.Client, tree) -> None: + @tree.command( + name="fouras", + description="Demander une énigme au Père Fouras" + ) + async def fouras( + interaction: discord.Interaction, + ): + if len(riddles) == 0: + await interaction.response.send_message("Désolé, mais j'ai oublié mes énigmes", ephemeral=True) + else: + index = random.randint(0, len(riddles) - 1) + await new_riddle(interaction, index) + + + @tree.command( + name="fouras_requete", + description="Demander une énigme spécifique au Père Fouras" + ) + @app_commands.describe(index="Numéro de l'énigme") + async def fouras_requete( + interaction: discord.Interaction, + index: int, + ): + index = index - 1 + if not (0 <= index < len(riddles)): + await interaction.response.send_message(INVALID_ID.format(len=len(riddles)+1), ephemeral=True) + return + await new_riddle(interaction, index) + + + @tree.command( + name="repete", + description="Demander au Père Fouras de répéter l'énigme en cours" + ) + async def repete( + interaction: discord.Interaction, + ): + current_riddle = get_current_riddle(interaction.channel.id) + if(not current_riddle): + await interaction.response.send_message("Aucune énigme en cours", ephemeral=True) + return + riddle_data = current_riddle["data"] + await interaction.response.send_message("Ok, je vais répéter l'énigme en cours", ephemeral=True) + msg = await interaction.channel.send(format_riddle_message(current_riddle)) + database.save_active_riddle( + channel_id=str(interaction.channel.id), + riddle_index=riddle_data["riddle_index"], + nb_clues=current_riddle["nbClues"], + message_id=msg.id, + solver_id=riddle_data["solver_id"], + ) + + + @tree.command( + name="about", + description="Qui est le Père Fouras ?" + ) + async def about( + interaction: discord.Interaction, + ): + author_user = await client.fetch_user(MAINTAINER_ID) + await interaction.response.send_message(ABOUT.format(user=author_user.mention, url=API_URL), ephemeral=True) + + + @tree.command( + name="indice", + description="Demander un indice pour l'énigme en cours" + ) + async def indice( + interaction: discord.Interaction, + ): + current_riddle = get_current_riddle(interaction.channel.id) + if(not current_riddle): + await interaction.response.send_message("Aucune énigme en cours", ephemeral=True) + return + answer = current_riddle["answer"] + riddle_data = current_riddle["data"] + nb_clues = current_riddle["nbClues"] + 1 + current_riddle["nbClues"] = nb_clues + + if nb_clues >= len(answer): + await interaction.response.send_message( + "Perdu ! La réponse était : `{0}`".format(answer) + ) + if(not await update_riddle_message(interaction.channel, current_riddle)): + return + await finish_riddle(interaction.channel, client) + else: + # Update nb clues in DB + database.save_active_riddle( + channel_id=str(interaction.channel.id), + riddle_index=riddle_data["riddle_index"], + nb_clues=nb_clues, + message_id=riddle_data["message_id"], + solver_id=riddle_data["solver_id"], + ) + if(not await update_riddle_message(interaction.channel, current_riddle)): + return + await interaction.response.send_message("Nouvel indice : `{0}`".format(clue_string(answer, nb_clues))) diff --git a/main.py b/main.py index 1fa5446..891dbca 100644 --- a/main.py +++ b/main.py @@ -25,15 +25,18 @@ async def on_ready(): global client, tree """Initialize bot state and sync commands.""" # Import initialization functions - from fouras import load_riddles - from rhymes import _ensure_log_file, load_rhymes + from fouras import load_riddles, setup_commands + from rhymes import ensure_log_file, load_rhymes # Ensure directories exist - _ensure_log_file() + ensure_log_file() # Load riddles and answers load_riddles() + # register fouras commands + setup_commands(client, tree) + # Load rhymes success, msg = load_rhymes() print(msg) diff --git a/rhymes.py b/rhymes.py index dbbf5a5..2f30201 100644 --- a/rhymes.py +++ b/rhymes.py @@ -1,7 +1,7 @@ # rhymes.py import json import random -from datetime import datetime +from datetime import datetime, timedelta from pathlib import Path from typing import Any, Dict, Tuple @@ -13,7 +13,7 @@ RHYME_LOG_FILE = "data/rhyme_log.csv" loaded_rhymes = {} -def _ensure_log_file() -> None: +def ensure_log_file() -> None: """Create CSV log file if it doesn't exist.""" Path(RHYME_LOG_FILE).parent.mkdir(parents=True, exist_ok=True) @@ -182,13 +182,7 @@ async def handle_rhyme_logic(message, client) -> bool: if bool(random.getrandbits(1)): wait_time = random.randint(900, 10800) - new_cooldown_dt = now_dt.replace(second=0, microsecond=0) - new_cooldown_dt = new_cooldown_dt.replace( - minute=new_cooldown_dt.minute + wait_time // 60 - ) - new_cooldown_dt = new_cooldown_dt.replace( - hour=new_cooldown_dt.hour + wait_time // 3600 - ) + new_cooldown_dt = now_dt.replace(second=0, microsecond=0) + timedelta(seconds=wait_time) database.update_guild_state( guild_id, @@ -207,7 +201,7 @@ async def handle_message(message, client) -> bool: """Main entry point for message handling.""" # Initialize database and log file on first run database.ensure_db() - _ensure_log_file() + ensure_log_file() # Handle debug commands first if await handle_debug_commands(message, client):