diff --git a/src/NzbDrone.Core/Extras/ExistingExtraFileService.cs b/src/NzbDrone.Core/Extras/ExistingExtraFileService.cs index b5e661de1..bdfdd20c3 100644 --- a/src/NzbDrone.Core/Extras/ExistingExtraFileService.cs +++ b/src/NzbDrone.Core/Extras/ExistingExtraFileService.cs @@ -10,7 +10,7 @@ namespace NzbDrone.Core.Extras { public interface IExistingExtraFiles { - List ImportFileList(Series series, List possibleExtraFiles); + List ImportExtraFiles(Series series, List possibleExtraFiles); } public class ExistingExtraFileService : IExistingExtraFiles, IHandle @@ -25,7 +25,7 @@ namespace NzbDrone.Core.Extras _logger = logger; } - public List ImportFileList(Series series, List possibleExtraFiles) + public List ImportExtraFiles(Series series, List possibleExtraFiles) { _logger.Debug("Looking for existing extra files in {0}", series.Path); @@ -47,7 +47,7 @@ namespace NzbDrone.Core.Extras var possibleExtraFiles = message.PossibleExtraFiles; - var importedFiles = ImportFileList(series, possibleExtraFiles); + var importedFiles = ImportExtraFiles(series, possibleExtraFiles); _logger.Info("Found {0} possible extra files, imported {1} files.", possibleExtraFiles.Count, importedFiles.Count); } diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs b/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs index 958eed347..eac485671 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs @@ -130,7 +130,7 @@ namespace NzbDrone.Core.MediaFiles try { MoveEpisodeFile(episodeFile, series, episodeFile.Episodes); - localEpisode.ImportRenamed = true; + localEpisode.FileRenamedAfterScriptImport = true; } catch (SameFilenameException) { diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs index 4e29da3da..5d4bb77f6 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs @@ -135,9 +135,9 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport { if (localEpisode.ScriptImported) { - _existingExtraFiles.ImportFileList(localEpisode.Series, localEpisode.PossibleExtraFiles); + _existingExtraFiles.ImportExtraFiles(localEpisode.Series, localEpisode.PossibleExtraFiles); - if (localEpisode.ImportRenamed) + if (localEpisode.FileRenamedAfterScriptImport) { _extraService.MoveFilesAfterRename(localEpisode.Series, episodeFile); } diff --git a/src/NzbDrone.Core/MediaFiles/ScriptImportDecider.cs b/src/NzbDrone.Core/MediaFiles/ScriptImportDecider.cs index 084d8c9aa..45ab383d7 100644 --- a/src/NzbDrone.Core/MediaFiles/ScriptImportDecider.cs +++ b/src/NzbDrone.Core/MediaFiles/ScriptImportDecider.cs @@ -47,12 +47,14 @@ namespace NzbDrone.Core.MediaFiles _logger = logger; } - private static readonly Regex OutputRegex = new Regex(@"^\[(?:(?MediaFile)|(?ExtraFile))\]\s(?.+)$", RegexOptions.Compiled); + private static readonly Regex OutputRegex = new Regex(@"^(?:\[(?:(?MediaFile)|(?ExtraFile))\]\s?(?.+)|(?\[PreventExtraImport\])|\[MoveStatus\]\s?(?:(?DeferMove)|(?MoveComplete)|(?RenameRequested)))$", RegexOptions.Compiled); private ScriptImportInfo ProcessOutput(List processOutputLines) { var possibleExtraFiles = new List(); string mediaFile = null; + var decision = ScriptImportDecision.MoveComplete; + var importExtraFiles = true; foreach (var line in processOutputLines) { @@ -78,18 +80,34 @@ namespace NzbDrone.Core.MediaFiles } else if (match.Groups["extraFile"].Success) { - possibleExtraFiles.Add(match.Groups["fileName"].Value); + var fileName = match.Groups["fileName"].Value; - var lastAdded = possibleExtraFiles.Last(); - - if (!_diskProvider.FileExists(lastAdded)) + if (!_diskProvider.FileExists(fileName)) { - throw new ScriptImportException("Script output contains non-existent possible extra file: {0}", lastAdded); + _logger.Warn("Script output contains non-existent possible extra file: {0}", fileName); } + + possibleExtraFiles.Add(fileName); + } + else if (match.Groups["moveComplete"].Success) + { + decision = ScriptImportDecision.MoveComplete; + } + else if (match.Groups["renameRequested"].Success) + { + decision = ScriptImportDecision.RenameRequested; + } + else if (match.Groups["deferMove"].Success) + { + decision = ScriptImportDecision.DeferMove; + } + else if (match.Groups["preventExtraImport"].Success) + { + importExtraFiles = false; } } - return new ScriptImportInfo(possibleExtraFiles, mediaFile); + return new ScriptImportInfo(possibleExtraFiles, mediaFile, decision, importExtraFiles); } public ScriptImportDecision TryImport(string sourcePath, string destinationFilePath, LocalEpisode localEpisode, EpisodeFile episodeFile, TransferMode mode) @@ -165,9 +183,13 @@ namespace NzbDrone.Core.MediaFiles var processOutput = _processProvider.StartAndCapture(_configService.ScriptImportPath, $"\"{sourcePath}\" \"{destinationFilePath}\"", environmentVariables); - _logger.Debug("Executed external script: {0} - Status: {1}", _configService.ScriptImportPath, processOutput.ExitCode); _logger.Debug("Script Output: \r\n{0}", string.Join("\r\n", processOutput.Lines)); + if (processOutput.ExitCode != 0) + { + throw new ScriptImportException("Script exited with non-zero exit code: {0}", processOutput.ExitCode); + } + var scriptImportInfo = ProcessOutput(processOutput.Lines); var mediaFile = scriptImportInfo.MediaFile ?? destinationFilePath; @@ -178,27 +200,20 @@ namespace NzbDrone.Core.MediaFiles var exitCode = processOutput.ExitCode; - if (exitCode >= 4) + localEpisode.ShouldImportExtras = scriptImportInfo.ImportExtraFiles; + + if (scriptImportInfo.Decision != ScriptImportDecision.DeferMove) { - localEpisode.ShouldImportExtras = true; - exitCode -= 4; + localEpisode.ScriptImported = true; } - switch (exitCode) + if (scriptImportInfo.Decision == ScriptImportDecision.RenameRequested) { - case 0: // Copy complete - localEpisode.ScriptImported = true; - return ScriptImportDecision.MoveComplete; - case 2: // Copy complete, file potentially changed, should try renaming again - localEpisode.ScriptImported = true; - episodeFile.MediaInfo = _videoFileInfoReader.GetMediaInfo(mediaFile); - episodeFile.Path = null; - return ScriptImportDecision.RenameRequested; - case 3: // Let Sonarr handle it - return ScriptImportDecision.DeferMove; - default: // Error, fail to import - throw new ScriptImportException("Moving with script failed! Exit code {0}", processOutput.ExitCode); + episodeFile.MediaInfo = _videoFileInfoReader.GetMediaInfo(mediaFile); + episodeFile.Path = null; } + + return scriptImportInfo.Decision; } } } diff --git a/src/NzbDrone.Core/MediaFiles/ScriptImportInfo.cs b/src/NzbDrone.Core/MediaFiles/ScriptImportInfo.cs index a44742fb5..6c861fa8d 100644 --- a/src/NzbDrone.Core/MediaFiles/ScriptImportInfo.cs +++ b/src/NzbDrone.Core/MediaFiles/ScriptImportInfo.cs @@ -6,11 +6,15 @@ namespace NzbDrone.Core.MediaFiles { public List PossibleExtraFiles { get; set; } public string MediaFile { get; set; } + public ScriptImportDecision Decision { get; set; } + public bool ImportExtraFiles { get; set; } - public ScriptImportInfo(List possibleExtraFiles, string mediaFile) + public ScriptImportInfo(List possibleExtraFiles, string mediaFile, ScriptImportDecision decision, bool importExtraFiles) { PossibleExtraFiles = possibleExtraFiles; MediaFile = mediaFile; + Decision = decision; + ImportExtraFiles = importExtraFiles; } } } diff --git a/src/NzbDrone.Core/Parser/Model/LocalEpisode.cs b/src/NzbDrone.Core/Parser/Model/LocalEpisode.cs index 283ca1189..470310b7c 100644 --- a/src/NzbDrone.Core/Parser/Model/LocalEpisode.cs +++ b/src/NzbDrone.Core/Parser/Model/LocalEpisode.cs @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Parser.Model public int CustomFormatScore { get; set; } public GrabbedReleaseInfo Release { get; set; } public bool ScriptImported { get; set; } - public bool ImportRenamed { get; set; } + public bool FileRenamedAfterScriptImport { get; set; } public bool ShouldImportExtras { get; set; } public List PossibleExtraFiles { get; set; }