mirror of
https://github.com/Ladebeze66/odoo_toolkit.git
synced 2025-12-13 09:06:52 +01:00
J8
This commit is contained in:
parent
59bafbadb3
commit
ade575f825
Binary file not shown.
299
data_filter.py
299
data_filter.py
@ -7,184 +7,148 @@ import shutil
|
||||
from typing import Dict, List, Any, Optional, Tuple, Union, Set
|
||||
|
||||
|
||||
def is_odoobot_message(message: Dict[str, Any]) -> bool:
|
||||
def is_odoobot_author(message: Dict[str, Any]) -> bool:
|
||||
"""
|
||||
Détecte si un message provient d'OdooBot ou d'un bot système.
|
||||
Vérifie si l'auteur du message est OdooBot ou un autre système.
|
||||
|
||||
Args:
|
||||
message: Dictionnaire du message à analyser
|
||||
message: Le message à vérifier
|
||||
|
||||
Returns:
|
||||
True si le message est d'OdooBot, False sinon
|
||||
True si le message provient d'OdooBot, False sinon
|
||||
"""
|
||||
if not message:
|
||||
return False
|
||||
# Vérifier le nom de l'auteur
|
||||
if 'author_id' in message and isinstance(message['author_id'], list) and len(message['author_id']) > 1:
|
||||
author_name = message['author_id'][1].lower()
|
||||
if 'odoobot' in author_name or 'bot' in author_name or 'système' in author_name:
|
||||
return True
|
||||
|
||||
# Vérifier par le nom de l'auteur
|
||||
author_name = ""
|
||||
if message.get('author_id') and isinstance(message.get('author_id'), list) and len(message.get('author_id')) > 1:
|
||||
author_name = message.get('author_id')[1].lower()
|
||||
elif message.get('author_details', {}).get('name'):
|
||||
author_name = message.get('author_details', {}).get('name', '').lower()
|
||||
|
||||
if 'odoobot' in author_name or 'bot' in author_name or 'système' in author_name or 'system' in author_name:
|
||||
return True
|
||||
|
||||
# Vérifier par le contenu du message (messages système typiques)
|
||||
body = message.get('body', '').lower()
|
||||
if body and isinstance(body, str):
|
||||
system_patterns = [
|
||||
r'assigné à',
|
||||
r'assigned to',
|
||||
r'étape changée',
|
||||
r'stage changed',
|
||||
r'créé automatiquement',
|
||||
r'automatically created',
|
||||
r'a modifié la date limite',
|
||||
r'changed the deadline',
|
||||
r'a ajouté une pièce jointe',
|
||||
r'added an attachment'
|
||||
]
|
||||
|
||||
for pattern in system_patterns:
|
||||
if re.search(pattern, body, re.IGNORECASE):
|
||||
return True
|
||||
|
||||
# Vérifier par le type de message/sous-type
|
||||
# Vérifier le type de message (souvent les notifications système)
|
||||
if message.get('message_type') == 'notification':
|
||||
return True
|
||||
|
||||
subtype_name = ""
|
||||
if message.get('subtype_id') and isinstance(message.get('subtype_id'), list) and len(message.get('subtype_id')) > 1:
|
||||
subtype_name = message.get('subtype_id')[1].lower()
|
||||
elif message.get('subtype_details') and isinstance(message.get('subtype_details'), list) and len(message.get('subtype_details')) > 0:
|
||||
subtype_name = message.get('subtype_details')[0].get('name', '').lower()
|
||||
# Vérifier le sous-type du message
|
||||
if 'subtype_id' in message and isinstance(message['subtype_id'], list) and len(message['subtype_id']) > 1:
|
||||
subtype = message['subtype_id'][1].lower()
|
||||
if 'notification' in subtype or 'system' in subtype:
|
||||
return True
|
||||
|
||||
if subtype_name and ('notification' in subtype_name or 'system' in subtype_name):
|
||||
return True
|
||||
# Vérifier le contenu du message
|
||||
if 'body' in message and isinstance(message['body'], str):
|
||||
body = message['body'].lower()
|
||||
system_patterns = [
|
||||
'assigné à', 'étape changée', 'créé automatiquement',
|
||||
'assigned to', 'stage changed', 'automatically created',
|
||||
'updated', 'mis à jour', 'a modifié', 'changed'
|
||||
]
|
||||
|
||||
for pattern in system_patterns:
|
||||
if pattern in body:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def is_important_image(img_tag: Any, message_text: str) -> bool:
|
||||
def is_important_image(tag, message_text: str) -> bool:
|
||||
"""
|
||||
Détermine si une image est importante ou s'il s'agit d'une image inutile (logo, signature, etc.).
|
||||
Détermine si une image est importante ou s'il s'agit d'un logo/signature.
|
||||
|
||||
Args:
|
||||
img_tag: Balise d'image BeautifulSoup
|
||||
message_text: Texte du message complet pour contexte
|
||||
tag: La balise d'image à analyser
|
||||
message_text: Le texte complet du message pour contexte
|
||||
|
||||
Returns:
|
||||
True si l'image semble importante, False sinon
|
||||
"""
|
||||
# Vérifier les attributs de l'image
|
||||
img_src = img_tag.get('src', '')
|
||||
img_alt = img_tag.get('alt', '')
|
||||
img_class = img_tag.get('class', '')
|
||||
img_style = img_tag.get('style', '')
|
||||
src = tag.get('src', '')
|
||||
alt = tag.get('alt', '')
|
||||
title = tag.get('title', '')
|
||||
css_class = tag.get('class', '')
|
||||
|
||||
# Mots-clés indiquant des images inutiles
|
||||
useless_patterns = [
|
||||
'logo', 'signature', 'footer', 'header', 'separator', 'separateur',
|
||||
'outlook', 'mail_signature', 'icon', 'emoticon', 'emoji', 'cid:',
|
||||
'pixel', 'spacer', 'vignette', 'footer', 'banner', 'banniere'
|
||||
# Patterns pour les images inutiles
|
||||
useless_img_patterns = [
|
||||
'logo', 'signature', 'outlook', 'footer', 'header', 'icon',
|
||||
'emoticon', 'emoji', 'cid:', 'pixel', 'spacer', 'vignette',
|
||||
'banner', 'separator', 'decoration', 'mail_signature'
|
||||
]
|
||||
|
||||
# Vérifier le src/alt/class pour les motifs inutiles
|
||||
for pattern in useless_patterns:
|
||||
if (pattern in img_src.lower() or
|
||||
pattern in img_alt.lower() or
|
||||
(isinstance(img_class, list) and any(pattern in c.lower() for c in img_class)) or
|
||||
(isinstance(img_class, str) and pattern in img_class.lower()) or
|
||||
pattern in img_style.lower()):
|
||||
# Vérifier si c'est une image inutile
|
||||
for pattern in useless_img_patterns:
|
||||
if (pattern in src.lower() or
|
||||
pattern in alt.lower() or
|
||||
pattern in title.lower() or
|
||||
(css_class and any(pattern in c.lower() for c in css_class if isinstance(c, str)))):
|
||||
return False
|
||||
|
||||
# Vérifier les dimensions (logos et icônes sont souvent petits)
|
||||
width = img_tag.get('width', '')
|
||||
height = img_tag.get('height', '')
|
||||
|
||||
# Convertir en entiers si possible
|
||||
# Vérifier la taille (les petites images sont souvent des icônes/logos)
|
||||
width = tag.get('width', '')
|
||||
height = tag.get('height', '')
|
||||
try:
|
||||
width = int(width) if width and width.isdigit() else None
|
||||
height = int(height) if height and height.isdigit() else None
|
||||
except (ValueError, TypeError):
|
||||
# Extraire les dimensions des attributs style si disponibles
|
||||
if img_style:
|
||||
width_match = re.search(r'width:[ ]*(\d+)', img_style)
|
||||
height_match = re.search(r'height:[ ]*(\d+)', img_style)
|
||||
|
||||
width = int(width_match.group(1)) if width_match else None
|
||||
height = int(height_match.group(1)) if height_match else None
|
||||
|
||||
# Images très petites sont souvent des éléments décoratifs
|
||||
if width is not None and height is not None:
|
||||
if width <= 50 and height <= 50: # Taille arbitraire pour les petites images
|
||||
width = int(width) if width and str(width).isdigit() else None
|
||||
height = int(height) if height and str(height).isdigit() else None
|
||||
if width and height and width <= 50 and height <= 50:
|
||||
return False
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
# Rechercher des termes qui indiquent l'importance de l'image dans le texte du message
|
||||
importance_indicators = [
|
||||
# Vérifier si l'image est mentionnée dans le texte
|
||||
image_indicators = [
|
||||
'capture', 'screenshot', 'image', 'photo', 'illustration',
|
||||
'pièce jointe', 'attachment', 'voir', 'regarder', 'ci-joint',
|
||||
'écran', 'erreur', 'problème', 'bug', 'issue'
|
||||
'voir', 'regarder', 'ci-joint', 'écran', 'erreur', 'problème',
|
||||
'bug', 'pièce jointe', 'attachment', 'veuillez trouver'
|
||||
]
|
||||
|
||||
for indicator in importance_indicators:
|
||||
for indicator in image_indicators:
|
||||
if indicator in message_text.lower():
|
||||
return True
|
||||
|
||||
# Par défaut, considérer l'image comme importante si aucun des filtres ci-dessus ne s'applique
|
||||
# Par défaut, considérer les images qui ne sont pas clairement inutiles comme potentiellement importantes
|
||||
return True
|
||||
|
||||
|
||||
def find_relevant_attachments(message_text: str, attachments_info: List[Dict[str, Any]]) -> List[int]:
|
||||
def find_attachment_references(message_text: str, attachments_info: List[Dict[str, Any]]) -> List[int]:
|
||||
"""
|
||||
Trouve les pièces jointes pertinentes mentionnées dans le message.
|
||||
Identifie les pièces jointes mentionnées dans le message.
|
||||
|
||||
Args:
|
||||
message_text: Texte du message
|
||||
attachments_info: Liste des informations sur les pièces jointes
|
||||
attachments_info: Informations sur les pièces jointes disponibles
|
||||
|
||||
Returns:
|
||||
Liste des IDs des pièces jointes pertinentes
|
||||
"""
|
||||
relevant_ids = []
|
||||
|
||||
if not message_text or not attachments_info:
|
||||
return relevant_ids
|
||||
return []
|
||||
|
||||
# Rechercher les mentions de pièces jointes dans le texte
|
||||
# Patterns indiquant des pièces jointes
|
||||
attachment_indicators = [
|
||||
r'pi(è|e)ce(s)? jointe(s)?', r'attachment(s)?', r'fichier(s)?', r'file(s)?',
|
||||
r'voir (le|la|les) document(s)?', r'voir (le|la|les) fichier(s)?',
|
||||
r'voir (le|la|les) image(s)?', r'voir (le|la|les) screenshot(s)?',
|
||||
r'voir (le|la|les) capture(s)?', r'voir (le|la|les) photo(s)?',
|
||||
r'voir ci-joint', r'voir ci-dessous', r'voir ci-après',
|
||||
r'veuillez trouver', r'please find', r'in attachment',
|
||||
r'joint(e)?(s)?', r'attached', r'screenshot(s)?', r'capture(s)? d(\'|e) (é|e)cran',
|
||||
r'image(s)?', r'photo(s)?'
|
||||
r'pi[èe]ce[s]? jointe[s]?', r'attachment[s]?', r'fichier[s]?', r'file[s]?',
|
||||
r'veuillez trouver', r'please find', r'voir ci-joint', r'voir ci-dessous',
|
||||
r'ci-joint', r'joint[e]?[s]?', r'attached', r'screenshot[s]?',
|
||||
r'capture[s]? d[\'e] ?[ée]cran', r'image[s]?', r'photo[s]?'
|
||||
]
|
||||
|
||||
has_attachment_mention = False
|
||||
for indicator in attachment_indicators:
|
||||
if re.search(indicator, message_text, re.IGNORECASE):
|
||||
has_attachment_mention = True
|
||||
relevant_ids = []
|
||||
|
||||
# Vérifier si le message mentionne des pièces jointes
|
||||
mention_found = False
|
||||
for pattern in attachment_indicators:
|
||||
if re.search(pattern, message_text, re.IGNORECASE):
|
||||
mention_found = True
|
||||
break
|
||||
|
||||
# Si le message mentionne des pièces jointes
|
||||
if has_attachment_mention:
|
||||
if mention_found:
|
||||
# Identifier les pièces jointes pertinentes (non logos/images d'interface)
|
||||
for attachment in attachments_info:
|
||||
# Exclure les pièces jointes qui semblent être des signatures ou des logos
|
||||
name = attachment.get('name', '').lower()
|
||||
useless_patterns = ['logo', 'signature', 'outlook', 'footer', 'header', 'icon', 'emoticon', 'emoji']
|
||||
name = attachment.get('name', '').lower() if attachment.get('name') else ''
|
||||
|
||||
is_useless = False
|
||||
for pattern in useless_patterns:
|
||||
if pattern in name:
|
||||
is_useless = True
|
||||
break
|
||||
# Exclure les pièces jointes qui semblent être des logos ou images d'interface
|
||||
useless_patterns = ['logo', 'signature', 'outlook', 'icon', 'emoticon', 'emoji']
|
||||
is_useless = any(pattern in name for pattern in useless_patterns)
|
||||
|
||||
if not is_useless:
|
||||
relevant_ids.append(attachment.get('id'))
|
||||
if not is_useless and 'id' in attachment:
|
||||
relevant_ids.append(attachment['id'])
|
||||
|
||||
return relevant_ids
|
||||
|
||||
@ -192,7 +156,7 @@ def find_relevant_attachments(message_text: str, attachments_info: List[Dict[str
|
||||
def clean_html(html_content: str) -> str:
|
||||
"""
|
||||
Nettoie le contenu HTML en supprimant toutes les balises mais en préservant le texte.
|
||||
Améliore le traitement des images, supprime les signatures et les éléments inutiles.
|
||||
Traite spécifiquement les images pour garder uniquement celles pertinentes.
|
||||
|
||||
Args:
|
||||
html_content: Contenu HTML à nettoyer
|
||||
@ -206,41 +170,38 @@ def clean_html(html_content: str) -> str:
|
||||
# Utiliser BeautifulSoup pour manipuler le HTML
|
||||
soup = BeautifulSoup(html_content, 'html.parser')
|
||||
|
||||
# Supprimer les signatures et pieds de courriels typiques
|
||||
signature_selectors = [
|
||||
# Supprimer les éléments de signature
|
||||
signature_elements = [
|
||||
'div.signature', '.gmail_signature', '.signature',
|
||||
'hr + div', 'hr + p', '.footer', '.mail-signature',
|
||||
'.ms-signature', '[data-smartmail="gmail_signature"]'
|
||||
'hr + div', 'hr + p', '.footer', '.mail-signature'
|
||||
]
|
||||
|
||||
for selector in signature_selectors:
|
||||
for selector in signature_elements:
|
||||
for element in soup.select(selector):
|
||||
element.decompose()
|
||||
|
||||
# Supprimer les lignes horizontales qui séparent souvent les signatures
|
||||
# Supprimer les lignes horizontales (souvent utilisées pour séparer les signatures)
|
||||
for hr in soup.find_all('hr'):
|
||||
hr.decompose()
|
||||
|
||||
# Récupérer le texte complet pour analyse
|
||||
full_text = soup.get_text(' ', strip=True)
|
||||
|
||||
# Traiter les images
|
||||
message_text = soup.get_text()
|
||||
for img in soup.find_all('img'):
|
||||
if is_important_image(img, message_text):
|
||||
if is_important_image(img, full_text):
|
||||
# Remplacer les images importantes par une description
|
||||
alt_text = img.get('alt', '') or img.get('title', '') or '[Image importante]'
|
||||
img.replace_with(f" [Image: {alt_text}] ")
|
||||
else:
|
||||
# Supprimer les images inutiles
|
||||
# Supprimer les images non pertinentes
|
||||
img.decompose()
|
||||
|
||||
# Traiter les références aux pièces jointes
|
||||
attachment_refs = soup.find_all('a', href=re.compile(r'attachment|piece|fichier|file', re.IGNORECASE))
|
||||
for ref in attachment_refs:
|
||||
ref.replace_with(f" [Pièce jointe: {ref.get_text()}] ")
|
||||
|
||||
# Filtrer les éléments vides ou non significatifs
|
||||
for tag in soup.find_all(['span', 'div', 'p']):
|
||||
if not tag.get_text(strip=True):
|
||||
tag.decompose()
|
||||
# Traiter les liens vers des pièces jointes
|
||||
for a in soup.find_all('a', href=True):
|
||||
href = a.get('href', '').lower()
|
||||
if 'attachment' in href or 'download' in href or 'file' in href:
|
||||
a.replace_with(f" [Pièce jointe: {a.get_text()}] ")
|
||||
|
||||
# Récupérer le texte sans balises HTML
|
||||
text = soup.get_text(separator=' ', strip=True)
|
||||
@ -254,7 +215,7 @@ def clean_html(html_content: str) -> str:
|
||||
# Nettoyer les lignes vides multiples
|
||||
text = re.sub(r'\n\s*\n', '\n\n', text)
|
||||
|
||||
# Supprimer les footers typiques des emails
|
||||
# Supprimer les disclaimers et signatures standards
|
||||
footer_patterns = [
|
||||
r'Sent from my .*',
|
||||
r'Envoyé depuis mon .*',
|
||||
@ -267,12 +228,7 @@ def clean_html(html_content: str) -> str:
|
||||
r'This message and any attachments.*',
|
||||
r'Ce message et ses pièces jointes.*',
|
||||
r'AVIS DE CONFIDENTIALITÉ.*',
|
||||
r'PRIVACY NOTICE.*',
|
||||
r'Droit à la déconnexion.*',
|
||||
r'L\'objectif du Support Technique.*',
|
||||
r'\\*\\*\\*\\*\\*\\* ATTENTION \\*\\*\\*\\*\\*\\*.*',
|
||||
r'Please consider the environment.*',
|
||||
r'Pensez à l\'environnement.*'
|
||||
r'PRIVACY NOTICE.*'
|
||||
]
|
||||
|
||||
for pattern in footer_patterns:
|
||||
@ -288,14 +244,14 @@ def process_message_file(message_file_path: str, output_dir: str, attachments_in
|
||||
Args:
|
||||
message_file_path: Chemin du fichier de message à traiter
|
||||
output_dir: Répertoire de sortie pour le fichier traité
|
||||
attachments_info: Informations sur les pièces jointes (optionnel)
|
||||
attachments_info: Informations sur les pièces jointes disponibles
|
||||
"""
|
||||
try:
|
||||
with open(message_file_path, 'r', encoding='utf-8') as f:
|
||||
message_data = json.load(f)
|
||||
|
||||
# Ignorer les messages d'OdooBot
|
||||
if is_odoobot_message(message_data):
|
||||
if is_odoobot_author(message_data):
|
||||
print(f"Message ignoré (OdooBot): {os.path.basename(message_file_path)}")
|
||||
return
|
||||
|
||||
@ -304,9 +260,9 @@ def process_message_file(message_file_path: str, output_dir: str, attachments_in
|
||||
# Remplacer le contenu HTML par le texte filtré
|
||||
message_data['body'] = clean_html(message_data['body'])
|
||||
|
||||
# Identifier les pièces jointes pertinentes si disponibles
|
||||
# Identifier les pièces jointes pertinentes mentionnées dans le message
|
||||
if attachments_info and message_data['body']:
|
||||
relevant_attachments = find_relevant_attachments(message_data['body'], attachments_info)
|
||||
relevant_attachments = find_attachment_references(message_data['body'], attachments_info)
|
||||
if relevant_attachments:
|
||||
message_data['relevant_attachment_ids'] = relevant_attachments
|
||||
|
||||
@ -328,48 +284,44 @@ def process_messages_threads(threads_file_path: str, output_dir: str, attachment
|
||||
Args:
|
||||
threads_file_path: Chemin du fichier de threads de messages
|
||||
output_dir: Répertoire de sortie pour le fichier traité
|
||||
attachments_info: Informations sur les pièces jointes (optionnel)
|
||||
attachments_info: Informations sur les pièces jointes disponibles
|
||||
"""
|
||||
try:
|
||||
with open(threads_file_path, 'r', encoding='utf-8') as f:
|
||||
threads_data = json.load(f)
|
||||
|
||||
# Stocker les IDs des threads à supprimer (qui ne contiennent que des messages d'OdooBot)
|
||||
# Liste des threads à supprimer (ceux qui ne contiennent que des messages d'OdooBot)
|
||||
threads_to_remove = []
|
||||
|
||||
# Parcourir tous les threads
|
||||
for thread_id, thread in threads_data.items():
|
||||
|
||||
# Vérifier si le message principal existe et n'est pas d'OdooBot
|
||||
# Traiter le message principal
|
||||
main_message_is_bot = False
|
||||
if thread.get('main_message'):
|
||||
if is_odoobot_message(thread['main_message']):
|
||||
if is_odoobot_author(thread['main_message']):
|
||||
main_message_is_bot = True
|
||||
# Si c'est un message d'OdooBot, on le supprime
|
||||
thread['main_message'] = None
|
||||
elif 'body' in thread['main_message']:
|
||||
# Sinon, on nettoie le corps du message
|
||||
thread['main_message']['body'] = clean_html(thread['main_message']['body'])
|
||||
|
||||
# Identifier les pièces jointes pertinentes
|
||||
if attachments_info and thread['main_message']['body']:
|
||||
relevant_attachments = find_relevant_attachments(
|
||||
relevant_attachments = find_attachment_references(
|
||||
thread['main_message']['body'], attachments_info
|
||||
)
|
||||
if relevant_attachments:
|
||||
thread['main_message']['relevant_attachment_ids'] = relevant_attachments
|
||||
|
||||
# Filtrer les réponses pour supprimer celles d'OdooBot
|
||||
# Traiter les réponses (filtrer les messages d'OdooBot)
|
||||
filtered_replies = []
|
||||
for reply in thread.get('replies', []):
|
||||
if not is_odoobot_message(reply):
|
||||
# Nettoyer le corps du message
|
||||
if not is_odoobot_author(reply):
|
||||
if 'body' in reply:
|
||||
reply['body'] = clean_html(reply['body'])
|
||||
|
||||
# Identifier les pièces jointes pertinentes
|
||||
if attachments_info and reply['body']:
|
||||
relevant_attachments = find_relevant_attachments(reply['body'], attachments_info)
|
||||
relevant_attachments = find_attachment_references(reply['body'], attachments_info)
|
||||
if relevant_attachments:
|
||||
reply['relevant_attachment_ids'] = relevant_attachments
|
||||
|
||||
@ -378,8 +330,7 @@ def process_messages_threads(threads_file_path: str, output_dir: str, attachment
|
||||
# Mettre à jour les réponses
|
||||
thread['replies'] = filtered_replies
|
||||
|
||||
# Si le thread ne contient plus de messages (tous étaient des messages d'OdooBot),
|
||||
# marquer pour suppression
|
||||
# Si le thread ne contient que des messages de bot, le marquer pour suppression
|
||||
if main_message_is_bot and not filtered_replies:
|
||||
threads_to_remove.append(thread_id)
|
||||
|
||||
@ -394,7 +345,7 @@ def process_messages_threads(threads_file_path: str, output_dir: str, attachment
|
||||
|
||||
print(f"Fichier de threads traité: {os.path.basename(threads_file_path)}")
|
||||
if threads_to_remove:
|
||||
print(f" {len(threads_to_remove)} threads supprimés (messages d'OdooBot uniquement)")
|
||||
print(f" {len(threads_to_remove)} threads supprimés (OdooBot uniquement)")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Erreur lors du traitement du fichier {threads_file_path}: {e}")
|
||||
@ -407,7 +358,7 @@ def process_messages_collection(messages_file_path: str, output_dir: str, attach
|
||||
Args:
|
||||
messages_file_path: Chemin du fichier de collection de messages
|
||||
output_dir: Répertoire de sortie pour le fichier traité
|
||||
attachments_info: Informations sur les pièces jointes (optionnel)
|
||||
attachments_info: Informations sur les pièces jointes disponibles
|
||||
"""
|
||||
try:
|
||||
with open(messages_file_path, 'r', encoding='utf-8') as f:
|
||||
@ -416,14 +367,14 @@ def process_messages_collection(messages_file_path: str, output_dir: str, attach
|
||||
# Filtrer les messages pour supprimer ceux d'OdooBot
|
||||
filtered_messages = []
|
||||
for message in messages_data:
|
||||
if not is_odoobot_message(message):
|
||||
# Nettoyer le corps du message
|
||||
if not is_odoobot_author(message):
|
||||
# Nettoyer le contenu HTML
|
||||
if 'body' in message:
|
||||
message['body'] = clean_html(message['body'])
|
||||
|
||||
# Identifier les pièces jointes pertinentes
|
||||
if attachments_info and message['body']:
|
||||
relevant_attachments = find_relevant_attachments(message['body'], attachments_info)
|
||||
relevant_attachments = find_attachment_references(message['body'], attachments_info)
|
||||
if relevant_attachments:
|
||||
message['relevant_attachment_ids'] = relevant_attachments
|
||||
|
||||
@ -464,7 +415,7 @@ def process_ticket_folder(ticket_folder: str, output_base_dir: str) -> None:
|
||||
shutil.copy2(src_file, dst_file)
|
||||
print(f"Fichier copié: {file_name}")
|
||||
|
||||
# Charger les informations sur les pièces jointes si disponibles
|
||||
# Charger les informations sur les pièces jointes
|
||||
attachments_info = []
|
||||
attachments_info_file = os.path.join(ticket_folder, 'attachments_info.json')
|
||||
if os.path.exists(attachments_info_file):
|
||||
@ -502,7 +453,7 @@ def process_ticket_folder(ticket_folder: str, output_base_dir: str) -> None:
|
||||
if os.path.exists(message_threads_file):
|
||||
process_messages_threads(message_threads_file, output_ticket_dir, attachments_info)
|
||||
|
||||
# Copier le répertoire des pièces jointes (on conserve toutes les pièces jointes)
|
||||
# Copier le répertoire des pièces jointes (on garde toutes les pièces jointes)
|
||||
src_attachments_dir = os.path.join(ticket_folder, 'attachments')
|
||||
if os.path.exists(src_attachments_dir):
|
||||
dst_attachments_dir = os.path.join(output_ticket_dir, 'attachments')
|
||||
@ -556,9 +507,9 @@ def run_filter_wizard() -> None:
|
||||
print("\n==== FILTRAGE DES MESSAGES DES TICKETS ====")
|
||||
print("Cette fonction va:")
|
||||
print("1. Supprimer les messages provenant d'OdooBot")
|
||||
print("2. Supprimer les logos, signatures et images non pertinentes")
|
||||
print("3. Conserver uniquement le texte utile des messages")
|
||||
print("4. Identifier les pièces jointes mentionnées dans les messages\n")
|
||||
print("2. Filtrer les images inutiles (logos, signatures, images Outlook)")
|
||||
print("3. Conserver les images pertinentes pour la demande")
|
||||
print("4. Identifier les pièces jointes importantes mentionnées dans les messages\n")
|
||||
|
||||
# Demander le répertoire source
|
||||
default_source = 'exported_tickets'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user