Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>pull/4342/head
parent
f430d1aab2
commit
72caab1b2b
@ -1,4 +0,0 @@
|
||||
.messageRemove {
|
||||
margin-bottom: 30px;
|
||||
color: $dangerColor;
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.MovieImport;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ProcessFixture : CoreTest<CompletedDownloadService>
|
||||
{
|
||||
private TrackedDownload _trackedDownload;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var completed = Builder<DownloadClientItem>.CreateNew()
|
||||
.With(h => h.Status = DownloadItemStatus.Completed)
|
||||
.With(h => h.OutputPath = new OsPath(@"C:\DropFolder\MyDownload".AsOsAgnostic()))
|
||||
.With(h => h.Title = "Drone.S01E01.HDTV")
|
||||
.Build();
|
||||
|
||||
var remoteMovie = BuildRemoteMovie();
|
||||
|
||||
_trackedDownload = Builder<TrackedDownload>.CreateNew()
|
||||
.With(c => c.State = TrackedDownloadState.Downloading)
|
||||
.With(c => c.DownloadItem = completed)
|
||||
.With(c => c.RemoteMovie = remoteMovie)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IDownloadClient>()
|
||||
.SetupGet(c => c.Definition)
|
||||
.Returns(new DownloadClientDefinition { Id = 1, Name = "testClient" });
|
||||
|
||||
Mocker.GetMock<IProvideDownloadClient>()
|
||||
.Setup(c => c.Get(It.IsAny<int>()))
|
||||
.Returns(Mocker.GetMock<IDownloadClient>().Object);
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.MostRecentForDownloadId(_trackedDownload.DownloadItem.DownloadId))
|
||||
.Returns(new History.History());
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.GetMovie("Drone.S01E01.HDTV"))
|
||||
.Returns(remoteMovie.Movie);
|
||||
}
|
||||
|
||||
private RemoteMovie BuildRemoteMovie()
|
||||
{
|
||||
return new RemoteMovie
|
||||
{
|
||||
Movie = new Movie(),
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenNoGrabbedHistory()
|
||||
{
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.MostRecentForDownloadId(_trackedDownload.DownloadItem.DownloadId))
|
||||
.Returns((History.History)null);
|
||||
}
|
||||
|
||||
private void GivenMovieMatch()
|
||||
{
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.GetMovie(It.IsAny<string>()))
|
||||
.Returns(_trackedDownload.RemoteMovie.Movie);
|
||||
}
|
||||
|
||||
private void GivenABadlyNamedDownload()
|
||||
{
|
||||
_trackedDownload.DownloadItem.DownloadId = "1234";
|
||||
_trackedDownload.DownloadItem.Title = "Droned Pilot"; // Set a badly named download
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.MostRecentForDownloadId(It.Is<string>(i => i == "1234")))
|
||||
.Returns(new History.History() { SourceTitle = "Droned S01E01" });
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.GetMovie(It.IsAny<string>()))
|
||||
.Returns((Movie)null);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.GetMovie("Droned S01E01"))
|
||||
.Returns(BuildRemoteMovie().Movie);
|
||||
}
|
||||
|
||||
[TestCase(DownloadItemStatus.Downloading)]
|
||||
[TestCase(DownloadItemStatus.Failed)]
|
||||
[TestCase(DownloadItemStatus.Queued)]
|
||||
[TestCase(DownloadItemStatus.Paused)]
|
||||
[TestCase(DownloadItemStatus.Warning)]
|
||||
public void should_not_process_if_download_status_isnt_completed(DownloadItemStatus status)
|
||||
{
|
||||
_trackedDownload.DownloadItem.Status = status;
|
||||
|
||||
Subject.Check(_trackedDownload);
|
||||
|
||||
AssertNotReadyToImport();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_matching_history_is_not_found_and_no_category_specified()
|
||||
{
|
||||
_trackedDownload.DownloadItem.Category = null;
|
||||
GivenNoGrabbedHistory();
|
||||
|
||||
Subject.Check(_trackedDownload);
|
||||
|
||||
AssertNotReadyToImport();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_process_if_matching_history_is_not_found_but_category_specified()
|
||||
{
|
||||
_trackedDownload.DownloadItem.Category = "tv";
|
||||
GivenNoGrabbedHistory();
|
||||
GivenMovieMatch();
|
||||
|
||||
Subject.Check(_trackedDownload);
|
||||
|
||||
AssertReadyToImport();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_output_path_is_empty()
|
||||
{
|
||||
_trackedDownload.DownloadItem.OutputPath = default(OsPath);
|
||||
|
||||
Subject.Check(_trackedDownload);
|
||||
|
||||
AssertNotReadyToImport();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_if_the_download_cannot_be_tracked_using_the_source_title_as_it_was_initiated_externally()
|
||||
{
|
||||
GivenABadlyNamedDownload();
|
||||
|
||||
Mocker.GetMock<IDownloadedMovieImportService>()
|
||||
.Setup(v => v.ProcessPath(It.IsAny<string>(), It.IsAny<ImportMode>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>()))
|
||||
.Returns(new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalMovie { Path = @"C:\TestPath\Droned.S01E01.mkv" }))
|
||||
});
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.MostRecentForDownloadId(It.Is<string>(i => i == "1234")));
|
||||
|
||||
Subject.Check(_trackedDownload);
|
||||
|
||||
AssertNotReadyToImport();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_process_when_there_is_a_title_mismatch()
|
||||
{
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.GetMovie("Drone.S01E01.HDTV"))
|
||||
.Returns((Movie)null);
|
||||
|
||||
Subject.Check(_trackedDownload);
|
||||
|
||||
AssertNotReadyToImport();
|
||||
}
|
||||
|
||||
private void AssertNotReadyToImport()
|
||||
{
|
||||
_trackedDownload.State.Should().NotBe(TrackedDownloadState.ImportPending);
|
||||
}
|
||||
|
||||
private void AssertReadyToImport()
|
||||
{
|
||||
_trackedDownload.State.Should().Be(TrackedDownloadState.ImportPending);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.FailedDownloadServiceTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ProcessFailedFixture : CoreTest<FailedDownloadService>
|
||||
{
|
||||
private TrackedDownload _trackedDownload;
|
||||
private List<History.History> _grabHistory;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var completed = Builder<DownloadClientItem>.CreateNew()
|
||||
.With(h => h.Status = DownloadItemStatus.Completed)
|
||||
.With(h => h.OutputPath = new OsPath(@"C:\DropFolder\MyDownload".AsOsAgnostic()))
|
||||
.With(h => h.Title = "Drone.S01E01.HDTV")
|
||||
.Build();
|
||||
|
||||
_grabHistory = Builder<History.History>.CreateListOfSize(2).BuildList();
|
||||
|
||||
var remoteMovie = new RemoteMovie
|
||||
{
|
||||
Movie = new Movie()
|
||||
};
|
||||
|
||||
_trackedDownload = Builder<TrackedDownload>.CreateNew()
|
||||
.With(c => c.State = TrackedDownloadState.FailedPending)
|
||||
.With(c => c.DownloadItem = completed)
|
||||
.With(c => c.RemoteMovie = remoteMovie)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.Find(_trackedDownload.DownloadItem.DownloadId, HistoryEventType.Grabbed))
|
||||
.Returns(_grabHistory);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_mark_failed_if_encrypted()
|
||||
{
|
||||
_trackedDownload.DownloadItem.IsEncrypted = true;
|
||||
|
||||
Subject.ProcessFailed(_trackedDownload);
|
||||
|
||||
AssertDownloadFailed();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_mark_failed_if_download_item_is_failed()
|
||||
{
|
||||
_trackedDownload.DownloadItem.Status = DownloadItemStatus.Failed;
|
||||
|
||||
Subject.ProcessFailed(_trackedDownload);
|
||||
|
||||
AssertDownloadFailed();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_include_tracked_download_in_message()
|
||||
{
|
||||
_trackedDownload.DownloadItem.Status = DownloadItemStatus.Failed;
|
||||
|
||||
Subject.ProcessFailed(_trackedDownload);
|
||||
|
||||
Mocker.GetMock<IEventAggregator>()
|
||||
.Verify(v => v.PublishEvent(It.Is<DownloadFailedEvent>(c => c.TrackedDownload != null)), Times.Once());
|
||||
|
||||
AssertDownloadFailed();
|
||||
}
|
||||
|
||||
private void AssertDownloadNotFailed()
|
||||
{
|
||||
Mocker.GetMock<IEventAggregator>()
|
||||
.Verify(v => v.PublishEvent(It.IsAny<DownloadFailedEvent>()), Times.Never());
|
||||
|
||||
_trackedDownload.State.Should().NotBe(TrackedDownloadState.Failed);
|
||||
}
|
||||
|
||||
private void AssertDownloadFailed()
|
||||
{
|
||||
Mocker.GetMock<IEventAggregator>()
|
||||
.Verify(v => v.PublishEvent(It.IsAny<DownloadFailedEvent>()), Times.Once());
|
||||
|
||||
_trackedDownload.State.Should().Be(TrackedDownloadState.Failed);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.TrackedDownloads
|
||||
{
|
||||
[TestFixture]
|
||||
public class TrackedDownloadAlreadyImportedFixture : CoreTest<TrackedDownloadAlreadyImported>
|
||||
{
|
||||
private Movie _movie;
|
||||
private TrackedDownload _trackedDownload;
|
||||
private List<History.History> _historyItems;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_movie = Builder<Movie>.CreateNew().Build();
|
||||
|
||||
var remoteMovie = Builder<RemoteMovie>.CreateNew()
|
||||
.With(r => r.Movie = _movie)
|
||||
.Build();
|
||||
|
||||
_trackedDownload = Builder<TrackedDownload>.CreateNew()
|
||||
.With(t => t.RemoteMovie = remoteMovie)
|
||||
.Build();
|
||||
|
||||
_historyItems = new List<History.History>();
|
||||
}
|
||||
|
||||
public void GivenHistoryForMovie(Movie movie, params HistoryEventType[] eventTypes)
|
||||
{
|
||||
foreach (var eventType in eventTypes)
|
||||
{
|
||||
_historyItems.Add(
|
||||
Builder<History.History>.CreateNew()
|
||||
.With(h => h.MovieId = movie.Id)
|
||||
.With(h => h.EventType = eventType)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_if_there_is_no_history()
|
||||
{
|
||||
Subject.IsImported(_trackedDownload, _historyItems)
|
||||
.Should()
|
||||
.BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_if_single_movie_download_is_not_imported()
|
||||
{
|
||||
GivenHistoryForMovie(_movie, HistoryEventType.Grabbed);
|
||||
|
||||
Subject.IsImported(_trackedDownload, _historyItems)
|
||||
.Should()
|
||||
.BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_if_single_movie_download_is_imported()
|
||||
{
|
||||
GivenHistoryForMovie(_movie, HistoryEventType.DownloadFolderImported, HistoryEventType.Grabbed);
|
||||
|
||||
Subject.IsImported(_trackedDownload, _historyItems)
|
||||
.Should()
|
||||
.BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class DownloadIgnoredEvent : IEvent
|
||||
{
|
||||
public int MovieId { get; set; }
|
||||
public List<Language> Languages { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public string SourceTitle { get; set; }
|
||||
public string DownloadClient { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class DownloadProcessingService : IExecute<ProcessMonitoredDownloadsCommand>
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly ICompletedDownloadService _completedDownloadService;
|
||||
private readonly IFailedDownloadService _failedDownloadService;
|
||||
private readonly ITrackedDownloadService _trackedDownloadService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public DownloadProcessingService(IConfigService configService,
|
||||
ICompletedDownloadService completedDownloadService,
|
||||
IFailedDownloadService failedDownloadService,
|
||||
ITrackedDownloadService trackedDownloadService,
|
||||
IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_completedDownloadService = completedDownloadService;
|
||||
_failedDownloadService = failedDownloadService;
|
||||
_trackedDownloadService = trackedDownloadService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private void RemoveCompletedDownloads(List<TrackedDownload> trackedDownloads)
|
||||
{
|
||||
foreach (var trackedDownload in trackedDownloads.Where(c => c.DownloadItem.CanBeRemoved && c.State == TrackedDownloadState.Imported))
|
||||
{
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
|
||||
}
|
||||
}
|
||||
|
||||
public void Execute(ProcessMonitoredDownloadsCommand message)
|
||||
{
|
||||
var enableCompletedDownloadHandling = _configService.EnableCompletedDownloadHandling;
|
||||
var trackedDownloads = _trackedDownloadService.GetTrackedDownloads();
|
||||
|
||||
foreach (var trackedDownload in trackedDownloads)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (trackedDownload.State == TrackedDownloadState.FailedPending)
|
||||
{
|
||||
_failedDownloadService.ProcessFailed(trackedDownload);
|
||||
}
|
||||
|
||||
if (enableCompletedDownloadHandling && trackedDownload.State == TrackedDownloadState.ImportPending)
|
||||
{
|
||||
_completedDownloadService.Import(trackedDownload);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Debug(e, "Failed to process download: {0}", trackedDownload.DownloadItem.Title);
|
||||
}
|
||||
}
|
||||
|
||||
if (enableCompletedDownloadHandling && _configService.RemoveCompletedDownloads)
|
||||
{
|
||||
// Remove tracked downloads that are now complete
|
||||
RemoveCompletedDownloads(trackedDownloads);
|
||||
}
|
||||
|
||||
_eventAggregator.PublishEvent(new DownloadsProcessedEvent());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using NzbDrone.Common.Messaging;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class DownloadsProcessedEvent : IEvent
|
||||
{
|
||||
public DownloadsProcessedEvent()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public interface IIgnoredDownloadService
|
||||
{
|
||||
bool IgnoreDownload(TrackedDownload trackedDownload);
|
||||
}
|
||||
|
||||
public class IgnoredDownloadService : IIgnoredDownloadService
|
||||
{
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public IgnoredDownloadService(IEventAggregator eventAggregator,
|
||||
Logger logger)
|
||||
{
|
||||
_eventAggregator = eventAggregator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool IgnoreDownload(TrackedDownload trackedDownload)
|
||||
{
|
||||
var movie = trackedDownload.RemoteMovie.Movie;
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
_logger.Warn("Unable to ignore download for unknown movie");
|
||||
return false;
|
||||
}
|
||||
|
||||
var downloadIgnoredEvent = new DownloadIgnoredEvent
|
||||
{
|
||||
MovieId = movie.Id,
|
||||
Languages = trackedDownload.RemoteMovie.ParsedMovieInfo.Languages,
|
||||
Quality = trackedDownload.RemoteMovie.ParsedMovieInfo.Quality,
|
||||
SourceTitle = trackedDownload.DownloadItem.Title,
|
||||
DownloadClient = trackedDownload.DownloadItem.DownloadClient,
|
||||
DownloadId = trackedDownload.DownloadItem.DownloadId,
|
||||
Message = "Manually ignored"
|
||||
};
|
||||
|
||||
_eventAggregator.PublishEvent(downloadIgnoredEvent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class ProcessMonitoredDownloadsCommand : Command
|
||||
{
|
||||
public override bool RequiresDiskAccess => true;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class RefreshMonitoredDownloadsCommand : Command
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.History;
|
||||
|
||||
namespace NzbDrone.Core.Download.TrackedDownloads
|
||||
{
|
||||
public interface ITrackedDownloadAlreadyImported
|
||||
{
|
||||
bool IsImported(TrackedDownload trackedDownload, List<History.History> historyItems);
|
||||
}
|
||||
|
||||
public class TrackedDownloadAlreadyImported : ITrackedDownloadAlreadyImported
|
||||
{
|
||||
public bool IsImported(TrackedDownload trackedDownload, List<History.History> historyItems)
|
||||
{
|
||||
if (historyItems.Empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var movie = trackedDownload.RemoteMovie.Movie;
|
||||
|
||||
var lastHistoryItem = historyItems.FirstOrDefault(h => h.MovieId == movie.Id);
|
||||
|
||||
if (lastHistoryItem == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var allEpisodesImportedInHistory = lastHistoryItem.EventType == HistoryEventType.DownloadFolderImported;
|
||||
|
||||
return allEpisodesImportedInHistory;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
|
||||
{
|
||||
public class AlreadyImportedSpecification : IImportDecisionEngineSpecification
|
||||
{
|
||||
private readonly IHistoryService _historyService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public AlreadyImportedSpecification(IHistoryService historyService,
|
||||
Logger logger)
|
||||
{
|
||||
_historyService = historyService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public SpecificationPriority Priority => SpecificationPriority.Database;
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (downloadClientItem == null)
|
||||
{
|
||||
_logger.Debug("No download client information is available, skipping");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
var movie = localMovie.Movie;
|
||||
|
||||
if (!movie.HasFile)
|
||||
{
|
||||
_logger.Debug("Skipping already imported check for movie without file");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
var movieImportedHistory = _historyService.GetByMovieId(movie.Id, null);
|
||||
var lastImported = movieImportedHistory.FirstOrDefault(h => h.EventType == HistoryEventType.DownloadFolderImported);
|
||||
var lastGrabbed = movieImportedHistory.FirstOrDefault(h => h.EventType == HistoryEventType.Grabbed);
|
||||
|
||||
if (lastImported == null)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
// If the release was grabbed again after importing don't reject it
|
||||
if (lastGrabbed != null && lastGrabbed.Date.After(lastImported.Date))
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
if (lastImported.DownloadId == downloadClientItem.DownloadId)
|
||||
{
|
||||
_logger.Debug("Movie file previously imported at {0}", lastImported.Date);
|
||||
return Decision.Reject("Movie file already imported at {0}", lastImported.Date);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue