uploader-bot/app/api/routes/converter_routes.py

146 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import asyncio
import logging
import os
import uuid
from typing import Optional, List, Dict, Any
from fastapi import APIRouter, UploadFile, File, Form, HTTPException, Query
from fastapi.responses import JSONResponse, FileResponse
from app.core.converter.conversion_manager import ConversionManager
from app.core.models.converter.conversion_models import (
ContentMetadata,
ConversionPriority,
ConversionStatus,
)
router = APIRouter(prefix="/api/converter", tags=["converter"])
logger = logging.getLogger(__name__)
# Глобальный singleton менеджера (можно заменить DI контейнером)
_conversion_manager: Optional[ConversionManager] = None
def get_manager() -> ConversionManager:
global _conversion_manager
if _conversion_manager is None:
_conversion_manager = ConversionManager()
return _conversion_manager
@router.post("/submit")
async def submit_conversion(
file: UploadFile = File(...),
title: str = Form(...),
description: Optional[str] = Form(None),
author: Optional[str] = Form(None),
collection: Optional[str] = Form(None),
tags: Optional[str] = Form(None), # CSV
language: Optional[str] = Form(None),
explicit: Optional[bool] = Form(None),
quality: str = Form("high"), # "high" | "low"
input_ext: Optional[str] = Form(None), # если неизвестно — попытаемся из файла
priority: int = Form(50),
trim: Optional[str] = Form(None),
custom: Optional[str] = Form(None), # произвольные ffmpeg-параметры через пробел
):
"""
Принимает файл и ставит задачу конвертации в очередь.
Возвращает task_id.
"""
try:
# Сохраняем входной файл во временное хранилище uploader-bot
uploads_dir = "uploader-bot/uploader-bot/data/uploads"
os.makedirs(uploads_dir, exist_ok=True)
input_name = file.filename or f"upload-{uuid.uuid4().hex}"
local_path = os.path.join(uploads_dir, input_name)
with open(local_path, "wb") as f:
f.write(await file.read())
# Определяем расширение, если не передано
in_ext = input_ext or os.path.splitext(input_name)[1].lstrip(".").lower() or "bin"
# Метаданные
md = ContentMetadata(
title=title,
description=description,
author=author,
collection=collection,
tags=[t.strip() for t in (tags.split(","))] if tags else [],
language=language,
explicit=explicit,
attributes={},
)
prio = ConversionPriority.NORMAL
try:
# нормализуем диапазон int -> enum
p_int = int(priority)
if p_int >= ConversionPriority.CRITICAL:
prio = ConversionPriority.CRITICAL
elif p_int >= ConversionPriority.HIGH:
prio = ConversionPriority.HIGH
elif p_int >= ConversionPriority.NORMAL:
prio = ConversionPriority.NORMAL
else:
prio = ConversionPriority.LOW
except Exception:
pass
custom_list: List[str] = []
if custom:
# Разбиваем по пробелам, без сложного парсинга
custom_list = [c for c in custom.split(" ") if c]
manager = get_manager()
task_id = await manager.process_upload(
local_input_path=local_path,
input_ext=in_ext,
quality="high" if quality == "high" else "low",
metadata=md,
priority=prio,
custom=custom_list,
trim=trim,
)
return JSONResponse({"task_id": task_id})
except Exception as e:
logger.exception("submit_conversion failed: %s", e)
raise HTTPException(status_code=500, detail=str(e))
@router.get("/status/{task_id}")
async def get_status(task_id: str):
"""
Возвращает статус задачи.
"""
try:
manager = get_manager()
status = await manager.get_conversion_status(task_id)
return JSONResponse({"task_id": task_id, "status": status.value})
except Exception as e:
logger.exception("get_status failed: %s", e)
raise HTTPException(status_code=500, detail=str(e))
@router.get("/result/{task_id}")
async def get_result(task_id: str):
"""
Возвращает результат задачи с content_id, чанками и nft метаданными.
"""
try:
manager = get_manager()
res = await manager.handle_conversion_result(task_id)
if not res:
# если задача всё ещё идёт/в очереди
status = await manager.get_conversion_status(task_id)
if status in (ConversionStatus.QUEUED, ConversionStatus.RUNNING):
return JSONResponse({"task_id": task_id, "status": status.value})
raise HTTPException(status_code=404, detail="result not ready")
return JSONResponse(res.to_dict())
except Exception as e:
logger.exception("get_result failed: %s", e)
raise HTTPException(status_code=500, detail=str(e))