1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-09-17 15:02:34 +02:00

Fixed: DiskScanService Updates

This commit is contained in:
Qstick 2019-07-09 23:14:53 -04:00
parent 612d948eba
commit b8f7ca0749
17 changed files with 155 additions and 91 deletions

View File

@ -1,15 +1,17 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Test.Common;
using System.Threading;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Download.Clients.Blackhole; using NzbDrone.Core.Download.Clients.Blackhole;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
{ {
@ -18,7 +20,7 @@ public class ScanWatchFolderFixture : CoreTest<ScanWatchFolder>
{ {
protected readonly string _title = "Droned.1998.1080p.WEB-DL-DRONE"; protected readonly string _title = "Droned.1998.1080p.WEB-DL-DRONE";
protected string _completedDownloadFolder = @"c:\blackhole\completed".AsOsAgnostic(); protected string _completedDownloadFolder = @"c:\blackhole\completed".AsOsAgnostic();
protected void GivenCompletedItem() protected void GivenCompletedItem()
{ {
var targetDir = Path.Combine(_completedDownloadFolder, _title); var targetDir = Path.Combine(_completedDownloadFolder, _title);
@ -33,6 +35,9 @@ protected void GivenCompletedItem()
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFileSize(It.IsAny<string>())) .Setup(c => c.GetFileSize(It.IsAny<string>()))
.Returns(1000000); .Returns(1000000);
Mocker.GetMock<IDiskScanService>().Setup(c => c.FilterFiles(It.IsAny<string>(), It.IsAny<IEnumerable<string>>()))
.Returns<string, IEnumerable<string>>((b, s) => s.ToList());
} }
protected void GivenChangedItem() protected void GivenChangedItem()
@ -43,7 +48,7 @@ protected void GivenChangedItem()
.Setup(c => c.GetFileSize(It.IsAny<string>())) .Setup(c => c.GetFileSize(It.IsAny<string>()))
.Returns(currentSize + 1); .Returns(currentSize + 1);
} }
private void VerifySingleItem(DownloadItemStatus status) private void VerifySingleItem(DownloadItemStatus status)
{ {
var items = Subject.GetItems(_completedDownloadFolder, TimeSpan.FromMilliseconds(50)).ToList(); var items = Subject.GetItems(_completedDownloadFolder, TimeSpan.FromMilliseconds(50)).ToList();

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@ -10,6 +11,7 @@
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Blackhole; using NzbDrone.Core.Download.Clients.Blackhole;
using NzbDrone.Core.Exceptions; using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
@ -48,6 +50,9 @@ public void Setup()
Mocker.GetMock<ITorrentFileInfoReader>() Mocker.GetMock<ITorrentFileInfoReader>()
.Setup(c => c.GetHashFromTorrentFile(It.IsAny<byte[]>())) .Setup(c => c.GetHashFromTorrentFile(It.IsAny<byte[]>()))
.Returns("myhash"); .Returns("myhash");
Mocker.GetMock<IDiskScanService>().Setup(c => c.FilterFiles(It.IsAny<string>(), It.IsAny<IEnumerable<string>>()))
.Returns<string, IEnumerable<string>>((b, s) => s.ToList());
} }
protected void GivenFailedDownload() protected void GivenFailedDownload()

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@ -10,6 +11,7 @@
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Blackhole; using NzbDrone.Core.Download.Clients.Blackhole;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
@ -41,6 +43,9 @@ public void Setup()
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(c => c.OpenWriteStream(It.IsAny<string>())) .Setup(c => c.OpenWriteStream(It.IsAny<string>()))
.Returns(() => new FileStream(GetTempFilePath(), FileMode.Create)); .Returns(() => new FileStream(GetTempFilePath(), FileMode.Create));
Mocker.GetMock<IDiskScanService>().Setup(c => c.FilterFiles(It.IsAny<string>(), It.IsAny<IEnumerable<string>>()))
.Returns<string, IEnumerable<string>>((b, s) => s.ToList());
} }
protected void GivenFailedDownload() protected void GivenFailedDownload()
@ -77,6 +82,9 @@ public void completed_download_should_have_required_properties()
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyCompleted(result); VerifyCompleted(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]

View File

@ -190,6 +190,9 @@ public void completed_download_should_have_required_properties()
PrepareClientToReturnCompletedItem(); PrepareClientToReturnCompletedItem();
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
VerifyCompleted(item); VerifyCompleted(item);
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]

View File

@ -103,10 +103,13 @@ public void GetItems_should_return_no_items_when_queue_is_empty()
public void queued_item_should_have_required_properties() public void queued_item_should_have_required_properties()
{ {
GivenQueue(_queued); GivenQueue(_queued);
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyQueued(result); VerifyQueued(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -118,6 +121,9 @@ public void paused_item_should_have_required_properties()
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyPaused(result); VerifyPaused(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -129,6 +135,9 @@ public void downloading_item_should_have_required_properties()
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyDownloading(result); VerifyDownloading(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -139,6 +148,9 @@ public void completed_download_should_have_required_properties()
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyCompleted(result); VerifyCompleted(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -149,6 +161,9 @@ public void failed_item_should_have_required_properties()
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyFailed(result); VerifyFailed(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]

View File

@ -191,7 +191,10 @@ public void queued_item_should_have_required_properties(SabnzbdDownloadStatus st
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyQueued(result); VerifyQueued(result);
result.RemainingTime.Should().NotBe(TimeSpan.Zero); result.RemainingTime.Should().NotBe(TimeSpan.Zero);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[TestCase(SabnzbdDownloadStatus.Paused)] [TestCase(SabnzbdDownloadStatus.Paused)]
@ -205,6 +208,9 @@ public void paused_item_should_have_required_properties(SabnzbdDownloadStatus st
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyPaused(result); VerifyPaused(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[TestCase(SabnzbdDownloadStatus.Checking)] [TestCase(SabnzbdDownloadStatus.Checking)]
@ -227,7 +233,10 @@ public void downloading_item_should_have_required_properties(SabnzbdDownloadStat
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyDownloading(result); VerifyDownloading(result);
result.RemainingTime.Should().NotBe(TimeSpan.Zero); result.RemainingTime.Should().NotBe(TimeSpan.Zero);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -239,6 +248,9 @@ public void completed_download_should_have_required_properties()
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyCompleted(result); VerifyCompleted(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -252,6 +264,9 @@ public void failed_item_should_have_required_properties()
var result = Subject.GetItems().Single(); var result = Subject.GetItems().Single();
VerifyFailed(result); VerifyFailed(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]

View File

@ -47,9 +47,12 @@ public void failed_item_should_have_required_properties()
[Test] [Test]
public void completed_download_should_have_required_properties() public void completed_download_should_have_required_properties()
{ {
PrepareClientToReturnCompletedItem(); PrepareClientToReturnCompletedItem(true, ratioLimit: 0.5);
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
VerifyCompleted(item); VerifyCompleted(item);
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
} }
[Test] [Test]
@ -72,7 +75,7 @@ public void Download_should_return_unique_id()
} }
[Test] [Test]
public void Download_with_TvDirectory_should_force_directory() public void Download_with_MovieDirectory_should_force_directory()
{ {
GivenMovieDirectory(); GivenMovieDirectory();
GivenSuccessfulDownload(); GivenSuccessfulDownload();
@ -122,7 +125,7 @@ public void Download_with_category_should_not_have_double_slashes()
} }
[Test] [Test]
public void Download_without_TvDirectory_and_Category_should_use_default() public void Download_without_MovieDirectory_and_Category_should_use_default()
{ {
GivenSuccessfulDownload(); GivenSuccessfulDownload();
@ -181,13 +184,13 @@ public void GetItems_should_return_downloading_item_as_downloadItemStatus(Transm
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
} }
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)]
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, false)] [TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, false)]
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, false)] [TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, false)]
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued, false)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued, false)]
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, false)] [TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, false)]
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, false)] [TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, false)]
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly) public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedValue)
{ {
_completed.Status = apiStatus; _completed.Status = apiStatus;
@ -196,8 +199,8 @@ public void GetItems_should_return_completed_item_as_downloadItemStatus(Transmis
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.Status.Should().Be(expectedItemStatus); item.Status.Should().Be(expectedItemStatus);
item.CanBeRemoved.Should().Be(expectedReadOnly); item.CanBeRemoved.Should().Be(expectedValue);
item.CanMoveFiles.Should().Be(expectedReadOnly); item.CanMoveFiles.Should().Be(expectedValue);
} }
[Test] [Test]

View File

@ -2,9 +2,12 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.MovieImport; using NzbDrone.Core.MediaFiles.MovieImport;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -13,9 +16,6 @@
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using FluentAssertions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download;
namespace NzbDrone.Core.Test.MediaFiles namespace NzbDrone.Core.Test.MediaFiles
{ {
@ -35,6 +35,9 @@ public void Setup()
Mocker.GetMock<IDiskScanService>().Setup(c => c.GetVideoFiles(It.IsAny<string>(), It.IsAny<bool>())) Mocker.GetMock<IDiskScanService>().Setup(c => c.GetVideoFiles(It.IsAny<string>(), It.IsAny<bool>()))
.Returns(_videoFiles); .Returns(_videoFiles);
Mocker.GetMock<IDiskScanService>().Setup(c => c.FilterFiles(It.IsAny<string>(), It.IsAny<IEnumerable<string>>()))
.Returns<string, IEnumerable<string>>((b, s) => s.ToList());
Mocker.GetMock<IDiskProvider>().Setup(c => c.GetDirectories(It.IsAny<string>())) Mocker.GetMock<IDiskProvider>().Setup(c => c.GetDirectories(It.IsAny<string>()))
.Returns(_subFolders); .Returns(_subFolders);

View File

@ -92,6 +92,7 @@ public void should_return_video_files_only()
[TestCase("Plex Versions")] [TestCase("Plex Versions")]
[TestCase(".secret")] [TestCase(".secret")]
[TestCase(".hidden")] [TestCase(".hidden")]
[TestCase(".unwanted")]
public void should_filter_certain_sub_folders(string subFolder) public void should_filter_certain_sub_folders(string subFolder)
{ {
var path = @"C:\Test\"; var path = @"C:\Test\";
@ -99,11 +100,7 @@ public void should_filter_certain_sub_folders(string subFolder)
var specialFiles = GetFiles(path, subFolder).ToList(); var specialFiles = GetFiles(path, subFolder).ToList();
var allFiles = files.Concat(specialFiles); var allFiles = files.Concat(specialFiles);
var series = Builder<Movie>.CreateNew() var filteredFiles = Subject.FilterFiles(path, allFiles);
.With(s => s.Path = path)
.Build();
var filteredFiles = Subject.FilterFiles(series, allFiles);
filteredFiles.Should().NotContain(specialFiles); filteredFiles.Should().NotContain(specialFiles);
filteredFiles.Count.Should().BeGreaterThan(0); filteredFiles.Count.Should().BeGreaterThan(0);
} }

View File

@ -1,7 +1,7 @@
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
namespace NzbDrone.Core.DecisionEngine namespace NzbDrone.Core.DecisionEngine
@ -13,13 +13,13 @@ public interface IPrioritizeDownloadDecision
public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision
{ {
private readonly IDelayProfileService _delayProfileService;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly IDelayProfileService _delayProfileService;
public DownloadDecisionPriorizationService(IDelayProfileService delayProfileService, IConfigService configService) public DownloadDecisionPriorizationService(IConfigService configService, IDelayProfileService delayProfileService)
{ {
_delayProfileService = delayProfileService;
_configService = configService; _configService = configService;
_delayProfileService = delayProfileService;
} }
public List<DownloadDecision> PrioritizeDecisionsForMovies(List<DownloadDecision> decisions) public List<DownloadDecision> PrioritizeDecisionsForMovies(List<DownloadDecision> decisions)

View File

@ -21,7 +21,7 @@ public class DiskSpaceService : IDiskSpaceService
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly Logger _logger; private readonly Logger _logger;
private static readonly Regex _regexSpecialDrive = new Regex("^/var/lib/(docker|rancher|kubelet)(/|$)|^/(boot|etc|snap)(/|$)|/docker(/var)?/aufs(/|$)", RegexOptions.Compiled); private static readonly Regex _regexSpecialDrive = new Regex("^/var/lib/(docker|rancher|kubelet)(/|$)|^/(boot|etc)(/|$)|/docker(/var)?/aufs(/|$)", RegexOptions.Compiled);
public DiskSpaceService(IMovieService movieService, IDiskProvider diskProvider, Logger logger) public DiskSpaceService(IMovieService movieService, IDiskProvider diskProvider, Logger logger)
{ {

View File

@ -1,3 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using NLog; using NLog;
using NzbDrone.Common.Cache; using NzbDrone.Common.Cache;
using NzbDrone.Common.Crypto; using NzbDrone.Common.Crypto;
@ -5,11 +10,6 @@
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Organizer; using NzbDrone.Core.Organizer;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.Download.Clients.Blackhole namespace NzbDrone.Core.Download.Clients.Blackhole
{ {
@ -39,7 +39,7 @@ public IEnumerable<WatchFolderItem> GetItems(string watchFolder, TimeSpan waitPe
{ {
var newWatchItems = new Dictionary<string, WatchFolderItem>(); var newWatchItems = new Dictionary<string, WatchFolderItem>();
var lastWatchItems = _watchFolderItemCache.Get(watchFolder, () => newWatchItems); var lastWatchItems = _watchFolderItemCache.Get(watchFolder, () => newWatchItems);
foreach (var newWatchItem in GetDownloadItems(watchFolder, lastWatchItems, waitPeriod)) foreach (var newWatchItem in GetDownloadItems(watchFolder, lastWatchItems, waitPeriod))
{ {
newWatchItems[newWatchItem.DownloadId] = newWatchItem; newWatchItems[newWatchItem.DownloadId] = newWatchItem;
@ -52,8 +52,7 @@ public IEnumerable<WatchFolderItem> GetItems(string watchFolder, TimeSpan waitPe
private IEnumerable<WatchFolderItem> GetDownloadItems(string watchFolder, Dictionary<string, WatchFolderItem> lastWatchItems, TimeSpan waitPeriod) private IEnumerable<WatchFolderItem> GetDownloadItems(string watchFolder, Dictionary<string, WatchFolderItem> lastWatchItems, TimeSpan waitPeriod)
{ {
// get a fresh naming config each time, in case the user has made changes foreach (var folder in _diskScanService.FilterFiles(watchFolder, _diskProvider.GetDirectories(watchFolder)))
foreach (var folder in _diskProvider.GetDirectories(watchFolder))
{ {
var title = FileNameBuilder.CleanFileName(Path.GetFileName(folder)); var title = FileNameBuilder.CleanFileName(Path.GetFileName(folder));
@ -89,7 +88,7 @@ private IEnumerable<WatchFolderItem> GetDownloadItems(string watchFolder, Dictio
yield return newWatchItem; yield return newWatchItem;
} }
foreach (var videoFile in _diskScanService.GetVideoFiles(watchFolder, false)) foreach (var videoFile in _diskScanService.FilterFiles(watchFolder, _diskScanService.GetVideoFiles(watchFolder, false)))
{ {
var title = FileNameBuilder.CleanFileName(Path.GetFileName(videoFile)); var title = FileNameBuilder.CleanFileName(Path.GetFileName(videoFile));

View File

@ -41,7 +41,7 @@ public void Handle(MovieScannedEvent message)
_logger.Debug("Looking for existing extra files in {0}", movie.Path); _logger.Debug("Looking for existing extra files in {0}", movie.Path);
var filesOnDisk = _diskScanService.GetNonVideoFiles(movie.Path); var filesOnDisk = _diskScanService.GetNonVideoFiles(movie.Path);
var possibleExtraFiles = _diskScanService.FilterFiles(movie, filesOnDisk); var possibleExtraFiles = _diskScanService.FilterFiles(movie.Path, filesOnDisk);
var filteredFiles = possibleExtraFiles; var filteredFiles = possibleExtraFiles;
var importedFiles = new List<string>(); var importedFiles = new List<string>();

View File

@ -16,6 +16,7 @@
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Events; using NzbDrone.Core.Movies.Events;
using NzbDrone.Core.RootFolders;
namespace NzbDrone.Core.MediaFiles namespace NzbDrone.Core.MediaFiles
{ {
@ -24,7 +25,7 @@ public interface IDiskScanService
void Scan(Movie movie); void Scan(Movie movie);
string[] GetVideoFiles(string path, bool allDirectories = true); string[] GetVideoFiles(string path, bool allDirectories = true);
string[] GetNonVideoFiles(string path, bool allDirectories = true); string[] GetNonVideoFiles(string path, bool allDirectories = true);
List<string> FilterFiles(Movie movie, IEnumerable<string> files); List<string> FilterFiles(string basePath, IEnumerable<string> files);
} }
public class DiskScanService : public class DiskScanService :
@ -35,9 +36,10 @@ public class DiskScanService :
private readonly IMakeImportDecision _importDecisionMaker; private readonly IMakeImportDecision _importDecisionMaker;
private readonly IImportApprovedMovie _importApprovedMovies; private readonly IImportApprovedMovie _importApprovedMovies;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly IMediaFileTableCleanupService _mediaFileTableCleanupService;
private readonly IEventAggregator _eventAggregator;
private readonly IMovieService _movieService; private readonly IMovieService _movieService;
private readonly IMediaFileTableCleanupService _mediaFileTableCleanupService;
private readonly IRootFolderService _rootFolderService;
private readonly IEventAggregator _eventAggregator;
private readonly IMediaFileService _movieFileRepository; private readonly IMediaFileService _movieFileRepository;
private readonly IRenameMovieFileService _renameMovieFiles; private readonly IRenameMovieFileService _renameMovieFiles;
private readonly Logger _logger; private readonly Logger _logger;
@ -46,9 +48,10 @@ public DiskScanService(IDiskProvider diskProvider,
IMakeImportDecision importDecisionMaker, IMakeImportDecision importDecisionMaker,
IImportApprovedMovie importApprovedMovies, IImportApprovedMovie importApprovedMovies,
IConfigService configService, IConfigService configService,
IMediaFileTableCleanupService mediaFileTableCleanupService,
IEventAggregator eventAggregator,
IMovieService movieService, IMovieService movieService,
IMediaFileTableCleanupService mediaFileTableCleanupService,
IRootFolderService rootFolderService,
IEventAggregator eventAggregator,
IMediaFileService movieFileRepository, IMediaFileService movieFileRepository,
IRenameMovieFileService renameMovieFiles, IRenameMovieFileService renameMovieFiles,
Logger logger) Logger logger)
@ -57,23 +60,21 @@ public DiskScanService(IDiskProvider diskProvider,
_importDecisionMaker = importDecisionMaker; _importDecisionMaker = importDecisionMaker;
_importApprovedMovies = importApprovedMovies; _importApprovedMovies = importApprovedMovies;
_configService = configService; _configService = configService;
_mediaFileTableCleanupService = mediaFileTableCleanupService;
_eventAggregator = eventAggregator;
_movieService = movieService; _movieService = movieService;
_mediaFileTableCleanupService = mediaFileTableCleanupService;
_rootFolderService = rootFolderService;
_eventAggregator = eventAggregator;
_movieFileRepository = movieFileRepository; _movieFileRepository = movieFileRepository;
_renameMovieFiles = renameMovieFiles; _renameMovieFiles = renameMovieFiles;
_logger = logger; _logger = logger;
} }
private static readonly Regex ExcludedSubFoldersRegex = new Regex(@"(?:\\|\/|^)(extras|@eadir|extrafanart|plex\sversions|\..+)(?:\\|\/)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ExcludedSubFoldersRegex = new Regex(@"(?:\\|\/|^)(?:extras|@eadir|extrafanart|plex versions|\.[^\\/]+)(?:\\|\/)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex ExcludedFilesRegex = new Regex(@"^\._|Thumbs\.db", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ExcludedFilesRegex = new Regex(@"^\._|^Thumbs\.db$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public void Scan(Movie movie) public void Scan(Movie movie)
{ {
//Try renaming the movie path in case anything changed such as year, title or something else. var rootFolder = _rootFolderService.GetBestRootFolderPath(movie.Path);
_renameMovieFiles.RenameMoviePath(movie, true);
var rootFolder = _diskProvider.GetParentFolder(movie.Path);
if (!_diskProvider.FolderExists(rootFolder)) if (!_diskProvider.FolderExists(rootFolder))
{ {
@ -93,17 +94,9 @@ public void Scan(Movie movie)
if (!_diskProvider.FolderExists(movie.Path)) if (!_diskProvider.FolderExists(movie.Path))
{ {
if (movie.MovieFileId != 0) if (_configService.CreateEmptyMovieFolders)
{ {
//Since there is no folder, there can't be any files right? _logger.Debug("Creating missing movie folder: {0}", movie.Path);
_mediaFileTableCleanupService.Clean(movie, new List<string>());
_logger.Debug("Movies folder doesn't exist: {0}", movie.Path);
}
else if (_configService.CreateEmptyMovieFolders &&
_diskProvider.FolderExists(rootFolder))
{
_logger.Debug("Creating missing movies folder: {0}", movie.Path);
_diskProvider.CreateFolder(movie.Path); _diskProvider.CreateFolder(movie.Path);
SetPermissions(movie.Path); SetPermissions(movie.Path);
} }
@ -112,28 +105,37 @@ public void Scan(Movie movie)
_logger.Debug("Movies folder doesn't exist: {0}", movie.Path); _logger.Debug("Movies folder doesn't exist: {0}", movie.Path);
} }
_eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.MovieFolderDoesNotExist)); CleanMediaFiles(movie, new List<string>());
CompletedScanning(movie);
return; return;
} }
var videoFilesStopwatch = Stopwatch.StartNew(); var videoFilesStopwatch = Stopwatch.StartNew();
var mediaFileList = FilterFiles(movie, GetVideoFiles(movie.Path)).ToList(); var mediaFileList = FilterFiles(movie.Path, GetVideoFiles(movie.Path)).ToList();
videoFilesStopwatch.Stop(); videoFilesStopwatch.Stop();
_logger.Trace("Finished getting movie files for: {0} [{1}]", movie, videoFilesStopwatch.Elapsed); _logger.Trace("Finished getting movie files for: {0} [{1}]", movie, videoFilesStopwatch.Elapsed);
_logger.Debug("{0} Cleaning up media files in DB", movie); CleanMediaFiles(movie, mediaFileList);
_mediaFileTableCleanupService.Clean(movie, mediaFileList);
var decisionsStopwatch = Stopwatch.StartNew(); var decisionsStopwatch = Stopwatch.StartNew();
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie, true); var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie, true);
decisionsStopwatch.Stop(); decisionsStopwatch.Stop();
_logger.Trace("Import decisions complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed); _logger.Trace("Import decisions complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed);
_importApprovedMovies.Import(decisions, false); _importApprovedMovies.Import(decisions, false);
RemoveEmptyMovieFolder(movie.Path); RemoveEmptyMovieFolder(movie.Path);
CompletedScanning(movie);
}
private void CleanMediaFiles(Movie movie, List<string> mediaFileList)
{
_logger.Debug("{0} Cleaning up media files in DB", movie);
_mediaFileTableCleanupService.Clean(movie, mediaFileList);
}
private void CompletedScanning(Movie movie)
{
_logger.Info("Completed scanning disk for {0}", movie.Title); _logger.Info("Completed scanning disk for {0}", movie.Title);
_eventAggregator.PublishEvent(new MovieScannedEvent(movie)); _eventAggregator.PublishEvent(new MovieScannedEvent(movie));
} }
@ -143,12 +145,14 @@ public string[] GetVideoFiles(string path, bool allDirectories = true)
_logger.Debug("Scanning '{0}' for video files", path); _logger.Debug("Scanning '{0}' for video files", path);
var searchOption = allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; var searchOption = allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
var filesOnDisk = _diskProvider.GetFiles(path, searchOption); var filesOnDisk = _diskProvider.GetFiles(path, searchOption).ToList();
var mediaFileList = filesOnDisk.Where(file => MediaFileExtensions.Extensions.Contains(Path.GetExtension(file))) var mediaFileList = filesOnDisk.Where(file => MediaFileExtensions.Extensions.Contains(Path.GetExtension(file)))
.ToList(); .ToList();
_logger.Trace("{0} files were found in {1}", filesOnDisk.Count, path);
_logger.Debug("{0} video files were found in {1}", mediaFileList.Count, path); _logger.Debug("{0} video files were found in {1}", mediaFileList.Count, path);
return mediaFileList.ToArray(); return mediaFileList.ToArray();
} }
@ -157,18 +161,20 @@ public string[] GetNonVideoFiles(string path, bool allDirectories = true)
_logger.Debug("Scanning '{0}' for non-video files", path); _logger.Debug("Scanning '{0}' for non-video files", path);
var searchOption = allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; var searchOption = allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
var filesOnDisk = _diskProvider.GetFiles(path, searchOption); var filesOnDisk = _diskProvider.GetFiles(path, searchOption).ToList();
var mediaFileList = filesOnDisk.Where(file => !MediaFileExtensions.Extensions.Contains(Path.GetExtension(file))) var mediaFileList = filesOnDisk.Where(file => !MediaFileExtensions.Extensions.Contains(Path.GetExtension(file)))
.ToList(); .ToList();
_logger.Trace("{0} files were found in {1}", filesOnDisk.Count, path);
_logger.Debug("{0} non-video files were found in {1}", mediaFileList.Count, path); _logger.Debug("{0} non-video files were found in {1}", mediaFileList.Count, path);
return mediaFileList.ToArray(); return mediaFileList.ToArray();
} }
public List<string> FilterFiles(Movie movie, IEnumerable<string> files) public List<string> FilterFiles(string basePath, IEnumerable<string> files)
{ {
return files.Where(file => !ExcludedSubFoldersRegex.IsMatch(movie.Path.GetRelativePath(file))) return files.Where(file => !ExcludedSubFoldersRegex.IsMatch(basePath.GetRelativePath(file)))
.Where(file => !ExcludedFilesRegex.IsMatch(Path.GetFileName(file))) .Where(file => !ExcludedFilesRegex.IsMatch(Path.GetFileName(file)))
.ToList(); .ToList();
} }
@ -196,20 +202,17 @@ private void SetPermissions(string path)
private void RemoveEmptyMovieFolder(string path) private void RemoveEmptyMovieFolder(string path)
{ {
if (_diskProvider.GetFiles(path, SearchOption.AllDirectories).Empty() && if (_configService.DeleteEmptyFolders)
!_configService.CreateEmptyMovieFolders) {
if (_configService.DeleteEmptyFolders) if (_diskProvider.GetFiles(path, SearchOption.AllDirectories).Empty())
{ {
_diskProvider.DeleteFolder(path, true); _diskProvider.DeleteFolder(path, true);
if (_diskProvider.GetFiles(path, SearchOption.AllDirectories).Empty())
{
_diskProvider.DeleteFolder(path, true);
}
else
{
_diskProvider.RemoveEmptySubfolders(path);
}
} }
else
{
_diskProvider.RemoveEmptySubfolders(path);
}
}
} }
public void Execute(RescanMovieCommand message) public void Execute(RescanMovieCommand message)
@ -219,6 +222,7 @@ public void Execute(RescanMovieCommand message)
var movie = _movieService.GetMovie(message.MovieId.Value); var movie = _movieService.GetMovie(message.MovieId.Value);
Scan(movie); Scan(movie);
} }
else else
{ {
var allMovies = _movieService.GetAllMovies(); var allMovies = _movieService.GetAllMovies();

View File

@ -182,7 +182,7 @@ private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode
_logger.Debug("{0} folder quality: {1}", cleanedUpName, folderInfo.Quality); _logger.Debug("{0} folder quality: {1}", cleanedUpName, folderInfo.Quality);
} }
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName); var videoFiles = _diskScanService.FilterFiles(directoryInfo.FullName, _diskScanService.GetVideoFiles(directoryInfo.FullName));
if (downloadClientItem == null) if (downloadClientItem == null)
{ {

View File

@ -116,7 +116,7 @@ private List<ManualImportItem> ProcessFolder(string folder, string downloadId, b
if (movie == null) if (movie == null)
{ {
var files = _diskScanService.GetVideoFiles(folder); var files = _diskScanService.FilterFiles(folder, _diskScanService.GetVideoFiles(folder));
return files.Select(file => ProcessFile(file, downloadId, folder)).Where(i => i != null).ToList(); return files.Select(file => ProcessFile(file, downloadId, folder)).Where(i => i != null).ToList();
} }

View File

@ -84,11 +84,15 @@ public Movie GetMovieInfo(int TmdbId, Profile profile = null, bool hasPreDBEntry
// The dude abides, so should us, Lets be nice to TMDb // The dude abides, so should us, Lets be nice to TMDb
// var allowed = int.Parse(response.Headers.GetValues("X-RateLimit-Limit").First()); // get allowed // var allowed = int.Parse(response.Headers.GetValues("X-RateLimit-Limit").First()); // get allowed
// var reset = long.Parse(response.Headers.GetValues("X-RateLimit-Reset").First()); // get time when it resets // var reset = long.Parse(response.Headers.GetValues("X-RateLimit-Reset").First()); // get time when it resets
var remaining = int.Parse(response.Headers.GetValues("X-RateLimit-Remaining").First());
if (remaining <= 5) if (response.Headers.ContainsKey("X-RateLimit-Remaining"))
{ {
_logger.Trace("Waiting 5 seconds to get information for the next 35 movies"); var remaining = int.Parse(response.Headers.GetValues("X-RateLimit-Remaining").First());
Thread.Sleep(5000); if (remaining <= 5)
{
_logger.Trace("Waiting 5 seconds to get information for the next 35 movies");
Thread.Sleep(5000);
}
} }
var resource = response.Resource; var resource = response.Resource;
@ -295,11 +299,14 @@ public Movie GetMovieInfo(string imdbId)
// The dude abides, so should us, Lets be nice to TMDb // The dude abides, so should us, Lets be nice to TMDb
// var allowed = int.Parse(response.Headers.GetValues("X-RateLimit-Limit").First()); // get allowed // var allowed = int.Parse(response.Headers.GetValues("X-RateLimit-Limit").First()); // get allowed
// var reset = long.Parse(response.Headers.GetValues("X-RateLimit-Reset").First()); // get time when it resets // var reset = long.Parse(response.Headers.GetValues("X-RateLimit-Reset").First()); // get time when it resets
var remaining = int.Parse(response.Headers.GetValues("X-RateLimit-Remaining").First()); if (response.Headers.ContainsKey("X-RateLimit-Remaining"))
if (remaining <= 5)
{ {
_logger.Trace("Waiting 5 seconds to get information for the next 35 movies"); var remaining = int.Parse(response.Headers.GetValues("X-RateLimit-Remaining").First());
Thread.Sleep(5000); if (remaining <= 5)
{
_logger.Trace("Waiting 5 seconds to get information for the next 35 movies");
Thread.Sleep(5000);
}
} }
var resources = response.Resource; var resources = response.Resource;