|
|
|
import IMDBRadarrProxy from '@server/api/rating/imdbRadarrProxy';
|
|
|
|
import RottenTomatoes from '@server/api/rating/rottentomatoes';
|
|
|
|
import { type RatingResponse } from '@server/api/ratings';
|
|
|
|
import TheMovieDb from '@server/api/themoviedb';
|
|
|
|
import { MediaType } from '@server/constants/media';
|
|
|
|
import Media from '@server/entity/Media';
|
|
|
|
import logger from '@server/logger';
|
|
|
|
import { mapMovieDetails } from '@server/models/Movie';
|
|
|
|
import { mapMovieResult } from '@server/models/Search';
|
|
|
|
import { Router } from 'express';
|
|
|
|
|
|
|
|
const movieRoutes = Router();
|
|
|
|
|
|
|
|
movieRoutes.get('/:id', async (req, res, next) => {
|
|
|
|
const tmdb = new TheMovieDb();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const tmdbMovie = await tmdb.getMovie({
|
|
|
|
movieId: Number(req.params.id),
|
|
|
|
language: (req.query.language as string) ?? req.locale,
|
|
|
|
});
|
|
|
|
|
|
|
|
const media = await Media.getMedia(tmdbMovie.id, MediaType.MOVIE);
|
|
|
|
|
|
|
|
return res.status(200).json(mapMovieDetails(tmdbMovie, media));
|
|
|
|
} catch (e) {
|
|
|
|
logger.debug('Something went wrong retrieving movie', {
|
|
|
|
label: 'API',
|
|
|
|
errorMessage: e.message,
|
|
|
|
movieId: req.params.id,
|
|
|
|
});
|
|
|
|
return next({
|
|
|
|
status: 500,
|
|
|
|
message: 'Unable to retrieve movie.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
movieRoutes.get('/:id/recommendations', async (req, res, next) => {
|
|
|
|
const tmdb = new TheMovieDb();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const results = await tmdb.getMovieRecommendations({
|
|
|
|
movieId: Number(req.params.id),
|
|
|
|
page: Number(req.query.page),
|
|
|
|
language: (req.query.language as string) ?? req.locale,
|
|
|
|
});
|
|
|
|
|
|
|
|
const media = await Media.getRelatedMedia(
|
|
|
|
results.results.map((result) => result.id)
|
|
|
|
);
|
|
|
|
|
|
|
|
return res.status(200).json({
|
|
|
|
page: results.page,
|
|
|
|
totalPages: results.total_pages,
|
|
|
|
totalResults: results.total_results,
|
|
|
|
results: results.results.map((result) =>
|
|
|
|
mapMovieResult(
|
|
|
|
result,
|
|
|
|
media.find(
|
|
|
|
(req) =>
|
|
|
|
req.tmdbId === result.id && req.mediaType === MediaType.MOVIE
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
logger.debug('Something went wrong retrieving movie recommendations', {
|
|
|
|
label: 'API',
|
|
|
|
errorMessage: e.message,
|
|
|
|
movieId: req.params.id,
|
|
|
|
});
|
|
|
|
return next({
|
|
|
|
status: 500,
|
|
|
|
message: 'Unable to retrieve movie recommendations.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
movieRoutes.get('/:id/similar', async (req, res, next) => {
|
|
|
|
const tmdb = new TheMovieDb();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const results = await tmdb.getMovieSimilar({
|
|
|
|
movieId: Number(req.params.id),
|
|
|
|
page: Number(req.query.page),
|
|
|
|
language: (req.query.language as string) ?? req.locale,
|
|
|
|
});
|
|
|
|
|
|
|
|
const media = await Media.getRelatedMedia(
|
|
|
|
results.results.map((result) => result.id)
|
|
|
|
);
|
|
|
|
|
|
|
|
return res.status(200).json({
|
|
|
|
page: results.page,
|
|
|
|
totalPages: results.total_pages,
|
|
|
|
totalResults: results.total_results,
|
|
|
|
results: results.results.map((result) =>
|
|
|
|
mapMovieResult(
|
|
|
|
result,
|
|
|
|
media.find(
|
|
|
|
(req) =>
|
|
|
|
req.tmdbId === result.id && req.mediaType === MediaType.MOVIE
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
logger.debug('Something went wrong retrieving similar movies', {
|
|
|
|
label: 'API',
|
|
|
|
errorMessage: e.message,
|
|
|
|
movieId: req.params.id,
|
|
|
|
});
|
|
|
|
return next({
|
|
|
|
status: 500,
|
|
|
|
message: 'Unable to retrieve similar movies.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Endpoint backed by RottenTomatoes
|
|
|
|
*/
|
|
|
|
movieRoutes.get('/:id/ratings', async (req, res, next) => {
|
|
|
|
const tmdb = new TheMovieDb();
|
|
|
|
const rtapi = new RottenTomatoes();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const movie = await tmdb.getMovie({
|
|
|
|
movieId: Number(req.params.id),
|
|
|
|
});
|
|
|
|
|
|
|
|
const rtratings = await rtapi.getMovieRatings(
|
|
|
|
movie.title,
|
|
|
|
Number(movie.release_date.slice(0, 4))
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!rtratings) {
|
|
|
|
return next({
|
|
|
|
status: 404,
|
|
|
|
message: 'Rotten Tomatoes ratings not found.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return res.status(200).json(rtratings);
|
|
|
|
} catch (e) {
|
|
|
|
logger.debug('Something went wrong retrieving movie ratings', {
|
|
|
|
label: 'API',
|
|
|
|
errorMessage: e.message,
|
|
|
|
movieId: req.params.id,
|
|
|
|
});
|
|
|
|
return next({
|
|
|
|
status: 500,
|
|
|
|
message: 'Unable to retrieve movie ratings.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Endpoint combining RottenTomatoes and IMDB
|
|
|
|
*/
|
|
|
|
movieRoutes.get('/:id/ratingscombined', async (req, res, next) => {
|
|
|
|
const tmdb = new TheMovieDb();
|
|
|
|
const rtapi = new RottenTomatoes();
|
|
|
|
const imdbApi = new IMDBRadarrProxy();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const movie = await tmdb.getMovie({
|
|
|
|
movieId: Number(req.params.id),
|
|
|
|
});
|
|
|
|
|
|
|
|
const rtratings = await rtapi.getMovieRatings(
|
|
|
|
movie.title,
|
|
|
|
Number(movie.release_date.slice(0, 4))
|
|
|
|
);
|
|
|
|
|
|
|
|
let imdbRatings;
|
|
|
|
if (movie.imdb_id) {
|
|
|
|
imdbRatings = await imdbApi.getMovieRatings(movie.imdb_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rtratings && !imdbRatings) {
|
|
|
|
return next({
|
|
|
|
status: 404,
|
|
|
|
message: 'No ratings found.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const ratings: RatingResponse = {
|
|
|
|
...(rtratings ? { rt: rtratings } : {}),
|
|
|
|
...(imdbRatings ? { imdb: imdbRatings } : {}),
|
|
|
|
};
|
|
|
|
|
|
|
|
return res.status(200).json(ratings);
|
|
|
|
} catch (e) {
|
|
|
|
logger.debug('Something went wrong retrieving movie ratings', {
|
|
|
|
label: 'API',
|
|
|
|
errorMessage: e.message,
|
|
|
|
movieId: req.params.id,
|
|
|
|
});
|
|
|
|
return next({
|
|
|
|
status: 500,
|
|
|
|
message: 'Unable to retrieve movie ratings.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
export default movieRoutes;
|