Added series page and scene page section, no overview (yet).

This commit is contained in:
2024-06-02 00:30:56 +02:00
parent eb2807d0e0
commit 5cfab6c9ca
12 changed files with 988 additions and 27 deletions

15
src/media.js Normal file
View File

@@ -0,0 +1,15 @@
export function curateMedia(media) {
if (!media) {
return null;
}
return {
id: media.id,
path: media.path,
thumbnail: media.thumbnail,
lazy: media.lazy,
isS3: media.is_s3,
width: media.width,
height: media.height,
};
}

View File

@@ -4,27 +4,12 @@ import { knexQuery as knex, knexOwner, knexManticore } from './knex.js';
import { utilsApi } from './manticore.js';
import { HttpError } from './errors.js';
import { fetchActorsById, curateActor, sortActorsByGender } from './actors.js';
import { curateMedia } from './media.js';
import { fetchTagsById } from './tags.js';
import { fetchEntitiesById } from './entities.js';
import { curateStash } from './stashes.js';
import promiseProps from '../utils/promise-props.js';
function curateMedia(media) {
if (!media) {
return null;
}
return {
id: media.id,
path: media.path,
thumbnail: media.thumbnail,
lazy: media.lazy,
isS3: media.is_s3,
width: media.width,
height: media.height,
};
}
function curateMovie(rawMovie, assets) {
if (!rawMovie) {
return null;
@@ -66,7 +51,7 @@ function curateMovie(rawMovie, assets) {
slug: tag.slug,
name: tag.name,
})),
poster: curateMedia(assets.poster),
// poster: curateMedia(assets.poster),
covers: assets.covers.map((cover) => curateMedia(cover)),
photos: assets.photos.map((photo) => curateMedia(photo)),
stashes: assets.stashes?.map((stash) => curateStash(stash)) || [],
@@ -147,7 +132,7 @@ export async function fetchMoviesById(movieIds, reqUser) {
const movie = movies.find((movieEntry) => movieEntry.id === movieId);
if (!movie) {
console.warn('cannot find movie', movieId);
console.warn('Cannot find movie', movieId);
return null;
}

View File

@@ -80,6 +80,12 @@ function curateScene(rawScene, assets) {
title: movie.title,
covers: movie.movie_covers?.map((cover) => curateMedia(cover)).toSorted((coverA, coverB) => coverA.index - coverB.index) || [],
})),
series: assets.series.map((serie) => ({
id: serie.id,
slug: serie.slug,
title: serie.title,
poster: curateMedia(serie.serie_poster),
})),
poster: curateMedia(assets.poster),
trailer: curateMedia(assets.trailer),
teaser: curateMedia(assets.teaser),
@@ -99,6 +105,7 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
directors,
tags,
movies,
series,
posters,
photos,
trailers,
@@ -141,6 +148,13 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
.leftJoin('media', 'media.id', 'movies_covers.media_id')
.whereIn('scene_id', sceneIds)
.groupBy('movies.id', 'movies_scenes.scene_id'),
series: knex('series_scenes')
.select('series_scenes.scene_id', 'series.*', knex.raw('row_to_json(media) as serie_poster'))
.leftJoin('series', 'series.id', 'series_scenes.serie_id')
.leftJoin('series_posters', 'series_posters.serie_id', 'series.id')
.leftJoin('media', 'media.id', 'series_posters.media_id')
.whereIn('scene_id', sceneIds)
.groupBy('series.id', 'series_scenes.scene_id', 'media.*'),
posters: knex('releases_posters')
.whereIn('release_id', sceneIds)
.leftJoin('media', 'media.id', 'releases_posters.media_id'),
@@ -198,13 +212,12 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
return null;
}
console.log(movies);
const sceneChannel = channels.find((entity) => entity.id === scene.entity_id);
const sceneActors = actors.filter((actor) => actor.release_id === sceneId);
const sceneDirectors = directors.filter((director) => director.release_id === sceneId);
const sceneTags = tags.filter((tag) => tag.release_id === sceneId);
const sceneMovies = movies.filter((movie) => movie.scene_id === sceneId);
const sceneSeries = series.filter((serie) => serie.scene_id === sceneId);
const scenePoster = posters.find((poster) => poster.release_id === sceneId);
const scenePhotos = photos.filter((photo) => photo.release_id === sceneId);
const sceneTrailers = trailers.find((trailer) => trailer.release_id === sceneId);
@@ -218,6 +231,7 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
directors: sceneDirectors,
tags: sceneTags,
movies: sceneMovies,
series: sceneSeries,
poster: scenePoster,
photos: scenePhotos,
trailer: sceneTrailers,
@@ -490,6 +504,10 @@ async function queryManticoreSql(filters, options, _reqUser) {
builder.whereRaw('any(movie_ids) = ?', filters.movieId);
}
if (filters.serieId) {
builder.whereRaw('any(serie_ids) = ?', filters.serieId);
}
if (typeof filters.isShowcased === 'boolean') {
builder.where('scenes.is_showcased', filters.isShowcased);
}

151
src/series.js Normal file
View File

@@ -0,0 +1,151 @@
import { knexQuery as knex, knexOwner } from './knex.js';
import { curateActor, sortActorsByGender } from './actors.js';
import { curateMedia } from './media.js';
import { curateStash } from './stashes.js';
import promiseProps from '../utils/promise-props.js';
function curateSerie(rawSerie, assets) {
if (!rawSerie) {
return null;
}
return {
id: rawSerie.id,
title: rawSerie.title,
slug: rawSerie.slug,
url: rawSerie.url,
date: rawSerie.date,
createdAt: rawSerie.created_at,
effectiveDate: rawSerie.effective_date,
description: rawSerie.description,
duration: rawSerie.duration,
channel: {
id: assets.channel.id,
slug: assets.channel.slug,
name: assets.channel.name,
type: assets.channel.type,
isIndependent: assets.channel.independent,
hasLogo: assets.channel.has_logo,
},
network: assets.channel.network_id ? {
id: assets.channel.network_id,
slug: assets.channel.network_slug,
name: assets.channel.network_name,
type: assets.channel.network_type,
hasLogo: assets.channel.has_logo,
} : null,
actors: sortActorsByGender(assets.actors.map((actor) => curateActor(actor, { sceneDate: rawSerie.effective_date }))),
directors: assets.directors.map((director) => ({
id: director.id,
slug: director.slug,
name: director.name,
})),
tags: assets.tags.map((tag) => ({
id: tag.id,
slug: tag.slug,
name: tag.name,
})),
poster: curateMedia(assets.poster),
// covers: assets.covers.map((cover) => curateMedia(cover)),
photos: assets.photos.map((photo) => curateMedia(photo)),
stashes: assets.stashes?.map((stash) => curateStash(stash)) || [],
createdBatchId: rawSerie.created_batch_id,
updatedBatchId: rawSerie.updated_batch_id,
};
}
export async function fetchSeriesById(serieIds, reqUser) {
const {
series,
channels,
actors,
directors,
tags,
posters,
photos,
stashes,
} = await promiseProps({
series: knex('series')
.select('series.*', knex.raw('sum(releases.duration) as duration'))
.leftJoin('series_scenes', 'series_scenes.serie_id', 'series.id')
.leftJoin('releases', 'releases.id', 'series_scenes.scene_id')
.whereIn('series.id', serieIds)
.groupBy('series.id'),
channels: knex('series')
.select('channels.*', 'networks.id as network_id', 'networks.slug as network_slug', 'networks.name as network_name', 'networks.type as network_type')
.whereIn('series.id', serieIds)
.leftJoin('entities as channels', 'channels.id', 'series.entity_id')
.leftJoin('entities as networks', 'networks.id', 'channels.parent_id')
.groupBy('channels.id', 'networks.id'),
actors: knex('series')
.select(
'actors.*',
'actors_meta.*',
'releases_actors.release_id',
'series.id as serie_id',
)
.distinctOn('actors.id', 'series.id') // cannot distinct on JSON column avatar, must specify
.whereIn('series.id', serieIds)
.whereNotNull('actors.id')
.leftJoin('series_scenes', 'series_scenes.serie_id', 'series.id')
.leftJoin('releases_actors', 'releases_actors.release_id', 'series_scenes.scene_id')
.leftJoin('actors', 'actors.id', 'releases_actors.actor_id')
.leftJoin('actors_meta', 'actors_meta.actor_id', 'actors.id'),
directors: knex('series')
.whereIn('series.id', serieIds)
.leftJoin('series_scenes', 'series_scenes.serie_id', 'series.id')
.leftJoin('releases_directors', 'releases_directors.release_id', 'series_scenes.scene_id')
.leftJoin('actors as directors', 'directors.id', 'releases_directors.director_id'),
tags: knex('series')
.select('tags.id', 'tags.slug', 'tags.name', 'tags.priority', 'series.id as serie_id')
.distinct()
.whereIn('series.id', serieIds)
.whereNotNull('tags.id')
.leftJoin('series_scenes', 'series_scenes.serie_id', 'series.id')
.leftJoin('releases_tags', 'releases_tags.release_id', 'series_scenes.scene_id')
.leftJoin('tags', 'tags.id', 'releases_tags.tag_id')
.orderBy('priority', 'desc'),
posters: knex('series_posters')
.whereIn('serie_id', serieIds)
.leftJoin('media', 'media.id', 'series_posters.media_id')
.orderBy('media.index'),
photos: knex('series')
.whereIn('series.id', serieIds)
.leftJoin('series_scenes', 'series_scenes.serie_id', 'series.id')
.leftJoin('releases_photos', 'releases_photos.release_id', 'series_scenes.scene_id')
.leftJoin('media', 'media.id', 'releases_photos.media_id'),
stashes: reqUser
? knexOwner('stashes_series')
.leftJoin('stashes', 'stashes.id', 'stashes_series.stash_id')
.where('stashes.user_id', reqUser.id)
.whereIn('stashes_series.serie_id', serieIds)
: [],
});
return serieIds.map((serieId) => {
const serie = series.find((serieEntry) => serieEntry.id === serieId);
if (!serie) {
console.warn('Cannot find serie', serieId);
return null;
}
const serieChannel = channels.find((entity) => entity.id === serie.entity_id);
const serieActors = actors.filter((actor) => actor.serie_id === serieId);
const serieDirectors = directors.filter((director) => director.release_id === serieId);
const serieTags = tags.filter((tag) => tag.serie_id === serieId);
const seriePosters = posters.filter((poster) => poster.serie_id === serieId);
const seriePhotos = photos.filter((photo) => photo.release_id === serieId);
const serieStashes = stashes.filter((stash) => stash.serie_id === serieId);
return curateSerie(serie, {
channel: serieChannel,
actors: serieActors,
directors: serieDirectors,
tags: serieTags,
posters: seriePosters,
photos: seriePhotos,
stashes: serieStashes,
});
}).filter(Boolean);
}

View File

@@ -34,6 +34,7 @@ export async function curateScenesQuery(query) {
entityId,
notEntityIds,
movieId: Number(query.movieId) || null,
serieId: Number(query.serieId) || null,
stashId: Number(query.stashId) || null,
isShowcased: typeof query.isShowcased === 'boolean' ? query.isShowcased : null,
};