Fixed: Don't mark a download as successful unless all valid files are imported
This commit is contained in:
parent
059028da02
commit
2651cd63a8
|
@ -9,7 +9,6 @@ using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.History;
|
using NzbDrone.Core.History;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
|
@ -104,9 +103,9 @@ namespace NzbDrone.Core.Test.Download
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
||||||
.Setup(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()))
|
.Setup(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()))
|
||||||
.Returns(new List<ImportDecision>()
|
.Returns(new List<ImportResult>
|
||||||
{
|
{
|
||||||
new ImportDecision(null)
|
new ImportResult(null)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,9 +113,9 @@ namespace NzbDrone.Core.Test.Download
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
||||||
.Setup(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()))
|
.Setup(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()))
|
||||||
.Returns(new List<ImportDecision>()
|
.Returns(new List<ImportResult>()
|
||||||
{
|
{
|
||||||
new ImportDecision(new LocalEpisode() { Path = @"C:\TestPath\Droned.S01E01.mkv" }, "Test Failure")
|
new ImportResult(new ImportDecision(new LocalEpisode() { Path = @"C:\TestPath\Droned.S01E01.mkv" }, "Test Failure"))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,5 +447,37 @@ namespace NzbDrone.Core.Test.Download
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Verify(c => c.DeleteFolder(It.IsAny<string>(), true), Times.Once());
|
.Verify(c => c.DeleteFolder(It.IsAny<string>(), true), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_mark_as_successful_if_no_files_were_imported()
|
||||||
|
{
|
||||||
|
GivenCompletedDownloadClientHistory();
|
||||||
|
|
||||||
|
var history = Builder<History.History>.CreateListOfSize(1)
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
GivenGrabbedHistory(history);
|
||||||
|
GivenNoImportedHistory();
|
||||||
|
|
||||||
|
Mocker.GetMock<IDownloadedEpisodesImportService>()
|
||||||
|
.Setup(v => v.ProcessFolder(It.IsAny<DirectoryInfo>(), It.IsAny<DownloadClientItem>()))
|
||||||
|
.Returns(new List<ImportResult>
|
||||||
|
{
|
||||||
|
new ImportResult(
|
||||||
|
new ImportDecision(new LocalEpisode() {Path = @"C:\TestPath\Droned.S01E01.mkv"}),
|
||||||
|
"Test Failure")
|
||||||
|
});
|
||||||
|
|
||||||
|
history.First().Data.Add("downloadClient", "SabnzbdClient");
|
||||||
|
history.First().Data.Add("downloadClientId", _completed.First().DownloadClientId);
|
||||||
|
|
||||||
|
Subject.Execute(new CheckForFinishedDownloadCommand());
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Verify(c => c.DeleteFolder(It.IsAny<string>(), true), Times.Never());
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedErrors(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common;
|
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
@ -42,7 +42,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
|
|
||||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
||||||
.Returns(new List<ImportDecision>());
|
.Returns(new List<ImportResult>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenValidSeries()
|
private void GivenValidSeries()
|
||||||
|
@ -125,7 +125,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), false, null))
|
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), false, null))
|
||||||
.Returns(new List<ImportDecision>());
|
.Returns(new List<ImportResult>());
|
||||||
|
|
||||||
Subject.Execute(new DownloadedEpisodesScanCommand());
|
Subject.Execute(new DownloadedEpisodesScanCommand());
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
|
|
||||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
||||||
.Returns(imported);
|
.Returns(imported.Select(i => new ImportResult(i)).ToList());
|
||||||
|
|
||||||
Subject.Execute(new DownloadedEpisodesScanCommand());
|
Subject.Execute(new DownloadedEpisodesScanCommand());
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
|
|
||||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||||
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
.Setup(s => s.Import(It.IsAny<List<ImportDecision>>(), true, null))
|
||||||
.Returns(imported);
|
.Returns(imported.Select(i => new ImportResult(i)).ToList());
|
||||||
|
|
||||||
Mocker.GetMock<ISampleService>()
|
Mocker.GetMock<ISampleService>()
|
||||||
.Setup(s => s.IsSample(It.IsAny<Series>(),
|
.Setup(s => s.IsSample(It.IsAny<Series>(),
|
||||||
|
|
|
@ -65,9 +65,11 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_empty_list_if_there_are_no_approved_decisions()
|
public void should_not_import_any_if_there_are_no_approved_decisions()
|
||||||
{
|
{
|
||||||
Subject.Import(_rejectedDecisions, false).Should().BeEmpty();
|
Subject.Import(_rejectedDecisions, false).Where(i => i.Result == ImportResultType.Imported).Should().BeEmpty();
|
||||||
|
|
||||||
|
Mocker.GetMock<IMediaFileService>().Verify(v => v.Add(It.IsAny<EpisodeFile>()), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -83,7 +85,10 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
all.AddRange(_rejectedDecisions);
|
all.AddRange(_rejectedDecisions);
|
||||||
all.AddRange(_approvedDecisions);
|
all.AddRange(_approvedDecisions);
|
||||||
|
|
||||||
Subject.Import(all, false).Should().HaveCount(5);
|
var result = Subject.Import(all, false);
|
||||||
|
|
||||||
|
result.Should().HaveCount(all.Count);
|
||||||
|
result.Where(i => i.Result == ImportResultType.Imported).Should().HaveCount(_approvedDecisions.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -93,7 +98,9 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
all.AddRange(_approvedDecisions);
|
all.AddRange(_approvedDecisions);
|
||||||
all.Add(new ImportDecision(_approvedDecisions.First().LocalEpisode));
|
all.Add(new ImportDecision(_approvedDecisions.First().LocalEpisode));
|
||||||
|
|
||||||
Subject.Import(all, false).Should().HaveCount(5);
|
var result = Subject.Import(all, false);
|
||||||
|
|
||||||
|
result.Where(i => i.Result == ImportResultType.Imported).Should().HaveCount(_approvedDecisions.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -136,7 +143,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
{
|
{
|
||||||
Series = fileDecision.LocalEpisode.Series,
|
Series = fileDecision.LocalEpisode.Series,
|
||||||
Episodes = new List<Episode> {fileDecision.LocalEpisode.Episodes.First()},
|
Episodes = new List<Episode> {fileDecision.LocalEpisode.Episodes.First()},
|
||||||
Path = @"C:\Test\TV\30 Rock\30 Rock - S01E01 - Pilit.avi".AsOsAgnostic(),
|
Path = @"C:\Test\TV\30 Rock\30 Rock - S01E01 - Pilot.avi".AsOsAgnostic(),
|
||||||
Quality = new QualityModel(Quality.Bluray720p),
|
Quality = new QualityModel(Quality.Bluray720p),
|
||||||
Size = 80.Megabytes()
|
Size = 80.Megabytes()
|
||||||
});
|
});
|
||||||
|
@ -148,8 +155,9 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
|
|
||||||
var results = Subject.Import(all, false);
|
var results = Subject.Import(all, false);
|
||||||
|
|
||||||
results.Should().HaveCount(1);
|
results.Should().HaveCount(all.Count);
|
||||||
results.Should().ContainSingle(d => d.LocalEpisode.Size == fileDecision.LocalEpisode.Size);
|
results.Should().ContainSingle(d => d.Result == ImportResultType.Imported);
|
||||||
|
results.Should().ContainSingle(d => d.Result == ImportResultType.Imported && d.ImportDecision.LocalEpisode.Size == fileDecision.LocalEpisode.Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,19 +3,13 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Cache;
|
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.History;
|
using NzbDrone.Core.History;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using NzbDrone.Common.EnsureThat;
|
|
||||||
using NzbDrone.Core.Parser;
|
|
||||||
using NzbDrone.Core.Tv;
|
|
||||||
using NzbDrone.Core.Qualities;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download
|
namespace NzbDrone.Core.Download
|
||||||
{
|
{
|
||||||
|
@ -97,51 +91,15 @@ namespace NzbDrone.Core.Download
|
||||||
|
|
||||||
if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath))
|
if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath))
|
||||||
{
|
{
|
||||||
var decisions = _downloadedEpisodesImportService.ProcessFolder(new DirectoryInfo(trackedDownload.DownloadItem.OutputPath), trackedDownload.DownloadItem);
|
var importResults = _downloadedEpisodesImportService.ProcessFolder(new DirectoryInfo(trackedDownload.DownloadItem.OutputPath), trackedDownload.DownloadItem);
|
||||||
|
|
||||||
if (!decisions.Any())
|
ProcessImportResults(trackedDownload, importResults);
|
||||||
{
|
|
||||||
UpdateStatusMessage(trackedDownload, LogLevel.Error, "No files found eligible for import in {0}", trackedDownload.DownloadItem.OutputPath);
|
|
||||||
}
|
|
||||||
else if (decisions.Any(v => v.Approved))
|
|
||||||
{
|
|
||||||
UpdateStatusMessage(trackedDownload, LogLevel.Info, "Imported {0} files.", decisions.Count(v => v.Approved));
|
|
||||||
|
|
||||||
trackedDownload.State = TrackedDownloadState.Imported;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var rejections = decisions
|
|
||||||
.Where(v => !v.Approved)
|
|
||||||
.Select(v => v.Rejections.Aggregate(Path.GetFileName(v.LocalEpisode.Path), (a, r) => a + "\r\n- " + r))
|
|
||||||
.Aggregate("Failed to import:", (a, r) => a + "\r\n" + r);
|
|
||||||
|
|
||||||
UpdateStatusMessage(trackedDownload, LogLevel.Error, rejections);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (_diskProvider.FileExists(trackedDownload.DownloadItem.OutputPath))
|
else if (_diskProvider.FileExists(trackedDownload.DownloadItem.OutputPath))
|
||||||
{
|
{
|
||||||
var decisions = _downloadedEpisodesImportService.ProcessFile(new FileInfo(trackedDownload.DownloadItem.OutputPath), trackedDownload.DownloadItem);
|
var importResults = _downloadedEpisodesImportService.ProcessFile(new FileInfo(trackedDownload.DownloadItem.OutputPath), trackedDownload.DownloadItem);
|
||||||
|
|
||||||
if (!decisions.Any())
|
ProcessImportResults(trackedDownload, importResults);
|
||||||
{
|
|
||||||
UpdateStatusMessage(trackedDownload, LogLevel.Error, "No files found eligible for import in {0}", trackedDownload.DownloadItem.OutputPath);
|
|
||||||
}
|
|
||||||
else if (decisions.Any(v => v.Approved))
|
|
||||||
{
|
|
||||||
UpdateStatusMessage(trackedDownload, LogLevel.Info, "Imported {0} files.", decisions.Count(v => v.Approved));
|
|
||||||
|
|
||||||
trackedDownload.State = TrackedDownloadState.Imported;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var rejections = decisions
|
|
||||||
.Where(v => !v.Approved)
|
|
||||||
.Select(v => v.Rejections.Aggregate(Path.GetFileName(v.LocalEpisode.Path), (a, r) => a + "\r\n- " + r))
|
|
||||||
.Aggregate("Failed to import:", (a, r) => a + "\r\n" + r);
|
|
||||||
|
|
||||||
UpdateStatusMessage(trackedDownload, LogLevel.Error, rejections);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -222,5 +180,28 @@ namespace NzbDrone.Core.Download
|
||||||
_logger.Debug(logMessage);
|
_logger.Debug(logMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ProcessImportResults(TrackedDownload trackedDownload, List<ImportResult> importResults)
|
||||||
|
{
|
||||||
|
if (importResults.Empty())
|
||||||
|
{
|
||||||
|
UpdateStatusMessage(trackedDownload, LogLevel.Error, "No files found are eligible for import in {0}", trackedDownload.DownloadItem.OutputPath);
|
||||||
|
}
|
||||||
|
else if (importResults.All(v => v.Result == ImportResultType.Imported || v.Result == ImportResultType.Rejected))
|
||||||
|
{
|
||||||
|
UpdateStatusMessage(trackedDownload, LogLevel.Info, "Imported {0} files.", importResults.Count(v => v.Result == ImportResultType.Imported));
|
||||||
|
|
||||||
|
trackedDownload.State = TrackedDownloadState.Imported;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var errors = importResults
|
||||||
|
.Where(v => v.Result == ImportResultType.Skipped || v.Result == ImportResultType.Rejected)
|
||||||
|
.Select(v => v.Errors.Aggregate(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), (a, r) => a + "\r\n- " + r))
|
||||||
|
.Aggregate("Failed to import:", (a, r) => a + "\r\n" + r);
|
||||||
|
|
||||||
|
UpdateStatusMessage(trackedDownload, LogLevel.Error, errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace NzbDrone.Core.Download
|
||||||
public Int32 RetryCount { get; set; }
|
public Int32 RetryCount { get; set; }
|
||||||
public Boolean HasError { get; set; }
|
public Boolean HasError { get; set; }
|
||||||
public String StatusMessage { get; set; }
|
public String StatusMessage { get; set; }
|
||||||
|
public List<String> StatusMessages { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TrackedDownloadState
|
public enum TrackedDownloadState
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
@ -12,7 +11,6 @@ using NzbDrone.Core.MediaFiles.Commands;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Qualities;
|
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
|
||||||
|
@ -20,8 +18,8 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
{
|
{
|
||||||
public interface IDownloadedEpisodesImportService
|
public interface IDownloadedEpisodesImportService
|
||||||
{
|
{
|
||||||
List<ImportDecision> ProcessFolder(DirectoryInfo directoryInfo, DownloadClientItem downloadClientItem);
|
List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, DownloadClientItem downloadClientItem);
|
||||||
List<ImportDecision> ProcessFile(FileInfo fileInfo, DownloadClientItem downloadClientItem);
|
List<ImportResult> ProcessFile(FileInfo fileInfo, DownloadClientItem downloadClientItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DownloadedEpisodesImportService : IDownloadedEpisodesImportService, IExecute<DownloadedEpisodesScanCommand>
|
public class DownloadedEpisodesImportService : IDownloadedEpisodesImportService, IExecute<DownloadedEpisodesScanCommand>
|
||||||
|
@ -57,7 +55,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ImportDecision> ProcessFolder(DirectoryInfo directoryInfo, DownloadClientItem downloadClientItem)
|
public List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, DownloadClientItem downloadClientItem)
|
||||||
{
|
{
|
||||||
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
||||||
var series = _parsingService.GetSeries(cleanedUpName);
|
var series = _parsingService.GetSeries(cleanedUpName);
|
||||||
|
@ -67,39 +65,35 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
if (series == null)
|
if (series == null)
|
||||||
{
|
{
|
||||||
_logger.Debug("Unknown Series {0}", cleanedUpName);
|
_logger.Debug("Unknown Series {0}", cleanedUpName);
|
||||||
return new List<ImportDecision>();
|
return new List<ImportResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
||||||
|
|
||||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), series, true, quality);
|
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), series, true, quality);
|
||||||
|
|
||||||
var importedDecisions = _importApprovedEpisodes.Import(decisions, true, downloadClientItem);
|
var importResults = _importApprovedEpisodes.Import(decisions, true, downloadClientItem);
|
||||||
|
|
||||||
if (!downloadClientItem.IsReadOnly && importedDecisions.Any() && ShouldDeleteFolder(directoryInfo))
|
if (!downloadClientItem.IsReadOnly && importResults.Any() && ShouldDeleteFolder(directoryInfo))
|
||||||
{
|
{
|
||||||
_logger.Debug("Deleting folder after importing valid files");
|
_logger.Debug("Deleting folder after importing valid files");
|
||||||
_diskProvider.DeleteFolder(directoryInfo.FullName, true);
|
_diskProvider.DeleteFolder(directoryInfo.FullName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return importedDecisions.Union(decisions).ToList();
|
return importResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ImportDecision> ProcessFile(FileInfo fileInfo, DownloadClientItem downloadClientItem)
|
public List<ImportResult> ProcessFile(FileInfo fileInfo, DownloadClientItem downloadClientItem)
|
||||||
{
|
{
|
||||||
var series = _parsingService.GetSeries(Path.GetFileNameWithoutExtension(fileInfo.Name));
|
var series = _parsingService.GetSeries(Path.GetFileNameWithoutExtension(fileInfo.Name));
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
{
|
{
|
||||||
_logger.Debug("Unknown Series for file: {0}", fileInfo.Name);
|
_logger.Debug("Unknown Series for file: {0}", fileInfo.Name);
|
||||||
return new List<ImportDecision>();
|
return new List<ImportResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, series, true, null);
|
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, series, true);
|
||||||
|
return _importApprovedEpisodes.Import(decisions, true, downloadClientItem);
|
||||||
var importedDecisions = _importApprovedEpisodes.Import(decisions, true, downloadClientItem);
|
|
||||||
|
|
||||||
return importedDecisions.Union(decisions).ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessDownloadedEpisodesFolder()
|
private void ProcessDownloadedEpisodesFolder()
|
||||||
|
@ -136,7 +130,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ImportDecision> ProcessFolder(DirectoryInfo directoryInfo)
|
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo)
|
||||||
{
|
{
|
||||||
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
||||||
var series = _parsingService.GetSeries(cleanedUpName);
|
var series = _parsingService.GetSeries(cleanedUpName);
|
||||||
|
@ -146,7 +140,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
if (series == null)
|
if (series == null)
|
||||||
{
|
{
|
||||||
_logger.Debug("Unknown Series {0}", cleanedUpName);
|
_logger.Debug("Unknown Series {0}", cleanedUpName);
|
||||||
return new List<ImportDecision>();
|
return new List<ImportResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
||||||
|
@ -156,7 +150,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
if (_diskProvider.IsFileLocked(videoFile))
|
if (_diskProvider.IsFileLocked(videoFile))
|
||||||
{
|
{
|
||||||
_logger.Debug("[{0}] is currently locked by another process, skipping", videoFile);
|
_logger.Debug("[{0}] is currently locked by another process, skipping", videoFile);
|
||||||
return new List<ImportDecision>();
|
return new List<ImportResult>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +15,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
{
|
{
|
||||||
public interface IImportApprovedEpisodes
|
public interface IImportApprovedEpisodes
|
||||||
{
|
{
|
||||||
List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownload, DownloadClientItem historyItem = null);
|
List<ImportResult> Import(List<ImportDecision> decisions, bool newDownload, DownloadClientItem historyItem = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportApprovedEpisodes : IImportApprovedEpisodes
|
public class ImportApprovedEpisodes : IImportApprovedEpisodes
|
||||||
|
@ -40,7 +39,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownload, DownloadClientItem historyItem = null)
|
public List<ImportResult> Import(List<ImportDecision> decisions, bool newDownload, DownloadClientItem historyItem = null)
|
||||||
{
|
{
|
||||||
var qualifiedImports = decisions.Where(c => c.Approved)
|
var qualifiedImports = decisions.Where(c => c.Approved)
|
||||||
.GroupBy(c => c.LocalEpisode.Series.Id, (i, s) => s
|
.GroupBy(c => c.LocalEpisode.Series.Id, (i, s) => s
|
||||||
|
@ -49,7 +48,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
.SelectMany(c => c)
|
.SelectMany(c => c)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var imported = new List<ImportDecision>();
|
var importResults = new List<ImportResult>();
|
||||||
|
|
||||||
foreach (var importDecision in qualifiedImports.OrderByDescending(e => e.LocalEpisode.Size))
|
foreach (var importDecision in qualifiedImports.OrderByDescending(e => e.LocalEpisode.Size))
|
||||||
{
|
{
|
||||||
|
@ -59,11 +58,12 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//check if already imported
|
//check if already imported
|
||||||
if (imported.SelectMany(r => r.LocalEpisode.Episodes)
|
if (importResults.SelectMany(r => r.ImportDecision.LocalEpisode.Episodes)
|
||||||
.Select(e => e.Id)
|
.Select(e => e.Id)
|
||||||
.Intersect(localEpisode.Episodes.Select(e => e.Id))
|
.Intersect(localEpisode.Episodes.Select(e => e.Id))
|
||||||
.Any())
|
.Any())
|
||||||
{
|
{
|
||||||
|
importResults.Add(new ImportResult(importDecision, "Episode has already been imported"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
}
|
}
|
||||||
|
|
||||||
_mediaFileService.Add(episodeFile);
|
_mediaFileService.Add(episodeFile);
|
||||||
imported.Add(importDecision);
|
importResults.Add(new ImportResult(importDecision));
|
||||||
|
|
||||||
if (historyItem != null)
|
if (historyItem != null)
|
||||||
{
|
{
|
||||||
|
@ -111,10 +111,15 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.WarnException("Couldn't import episode " + localEpisode, e);
|
_logger.WarnException("Couldn't import episode " + localEpisode, e);
|
||||||
|
importResults.Add(new ImportResult(importDecision, "Failed to import episode"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return imported;
|
//Adding all the rejected decisions
|
||||||
|
importResults.AddRange(decisions.Where(c => !c.Approved)
|
||||||
|
.Select(d => new ImportResult(d, d.Rejections.ToArray())));
|
||||||
|
|
||||||
|
return importResults;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Common;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
|
{
|
||||||
|
public class ImportResult
|
||||||
|
{
|
||||||
|
public ImportDecision ImportDecision { get; private set; }
|
||||||
|
public List<String> Errors { get; private set; }
|
||||||
|
|
||||||
|
public ImportResultType Result
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
//Approved and imported
|
||||||
|
if (Errors.Empty()) return ImportResultType.Imported;
|
||||||
|
|
||||||
|
//Decision was approved, but it was not imported
|
||||||
|
if (ImportDecision.Approved) return ImportResultType.Skipped;
|
||||||
|
|
||||||
|
//Decision was rejected
|
||||||
|
return ImportResultType.Rejected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportResult(ImportDecision importDecision, params String[] errors)
|
||||||
|
{
|
||||||
|
ImportDecision = importDecision;
|
||||||
|
Errors = errors.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
|
{
|
||||||
|
public enum ImportResultType
|
||||||
|
{
|
||||||
|
Imported,
|
||||||
|
Rejected,
|
||||||
|
Skipped
|
||||||
|
}
|
||||||
|
}
|
|
@ -468,10 +468,12 @@
|
||||||
<Compile Include="MediaFiles\EpisodeFile.cs" />
|
<Compile Include="MediaFiles\EpisodeFile.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeFileMoveResult.cs" />
|
<Compile Include="MediaFiles\EpisodeFileMoveResult.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeFileMovingService.cs" />
|
<Compile Include="MediaFiles\EpisodeFileMovingService.cs" />
|
||||||
|
<Compile Include="MediaFiles\EpisodeImport\ImportResult.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\IImportDecisionEngineSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\IImportDecisionEngineSpecification.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\ImportApprovedEpisodes.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\ImportApprovedEpisodes.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\ImportDecision.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\ImportDecision.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\ImportDecisionMaker.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\ImportDecisionMaker.cs" />
|
||||||
|
<Compile Include="MediaFiles\EpisodeImport\ImportResultType.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\SampleService.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\SampleService.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecification.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\FullSeasonSpecification.cs" />
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Queue
|
namespace NzbDrone.Core.Queue
|
||||||
|
|
Loading…
Reference in New Issue