import json from pathlib import Path from fpdf import FPDF import unicodedata def clean_text(text): if not text: return "N/A" # Replace unicode quotes and dashes with ascii equivalents to avoid FPDF errors with Latin-1 text = str(text) text = text.replace('"', '"').replace('"', '"').replace('"', "'").replace('"', "'") text = text.replace('—', '-').replace('–', '-') # Normalize to nearest ascii character res = unicodedata.normalize('NFKD', text).encode('ascii', 'ignore').decode('ascii') res = res.strip() if not res: return "N/A" # Break up extremely long words that crash FPDF res = " ".join([word[:50] for word in res.split()]) return res def generate_political_pdf(selected_articles, job_dir): job_dir = Path(job_dir) images_dir = job_dir / "all_political_images" if not images_dir.exists() or not selected_articles: return pdf = FPDF() pdf.set_auto_page_break(auto=True, margin=15) # Sort articles: high priority first high = [a for a in selected_articles if a.get("priority") == "high"] medium = [a for a in selected_articles if a.get("priority") == "medium"] sorted_articles = high + medium for i, art in enumerate(sorted_articles, 1): pdf.add_page() # Add Header pdf.set_font("helvetica", "B", 16) priority = str(art.get("priority", "N/A")).upper() pdf.cell(0, 10, f"Article {i} - {priority} PRIORITY", new_x="LMARGIN", new_y="NEXT", align="C") pdf.ln(5) # Details pdf.set_font("helvetica", "B", 12) pdf.multi_cell(0, 8, f"Headline: {clean_text(art.get('headline_english'))}", new_x="LMARGIN", new_y="NEXT") pdf.multi_cell(0, 8, f"Category: {clean_text(art.get('category')).upper()}", new_x="LMARGIN", new_y="NEXT") pdf.set_font("helvetica", "", 12) pdf.multi_cell(0, 8, f"Why: {clean_text(art.get('political_significance'))}", new_x="LMARGIN", new_y="NEXT") pdf.multi_cell(0, 8, f"Attack Angle: {clean_text(art.get('attack_angle'))}", new_x="LMARGIN", new_y="NEXT") pdf.ln(5) # Image art_id = art.get("id") img_name = f"{art_id}.png" if art_id else None if img_name: img_path = images_dir / img_name if img_path.exists(): # Get image dimensions to scale it properly if needed try: pdf.image(str(img_path), w=180) except Exception as e: print(f"Error adding image to PDF: {e}") output_path = job_dir / "political_articles_insights.pdf" try: pdf.output(str(output_path)) print(f"Successfully generated PDF report at {output_path}") except Exception as e: print(f"Failed to generate PDF: {e}")