diff --git a/apps/master-api/src/viewer/routes.ts b/apps/master-api/src/viewer/routes.ts index 08dced8..f9333e0 100644 --- a/apps/master-api/src/viewer/routes.ts +++ b/apps/master-api/src/viewer/routes.ts @@ -642,9 +642,9 @@ export function registerViewerRoutes( app.get("/api/v1/client/movies/:id", async (request) => { const auth = await viewers.authFromBearer(request.headers.authorization); - requireProfile(auth); + const profileId = requireProfile(auth); const { id } = request.params as { id: string }; - return viewers.movieDetail(id, auth.profile?.isKids === true); + return viewers.movieDetail(id, auth.profile?.isKids === true, profileId); }); app.get("/api/v1/client/series/:id", async (request) => { @@ -684,8 +684,12 @@ export function registerViewerRoutes( hiddenFromContinue?: boolean; }; if (!body.mediaType) throw new AppError("INVALID_REQUEST", "mediaType verplicht", 400); + const mediaType = String(body.mediaType).trim().toUpperCase(); + if (mediaType !== "MOVIE" && mediaType !== "EPISODE") { + throw new AppError("INVALID_REQUEST", "mediaType moet MOVIE of EPISODE zijn", 400); + } const row = await viewers.upsertProgress(profileId, { - mediaType: body.mediaType, + mediaType: mediaType as "MOVIE" | "EPISODE", movieId: body.movieId, episodeId: body.episodeId, seriesId: body.seriesId, diff --git a/apps/master-api/src/viewer/service.ts b/apps/master-api/src/viewer/service.ts index ea449e8..bf4ccd3 100644 --- a/apps/master-api/src/viewer/service.ts +++ b/apps/master-api/src/viewer/service.ts @@ -2026,13 +2026,17 @@ export class ViewerService { hiddenFromContinue?: boolean; } ) { + const mediaType = String(body.mediaType || "").trim().toUpperCase(); + if (mediaType !== "MOVIE" && mediaType !== "EPISODE") { + throw new AppError("INVALID_REQUEST", "mediaType moet MOVIE of EPISODE zijn", 400); + } const positionMs = Math.max(0, Math.floor(body.positionMs || 0)); const durationMs = Math.max(0, Math.floor(body.durationMs || 0)); const autoComplete = body.completed === true || (durationMs > 0 && positionMs / durationMs >= 0.9); - if (body.mediaType === "MOVIE") { + if (mediaType === "MOVIE") { if (!body.movieId) throw new AppError("INVALID_REQUEST", "movieId verplicht", 400); const existingMovie = await prisma.watchProgress.findUnique({ where: { profileId_movieId: { profileId, movieId: body.movieId } }, @@ -2523,7 +2527,7 @@ export class ViewerService { return this.getShelfPrefs(profileId); } - async movieDetail(movieId: string, kidsMode = false) { + async movieDetail(movieId: string, kidsMode = false, profileId?: string | null) { const movie = await prisma.movie.findUnique({ where: { id: movieId }, include: { @@ -2552,6 +2556,12 @@ export class ViewerService { .catch(() => undefined); } + const progress = profileId + ? await prisma.watchProgress.findUnique({ + where: { profileId_movieId: { profileId, movieId: movie.id } }, + }) + : null; + return { type: "movie" as const, id: movie.id, @@ -2567,6 +2577,10 @@ export class ViewerService { cast: extras.cast ?? [], director: extras.director ?? [], trailerYoutubeKey: extras.trailers?.[0]?.source ?? null, + positionMs: progress && !progress.completed ? progress.positionMs : 0, + durationMs: progress?.durationMs ?? 0, + completed: progress?.completed === true, + progressId: progress?.id ?? null, mediaFiles: movie.mediaFiles.map((f, index) => ({ id: f.id, resolution: cleanMeta(f.resolution),