diff --git a/NzbDrone.Core.Test/PostDownloadProviderTest.cs b/NzbDrone.Core.Test/PostDownloadProviderTest.cs index 4ffe4af05..c3d37bfce 100644 --- a/NzbDrone.Core.Test/PostDownloadProviderTest.cs +++ b/NzbDrone.Core.Test/PostDownloadProviderTest.cs @@ -47,7 +47,7 @@ namespace NzbDrone.Core.Test .Have(c => c.PostDownloadStatus = PostDownloadStatusType.Unknown) .Build(); - var expectedEpisodesNumbers = fakeEpisodes.Select(e => e.EpisodeId); + var expectedEpisodesNumbers = fakeEpisodes.Select(e => e.EpisodeId).ToList(); mocker.GetMock().Setup(s => s.FindSeries("officeus")).Returns(fakeSeries); mocker.GetMock().Setup(s => s.GetEpisodesByParseResult(It.IsAny(), false)).Returns(fakeEpisodes); @@ -124,6 +124,8 @@ namespace NzbDrone.Core.Test [TestCase(PostDownloadStatusType.ParseError, 21)] [TestCase(PostDownloadStatusType.Unknown, 10)] [TestCase(PostDownloadStatusType.Processed, 0)] + [TestCase(PostDownloadStatusType.InvalidEpisode, 25)] + [TestCase(PostDownloadStatusType.NoError, 0)] public void GetPrefixLength(PostDownloadStatusType postDownloadStatus, int expected) { //Setup @@ -244,5 +246,107 @@ namespace NzbDrone.Core.Test //Assert mocker.VerifyAllMocks(); } + + [TestCase("_NzbDrone_InvalidEpisode_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidEpisode)] + [TestCase("_NzbDrone_InvalidSeries_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidSeries)] + [TestCase("_NzbDrone_ParseError_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.ParseError)] + [TestCase("_UNPACK_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Unpacking)] + [TestCase("_FAILED_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Failed)] + [TestCase("_NzbDrone_The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Unknown)] + [TestCase("The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.NoError)] + public void GetPostDownloadStatusForFolder_should_return_a_proper_match(string folderName, PostDownloadStatusType expectedStatus) + { + //Setup + var mocker = new AutoMoqer(MockBehavior.Strict); + + //Act + var result = mocker.Resolve().GetPostDownloadStatusForFolder(folderName); + + //Assert + result.Should().Be(expectedStatus); + } + + [TestCase("_NzbDrone_InvalidEpisode_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidSeries)] + [TestCase("_NzbDrone_InvalidSeries_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidEpisode)] + [TestCase("_NzbDrone_ParseError_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidSeries)] + [TestCase("_UNPACK_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidEpisode)] + [TestCase("_FAILED_", "The Office (US) - S01E01 - Title", PostDownloadStatusType.ParseError)] + [TestCase("_NzbDrone_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.ParseError)] + public void GetNewFolderNameWithPostDownloadStatus_should_return_a_string_with_the_error_removing_existing_error(string existingErrorString, string folderName, PostDownloadStatusType postDownloadStatus) + { + //Setup + var mocker = new AutoMoqer(MockBehavior.Strict); + + var di = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), existingErrorString + folderName)); + var expectedFolderName = String.Format("_NzbDrone_{0}_{1}", postDownloadStatus.ToString(), folderName); + + var expectedResult = Path.Combine(Directory.GetCurrentDirectory(), expectedFolderName); + + //Act + var result = mocker.Resolve().GetNewFolderNameWithPostDownloadStatus(di, postDownloadStatus); + + //Assert + result.Should().Be(expectedResult); + } + + [TestCase("The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidSeries)] + [TestCase("The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.InvalidEpisode)] + [TestCase("The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.ParseError)] + public void GetNewFolderNameWithPostDownloadStatus_should_return_a_string_with_the_error(string folderName, PostDownloadStatusType postDownloadStatus) + { + //Setup + var mocker = new AutoMoqer(MockBehavior.Strict); + + var di = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), folderName)); + var expectedFolderName = String.Format("_NzbDrone_{0}_{1}", postDownloadStatus.ToString(), folderName); + + var expectedResult = Path.Combine(Directory.GetCurrentDirectory(), expectedFolderName); + + //Act + var result = mocker.Resolve().GetNewFolderNameWithPostDownloadStatus(di, postDownloadStatus); + + //Assert + result.Should().Be(expectedResult); + } + + [TestCase("_NzbDrone_ParseError_", "The Office (US) - S01E01 - Episode Title")] + [TestCase("", "The Office (US) - S01E01 - Episode Title")] + public void GetNewFolderNameWithPostDownloadStatus_should_return_a_path_with_a_unknown_error(string existingError, string folderName) + { + //Setup + var mocker = new AutoMoqer(MockBehavior.Strict); + + var di = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), folderName)); + var expectedFolderName = String.Format("_NzbDrone_{0}", folderName); + + var expectedResult = Path.Combine(Directory.GetCurrentDirectory(), expectedFolderName); + + //Act + var result = mocker.Resolve().GetNewFolderNameWithPostDownloadStatus(di, PostDownloadStatusType.Unknown); + + //Assert + result.Should().Be(expectedResult); + } + + [TestCase("_NzbDrone_ParseError_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.NoError)] + [TestCase("", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.NoError)] + [TestCase("_NzbDrone_ParseError_", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Processed)] + [TestCase("", "The Office (US) - S01E01 - Episode Title", PostDownloadStatusType.Processed)] + public void GetNewFolderNameWithPostDownloadStatus_should_return_a_path_with_no_error(string existingError, string folderName, PostDownloadStatusType postDownloadStatus) + { + //Setup + var mocker = new AutoMoqer(MockBehavior.Strict); + + var di = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), folderName)); + var expectedFolderName = folderName; + + var expectedResult = Path.Combine(Directory.GetCurrentDirectory(), expectedFolderName); + + //Act + var result = mocker.Resolve().GetNewFolderNameWithPostDownloadStatus(di, postDownloadStatus); + + //Assert + result.Should().Be(expectedResult); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Model/PostDownloadStatusType.cs b/NzbDrone.Core/Model/PostDownloadStatusType.cs index 6389159d6..3a5cf2bc2 100644 --- a/NzbDrone.Core/Model/PostDownloadStatusType.cs +++ b/NzbDrone.Core/Model/PostDownloadStatusType.cs @@ -36,5 +36,10 @@ /// InvalidEpisode /// InvalidEpisode = 6, + + /// + /// NoError + /// + NoError = 7, } } \ No newline at end of file diff --git a/NzbDrone.Core/Providers/PostDownloadProvider.cs b/NzbDrone.Core/Providers/PostDownloadProvider.cs index 1afabb4e2..e6050b7eb 100644 --- a/NzbDrone.Core/Providers/PostDownloadProvider.cs +++ b/NzbDrone.Core/Providers/PostDownloadProvider.cs @@ -67,31 +67,27 @@ namespace NzbDrone.Core.Providers { var subfolderInfo = new DirectoryInfo(subfolder); - if (subfolderInfo.Name.StartsWith("_UNPACK_")) + var folderStatus = GetPostDownloadStatusForFolder(subfolderInfo.Name); + + if (folderStatus == PostDownloadStatusType.Unpacking) { ProcessFailedOrUnpackingDownload(subfolderInfo, PostDownloadStatusType.Unpacking); Logger.Debug("Folder [{0}] is still being unpacked. skipping.", subfolder); continue; } - if (subfolderInfo.Name.StartsWith("_FAILED_")) + if (folderStatus == PostDownloadStatusType.Failed) { ProcessFailedOrUnpackingDownload(subfolderInfo, PostDownloadStatusType.Failed); Logger.Debug("Folder [{0}] is marked as failed. skipping.", subfolder); continue; } - if (subfolderInfo.Name.StartsWith("_NzbDrone_")) + if (folderStatus != PostDownloadStatusType.Unknown) { - if (subfolderInfo.Name.StartsWith("_NzbDrone_InvalidSeries_")) - ReProcessDownload(new PostDownloadInfoModel { Name = subfolderInfo.FullName, Status = PostDownloadStatusType.InvalidSeries }); - - else if (subfolderInfo.Name.StartsWith("_NzbDrone_ParseError_")) - ReProcessDownload(new PostDownloadInfoModel { Name = subfolderInfo.FullName, Status = PostDownloadStatusType.ParseError }); - - else - ReProcessDownload(new PostDownloadInfoModel { Name = subfolderInfo.FullName, Status = PostDownloadStatusType.Unknown }); - + //Retry processing on the download + ReProcessDownload(new PostDownloadInfoModel{ Name = subfolderInfo.FullName, Status = folderStatus }); + continue; } @@ -172,12 +168,6 @@ namespace NzbDrone.Core.Providers return; } - //Add to InfoList for possible later processing - InfoList.Add(new PostDownloadInfoModel{ Name = directoryInfo.FullName, - Added = DateTime.Now, - Status = postDownloadStatus - }); - //Remove the error prefix before processing var parseResult = Parser.ParseTitle(directoryInfo.Name.Substring(GetPrefixLength(postDownloadStatus))); @@ -198,9 +188,9 @@ namespace NzbDrone.Core.Providers { //Mark as InvalidEpisode Logger.Warn("Unable to Import new download [{0}], no episode(s) found in database.", directoryInfo.FullName); - _diskProvider.MoveDirectory(directoryInfo.FullName, - Path.Combine(directoryInfo.Parent.FullName, - "_NzbDrone_InvalidEpisode_" + directoryInfo.Name.Substring(GetPrefixLength(postDownloadStatus)))); + + var newPath = GetNewFolderNameWithPostDownloadStatus(directoryInfo, PostDownloadStatusType.InvalidEpisode); + _diskProvider.MoveDirectory(directoryInfo.FullName, newPath); return; } @@ -220,7 +210,7 @@ namespace NzbDrone.Core.Providers public virtual void ReProcessDownload(PostDownloadInfoModel model) { var directoryInfo = new DirectoryInfo(model.Name); - var newName = Path.Combine(directoryInfo.Parent.FullName, directoryInfo.Name.Substring(GetPrefixLength(model.Status))); + var newName = GetNewFolderNameWithPostDownloadStatus(directoryInfo, PostDownloadStatusType.NoError); _diskProvider.MoveDirectory(directoryInfo.FullName, newName); @@ -235,20 +225,17 @@ namespace NzbDrone.Core.Providers if (postDownloadStatus == PostDownloadStatusType.Unpacking || postDownloadStatus == PostDownloadStatusType.Failed) return 8; - //_NzbDrone_InvalidSeries_ - Length = 24 - if (postDownloadStatus == PostDownloadStatusType.InvalidSeries) - return 24; - - //_NzbDrone_ParseError_ - Length = - if (postDownloadStatus == PostDownloadStatusType.ParseError) - return 21; - - //_NzbDrone_ - Length = 10 if (postDownloadStatus == PostDownloadStatusType.Unknown) return 10; - //Default to zero - return 0; + if (postDownloadStatus == PostDownloadStatusType.Processed) + return 0; + + if (postDownloadStatus == PostDownloadStatusType.NoError) + return 0; + + //Return the 11 (_NzbDrone_) + trailing underscore + postDownloadStatus length + return 11 + postDownloadStatus.ToString().Length; } public void Add(PostDownloadInfoModel model) @@ -265,5 +252,51 @@ namespace NzbDrone.Core.Providers { return InfoList.SingleOrDefault(i => i.Name == path); } + + public PostDownloadStatusType GetPostDownloadStatusForFolder(string folderName) + { + if (folderName.StartsWith("_UNPACK_")) + return PostDownloadStatusType.Unpacking; + + if (folderName.StartsWith("_FAILED_")) + return PostDownloadStatusType.Failed; + + foreach (PostDownloadStatusType postDownloadStatusType in Enum.GetValues(typeof(PostDownloadStatusType))) + { + var startsWith = String.Format("_NzbDrone_{0}_", postDownloadStatusType.ToString()); + + if (folderName.StartsWith(startsWith)) + return postDownloadStatusType; + } + + if (folderName.StartsWith("_NzbDrone_")) + return PostDownloadStatusType.Unknown; + + return PostDownloadStatusType.NoError; + } + + public string GetNewFolderNameWithPostDownloadStatus(DirectoryInfo directoryInfo, PostDownloadStatusType postDownloadStatus) + { + var existingError = GetPostDownloadStatusForFolder(directoryInfo.Name); + var newFolderName = directoryInfo.Name; + var error = String.Format("_NzbDrone_{0}_", postDownloadStatus.ToString()); + + if (existingError != PostDownloadStatusType.NoError) + newFolderName = directoryInfo.Name.Substring(GetPrefixLength(existingError)); + + if (postDownloadStatus == PostDownloadStatusType.Unknown) + error = "_NzbDrone_"; + + if (postDownloadStatus == PostDownloadStatusType.NoError) + error = String.Empty; + + if (postDownloadStatus == PostDownloadStatusType.Processed) + error = String.Empty; + + var parent = directoryInfo.Parent.FullName; + var newName = error + newFolderName; + + return Path.Combine(parent, newName); + } } } diff --git a/SharedLiveTemplates.xml b/SharedLiveTemplates.xml deleted file mode 100644 index 65e47d6b6..000000000 --- a/SharedLiveTemplates.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - \ No newline at end of file