PoC: native Radarr scan via original downloadId #5

Merged
sascha merged 3 commits from poc/radarr-native-scan-20260912 into main 2026-09-12 20:53:51 +02:00
3 changed files with 38 additions and 3 deletions

View file

@ -353,6 +353,7 @@
"UseUnmappedPath": false, "UseUnmappedPath": false,
"MoveMode": true, "MoveMode": true,
"TimeOut": 900, "TimeOut": 900,
"PocHoldRelease": "The.Ritual.2017.German.DL.1080p.WEB.x264.iNTERNAL-BiGiNT",
"Color": "" "Color": ""
} }
}, },

View file

@ -2,7 +2,7 @@
* @name Radarr - Trigger Manual Import * @name Radarr - Trigger Manual Import
* @description Safely trigger Radarr ManualImport for exactly one processed file. * @description Safely trigger Radarr ManualImport for exactly one processed file.
* @author FileFlows + Sascha * @author FileFlows + Sascha
* @revision 11 * @revision 12
* @output Import erfolgreich * @output Import erfolgreich
* @output Fehler * @output Fehler
* @param {string} URL Radarr root URL and port * @param {string} URL Radarr root URL and port
@ -11,11 +11,12 @@
* @param {bool} UseUnmappedPath Whether to Unmap the path * @param {bool} UseUnmappedPath Whether to Unmap the path
* @param {bool} MoveMode Import mode: true=move, false=copy * @param {bool} MoveMode Import mode: true=move, false=copy
* @param {int} TimeOut Timeout in seconds (max 3600) * @param {int} TimeOut Timeout in seconds (max 3600)
* @param {string} PocHoldRelease Exact release title to leave for an external native-scan proof
*/ */
import { Radarr } from 'Shared/Radarr'; import { Radarr } from 'Shared/Radarr';
function Script(URL, ApiKey, ImportPath, UseUnmappedPath, MoveMode, TimeOut) { function Script(URL, ApiKey, ImportPath, UseUnmappedPath, MoveMode, TimeOut, PocHoldRelease) {
URL = (URL || Variables['Radarr.Url'] || Variables['Radarr.URI']).replace(/\/+$/g, ''); URL = (URL || Variables['Radarr.Url'] || Variables['Radarr.URI']).replace(/\/+$/g, '');
ApiKey = ApiKey || Variables['Radarr.ApiKey']; ApiKey = ApiKey || Variables['Radarr.ApiKey'];
const currentFile = Variables['file.FullName'] || Variables.file?.FullName || ''; const currentFile = Variables['file.FullName'] || Variables.file?.FullName || '';
@ -53,6 +54,11 @@ function Script(URL, ApiKey, ImportPath, UseUnmappedPath, MoveMode, TimeOut) {
const searchPatterns = [folderPattern, filePattern] const searchPatterns = [folderPattern, filePattern]
.filter(Boolean) .filter(Boolean)
.filter((value, index, values) => values.indexOf(value) === index); .filter((value, index, values) => values.indexOf(value) === index);
const pocHold = normalizeReleaseTitle(PocHoldRelease || '');
if (pocHold && searchPatterns.some(pattern => normalizeReleaseTitle(pattern) === pocHold)) {
Logger.ILog(`PoC hold: leaving '${exactImportPath}' on NVMe for external native Arr scan.`);
return 1;
}
let movieId = Variables['Radarr.movieId'] ?? null; let movieId = Variables['Radarr.movieId'] ?? null;
for (const pattern of searchPatterns) { for (const pattern of searchPatterns) {
if (!movieId) { if (!movieId) {

View file

@ -61,7 +61,8 @@ const result = context.__exports.Script(
scenario.scopeRoot, scenario.scopeRoot,
false, false,
true, true,
300 300,
scenario.pocHoldRelease || ''
); );
process.stdout.write(JSON.stringify({result, calls})); process.stdout.write(JSON.stringify({result, calls}));
""" """
@ -262,6 +263,33 @@ class RadarrImportSafetyTests(unittest.TestCase):
self.assertEqual(result["result"], 1) self.assertEqual(result["result"], 1)
command = next(call for call in result["calls"] if call["type"] == "command") command = next(call for call in result["calls"] if call["type"] == "command")
self.assertEqual(command["body"]["files"][0]["movieId"], 7331) self.assertEqual(command["body"]["files"][0]["movieId"], 7331)
def test_poc_hold_leaves_exact_release_for_external_native_scan(self):
release = "The.Ritual.2017.German.DL.1080p.WEB.x264.iNTERNAL-BiGiNT"
exact = f"/tdarr/converted/video/{release}/{release}.mkv"
result = run_script(
{
"releaseTitle": release,
"exactPath": exact,
"scopeRoot": "/tdarr/converted/video/",
"pocHoldRelease": release,
"queueResponse": {"records": [{"title": release, "movieId": 6676}]},
"historyResponse": {
"records": [
{
"sourceTitle": release,
"movieId": 6676,
"downloadId": "poc-nzo-id",
"eventType": "grabbed",
}
]
},
"candidates": [],
}
)
self.assertEqual(result["result"], 1)
commands = [call for call in result["calls"] if call["type"] == "command"]
self.assertEqual(commands, [])
if __name__ == "__main__": if __name__ == "__main__":