"""Endpoint dùng chung: trạng thái job, tải file kết quả.""" from __future__ import annotations import os from urllib.parse import quote from fastapi import APIRouter, HTTPException from fastapi.responses import FileResponse from ..core.files import session_dir, delete_session from ..core.jobs import jobs router = APIRouter(prefix="/api", tags=["common"]) @router.delete("/sessions/{sid}") def drop_session(sid: str): """Xoá phiên tạm sau khi user đã tải kết quả về máy (không bắt buộc).""" return {"deleted": delete_session(sid), "session": sid} @router.get("/jobs/{job_id}") def job_status(job_id: str): job = jobs.get(job_id) if not job: raise HTTPException(404, "job không tồn tại") return job.to_dict() @router.get("/queue/stats") def queue_stats(): """Số liệu hàng đợi: số job đang chạy/chờ theo loại + tổng job trong bộ nhớ.""" return jobs.stats() @router.post("/jobs/{job_id}/cancel") def job_cancel(job_id: str): jobs.cancel(job_id) return {"ok": True} @router.get("/sessions/{sid}/inputs") def list_inputs(sid: str): """Liệt kê video trong thư mục inputs của phiên (dùng khi đẩy từ Down list).""" d = os.path.join(session_dir(sid), "inputs") if not os.path.isdir(d): return {"session": sid, "files": []} out = [] for name in sorted(os.listdir(d)): full = os.path.join(d, name) if os.path.isfile(full): out.append({ "file": f"inputs/{name}", "name": name, "size": os.path.getsize(full), "url": f"/api/files/{sid}/inputs/{quote(name)}", }) return {"session": sid, "files": out} @router.get("/files/{sid}/{path:path}") def get_file(sid: str, path: str): base = os.path.abspath(session_dir(sid)) full = os.path.abspath(os.path.join(base, path)) if not full.startswith(base) or not os.path.exists(full): raise HTTPException(404, "file không tồn tại") # inline (KHÔNG attachment) -> trình duyệt render video/ảnh trực tiếp trong