mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2025-12-31 19:59:31 -05:00
feat(tv): tv seasons
tv seasons
This commit is contained in:
@@ -1031,6 +1031,13 @@ components:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/WatchProviders'
|
$ref: '#/components/schemas/WatchProviders'
|
||||||
|
TvSeasons:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
seasons:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Season'
|
||||||
MediaRequest:
|
MediaRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -5082,6 +5089,37 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/TvDetails'
|
$ref: '#/components/schemas/TvDetails'
|
||||||
|
/tv/{tvId}/seasons:
|
||||||
|
get:
|
||||||
|
summary: Get TV seasons
|
||||||
|
description: Returns TV seasons based on the provided tvId in a JSON object.
|
||||||
|
tags:
|
||||||
|
- tv
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: tvId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 76479
|
||||||
|
- in: query
|
||||||
|
name: page
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 1
|
||||||
|
default: 1
|
||||||
|
- in: query
|
||||||
|
name: language
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: en
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: TV seasons
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/TvSeasons'
|
||||||
/tv/{tvId}/season/{seasonId}:
|
/tv/{tvId}/season/{seasonId}:
|
||||||
get:
|
get:
|
||||||
summary: Get season details and episode list
|
summary: Get season details and episode list
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
TmdbSearchTvResponse,
|
TmdbSearchTvResponse,
|
||||||
TmdbSeasonWithEpisodes,
|
TmdbSeasonWithEpisodes,
|
||||||
TmdbTvDetails,
|
TmdbTvDetails,
|
||||||
|
TmdbTvSeasonResult,
|
||||||
TmdbUpcomingMoviesResponse,
|
TmdbUpcomingMoviesResponse,
|
||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
|
|
||||||
@@ -271,6 +272,32 @@ class TheMovieDb extends ExternalAPI {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public getTvSeasons = async ({
|
||||||
|
tvId,
|
||||||
|
page = 1,
|
||||||
|
language = 'en',
|
||||||
|
}: {
|
||||||
|
tvId: number;
|
||||||
|
page: number;
|
||||||
|
language?: string;
|
||||||
|
}): Promise<TmdbTvSeasonResult[]> => {
|
||||||
|
try {
|
||||||
|
const data = await this.get<TmdbTvDetails>(
|
||||||
|
`/tv/${tvId}`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
page,
|
||||||
|
language,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
43200
|
||||||
|
);
|
||||||
|
return data.seasons;
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`[TMDb] Failed to fetch TV show seasons: ${e.message}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public getTvSeason = async ({
|
public getTvSeason = async ({
|
||||||
tvId,
|
tvId,
|
||||||
seasonNumber,
|
seasonNumber,
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ interface Season {
|
|||||||
seasonNumber: number;
|
seasonNumber: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TvSeasons {
|
||||||
|
seasons: Season[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface SeasonWithEpisodes extends Season {
|
export interface SeasonWithEpisodes extends Season {
|
||||||
episodes: Episode[];
|
episodes: Episode[];
|
||||||
externalIds: ExternalIds;
|
externalIds: ExternalIds;
|
||||||
@@ -223,3 +227,7 @@ export const mapTvDetails = (
|
|||||||
mediaInfo: media,
|
mediaInfo: media,
|
||||||
watchProviders: mapWatchProviders(show['watch/providers']?.results ?? {}),
|
watchProviders: mapWatchProviders(show['watch/providers']?.results ?? {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const mapTvSeasons = (seasons: TmdbTvSeasonResult[]): TvSeasons => ({
|
||||||
|
seasons: seasons.map(mapSeasonResult),
|
||||||
|
});
|
||||||
|
|||||||
@@ -5,7 +5,11 @@ import { MediaType } from '../constants/media';
|
|||||||
import Media from '../entity/Media';
|
import Media from '../entity/Media';
|
||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
import { mapTvResult } from '../models/Search';
|
import { mapTvResult } from '../models/Search';
|
||||||
import { mapSeasonWithEpisodes, mapTvDetails } from '../models/Tv';
|
import {
|
||||||
|
mapSeasonWithEpisodes,
|
||||||
|
mapTvDetails,
|
||||||
|
mapTvSeasons,
|
||||||
|
} from '../models/Tv';
|
||||||
|
|
||||||
const tvRoutes = Router();
|
const tvRoutes = Router();
|
||||||
|
|
||||||
@@ -33,6 +37,29 @@ tvRoutes.get('/:id', async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tvRoutes.get('/:id/seasons', async (req, res, next) => {
|
||||||
|
const tmdb = new TheMovieDb();
|
||||||
|
try {
|
||||||
|
const seasons = await tmdb.getTvSeasons({
|
||||||
|
tvId: Number(req.params.id),
|
||||||
|
page: Number(req.query.page),
|
||||||
|
language: req.locale ?? (req.query.language as string),
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json(mapTvSeasons(seasons));
|
||||||
|
} catch (e) {
|
||||||
|
logger.debug('Something went wrong retrieving seasons', {
|
||||||
|
label: 'API',
|
||||||
|
errorMessage: e.message,
|
||||||
|
tvId: req.params.id,
|
||||||
|
});
|
||||||
|
return next({
|
||||||
|
status: 500,
|
||||||
|
message: 'Unable to retrieve seasons.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
tvRoutes.get('/:id/season/:seasonNumber', async (req, res, next) => {
|
tvRoutes.get('/:id/season/:seasonNumber', async (req, res, next) => {
|
||||||
const tmdb = new TheMovieDb();
|
const tmdb = new TheMovieDb();
|
||||||
|
|
||||||
|
|||||||
@@ -672,6 +672,14 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<MediaSlider
|
||||||
|
sliderKey="seasons"
|
||||||
|
title={intl.formatMessage(messages.seasons)}
|
||||||
|
url={`/api/v1/tv/${data.id}/seasons`}
|
||||||
|
linkUrl={`/tv/${data.id}/seasons`}
|
||||||
|
hideWhenEmpty={false}
|
||||||
|
/>
|
||||||
|
|
||||||
{data.credits.cast.length > 0 && (
|
{data.credits.cast.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div className="slider-header">
|
<div className="slider-header">
|
||||||
|
|||||||
Reference in New Issue
Block a user