""" Shared utility functions for the Puff n Parse backend. """ import os import uuid import tempfile from pathlib import Path # Temporary upload directory — ephemeral, cleaned after processing UPLOAD_DIR = Path(tempfile.gettempdir()) / "puffnparse_uploads" UPLOAD_DIR.mkdir(parents=True, exist_ok=True) # Maximum file sizes MAX_FILE_SIZE_UNREGISTERED = 10 * 1024 * 1024 # 10MB MAX_FILE_SIZE_REGISTERED = 50 * 1024 * 1024 # 50MB (placeholder) # Supported MIME types and their corresponding FileType SUPPORTED_MIME_TYPES = { "application/pdf": "pdf", "image/jpeg": "jpeg", "image/jpg": "jpeg", "image/png": "png", } SUPPORTED_EXTENSIONS = {".pdf", ".jpg", ".jpeg", ".png"} def generate_temp_filename(original_filename: str) -> str: """Generate a unique temporary filename preserving the extension.""" ext = Path(original_filename).suffix.lower() return f"{uuid.uuid4().hex}{ext}" def get_file_extension(filename: str) -> str: """Extract and normalise the file extension.""" return Path(filename).suffix.lower() def validate_file_type(filename: str, content_type: str | None) -> str | None: """ Validate the uploaded file type. Returns the normalised type string ('pdf', 'jpeg', 'png') or None if invalid. """ ext = get_file_extension(filename) if ext not in SUPPORTED_EXTENSIONS: return None # Normalise jpeg/jpg if ext in {".jpg", ".jpeg"}: return "jpeg" return ext.lstrip(".") def cleanup_temp_file(filepath: str | Path) -> None: """Safely remove a temporary file.""" try: path = Path(filepath) if path.exists(): path.unlink() except OSError: pass # Best-effort cleanup def format_file_size(size_bytes: int) -> str: """Format bytes into a human-readable string.""" if size_bytes < 1024: return f"{size_bytes} B" elif size_bytes < 1024 * 1024: return f"{size_bytes / 1024:.1f} KB" else: return f"{size_bytes / (1024 * 1024):.1f} MB"