from fastapi import APIRouter, BackgroundTasks, Depends, Form, Request, UploadFile from fastapi.responses import RedirectResponse from fastapi.templating import Jinja2Templates from app.db import SessionLocal, get_db from app.models import Playlist from app.security.deps import require_auth from app.services import manual_import async def _run_import_bg(source: str | None, playlist_name: str | None, imported_by: str) -> None: """Import in the background with its own DB session. The request's session is closed once the response is sent, so we cannot reuse it here.""" db = SessionLocal() try: await manual_import.import_track(db, source, playlist_name, imported_by) finally: db.close() router = APIRouter(prefix="/import", tags=["import"]) templates = Jinja2Templates(directory="app/templates") @router.get("") async def import_index(request: Request, user: dict = Depends(require_auth), db=Depends(get_db)): from sqlalchemy import select contents = manual_import.list_import_me_contents() playlists = list(db.execute(select(Playlist).order_by(Playlist.name)).scalars()) return templates.TemplateResponse( request, "import/index.html", {"contents": contents, "playlists": playlists}, ) @router.post("/upload") async def upload( request: Request, file: UploadFile, user: dict = Depends(require_auth), ): content = await file.read() manual_import.save_uploaded_file(file.filename, content) return RedirectResponse(url="/import", status_code=303) @router.post("/run") async def run_import( background: BackgroundTasks, source: str = Form(""), playlist_name: str = Form(""), user: dict = Depends(require_auth), ): # Importing (tag, prep, beets import, rescan) can take a while, so run it in # the background and redirect immediately. Progress and the outcome show up # under Settings then Jobs. imported_by = user.get("email") or user.get("sub", "unknown") background.add_task(_run_import_bg, source or None, playlist_name or None, imported_by) return RedirectResponse(url="/import?started=1", status_code=303)