fix: preserve Arr metadata and fail closed
This commit is contained in:
parent
aa575a17fd
commit
81a01d5880
1 changed files with 53 additions and 15 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 9
|
||||
* @revision 10
|
||||
* @output Import erfolgreich
|
||||
* @output Fehler
|
||||
* @param {string} URL Sonarr root URL and port
|
||||
|
|
@ -43,14 +43,22 @@ function Script(URL, ApiKey, ImportPath, UseUnmappedPath, MoveMode, TimeOut) {
|
|||
const sonarr = new Sonarr(URL, ApiKey);
|
||||
|
||||
/*── seriesId / episodeId detection ──────────────────────────────────*/
|
||||
const searchPattern = Variables.file.Orig.FileNameNoExtension;
|
||||
const filePattern = Variables.file.Orig.FileNameNoExtension;
|
||||
const folderPattern = System.IO.Path.GetFileName(System.IO.Path.GetDirectoryName(exactImportPath));
|
||||
const searchPatterns = [folderPattern, filePattern]
|
||||
.filter(Boolean)
|
||||
.filter((value, index, values) => values.indexOf(value) === index);
|
||||
let seriesId = Variables['Sonarr.seriesId'] ?? Variables.TVShowInfo?.id ?? null;
|
||||
let episodeIds = Variables['Sonarr.episodeIds'] ?? Variables.TVShowInfo?.EpisodesInfo ?? null;
|
||||
|
||||
if (!(seriesId && episodeIds)) {
|
||||
const trackedEpisode = findEpisodeFromQueue(searchPattern, sonarr)
|
||||
?? findEpisodeFromGrabHistory(searchPattern, sonarr)
|
||||
?? parseSeries(searchPattern, sonarr);
|
||||
let trackedEpisode = null;
|
||||
for (const pattern of searchPatterns) {
|
||||
trackedEpisode = findEpisodeFromQueue(pattern, sonarr)
|
||||
?? findEpisodeFromGrabHistory(pattern, sonarr);
|
||||
if (trackedEpisode) break;
|
||||
}
|
||||
if (!trackedEpisode) trackedEpisode = parseSeries(searchPatterns[0] || '', sonarr);
|
||||
seriesId = trackedEpisode?.id ?? null;
|
||||
episodeIds = trackedEpisode?.episodeIds ?? null;
|
||||
}
|
||||
|
|
@ -60,11 +68,12 @@ function Script(URL, ApiKey, ImportPath, UseUnmappedPath, MoveMode, TimeOut) {
|
|||
Logger.ILog(`Import Mode: ${importMode}`);
|
||||
|
||||
if (seriesId && episodeIds) {
|
||||
const releaseMetadata = findGrabMetadata(searchPatterns, sonarr, seriesId, episodeIds);
|
||||
Logger.ILog(`seriesId=${seriesId}, episodeIds=[${episodeIds.join(', ')}] → ManualImport`);
|
||||
return manualImportWorkflow(sonarr, exactImportPath, importMode, seriesId, episodeIds, TimeOut);
|
||||
return manualImportWorkflow(sonarr, exactImportPath, importMode, seriesId, episodeIds, releaseMetadata, TimeOut);
|
||||
}
|
||||
|
||||
Logger.ELog(`Unable to identify '${searchPattern}' uniquely; file remains for manual recovery.`);
|
||||
Logger.ELog(`Unable to identify '${searchPatterns.join("' or '")}' uniquely; file remains for manual recovery.`);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +89,7 @@ function Script(URL, ApiKey, ImportPath, UseUnmappedPath, MoveMode, TimeOut) {
|
|||
* @param {number} timeout - Timeout in milliseconds
|
||||
* @returns {number} 1 on success, −1 on failure
|
||||
*/
|
||||
function manualImportWorkflow(sonarr, path, mode, seriesId, episodeIds, timeout) {
|
||||
function manualImportWorkflow(sonarr, path, mode, seriesId, episodeIds, releaseMetadata, timeout) {
|
||||
const candidates = getManualImportCandidates(sonarr, path);
|
||||
if (!candidates.length) {
|
||||
Logger.WLog('No candidates returned by fetching ManualImport');
|
||||
|
|
@ -98,7 +107,7 @@ function manualImportWorkflow(sonarr, path, mode, seriesId, episodeIds, timeout)
|
|||
return -1;
|
||||
}
|
||||
|
||||
const fileObj = buildManualImportFile(cand, seriesId, episodeIds, path);
|
||||
const fileObj = buildManualImportFile(cand, seriesId, episodeIds, path, releaseMetadata);
|
||||
const cmdBody = { name: 'ManualImport', files: [fileObj], importMode: mode };
|
||||
const cmdId = sendManualImportCommand(sonarr, cmdBody);
|
||||
if (cmdId === null) {
|
||||
|
|
@ -137,23 +146,52 @@ function getManualImportCandidates(sonarr, importPath) {
|
|||
* @param {number} episodeIds – Sonarr episodeIds to which the file is linked
|
||||
* @returns {object} File descriptor for ManualImport
|
||||
*/
|
||||
function buildManualImportFile(src, seriesId, episodeIds, importPath) {
|
||||
function buildManualImportFile(src, seriesId, episodeIds, importPath, releaseMetadata) {
|
||||
const path = src.path || importPath;
|
||||
const fallbackFolder = System.IO.Path.GetFileName(System.IO.Path.GetDirectoryName(path)) ?? Variables.folder.Name;
|
||||
const metadata = releaseMetadata || {};
|
||||
const metadataData = metadata.data || {};
|
||||
|
||||
return {
|
||||
path: path,
|
||||
folderName: src.folderName || src.name || fallbackFolder,
|
||||
seriesId: seriesId,
|
||||
episodeIds: episodeIds,
|
||||
releaseGroup: src.releaseGroup || 'Sonarr',
|
||||
quality: src.quality,
|
||||
languages: src.languages || [ { id:0, name:'Unknown' } ],
|
||||
indexerFlags: src.indexerFlags ?? 0,
|
||||
releaseType: src.releaseType ?? 'unknown'
|
||||
releaseGroup: metadataData.releaseGroup || metadata.releaseGroup || src.releaseGroup || 'Sonarr',
|
||||
quality: metadata.quality || src.quality,
|
||||
languages: metadata.languages || src.languages || [ { id:0, name:'Unknown' } ],
|
||||
indexerFlags: Number(metadataData.indexerFlags ?? metadata.indexerFlags ?? src.indexerFlags ?? 0),
|
||||
releaseType: metadataData.releaseType || metadata.releaseType || src.releaseType || 'unknown'
|
||||
};
|
||||
}
|
||||
|
||||
function findGrabMetadata(searchPatterns, sonarr, seriesId, episodeIds) {
|
||||
try {
|
||||
const query = buildQueryParams({
|
||||
page: 1, pageSize: 250, eventType: 1,
|
||||
sortKey: 'date', sortDirection: 'descending'
|
||||
});
|
||||
const response = sonarr.fetchJson('history', query) || {};
|
||||
const records = Array.isArray(response) ? response : (response.records || []);
|
||||
const wanted = searchPatterns.map(normalizeReleaseTitle);
|
||||
const matching = records.filter(item =>
|
||||
item?.seriesId === seriesId
|
||||
&& episodeIds.includes(item?.episodeId)
|
||||
&& wanted.includes(normalizeReleaseTitle(item.sourceTitle || ''))
|
||||
);
|
||||
if (!matching.length) return null;
|
||||
const targetKeys = matching
|
||||
.map(item => `${item.seriesId}:${item.episodeId}`)
|
||||
.filter((key, index, values) => values.indexOf(key) === index);
|
||||
if (targetKeys.some(key => !episodeIds.includes(Number(key.split(':')[1])))) return null;
|
||||
Logger.ILog(`Using metadata from exact Sonarr grab history match (${matching[0].sourceTitle}).`);
|
||||
return matching[0];
|
||||
} catch (e) {
|
||||
Logger.WLog(`Unable to recover Sonarr grab metadata: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Send the **ManualImport** command to Sonarr and return command-id
|
||||
* @param {Sonarr} sonarr – Sonarr API instance
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue