""" Module for generating PDF reports with meeting analysis results. Uses reportlab to create well-formatted documents. """ import os import tempfile from datetime import datetime from typing import Dict, Optional try: from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak from reportlab.lib import colors except ImportError: A4 = None getSampleStyleSheet = None ParagraphStyle = None inch = None SimpleDocTemplate = None Paragraph = None Spacer = None PageBreak = None colors = None # Configurazione logging import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def generate_pdf(meeting_data: Dict) -> Optional[str]: """ Generate a PDF with meeting analysis results. Args: meeting_data (Dict): Meeting data with summary, topics, keywords Returns: Optional[str]: Path to generated PDF file or None if error """ if not meeting_data: logger.error("Meeting data not provided") return None if SimpleDocTemplate is None: logger.error("reportlab not installed. Install with: pip install reportlab") return None try: # Create temporary file temp_dir = tempfile.gettempdir() timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") pdf_filename = f"meeting_summary_{timestamp}.pdf" pdf_path = os.path.join(temp_dir, pdf_filename) # Create PDF document doc = SimpleDocTemplate( pdf_path, pagesize=A4, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18 ) # Custom styles styles = getSampleStyleSheet() # Title style title_style = ParagraphStyle( 'CustomTitle', parent=styles['Heading1'], fontSize=18, spaceAfter=30, alignment=1, # Centered textColor=colors.darkblue ) # Section style section_style = ParagraphStyle( 'CustomSection', parent=styles['Heading2'], fontSize=14, spaceAfter=12, spaceBefore=20, textColor=colors.darkblue ) # Normal text style normal_style = ParagraphStyle( 'CustomNormal', parent=styles['Normal'], fontSize=11, spaceAfter=6, leading=14 ) # List style list_style = ParagraphStyle( 'CustomList', parent=styles['Normal'], fontSize=11, spaceAfter=3, leftIndent=20, bulletIndent=10 ) # Build content story = [] # Title story.append(Paragraph("Meeting Summary", title_style)) story.append(Spacer(1, 12)) # Date and info current_date = datetime.now().strftime("%m/%d/%Y %H:%M") story.append(Paragraph(f"Analysis date: {current_date}", normal_style)) story.append(Spacer(1, 20)) # Summary story.append(Paragraph("Summary", section_style)) summary_text = meeting_data.get("summary", "Summary not available") story.append(Paragraph(summary_text, normal_style)) story.append(Spacer(1, 20)) # Main topics story.append(Paragraph("Main Topics", section_style)) topics = meeting_data.get("topics", []) if topics: for topic in topics: story.append(Paragraph(f"• {topic}", list_style)) else: story.append(Paragraph("Topics not available", normal_style)) story.append(Spacer(1, 20)) # Keywords story.append(Paragraph("Keywords", section_style)) keywords = meeting_data.get("keywords", []) if keywords: # Group keywords in rows of 3-4 keyword_lines = [] for i in range(0, len(keywords), 4): line_keywords = keywords[i:i+4] keyword_lines.append(" • ".join(line_keywords)) for line in keyword_lines: story.append(Paragraph(f"• {line}", list_style)) else: story.append(Paragraph("Keywords not available", normal_style)) # Footer story.append(Spacer(1, 30)) story.append(Paragraph( f"Automatically generated on {current_date} by Meeting Summarizer", ParagraphStyle('Footer', parent=styles['Normal'], fontSize=9, alignment=1) )) # Generate PDF doc.build(story) logger.info(f"PDF generated successfully: {pdf_path}") return pdf_path except Exception as e: logger.error(f"Error during PDF generation: {str(e)}") return None def cleanup_temp_pdf(pdf_path: str) -> None: """ Clean up temporary PDF file. Args: pdf_path (str): Path to PDF file to delete """ try: if os.path.exists(pdf_path): os.remove(pdf_path) logger.info(f"Temporary PDF file deleted: {pdf_path}") except Exception as e: logger.warning(f"Unable to delete temporary PDF file {pdf_path}: {str(e)}")