from flask import Blueprint, jsonify, request from server.permissions import editor_or_higher from server.database import Session from models.models import Conversion, ConversionStatus, EventMedia, MediaType from server.task_queue import get_queue from server.worker import convert_event_media_to_pdf from datetime import datetime, timezone import hashlib conversions_bp = Blueprint("conversions", __name__, url_prefix="/api/conversions") def sha256_file(abs_path: str) -> str: h = hashlib.sha256() with open(abs_path, "rb") as f: for chunk in iter(lambda: f.read(8192), b""): h.update(chunk) return h.hexdigest() @conversions_bp.route("//pdf", methods=["POST"]) @editor_or_higher def ensure_conversion(media_id: int): session = Session() try: media = session.query(EventMedia).get(media_id) if not media or not media.file_path: return jsonify({"error": "Media not found or no file"}), 404 # Only enqueue for office presentation formats if media.media_type not in {MediaType.ppt, MediaType.pptx, MediaType.odp}: return jsonify({"message": "No conversion required for this media_type"}), 200 # Compute file hash import os base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) media_root = os.path.join(base_dir, "media") abs_source = os.path.join(media_root, media.file_path) file_hash = sha256_file(abs_source) # Find or create conversion row conv = ( session.query(Conversion) .filter_by( source_event_media_id=media.id, target_format="pdf", file_hash=file_hash, ) .one_or_none() ) if not conv: conv = Conversion( source_event_media_id=media.id, target_format="pdf", status=ConversionStatus.pending, file_hash=file_hash, ) session.add(conv) session.commit() # Enqueue if not already processing/ready if conv.status in {ConversionStatus.pending, ConversionStatus.failed}: q = get_queue() job = q.enqueue(convert_event_media_to_pdf, conv.id) return jsonify({"id": conv.id, "status": conv.status.value, "job_id": job.get_id()}), 202 else: return jsonify({"id": conv.id, "status": conv.status.value, "target_path": conv.target_path}), 200 finally: session.close() @conversions_bp.route("//status", methods=["GET"]) def conversion_status(media_id: int): session = Session() try: conv = ( session.query(Conversion) .filter_by(source_event_media_id=media_id, target_format="pdf") .order_by(Conversion.id.desc()) .first() ) if not conv: return jsonify({"status": "missing"}), 404 return jsonify( { "id": conv.id, "status": conv.status.value, "target_path": conv.target_path, "started_at": conv.started_at.isoformat() if conv.started_at else None, "completed_at": conv.completed_at.isoformat() if conv.completed_at else None, "error_message": conv.error_message, } ) finally: session.close()