|
@@ -11,6 +11,7 @@ import httpx
|
|
|
import base64
|
|
import base64
|
|
|
import re
|
|
import re
|
|
|
import signal
|
|
import signal
|
|
|
|
|
+import asyncio
|
|
|
import sys
|
|
import sys
|
|
|
|
|
|
|
|
from dotenv import load_dotenv
|
|
from dotenv import load_dotenv
|
|
@@ -46,7 +47,7 @@ if WEB_SEARCH_RESULT_COUNT < 1:
|
|
|
# Initialiser le client OpenAI asynchrone ici
|
|
# Initialiser le client OpenAI asynchrone ici
|
|
|
openai_client = AsyncOpenAI(api_key=OPENAI_API_KEY, base_url=URL_OPENAI_API)
|
|
openai_client = AsyncOpenAI(api_key=OPENAI_API_KEY, base_url=URL_OPENAI_API)
|
|
|
|
|
|
|
|
-BOT_VERSION = "3.0"
|
|
|
|
|
|
|
+BOT_VERSION = "3.0.1"
|
|
|
|
|
|
|
|
# Vérifier la version de Discord
|
|
# Vérifier la version de Discord
|
|
|
if not sys.version_info[:2] >= (3, 15):
|
|
if not sys.version_info[:2] >= (3, 15):
|
|
@@ -151,12 +152,17 @@ def split_message(message, max_length=2000):
|
|
|
current_part = ""
|
|
current_part = ""
|
|
|
|
|
|
|
|
for line in message.split('\n'):
|
|
for line in message.split('\n'):
|
|
|
- if len(current_part) + len(line) + 1 > max_length:
|
|
|
|
|
|
|
+ if current_part and len(current_part) + len(line) + 1 > max_length:
|
|
|
parts.append(current_part)
|
|
parts.append(current_part)
|
|
|
- current_part = line + '\n'
|
|
|
|
|
- else:
|
|
|
|
|
- current_part += line + '\n'
|
|
|
|
|
-
|
|
|
|
|
|
|
+ current_part = ""
|
|
|
|
|
+ while len(line) > max_length:
|
|
|
|
|
+ parts.append(line[:max_length])
|
|
|
|
|
+ line = line[max_length:]
|
|
|
|
|
+ if line:
|
|
|
|
|
+ current_part += line
|
|
|
|
|
+ if len(current_part) < max_length:
|
|
|
|
|
+ current_part += '\n'
|
|
|
|
|
+
|
|
|
if current_part:
|
|
if current_part:
|
|
|
parts.append(current_part)
|
|
parts.append(current_part)
|
|
|
|
|
|
|
@@ -193,13 +199,10 @@ def resize_image(image_bytes, attachment_filename=None):
|
|
|
"""Redimensionne l'image selon le mode spécifié."""
|
|
"""Redimensionne l'image selon le mode spécifié."""
|
|
|
|
|
|
|
|
with Image.open(BytesIO(image_bytes)) as img:
|
|
with Image.open(BytesIO(image_bytes)) as img:
|
|
|
- original_format = img.format # Stocker le format original
|
|
|
|
|
-
|
|
|
|
|
img.thumbnail((2000, 2000))
|
|
img.thumbnail((2000, 2000))
|
|
|
|
|
|
|
|
buffer = BytesIO()
|
|
buffer = BytesIO()
|
|
|
- img_format = img.format or _infer_image_format(attachment_filename)
|
|
|
|
|
- img.save(buffer, format=img_format)
|
|
|
|
|
|
|
+ img.convert("RGB").save(buffer, format="JPEG")
|
|
|
|
|
|
|
|
return buffer.getvalue()
|
|
return buffer.getvalue()
|
|
|
|
|
|
|
@@ -252,6 +255,8 @@ class MyDiscordClient(discord.Client):
|
|
|
async def close(self):
|
|
async def close(self):
|
|
|
global openai_client
|
|
global openai_client
|
|
|
|
|
|
|
|
|
|
+ update_status.cancel()
|
|
|
|
|
+
|
|
|
if openai_client is not None:
|
|
if openai_client is not None:
|
|
|
await openai_client.close()
|
|
await openai_client.close()
|
|
|
openai_client = None
|
|
openai_client = None
|
|
@@ -305,8 +310,6 @@ async def call_for_image_analysis(image_data, user_name, user_text=None):
|
|
|
else:
|
|
else:
|
|
|
messages = [prompt] + [message_to_send]
|
|
messages = [prompt] + [message_to_send]
|
|
|
|
|
|
|
|
- await add_to_conversation_history(message_history)
|
|
|
|
|
-
|
|
|
|
|
analysis = await openai_client.chat.completions.create(
|
|
analysis = await openai_client.chat.completions.create(
|
|
|
model=MODEL,
|
|
model=MODEL,
|
|
|
stream=False,
|
|
stream=False,
|
|
@@ -319,6 +322,7 @@ async def call_for_image_analysis(image_data, user_name, user_text=None):
|
|
|
else:
|
|
else:
|
|
|
logger.info(f"Analyse de l'image par l'API : {analysis.choices[0].message.content}")
|
|
logger.info(f"Analyse de l'image par l'API : {analysis.choices[0].message.content}")
|
|
|
|
|
|
|
|
|
|
+ await add_to_conversation_history(message_history)
|
|
|
await add_to_conversation_history({
|
|
await add_to_conversation_history({
|
|
|
"role": "assistant",
|
|
"role": "assistant",
|
|
|
"content": analysis.choices[0].message.content
|
|
"content": analysis.choices[0].message.content
|
|
@@ -589,29 +593,13 @@ async def on_message(message):
|
|
|
analysis = await call_for_image_analysis(image_data, message.author.name, user_text=user_text_to_use)
|
|
analysis = await call_for_image_analysis(image_data, message.author.name, user_text=user_text_to_use)
|
|
|
|
|
|
|
|
reply = filter_message(analysis)
|
|
reply = filter_message(analysis)
|
|
|
- reply = transform_emote(analysis, True)
|
|
|
|
|
|
|
+ reply = transform_emote(reply, True)
|
|
|
|
|
|
|
|
if analysis:
|
|
if analysis:
|
|
|
await temp_msg.delete()
|
|
await temp_msg.delete()
|
|
|
- await message.channel.send(reply)
|
|
|
|
|
-
|
|
|
|
|
- if has_user_text:
|
|
|
|
|
- user_message_text = f"{message.author.name} a envoyé une image avec le messsage : \"{user_text}\"."
|
|
|
|
|
- else:
|
|
|
|
|
- user_message_text = f"{message.author.name} a envoyé une image."
|
|
|
|
|
|
|
+ for part in split_message(reply):
|
|
|
|
|
+ await message.channel.send(part)
|
|
|
|
|
|
|
|
- user_message = {
|
|
|
|
|
- "role": "user",
|
|
|
|
|
- "content": f"{user_message_text}"
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- assistant_message = {
|
|
|
|
|
- "role": "assistant",
|
|
|
|
|
- "content": analysis
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- await add_to_conversation_history(user_message)
|
|
|
|
|
- await add_to_conversation_history(assistant_message)
|
|
|
|
|
else:
|
|
else:
|
|
|
await temp_msg.delete()
|
|
await temp_msg.delete()
|
|
|
await message.channel.send("Désolé, je n'ai pas pu analyser l'image.")
|
|
await message.channel.send("Désolé, je n'ai pas pu analyser l'image.")
|
|
@@ -649,6 +637,8 @@ async def on_message(message):
|
|
|
|
|
|
|
|
# Afficher dans la console
|
|
# Afficher dans la console
|
|
|
logging.info(f"Réponse envoyée. ({len(message_parts)} message(s))")
|
|
logging.info(f"Réponse envoyée. ({len(message_parts)} message(s))")
|
|
|
|
|
+ else:
|
|
|
|
|
+ await message.channel.send("Désolé, le modèle ne répond pas pour le moment. Réessaie dans un instant.")
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
await message.channel.send("Franchement, je sais pas quoi te répondre. <:haptriste:358054014262181889>")
|
|
await message.channel.send("Franchement, je sais pas quoi te répondre. <:haptriste:358054014262181889>")
|
|
|
logger.error(f"Erreur lors du traitement du texte: {e}")
|
|
logger.error(f"Erreur lors du traitement du texte: {e}")
|
|
@@ -690,14 +680,14 @@ async def before_update_status():
|
|
|
|
|
|
|
|
# Démarrer le bot Discord
|
|
# Démarrer le bot Discord
|
|
|
async def exit_app(signum=None):
|
|
async def exit_app(signum=None):
|
|
|
- globals.logger.debug("Received signal {}".format(signum))
|
|
|
|
|
- globals.logger.info("Closing all tasks...")
|
|
|
|
|
|
|
+ logger.debug("Received signal {}".format(signum))
|
|
|
|
|
+ logger.info("Closing all tasks...")
|
|
|
|
|
|
|
|
# On ferme la connexion à Discord
|
|
# On ferme la connexion à Discord
|
|
|
if client_discord:
|
|
if client_discord:
|
|
|
await client_discord.close()
|
|
await client_discord.close()
|
|
|
|
|
|
|
|
- globals.logger.critical("Script halted.")
|
|
|
|
|
|
|
+ logger.critical("Script halted.")
|
|
|
|
|
|
|
|
def handle_signal(signum, frame):
|
|
def handle_signal(signum, frame):
|
|
|
loop = asyncio.get_event_loop()
|
|
loop = asyncio.get_event_loop()
|
|
@@ -713,4 +703,4 @@ if __name__ == "__main__":
|
|
|
# Démarrer le bot Discord
|
|
# Démarrer le bot Discord
|
|
|
client_discord.run(DISCORD_TOKEN)
|
|
client_discord.run(DISCORD_TOKEN)
|
|
|
except Exception as e:
|
|
except Exception as e:
|
|
|
- globals.logger.error("Encountered exception while running the bot: {}".format(e))
|
|
|
|
|
|
|
+ logger.error("Encountered exception while running the bot: {}".format(e))
|