feat(plex): P0 backend foundations — catalog model, config, client
Optional Plex module groundwork (design locked 2026-07-05): plays the LOCAL physical file; Plex is metadata + optional watch-sync only. - models + migration 0044: plex_libraries/plex_shows/plex_seasons/plex_items (playable leaf, ffprobe playability class, markers, weighted FTS search_vector) + plex_states (per-user watch state, mirrors video_states) - sysconfig 'plex' group + config.py env defaults (server url/token[secret]/ path-map/libraries/sync-interval/max-transcodes) - app/plex/client.py (PlexClient httpx: server info, sections, items, metadata +markers, image) + app/plex/paths.py (Plex→local path map + file resolve) - routes/plex.py admin POST /api/plex/test (verify connection + list sections)
This commit is contained in:
parent
401fe90256
commit
a88254c841
9 changed files with 552 additions and 0 deletions
47
backend/app/routes/plex.py
Normal file
47
backend/app/routes/plex.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
"""Plex integration API.
|
||||
|
||||
Read endpoints (browse/search/stream/image/state) are available to ANY authenticated user — the
|
||||
whole point of the module is to be an access layer to the Plex library WITHOUT requiring a plex.tv
|
||||
account, and playback is a local file (no quota/credit cost), so demo + pure-Siftlode users are
|
||||
allowed. Admin endpoints configure + test the connection and trigger a sync.
|
||||
|
||||
P0 ships only the admin connectivity endpoints; browse/search/player land in P1/P2.
|
||||
"""
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.db import get_db
|
||||
from app.models import User
|
||||
from app.plex.client import PlexClient, PlexError, PlexNotConfigured
|
||||
from app.routes.admin import admin_user
|
||||
|
||||
router = APIRouter(prefix="/api/plex", tags=["plex"])
|
||||
|
||||
|
||||
@router.post("/test")
|
||||
def test_connection(_: User = Depends(admin_user), db: Session = Depends(get_db)) -> dict:
|
||||
"""Admin: verify the configured Plex server URL + token, returning the server name and the
|
||||
available library sections (movie/show) for the config library-picker."""
|
||||
try:
|
||||
with PlexClient(db) as plex:
|
||||
info = plex.server_info()
|
||||
sections = plex.sections()
|
||||
except PlexNotConfigured as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except PlexError as e:
|
||||
raise HTTPException(status_code=422, detail=f"Plex connection failed: {e}")
|
||||
return {
|
||||
"ok": True,
|
||||
"server_name": info.get("friendlyName") or info.get("title1") or "Plex",
|
||||
"version": info.get("version"),
|
||||
"sections": [
|
||||
{
|
||||
"key": str(s.get("key")),
|
||||
"title": s.get("title"),
|
||||
"type": s.get("type"),
|
||||
"count": s.get("count"),
|
||||
}
|
||||
for s in sections
|
||||
if s.get("type") in ("movie", "show")
|
||||
],
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue