mission-control-v2 / core /file_builder.py
vfven's picture
Update core/file_builder.py
f3a144b verified
Raw
History Blame
3.86 kB
# 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
def build_excel(task: str, excel_data: dict) -> Path | None:
wb = openpyxl.Workbook()
ws = wb.active
ws.title = excel_data.get("sheet_name", "Hoja1")[:31]
title = excel_data.get("title", task[:50])
headers = excel_data.get("headers", [])
rows = excel_data.get("sample_rows", [])
# Título
if title and headers:
ws.merge_cells(f"A1:{chr(64 + len(headers))}1")
cell = ws["A1"]
cell.value = title
cell.font = Font(bold=True, size=14, color="FFFFFF")
cell.fill = PatternFill("solid", fgColor="1A56DB")
cell.alignment = Alignment(horizontal="center", vertical="center")
ws.row_dimensions[1].height = 30
# Headers
for col, h in enumerate(headers, 1):
cell = ws.cell(row=2, column=col, value=h)
cell.font = Font(bold=True, color="FFFFFF")
cell.fill = PatternFill("solid", fgColor="2563EB")
cell.alignment = Alignment(horizontal="center", vertical="center")
# Datos
for r_idx, row in enumerate(rows, 3):
for c_idx, val in enumerate(row, 1):
ws.cell(row=r_idx, column=c_idx, value=val)
safe = "".join(c for c in task if c.isalnum() or c in (' ', '-'))[:30]
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
path = DOCS_DIR / f"{safe}_{ts}.xlsx"
wb.save(path)
return path