diff --git a/server/entity/MediaRequest.ts b/server/entity/MediaRequest.ts index 295b49614..afc8010e9 100644 --- a/server/entity/MediaRequest.ts +++ b/server/entity/MediaRequest.ts @@ -247,7 +247,9 @@ export class MediaRequest { >; const requestedSeasons = requestBody.seasons === 'all' - ? tmdbMediaShow.seasons.map((season) => season.season_number) + ? tmdbMediaShow.seasons + .filter((season) => season.season_number !== 0) + .map((season) => season.season_number) : (requestBody.seasons as number[]); let existingSeasons: number[] = []; diff --git a/server/subscriber/MediaRequestSubscriber.ts b/server/subscriber/MediaRequestSubscriber.ts index 6b4a7ae85..2b293d97b 100644 --- a/server/subscriber/MediaRequestSubscriber.ts +++ b/server/subscriber/MediaRequestSubscriber.ts @@ -69,11 +69,7 @@ export class MediaRequestSubscriber availableSeasons.length > 0 && availableSeasons.length === requestedSeasons.length; - if ( - entity.media[entity.is4k ? 'status4k' : 'status'] === - MediaStatus.AVAILABLE || - isMediaAvailable - ) { + if (isMediaAvailable) { const tmdb = new TheMovieDb(); try { diff --git a/server/subscriber/MediaSubscriber.ts b/server/subscriber/MediaSubscriber.ts index 93d7d3fea..3cf8229f0 100644 --- a/server/subscriber/MediaSubscriber.ts +++ b/server/subscriber/MediaSubscriber.ts @@ -55,57 +55,59 @@ export class MediaSubscriber implements EntitySubscriberInterface { if (relatedRequests.length > 0) { const completedRequests: MediaRequest[] = []; - relatedRequests.forEach((request) => { + for (const request of relatedRequests) { let shouldComplete = false; if ( - event[request.is4k ? 'status4k' : 'status'] === + (event[request.is4k ? 'status4k' : 'status'] === MediaStatus.AVAILABLE || - event[request.is4k ? 'status4k' : 'status'] === MediaStatus.DELETED + event[request.is4k ? 'status4k' : 'status'] === + MediaStatus.DELETED) && + event.mediaType === MediaType.MOVIE ) { shouldComplete = true; } else if (event.mediaType === 'tv') { - // For TV, check if all requested seasons are available or deleted - const allSeasonsReady = request.seasons.every((requestSeason) => { - const matchingSeason = event.seasons.find( - (mediaSeason) => - mediaSeason.seasonNumber === requestSeason.seasonNumber - ); - const matchingOldSeason = databaseEvent.seasons.find( - (oldSeason) => - oldSeason.seasonNumber === requestSeason.seasonNumber - ); + const allSeasonResults = await Promise.all( + request.seasons.map(async (requestSeason) => { + const matchingSeason = event.seasons.find( + (mediaSeason) => + mediaSeason.seasonNumber === requestSeason.seasonNumber + ); + const matchingOldSeason = databaseEvent.seasons.find( + (oldSeason) => + oldSeason.seasonNumber === requestSeason.seasonNumber + ); + + if (!matchingSeason) { + return false; + } + + const currentSeasonStatus = + matchingSeason[request.is4k ? 'status4k' : 'status']; + const previousSeasonStatus = + matchingOldSeason?.[request.is4k ? 'status4k' : 'status']; + + const hasStatusChanged = + currentSeasonStatus !== previousSeasonStatus; + + const shouldUpdate = + (hasStatusChanged || + requestSeason.status === MediaRequestStatus.COMPLETED) && + (currentSeasonStatus === MediaStatus.AVAILABLE || + currentSeasonStatus === MediaStatus.DELETED); + + if (shouldUpdate) { + requestSeason.status = MediaRequestStatus.COMPLETED; + await seasonRequestRepository.save(requestSeason); + + return true; + } - if (!matchingSeason) { return false; - } - - const currentSeasonStatus = - matchingSeason[request.is4k ? 'status4k' : 'status']; - const previousSeasonStatus = - matchingOldSeason?.[request.is4k ? 'status4k' : 'status']; - - 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; - }); + }) + ); + const allSeasonsReady = allSeasonResults.every((result) => result); shouldComplete = allSeasonsReady; } @@ -113,7 +115,7 @@ export class MediaSubscriber implements EntitySubscriberInterface { request.status = MediaRequestStatus.COMPLETED; completedRequests.push(request); } - }); + } await requestRepository.save(completedRequests); } diff --git a/src/components/ManageSlideOver/index.tsx b/src/components/ManageSlideOver/index.tsx index 01af2e2f2..4487cf813 100644 --- a/src/components/ManageSlideOver/index.tsx +++ b/src/components/ManageSlideOver/index.tsx @@ -96,7 +96,9 @@ const ManageSlideOver = ({ if (data.mediaInfo) { await axios.post(`/api/v1/media/${data.mediaInfo?.id}/available`, { is4k, - ...(mediaType === 'tv' && { seasons: data.seasons }), + ...(mediaType === 'tv' && { + seasons: data.seasons.filter((season) => season.seasonNumber !== 0), + }), }); revalidate(); } diff --git a/src/components/RequestModal/TvRequestModal.tsx b/src/components/RequestModal/TvRequestModal.tsx index d5c7ec824..1e3a86701 100644 --- a/src/components/RequestModal/TvRequestModal.tsx +++ b/src/components/RequestModal/TvRequestModal.tsx @@ -309,12 +309,16 @@ const TvRequestModal = ({ return; } + const standardUnrequestedSeasons = unrequestedSeasons.filter( + (seasonNumber) => seasonNumber !== 0 + ); + if ( data && selectedSeasons.length >= 0 && - selectedSeasons.length < unrequestedSeasons.length + selectedSeasons.length < standardUnrequestedSeasons.length ) { - setSelectedSeasons(unrequestedSeasons); + setSelectedSeasons(standardUnrequestedSeasons); } else { setSelectedSeasons([]); } @@ -325,9 +329,9 @@ const TvRequestModal = ({ return false; } return ( - selectedSeasons.length === + selectedSeasons.filter((season) => season !== 0).length === getAllSeasons().filter( - (season) => !getAllRequestedSeasons().includes(season) + (season) => !getAllRequestedSeasons().includes(season) && season !== 0 ).length ); };