78 lines
2.8 KiB
Python
78 lines
2.8 KiB
Python
"""Files router — directory listing, ffprobe, stat, path resolution."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import logging
|
|
from typing import Any
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
|
|
from media_library_viewer_api.clients.ssh import RemoteSSHClient
|
|
from media_library_viewer_api.config import get_settings
|
|
from media_library_viewer_api.dependencies import get_ssh_client
|
|
from media_library_viewer_api.path_utils import resolve_remote_media_path
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/api/files", tags=["files"])
|
|
|
|
|
|
@router.get("/list")
|
|
def list_directory(
|
|
path: str = Query(..., description="Remote directory path to list"),
|
|
ssh: RemoteSSHClient = Depends(get_ssh_client),
|
|
) -> dict[str, Any]:
|
|
"""List a remote directory."""
|
|
result = ssh.list_dir(path)
|
|
if result.exit_status != 0:
|
|
logger.warning("Files list failed path=%s exit_status=%s", path, result.exit_status)
|
|
raise HTTPException(status_code=400, detail=result.stderr or result.stdout or "Failed to list directory")
|
|
entries = json.loads(result.stdout)
|
|
logger.info("Files list path=%s entries=%s", path, len(entries))
|
|
return {
|
|
"path": path,
|
|
"entries": entries,
|
|
"count": len(entries),
|
|
}
|
|
|
|
|
|
@router.get("/ffprobe")
|
|
def get_ffprobe(
|
|
path: str = Query(..., description="Remote file path to probe"),
|
|
ssh: RemoteSSHClient = Depends(get_ssh_client),
|
|
) -> dict[str, Any]:
|
|
"""Run ffprobe on a remote file and return parsed JSON."""
|
|
try:
|
|
data = ssh.ffprobe_json(path)
|
|
except RuntimeError as exc:
|
|
logger.warning("Files ffprobe failed path=%s error=%s", path, exc)
|
|
raise HTTPException(status_code=400, detail=str(exc))
|
|
logger.info("Files ffprobe path=%s", path)
|
|
return data
|
|
|
|
|
|
@router.get("/stat")
|
|
def get_stat(
|
|
path: str = Query(..., description="Remote path to stat"),
|
|
ssh: RemoteSSHClient = Depends(get_ssh_client),
|
|
) -> dict[str, str]:
|
|
"""Run stat on a remote path."""
|
|
result = ssh.stat_path(path)
|
|
if result.exit_status != 0:
|
|
logger.warning("Files stat failed path=%s exit_status=%s", path, result.exit_status)
|
|
raise HTTPException(status_code=400, detail=result.stderr or result.stdout or "stat failed")
|
|
logger.info("Files stat path=%s", path)
|
|
return {"path": path, "output": result.stdout}
|
|
|
|
|
|
@router.get("/resolve-path")
|
|
def resolve_path(
|
|
path: str = Query(..., description="Jellyfin path to resolve to SSH path"),
|
|
) -> dict[str, str]:
|
|
"""Resolve a Jellyfin path to its SSH-visible equivalent."""
|
|
settings = get_settings()
|
|
resolved = resolve_remote_media_path(path, settings.media_root, settings.path_prefix)
|
|
logger.info("Files resolve path original=%s resolved=%s", path, resolved)
|
|
return {"original": path, "resolved": resolved}
|