mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
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:
@@ -247,7 +247,9 @@ export class MediaRequest {
|
|||||||
>;
|
>;
|
||||||
const requestedSeasons =
|
const requestedSeasons =
|
||||||
requestBody.seasons === 'all'
|
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[]);
|
: (requestBody.seasons as number[]);
|
||||||
let existingSeasons: number[] = [];
|
let existingSeasons: number[] = [];
|
||||||
|
|
||||||
|
@@ -69,11 +69,7 @@ export class MediaRequestSubscriber
|
|||||||
availableSeasons.length > 0 &&
|
availableSeasons.length > 0 &&
|
||||||
availableSeasons.length === requestedSeasons.length;
|
availableSeasons.length === requestedSeasons.length;
|
||||||
|
|
||||||
if (
|
if (isMediaAvailable) {
|
||||||
entity.media[entity.is4k ? 'status4k' : 'status'] ===
|
|
||||||
MediaStatus.AVAILABLE ||
|
|
||||||
isMediaAvailable
|
|
||||||
) {
|
|
||||||
const tmdb = new TheMovieDb();
|
const tmdb = new TheMovieDb();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@@ -55,57 +55,59 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
|
|||||||
if (relatedRequests.length > 0) {
|
if (relatedRequests.length > 0) {
|
||||||
const completedRequests: MediaRequest[] = [];
|
const completedRequests: MediaRequest[] = [];
|
||||||
|
|
||||||
relatedRequests.forEach((request) => {
|
for (const request of relatedRequests) {
|
||||||
let shouldComplete = false;
|
let shouldComplete = false;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
event[request.is4k ? 'status4k' : 'status'] ===
|
(event[request.is4k ? 'status4k' : 'status'] ===
|
||||||
MediaStatus.AVAILABLE ||
|
MediaStatus.AVAILABLE ||
|
||||||
event[request.is4k ? 'status4k' : 'status'] === MediaStatus.DELETED
|
event[request.is4k ? 'status4k' : 'status'] ===
|
||||||
|
MediaStatus.DELETED) &&
|
||||||
|
event.mediaType === MediaType.MOVIE
|
||||||
) {
|
) {
|
||||||
shouldComplete = true;
|
shouldComplete = true;
|
||||||
} else if (event.mediaType === 'tv') {
|
} else if (event.mediaType === 'tv') {
|
||||||
// For TV, check if all requested seasons are available or deleted
|
const allSeasonResults = await Promise.all(
|
||||||
const allSeasonsReady = request.seasons.every((requestSeason) => {
|
request.seasons.map(async (requestSeason) => {
|
||||||
const matchingSeason = event.seasons.find(
|
const matchingSeason = event.seasons.find(
|
||||||
(mediaSeason) =>
|
(mediaSeason) =>
|
||||||
mediaSeason.seasonNumber === requestSeason.seasonNumber
|
mediaSeason.seasonNumber === requestSeason.seasonNumber
|
||||||
);
|
);
|
||||||
const matchingOldSeason = databaseEvent.seasons.find(
|
const matchingOldSeason = databaseEvent.seasons.find(
|
||||||
(oldSeason) =>
|
(oldSeason) =>
|
||||||
oldSeason.seasonNumber === requestSeason.seasonNumber
|
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;
|
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;
|
shouldComplete = allSeasonsReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +115,7 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
|
|||||||
request.status = MediaRequestStatus.COMPLETED;
|
request.status = MediaRequestStatus.COMPLETED;
|
||||||
completedRequests.push(request);
|
completedRequests.push(request);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
await requestRepository.save(completedRequests);
|
await requestRepository.save(completedRequests);
|
||||||
}
|
}
|
||||||
|
@@ -96,7 +96,9 @@ const ManageSlideOver = ({
|
|||||||
if (data.mediaInfo) {
|
if (data.mediaInfo) {
|
||||||
await axios.post(`/api/v1/media/${data.mediaInfo?.id}/available`, {
|
await axios.post(`/api/v1/media/${data.mediaInfo?.id}/available`, {
|
||||||
is4k,
|
is4k,
|
||||||
...(mediaType === 'tv' && { seasons: data.seasons }),
|
...(mediaType === 'tv' && {
|
||||||
|
seasons: data.seasons.filter((season) => season.seasonNumber !== 0),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
revalidate();
|
revalidate();
|
||||||
}
|
}
|
||||||
|
@@ -309,12 +309,16 @@ const TvRequestModal = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const standardUnrequestedSeasons = unrequestedSeasons.filter(
|
||||||
|
(seasonNumber) => seasonNumber !== 0
|
||||||
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
data &&
|
data &&
|
||||||
selectedSeasons.length >= 0 &&
|
selectedSeasons.length >= 0 &&
|
||||||
selectedSeasons.length < unrequestedSeasons.length
|
selectedSeasons.length < standardUnrequestedSeasons.length
|
||||||
) {
|
) {
|
||||||
setSelectedSeasons(unrequestedSeasons);
|
setSelectedSeasons(standardUnrequestedSeasons);
|
||||||
} else {
|
} else {
|
||||||
setSelectedSeasons([]);
|
setSelectedSeasons([]);
|
||||||
}
|
}
|
||||||
@@ -325,9 +329,9 @@ const TvRequestModal = ({
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
selectedSeasons.length ===
|
selectedSeasons.filter((season) => season !== 0).length ===
|
||||||
getAllSeasons().filter(
|
getAllSeasons().filter(
|
||||||
(season) => !getAllRequestedSeasons().includes(season)
|
(season) => !getAllRequestedSeasons().includes(season) && season !== 0
|
||||||
).length
|
).length
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user