first commit
This commit is contained in:
commit
e6c52820cd
227 changed files with 16156 additions and 0 deletions
89
modules/email/draft_handler.py
Normal file
89
modules/email/draft_handler.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import os
|
||||
import json
|
||||
from typing import List, Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
|
||||
from modules.email.draft import EmailDraft
|
||||
|
||||
|
||||
class DraftHandler:
|
||||
"""
|
||||
Gestionnaire de brouillons (fichiers JSON).
|
||||
Répertoire: Data/email_drafts
|
||||
"""
|
||||
def __init__(self, base_dir: Optional[str] = None):
|
||||
base_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
self.base_dir = base_dir or os.path.join(base_root, "Data", "email_drafts")
|
||||
os.makedirs(self.base_dir, exist_ok=True)
|
||||
|
||||
def _draft_path(self, draft_id: str) -> str:
|
||||
return os.path.join(self.base_dir, f"{draft_id}.json")
|
||||
|
||||
def add_draft(self, draft: EmailDraft) -> str:
|
||||
path = self._draft_path(draft.id)
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(draft.to_dict(), f, ensure_ascii=False, indent=2)
|
||||
return draft.id
|
||||
|
||||
def get_draft(self, draft_id: str) -> Optional[EmailDraft]:
|
||||
path = self._draft_path(draft_id)
|
||||
if not os.path.exists(path):
|
||||
return None
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return EmailDraft.from_dict(json.load(f))
|
||||
|
||||
def update_draft(self, draft: EmailDraft) -> bool:
|
||||
path = self._draft_path(draft.id)
|
||||
if not os.path.exists(path):
|
||||
return False
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(draft.to_dict(), f, ensure_ascii=False, indent=2)
|
||||
return True
|
||||
|
||||
def delete_draft(self, draft_id: str) -> bool:
|
||||
path = self._draft_path(draft_id)
|
||||
if os.path.exists(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
return False
|
||||
|
||||
def list_drafts(self, status: Optional[str] = None) -> List[EmailDraft]:
|
||||
drafts: List[EmailDraft] = []
|
||||
for filename in os.listdir(self.base_dir):
|
||||
if filename.endswith(".json"):
|
||||
try:
|
||||
with open(os.path.join(self.base_dir, filename), "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
d = EmailDraft.from_dict(data)
|
||||
if status is None or d.status == status:
|
||||
drafts.append(d)
|
||||
except Exception:
|
||||
continue
|
||||
# Tri: plus récents d'abord
|
||||
drafts.sort(key=lambda d: d.created_at or "", reverse=True)
|
||||
return drafts
|
||||
|
||||
def list_pending(self) -> List[EmailDraft]:
|
||||
return self.list_drafts(status="draft")
|
||||
|
||||
def mark_sent(self, draft_id: str, success: bool, error_message: Optional[str] = None) -> bool:
|
||||
d = self.get_draft(draft_id)
|
||||
if not d:
|
||||
return False
|
||||
d.status = "sent" if success else "failed"
|
||||
d.sent_at = datetime.utcnow().isoformat()
|
||||
d.error_message = None if success else (error_message or "Unknown error")
|
||||
return self.update_draft(d)
|
||||
|
||||
def find_existing_for_task(self, task_id: str) -> Optional[EmailDraft]:
|
||||
"""
|
||||
Évite les doublons: si un draft 'draft' existe déjà pour cette tâche, le renvoie.
|
||||
Les brouillons 'failed' ne bloquent pas la régénération.
|
||||
"""
|
||||
for d in self.list_drafts():
|
||||
if d.task_id == task_id and d.status == "draft":
|
||||
return d
|
||||
return None
|
||||
Loading…
Add table
Add a link
Reference in a new issue