From 15be3d7475805a5a2a7771d4ec9acd0eb942f3d1 Mon Sep 17 00:00:00 2001 From: fallenbagel <98979876+fallenbagel@users.noreply.github.com> Date: Fri, 13 Feb 2026 23:05:59 +0500 Subject: [PATCH] =?UTF-8?q?fix(base-scanner):=20derive=20media=20availabil?= =?UTF-8?q?ity=20from=20actual=20season=20state=E2=80=A6=20(#2412)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/lib/scanners/baseScanner.ts | 105 +++++++++++++---------------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/server/lib/scanners/baseScanner.ts b/server/lib/scanners/baseScanner.ts index 4a5549f3..9ad2b381 100644 --- a/server/lib/scanners/baseScanner.ts +++ b/server/lib/scanners/baseScanner.ts @@ -385,26 +385,6 @@ class BaseScanner { } } - // We want to skip specials when checking if a show is available - const isAllStandardSeasons = - seasons.length && - seasons - .filter((season) => season.seasonNumber !== 0) - .every( - (season) => - season.episodes === season.totalEpisodes && season.episodes > 0 - ); - - const isAll4kSeasons = - seasons.length && - seasons - .filter((season) => season.seasonNumber !== 0) - .every( - (season) => - season.episodes4k === season.totalEpisodes && - season.episodes4k > 0 - ); - if (media) { media.seasons = [...media.seasons, ...newSeasons]; @@ -464,43 +444,38 @@ class BaseScanner { externalServiceSlug; } - // If the show is already available, and there are no new seasons, dont adjust - // the status. Skip specials when performing availability check - const shouldStayAvailable = - media.status === MediaStatus.AVAILABLE && - newSeasons.filter( - (season) => - season.status !== MediaStatus.UNKNOWN && - season.status !== MediaStatus.DELETED && - season.seasonNumber !== 0 - ).length === 0; - const shouldStayAvailable4k = - media.status4k === MediaStatus.AVAILABLE && - newSeasons.filter( - (season) => - season.status4k !== MediaStatus.UNKNOWN && - season.status4k !== MediaStatus.DELETED && - season.seasonNumber !== 0 - ).length === 0; - media.status = - isAllStandardSeasons || shouldStayAvailable - ? MediaStatus.AVAILABLE - : media.seasons.some( - (season) => - season.status === MediaStatus.PARTIALLY_AVAILABLE || - season.status === MediaStatus.AVAILABLE + const nonSpecialSeasons = media.seasons.filter( + (s) => s.seasonNumber !== 0 + ); + + // Check the actual season objects instead scanner input + // to determine overall availability status + const isAllStandardSeasonsAvailable = + nonSpecialSeasons.length > 0 && + nonSpecialSeasons.every((s) => s.status === MediaStatus.AVAILABLE); + + const isAll4kSeasonsAvailable = + nonSpecialSeasons.length > 0 && + nonSpecialSeasons.every((s) => s.status4k === MediaStatus.AVAILABLE); + + media.status = isAllStandardSeasonsAvailable + ? MediaStatus.AVAILABLE + : media.seasons.some( + (season) => + season.status === MediaStatus.PARTIALLY_AVAILABLE || + season.status === MediaStatus.AVAILABLE + ) + ? MediaStatus.PARTIALLY_AVAILABLE + : (!seasons.length && media.status !== MediaStatus.DELETED) || + media.seasons.some( + (season) => season.status === MediaStatus.PROCESSING ) - ? MediaStatus.PARTIALLY_AVAILABLE - : (!seasons.length && media.status !== MediaStatus.DELETED) || - media.seasons.some( - (season) => season.status === MediaStatus.PROCESSING - ) - ? MediaStatus.PROCESSING - : media.status === MediaStatus.DELETED - ? MediaStatus.DELETED - : MediaStatus.UNKNOWN; + ? MediaStatus.PROCESSING + : media.status === MediaStatus.DELETED + ? MediaStatus.DELETED + : MediaStatus.UNKNOWN; media.status4k = - (isAll4kSeasons || shouldStayAvailable4k) && this.enable4kShow + isAll4kSeasonsAvailable && this.enable4kShow ? MediaStatus.AVAILABLE : this.enable4kShow && media.seasons.some( @@ -520,6 +495,22 @@ class BaseScanner { await mediaRepository.save(media); this.log(`Updating existing title: ${title}`); } else { + // For new media, check actual newSeasons objects instead of scanner + // input to determine overall availability status + const nonSpecialNewSeasons = newSeasons.filter( + (s) => s.seasonNumber !== 0 + ); + + const isAllStandardSeasonsAvailable = + nonSpecialNewSeasons.length > 0 && + nonSpecialNewSeasons.every((s) => s.status === MediaStatus.AVAILABLE); + + const isAll4kSeasonsAvailable = + nonSpecialNewSeasons.length > 0 && + nonSpecialNewSeasons.every( + (s) => s.status4k === MediaStatus.AVAILABLE + ); + const newMedia = new Media({ mediaType: MediaType.TV, seasons: newSeasons, @@ -564,7 +555,7 @@ class BaseScanner { ) ? jellyfinMediaId : undefined, - status: isAllStandardSeasons + status: isAllStandardSeasonsAvailable ? MediaStatus.AVAILABLE : newSeasons.some( (season) => @@ -578,7 +569,7 @@ class BaseScanner { ? MediaStatus.PROCESSING : MediaStatus.UNKNOWN, status4k: - isAll4kSeasons && this.enable4kShow + isAll4kSeasonsAvailable && this.enable4kShow ? MediaStatus.AVAILABLE : this.enable4kShow && newSeasons.some(