fix: handle partial seasons more reliably (#4116)

refactor: remove matchingOldSeason variable
This commit is contained in:
Brandon Cohen
2025-04-18 18:20:30 -05:00
committed by GitHub
parent 064ae92134
commit 8cd53cdc3c
3 changed files with 50 additions and 50 deletions

View File

@@ -355,6 +355,7 @@ class AvailabilitySync {
); );
} }
media.lastSeasonChange = new Date();
await mediaRepository.save(media); await mediaRepository.save(media);
logger.info( logger.info(

View File

@@ -58,19 +58,16 @@ export class MediaRequestSubscriber
// Find all seasons in the related media entity // Find all seasons in the related media entity
// and see if they are available, then we can check // and see if they are available, then we can check
// if the request contains the same seasons // if the request contains the same seasons
const requestedSeasons =
entity.seasons?.map((entitySeason) => entitySeason.seasonNumber) ?? [];
const availableSeasons = entity.media.seasons.filter( const availableSeasons = entity.media.seasons.filter(
(season) => (season) =>
season[entity.is4k ? 'status4k' : 'status'] === MediaStatus.AVAILABLE season[entity.is4k ? 'status4k' : 'status'] === MediaStatus.AVAILABLE &&
requestedSeasons.includes(season.seasonNumber)
); );
const isMediaAvailable = const isMediaAvailable =
availableSeasons.length > 0 && availableSeasons.length > 0 &&
availableSeasons.every((availableSeason) => availableSeasons.length === requestedSeasons.length;
entity.seasons?.some(
(entitySeason) =>
entitySeason.seasonNumber === availableSeason.seasonNumber
)
);
if ( if (
entity.media[entity.is4k ? 'status4k' : 'status'] === entity.media[entity.is4k ? 'status4k' : 'status'] ===

View File

@@ -31,7 +31,11 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
} }
} }
private async updateRelatedMediaRequest(event: Media, is4k: boolean) { private async updateRelatedMediaRequest(
event: Media,
databaseEvent: Media,
is4k: boolean
) {
const requestRepository = getRepository(MediaRequest); const requestRepository = getRepository(MediaRequest);
const seasonRequestRepository = getRepository(SeasonRequest); const seasonRequestRepository = getRepository(SeasonRequest);
@@ -67,17 +71,39 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
(mediaSeason) => (mediaSeason) =>
mediaSeason.seasonNumber === requestSeason.seasonNumber mediaSeason.seasonNumber === requestSeason.seasonNumber
); );
const matchingOldSeason = databaseEvent.seasons.find(
(oldSeason) =>
oldSeason.seasonNumber === requestSeason.seasonNumber
);
if (!matchingSeason) { if (!matchingSeason) {
return false; return false;
} }
return ( const currentSeasonStatus =
matchingSeason[request.is4k ? 'status4k' : 'status'] === matchingSeason[request.is4k ? 'status4k' : 'status'];
MediaStatus.AVAILABLE || const previousSeasonStatus =
matchingSeason[request.is4k ? 'status4k' : 'status'] === matchingOldSeason?.[request.is4k ? 'status4k' : 'status'];
MediaStatus.DELETED
); const hasStatusChanged =
currentSeasonStatus !== previousSeasonStatus;
const shouldUpdate =
(hasStatusChanged ||
requestSeason.status === MediaRequestStatus.COMPLETED) &&
(currentSeasonStatus === MediaStatus.AVAILABLE ||
currentSeasonStatus === MediaStatus.DELETED);
if (shouldUpdate) {
// Handle season requests and mark them completed when
// that specific season becomes available
seasonRequestRepository.update(requestSeason.id, {
status: MediaRequestStatus.COMPLETED,
});
return true;
}
return false;
}); });
shouldComplete = allSeasonsReady; shouldComplete = allSeasonsReady;
@@ -90,38 +116,6 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
}); });
await requestRepository.save(completedRequests); await requestRepository.save(completedRequests);
// Handle season requests and mark them completed when
// that specific season becomes available
if (event.mediaType === 'tv') {
const seasonsToUpdate = relatedRequests.flatMap((request) => {
return request.seasons.filter((requestSeason) => {
const matchingSeason = event.seasons.find(
(mediaSeason) =>
mediaSeason.seasonNumber === requestSeason.seasonNumber
);
if (!matchingSeason) {
return false;
}
return (
matchingSeason[request.is4k ? 'status4k' : 'status'] ===
MediaStatus.AVAILABLE ||
matchingSeason[request.is4k ? 'status4k' : 'status'] ===
MediaStatus.DELETED
);
});
});
await Promise.all(
seasonsToUpdate.map((season) =>
seasonRequestRepository.update(season.id, {
status: MediaRequestStatus.COMPLETED,
})
)
);
}
} }
} }
@@ -173,7 +167,7 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
return ( return (
season[is4k ? 'status4k' : 'status'] !== season[is4k ? 'status4k' : 'status'] !==
previousSeason[is4k ? 'status4k' : 'status'] previousSeason?.[is4k ? 'status4k' : 'status']
); );
}); });
}; };
@@ -184,7 +178,11 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
seasonStatusCheck(false))) && seasonStatusCheck(false))) &&
validStatuses.includes(event.entity.status) validStatuses.includes(event.entity.status)
) { ) {
this.updateRelatedMediaRequest(event.entity as Media, false); this.updateRelatedMediaRequest(
event.entity as Media,
event.databaseEntity as Media,
false
);
} }
if ( if (
@@ -192,7 +190,11 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
(event.entity.mediaType === MediaType.TV && seasonStatusCheck(true))) && (event.entity.mediaType === MediaType.TV && seasonStatusCheck(true))) &&
validStatuses.includes(event.entity.status4k) validStatuses.includes(event.entity.status4k)
) { ) {
this.updateRelatedMediaRequest(event.entity as Media, true); this.updateRelatedMediaRequest(
event.entity as Media,
event.databaseEntity as Media,
true
);
} }
} }