diff --git a/scanner/scanner/models/movie.py b/scanner/scanner/models/movie.py index c959accd..ae75dde6 100644 --- a/scanner/scanner/models/movie.py +++ b/scanner/scanner/models/movie.py @@ -50,6 +50,7 @@ class MovieTranslation(Model): class SearchMovie(Model): + id: str slug: str name: str description: str | None diff --git a/scanner/scanner/models/page.py b/scanner/scanner/models/page.py new file mode 100644 index 00000000..d019b036 --- /dev/null +++ b/scanner/scanner/models/page.py @@ -0,0 +1,11 @@ +from typing import Generic, TypeVar + +from ..utils import Model + +T = TypeVar("T") + + +class Page(Model, Generic[T]): + items: list[T] + this_: str + next: str | None = None diff --git a/scanner/scanner/models/serie.py b/scanner/scanner/models/serie.py index a1b60ef5..230c4985 100644 --- a/scanner/scanner/models/serie.py +++ b/scanner/scanner/models/serie.py @@ -57,6 +57,7 @@ class SerieTranslation(Model): class SearchSerie(Model): + id: str slug: str name: str description: str | None diff --git a/scanner/scanner/providers/themoviedatabase.py b/scanner/scanner/providers/themoviedatabase.py index 6dae2136..0d4fe60c 100644 --- a/scanner/scanner/providers/themoviedatabase.py +++ b/scanner/scanner/providers/themoviedatabase.py @@ -118,6 +118,7 @@ class TheMovieDatabase(Provider): search = self._sort_search(search, title, year) return [ SearchMovie( + id=x["id"], slug=to_slug(x["title"]), name=x["title"], description=x["overview"], @@ -252,6 +253,7 @@ class TheMovieDatabase(Provider): search = self._sort_search(search, title, year) return [ SearchSerie( + id=x["id"], slug=to_slug(x["name"]), name=x["name"], description=x["overview"], diff --git a/scanner/scanner/providers/thetvdb.py b/scanner/scanner/providers/thetvdb.py index 67a0e3a4..84f08bca 100644 --- a/scanner/scanner/providers/thetvdb.py +++ b/scanner/scanner/providers/thetvdb.py @@ -171,6 +171,7 @@ class TVDB(Provider): ) return [ SearchSerie( + id=x["id"], slug=x["slug"], name=next( ( diff --git a/scanner/scanner/routers/routes.py b/scanner/scanner/routers/routes.py index ce9cc761..938b075a 100644 --- a/scanner/scanner/routers/routes.py +++ b/scanner/scanner/routers/routes.py @@ -1,11 +1,18 @@ from typing import Annotated, Literal -from fastapi import APIRouter, BackgroundTasks, Depends, Security +from fastapi import ( + APIRouter, + BackgroundTasks, + Depends, + Request as HttpRequest, + Security, +) from ..fsscan import create_scanner from ..identifiers.identify import identify from ..jwt import validate_bearer from ..models.movie import SearchMovie +from ..models.page import Page from ..models.request import CreateRequest, Request, RequestRet from ..models.serie import SearchSerie from ..models.videos import Video @@ -21,14 +28,16 @@ router = APIRouter() @router.get("/scan") async def get_scan_status( svc: Annotated[StatusService, Depends(StatusService.create)], + request: HttpRequest, _: Annotated[None, Security(validate_bearer, scopes=["scanner.trigger"])], status: Literal["pending", "running", "failed"] | None = None, -) -> list[RequestRet]: +) -> Page[RequestRet]: """ Get scan status, know what tasks are running, pending or failed. """ - return await svc.list_requests(status=status) + items = await svc.list_requests(status=status) + return Page(items=items, this_=str(request.url), next=None) @router.put( @@ -75,15 +84,17 @@ async def get_guess( async def get_movies( provider: Annotated[CompositeProvider, Depends(get_provider)], language: Annotated[list[Language], Depends(get_preferred_languages)], + request: HttpRequest, _: Annotated[None, Security(validate_bearer, scopes=["scanner.search"])], query: str, year: int | None = None, -) -> list[SearchMovie]: +) -> Page[SearchMovie]: """ Search for a movie """ - return await provider.search_movies(query, year=year, language=language) + items = await provider.search_movies(query, year=year, language=language) + return Page(items=items, this_=str(request.url), next=None) @router.get( @@ -94,15 +105,17 @@ async def get_movies( async def get_series( provider: Annotated[CompositeProvider, Depends(get_provider)], language: Annotated[list[Language], Depends(get_preferred_languages)], + request: HttpRequest, _: Annotated[None, Security(validate_bearer, scopes=["scanner.search"])], query: str, year: int | None = None, -) -> list[SearchSerie]: +) -> Page[SearchSerie]: """ Search for a serie """ - return await provider.search_series(query, year=year, language=language) + items = await provider.search_series(query, year=year, language=language) + return Page(items=items, this_=str(request.url), next=None) @router.post(