mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2026-01-01 04:08:45 -05:00
feat(tv): tv seasons
tv seasons
This commit is contained in:
@@ -1031,6 +1031,13 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/WatchProviders'
|
||||
TvSeasons:
|
||||
type: object
|
||||
properties:
|
||||
seasons:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Season'
|
||||
MediaRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -5082,6 +5089,37 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$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}:
|
||||
get:
|
||||
summary: Get season details and episode list
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
TmdbSearchTvResponse,
|
||||
TmdbSeasonWithEpisodes,
|
||||
TmdbTvDetails,
|
||||
TmdbTvSeasonResult,
|
||||
TmdbUpcomingMoviesResponse,
|
||||
} 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 ({
|
||||
tvId,
|
||||
seasonNumber,
|
||||
|
||||
@@ -48,6 +48,10 @@ interface Season {
|
||||
seasonNumber: number;
|
||||
}
|
||||
|
||||
export interface TvSeasons {
|
||||
seasons: Season[];
|
||||
}
|
||||
|
||||
export interface SeasonWithEpisodes extends Season {
|
||||
episodes: Episode[];
|
||||
externalIds: ExternalIds;
|
||||
@@ -223,3 +227,7 @@ export const mapTvDetails = (
|
||||
mediaInfo: media,
|
||||
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 logger from '../logger';
|
||||
import { mapTvResult } from '../models/Search';
|
||||
import { mapSeasonWithEpisodes, mapTvDetails } from '../models/Tv';
|
||||
import {
|
||||
mapSeasonWithEpisodes,
|
||||
mapTvDetails,
|
||||
mapTvSeasons,
|
||||
} from '../models/Tv';
|
||||
|
||||
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) => {
|
||||
const tmdb = new TheMovieDb();
|
||||
|
||||
|
||||
@@ -672,6 +672,14 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
|
||||
</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 && (
|
||||
<>
|
||||
<div className="slider-header">
|
||||
|
||||
Reference in New Issue
Block a user