Fixed: Some Tests and Added New Ones

This commit is contained in:
Qstick 2019-07-09 22:05:32 -04:00
parent a3f72bd4a0
commit 612d948eba
22 changed files with 604 additions and 84 deletions

View File

@ -52,15 +52,6 @@ CleanFolder()
find $path -depth -empty -type d -exec rm -r "{}" \; find $path -depth -empty -type d -exec rm -r "{}" \;
} }
AddJsonNet()
{
rm $outputFolder/Newtonsoft.Json.*
cp $sourceFolder/packages/Newtonsoft.Json.*/lib/net35/*.dll $outputFolder
cp $sourceFolder/packages/Newtonsoft.Json.*/lib/net35/*.dll $outputFolder/NzbDrone.Update
}
BuildWithMSBuild() BuildWithMSBuild()
{ {
export PATH=$msBuild:$PATH export PATH=$msBuild:$PATH
@ -115,8 +106,6 @@ Build()
CleanFolder $outputFolder false CleanFolder $outputFolder false
AddJsonNet
echo "Removing Mono.Posix.dll" echo "Removing Mono.Posix.dll"
rm $outputFolder/Mono.Posix.dll rm $outputFolder/Mono.Posix.dll

View File

@ -1,11 +1,13 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using FluentAssertions;
namespace NzbDrone.Common.Test.DiskTests namespace NzbDrone.Common.Test.DiskTests
{ {
@ -16,6 +18,7 @@ namespace NzbDrone.Common.Test.DiskTests
private readonly string _targetPath = @"C:\target\my.video.mkv".AsOsAgnostic(); private readonly string _targetPath = @"C:\target\my.video.mkv".AsOsAgnostic();
private readonly string _backupPath = @"C:\source\my.video.mkv.backup~".AsOsAgnostic(); private readonly string _backupPath = @"C:\source\my.video.mkv.backup~".AsOsAgnostic();
private readonly string _tempTargetPath = @"C:\target\my.video.mkv.partial~".AsOsAgnostic(); private readonly string _tempTargetPath = @"C:\target\my.video.mkv.partial~".AsOsAgnostic();
private readonly string _nfsFile = ".nfs01231232";
[SetUp] [SetUp]
public void SetUp() public void SetUp()
@ -237,7 +240,7 @@ namespace NzbDrone.Common.Test.DiskTests
WithExistingFile(_targetPath); WithExistingFile(_targetPath);
Assert.Throws<IOException>(() => Subject.TransferFile(_sourcePath, _targetPath, TransferMode.Move, false)); Assert.Throws<DestinationAlreadyExistsException>(() => Subject.TransferFile(_sourcePath, _targetPath, TransferMode.Move, false));
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Verify(v => v.DeleteFile(_targetPath), Times.Never()); .Verify(v => v.DeleteFile(_targetPath), Times.Never());
@ -642,6 +645,21 @@ namespace NzbDrone.Common.Test.DiskTests
VerifyCopyFolder(source.FullName, destination.FullName); VerifyCopyFolder(source.FullName, destination.FullName);
} }
[Test]
public void CopyFolder_should_ignore_nfs_temp_file()
{
WithRealDiskProvider();
var source = GetFilledTempFolder();
File.WriteAllText(Path.Combine(source.FullName, _nfsFile), "SubFile1");
var destination = new DirectoryInfo(GetTempFilePath());
Subject.TransferFolder(source.FullName, destination.FullName, TransferMode.Copy);
File.Exists(Path.Combine(destination.FullName, _nfsFile)).Should().BeFalse();
}
[Test] [Test]
public void MoveFolder_should_move_folder() public void MoveFolder_should_move_folder()
@ -704,6 +722,26 @@ namespace NzbDrone.Common.Test.DiskTests
destination.GetFileSystemInfos().Should().BeEmpty(); destination.GetFileSystemInfos().Should().BeEmpty();
} }
[Test]
public void MirrorFolder_should_not_remove_nfs_files()
{
WithRealDiskProvider();
var original = GetFilledTempFolder();
var source = new DirectoryInfo(GetTempFilePath());
var destination = new DirectoryInfo(GetTempFilePath());
source.Create();
Subject.TransferFolder(original.FullName, destination.FullName, TransferMode.Copy);
File.WriteAllText(Path.Combine(destination.FullName, _nfsFile), "SubFile1");
var count = Subject.MirrorFolder(source.FullName, destination.FullName);
count.Should().Equals(0);
destination.GetFileSystemInfos().Should().HaveCount(1);
}
[Test] [Test]
public void MirrorFolder_should_add_new_files() public void MirrorFolder_should_add_new_files()
{ {
@ -721,6 +759,24 @@ namespace NzbDrone.Common.Test.DiskTests
VerifyCopyFolder(original.FullName, destination.FullName); VerifyCopyFolder(original.FullName, destination.FullName);
} }
[Test]
public void MirrorFolder_should_ignore_nfs_temp_file()
{
WithRealDiskProvider();
var source = GetFilledTempFolder();
File.WriteAllText(Path.Combine(source.FullName, _nfsFile), "SubFile1");
var destination = new DirectoryInfo(GetTempFilePath());
var count = Subject.MirrorFolder(source.FullName, destination.FullName);
count.Should().Equals(3);
File.Exists(Path.Combine(destination.FullName, _nfsFile)).Should().BeFalse();
}
[Test] [Test]
public void MirrorFolder_should_not_touch_equivalent_files() public void MirrorFolder_should_not_touch_equivalent_files()
{ {
@ -740,6 +796,75 @@ namespace NzbDrone.Common.Test.DiskTests
VerifyCopyFolder(original.FullName, destination.FullName); VerifyCopyFolder(original.FullName, destination.FullName);
} }
[Test]
public void TransferFolder_should_use_movefolder_if_on_same_mount()
{
WithEmulatedDiskProvider();
var src = @"C:\Base1\TestDir1".AsOsAgnostic();
var dst = @"C:\Base1\TestDir2".AsOsAgnostic();
WithMockMount(@"C:\Base1".AsOsAgnostic());
WithExistingFile(@"C:\Base1\TestDir1\test.file.txt".AsOsAgnostic());
Subject.TransferFolder(src, dst, TransferMode.Move);
Mocker.GetMock<IDiskProvider>()
.Verify(v => v.MoveFolder(src, dst, false), Times.Once());
}
[Test]
public void TransferFolder_should_not_use_movefolder_if_on_same_mount_but_target_already_exists()
{
WithEmulatedDiskProvider();
var src = @"C:\Base1\TestDir1".AsOsAgnostic();
var dst = @"C:\Base1\TestDir2".AsOsAgnostic();
WithMockMount(@"C:\Base1".AsOsAgnostic());
WithExistingFile(@"C:\Base1\TestDir1\test.file.txt".AsOsAgnostic());
WithExistingFolder(dst);
Subject.TransferFolder(src, dst, TransferMode.Move);
Mocker.GetMock<IDiskProvider>()
.Verify(v => v.MoveFolder(src, dst, false), Times.Never());
}
[Test]
public void TransferFolder_should_not_use_movefolder_if_on_same_mount_but_transactional()
{
WithEmulatedDiskProvider();
var src = @"C:\Base1\TestDir1".AsOsAgnostic();
var dst = @"C:\Base1\TestDir2".AsOsAgnostic();
WithMockMount(@"C:\Base1".AsOsAgnostic());
WithExistingFile(@"C:\Base1\TestDir1\test.file.txt".AsOsAgnostic());
Subject.TransferFolder(src, dst, TransferMode.Move, DiskTransferVerificationMode.Transactional);
Mocker.GetMock<IDiskProvider>()
.Verify(v => v.MoveFolder(src, dst, false), Times.Never());
}
[Test]
public void TransferFolder_should_not_use_movefolder_if_on_different_mount()
{
WithEmulatedDiskProvider();
var src = @"C:\Base1\TestDir1".AsOsAgnostic();
var dst = @"C:\Base2\TestDir2".AsOsAgnostic();
WithMockMount(@"C:\Base1".AsOsAgnostic());
WithMockMount(@"C:\Base2".AsOsAgnostic());
Subject.TransferFolder(src, dst, TransferMode.Move);
Mocker.GetMock<IDiskProvider>()
.Verify(v => v.MoveFolder(src, dst, false), Times.Never());
}
public DirectoryInfo GetFilledTempFolder() public DirectoryInfo GetFilledTempFolder()
{ {
var tempFolder = GetTempFilePath(); var tempFolder = GetTempFilePath();
@ -756,8 +881,23 @@ namespace NzbDrone.Common.Test.DiskTests
return new DirectoryInfo(tempFolder); return new DirectoryInfo(tempFolder);
} }
private void WithExistingFolder(string path, bool exists = true)
{
var dir = Path.GetDirectoryName(path);
if (exists && dir.IsNotNullOrWhiteSpace())
WithExistingFolder(dir);
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FolderExists(path))
.Returns(exists);
}
private void WithExistingFile(string path, bool exists = true, int size = 1000) private void WithExistingFile(string path, bool exists = true, int size = 1000)
{ {
var dir = Path.GetDirectoryName(path);
if (exists && dir.IsNotNullOrWhiteSpace())
WithExistingFolder(dir);
Mocker.GetMock<IDiskProvider>() Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FileExists(path)) .Setup(v => v.FileExists(path))
.Returns(exists); .Returns(exists);
@ -809,6 +949,45 @@ namespace NzbDrone.Common.Test.DiskTests
{ {
WithExistingFile(v, false); WithExistingFile(v, false);
}); });
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.FolderExists(It.IsAny<string>()))
.Returns(false);
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.CreateFolder(It.IsAny<string>()))
.Callback<string>((f) =>
{
WithExistingFolder(f);
});
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.MoveFolder(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Callback<string, string, bool>((s, d, b) =>
{
WithExistingFolder(s, false);
WithExistingFolder(d);
// Note: Should also deal with the files.
});
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.DeleteFolder(It.IsAny<string>(), It.IsAny<bool>()))
.Callback<string, bool>((f, r) =>
{
WithExistingFolder(f, false);
// Note: Should also deal with the files.
});
// Note: never returns anything.
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.GetDirectoryInfos(It.IsAny<string>()))
.Returns(new List<DirectoryInfo>());
// Note: never returns anything.
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.GetFileInfos(It.IsAny<string>()))
.Returns(new List<FileInfo>());
} }
private void WithRealDiskProvider() private void WithRealDiskProvider()
@ -865,6 +1044,18 @@ namespace NzbDrone.Common.Test.DiskTests
.Returns<string>(s => new FileStream(s, FileMode.Open, FileAccess.Read)); .Returns<string>(s => new FileStream(s, FileMode.Open, FileAccess.Read));
} }
private void WithMockMount(string root)
{
var rootDir = root;
var mock = new Mock<IMount>();
mock.SetupGet(v => v.RootDirectory)
.Returns(rootDir);
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.GetMount(It.Is<string>(s => s.StartsWith(rootDir))))
.Returns(mock.Object);
}
private void VerifyCopyFolder(string source, string destination) private void VerifyCopyFolder(string source, string destination)
{ {
var sourceFiles = Directory.GetFileSystemEntries(source, "*", SearchOption.AllDirectories).Select(v => v.Substring(source.Length + 1)).ToArray(); var sourceFiles = Directory.GetFileSystemEntries(source, "*", SearchOption.AllDirectories).Select(v => v.Substring(source.Length + 1)).ToArray();

View File

@ -32,7 +32,7 @@ namespace NzbDrone.Common.Test.DiskTests
public void should_be_able_to_check_space_on_ramdrive() public void should_be_able_to_check_space_on_ramdrive()
{ {
MonoOnly(); MonoOnly();
Subject.GetAvailableSpace("/").Should().NotBe(0); Subject.GetAvailableSpace("/run/").Should().NotBe(0);
} }
[Ignore("Docker")] [Ignore("Docker")]
@ -62,7 +62,7 @@ namespace NzbDrone.Common.Test.DiskTests
{ {
if (new DriveInfo(driveletter.ToString()).IsReady) if (new DriveInfo(driveletter.ToString()).IsReady)
continue; continue;
Assert.Throws<DirectoryNotFoundException>(() => Subject.GetAvailableSpace(driveletter + @":\NOT_A_REAL_PATH\DOES_NOT_EXIST".AsOsAgnostic())); Assert.Throws<DirectoryNotFoundException>(() => Subject.GetAvailableSpace(driveletter + @":\NOT_A_REAL_PATH\DOES_NOT_EXIST".AsOsAgnostic()));
return; return;
} }

View File

@ -10,8 +10,9 @@ namespace NzbDrone.Common.Test.EnvironmentInfo
[Test] [Test]
public void should_return_version() public void should_return_version()
{ {
BuildInfo.Version.Major.Should().BeOneOf(0, 10); BuildInfo.Version.Major.Should().BeOneOf(2, 10);
} }
[Test] [Test]
public void should_get_branch() public void should_get_branch()
{ {

View File

@ -7,6 +7,13 @@ namespace NzbDrone.Common.Test.Http
{ {
public class HttpUriFixture : TestBase public class HttpUriFixture : TestBase
{ {
[TestCase("abc://my_host.com:8080/root/api/")]
public void should_parse(string uri)
{
var newUri = new HttpUri(uri);
newUri.FullUri.Should().Be(uri);
}
[TestCase("", "", "")] [TestCase("", "", "")]
[TestCase("/", "", "/")] [TestCase("/", "", "/")]
[TestCase("base", "", "base")] [TestCase("base", "", "base")]
@ -77,7 +84,7 @@ namespace NzbDrone.Common.Test.Http
public void should_combine_relative_path(string basePath, string relativePath, string expected) public void should_combine_relative_path(string basePath, string relativePath, string expected)
{ {
var newUri = new HttpUri(basePath).CombinePath(relativePath); var newUri = new HttpUri(basePath).CombinePath(relativePath);
newUri.FullUri.Should().Be(expected); newUri.FullUri.Should().Be(expected);
} }
} }

View File

@ -20,6 +20,7 @@ namespace NzbDrone.Common.Test
} }
[TestCase("")] [TestCase("")]
[TestCase("http://")]
public void DownloadString_should_throw_on_error(string url) public void DownloadString_should_throw_on_error(string url)
{ {
Assert.Throws<ArgumentException>(() => Subject.DownloadString(url)); Assert.Throws<ArgumentException>(() => Subject.DownloadString(url));

View File

@ -16,7 +16,6 @@ namespace NzbDrone.Common.Extensions
private const string LOG_DB = "logs.db"; private const string LOG_DB = "logs.db";
private const string NLOG_CONFIG_FILE = "nlog.config"; private const string NLOG_CONFIG_FILE = "nlog.config";
private const string UPDATE_CLIENT_EXE = "Radarr.Update.exe"; private const string UPDATE_CLIENT_EXE = "Radarr.Update.exe";
private const string BACKUP_FOLDER = "Backups";
private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "radarr_update" + Path.DirectorySeparatorChar; private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "radarr_update" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "Radarr" + Path.DirectorySeparatorChar; private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "Radarr" + Path.DirectorySeparatorChar;

View File

@ -7,7 +7,7 @@ namespace NzbDrone.Common.Extensions
{ {
public static int? ParseInt32(this string source) public static int? ParseInt32(this string source)
{ {
int result = 0; int result;
if (int.TryParse(source, out result)) if (int.TryParse(source, out result))
{ {
@ -17,9 +17,9 @@ namespace NzbDrone.Common.Extensions
return null; return null;
} }
public static Nullable<long> ParseInt64(this string source) public static long? ParseInt64(this string source)
{ {
long result = 0; long result;
if (long.TryParse(source, out result)) if (long.TryParse(source, out result))
{ {

View File

@ -13,6 +13,9 @@ using NzbDrone.Core.Qualities;
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 NzbDrone.Core.Exceptions;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Download.Clients;
namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
{ {
@ -36,7 +39,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
.Build(); .Build();
} }
private RemoteMovie GetRemoteMovie(QualityModel quality, Movie movie = null) private RemoteMovie GetRemoteMovie(QualityModel quality, Movie movie = null, DownloadProtocol downloadProtocol = DownloadProtocol.Usenet)
{ {
if (movie == null) if (movie == null)
{ {
@ -54,12 +57,13 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
MovieTitle = "A Movie", MovieTitle = "A Movie",
}, },
Movie = movie, Movie = movie,
Release = new ReleaseInfo() Release = new ReleaseInfo()
{ {
PublishDate = DateTime.UtcNow, PublishDate = DateTime.UtcNow,
Title = "A.Movie.1998", Title = "A.Movie.1998",
Size = 200 Size = 200,
DownloadProtocol = downloadProtocol
} }
}; };
@ -91,6 +95,25 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Once());
} }
[Test]
public void should_not_download_if_any_movie_was_already_downloaded()
{
var remoteMovie1 = GetRemoteMovie(
new QualityModel(Quality.HDTV720p)
);
var remoteMovie2 = GetRemoteMovie(
new QualityModel(Quality.HDTV720p)
);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteMovie1));
decisions.Add(new DownloadDecision(remoteMovie2));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Once());
}
[Test] [Test]
public void should_return_downloaded_reports() public void should_return_downloaded_reports()
{ {
@ -179,7 +202,6 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
var decisions = new List<DownloadDecision>(); var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteMovie, new Rejection("Failure!", RejectionType.Temporary))); decisions.Add(new DownloadDecision(remoteMovie, new Rejection("Failure!", RejectionType.Temporary)));
decisions.Add(new DownloadDecision(remoteMovie));
Subject.ProcessDecisions(decisions); Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Never()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Never());
@ -201,15 +223,68 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
[Test] [Test]
public void should_add_to_pending_even_if_already_added_to_pending() public void should_add_to_pending_even_if_already_added_to_pending()
{ {
var remoteEpisode = GetRemoteMovie(new QualityModel(Quality.HDTV720p));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteEpisode, new Rejection("Failure!", RejectionType.Temporary)));
decisions.Add(new DownloadDecision(remoteEpisode, new Rejection("Failure!", RejectionType.Temporary)));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IPendingReleaseService>().Verify(v => v.AddMany(It.IsAny<List<Tuple<DownloadDecision, PendingReleaseReason>>>()), Times.Once());
}
[Test]
public void should_add_to_failed_if_already_failed_for_that_protocol()
{
var remoteMovie = GetRemoteMovie(new QualityModel(Quality.HDTV720p)); var remoteMovie = GetRemoteMovie(new QualityModel(Quality.HDTV720p));
var decisions = new List<DownloadDecision>(); var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteMovie, new Rejection("Failure!", RejectionType.Temporary))); decisions.Add(new DownloadDecision(remoteMovie));
decisions.Add(new DownloadDecision(remoteMovie, new Rejection("Failure!", RejectionType.Temporary))); decisions.Add(new DownloadDecision(remoteMovie));
Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteMovie>()))
.Throws(new DownloadClientUnavailableException("Download client failed"));
Subject.ProcessDecisions(decisions); Subject.ProcessDecisions(decisions);
Mocker.GetMock<IPendingReleaseService>().Verify(v => v.AddMany(It.IsAny<List<Tuple<DownloadDecision, PendingReleaseReason>>>()), Times.Exactly(2)); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Once());
}
[Test]
public void should_not_add_to_failed_if_failed_for_a_different_protocol()
{
var remoteMovie = GetRemoteMovie(new QualityModel(Quality.HDTV720p), null, DownloadProtocol.Usenet);
var remoteMovie2 = GetRemoteMovie(new QualityModel(Quality.HDTV720p), null, DownloadProtocol.Torrent);
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteMovie));
decisions.Add(new DownloadDecision(remoteMovie2));
Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.Is<RemoteMovie>(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet)))
.Throws(new DownloadClientUnavailableException("Download client failed"));
Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteMovie>(r => r.Release.DownloadProtocol == DownloadProtocol.Usenet)), Times.Once());
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.Is<RemoteMovie>(r => r.Release.DownloadProtocol == DownloadProtocol.Torrent)), Times.Once());
}
[Test]
public void should_add_to_rejected_if_release_unavailable_on_indexer()
{
var remoteMovie = GetRemoteMovie(new QualityModel(Quality.HDTV720p));
var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteMovie));
Mocker.GetMock<IDownloadService>()
.Setup(s => s.DownloadReport(It.IsAny<RemoteMovie>()))
.Throws(new ReleaseUnavailableException(remoteMovie.Release, "That 404 Error is not just a Quirk"));
var result = Subject.ProcessDecisions(decisions);
result.Grabbed.Should().BeEmpty();
result.Rejected.Should().NotBeEmpty();
ExceptionVerification.ExpectedWarns(1);
} }
} }
} }

View File

@ -42,8 +42,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
VerifyCompleted(item); VerifyCompleted(item);
item.CanBeRemoved.Should().BeTrue(); item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeTrue(); item.CanMoveFiles.Should().BeFalse();
} }
[Test] [Test]
@ -66,9 +66,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
} }
[Test] [Test]
public void Download_with_TvDirectory_should_force_directory() public void Download_with_MovieDirectory_should_force_directory()
{ {
GivenTvDirectory(); GivenMovieDirectory();
GivenSuccessfulDownload(); GivenSuccessfulDownload();
var remoteMovie = CreateRemoteMovie(); var remoteMovie = CreateRemoteMovie();
@ -84,7 +84,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
[Test] [Test]
public void Download_with_category_should_force_directory() public void Download_with_category_should_force_directory()
{ {
GivenTvCategory(); GivenMovieCategory();
GivenSuccessfulDownload(); GivenSuccessfulDownload();
var remoteMovie = CreateRemoteMovie(); var remoteMovie = CreateRemoteMovie();
@ -100,7 +100,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
[Test] [Test]
public void Download_with_category_should_not_have_double_slashes() public void Download_with_category_should_not_have_double_slashes()
{ {
GivenTvCategory(); GivenMovieCategory();
GivenSuccessfulDownload(); GivenSuccessfulDownload();
_transmissionConfigItems["download-dir"] += "/"; _transmissionConfigItems["download-dir"] += "/";
@ -175,7 +175,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
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.Completed, false)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, false)]
@ -207,7 +207,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
[Test] [Test]
public void should_exclude_items_not_in_category() public void should_exclude_items_not_in_category()
{ {
GivenTvCategory(); GivenMovieCategory();
_downloading.DownloadDir = @"C:/Downloads/Finished/transmission/radarr"; _downloading.DownloadDir = @"C:/Downloads/Finished/transmission/radarr";
@ -226,7 +226,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
[Test] [Test]
public void should_exclude_items_not_in_TvDirectory() public void should_exclude_items_not_in_TvDirectory()
{ {
GivenTvDirectory(); GivenMovieDirectory();
_downloading.DownloadDir = @"C:/Downloads/Finished/radarr/subdir"; _downloading.DownloadDir = @"C:/Downloads/Finished/radarr/subdir";
@ -283,5 +283,139 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
var item = Subject.GetItems().Single(); var item = Subject.GetItems().Single();
item.RemainingTime.Should().NotHaveValue(); item.RemainingTime.Should().NotHaveValue();
} }
[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_reached_and_not_stopped()
{
GivenGlobalSeedLimits(1.0);
PrepareClientToReturnCompletedItem(false, ratio: 1.0);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_is_not_set()
{
GivenGlobalSeedLimits();
PrepareClientToReturnCompletedItem(true, ratio: 1.0);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_max_ratio_reached_and_paused()
{
GivenGlobalSeedLimits(1.0);
PrepareClientToReturnCompletedItem(true, ratio: 1.0);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_overridden_max_ratio_reached_and_paused()
{
GivenGlobalSeedLimits(2.0);
PrepareClientToReturnCompletedItem(true, ratio: 1.0, ratioLimit: 0.8);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
[Test]
public void should_not_be_removable_if_overridden_max_ratio_not_reached_and_paused()
{
GivenGlobalSeedLimits(0.2);
PrepareClientToReturnCompletedItem(true, ratio: 0.5, ratioLimit: 0.8);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_idletime_reached_and_not_paused()
{
GivenGlobalSeedLimits(null, 20);
PrepareClientToReturnCompletedItem(false, ratio: 2.0, seedingTime: 30);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_max_idletime_reached_and_paused()
{
GivenGlobalSeedLimits(null, 20);
PrepareClientToReturnCompletedItem(true, ratio: 2.0, seedingTime: 20);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_overridden_max_idletime_reached_and_paused()
{
GivenGlobalSeedLimits(null, 40);
PrepareClientToReturnCompletedItem(true, ratio: 2.0, seedingTime: 20, idleLimit: 10);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
[Test]
public void should_be_removable_and_should_not_allow_move_files_if_overridden_max_idletime_reached_and_not_paused()
{
GivenGlobalSeedLimits(null, 40);
PrepareClientToReturnCompletedItem(false, ratio: 2.0, seedingTime: 20, idleLimit: 10);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_not_be_removable_if_overridden_max_idletime_not_reached_and_paused()
{
GivenGlobalSeedLimits(null, 20);
PrepareClientToReturnCompletedItem(true, ratio: 2.0, seedingTime: 30, idleLimit: 40);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_not_be_removable_if_max_idletime_reached_but_ratio_not_and_not_paused()
{
GivenGlobalSeedLimits(2.0, 20);
PrepareClientToReturnCompletedItem(false, ratio: 1.0, seedingTime: 30);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_max_idletime_configured_and_paused()
{
GivenGlobalSeedLimits(2.0, 20);
PrepareClientToReturnCompletedItem(true, ratio: 1.0, seedingTime: 30);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
} }
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Transmission; using NzbDrone.Core.Download.Clients.Transmission;
using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.MediaFiles.TorrentInfo;
@ -72,11 +73,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
{ {
HashString = "HASH", HashString = "HASH",
IsFinished = true, IsFinished = true,
Status = TransmissionTorrentStatus.Stopped, Status = TransmissionTorrentStatus.Seeding,
Name = _title, Name = _title,
TotalSize = 1000, TotalSize = 1000,
LeftUntilDone = 0, LeftUntilDone = 0,
DownloadDir = "somepath" DownloadDir = "somepath",
DownloadedEver = 1000,
UploadedEver = 900
}; };
_magnet = new TransmissionTorrent _magnet = new TransmissionTorrent
@ -106,16 +109,16 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
Mocker.GetMock<ITransmissionProxy>() Mocker.GetMock<ITransmissionProxy>()
.Setup(v => v.GetConfig(It.IsAny<TransmissionSettings>())) .Setup(v => v.GetConfig(It.IsAny<TransmissionSettings>()))
.Returns(_transmissionConfigItems); .Returns(() => Json.Deserialize<TransmissionConfig>(_transmissionConfigItems.ToJson()));
} }
protected void GivenTvCategory() protected void GivenMovieCategory()
{ {
_settings.MovieCategory = "radarr"; _settings.MovieCategory = "radarr";
} }
protected void GivenTvDirectory() protected void GivenMovieDirectory()
{ {
_settings.MovieDirectory = @"C:/Downloads/Finished/radarr"; _settings.MovieDirectory = @"C:/Downloads/Finished/radarr";
} }
@ -178,8 +181,40 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
}); });
} }
protected void PrepareClientToReturnCompletedItem() protected void PrepareClientToReturnCompletedItem(bool stopped = false, double ratio = 0.9, int seedingTime = 60, double? ratioLimit = null, int? idleLimit = null)
{ {
if (stopped)
_completed.Status = TransmissionTorrentStatus.Stopped;
_completed.UploadedEver = (int)(_completed.DownloadedEver * ratio);
_completed.SecondsSeeding = seedingTime * 60;
if (ratioLimit.HasValue)
{
if (double.IsPositiveInfinity(ratioLimit.Value))
{
_completed.SeedRatioMode = 2;
}
else
{
_completed.SeedRatioMode = 1;
_completed.SeedRatioLimit = ratioLimit.Value;
}
}
if (idleLimit.HasValue)
{
if (double.IsPositiveInfinity(idleLimit.Value))
{
_completed.SeedIdleMode = 2;
}
else
{
_completed.SeedIdleMode = 1;
_completed.SeedIdleLimit = idleLimit.Value;
}
}
GivenTorrents(new List<TransmissionTorrent> GivenTorrents(new List<TransmissionTorrent>
{ {
_completed _completed
@ -193,5 +228,20 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
_magnet _magnet
}); });
} }
protected void GivenGlobalSeedLimits(double? ratioLimit = null, int? idleLimit = null)
{
_transmissionConfigItems["seedRatioLimited"] = ratioLimit.HasValue;
if (ratioLimit.HasValue)
{
_transmissionConfigItems["seedRatioLimit"] = ratioLimit.Value;
}
_transmissionConfigItems["idle-seeding-limit-enabled"] = idleLimit.HasValue;
if (idleLimit.HasValue)
{
_transmissionConfigItems["idle-seeding-limit"] = idleLimit.Value;
}
}
} }
} }

View File

@ -74,7 +74,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[Test] [Test]
public void Download_with_TvDirectory_should_force_directory() public void Download_with_TvDirectory_should_force_directory()
{ {
GivenTvDirectory(); GivenMovieDirectory();
GivenSuccessfulDownload(); GivenSuccessfulDownload();
var remoteMovie = CreateRemoteMovie(); var remoteMovie = CreateRemoteMovie();
@ -90,7 +90,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[Test] [Test]
public void Download_with_category_should_force_directory() public void Download_with_category_should_force_directory()
{ {
GivenTvCategory(); GivenMovieCategory();
GivenSuccessfulDownload(); GivenSuccessfulDownload();
var remoteMovie = CreateRemoteMovie(); var remoteMovie = CreateRemoteMovie();
@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[Test] [Test]
public void Download_with_category_should_not_have_double_slashes() public void Download_with_category_should_not_have_double_slashes()
{ {
GivenTvCategory(); GivenMovieCategory();
GivenSuccessfulDownload(); GivenSuccessfulDownload();
_transmissionConfigItems["download-dir"] += "/"; _transmissionConfigItems["download-dir"] += "/";
@ -213,7 +213,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[Test] [Test]
public void should_exclude_items_not_in_category() public void should_exclude_items_not_in_category()
{ {
GivenTvCategory(); GivenMovieCategory();
_downloading.DownloadDir = @"C:/Downloads/Finished/transmission/radarr"; _downloading.DownloadDir = @"C:/Downloads/Finished/transmission/radarr";
@ -232,7 +232,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[Test] [Test]
public void should_exclude_items_not_in_TvDirectory() public void should_exclude_items_not_in_TvDirectory()
{ {
GivenTvDirectory(); GivenMovieDirectory();
_downloading.DownloadDir = @"C:/Downloads/Finished/radarr/subdir"; _downloading.DownloadDir = @"C:/Downloads/Finished/radarr/subdir";

View File

@ -8,6 +8,8 @@ using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Qualities; using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using NzbDrone.Core.Languages;
using System.Collections.Generic;
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
{ {
@ -70,6 +72,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
var movieFile = Builder<MovieFile>.CreateNew() var movieFile = Builder<MovieFile>.CreateNew()
.With(h => h.Quality = new QualityModel()) .With(h => h.Quality = new QualityModel())
.With(h => h.Languages = new List<Language>())
.BuildNew(); .BuildNew();
Db.Insert(movie); Db.Insert(movie);

View File

@ -22,7 +22,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("The Colbert Report - 2014-06-02 - Thomas Piketty.mkv", null)] [TestCase("The Colbert Report - 2014-06-02 - Thomas Piketty.mkv", null)]
[TestCase("Real Time with Bill Maher S12E17 May 23, 2014.mp4", null)] [TestCase("Real Time with Bill Maher S12E17 May 23, 2014.mp4", null)]
[TestCase("Reizen Waes - S01E08 - Transistri\u00EB, Zuid-Osseti\u00EB en Abchazi\u00EB SDTV.avi", null)] [TestCase("Reizen Waes - S01E08 - Transistri\u00EB, Zuid-Osseti\u00EB en Abchazi\u00EB SDTV.avi", null)]
[TestCase("Simpsons 10x11 - Wild Barts Cant Be Broken [rl].avi", null)] [TestCase("Simpsons 10x11 - Wild Barts Cant Be Broken [rl].avi", "rl")]
[TestCase("[ www.Torrenting.com ] - Revenge.S03E14.720p.HDTV.X264-DIMENSION", "DIMENSION")] [TestCase("[ www.Torrenting.com ] - Revenge.S03E14.720p.HDTV.X264-DIMENSION", "DIMENSION")]
[TestCase("Seed S02E09 HDTV x264-2HD [eztv]-[rarbg.com]", "2HD")] [TestCase("Seed S02E09 HDTV x264-2HD [eztv]-[rarbg.com]", "2HD")]
[TestCase("7s-atlantis-s02e01-720p.mkv", null)] [TestCase("7s-atlantis-s02e01-720p.mkv", null)]
@ -32,6 +32,11 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Who.is.America.S01E01.INTERNAL.720p.HDTV.x264-aAF-RakuvUS-Obfuscated", "aAF")] [TestCase("Who.is.America.S01E01.INTERNAL.720p.HDTV.x264-aAF-RakuvUS-Obfuscated", "aAF")]
[TestCase("Haunted.Hayride.2018.720p.WEBRip.DDP5.1.x264-NTb-postbot", "NTb")] [TestCase("Haunted.Hayride.2018.720p.WEBRip.DDP5.1.x264-NTb-postbot", "NTb")]
[TestCase("Haunted.Hayride.2018.720p.WEBRip.DDP5.1.x264-NTb-xpost", "NTb")] [TestCase("Haunted.Hayride.2018.720p.WEBRip.DDP5.1.x264-NTb-xpost", "NTb")]
[TestCase("2.Broke.Girls.S02E24.1080p.AMZN.WEBRip.DD5.1.x264-CasStudio-AsRequested", "CasStudio")]
[TestCase("Billions.S04E11.Lamster.1080p.AMZN.WEB-DL.DDP5.1.H.264-NTb-AlternativeToRequested", "NTb")]
[TestCase("NCIS.S16E04.Third.Wheel.1080p.AMZN.WEB-DL.DDP5.1.H.264-NTb-GEROV", "NTb")]
[TestCase("Will.and.Grace.S10E06.Kid.n.Play.1080p.AMZN.WEB-DL.DDP5.1.H.264-NTb-Z0iDS3N", "NTb")]
[TestCase("Absolute.Power.S02E06.The.House.of.Lords.DVDRip.x264-MaG-Chamele0n", "MaG")]
//[TestCase("", "")] //[TestCase("", "")]
public void should_parse_release_group(string title, string expected) public void should_parse_release_group(string title, string expected)
{ {

View File

@ -36,11 +36,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
} }
var qualityDefinition = _qualityDefinitionService.Get(quality); var qualityDefinition = _qualityDefinitionService.Get(quality);
if (subject.Movie.Runtime == 0)
{ if (subject.Movie.Runtime == 0)
_logger.Warn("{0} has no runtime information using median movie runtime of 110 minutes.", subject.Movie); {
subject.Movie.Runtime = 110; _logger.Warn("{0} has no runtime information using median movie runtime of 110 minutes.", subject.Movie);
} subject.Movie.Runtime = 110;
}
if (qualityDefinition.MinSize.HasValue) if (qualityDefinition.MinSize.HasValue)
{ {
var minSize = qualityDefinition.MinSize.Value.Megabytes(); var minSize = qualityDefinition.MinSize.Value.Megabytes();

View File

@ -7,4 +7,4 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
public string Name { get; set; } public string Name { get; set; }
public string SavePath { get; set; } public string SavePath { get; set; }
} }
} }

View File

@ -35,17 +35,8 @@ namespace NzbDrone.Core.Download.Clients.Transmission
public override IEnumerable<DownloadClientItem> GetItems() public override IEnumerable<DownloadClientItem> GetItems()
{ {
List<TransmissionTorrent> torrents; var configFunc = new Lazy<TransmissionConfig>(() => _proxy.GetConfig(Settings));
var torrents = _proxy.GetTorrents(Settings);
try
{
torrents = _proxy.GetTorrents(Settings);
}
catch (DownloadClientException ex)
{
_logger.Error(ex, ex.Message);
return Enumerable.Empty<DownloadClientItem>();
}
var items = new List<DownloadClientItem>(); var items = new List<DownloadClientItem>();
@ -111,9 +102,8 @@ namespace NzbDrone.Core.Download.Clients.Transmission
item.Status = DownloadItemStatus.Downloading; item.Status = DownloadItemStatus.Downloading;
} }
item.CanMoveFiles = item.CanBeRemoved = item.CanBeRemoved = HasReachedSeedLimit(torrent, item.SeedRatio, configFunc);
torrent.Status == TransmissionTorrentStatus.Stopped && item.CanMoveFiles = item.CanBeRemoved && torrent.Status == TransmissionTorrentStatus.Stopped;
item.SeedRatio >= torrent.SeedRatioLimit;
items.Add(item); items.Add(item);
} }
@ -121,6 +111,46 @@ namespace NzbDrone.Core.Download.Clients.Transmission
return items; return items;
} }
protected bool HasReachedSeedLimit(TransmissionTorrent torrent, double? ratio, Lazy<TransmissionConfig> config)
{
var isStopped = torrent.Status == TransmissionTorrentStatus.Stopped;
var isSeeding = torrent.Status == TransmissionTorrentStatus.Seeding;
if (torrent.SeedRatioMode == 1)
{
if (isStopped && ratio.HasValue && ratio >= torrent.SeedRatioLimit)
{
return true;
}
}
else if (torrent.SeedRatioMode == 0)
{
if (isStopped && config.Value.SeedRatioLimited && ratio >= config.Value.SeedRatioLimit)
{
return true;
}
}
// Transmission doesn't support SeedTimeLimit, use/abuse seed idle limit, but only if it was set per-torrent.
if (torrent.SeedIdleMode == 1)
{
if ((isStopped || isSeeding) && torrent.SecondsSeeding > torrent.SeedIdleLimit * 60)
{
return true;
}
}
else if (torrent.SeedIdleMode == 0)
{
// The global idle limit is a real idle limit, if it's configured then 'Stopped' is enough.
if (isStopped && config.Value.IdleSeedingLimitEnabled)
{
return true;
}
}
return false;
}
public override void RemoveItem(string downloadId, bool deleteData) public override void RemoveItem(string downloadId, bool deleteData)
{ {
_proxy.RemoveTorrent(downloadId.ToLower(), deleteData, Settings); _proxy.RemoveTorrent(downloadId.ToLower(), deleteData, Settings);
@ -129,8 +159,8 @@ namespace NzbDrone.Core.Download.Clients.Transmission
public override DownloadClientInfo GetStatus() public override DownloadClientInfo GetStatus()
{ {
var config = _proxy.GetConfig(Settings); var config = _proxy.GetConfig(Settings);
var destDir = config.GetValueOrDefault("download-dir") as string; var destDir = config.DownloadDir;
if (Settings.MovieCategory.IsNotNullOrWhiteSpace()) if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{ {
destDir = string.Format("{0}/.{1}", destDir, Settings.MovieCategory); destDir = string.Format("{0}/.{1}", destDir, Settings.MovieCategory);
@ -197,7 +227,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
if (!Settings.MovieCategory.IsNotNullOrWhiteSpace()) return null; if (!Settings.MovieCategory.IsNotNullOrWhiteSpace()) return null;
var config = _proxy.GetConfig(Settings); var config = _proxy.GetConfig(Settings);
var destDir = (string)config.GetValueOrDefault("download-dir"); var destDir = config.DownloadDir;
return $"{destDir.TrimEnd('/')}/{Settings.MovieCategory}"; return $"{destDir.TrimEnd('/')}/{Settings.MovieCategory}";
} }

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace NzbDrone.Core.Download.Clients.Transmission
{
public class TransmissionConfig
{
[JsonProperty("rpc-version")]
public string RpcVersion { get; set; }
public string Version { get; set; }
[JsonProperty("download-dir")]
public string DownloadDir { get; set; }
public double SeedRatioLimit { get; set; }
public bool SeedRatioLimited { get; set; }
[JsonProperty("idle-seeding-limit")]
public long IdleSeedingLimit { get; set; }
[JsonProperty("idle-seeding-limit-enabled")]
public bool IdleSeedingLimitEnabled { get; set; }
}
}

View File

@ -16,7 +16,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
void AddTorrentFromUrl(string torrentUrl, string downloadDirectory, TransmissionSettings settings); void AddTorrentFromUrl(string torrentUrl, string downloadDirectory, TransmissionSettings settings);
void AddTorrentFromData(byte[] torrentData, string downloadDirectory, TransmissionSettings settings); void AddTorrentFromData(byte[] torrentData, string downloadDirectory, TransmissionSettings settings);
void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, TransmissionSettings settings); void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, TransmissionSettings settings);
Dictionary<string, object> GetConfig(TransmissionSettings settings); TransmissionConfig GetConfig(TransmissionSettings settings);
string GetProtocolVersion(TransmissionSettings settings); string GetProtocolVersion(TransmissionSettings settings);
string GetClientVersion(TransmissionSettings settings); string GetClientVersion(TransmissionSettings settings);
void RemoveTorrent(string hash, bool removeData, TransmissionSettings settings); void RemoveTorrent(string hash, bool removeData, TransmissionSettings settings);
@ -101,26 +101,22 @@ namespace NzbDrone.Core.Download.Clients.Transmission
{ {
var config = GetConfig(settings); var config = GetConfig(settings);
var version = config["rpc-version"]; return config.RpcVersion;
return version.ToString();
} }
public string GetClientVersion(TransmissionSettings settings) public string GetClientVersion(TransmissionSettings settings)
{ {
var config = GetConfig(settings); var config = GetConfig(settings);
var version = config["version"]; return config.Version;
return version.ToString();
} }
public Dictionary<string, object> GetConfig(TransmissionSettings settings) public TransmissionConfig GetConfig(TransmissionSettings settings)
{ {
// Gets the transmission version. // Gets the transmission version.
var result = GetSessionVariables(settings); var result = GetSessionVariables(settings);
return result.Arguments; return Json.Deserialize<TransmissionConfig>(result.Arguments.ToJson());
} }
public void RemoveTorrent(string hashString, bool removeData, TransmissionSettings settings) public void RemoveTorrent(string hashString, bool removeData, TransmissionSettings settings)
@ -164,15 +160,20 @@ namespace NzbDrone.Core.Download.Clients.Transmission
"hashString", // Unique torrent ID. Use this instead of the client id? "hashString", // Unique torrent ID. Use this instead of the client id?
"name", "name",
"downloadDir", "downloadDir",
"status",
"totalSize", "totalSize",
"leftUntilDone", "leftUntilDone",
"isFinished", "isFinished",
"eta", "eta",
"status",
"secondsDownloading",
"secondsSeeding",
"errorString", "errorString",
"uploadedEver", "uploadedEver",
"downloadedEver", "downloadedEver",
"seedRatioLimit", "seedRatioLimit",
"seedRatioMode",
"seedIdleLimit",
"seedIdleMode",
"fileCount" "fileCount"
}; };

View File

@ -12,10 +12,14 @@
public int Eta { get; set; } public int Eta { get; set; }
public TransmissionTorrentStatus Status { get; set; } public TransmissionTorrentStatus Status { get; set; }
public int SecondsDownloading { get; set; } public int SecondsDownloading { get; set; }
public int SecondsSeeding { get; set; }
public string ErrorString { get; set; } public string ErrorString { get; set; }
public long DownloadedEver { get; set; } public long DownloadedEver { get; set; }
public long UploadedEver { get; set; } public long UploadedEver { get; set; }
public long SeedRatioLimit { get; set; } public double SeedRatioLimit { get; set; }
public int SeedRatioMode { get; set; }
public long SeedIdleLimit { get; set; }
public int SeedIdleMode { get; set; }
public int FileCount { get; set; } public int FileCount { get; set; }
} }
} }

View File

@ -171,6 +171,7 @@
<Compile Include="Download\Clients\QBittorrent\QBittorrentProxySelector.cs" /> <Compile Include="Download\Clients\QBittorrent\QBittorrentProxySelector.cs" />
<Compile Include="Download\Clients\QBittorrent\QBittorrentProxyV1.cs" /> <Compile Include="Download\Clients\QBittorrent\QBittorrentProxyV1.cs" />
<Compile Include="Download\Clients\QBittorrent\QBittorrentProxyV2.cs" /> <Compile Include="Download\Clients\QBittorrent\QBittorrentProxyV2.cs" />
<Compile Include="Download\Clients\Transmission\TransmissionConfig.cs" />
<Compile Include="Download\DownloadClientInfo.cs" /> <Compile Include="Download\DownloadClientInfo.cs" />
<Compile Include="Download\DownloadClientStatusRepository.cs" /> <Compile Include="Download\DownloadClientStatusRepository.cs" />
<Compile Include="Download\DownloadClientStatusService.cs" /> <Compile Include="Download\DownloadClientStatusService.cs" />

View File

@ -113,7 +113,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex SixDigitAirDateRegex = new Regex(@"(?<=[_.-])(?<airdate>(?<!\d)(?<airyear>[1-9]\d{1})(?<airmonth>[0-1][0-9])(?<airday>[0-3][0-9]))(?=[_.-])", private static readonly Regex SixDigitAirDateRegex = new Regex(@"(?<=[_.-])(?<airdate>(?<!\d)(?<airyear>[1-9]\d{1})(?<airmonth>[0-1][0-9])(?<airday>[0-3][0-9]))(?=[_.-])",
RegexOptions.IgnoreCase | RegexOptions.Compiled); RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex CleanReleaseGroupRegex = new Regex(@"^(.*?[-._ ](S\d+E\d+)[-._ ])|(-(RP|1|NZBGeek|Obfuscated|sample|Pre|postbot|xpost|Rakuv[a-z]*|WhiteRev|BUYMORE|AsRequested))+$", private static readonly Regex CleanReleaseGroupRegex = new Regex(@"^(.*?[-._ ](S\d+E\d+)[-._ ])|(-(RP|1|NZBGeek|Obfuscated|sample|Pre|postbot|xpost|Rakuv[a-z]*|WhiteRev|BUYMORE|AsRequested|AlternativeToRequested|GEROV|Z0iDS3N|Chamele0n))+$",
RegexOptions.IgnoreCase | RegexOptions.Compiled); RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex CleanTorrentSuffixRegex = new Regex(@"\[(?:ettv|rartv|rarbg|cttv)\]$", private static readonly Regex CleanTorrentSuffixRegex = new Regex(@"\[(?:ettv|rartv|rarbg|cttv)\]$",