diff --git a/front/src/components/items/context-menus.tsx b/front/src/components/items/context-menus.tsx
index e007c4a7..c102e7c6 100644
--- a/front/src/components/items/context-menus.tsx
+++ b/front/src/components/items/context-menus.tsx
@@ -1,11 +1,12 @@
// import Download from "@material-symbols/svg-400/rounded/download.svg";
+import Refresh from "@material-symbols/svg-400/rounded/autorenew.svg";
import Info from "@material-symbols/svg-400/rounded/info.svg";
import MoreVert from "@material-symbols/svg-400/rounded/more_vert.svg";
import MovieInfo from "@material-symbols/svg-400/rounded/movie_info.svg";
import type { ComponentProps } from "react";
import { useTranslation } from "react-i18next";
import { WatchStatusV } from "~/models";
-import { IconButton, Menu, tooltip } from "~/primitives";
+import { HR, IconButton, Menu, tooltip } from "~/primitives";
import { useAccount } from "~/providers/account-context";
import { useMutation } from "~/query";
import { cn } from "~/utils";
@@ -89,11 +90,11 @@ export const ItemContext = ({
invalidate: [kind, slug],
});
- // const metadataRefreshMutation = useMutation({
- // method: "POST",
- // path: [kind, slug, "refresh"],
- // invalidate: null,
- // });
+ const metadataRefreshMutation = useMutation({
+ method: "POST",
+ path: ["scanner", `${kind}s`, slug, "refresh"],
+ invalidate: null,
+ });
return (
>
)}
- {/* {account?.isAdmin === true && ( */}
- {/* <> */}
- {/*
*/}
- {/* metadataRefreshMutation.mutate()} */}
- {/* /> */}
- {/* > */}
- {/* )} */}
+ {account?.isAdmin === true && (
+ <>
+
+ metadataRefreshMutation.mutate()}
+ />
+ >
+ )}
);
};
diff --git a/front/src/ui/details/header.tsx b/front/src/ui/details/header.tsx
index f8cd56a7..4b07e629 100644
--- a/front/src/ui/details/header.tsx
+++ b/front/src/ui/details/header.tsx
@@ -1,3 +1,4 @@
+import Refresh from "@material-symbols/svg-400/rounded/autorenew.svg";
import BookmarkAdd from "@material-symbols/svg-400/rounded/bookmark_add.svg";
import Delete from "@material-symbols/svg-400/rounded/delete.svg";
import MoreHoriz from "@material-symbols/svg-400/rounded/more_horiz.svg";
@@ -83,11 +84,11 @@ const ButtonList = ({
invalidate: ["api", "shows"],
});
- // const metadataRefreshMutation = useMutation({
- // method: "POST",
- // path: [kind, slug, "refresh"],
- // invalidate: null,
- // });
+ const metadataRefreshMutation = useMutation({
+ method: "POST",
+ path: ["scanner", `${kind}s`, slug, "refresh"],
+ invalidate: null,
+ });
return (
@@ -163,6 +164,13 @@ const ButtonList = ({
href={`/${kind === "movie" ? "movies" : "series"}/${slug}/videos`}
/>
{kind !== "collection" &&
}
+ {kind !== "collection" && (
+ metadataRefreshMutation.mutate()}
+ />
+ )}
- {/* metadataRefreshMutation.mutate()} */}
- {/* /> */}
>
)}
diff --git a/front/src/ui/player/controls/tracks-menu.tsx b/front/src/ui/player/controls/tracks-menu.tsx
index 50263c52..9ed05a90 100644
--- a/front/src/ui/player/controls/tracks-menu.tsx
+++ b/front/src/ui/player/controls/tracks-menu.tsx
@@ -126,7 +126,7 @@ export const VideoMenu = ({
key={x.id}
label={getDisplayName({ title: x.label, language: x.language })}
selected={x.selected}
- onSelect={() => player.selectAudioTrack(x)}
+ onSelect={() => player.selectVideoTrack(x)}
/>
))}
diff --git a/scanner/scanner/client.py b/scanner/scanner/client.py
index 7abed1ae..b72c6e30 100644
--- a/scanner/scanner/client.py
+++ b/scanner/scanner/client.py
@@ -97,6 +97,16 @@ class KyooClient(metaclass=Singleton):
await self.raise_for_status(r)
return Page[Show].model_validate(await r.json())
+ async def get_movie(self, slug: str) -> Show:
+ async with self._client.get(f"movies/{slug}") as r:
+ await self.raise_for_status(r)
+ return Show.model_validate(await r.json())
+
+ async def get_serie(self, slug: str) -> Show:
+ async with self._client.get(f"series/{slug}") as r:
+ await self.raise_for_status(r)
+ return Show.model_validate(await r.json())
+
async def link_videos(
self,
kind: Literal["movie", "serie"],
diff --git a/scanner/scanner/routers/dependencies.py b/scanner/scanner/routers/dependencies.py
index f78e3a54..344939e2 100644
--- a/scanner/scanner/routers/dependencies.py
+++ b/scanner/scanner/routers/dependencies.py
@@ -3,6 +3,7 @@ from typing import Annotated
from fastapi import Header, Request
from langcodes import Language
+from ..client import KyooClient
from ..database import get_db
from ..providers.composite import CompositeProvider
from ..requests import RequestCreator
@@ -12,6 +13,10 @@ def get_provider(request: Request) -> CompositeProvider:
return request.app.state.provider
+def get_client(_request: Request) -> KyooClient:
+ return KyooClient()
+
+
async def get_request_creator():
async with get_db() as db:
yield RequestCreator(db)
diff --git a/scanner/scanner/routers/routes.py b/scanner/scanner/routers/routes.py
index 938b075a..060bb273 100644
--- a/scanner/scanner/routers/routes.py
+++ b/scanner/scanner/routers/routes.py
@@ -4,23 +4,33 @@ from fastapi import (
APIRouter,
BackgroundTasks,
Depends,
- Request as HttpRequest,
Security,
)
+from fastapi import (
+ Request as HttpRequest,
+)
+from ..client import KyooClient
from ..fsscan import create_scanner
from ..identifiers.identify import identify
from ..jwt import validate_bearer
+from ..models.metadataid import MetadataId
from ..models.movie import SearchMovie
from ..models.page import Page
from ..models.request import CreateRequest, Request, RequestRet
from ..models.serie import SearchSerie
+from ..models.show import Show
from ..models.videos import Video
from ..providers.composite import CompositeProvider
from ..requests import RequestCreator
from ..status import StatusService
from ..utils import Language
-from .dependencies import get_preferred_languages, get_provider, get_request_creator
+from .dependencies import (
+ get_client,
+ get_preferred_languages,
+ get_provider,
+ get_request_creator,
+)
router = APIRouter()
@@ -172,3 +182,67 @@ async def create_serie(
]
)
return ret
+
+
+@router.post(
+ "/movies/{slug}/refresh",
+ status_code=201,
+ response_description="Movie refresh request created.",
+)
+async def refresh_movie_by_slug(
+ slug: str,
+ client: Annotated[KyooClient, Depends(get_client)],
+ requests: Annotated[RequestCreator, Depends(get_request_creator)],
+ _: Annotated[None, Security(validate_bearer, scopes=["scanner.add"])],
+) -> RequestRet:
+ """
+ Refresh an existing movie
+ """
+
+ show = await client.get_movie(slug)
+ [ret] = await requests.enqueue(
+ [
+ Request(
+ kind="movie",
+ title=show.name,
+ year=show.air_date.year
+ if show.air_date is not None
+ else None,
+ external_id=MetadataId.map_dict(show.external_id),
+ videos=[],
+ )
+ ]
+ )
+ return ret
+
+
+@router.post(
+ "/series/{slug}/refresh",
+ status_code=201,
+ response_description="Series refresh request created.",
+)
+async def refresh_serie_by_slug(
+ slug: str,
+ client: Annotated[KyooClient, Depends(get_client)],
+ requests: Annotated[RequestCreator, Depends(get_request_creator)],
+ _: Annotated[None, Security(validate_bearer, scopes=["scanner.add"])],
+) -> RequestRet:
+ """
+ Refresh an existing serie
+ """
+
+ show = await client.get_serie(slug)
+ [ret] = await requests.enqueue(
+ [
+ Request(
+ kind="episode",
+ title=show.name,
+ year=show.start_air.year
+ if show.start_air is not None
+ else None,
+ external_id=MetadataId.map_dict(show.external_id),
+ videos=[],
+ )
+ ]
+ )
+ return ret