Intelex / backend /api /export.py
yakub
Initial cloud-ready commit
b2b6341
Raw
History Blame Contribute Delete
2.77 kB
from fastapi import APIRouter, HTTPException
from fastapi.responses import FileResponse
from pydantic import BaseModel
from fpdf import FPDF
import os
import tempfile
import uuid
router = APIRouter()
class ExportRequest(BaseModel):
title: str
content: str
citations: list[dict] = []
class PDFGenerator(FPDF):
def header(self):
self.set_font('helvetica', 'B', 12)
self.cell(0, 10, 'InteleX Research Memorandum', 0, 1, 'C')
self.ln(5)
def footer(self):
self.set_y(-15)
self.set_font('helvetica', 'I', 8)
self.cell(0, 10, f'Page {self.page_no()}', 0, 0, 'C')
import re
def _clean_text(text: str) -> str:
"""Strip emojis and non-latin characters that crash FPDF."""
if not text:
return " "
# Remove markdown headers
text = text.replace('#', '').replace('*', '')
# Keep only common latin characters and punctuation for standard fonts
cleaned = re.sub(r'[^\x00-\x7F]+', '', text)
return cleaned if cleaned.strip() else "[Non-supported characters]"
@router.post("/pdf")
async def export_pdf(req: ExportRequest):
try:
pdf = PDFGenerator()
pdf.add_page()
# Ensure we are at the left margin to avoid "horizontal space" errors
pdf.set_x(pdf.l_margin)
# Title
pdf.set_font("helvetica", 'B', 16)
title = _clean_text(req.title)
pdf.multi_cell(0, 10, title)
pdf.ln(10)
# Content
pdf.set_font("helvetica", '', 11)
content = _clean_text(req.content)
pdf.set_x(pdf.l_margin) # Reset X before body
pdf.multi_cell(0, 7, content)
# Citations
if req.citations:
pdf.ln(10)
pdf.set_font("helvetica", 'B', 12)
pdf.set_x(pdf.l_margin)
pdf.cell(0, 10, 'Sources & Citations', 0, 1)
pdf.set_font("helvetica", '', 9)
for i, cite in enumerate(req.citations):
source_title = cite.get('source_title') or cite.get('sourceTitle') or "Source"
ref = cite.get('reference') or ""
text = f"[{i+1}] {source_title} - {ref}"
pdf.set_x(pdf.l_margin)
pdf.multi_cell(0, 5, _clean_text(text))
# Save to temp file
tmp_dir = tempfile.gettempdir()
filename = f"research_{uuid.uuid4().hex[:8]}.pdf"
filepath = os.path.join(tmp_dir, filename)
pdf.output(filepath)
return FileResponse(
path=filepath,
filename=filename,
media_type='application/pdf'
)
except Exception as e:
print(f"[Export] PDF Error: {e}")
raise HTTPException(status_code=500, detail=str(e))