Skip to content

Commit

Permalink
feat: add studio/network view to movie/series Discover results
Browse files Browse the repository at this point in the history
  • Loading branch information
TheCatLady committed Mar 3, 2021
1 parent a22d207 commit a646347
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 6 deletions.
50 changes: 50 additions & 0 deletions overseerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3228,6 +3228,11 @@ paths:
schema:
type: number
example: 10751
- in: query
name: studio
schema:
type: number
example: 2
responses:
'200':
description: Results
Expand Down Expand Up @@ -3311,6 +3316,11 @@ paths:
schema:
type: number
example: 18
- in: query
name: network
schema:
type: number
example: 1
responses:
'200':
description: Results
Expand Down Expand Up @@ -4371,6 +4381,46 @@ paths:
name:
type: string
example: English
/studio/{studioId}:
get:
summary: Get movie studio details
description: Returns movie studio details in a JSON object.
tags:
- tmdb
parameters:
- in: path
name: studioId
required: true
schema:
type: number
example: 2
responses:
'200':
description: Movie studio details
content:
application/json:
schema:
$ref: '#/components/schemas/ProductionCompany'
/network/{networkId}:
get:
summary: Get TV network details
description: Returns TV network details in a JSON object.
tags:
- tmdb
parameters:
- in: path
name: networkId
required: true
schema:
type: number
example: 1
responses:
'200':
description: TV network details
content:
application/json:
schema:
$ref: '#/components/schemas/ProductionCompany'
/genres/movie:
get:
summary: Get list of official TMDb movie genres
Expand Down
28 changes: 28 additions & 0 deletions server/api/themoviedb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import cacheManager from '../../lib/cache';
import ExternalAPI from '../externalapi';
import {
TmdbCollection,
TmdbStudio,
TmdbExternalIdResponse,
TmdbGenre,
TmdbGenresResult,
TmdbLanguage,
TmdbMovieDetails,
TmdbNetwork,
TmdbPersonCombinedCredits,
TmdbPersonDetail,
TmdbRegion,
Expand All @@ -33,6 +35,7 @@ interface DiscoverMovieOptions {
primaryReleaseDateGte?: string;
primaryReleaseDateLte?: string;
genre?: number;
studio?: number;
sortBy?:
| 'popularity.asc'
| 'popularity.desc'
Expand All @@ -57,6 +60,7 @@ interface DiscoverTvOptions {
firstAirDateLte?: string;
includeEmptyReleaseDate?: boolean;
genre?: number;
network?: number;
sortBy?:
| 'popularity.asc'
| 'popularity.desc'
Expand Down Expand Up @@ -365,6 +369,7 @@ class TheMovieDb extends ExternalAPI {
primaryReleaseDateGte,
primaryReleaseDateLte,
genre,
studio,
}: DiscoverMovieOptions = {}): Promise<TmdbSearchMovieResponse> => {
try {
const data = await this.get<TmdbSearchMovieResponse>('/discover/movie', {
Expand All @@ -379,6 +384,7 @@ class TheMovieDb extends ExternalAPI {
'primary_release_date.gte': primaryReleaseDateGte,
'primary_release_date.lte': primaryReleaseDateLte,
with_genres: genre,
with_companies: studio,
},
});

Expand All @@ -396,6 +402,7 @@ class TheMovieDb extends ExternalAPI {
firstAirDateLte,
includeEmptyReleaseDate = false,
genre,
network,
}: DiscoverTvOptions = {}): Promise<TmdbSearchTvResponse> => {
try {
const data = await this.get<TmdbSearchTvResponse>('/discover/tv', {
Expand All @@ -409,6 +416,7 @@ class TheMovieDb extends ExternalAPI {
with_original_language: this.originalLanguage,
include_null_first_air_dates: includeEmptyReleaseDate,
with_genres: genre,
with_networks: network,
},
});

Expand Down Expand Up @@ -668,6 +676,26 @@ class TheMovieDb extends ExternalAPI {
}
}

public async getStudio(studioId: number): Promise<TmdbStudio> {
try {
const data = await this.get<TmdbStudio>(`/company/${studioId}`);

return data;
} catch (e) {
throw new Error(`[TMDb] Failed to fetch movie studio: ${e.message}`);
}
}

public async getNetwork(networkId: number): Promise<TmdbNetwork> {
try {
const data = await this.get<TmdbNetwork>(`/network/${networkId}`);

return data;
} catch (e) {
throw new Error(`[TMDb] Failed to fetch TV network: ${e.message}`);
}
}

public async getMovieGenres(): Promise<TmdbGenre[]> {
try {
const data = await this.get<TmdbGenresResult>(
Expand Down
20 changes: 20 additions & 0 deletions server/api/themoviedb/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,23 @@ export interface TmdbGenre {
id: number;
name: string;
}

export interface TmdbStudio {
id: number;
name: string;
description?: string;
headquarters?: string;
homepage?: string;
logo_path?: string;
origin_country?: string;
parent_company?: TmdbStudio;
}

export interface TmdbNetwork {
id: number;
name: string;
headquarters?: string;
homepage?: string;
logo_path?: string;
origin_country?: string;
}
2 changes: 2 additions & 0 deletions server/routes/discover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ discoverRoutes.get('/movies', async (req, res) => {
page: Number(req.query.page),
language: req.query.language as string,
genre: req.query.genre ? Number(req.query.genre) : undefined,
studio: req.query.studio ? Number(req.query.studio) : undefined,
});

const media = await Media.getRelatedMedia(
Expand Down Expand Up @@ -101,6 +102,7 @@ discoverRoutes.get('/tv', async (req, res) => {
page: Number(req.query.page),
language: req.query.language as string,
genre: req.query.genre ? Number(req.query.genre) : undefined,
network: req.query.network ? Number(req.query.network) : undefined,
});

const media = await Media.getRelatedMedia(
Expand Down
16 changes: 16 additions & 0 deletions server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ router.get('/languages', isAuthenticated(), async (req, res) => {
return res.status(200).json(languages);
});

router.get<{ id: string }>('/studio/:id', async (req, res) => {
const tmdb = new TheMovieDb();

const studio = await tmdb.getStudio(Number(req.params.id));

return res.status(200).json(studio);
});

router.get<{ id: string }>('/network/:id', async (req, res) => {
const tmdb = new TheMovieDb();

const network = await tmdb.getNetwork(Number(req.params.id));

return res.status(200).json(network);
});

router.get('/genres/movie', isAuthenticated(), async (req, res) => {
const tmdb = new TheMovieDb();

Expand Down
14 changes: 12 additions & 2 deletions src/components/Discover/DiscoverMovies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import useSettings from '../../hooks/useSettings';
import { MediaStatus } from '../../../server/constants/media';
import PageTitle from '../Common/PageTitle';
import { useRouter } from 'next/router';
import { TmdbGenre } from '../../../server/api/themoviedb/interfaces';
import {
TmdbStudio,
TmdbGenre,
} from '../../../server/api/themoviedb/interfaces';

const messages = defineMessages({
discovermovies: 'Popular Movies',
genreMovies: '{genre} Movies',
studioMovies: '{studio} Movies',
});

interface SearchResult {
Expand All @@ -32,6 +36,10 @@ const DiscoverMovies: React.FC = () => {
const { data: genres } = useSWR<TmdbGenre[]>('/api/v1/genres/movie');
const genre = genres?.find((g) => g.id === Number(router.query.genreId));

const { data: studio } = useSWR<TmdbStudio>(
`/api/v1/studio/${router.query.studioId}`
);

const { data, error, size, setSize } = useSWRInfinite<SearchResult>(
(pageIndex: number, previousPageData: SearchResult | null) => {
if (previousPageData && pageIndex + 1 > previousPageData.totalPages) {
Expand All @@ -40,7 +48,7 @@ const DiscoverMovies: React.FC = () => {

return `/api/v1/discover/movies?page=${pageIndex + 1}&language=${locale}${
genre ? `&genre=${genre.id}` : ''
}`;
}${studio ? `&studio=${studio.id}` : ''}`;
},
{
initialSize: 3,
Expand Down Expand Up @@ -80,6 +88,8 @@ const DiscoverMovies: React.FC = () => {

const title = genre
? intl.formatMessage(messages.genreMovies, { genre: genre.name })
: studio
? intl.formatMessage(messages.studioMovies, { studio: studio.name })
: intl.formatMessage(messages.discovermovies);

return (
Expand Down
14 changes: 12 additions & 2 deletions src/components/Discover/DiscoverTv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import useSettings from '../../hooks/useSettings';
import { MediaStatus } from '../../../server/constants/media';
import PageTitle from '../Common/PageTitle';
import { useRouter } from 'next/router';
import { TmdbGenre } from '../../../server/api/themoviedb/interfaces';
import {
TmdbGenre,
TmdbNetwork,
} from '../../../server/api/themoviedb/interfaces';

const messages = defineMessages({
discovertv: 'Popular Series',
genreSeries: '{genre} Series',
networkSeries: '{network} Series',
});

interface SearchResult {
Expand All @@ -32,6 +36,10 @@ const DiscoverTv: React.FC = () => {
const { data: genres } = useSWR<TmdbGenre[]>('/api/v1/genres/tv');
const genre = genres?.find((g) => g.id === Number(router.query.genreId));

const { data: network } = useSWR<TmdbNetwork>(
`/api/v1/network/${router.query.networkId}`
);

const { data, error, size, setSize } = useSWRInfinite<SearchResult>(
(pageIndex: number, previousPageData: SearchResult | null) => {
if (previousPageData && pageIndex + 1 > previousPageData.totalPages) {
Expand All @@ -40,7 +48,7 @@ const DiscoverTv: React.FC = () => {

return `/api/v1/discover/tv?page=${pageIndex + 1}&language=${locale}${
genre ? `&genre=${genre.id}` : ''
}`;
}${network ? `&network=${network.id}` : ''}`;
},
{
initialSize: 3,
Expand Down Expand Up @@ -79,6 +87,8 @@ const DiscoverTv: React.FC = () => {

const title = genre
? intl.formatMessage(messages.genreSeries, { genre: genre.name })
: network
? intl.formatMessage(messages.networkSeries, { network: network.name })
: intl.formatMessage(messages.discovertv);

return (
Expand Down
8 changes: 7 additions & 1 deletion src/components/MovieDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,13 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
{intl.formatMessage(messages.studio)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
{data.productionCompanies[0]?.name}
<Link
href={`/discover/movies/studio/${data.productionCompanies[0].id}`}
>
<a className="hover:underline">
{data.productionCompanies[0].name}
</a>
</Link>
</span>
</div>
)}
Expand Down
15 changes: 14 additions & 1 deletion src/components/TvDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,20 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
{intl.formatMessage(messages.network)}
</span>
<span className="flex-1 text-sm text-right text-gray-400">
{data.networks.map((n) => n.name).join(', ')}
{data.networks
.map((n) => (
<Link
href={`/discover/tv/network/${n.id}`}
key={`network-${n.id}`}
>
<a className="hover:underline">{n.name}</a>
</Link>
))
.reduce((prev, curr) => (
<>
{prev}, {curr}
</>
))}
</span>
</div>
)}
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
"components.Discover.discovertv": "Popular Series",
"components.Discover.genreMovies": "{genre} Movies",
"components.Discover.genreSeries": "{genre} Series",
"components.Discover.networkSeries": "{network} Series",
"components.Discover.nopending": "No Pending Requests",
"components.Discover.popularmovies": "Popular Movies",
"components.Discover.populartv": "Popular Series",
"components.Discover.recentlyAdded": "Recently Added",
"components.Discover.recentrequests": "Recent Requests",
"components.Discover.studioMovies": "{studio} Movies",
"components.Discover.trending": "Trending",
"components.Discover.upcoming": "Upcoming Movies",
"components.Discover.upcomingmovies": "Upcoming Movies",
Expand Down
9 changes: 9 additions & 0 deletions src/pages/discover/movies/studio/[studioId]/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import { NextPage } from 'next';
import DiscoverMovies from '../../../../../components/Discover/DiscoverMovies';

const DiscoverMoviesStudioPage: NextPage = () => {
return <DiscoverMovies />;
};

export default DiscoverMoviesStudioPage;
9 changes: 9 additions & 0 deletions src/pages/discover/tv/network/[networkId]/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import { NextPage } from 'next';
import DiscoverTv from '../../../../../components/Discover/DiscoverTv';

const DiscoverTvNetworkPage: NextPage = () => {
return <DiscoverTv />;
};

export default DiscoverTvNetworkPage;

0 comments on commit a646347

Please sign in to comment.