mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-11 03:52:33 +02:00
Merge branch 'blackhole-delay' into develop
This commit is contained in:
commit
19b8fb6d8b
@ -10,12 +10,16 @@ public static class HashConverter
|
||||
|
||||
public static int GetHashInt31(string target)
|
||||
{
|
||||
byte[] hash;
|
||||
var hash = GetHash(target);
|
||||
return BitConverter.ToInt32(hash, 0) & 0x7fffffff;
|
||||
}
|
||||
|
||||
public static byte[] GetHash(string target)
|
||||
{
|
||||
lock (Sha1)
|
||||
{
|
||||
hash = Sha1.ComputeHash(Encoding.Default.GetBytes(target));
|
||||
return Sha1.ComputeHash(Encoding.Default.GetBytes(target));
|
||||
}
|
||||
return BitConverter.ToInt32(hash, 0) & 0x7fffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,5 +100,10 @@ public static byte[] HexToByteArray(this string input)
|
||||
.Select(x => Convert.ToByte(input.Substring(x, 2), 16))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static string ToHexString(this byte[] input)
|
||||
{
|
||||
return string.Concat(Array.ConvertAll(input, x => x.ToString("X2")));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Test.Common;
|
||||
using System.Threading;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Download.Clients.Blackhole;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
|
||||
{
|
||||
[TestFixture]
|
||||
public class ScanWatchFolderFixture : CoreTest<ScanWatchFolder>
|
||||
{
|
||||
protected readonly string _title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE";
|
||||
protected string _completedDownloadFolder = @"c:\blackhole\completed".AsOsAgnostic();
|
||||
|
||||
protected void GivenCompletedItem()
|
||||
{
|
||||
var targetDir = Path.Combine(_completedDownloadFolder, _title);
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetDirectories(_completedDownloadFolder))
|
||||
.Returns(new[] { targetDir });
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
||||
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||
.Returns(1000000);
|
||||
}
|
||||
|
||||
protected void GivenChangedItem()
|
||||
{
|
||||
var currentSize = Mocker.GetMock<IDiskProvider>().Object.GetFileSize("abc");
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||
.Returns(currentSize + 1);
|
||||
}
|
||||
|
||||
private void VerifySingleItem(DownloadItemStatus status)
|
||||
{
|
||||
var items = Subject.GetItems(_completedDownloadFolder, TimeSpan.FromMilliseconds(50)).ToList();
|
||||
|
||||
items.Count.Should().Be(1);
|
||||
items.First().Status.Should().Be(status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_considered_locked_files_queued()
|
||||
{
|
||||
GivenCompletedItem();
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.IsFileLocked(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
Thread.Sleep(60);
|
||||
|
||||
VerifySingleItem(DownloadItemStatus.Downloading);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_considered_changing_files_queued()
|
||||
{
|
||||
GivenCompletedItem();
|
||||
|
||||
VerifySingleItem(DownloadItemStatus.Downloading);
|
||||
|
||||
// If we keep changing the file every 20ms we should stay Downloading.
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
TestLogger.Info("Iteration {0}", i);
|
||||
|
||||
GivenChangedItem();
|
||||
|
||||
VerifySingleItem(DownloadItemStatus.Downloading);
|
||||
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
|
||||
// Until it remains unchanged for >=50ms.
|
||||
Thread.Sleep(60);
|
||||
|
||||
VerifySingleItem(DownloadItemStatus.Completed);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients.TorrentBlackhole;
|
||||
using NzbDrone.Core.Download.Clients.Blackhole;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
using NzbDrone.Core.MediaFiles.TorrentInfo;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
@ -30,6 +30,8 @@ public void Setup()
|
||||
_blackholeFolder = @"c:\blackhole\torrent".AsOsAgnostic();
|
||||
_filePath = (@"c:\blackhole\torrent\" + _title + ".torrent").AsOsAgnostic();
|
||||
|
||||
Mocker.SetConstant<IScanWatchFolder>(Mocker.Resolve<ScanWatchFolder>());
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new TorrentBlackholeSettings
|
||||
{
|
||||
@ -56,13 +58,14 @@ protected void GivenFailedDownload()
|
||||
protected void GivenCompletedItem()
|
||||
{
|
||||
var targetDir = Path.Combine(_completedDownloadFolder, _title);
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetDirectories(_completedDownloadFolder))
|
||||
.Returns(new[] { targetDir });
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
||||
.Returns(new[] { Path.Combine(_completedDownloadFolder, "somefile.mkv") });
|
||||
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||
@ -87,6 +90,8 @@ protected override RemoteEpisode CreateRemoteEpisode()
|
||||
[Test]
|
||||
public void completed_download_should_have_required_properties()
|
||||
{
|
||||
Subject.ScanGracePeriod = TimeSpan.Zero;
|
||||
|
||||
GivenCompletedItem();
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
@ -94,6 +99,16 @@ public void completed_download_should_have_required_properties()
|
||||
VerifyCompleted(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void partial_download_should_have_required_properties()
|
||||
{
|
||||
GivenCompletedItem();
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyPostprocessing(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_category()
|
||||
{
|
||||
@ -142,21 +157,6 @@ public void Download_should_throw_if_magnet_and_torrent_url_does_not_exist()
|
||||
Assert.Throws<ReleaseDownloadException>(() => Subject.Download(remoteEpisode));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_considered_locked_files_queued()
|
||||
{
|
||||
GivenCompletedItem();
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.IsFileLocked(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
var items = Subject.GetItems().ToList();
|
||||
|
||||
items.Count.Should().Be(1);
|
||||
items.First().Status.Should().Be(DownloadItemStatus.Downloading);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveItem_should_delete_file()
|
||||
{
|
||||
|
@ -9,7 +9,7 @@
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients.UsenetBlackhole;
|
||||
using NzbDrone.Core.Download.Clients.Blackhole;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
|
||||
@ -29,6 +29,8 @@ public void Setup()
|
||||
_blackholeFolder = @"c:\blackhole\nzb".AsOsAgnostic();
|
||||
_filePath = (@"c:\blackhole\nzb\" + _title + ".nzb").AsOsAgnostic();
|
||||
|
||||
Mocker.SetConstant<IScanWatchFolder>(Mocker.Resolve<ScanWatchFolder>());
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new UsenetBlackholeSettings
|
||||
{
|
||||
@ -58,7 +60,7 @@ protected void GivenCompletedItem()
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
||||
.Returns(new[] { Path.Combine(_completedDownloadFolder, "somefile.mkv") });
|
||||
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||
@ -68,6 +70,8 @@ protected void GivenCompletedItem()
|
||||
[Test]
|
||||
public void completed_download_should_have_required_properties()
|
||||
{
|
||||
Subject.ScanGracePeriod = TimeSpan.Zero;
|
||||
|
||||
GivenCompletedItem();
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
@ -75,6 +79,17 @@ public void completed_download_should_have_required_properties()
|
||||
VerifyCompleted(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void partial_download_should_have_required_properties()
|
||||
{
|
||||
GivenCompletedItem();
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyPostprocessing(result);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_return_category()
|
||||
{
|
||||
@ -114,20 +129,6 @@ public void Download_should_replace_illegal_characters_in_title()
|
||||
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_considered_locked_files_downloading()
|
||||
{
|
||||
GivenCompletedItem();
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(c => c.IsFileLocked(It.IsAny<string>()))
|
||||
.Returns(true);
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
result.Status.Should().Be(DownloadItemStatus.Downloading);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveItem_should_delete_file()
|
||||
{
|
||||
|
@ -96,6 +96,15 @@ protected void VerifyDownloading(DownloadClientItem downloadClientItem)
|
||||
downloadClientItem.Status.Should().Be(DownloadItemStatus.Downloading);
|
||||
}
|
||||
|
||||
protected void VerifyPostprocessing(DownloadClientItem downloadClientItem)
|
||||
{
|
||||
VerifyIdentifiable(downloadClientItem);
|
||||
|
||||
//downloadClientItem.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
//downloadClientItem.OutputPath.Should().NotBeNullOrEmpty();
|
||||
downloadClientItem.Status.Should().Be(DownloadItemStatus.Downloading);
|
||||
}
|
||||
|
||||
protected void VerifyCompleted(DownloadClientItem downloadClientItem)
|
||||
{
|
||||
VerifyIdentifiable(downloadClientItem);
|
||||
|
@ -23,8 +23,6 @@ public class TorrentRssIndexerFixture : CoreTest<TestTorrentRssIndexer>
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Mocker.SetConstant<IHttpClient>(Mocker.GetMock<IHttpClient>().Object);
|
||||
Mocker.SetConstant<ICacheManager>(Mocker.Resolve<CacheManager>());
|
||||
Mocker.SetConstant<ITorrentRssSettingsDetector>(Mocker.Resolve<TorrentRssSettingsDetector>());
|
||||
Mocker.SetConstant<ITorrentRssParserFactory>(Mocker.Resolve<TorrentRssParserFactory>());
|
||||
|
||||
|
@ -158,6 +158,7 @@
|
||||
<Compile Include="DecisionEngineTests\UpgradeDiskSpecificationFixture.cs" />
|
||||
<Compile Include="Download\CompletedDownloadServiceFixture.cs" />
|
||||
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\Blackhole\ScanWatchFolderFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\Blackhole\TorrentBlackholeFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\DelugeTests\DelugeFixture.cs" />
|
||||
|
196
src/NzbDrone.Core/Download/Clients/Blackhole/ScanWatchFolder.cs
Normal file
196
src/NzbDrone.Core/Download/Clients/Blackhole/ScanWatchFolder.cs
Normal file
@ -0,0 +1,196 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Crypto;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
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
|
||||
{
|
||||
public interface IScanWatchFolder
|
||||
{
|
||||
IEnumerable<WatchFolderItem> GetItems(string watchFolder, TimeSpan waitPeriod);
|
||||
}
|
||||
|
||||
public class ScanWatchFolder : IScanWatchFolder
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
private readonly ICached<Dictionary<string, WatchFolderItem>> _watchFolderItemCache;
|
||||
|
||||
public ScanWatchFolder(ICacheManager cacheManager, IDiskScanService diskScanService, IDiskProvider diskProvider, Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_diskProvider = diskProvider;
|
||||
_diskScanService = diskScanService;
|
||||
_watchFolderItemCache = cacheManager.GetCache<Dictionary<string, WatchFolderItem>>(GetType());
|
||||
}
|
||||
|
||||
public IEnumerable<WatchFolderItem> GetItems(string watchFolder, TimeSpan waitPeriod)
|
||||
{
|
||||
var newWatchItems = new Dictionary<string, WatchFolderItem>();
|
||||
var lastWatchItems = _watchFolderItemCache.Get(watchFolder, () => newWatchItems);
|
||||
|
||||
foreach (var newWatchItem in GetDownloadItems(watchFolder, lastWatchItems, waitPeriod))
|
||||
{
|
||||
newWatchItems[newWatchItem.DownloadId] = newWatchItem;
|
||||
}
|
||||
|
||||
_watchFolderItemCache.Set(watchFolder, newWatchItems, TimeSpan.FromMinutes(5));
|
||||
|
||||
return newWatchItems.Values;
|
||||
}
|
||||
|
||||
private IEnumerable<WatchFolderItem> GetDownloadItems(string watchFolder, Dictionary<string, WatchFolderItem> lastWatchItems, TimeSpan waitPeriod)
|
||||
{
|
||||
foreach (var folder in _diskProvider.GetDirectories(watchFolder))
|
||||
{
|
||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(folder));
|
||||
|
||||
var newWatchItem = new WatchFolderItem
|
||||
{
|
||||
DownloadId = Path.GetFileName(folder) + "_" + _diskProvider.FolderGetCreationTime(folder).Ticks,
|
||||
Title = title,
|
||||
|
||||
OutputPath = new OsPath(folder),
|
||||
|
||||
Status = DownloadItemStatus.Completed,
|
||||
RemainingTime = TimeSpan.Zero
|
||||
};
|
||||
|
||||
var oldWatchItem = lastWatchItems.GetValueOrDefault(newWatchItem.DownloadId);
|
||||
|
||||
if (PreCheckWatchItemExpiry(newWatchItem, oldWatchItem))
|
||||
{
|
||||
var files = _diskProvider.GetFiles(folder, SearchOption.AllDirectories);
|
||||
|
||||
newWatchItem.TotalSize = files.Select(_diskProvider.GetFileSize).Sum();
|
||||
newWatchItem.Hash = GetHash(folder, files);
|
||||
|
||||
if (files.Any(_diskProvider.IsFileLocked))
|
||||
{
|
||||
newWatchItem.Status = DownloadItemStatus.Downloading;
|
||||
newWatchItem.RemainingTime = null;
|
||||
}
|
||||
|
||||
UpdateWatchItemExpiry(newWatchItem, oldWatchItem, waitPeriod);
|
||||
}
|
||||
|
||||
yield return newWatchItem;
|
||||
}
|
||||
|
||||
foreach (var videoFile in _diskScanService.GetVideoFiles(watchFolder, false))
|
||||
{
|
||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(videoFile));
|
||||
|
||||
var newWatchItem = new WatchFolderItem
|
||||
{
|
||||
DownloadId = Path.GetFileName(videoFile) + "_" + _diskProvider.FileGetLastWrite(videoFile).Ticks,
|
||||
Title = title,
|
||||
|
||||
OutputPath = new OsPath(videoFile),
|
||||
|
||||
Status = DownloadItemStatus.Completed,
|
||||
RemainingTime = TimeSpan.Zero
|
||||
};
|
||||
|
||||
var oldWatchItem = lastWatchItems.GetValueOrDefault(newWatchItem.DownloadId);
|
||||
|
||||
if (PreCheckWatchItemExpiry(oldWatchItem, newWatchItem))
|
||||
{
|
||||
newWatchItem.TotalSize = _diskProvider.GetFileSize(videoFile);
|
||||
newWatchItem.Hash = GetHash(videoFile);
|
||||
|
||||
if (_diskProvider.IsFileLocked(videoFile))
|
||||
{
|
||||
newWatchItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
|
||||
UpdateWatchItemExpiry(newWatchItem, oldWatchItem, waitPeriod);
|
||||
}
|
||||
|
||||
yield return newWatchItem;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool PreCheckWatchItemExpiry(WatchFolderItem newWatchItem, WatchFolderItem oldWatchItem)
|
||||
{
|
||||
if (oldWatchItem == null || oldWatchItem.LastChanged.AddHours(1) > DateTime.UtcNow)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
newWatchItem.TotalSize = oldWatchItem.TotalSize;
|
||||
newWatchItem.Hash = oldWatchItem.Hash;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void UpdateWatchItemExpiry(WatchFolderItem newWatchItem, WatchFolderItem oldWatchItem, TimeSpan waitPeriod)
|
||||
{
|
||||
if (oldWatchItem != null && newWatchItem.Hash == oldWatchItem.Hash)
|
||||
{
|
||||
newWatchItem.LastChanged = oldWatchItem.LastChanged;
|
||||
}
|
||||
else
|
||||
{
|
||||
newWatchItem.LastChanged = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
var remainingTime = waitPeriod - (DateTime.UtcNow - newWatchItem.LastChanged);
|
||||
|
||||
if (remainingTime > TimeSpan.Zero)
|
||||
{
|
||||
newWatchItem.RemainingTime = remainingTime;
|
||||
newWatchItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetHash(string folder, string[] files)
|
||||
{
|
||||
var data = new StringBuilder();
|
||||
|
||||
data.Append(folder);
|
||||
try
|
||||
{
|
||||
data.Append(_diskProvider.FolderGetLastWrite(folder).ToBinary());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.TraceException(string.Format("Ignored hashing error during scan for {0}", folder), ex);
|
||||
}
|
||||
|
||||
foreach (var file in files.OrderBy(v => v))
|
||||
{
|
||||
data.Append(GetHash(file));
|
||||
}
|
||||
|
||||
return HashConverter.GetHash(data.ToString()).ToHexString();
|
||||
}
|
||||
|
||||
private string GetHash(string file)
|
||||
{
|
||||
var data = new StringBuilder();
|
||||
|
||||
data.Append(file);
|
||||
try
|
||||
{
|
||||
data.Append(_diskProvider.FileGetLastWrite(file).ToBinary());
|
||||
data.Append(_diskProvider.GetFileSize(file));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.TraceException(string.Format("Ignored hashing error during scan for {0}", file), ex);
|
||||
}
|
||||
|
||||
return HashConverter.GetHash(data.ToString()).ToHexString();
|
||||
}
|
||||
}
|
||||
}
|
@ -15,13 +15,15 @@
|
||||
using NzbDrone.Core.RemotePathMappings;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.TorrentBlackhole
|
||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
{
|
||||
public class TorrentBlackhole : TorrentClientBase<TorrentBlackholeSettings>
|
||||
{
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
private readonly IScanWatchFolder _scanWatchFolder;
|
||||
|
||||
public TorrentBlackhole(IDiskScanService diskScanService,
|
||||
public TimeSpan ScanGracePeriod { get; set; }
|
||||
|
||||
public TorrentBlackhole(IScanWatchFolder scanWatchFolder,
|
||||
ITorrentFileInfoReader torrentFileInfoReader,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
@ -30,7 +32,9 @@ public TorrentBlackhole(IDiskScanService diskScanService,
|
||||
Logger logger)
|
||||
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger)
|
||||
{
|
||||
_diskScanService = diskScanService;
|
||||
_scanWatchFolder = scanWatchFolder;
|
||||
|
||||
ScanGracePeriod = TimeSpan.FromSeconds(30);
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
||||
@ -72,71 +76,28 @@ public override ProviderMessage Message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
{
|
||||
foreach (var folder in _diskProvider.GetDirectories(Settings.WatchFolder))
|
||||
foreach (var item in _scanWatchFolder.GetItems(Settings.WatchFolder, ScanGracePeriod))
|
||||
{
|
||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(folder));
|
||||
|
||||
var files = _diskProvider.GetFiles(folder, SearchOption.AllDirectories);
|
||||
|
||||
var historyItem = new DownloadClientItem
|
||||
yield return new DownloadClientItem
|
||||
{
|
||||
DownloadClient = Definition.Name,
|
||||
DownloadId = Definition.Name + "_" + Path.GetFileName(folder) + "_" + _diskProvider.FolderGetCreationTime(folder).Ticks,
|
||||
DownloadId = Definition.Name + "_" + item.DownloadId,
|
||||
Category = "sonarr",
|
||||
Title = title,
|
||||
Title = item.Title,
|
||||
|
||||
TotalSize = files.Select(_diskProvider.GetFileSize).Sum(),
|
||||
TotalSize = item.TotalSize,
|
||||
RemainingTime = item.RemainingTime,
|
||||
|
||||
OutputPath = new OsPath(folder)
|
||||
OutputPath = item.OutputPath,
|
||||
|
||||
Status = item.Status,
|
||||
|
||||
IsReadOnly = Settings.ReadOnly
|
||||
};
|
||||
|
||||
if (files.Any(_diskProvider.IsFileLocked))
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
else
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
|
||||
historyItem.RemainingTime = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
historyItem.IsReadOnly = Settings.ReadOnly;
|
||||
|
||||
yield return historyItem;
|
||||
}
|
||||
|
||||
foreach (var videoFile in _diskScanService.GetVideoFiles(Settings.WatchFolder, false))
|
||||
{
|
||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(videoFile));
|
||||
|
||||
var historyItem = new DownloadClientItem
|
||||
{
|
||||
DownloadClient = Definition.Name,
|
||||
DownloadId = Definition.Name + "_" + Path.GetFileName(videoFile) + "_" + _diskProvider.FileGetLastWrite(videoFile).Ticks,
|
||||
Category = "sonarr",
|
||||
Title = title,
|
||||
|
||||
TotalSize = _diskProvider.GetFileSize(videoFile),
|
||||
|
||||
OutputPath = new OsPath(videoFile)
|
||||
};
|
||||
|
||||
if (_diskProvider.IsFileLocked(videoFile))
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
else
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
historyItem.RemainingTime = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
historyItem.IsReadOnly = Settings.ReadOnly;
|
||||
|
||||
yield return historyItem;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.TorrentBlackhole
|
||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
{
|
||||
public class TorrentBlackholeSettingsValidator : AbstractValidator<TorrentBlackholeSettings>
|
||||
{
|
@ -13,13 +13,15 @@
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.RemotePathMappings;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
|
||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
{
|
||||
public class UsenetBlackhole : UsenetClientBase<UsenetBlackholeSettings>
|
||||
{
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
private readonly IScanWatchFolder _scanWatchFolder;
|
||||
|
||||
public UsenetBlackhole(IDiskScanService diskScanService,
|
||||
public TimeSpan ScanGracePeriod { get; set; }
|
||||
|
||||
public UsenetBlackhole(IScanWatchFolder scanWatchFolder,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IDiskProvider diskProvider,
|
||||
@ -27,7 +29,9 @@ public UsenetBlackhole(IDiskScanService diskScanService,
|
||||
Logger logger)
|
||||
: base(httpClient, configService, diskProvider, remotePathMappingService, logger)
|
||||
{
|
||||
_diskScanService = diskScanService;
|
||||
_scanWatchFolder = scanWatchFolder;
|
||||
|
||||
ScanGracePeriod = TimeSpan.FromSeconds(30);
|
||||
}
|
||||
|
||||
protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContent)
|
||||
@ -58,65 +62,22 @@ public override string Name
|
||||
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
{
|
||||
foreach (var folder in _diskProvider.GetDirectories(Settings.WatchFolder))
|
||||
foreach (var item in _scanWatchFolder.GetItems(Settings.WatchFolder, ScanGracePeriod))
|
||||
{
|
||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(folder));
|
||||
|
||||
var files = _diskProvider.GetFiles(folder, SearchOption.AllDirectories);
|
||||
|
||||
var historyItem = new DownloadClientItem
|
||||
yield return new DownloadClientItem
|
||||
{
|
||||
DownloadClient = Definition.Name,
|
||||
DownloadId = Definition.Name + "_" + Path.GetFileName(folder) + "_" + _diskProvider.FolderGetCreationTime(folder).Ticks,
|
||||
DownloadId = Definition.Name + "_" + item.DownloadId,
|
||||
Category = "sonarr",
|
||||
Title = title,
|
||||
Title = item.Title,
|
||||
|
||||
TotalSize = files.Select(_diskProvider.GetFileSize).Sum(),
|
||||
TotalSize = item.TotalSize,
|
||||
RemainingTime = item.RemainingTime,
|
||||
|
||||
OutputPath = new OsPath(folder)
|
||||
OutputPath = item.OutputPath,
|
||||
|
||||
Status = item.Status
|
||||
};
|
||||
|
||||
if (files.Any(_diskProvider.IsFileLocked))
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
else
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
|
||||
historyItem.RemainingTime = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
yield return historyItem;
|
||||
}
|
||||
|
||||
foreach (var videoFile in _diskScanService.GetVideoFiles(Settings.WatchFolder, false))
|
||||
{
|
||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(videoFile));
|
||||
|
||||
var historyItem = new DownloadClientItem
|
||||
{
|
||||
DownloadClient = Definition.Name,
|
||||
DownloadId = Definition.Name + "_" + Path.GetFileName(videoFile) + "_" + _diskProvider.FileGetLastWrite(videoFile).Ticks,
|
||||
Category = "sonarr",
|
||||
Title = title,
|
||||
|
||||
TotalSize = _diskProvider.GetFileSize(videoFile),
|
||||
|
||||
OutputPath = new OsPath(videoFile)
|
||||
};
|
||||
|
||||
if (_diskProvider.IsFileLocked(videoFile))
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Downloading;
|
||||
}
|
||||
else
|
||||
{
|
||||
historyItem.Status = DownloadItemStatus.Completed;
|
||||
historyItem.RemainingTime = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
yield return historyItem;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
|
||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
{
|
||||
public class UsenetBlackholeSettingsValidator : AbstractValidator<UsenetBlackholeSettings>
|
||||
{
|
@ -0,0 +1,22 @@
|
||||
using NzbDrone.Common.Disk;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||
{
|
||||
|
||||
public class WatchFolderItem
|
||||
{
|
||||
public string DownloadId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public long TotalSize { get; set; }
|
||||
public TimeSpan? RemainingTime { get; set; }
|
||||
public OsPath OutputPath { get; set; }
|
||||
public DownloadItemStatus Status { get; set; }
|
||||
|
||||
public DateTime LastChanged { get; set; }
|
||||
public string Hash { get; set; }
|
||||
}
|
||||
}
|
@ -332,6 +332,8 @@
|
||||
<Compile Include="DiskSpace\DiskSpace.cs" />
|
||||
<Compile Include="DiskSpace\DiskSpaceService.cs" />
|
||||
<Compile Include="Download\CheckForFinishedDownloadCommand.cs" />
|
||||
<Compile Include="Download\Clients\Blackhole\ScanWatchFolder.cs" />
|
||||
<Compile Include="Download\Clients\Blackhole\WatchFolderItem.cs" />
|
||||
<Compile Include="Download\Clients\Deluge\Deluge.cs" />
|
||||
<Compile Include="Download\Clients\Deluge\DelugeError.cs" />
|
||||
<Compile Include="Download\Clients\Deluge\DelugeException.cs" />
|
||||
@ -411,8 +413,8 @@
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdQueue.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdQueueItem.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdSettings.cs" />
|
||||
<Compile Include="Download\Clients\TorrentBlackhole\TorrentBlackhole.cs" />
|
||||
<Compile Include="Download\Clients\TorrentBlackhole\TorrentBlackholeSettings.cs" />
|
||||
<Compile Include="Download\Clients\Blackhole\TorrentBlackhole.cs" />
|
||||
<Compile Include="Download\Clients\Blackhole\TorrentBlackholeSettings.cs" />
|
||||
<Compile Include="Download\Clients\TorrentSeedConfiguration.cs" />
|
||||
<Compile Include="Download\Clients\rTorrent\RTorrent.cs" />
|
||||
<Compile Include="Download\Clients\rTorrent\RTorrentPriority.cs" />
|
||||
@ -427,8 +429,8 @@
|
||||
<Compile Include="Download\Clients\Transmission\TransmissionTorrent.cs" />
|
||||
<Compile Include="Download\Clients\Transmission\TransmissionTorrentStatus.cs" />
|
||||
<Compile Include="Download\Clients\Transmission\TransmissionPriority.cs" />
|
||||
<Compile Include="Download\Clients\UsenetBlackhole\UsenetBlackhole.cs" />
|
||||
<Compile Include="Download\Clients\UsenetBlackhole\UsenetBlackholeSettings.cs" />
|
||||
<Compile Include="Download\Clients\Blackhole\UsenetBlackhole.cs" />
|
||||
<Compile Include="Download\Clients\Blackhole\UsenetBlackholeSettings.cs" />
|
||||
<Compile Include="Download\Clients\uTorrent\UTorrentPriority.cs" />
|
||||
<Compile Include="Download\Clients\uTorrent\UTorrent.cs" />
|
||||
<Compile Include="Download\Clients\uTorrent\UTorrentProxy.cs" />
|
||||
|
@ -80,6 +80,8 @@ public virtual void SetMock(Type type, Mock mock)
|
||||
{
|
||||
if (_registeredMocks.ContainsKey(type) == false)
|
||||
_registeredMocks.Add(type, mock);
|
||||
if (mock != null)
|
||||
_container.RegisterInstance(type, mock.Object);
|
||||
}
|
||||
|
||||
public virtual void SetConstant<T>(T instance)
|
||||
|
Loading…
Reference in New Issue
Block a user