Fix Sonarr season-pack imports after container updates #9
1 changed files with 56 additions and 7 deletions
|
|
@ -2,7 +2,7 @@
|
|||
* @name Sonarr - Trigger Manual Import
|
||||
* @description Safely trigger Sonarr ManualImport for exactly one processed episode file.
|
||||
* @author FileFlows + Sascha
|
||||
* @revision 11
|
||||
* @revision 12
|
||||
* @output Import erfolgreich
|
||||
* @output Fehler
|
||||
* @param {string} URL Sonarr root URL and port
|
||||
|
|
@ -57,8 +57,8 @@ function Script(URL, ApiKey, ImportPath, UseUnmappedPath, MoveMode, TimeOut) {
|
|||
if (!(seriesId && episodeIds)) {
|
||||
let trackedEpisode = null;
|
||||
for (const pattern of searchPatterns) {
|
||||
trackedEpisode = findEpisodeFromQueue(pattern, sonarr)
|
||||
?? findEpisodeFromGrabHistory(pattern, sonarr);
|
||||
trackedEpisode = findEpisodeFromQueue(pattern, sonarr, filePattern)
|
||||
?? findEpisodeFromGrabHistory(pattern, sonarr, filePattern);
|
||||
if (trackedEpisode) break;
|
||||
}
|
||||
if (!trackedEpisode) {
|
||||
|
|
@ -226,7 +226,7 @@ function sendManualImportCommand(sonarr, cmdBody) {
|
|||
|
||||
/*────────────────────────────── helpers ──────────────────────────────────*/
|
||||
|
||||
function findEpisodeFromQueue(searchPattern, sonarr) {
|
||||
function findEpisodeFromQueue(searchPattern, sonarr, episodePattern) {
|
||||
if (!searchPattern) return null;
|
||||
try {
|
||||
const query = buildQueryParams({ page: 1, pageSize: 200, includeUnknownSeriesItems: true });
|
||||
|
|
@ -240,7 +240,11 @@ function findEpisodeFromQueue(searchPattern, sonarr) {
|
|||
Logger.ILog(`Matched Sonarr queue seriesId ${matches[0].seriesId}, episodeId ${matches[0].episodeId}.`);
|
||||
return { id: matches[0].seriesId, episodeIds: [matches[0].episodeId] };
|
||||
}
|
||||
if (matches.length > 1) Logger.WLog(`Ambiguous Sonarr queue match (${matches.length} records).`);
|
||||
if (matches.length > 1) {
|
||||
const resolved = resolvePackEpisode(matches, episodePattern, sonarr);
|
||||
if (resolved) return resolved;
|
||||
Logger.WLog(`Ambiguous Sonarr queue match (${matches.length} records).`);
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
Logger.ELog(`Error fetching Sonarr queue: ${e.message}`);
|
||||
|
|
@ -248,7 +252,7 @@ function findEpisodeFromQueue(searchPattern, sonarr) {
|
|||
}
|
||||
}
|
||||
|
||||
function findEpisodeFromGrabHistory(searchPattern, sonarr) {
|
||||
function findEpisodeFromGrabHistory(searchPattern, sonarr, episodePattern) {
|
||||
if (!searchPattern) return null;
|
||||
try {
|
||||
const query = buildQueryParams({
|
||||
|
|
@ -269,7 +273,11 @@ function findEpisodeFromGrabHistory(searchPattern, sonarr) {
|
|||
Logger.ILog(`Matched Sonarr grab history seriesId ${seriesId}, episodeId ${episodeId}.`);
|
||||
return { id: seriesId, episodeIds: [episodeId] };
|
||||
}
|
||||
if (keys.length > 1) Logger.WLog(`Ambiguous Sonarr grab history match (${keys.length} episodes).`);
|
||||
if (keys.length > 1) {
|
||||
const resolved = resolvePackEpisode(matches, episodePattern, sonarr);
|
||||
if (resolved) return resolved;
|
||||
Logger.WLog(`Ambiguous Sonarr grab history match (${keys.length} episodes).`);
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
Logger.ELog(`Error fetching Sonarr history: ${e.message}`);
|
||||
|
|
@ -277,6 +285,47 @@ function findEpisodeFromGrabHistory(searchPattern, sonarr) {
|
|||
}
|
||||
}
|
||||
|
||||
function resolvePackEpisode(matches, episodePattern, sonarr) {
|
||||
const coordinates = extractEpisodeCoordinates(episodePattern);
|
||||
if (!coordinates) return null;
|
||||
|
||||
const seriesIds = matches
|
||||
.map(item => Number(item?.seriesId))
|
||||
.filter(Boolean)
|
||||
.filter((value, index, values) => values.indexOf(value) === index);
|
||||
if (seriesIds.length !== 1) return null;
|
||||
|
||||
try {
|
||||
const seriesId = seriesIds[0];
|
||||
const query = buildQueryParams({ seriesId });
|
||||
const episodes = sonarr.fetchJson('episode', query) || [];
|
||||
const candidates = episodes.filter(item =>
|
||||
Number(item?.seasonNumber) === coordinates.seasonNumber
|
||||
&& Number(item?.episodeNumber) === coordinates.episodeNumber
|
||||
);
|
||||
if (candidates.length !== 1) return null;
|
||||
|
||||
const episodeId = Number(candidates[0]?.id);
|
||||
const trackedIds = matches.map(item => Number(item?.episodeId)).filter(Boolean);
|
||||
if (!episodeId || !trackedIds.includes(episodeId)) return null;
|
||||
|
||||
Logger.ILog(
|
||||
`Resolved season-pack match via exact filename S${coordinates.seasonNumber}`
|
||||
+ `E${coordinates.episodeNumber}: seriesId ${seriesId}, episodeId ${episodeId}.`
|
||||
);
|
||||
return { id: seriesId, episodeIds: [episodeId] };
|
||||
} catch (e) {
|
||||
Logger.WLog(`Unable to resolve season-pack episode: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function extractEpisodeCoordinates(value) {
|
||||
const match = String(value || '').match(/(?:^|[^a-z0-9])s(\d{1,2})e(\d{1,3})(?:[^a-z0-9]|$)/i);
|
||||
if (!match) return null;
|
||||
return { seasonNumber: Number(match[1]), episodeNumber: Number(match[2]) };
|
||||
}
|
||||
|
||||
function normalizeReleaseTitle(value) {
|
||||
return (value || '').toLowerCase().replace(/[^a-z0-9]+/g, '');
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue