diff --git a/overseerr-api.yml b/overseerr-api.yml index c4c1e97b..e23b97c3 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -5018,7 +5018,7 @@ paths: - type: array items: type: number - minimum: 1 + minimum: 0 - type: string enum: [all] is4k: @@ -5124,7 +5124,7 @@ paths: type: array items: type: number - minimum: 1 + minimum: 0 is4k: type: boolean example: false diff --git a/server/entity/MediaRequest.ts b/server/entity/MediaRequest.ts index ba67ab7b..bf4eb6df 100644 --- a/server/entity/MediaRequest.ts +++ b/server/entity/MediaRequest.ts @@ -246,9 +246,7 @@ export class MediaRequest { >; const requestedSeasons = requestBody.seasons === 'all' - ? tmdbMediaShow.seasons - .map((season) => season.season_number) - .filter((sn) => sn > 0) + ? tmdbMediaShow.seasons.map((season) => season.season_number) : (requestBody.seasons as number[]); let existingSeasons: number[] = []; diff --git a/server/lib/scanners/plex/index.ts b/server/lib/scanners/plex/index.ts index f074872b..58a948a8 100644 --- a/server/lib/scanners/plex/index.ts +++ b/server/lib/scanners/plex/index.ts @@ -278,9 +278,7 @@ class PlexScanner const seasons = tvShow.seasons; const processableSeasons: ProcessableSeason[] = []; - const filteredSeasons = seasons.filter((sn) => sn.season_number !== 0); - - for (const season of filteredSeasons) { + for (const season of seasons) { const matchedPlexSeason = metadata.Children?.Metadata.find( (md) => Number(md.index) === season.season_number ); diff --git a/server/lib/scanners/sonarr/index.ts b/server/lib/scanners/sonarr/index.ts index 3256c948..5d28e014 100644 --- a/server/lib/scanners/sonarr/index.ts +++ b/server/lib/scanners/sonarr/index.ts @@ -103,10 +103,8 @@ class SonarrScanner const tmdbId = tvShow.id; - const filteredSeasons = sonarrSeries.seasons.filter( - (sn) => - sn.seasonNumber !== 0 && - tvShow.seasons.find((s) => s.season_number === sn.seasonNumber) + const filteredSeasons = sonarrSeries.seasons.filter((sn) => + tvShow.seasons.find((s) => s.season_number === sn.seasonNumber) ); for (const season of filteredSeasons) { diff --git a/src/components/RequestBlock/index.tsx b/src/components/RequestBlock/index.tsx index ed4c3ec3..fa09e145 100644 --- a/src/components/RequestBlock/index.tsx +++ b/src/components/RequestBlock/index.tsx @@ -35,6 +35,7 @@ const messages = defineMessages({ decline: 'Decline Request', edit: 'Edit Request', delete: 'Delete Request', + specials: 'Specials', }); interface RequestBlockProps { @@ -243,7 +244,11 @@ const RequestBlock = ({ request, onUpdate }: RequestBlockProps) => { key={`season-${season.id}`} className="mb-1 mr-2 inline-block" > - {season.seasonNumber} + + {season.seasonNumber == 0 + ? intl.formatMessage(messages.specials) + : season.seasonNumber} + ))} diff --git a/src/components/RequestCard/index.tsx b/src/components/RequestCard/index.tsx index 44abd555..7dc6683b 100644 --- a/src/components/RequestCard/index.tsx +++ b/src/components/RequestCard/index.tsx @@ -40,6 +40,7 @@ const messages = defineMessages({ cancelrequest: 'Cancel Request', deleterequest: 'Delete Request', unknowntitle: 'Unknown Title', + specials: 'Specials', }); const isMovie = (movie: MovieDetails | TvDetails): movie is MovieDetails => { @@ -381,8 +382,7 @@ const RequestCard = ({ request, onTitleData }: RequestCardProps) => { {intl.formatMessage(messages.seasons, { seasonCount: - title.seasons.filter((season) => season.seasonNumber !== 0) - .length === request.seasons.length + title.seasons.length === request.seasons.length ? 0 : request.seasons.length, })} @@ -390,7 +390,11 @@ const RequestCard = ({ request, onTitleData }: RequestCardProps) => {
{request.seasons.map((season) => ( - {season.seasonNumber} + + {season.seasonNumber == 0 + ? intl.formatMessage(messages.specials) + : season.seasonNumber} + ))}
diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx index a42483ab..556982b1 100644 --- a/src/components/RequestList/RequestItem/index.tsx +++ b/src/components/RequestList/RequestItem/index.tsx @@ -41,6 +41,7 @@ const messages = defineMessages({ tmdbid: 'TMDB ID', tvdbid: 'TheTVDB ID', unknowntitle: 'Unknown Title', + specials: 'Specials', }); const isMovie = (movie: MovieDetails | TvDetails): movie is MovieDetails => { @@ -440,9 +441,7 @@ const RequestItem = ({ request, revalidateList }: RequestItemProps) => { {intl.formatMessage(messages.seasons, { seasonCount: - title.seasons.filter( - (season) => season.seasonNumber !== 0 - ).length === request.seasons.length + title.seasons.length === request.seasons.length ? 0 : request.seasons.length, })} @@ -450,7 +449,11 @@ const RequestItem = ({ request, revalidateList }: RequestItemProps) => {
{request.seasons.map((season) => ( - {season.seasonNumber} + + {season.seasonNumber == 0 + ? intl.formatMessage(messages.specials) + : season.seasonNumber} + ))}
diff --git a/src/components/RequestModal/TvRequestModal.tsx b/src/components/RequestModal/TvRequestModal.tsx index 25c8fd3c..ac0fec5a 100644 --- a/src/components/RequestModal/TvRequestModal.tsx +++ b/src/components/RequestModal/TvRequestModal.tsx @@ -41,7 +41,7 @@ const messages = defineMessages({ season: 'Season', numberofepisodes: '# of Episodes', seasonnumber: 'Season {number}', - extras: 'Extras', + specials: 'Specials', errorediting: 'Something went wrong while editing the request.', requestedited: 'Request for {title} edited successfully!', requestApproved: 'Request for {title} approved!', @@ -232,9 +232,7 @@ const TvRequestModal = ({ const getAllSeasons = (): number[] => { return (data?.seasons ?? []) - .filter( - (season) => season.seasonNumber !== 0 && season.episodeCount !== 0 - ) + .filter((season) => season.episodeCount !== 0) .map((season) => season.seasonNumber); }; @@ -557,10 +555,7 @@ const TvRequestModal = ({ {data?.seasons - .filter( - (season) => - season.seasonNumber !== 0 && season.episodeCount !== 0 - ) + .filter((season) => season.episodeCount !== 0) .map((season) => { const seasonRequest = getSeasonRequest( season.seasonNumber @@ -637,7 +632,7 @@ const TvRequestModal = ({ {season.seasonNumber === 0 - ? intl.formatMessage(messages.extras) + ? intl.formatMessage(messages.specials) : intl.formatMessage(messages.seasonnumber, { number: season.seasonNumber, })} diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index 2f44a7d8..e70346db 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -82,6 +82,7 @@ const messages = defineMessages({ seasonstitle: 'Seasons', episodeCount: '{episodeCount, plural, one {# Episode} other {# Episodes}}', seasonnumber: 'Season {seasonNumber}', + specials: 'Specials', status4k: '4K {status}', rtcriticsscore: 'Rotten Tomatoes Tomatometer', rtaudiencescore: 'Rotten Tomatoes Audience Score', @@ -200,6 +201,7 @@ const TvDetails = ({ tv }: TvDetailsProps) => { ); } + // Does NOT include "Specials" const seasonCount = data.seasons.filter( (season) => season.seasonNumber !== 0 && season.episodeCount !== 0 ).length; @@ -257,9 +259,17 @@ const TvDetails = ({ tv }: TvDetailsProps) => { return [...requestedSeasons, ...availableSeasons]; }; - const isComplete = seasonCount <= getAllRequestedSeasons(false).length; + const showHasSpecials = data.seasons.some( + (season) => season.seasonNumber == 0 + ); + + const isComplete = + (showHasSpecials ? seasonCount + 1 : seasonCount) <= + getAllRequestedSeasons(false).length; - const is4kComplete = seasonCount <= getAllRequestedSeasons(true).length; + const is4kComplete = + (showHasSpecials ? seasonCount + 1 : seasonCount) <= + getAllRequestedSeasons(true).length; const streamingProviders = data?.watchProviders?.find((provider) => provider.iso_3166_1 === region) @@ -522,7 +532,6 @@ const TvDetails = ({ tv }: TvDetailsProps) => { {data.seasons .slice() .reverse() - .filter((season) => season.seasonNumber !== 0) .map((season) => { const show4k = settings.currentSettings.series4kEnabled && @@ -576,9 +585,11 @@ const TvDetails = ({ tv }: TvDetailsProps) => { >
- {intl.formatMessage(messages.seasonnumber, { - seasonNumber: season.seasonNumber, - })} + {season.seasonNumber == 0 + ? intl.formatMessage(messages.specials) + : intl.formatMessage(messages.seasonnumber, { + seasonNumber: season.seasonNumber, + })} {intl.formatMessage(messages.episodeCount, { diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 10165c9e..2d232b1a 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -399,6 +399,7 @@ "components.RequestBlock.rootfolder": "Root Folder", "components.RequestBlock.seasons": "{seasonCount, plural, one {Season} other {Seasons}}", "components.RequestBlock.server": "Destination Server", + "components.RequestBlock.specials": "Specials", "components.RequestButton.approve4krequests": "Approve {requestCount, plural, one {4K Request} other {{requestCount} 4K Requests}}", "components.RequestButton.approverequest": "Approve Request", "components.RequestButton.approverequest4k": "Approve 4K Request", @@ -419,6 +420,7 @@ "components.RequestCard.failedretry": "Something went wrong while retrying the request.", "components.RequestCard.mediaerror": "{mediaType} Not Found", "components.RequestCard.seasons": "{seasonCount, plural, one {Season} other {Seasons}}", + "components.RequestCard.specials": "Specials", "components.RequestCard.tmdbid": "TMDB ID", "components.RequestCard.tvdbid": "TheTVDB ID", "components.RequestCard.unknowntitle": "Unknown Title", @@ -432,6 +434,7 @@ "components.RequestList.RequestItem.requested": "Requested", "components.RequestList.RequestItem.requesteddate": "Requested", "components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Season} other {Seasons}}", + "components.RequestList.RequestItem.specials": "Specials", "components.RequestList.RequestItem.tmdbid": "TMDB ID", "components.RequestList.RequestItem.tvdbid": "TheTVDB ID", "components.RequestList.RequestItem.unknowntitle": "Unknown Title", @@ -471,7 +474,6 @@ "components.RequestModal.cancel": "Cancel Request", "components.RequestModal.edit": "Edit Request", "components.RequestModal.errorediting": "Something went wrong while editing the request.", - "components.RequestModal.extras": "Extras", "components.RequestModal.numberofepisodes": "# of Episodes", "components.RequestModal.pending4krequest": "Pending 4K Request", "components.RequestModal.pendingapproval": "Your request is pending approval.", @@ -498,6 +500,7 @@ "components.RequestModal.seasonnumber": "Season {number}", "components.RequestModal.selectmovies": "Select Movie(s)", "components.RequestModal.selectseason": "Select Season(s)", + "components.RequestModal.specials": "Specials", "components.ResetPassword.confirmpassword": "Confirm Password", "components.ResetPassword.email": "Email Address", "components.ResetPassword.emailresetlink": "Email Recovery Link", @@ -1027,6 +1030,7 @@ "components.TvDetails.seasonstitle": "Seasons", "components.TvDetails.showtype": "Series Type", "components.TvDetails.similar": "Similar Series", + "components.TvDetails.specials": "Specials", "components.TvDetails.status4k": "4K {status}", "components.TvDetails.streamingproviders": "Currently Streaming On", "components.TvDetails.tmdbuserscore": "TMDB User Score",