fix: filter specials from modal all seasons and watchlist (#4108)

* fix: filter specials from modal all seasons and watchlist

* fix: skip specials when marking available

* fix: edge case where specials were marked as completed
This commit is contained in:
Brandon Cohen
2025-04-19 19:30:58 -05:00
committed by GitHub
parent 208d31180c
commit 7f868f38e6
5 changed files with 59 additions and 53 deletions

View File

@@ -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[] = [];

View File

@@ -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 {

View File

@@ -55,57 +55,59 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
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<Media> {
request.status = MediaRequestStatus.COMPLETED;
completedRequests.push(request);
}
});
}
await requestRepository.save(completedRequests);
}

View File

@@ -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();
}

View File

@@ -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
);
};