fix: availability sync file detection (#3371)

* fix: added extra check for unmonitored movies in radarr

* feat: created new radarr/sonarr routes  to grab existing series data

* refactor: updated job routes to check by external service id

* fix: season check will now also look at episode file count
This commit is contained in:
Brandon Cohen
2023-05-10 20:36:12 -04:00
committed by GitHub
parent 77a33cb74d
commit 7522aa3174
2 changed files with 335 additions and 244 deletions

View File

@@ -76,6 +76,15 @@ export interface SonarrSeries {
ignoreEpisodesWithoutFiles?: boolean; ignoreEpisodesWithoutFiles?: boolean;
searchForMissingEpisodes?: boolean; searchForMissingEpisodes?: boolean;
}; };
statistics: {
seasonCount: number;
episodeFileCount: number;
episodeCount: number;
totalEpisodeCount: number;
sizeOnDisk: number;
releaseGroups: string[];
percentOfEpisodes: number;
};
} }
export interface AddSeriesOptions { export interface AddSeriesOptions {
@@ -116,6 +125,16 @@ class SonarrAPI extends ServarrBase<{
} }
} }
public async getSeriesById(id: number): Promise<SonarrSeries> {
try {
const response = await this.axios.get<SonarrSeries>(`/series/${id}`);
return response.data;
} catch (e) {
throw new Error(`[Sonarr] Failed to retrieve series by ID: ${e.message}`);
}
}
public async getSeriesByTitle(title: string): Promise<SonarrSeries[]> { public async getSeriesByTitle(title: string): Promise<SonarrSeries[]> {
try { try {
const response = await this.axios.get<SonarrSeries[]>('/series/lookup', { const response = await this.axios.get<SonarrSeries[]>('/series/lookup', {

View File

@@ -1,7 +1,8 @@
import type { PlexMetadata } from '@server/api/plexapi'; import type { PlexMetadata } from '@server/api/plexapi';
import PlexAPI from '@server/api/plexapi'; import PlexAPI from '@server/api/plexapi';
import type { RadarrMovie } from '@server/api/servarr/radarr';
import RadarrAPI from '@server/api/servarr/radarr'; import RadarrAPI from '@server/api/servarr/radarr';
import type { SonarrSeason } from '@server/api/servarr/sonarr'; import type { SonarrSeason, SonarrSeries } from '@server/api/servarr/sonarr';
import SonarrAPI from '@server/api/servarr/sonarr'; import SonarrAPI from '@server/api/servarr/sonarr';
import { MediaStatus } from '@server/constants/media'; import { MediaStatus } from '@server/constants/media';
import { getRepository } from '@server/datasource'; import { getRepository } from '@server/datasource';
@@ -47,158 +48,150 @@ class AvailabilitySync {
try { try {
for await (const media of this.loadAvailableMediaPaginated(pageSize)) { for await (const media of this.loadAvailableMediaPaginated(pageSize)) {
try { if (!this.running) {
if (!this.running) { throw new Error('Job aborted');
throw new Error('Job aborted'); }
}
const mediaExists = await this.mediaExists(media); const mediaExists = await this.mediaExists(media);
//We can not delete media so if both versions do not exist, we will change both columns to unknown or null // We can not delete media so if both versions do not exist, we will change both columns to unknown or null
if (!mediaExists) { if (!mediaExists) {
if ( if (
media.status !== MediaStatus.UNKNOWN || media.status !== MediaStatus.UNKNOWN ||
media.status4k !== MediaStatus.UNKNOWN media.status4k !== MediaStatus.UNKNOWN
) { ) {
const request = await requestRepository.find({ const request = await requestRepository.find({
relations: { relations: {
media: true, media: true,
}, },
where: { media: { id: media.id } }, where: { media: { id: media.id } },
});
logger.info(
`${
media.mediaType === 'tv' ? media.tvdbId : media.tmdbId
} does not exist in any of your media instances. We will change its status to unknown.`,
{ label: 'AvailabilitySync' }
);
await mediaRepository.update(media.id, {
status: MediaStatus.UNKNOWN,
status4k: MediaStatus.UNKNOWN,
serviceId: null,
serviceId4k: null,
externalServiceId: null,
externalServiceId4k: null,
externalServiceSlug: null,
externalServiceSlug4k: null,
ratingKey: null,
ratingKey4k: null,
});
await requestRepository.remove(request);
}
}
if (media.mediaType === 'tv') {
// ok, the show itself exists, but do all it's seasons?
const seasons = await seasonRepository.find({
where: [
{ status: MediaStatus.AVAILABLE, media: { id: media.id } },
{
status: MediaStatus.PARTIALLY_AVAILABLE,
media: { id: media.id },
},
{ status4k: MediaStatus.AVAILABLE, media: { id: media.id } },
{
status4k: MediaStatus.PARTIALLY_AVAILABLE,
media: { id: media.id },
},
],
}); });
let didDeleteSeasons = false; logger.info(
for (const season of seasons) { `Media ID ${media.id} does not exist in any of your media instances. Status will be changed to unknown.`,
if ( { label: 'AvailabilitySync' }
!mediaExists && );
(season.status !== MediaStatus.UNKNOWN ||
season.status4k !== MediaStatus.UNKNOWN) await mediaRepository.update(media.id, {
) { status: MediaStatus.UNKNOWN,
await seasonRepository.update( status4k: MediaStatus.UNKNOWN,
{ id: season.id }, serviceId: null,
serviceId4k: null,
externalServiceId: null,
externalServiceId4k: null,
externalServiceSlug: null,
externalServiceSlug4k: null,
ratingKey: null,
ratingKey4k: null,
});
await requestRepository.remove(request);
}
}
if (media.mediaType === 'tv') {
// ok, the show itself exists, but do all it's seasons?
const seasons = await seasonRepository.find({
where: [
{ status: MediaStatus.AVAILABLE, media: { id: media.id } },
{
status: MediaStatus.PARTIALLY_AVAILABLE,
media: { id: media.id },
},
{ status4k: MediaStatus.AVAILABLE, media: { id: media.id } },
{
status4k: MediaStatus.PARTIALLY_AVAILABLE,
media: { id: media.id },
},
],
});
let didDeleteSeasons = false;
for (const season of seasons) {
if (
!mediaExists &&
(season.status !== MediaStatus.UNKNOWN ||
season.status4k !== MediaStatus.UNKNOWN)
) {
await seasonRepository.update(
{ id: season.id },
{
status: MediaStatus.UNKNOWN,
status4k: MediaStatus.UNKNOWN,
}
);
} else {
const seasonExists = await this.seasonExists(media, season);
if (!seasonExists) {
logger.info(
`Removing season ${season.seasonNumber}, media ID ${media.id} because it does not exist in any of your media instances.`,
{ label: 'AvailabilitySync' }
);
if (
season.status !== MediaStatus.UNKNOWN ||
season.status4k !== MediaStatus.UNKNOWN
) {
await seasonRepository.update(
{ id: season.id },
{
status: MediaStatus.UNKNOWN,
status4k: MediaStatus.UNKNOWN,
}
);
}
const seasonToBeDeleted = await seasonRequestRepository.findOne(
{ {
status: MediaStatus.UNKNOWN, relations: {
status4k: MediaStatus.UNKNOWN, request: {
media: true,
},
},
where: {
request: {
media: {
id: media.id,
},
},
seasonNumber: season.seasonNumber,
},
} }
); );
} else {
const seasonExists = await this.seasonExists(media, season);
if (!seasonExists) { if (seasonToBeDeleted) {
logger.info( await seasonRequestRepository.remove(seasonToBeDeleted);
`Removing season ${season.seasonNumber}, media id: ${media.tvdbId} because it does not exist in any of your media instances.`,
{ label: 'AvailabilitySync' }
);
if (
season.status !== MediaStatus.UNKNOWN ||
season.status4k !== MediaStatus.UNKNOWN
) {
await seasonRepository.update(
{ id: season.id },
{
status: MediaStatus.UNKNOWN,
status4k: MediaStatus.UNKNOWN,
}
);
}
const seasonToBeDeleted =
await seasonRequestRepository.findOne({
relations: {
request: {
media: true,
},
},
where: {
request: {
media: {
id: media.id,
},
},
seasonNumber: season.seasonNumber,
},
});
if (seasonToBeDeleted) {
await seasonRequestRepository.remove(seasonToBeDeleted);
}
didDeleteSeasons = true;
} }
didDeleteSeasons = true;
} }
}
if (didDeleteSeasons) { if (didDeleteSeasons) {
if ( if (
media.status === MediaStatus.AVAILABLE || media.status === MediaStatus.AVAILABLE ||
media.status4k === MediaStatus.AVAILABLE media.status4k === MediaStatus.AVAILABLE
) { ) {
logger.info( logger.info(
`Marking media id: ${media.tvdbId} as PARTIALLY_AVAILABLE because we deleted some of its seasons.`, `Marking media ID ${media.id} as PARTIALLY_AVAILABLE because season removal has occurred.`,
{ label: 'AvailabilitySync' } { label: 'AvailabilitySync' }
); );
if (media.status === MediaStatus.AVAILABLE) { if (media.status === MediaStatus.AVAILABLE) {
await mediaRepository.update(media.id, { await mediaRepository.update(media.id, {
status: MediaStatus.PARTIALLY_AVAILABLE, status: MediaStatus.PARTIALLY_AVAILABLE,
}); });
} }
if (media.status4k === MediaStatus.AVAILABLE) { if (media.status4k === MediaStatus.AVAILABLE) {
await mediaRepository.update(media.id, { await mediaRepository.update(media.id, {
status4k: MediaStatus.PARTIALLY_AVAILABLE, status4k: MediaStatus.PARTIALLY_AVAILABLE,
}); });
}
} }
} }
} }
} }
} catch (ex) {
logger.error('Failure with media.', {
errorMessage: ex.message,
label: 'AvailabilitySync',
});
} }
} }
} catch (ex) { } catch (ex) {
@@ -254,9 +247,9 @@ class AvailabilitySync {
}); });
logger.info( logger.info(
`${media.tmdbId} does not exist in your ${is4k ? '4k' : 'non-4k'} ${ `Media ID ${media.id} does not exist in your ${is4k ? '4k' : 'non-4k'} ${
isTVType ? 'sonarr' : 'radarr' isTVType ? 'Sonarr' : 'Radarr'
} and plex instance. We will change its status to unknown.`, } and Plex instance. Status will be changed to unknown.`,
{ label: 'AvailabilitySync' } { label: 'AvailabilitySync' }
); );
@@ -306,46 +299,70 @@ class AvailabilitySync {
apiKey: server.apiKey, apiKey: server.apiKey,
url: RadarrAPI.buildUrl(server, '/api/v3'), url: RadarrAPI.buildUrl(server, '/api/v3'),
}); });
const meta = await api.getMovieByTmdbId(media.tmdbId); try {
// Check if both exist or if a single non-4k or 4k exists
// If both do not exist we will return false
//check if both exist or if a single non-4k or 4k exists let meta: RadarrMovie | undefined;
//if both do not exist we will return false
if (!server.is4k && !meta.id) {
existsInRadarr = false;
}
if (server.is4k && !meta.id) { if (!server.is4k && media.externalServiceId) {
existsInRadarr4k = false; meta = await api.getMovie({ id: media.externalServiceId });
}
if (server.is4k && media.externalServiceId4k) {
meta = await api.getMovie({ id: media.externalServiceId4k });
}
if (!server.is4k && (!meta || !meta.hasFile)) {
existsInRadarr = false;
}
if (server.is4k && (!meta || !meta.hasFile)) {
existsInRadarr4k = false;
}
} catch (ex) {
logger.debug(
`Failure retrieving media ID ${media.id} from your ${
!server.is4k ? 'non-4K' : '4K'
} Radarr.`,
{
errorMessage: ex.message,
label: 'AvailabilitySync',
}
);
if (!server.is4k) {
existsInRadarr = false;
}
if (server.is4k) {
existsInRadarr4k = false;
}
} }
} }
if (existsInRadarr && existsInRadarr4k) { // If only a single non-4k or 4k exists, then change entity columns accordingly
return true; // Related media request will then be deleted
} if (
!existsInRadarr &&
if (!existsInRadarr && existsInPlex) { (existsInRadarr4k || existsInPlex4k) &&
return true; !existsInPlex
} ) {
if (!existsInRadarr4k && existsInPlex4k) {
return true;
}
//if only a single non-4k or 4k exists, then change entity columns accordingly
//related media request will then be deleted
if (!existsInRadarr && existsInRadarr4k && !existsInPlex) {
if (media.status !== MediaStatus.UNKNOWN) { if (media.status !== MediaStatus.UNKNOWN) {
this.mediaUpdater(media, false); this.mediaUpdater(media, false);
} }
} }
if (existsInRadarr && !existsInRadarr4k && !existsInPlex4k) { if (
(existsInRadarr || existsInPlex) &&
!existsInRadarr4k &&
!existsInPlex4k
) {
if (media.status4k !== MediaStatus.UNKNOWN) { if (media.status4k !== MediaStatus.UNKNOWN) {
this.mediaUpdater(media, true); this.mediaUpdater(media, true);
} }
} }
if (existsInRadarr || existsInRadarr4k) { if (existsInRadarr || existsInRadarr4k || existsInPlex || existsInPlex4k) {
return true; return true;
} }
@@ -357,10 +374,6 @@ class AvailabilitySync {
existsInPlex: boolean, existsInPlex: boolean,
existsInPlex4k: boolean existsInPlex4k: boolean
): Promise<boolean> { ): Promise<boolean> {
if (!media.tvdbId) {
return false;
}
let existsInSonarr = true; let existsInSonarr = true;
let existsInSonarr4k = true; let existsInSonarr4k = true;
@@ -369,49 +382,75 @@ class AvailabilitySync {
apiKey: server.apiKey, apiKey: server.apiKey,
url: SonarrAPI.buildUrl(server, '/api/v3'), url: SonarrAPI.buildUrl(server, '/api/v3'),
}); });
try {
// Check if both exist or if a single non-4k or 4k exists
// If both do not exist we will return false
const meta = await api.getSeriesByTvdbId(media.tvdbId); let meta: SonarrSeries | undefined;
this.sonarrSeasonsCache[`${server.id}-${media.tvdbId}`] = meta.seasons; if (!server.is4k && media.externalServiceId) {
meta = await api.getSeriesById(media.externalServiceId);
this.sonarrSeasonsCache[`${server.id}-${media.externalServiceId}`] =
meta.seasons;
}
//check if both exist or if a single non-4k or 4k exists if (server.is4k && media.externalServiceId4k) {
//if both do not exist we will return false meta = await api.getSeriesById(media.externalServiceId4k);
if (!server.is4k && !meta.id) { this.sonarrSeasonsCache[`${server.id}-${media.externalServiceId4k}`] =
existsInSonarr = false; meta.seasons;
} }
if (server.is4k && !meta.id) { if (!server.is4k && (!meta || meta.statistics.episodeFileCount === 0)) {
existsInSonarr4k = false; existsInSonarr = false;
}
if (server.is4k && (!meta || meta.statistics.episodeFileCount === 0)) {
existsInSonarr4k = false;
}
} catch (ex) {
logger.debug(
`Failure retrieving media ID ${media.id} from your ${
!server.is4k ? 'non-4K' : '4K'
} Sonarr.`,
{
errorMessage: ex.message,
label: 'AvailabilitySync',
}
);
if (!server.is4k) {
existsInSonarr = false;
}
if (server.is4k) {
existsInSonarr4k = false;
}
} }
} }
if (existsInSonarr && existsInSonarr4k) { // If only a single non-4k or 4k exists, then change entity columns accordingly
return true; // Related media request will then be deleted
} if (
!existsInSonarr &&
if (!existsInSonarr && existsInPlex) { (existsInSonarr4k || existsInPlex4k) &&
return true; !existsInPlex
} ) {
if (!existsInSonarr4k && existsInPlex4k) {
return true;
}
//if only a single non-4k or 4k exists, then change entity columns accordingly
//related media request will then be deleted
if (!existsInSonarr && existsInSonarr4k && !existsInPlex) {
if (media.status !== MediaStatus.UNKNOWN) { if (media.status !== MediaStatus.UNKNOWN) {
this.mediaUpdater(media, false); this.mediaUpdater(media, false);
} }
} }
if (existsInSonarr && !existsInSonarr4k && !existsInPlex4k) { if (
(existsInSonarr || existsInPlex) &&
!existsInSonarr4k &&
!existsInPlex4k
) {
if (media.status4k !== MediaStatus.UNKNOWN) { if (media.status4k !== MediaStatus.UNKNOWN) {
this.mediaUpdater(media, true); this.mediaUpdater(media, true);
} }
} }
if (existsInSonarr || existsInSonarr4k) { if (existsInSonarr || existsInSonarr4k || existsInPlex || existsInPlex4k) {
return true; return true;
} }
@@ -424,10 +463,6 @@ class AvailabilitySync {
seasonExistsInPlex: boolean, seasonExistsInPlex: boolean,
seasonExistsInPlex4k: boolean seasonExistsInPlex4k: boolean
): Promise<boolean> { ): Promise<boolean> {
if (!media.tvdbId) {
return false;
}
let seasonExistsInSonarr = true; let seasonExistsInSonarr = true;
let seasonExistsInSonarr4k = true; let seasonExistsInSonarr4k = true;
@@ -441,35 +476,67 @@ class AvailabilitySync {
url: SonarrAPI.buildUrl(server, '/api/v3'), url: SonarrAPI.buildUrl(server, '/api/v3'),
}); });
const seasons = try {
this.sonarrSeasonsCache[`${server.id}-${media.tvdbId}`] ?? // Here we can use the cache we built when we fetched the series with mediaExistsInSonarr
(await api.getSeriesByTvdbId(media.tvdbId)).seasons; // If the cache does not have data, we will fetch with the api route
this.sonarrSeasonsCache[`${server.id}-${media.tvdbId}`] = seasons;
const hasMonitoredSeason = seasons.find( let seasons: SonarrSeason[] =
({ monitored, seasonNumber }) => this.sonarrSeasonsCache[
monitored && season.seasonNumber === seasonNumber `${server.id}-${
); !server.is4k ? media.externalServiceId : media.externalServiceId4k
}`
];
if (!server.is4k && !hasMonitoredSeason) { if (!server.is4k && media.externalServiceId) {
seasonExistsInSonarr = false; seasons =
this.sonarrSeasonsCache[
`${server.id}-${media.externalServiceId}`
] ?? (await api.getSeriesById(media.externalServiceId)).seasons;
this.sonarrSeasonsCache[`${server.id}-${media.externalServiceId}`] =
seasons;
}
if (server.is4k && media.externalServiceId4k) {
seasons =
this.sonarrSeasonsCache[
`${server.id}-${media.externalServiceId4k}`
] ?? (await api.getSeriesById(media.externalServiceId4k)).seasons;
this.sonarrSeasonsCache[`${server.id}-${media.externalServiceId4k}`] =
seasons;
}
const seasonIsUnavailable = seasons?.find(
({ seasonNumber, statistics }) =>
season.seasonNumber === seasonNumber &&
statistics?.episodeFileCount === 0
);
if (!server.is4k && seasonIsUnavailable) {
seasonExistsInSonarr = false;
}
if (server.is4k && seasonIsUnavailable) {
seasonExistsInSonarr4k = false;
}
} catch (ex) {
logger.debug(
`Failure retrieving media ID ${media.id} from your ${
!server.is4k ? 'non-4K' : '4K'
} Sonarr.`,
{
errorMessage: ex.message,
label: 'AvailabilitySync',
}
);
if (!server.is4k) {
seasonExistsInSonarr = false;
}
if (server.is4k) {
seasonExistsInSonarr4k = false;
}
} }
if (server.is4k && !hasMonitoredSeason) {
seasonExistsInSonarr4k = false;
}
}
if (seasonExistsInSonarr && seasonExistsInSonarr4k) {
return true;
}
if (!seasonExistsInSonarr && seasonExistsInPlex) {
return true;
}
if (!seasonExistsInSonarr4k && seasonExistsInPlex4k) {
return true;
} }
const seasonToBeDeleted = await seasonRequestRepository.findOne({ const seasonToBeDeleted = await seasonRequestRepository.findOne({
@@ -489,16 +556,16 @@ class AvailabilitySync {
}, },
}); });
//if season does not exist, we will change status to unknown and delete related season request // If season does not exist, we will change status to unknown and delete related season request
//if parent media request is empty(all related seasons have been removed), parent is automatically deleted // If parent media request is empty(all related seasons have been removed), parent is automatically deleted
if ( if (
!seasonExistsInSonarr && !seasonExistsInSonarr &&
seasonExistsInSonarr4k && (seasonExistsInSonarr4k || seasonExistsInPlex4k) &&
!seasonExistsInPlex !seasonExistsInPlex
) { ) {
if (season.status !== MediaStatus.UNKNOWN) { if (season.status !== MediaStatus.UNKNOWN) {
logger.info( logger.info(
`${media.tvdbId}, season: ${season.seasonNumber} does not exist in your non-4k sonarr and plex instance. We will change its status to unknown.`, `Season ${season.seasonNumber}, media ID ${media.id} does not exist in your non-4k Sonarr and Plex instance. Status will be changed to unknown.`,
{ label: 'AvailabilitySync' } { label: 'AvailabilitySync' }
); );
await seasonRepository.update(season.id, { await seasonRepository.update(season.id, {
@@ -511,7 +578,7 @@ class AvailabilitySync {
if (media.status === MediaStatus.AVAILABLE) { if (media.status === MediaStatus.AVAILABLE) {
logger.info( logger.info(
`Marking media id: ${media.tvdbId} as PARTIALLY_AVAILABLE because we deleted one of its seasons.`, `Marking media ID ${media.id} as PARTIALLY_AVAILABLE because season removal has occurred.`,
{ label: 'AvailabilitySync' } { label: 'AvailabilitySync' }
); );
await mediaRepository.update(media.id, { await mediaRepository.update(media.id, {
@@ -522,13 +589,13 @@ class AvailabilitySync {
} }
if ( if (
seasonExistsInSonarr && (seasonExistsInSonarr || seasonExistsInPlex) &&
!seasonExistsInSonarr4k && !seasonExistsInSonarr4k &&
!seasonExistsInPlex4k !seasonExistsInPlex4k
) { ) {
if (season.status4k !== MediaStatus.UNKNOWN) { if (season.status4k !== MediaStatus.UNKNOWN) {
logger.info( logger.info(
`${media.tvdbId}, season: ${season.seasonNumber} does not exist in your 4k sonarr and plex instance. We will change its status to unknown.`, `Season ${season.seasonNumber}, media ID ${media.id} does not exist in your 4k Sonarr and Plex instance. Status will be changed to unknown.`,
{ label: 'AvailabilitySync' } { label: 'AvailabilitySync' }
); );
await seasonRepository.update(season.id, { await seasonRepository.update(season.id, {
@@ -541,7 +608,7 @@ class AvailabilitySync {
if (media.status4k === MediaStatus.AVAILABLE) { if (media.status4k === MediaStatus.AVAILABLE) {
logger.info( logger.info(
`Marking media id: ${media.tvdbId} as PARTIALLY_AVAILABLE because we deleted one of its seasons.`, `Marking media ID ${media.id} as PARTIALLY_AVAILABLE because season removal has occurred.`,
{ label: 'AvailabilitySync' } { label: 'AvailabilitySync' }
); );
await mediaRepository.update(media.id, { await mediaRepository.update(media.id, {
@@ -551,7 +618,12 @@ class AvailabilitySync {
} }
} }
if (seasonExistsInSonarr || seasonExistsInSonarr4k) { if (
seasonExistsInSonarr ||
seasonExistsInSonarr4k ||
seasonExistsInPlex ||
seasonExistsInPlex4k
) {
return true; return true;
} }
@@ -565,7 +637,7 @@ class AvailabilitySync {
let existsInPlex = false; let existsInPlex = false;
let existsInPlex4k = false; let existsInPlex4k = false;
//check each plex instance to see if media exists // Check each plex instance to see if media exists
try { try {
if (ratingKey) { if (ratingKey) {
const meta = await this.plexClient?.getMetadata(ratingKey); const meta = await this.plexClient?.getMetadata(ratingKey);
@@ -573,6 +645,7 @@ class AvailabilitySync {
existsInPlex = true; existsInPlex = true;
} }
} }
if (ratingKey4k) { if (ratingKey4k) {
const meta4k = await this.plexClient?.getMetadata(ratingKey4k); const meta4k = await this.plexClient?.getMetadata(ratingKey4k);
if (meta4k) { if (meta4k) {
@@ -580,18 +653,17 @@ class AvailabilitySync {
} }
} }
} catch (ex) { } catch (ex) {
// TODO: oof, not the nicest way of handling this, but plex-api does not leave us with any other options...
if (!ex.message.includes('response code: 404')) { if (!ex.message.includes('response code: 404')) {
throw ex; throw ex;
} }
} }
//base case for if both media versions exist in plex // Base case if both media versions exist in plex
if (existsInPlex && existsInPlex4k) { if (existsInPlex && existsInPlex4k) {
return true; return true;
} }
//we then check radarr or sonarr has that specific media. If not, then we will move to delete // We then check radarr or sonarr has that specific media. If not, then we will move to delete
//if a non-4k or 4k version exists in at least one of the instances, we will only update that specific version // If a non-4k or 4k version exists in at least one of the instances, we will only update that specific version
if (media.mediaType === 'movie') { if (media.mediaType === 'movie') {
const existsInRadarr = await this.mediaExistsInRadarr( const existsInRadarr = await this.mediaExistsInRadarr(
media, media,
@@ -599,10 +671,10 @@ class AvailabilitySync {
existsInPlex4k existsInPlex4k
); );
//if true, media exists in at least one radarr or plex instance. // If true, media exists in at least one radarr or plex instance.
if (existsInRadarr) { if (existsInRadarr) {
logger.warn( logger.warn(
`${media.tmdbId} exists in at least one radarr or plex instance. Media will be updated if set to available.`, `${media.id} exists in at least one Radarr or Plex instance. Media will be updated if set to available.`,
{ {
label: 'AvailabilitySync', label: 'AvailabilitySync',
} }
@@ -619,10 +691,10 @@ class AvailabilitySync {
existsInPlex4k existsInPlex4k
); );
//if true, media exists in at least one sonarr or plex instance. // If true, media exists in at least one sonarr or plex instance.
if (existsInSonarr) { if (existsInSonarr) {
logger.warn( logger.warn(
`${media.tvdbId} exists in at least one sonarr or plex instance. Media will be updated if set to available.`, `${media.id} exists in at least one Sonarr or Plex instance. Media will be updated if set to available.`,
{ {
label: 'AvailabilitySync', label: 'AvailabilitySync',
} }
@@ -672,7 +744,7 @@ class AvailabilitySync {
} }
} }
//base case for if both season versions exist in plex // Base case if both season versions exist in plex
if (seasonExistsInPlex && seasonExistsInPlex4k) { if (seasonExistsInPlex && seasonExistsInPlex4k) {
return true; return true;
} }
@@ -686,7 +758,7 @@ class AvailabilitySync {
if (existsInSonarr) { if (existsInSonarr) {
logger.warn( logger.warn(
`${media.tvdbId}, season: ${season.seasonNumber} exists in at least one sonarr or plex instance. Media will be updated if set to available.`, `Season ${season.seasonNumber}, media ID ${media.id} exists in at least one Sonarr or Plex instance. Media will be updated if set to available.`,
{ {
label: 'AvailabilitySync', label: 'AvailabilitySync',
} }