feat: discover overhaul (filters!) (#3232)

This commit is contained in:
Ryan Cohen
2023-01-13 16:54:35 +09:00
committed by GitHub
parent b5157010c4
commit dd00e48f59
26 changed files with 1445 additions and 179 deletions

View File

@@ -1,4 +1,5 @@
import PlexTvAPI from '@server/api/plextv';
import type { SortOptions } from '@server/api/themoviedb';
import TheMovieDb from '@server/api/themoviedb';
import type { TmdbKeyword } from '@server/api/themoviedb/interfaces';
import { MediaType } from '@server/constants/media';
@@ -21,6 +22,7 @@ import { mapNetwork } from '@server/models/Tv';
import { isMovie, isPerson } from '@server/utils/typeHelpers';
import { Router } from 'express';
import { sortBy } from 'lodash';
import { z } from 'zod';
export const createTmdbWithRegionLanguage = (user?: User): TheMovieDb => {
const settings = getSettings();
@@ -47,17 +49,50 @@ export const createTmdbWithRegionLanguage = (user?: User): TheMovieDb => {
const discoverRoutes = Router();
const QueryFilterOptions = z.object({
page: z.coerce.string().optional(),
sortBy: z.coerce.string().optional(),
primaryReleaseDateGte: z.coerce.string().optional(),
primaryReleaseDateLte: z.coerce.string().optional(),
firstAirDateGte: z.coerce.string().optional(),
firstAirDateLte: z.coerce.string().optional(),
studio: z.coerce.string().optional(),
genre: z.coerce.string().optional(),
keywords: z.coerce.string().optional(),
language: z.coerce.string().optional(),
withRuntimeGte: z.coerce.string().optional(),
withRuntimeLte: z.coerce.string().optional(),
voteAverageGte: z.coerce.string().optional(),
voteAverageLte: z.coerce.string().optional(),
network: z.coerce.string().optional(),
});
export type FilterOptions = z.infer<typeof QueryFilterOptions>;
discoverRoutes.get('/movies', async (req, res, next) => {
const tmdb = createTmdbWithRegionLanguage(req.user);
const keywords = req.query.keywords as string;
try {
const query = QueryFilterOptions.parse(req.query);
const keywords = query.keywords;
const data = await tmdb.getDiscoverMovies({
page: Number(req.query.page),
language: req.locale ?? (req.query.language as string),
genre: req.query.genre ? Number(req.query.genre) : undefined,
studio: req.query.studio ? Number(req.query.studio) : undefined,
page: Number(query.page),
sortBy: query.sortBy as SortOptions,
language: req.locale ?? query.language,
originalLanguage: query.language,
genre: query.genre,
studio: query.studio,
primaryReleaseDateLte: query.primaryReleaseDateLte
? new Date(query.primaryReleaseDateLte).toISOString().split('T')[0]
: undefined,
primaryReleaseDateGte: query.primaryReleaseDateGte
? new Date(query.primaryReleaseDateGte).toISOString().split('T')[0]
: undefined,
keywords,
withRuntimeGte: query.withRuntimeGte,
withRuntimeLte: query.withRuntimeLte,
voteAverageGte: query.voteAverageGte,
voteAverageLte: query.voteAverageLte,
});
const media = await Media.getRelatedMedia(
@@ -178,7 +213,7 @@ discoverRoutes.get<{ genreId: string }>(
const data = await tmdb.getDiscoverMovies({
page: Number(req.query.page),
language: req.locale ?? (req.query.language as string),
genre: Number(req.params.genreId),
genre: req.params.genreId as string,
});
const media = await Media.getRelatedMedia(
@@ -225,7 +260,7 @@ discoverRoutes.get<{ studioId: string }>(
const data = await tmdb.getDiscoverMovies({
page: Number(req.query.page),
language: req.locale ?? (req.query.language as string),
studio: Number(req.params.studioId),
studio: req.params.studioId as string,
});
const media = await Media.getRelatedMedia(
@@ -309,15 +344,28 @@ discoverRoutes.get('/movies/upcoming', async (req, res, next) => {
discoverRoutes.get('/tv', async (req, res, next) => {
const tmdb = createTmdbWithRegionLanguage(req.user);
const keywords = req.query.keywords as string;
try {
const query = QueryFilterOptions.parse(req.query);
const keywords = query.keywords;
const data = await tmdb.getDiscoverTv({
page: Number(req.query.page),
language: req.locale ?? (req.query.language as string),
genre: req.query.genre ? Number(req.query.genre) : undefined,
network: req.query.network ? Number(req.query.network) : undefined,
page: Number(query.page),
sortBy: query.sortBy as SortOptions,
language: req.locale ?? query.language,
genre: query.genre ? Number(query.genre) : undefined,
network: query.network ? Number(query.network) : undefined,
firstAirDateLte: query.firstAirDateLte
? new Date(query.firstAirDateLte).toISOString().split('T')[0]
: undefined,
firstAirDateGte: query.firstAirDateGte
? new Date(query.firstAirDateGte).toISOString().split('T')[0]
: undefined,
originalLanguage: query.language,
keywords,
withRuntimeGte: query.withRuntimeGte,
withRuntimeLte: query.withRuntimeLte,
voteAverageGte: query.voteAverageGte,
voteAverageLte: query.voteAverageLte,
});
const media = await Media.getRelatedMedia(
@@ -672,7 +720,9 @@ discoverRoutes.get<{ language: string }, GenreSliderItem[]>(
await Promise.all(
genres.map(async (genre) => {
const genreData = await tmdb.getDiscoverMovies({ genre: genre.id });
const genreData = await tmdb.getDiscoverMovies({
genre: genre.id.toString(),
});
mappedGenres.push({
id: genre.id,