mirror of
https://github.com/Ladebeze66/llm_ticket3.git
synced 2025-12-13 10:46:51 +01:00
230 lines
8.3 KiB
Python
230 lines
8.3 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
Script pour extraire les images manquantes des messages HTML dans un ticket Odoo
|
|
et les ajouter aux pièces jointes.
|
|
"""
|
|
|
|
import os
|
|
import json
|
|
import re
|
|
import requests
|
|
import sys
|
|
import shutil
|
|
import argparse
|
|
from datetime import datetime
|
|
from typing import Dict, List, Any, Optional, Tuple
|
|
|
|
def load_json_file(file_path: str) -> Any:
|
|
"""
|
|
Charge un fichier JSON.
|
|
|
|
Args:
|
|
file_path: Chemin du fichier JSON à charger
|
|
|
|
Returns:
|
|
Contenu du fichier JSON
|
|
"""
|
|
try:
|
|
if os.path.exists(file_path):
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
return json.load(f)
|
|
else:
|
|
return None
|
|
except Exception as e:
|
|
print(f"Erreur lors du chargement du fichier {file_path}: {e}")
|
|
return None
|
|
|
|
def save_json_file(file_path: str, data: Any) -> bool:
|
|
"""
|
|
Sauvegarde des données dans un fichier JSON.
|
|
|
|
Args:
|
|
file_path: Chemin du fichier JSON à sauvegarder
|
|
data: Données à sauvegarder
|
|
|
|
Returns:
|
|
True si la sauvegarde a réussi, False sinon
|
|
"""
|
|
try:
|
|
with open(file_path, 'w', encoding='utf-8') as f:
|
|
json.dump(data, f, indent=2, ensure_ascii=False)
|
|
return True
|
|
except Exception as e:
|
|
print(f"Erreur lors de la sauvegarde du fichier {file_path}: {e}")
|
|
return False
|
|
|
|
def download_image(url: str, save_path: str) -> bool:
|
|
"""
|
|
Télécharge une image depuis une URL.
|
|
|
|
Args:
|
|
url: URL de l'image à télécharger
|
|
save_path: Chemin où sauvegarder l'image
|
|
|
|
Returns:
|
|
True si le téléchargement a réussi, False sinon
|
|
"""
|
|
try:
|
|
# Créer le répertoire parent si nécessaire
|
|
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
|
|
|
# Télécharger l'image
|
|
response = requests.get(url, stream=True)
|
|
|
|
if response.status_code == 200:
|
|
with open(save_path, 'wb') as f:
|
|
response.raw.decode_content = True
|
|
shutil.copyfileobj(response.raw, f)
|
|
print(f"Image téléchargée et sauvegardée dans: {save_path}")
|
|
return True
|
|
else:
|
|
print(f"Erreur lors du téléchargement de l'image: {response.status_code}")
|
|
return False
|
|
except Exception as e:
|
|
print(f"Erreur lors du téléchargement de l'image: {e}")
|
|
return False
|
|
|
|
def extract_missing_attachments(ticket_dir: str) -> None:
|
|
"""
|
|
Extrait les images manquantes d'un ticket et les ajoute aux pièces jointes.
|
|
|
|
Args:
|
|
ticket_dir: Répertoire du ticket
|
|
"""
|
|
# Vérifier que le répertoire existe
|
|
if not os.path.exists(ticket_dir):
|
|
print(f"Répertoire introuvable: {ticket_dir}")
|
|
return
|
|
|
|
# Chemins des fichiers
|
|
messages_file = os.path.join(ticket_dir, "all_messages.json")
|
|
attachments_file = os.path.join(ticket_dir, "attachments_info.json")
|
|
attachments_dir = os.path.join(ticket_dir, "attachments")
|
|
|
|
# Vérifier que les fichiers nécessaires existent
|
|
if not os.path.exists(messages_file):
|
|
print(f"Fichier de messages introuvable: {messages_file}")
|
|
return
|
|
|
|
# Charger les messages
|
|
messages_data = load_json_file(messages_file)
|
|
if not messages_data:
|
|
print("Impossible de charger les messages")
|
|
return
|
|
|
|
# Charger les pièces jointes existantes
|
|
attachments_info = load_json_file(attachments_file) or []
|
|
|
|
# Vérifier si le dossier des attachements existe, sinon le créer
|
|
if not os.path.exists(attachments_dir):
|
|
os.makedirs(attachments_dir)
|
|
|
|
# Extraire les IDs des pièces jointes existantes
|
|
existing_attachment_ids = set()
|
|
for attachment in attachments_info:
|
|
if "id" in attachment:
|
|
existing_attachment_ids.add(attachment["id"])
|
|
|
|
# Parcourir les messages pour trouver les images manquantes
|
|
messages = messages_data.get("messages", [])
|
|
newly_added_attachments = []
|
|
|
|
for message in messages:
|
|
message_id = message.get("id")
|
|
|
|
# Traiter uniquement les messages avec body_original contenant des images
|
|
body_original = message.get("body_original", "")
|
|
if not body_original:
|
|
continue
|
|
|
|
# Chercher toutes les références d'images
|
|
image_matches = re.finditer(r'<img[^>]+src=["\']([^"\']+)["\'][^>]*>', body_original)
|
|
|
|
for match in image_matches:
|
|
img_url = match.group(1)
|
|
|
|
# Extraire l'ID de l'image
|
|
img_id = None
|
|
access_token = None
|
|
|
|
# Pattern 1: /web/image/ID?access_token=...
|
|
id_match = re.search(r"/web/image/(\d+)", img_url)
|
|
if id_match:
|
|
img_id = int(id_match.group(1))
|
|
|
|
# Extraire le token d'accès
|
|
token_match = re.search(r"access_token=([^&]+)", img_url)
|
|
if token_match:
|
|
access_token = token_match.group(1)
|
|
|
|
# Vérifier si l'image existe déjà dans les pièces jointes
|
|
if img_id and img_id not in existing_attachment_ids:
|
|
print(f"Image manquante trouvée: ID {img_id} dans le message {message_id}")
|
|
|
|
# Déterminer le nom du fichier
|
|
file_name = f"image_{img_id}.png" # Nom par défaut
|
|
|
|
# Chercher un attribut alt ou title qui pourrait contenir le nom
|
|
alt_match = re.search(r'<img[^>]+alt=["\']([^"\']+)["\'][^>]*>', match.group(0))
|
|
if alt_match and alt_match.group(1).strip():
|
|
alt_text = alt_match.group(1).strip()
|
|
# Nettoyer et limiter la longueur du nom
|
|
alt_text = re.sub(r'[^\w\s.-]', '', alt_text)
|
|
alt_text = alt_text[:50] # Limiter la longueur
|
|
if alt_text:
|
|
file_name = f"{alt_text}_{img_id}.png"
|
|
|
|
# Chemin de destination pour l'image
|
|
img_save_path = os.path.join(attachments_dir, file_name)
|
|
|
|
# Télécharger l'image
|
|
if download_image(img_url, img_save_path):
|
|
# Taille du fichier
|
|
file_size = os.path.getsize(img_save_path)
|
|
|
|
# Ajouter l'information de la pièce jointe
|
|
attachment_info = {
|
|
"id": img_id,
|
|
"name": file_name,
|
|
"mimetype": "image/png", # Type par défaut
|
|
"file_size": file_size,
|
|
"create_date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
"creator_name": message.get("author_details", {}).get("name", "Inconnu"),
|
|
"download_status": "success",
|
|
"local_path": img_save_path,
|
|
"error": "",
|
|
"was_missing": True,
|
|
"message_id": message_id,
|
|
"access_token": access_token
|
|
}
|
|
|
|
attachments_info.append(attachment_info)
|
|
existing_attachment_ids.add(img_id)
|
|
newly_added_attachments.append(attachment_info)
|
|
|
|
# Sauvegarder immédiatement pour éviter la perte en cas d'erreur
|
|
save_json_file(attachments_file, attachments_info)
|
|
|
|
# Afficher un résumé
|
|
if newly_added_attachments:
|
|
print(f"Ajouté {len(newly_added_attachments)} nouvelles pièces jointes:")
|
|
for att in newly_added_attachments:
|
|
print(f" - {att['name']} (ID: {att['id']}, Taille: {att['file_size']} octets)")
|
|
else:
|
|
print("Aucune nouvelle pièce jointe ajoutée.")
|
|
|
|
def main():
|
|
"""
|
|
Point d'entrée principal du script.
|
|
"""
|
|
parser = argparse.ArgumentParser(description="Extrait les images manquantes des messages HTML dans un ticket Odoo.")
|
|
parser.add_argument("ticket_dir", help="Répertoire du ticket contenant les messages et pièces jointes")
|
|
|
|
args = parser.parse_args()
|
|
|
|
extract_missing_attachments(args.ticket_dir)
|
|
|
|
if __name__ == "__main__":
|
|
main() |