most fouras commands are now using discord slash commands

This commit is contained in:
Anselme FRANÇOIS 2026-07-10 16:03:59 +02:00
parent 400dcecf13
commit 343eecb4d8
3 changed files with 158 additions and 153 deletions

288
fouras.py
View File

@ -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)))

View File

@ -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)

View File

@ -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):