fix(base-scanner): derive media availability from actual season state instead of scanner input
The media-level status was incorrectly set to AVAILABLE when only some seasons were available. The issue was isAllStandardSeasons/isAll4kSeasons checked the scanner's input array which only contains seasons found by current scanner (e.g. 1 seaason in jellyfin). If that single season was fully available, the check passes and the media gets marked AVAILABLE regardless of how many total seasons existed. And the shouldStayAvailable (and its 4k check) locked the AVAILABLE status once set, as long as no new seasons were added with a status which prevented the incorrect status from correcting itself.
This commit is contained in:
@@ -385,26 +385,6 @@ class BaseScanner<T> {
|
||||
}
|
||||
}
|
||||
|
||||
// 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<T> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
)
|
||||
? jellyfinMediaId
|
||||
: undefined,
|
||||
status: isAllStandardSeasons
|
||||
status: isAllStandardSeasonsAvailable
|
||||
? MediaStatus.AVAILABLE
|
||||
: newSeasons.some(
|
||||
(season) =>
|
||||
@@ -578,7 +569,7 @@ class BaseScanner<T> {
|
||||
? MediaStatus.PROCESSING
|
||||
: MediaStatus.UNKNOWN,
|
||||
status4k:
|
||||
isAll4kSeasons && this.enable4kShow
|
||||
isAll4kSeasonsAvailable && this.enable4kShow
|
||||
? MediaStatus.AVAILABLE
|
||||
: this.enable4kShow &&
|
||||
newSeasons.some(
|
||||
|
||||
Reference in New Issue
Block a user