# core/file_builder.py from pathlib import Path from io import BytesIO from datetime import datetime from docx import Document from docx.shared import Inches, Pt, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH import openpyxl from openpyxl.styles import Font, PatternFill, Alignment, Border, Side DOCS_DIR = Path("data/docs") DOCS_DIR.mkdir(parents=True, exist_ok=True) def build_docx(title: str, content: str, images: list[bytes] = None) -> Path | None: doc = Document() # Configuración básica section = doc.sections[0] section.top_margin = section.bottom_margin = Inches(1) section.left_margin = section.right_margin = Inches(1.2) # Título p = doc.add_heading(title, 0) p.alignment = WD_ALIGN_PARAGRAPH.CENTER if p.runs: run = p.runs[0] run.font.color.rgb = RGBColor(0x1a, 0x56, 0xdb) # Fecha doc.add_paragraph(f"Generado por Mission Control AI — {datetime.now().strftime('%B %d, %Y')}", style='Italic') doc.add_paragraph() # Procesar contenido markdown-like lines = content.splitlines() current_p = None for line in lines: line = line.strip() if not line: continue if line.startswith('## '): doc.add_heading(line[3:], level=1) elif line.startswith('### '): doc.add_heading(line[4:], level=2) elif line.startswith('- ') or line.startswith('* '): p = doc.add_paragraph(line[2:], style='List Bullet') else: if current_p is None: current_p = doc.add_paragraph() current_p.add_run(line + " ") # Insertar imágenes si existen if images: for img_bytes in images: try: doc.add_picture(BytesIO(img_bytes), width=Inches(5)) last_p = doc.paragraphs[-1] last_p.alignment = WD_ALIGN_PARAGRAPH.CENTER except: pass # Pie de página p = doc.add_paragraph("— Generado por Mission Control AI —") p.alignment = WD_ALIGN_PARAGRAPH.CENTER if p.runs: p.runs[0].italic = True p.runs[0].font.size = Pt(9) p.runs[0].font.color.rgb = RGBColor(0x6b, 0x72, 0x80) # Guardar safe_title = "".join(c for c in title if c.isalnum() or c in " -_")[:40] timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = DOCS_DIR / f"{safe_title}_{timestamp}.docx" doc.save(filename) return filename