From c8b2a57721a51adcc7f90ec1acb48b127991d467 Mon Sep 17 00:00:00 2001 From: Danshil Mungur Date: Tue, 9 Feb 2021 12:24:07 +0400 Subject: [PATCH] feat(ui): added content ratings for tv shows and movie ratings (#878) --- .gitignore | 2 ++ overseerr-api.yml | 49 +++++++++++++++++++++++++++ server/api/themoviedb/index.ts | 4 +-- server/api/themoviedb/interfaces.ts | 26 ++++++++++++++ server/models/Movie.ts | 7 +++- server/models/Tv.ts | 3 ++ src/components/MovieDetails/index.tsx | 25 ++++++++++++-- src/components/TvDetails/index.tsx | 28 ++++++++++++++- 8 files changed, 138 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index b13c94726..8e1866224 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,8 @@ config/settings.json # logs config/logs/*.log* config/logs/*.json +config/logs/*.log.gz +config/logs/*-audit.json # anidb mapping file config/anime-list.xml diff --git a/overseerr-api.yml b/overseerr-api.yml index cf7224484..5c9ae45a6 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -644,6 +644,41 @@ components: type: string releaseDate: type: string + releases: + type: object + properties: + results: + type: array + items: + type: object + properties: + iso_3166_1: + type: string + example: 'US' + rating: + type: string + nullable: true + release_dates: + type: array + items: + type: object + properties: + certification: + type: string + example: 'PG-13' + iso_639_1: + type: string + nullable: true + note: + type: string + nullable: true + example: 'Blu ray' + release_date: + type: string + example: '2017-07-12T00:00:00.000Z' + type: + type: number + example: 1 revenue: type: number nullable: true @@ -752,6 +787,20 @@ components: type: string posterPath: type: string + contentRatings: + type: object + properties: + results: + type: array + items: + type: object + properties: + iso_3166_1: + type: string + example: 'US' + rating: + type: string + example: 'TV-14' createdBy: type: array items: diff --git a/server/api/themoviedb/index.ts b/server/api/themoviedb/index.ts index be1a629eb..689b3a87f 100644 --- a/server/api/themoviedb/index.ts +++ b/server/api/themoviedb/index.ts @@ -145,7 +145,7 @@ class TheMovieDb extends ExternalAPI { { params: { language, - append_to_response: 'credits,external_ids,videos', + append_to_response: 'credits,external_ids,videos,release_dates', }, }, 43200 @@ -171,7 +171,7 @@ class TheMovieDb extends ExternalAPI { params: { language, append_to_response: - 'aggregate_credits,credits,external_ids,keywords,videos', + 'aggregate_credits,credits,external_ids,keywords,videos,content_ratings', }, }, 43200 diff --git a/server/api/themoviedb/interfaces.ts b/server/api/themoviedb/interfaces.ts index 63b0ba9a2..383380cb4 100644 --- a/server/api/themoviedb/interfaces.ts +++ b/server/api/themoviedb/interfaces.ts @@ -136,6 +136,7 @@ export interface TmdbMovieDetails { name: string; }[]; release_date: string; + release_dates: TmdbMovieReleaseResult; revenue: number; runtime?: number; spoken_languages: { @@ -205,6 +206,7 @@ export interface TmdbTvSeasonResult { export interface TmdbTvDetails { id: number; backdrop_path?: string; + content_ratings: TmdbTvRatingResult; created_by: { id: number; credit_id: string; @@ -272,6 +274,29 @@ export interface TmdbVideoResult { results: TmdbVideo[]; } +export interface TmdbTvRatingResult { + results: TmdbRating[]; +} + +export interface TmdbRating { + iso_3166_1: string; + rating: string; +} + +export interface TmdbMovieReleaseResult { + results: TmdbRelease[]; +} + +export interface TmdbRelease extends TmdbRating { + release_dates: { + certification: string; + iso_639_1?: string; + note?: string; + release_date: string; + type: number; + }[]; +} + export interface TmdbKeyword { id: number; name: string; @@ -316,6 +341,7 @@ export interface TmdbPersonCredit { adult: boolean; release_date: string; } + export interface TmdbPersonCreditCast extends TmdbPersonCredit { character: string; } diff --git a/server/models/Movie.ts b/server/models/Movie.ts index bfeb95ac3..be4828ec6 100644 --- a/server/models/Movie.ts +++ b/server/models/Movie.ts @@ -1,4 +1,7 @@ -import type { TmdbMovieDetails } from '../api/themoviedb/interfaces'; +import type { + TmdbMovieDetails, + TmdbMovieReleaseResult, +} from '../api/themoviedb/interfaces'; import { ProductionCompany, Genre, @@ -48,6 +51,7 @@ export interface MovieDetails { name: string; }[]; releaseDate: string; + releases: TmdbMovieReleaseResult; revenue: number; runtime?: number; spokenLanguages: { @@ -95,6 +99,7 @@ export const mapMovieDetails = ( })), productionCountries: movie.production_countries, releaseDate: movie.release_date, + releases: movie.release_dates, revenue: movie.revenue, spokenLanguages: movie.spoken_languages, status: movie.status, diff --git a/server/models/Tv.ts b/server/models/Tv.ts index 420dca28f..3631573ea 100644 --- a/server/models/Tv.ts +++ b/server/models/Tv.ts @@ -15,6 +15,7 @@ import type { TmdbTvSeasonResult, TmdbTvDetails, TmdbSeasonWithEpisodes, + TmdbTvRatingResult, } from '../api/themoviedb/interfaces'; import type Media from '../entity/Media'; import { Video } from './Movie'; @@ -58,6 +59,7 @@ export interface TvDetails { id: number; backdropPath?: string; posterPath?: string; + contentRatings: TmdbTvRatingResult; createdBy: { id: number; name: string; @@ -174,6 +176,7 @@ export const mapTvDetails = ( originCountry: company.origin_country, logoPath: company.logo_path, })), + contentRatings: show.content_ratings, spokenLanguages: show.spoken_languages.map((language) => ({ englishName: language.english_name, iso_639_1: language.iso_639_1, diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index 4804d238d..970632ccb 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -129,7 +129,22 @@ const MovieDetails: React.FC = ({ movie }) => { revalidate(); }; - const movieAttributes = []; + const movieAttributes: React.ReactNode[] = []; + + if ( + data.releases.results.length && + (data.releases.results.find((r) => r.iso_3166_1 === 'US')?.release_dates[0] + .certification || + data.releases.results[0].release_dates[0].certification) + ) { + movieAttributes.push( + + {data.releases.results.find((r) => r.iso_3166_1 === 'US') + ?.release_dates[0].certification || + data.releases.results[0].release_dates[0].certification} + + ); + } if (data.runtime) { movieAttributes.push( @@ -369,7 +384,13 @@ const MovieDetails: React.FC = ({ movie }) => { )} - {movieAttributes.join(' | ')} + {movieAttributes + .map((t, k) => {t}) + .reduce((prev, curr) => ( + <> + {prev} | {curr} + + ))}
diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index f19ca4983..affc4ad57 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -133,6 +133,26 @@ const TvDetails: React.FC = ({ tv }) => { revalidate(); }; + const seriesAttributes: React.ReactNode[] = []; + + if ( + data.contentRatings.results.length && + data.contentRatings.results.find( + (r) => r.iso_3166_1 === 'US' || data.contentRatings.results[0].rating + ) + ) { + seriesAttributes.push( + + {data.contentRatings.results.find((r) => r.iso_3166_1 === 'US') + ?.rating || data.contentRatings.results[0].rating} + + ); + } + + if (data.genres.length) { + seriesAttributes.push(data.genres.map((g) => g.name).join(', ')); + } + const isComplete = data.seasons.filter((season) => season.seasonNumber !== 0).length <= ( @@ -392,7 +412,13 @@ const TvDetails: React.FC = ({ tv }) => { )} - {data.genres.map((g) => g.name).join(', ')} + {seriesAttributes + .map((t, k) => {t}) + .reduce((prev, curr) => ( + <> + {prev} | {curr} + + ))}