|
|
@@ -1,212 +0,0 @@
|
|
|
-# Définir le client Discord et les gestionnaires d'événements.
|
|
|
-
|
|
|
-import discord
|
|
|
-from discord.ext import commands
|
|
|
-from config import CHATGPT_CHANNEL_ID, BOT_NAME, BOT_VERSION
|
|
|
-from logger import logger
|
|
|
-from history import load_conversation_history, conversation_history, add_to_conversation_history, save_conversation_history
|
|
|
-from openai_client import call_gpt4o_for_image_analysis, call_gpt4o_mini_with_analysis, call_openai_api
|
|
|
-from utils import has_text, read_text_file, encode_image_from_attachment
|
|
|
-from history import IMAGE_ANALYSIS_MARKER
|
|
|
-import json
|
|
|
-
|
|
|
-class MyDiscordClient(discord.Client):
|
|
|
- def __init__(self, intents):
|
|
|
- super().__init__(intents=intents)
|
|
|
- self.last_analysis_index = None
|
|
|
- self.messages_since_last_analysis = 0
|
|
|
-
|
|
|
- async def close(self):
|
|
|
- from openai_client import openai_client
|
|
|
- if openai_client is not None:
|
|
|
- await openai_client.close()
|
|
|
- await super().close()
|
|
|
-
|
|
|
-# Initialiser les intents
|
|
|
-intents = discord.Intents.default()
|
|
|
-intents.message_content = True # Activer l'intent pour les contenus de message
|
|
|
-
|
|
|
-# Initialiser le client Discord
|
|
|
-client_discord = MyDiscordClient(intents=intents)
|
|
|
-
|
|
|
-# Charger l'historique au démarrage
|
|
|
-load_conversation_history()
|
|
|
-
|
|
|
-@client_discord.event
|
|
|
-async def on_ready():
|
|
|
- logger.info(f'{BOT_NAME} connecté en tant que {client_discord.user}')
|
|
|
-
|
|
|
- if not conversation_history:
|
|
|
- logger.info("Aucun historique trouvé. L'historique commence vide.")
|
|
|
-
|
|
|
- try:
|
|
|
- # Utiliser fetch_channel au lieu de get_channel
|
|
|
- channel = await client_discord.fetch_channel(CHATGPT_CHANNEL_ID)
|
|
|
- if channel:
|
|
|
- embed = discord.Embed(
|
|
|
- title="Bot Démarré",
|
|
|
- description=f"🎉 {BOT_NAME} est en ligne ! Version {BOT_VERSION}",
|
|
|
- color=0x00ff00 # Vert
|
|
|
- )
|
|
|
- await channel.send(embed=embed)
|
|
|
- logger.info(f"Message de connexion envoyé dans le canal ID {CHATGPT_CHANNEL_ID}")
|
|
|
- except discord.NotFound:
|
|
|
- logger.error(f"Canal avec ID {CHATGPT_CHANNEL_ID} non trouvé.")
|
|
|
- except discord.Forbidden:
|
|
|
- logger.error(f"Permissions insuffisantes pour envoyer des messages dans le canal ID {CHATGPT_CHANNEL_ID}.")
|
|
|
- except discord.HTTPException as e:
|
|
|
- logger.error(f"Erreur lors de l'envoi du message de connexion : {e}")
|
|
|
-
|
|
|
-@client_discord.event
|
|
|
-async def on_message(message):
|
|
|
- global conversation_history
|
|
|
-
|
|
|
- # Vérifier si le message provient du canal autorisé
|
|
|
- if message.channel.id != CHATGPT_CHANNEL_ID:
|
|
|
- return
|
|
|
-
|
|
|
- # Ignorer les messages du bot lui-même
|
|
|
- if message.author == client_discord.user:
|
|
|
- return
|
|
|
-
|
|
|
- user_text = message.content.strip()
|
|
|
- image_data = None
|
|
|
- file_content = None
|
|
|
- attachment_filename = None
|
|
|
-
|
|
|
- # Vérifier si le message est la commande de réinitialisation
|
|
|
- if user_text.lower() == "!reset_history":
|
|
|
- # Vérifier si l'utilisateur a les permissions administratives
|
|
|
- if not message.author.guild_permissions.administrator:
|
|
|
- await message.channel.send("❌ Vous n'avez pas la permission d'utiliser cette commande.")
|
|
|
- return
|
|
|
-
|
|
|
- conversation_history.clear()
|
|
|
- save_conversation_history()
|
|
|
- await message.channel.send("✅ L'historique des conversations a été réinitialisé.")
|
|
|
- logger.info(f"Historique des conversations réinitialisé par {message.author}.")
|
|
|
- return # Arrêter le traitement du message après la réinitialisation
|
|
|
-
|
|
|
- # Extensions de fichiers autorisées
|
|
|
- allowed_extensions = ['.txt', '.py', '.html', '.css', '.js']
|
|
|
-
|
|
|
- # Variables pour stocker si le message contient une image et/ou un fichier
|
|
|
- has_image = False
|
|
|
- has_file = False
|
|
|
-
|
|
|
- # Vérifier s'il y a une pièce jointe
|
|
|
- if message.attachments:
|
|
|
- for attachment in message.attachments:
|
|
|
- # Vérifier si c'est un fichier avec une extension autorisée
|
|
|
- if any(attachment.filename.endswith(ext) for ext in allowed_extensions):
|
|
|
- file_content = await read_text_file(attachment)
|
|
|
- attachment_filename = attachment.filename
|
|
|
- break
|
|
|
- # Vérifier si c'est une image
|
|
|
- elif attachment.content_type in ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/tiff']:
|
|
|
- image_data = await encode_image_from_attachment(attachment, mode='high')
|
|
|
- break
|
|
|
-
|
|
|
- # Si une image est présente, la traiter
|
|
|
- if image_data:
|
|
|
- has_user_text = has_text(user_text)
|
|
|
- user_text_to_use = user_text if has_user_text else None
|
|
|
-
|
|
|
- # Étape 1 : Envoyer un message temporaire indiquant que l'image est en cours d'analyse
|
|
|
- temp_msg = await message.channel.send(f"*{BOT_NAME} observe l'image...*")
|
|
|
-
|
|
|
- try:
|
|
|
- # Étape 2 : GPT-4o analyse l'image, potentiellement guidée par le texte de l'utilisateur
|
|
|
- analysis = await call_gpt4o_for_image_analysis(image_data, user_text=user_text_to_use)
|
|
|
-
|
|
|
- if analysis:
|
|
|
- # Ajouter l'analyse à l'historique avant de réagir avec GPT-4o Mini
|
|
|
- analysis_message = {
|
|
|
- "role": "system",
|
|
|
- "content": f"{IMAGE_ANALYSIS_MARKER}{analysis}"
|
|
|
- }
|
|
|
- await add_to_conversation_history(analysis_message)
|
|
|
-
|
|
|
- # Étape 3 : GPT-4o Mini réagit à la question et à l'analyse
|
|
|
- reply = await call_gpt4o_mini_with_analysis(
|
|
|
- analysis,
|
|
|
- message.author.name,
|
|
|
- user_text,
|
|
|
- has_text=has_user_text,
|
|
|
- conversation_history=conversation_history
|
|
|
- )
|
|
|
- if reply:
|
|
|
- # Étape 4 : Supprimer le message temporaire
|
|
|
- await temp_msg.delete()
|
|
|
-
|
|
|
- # Étape 5 : Envoyer la réponse finale
|
|
|
- await message.channel.send(reply)
|
|
|
-
|
|
|
- # Ajouter le message utilisateur à l'historique
|
|
|
- if has_user_text:
|
|
|
- user_message_content = f"{user_text} (a posté une image.)"
|
|
|
- else:
|
|
|
- user_message_content = (
|
|
|
- "Une image a été postée, mais elle n'est pas disponible pour analyse directe. "
|
|
|
- "Veuillez vous baser uniquement sur l'analyse fournie."
|
|
|
- )
|
|
|
-
|
|
|
- user_message = {
|
|
|
- "role": "user",
|
|
|
- "content": user_message_content
|
|
|
- }
|
|
|
-
|
|
|
- # Ajouter le message utilisateur à l'historique
|
|
|
- await add_to_conversation_history(user_message)
|
|
|
-
|
|
|
- # Ajouter le message assistant à l'historique
|
|
|
- assistant_message = {
|
|
|
- "role": "assistant",
|
|
|
- "content": reply
|
|
|
- }
|
|
|
- await add_to_conversation_history(assistant_message)
|
|
|
- else:
|
|
|
- # Étape 4 : Supprimer le message temporaire en cas d'échec de génération de réponse
|
|
|
- await temp_msg.delete()
|
|
|
- await message.channel.send("Désolé, je n'ai pas pu générer une réponse.")
|
|
|
- else:
|
|
|
- # Étape 4 : Supprimer le message temporaire en cas d'échec d'analyse
|
|
|
- await temp_msg.delete()
|
|
|
- await message.channel.send("Désolé, je n'ai pas pu analyser l'image.")
|
|
|
-
|
|
|
- except Exception as e:
|
|
|
- # Étape 4 : Supprimer le message temporaire en cas d'erreur
|
|
|
- await temp_msg.delete()
|
|
|
- await message.channel.send("Une erreur est survenue lors du traitement de l'image.")
|
|
|
- logger.error(f"Error during image processing: {e}")
|
|
|
-
|
|
|
- # Après traitement de l'image, ne pas continuer
|
|
|
- return
|
|
|
-
|
|
|
- # Ajouter le contenu du fichier à la requête si présent
|
|
|
- if file_content:
|
|
|
- user_text += f"\nContenu du fichier {attachment_filename}:\n{file_content}"
|
|
|
-
|
|
|
- # Vérifier si le texte n'est pas vide après ajout du contenu du fichier
|
|
|
- if not has_text(user_text):
|
|
|
- return # Ne pas appeler l'API si le texte est vide
|
|
|
-
|
|
|
- # Appeler l'API OpenAI
|
|
|
- result = await call_openai_api(user_text, message.author.name, conversation_history, image_data)
|
|
|
- if result:
|
|
|
- reply = result.choices[0].message.content
|
|
|
- await message.channel.send(reply)
|
|
|
-
|
|
|
- # Ajouter le message utilisateur à l'historique
|
|
|
- user_message = {
|
|
|
- "role": "user",
|
|
|
- "content": user_text
|
|
|
- }
|
|
|
- await add_to_conversation_history(user_message)
|
|
|
-
|
|
|
- # Ajouter le message assistant à l'historique
|
|
|
- assistant_message = {
|
|
|
- "role": "assistant",
|
|
|
- "content": reply
|
|
|
- }
|
|
|
- await add_to_conversation_history(assistant_message)
|