1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-08-16 07:19:51 +02:00

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 @@ public class DiskTransferServiceFixture : TestBase<DiskTransferService>
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 @@ public void mode_none_should_throw_if_existing_target_when_not_overwriting()
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 @@ public void CopyFolder_should_overwrite_existing_folder()
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 @@ public void MirrorFolder_should_remove_additional_files()
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 @@ public void MirrorFolder_should_add_new_files()
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 @@ public void MirrorFolder_should_not_touch_equivalent_files()
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 @@ public DirectoryInfo GetFilledTempFolder()
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 @@ private void WithEmulatedDiskProvider()
{ {
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 @@ private void WithRealDiskProvider()
.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 @@ public void should_get_free_space_for_folder_that_doesnt_exist()
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")]

View File

@ -10,8 +10,9 @@ public class BuildInfoFixture
[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")]

View File

@ -20,6 +20,7 @@ public void DownloadString_should_be_able_to_dowload_text_file()
} }
[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 @@ public static class PathExtensions
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 @@ public static class TryParseExtensions
{ {
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 @@ public static class TryParseExtensions
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.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 @@ private Movie GetMovie(int id)
.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)
{ {
@ -59,7 +62,8 @@ private RemoteMovie GetRemoteMovie(QualityModel quality, Movie movie = null)
{ {
PublishDate = DateTime.UtcNow, PublishDate = DateTime.UtcNow,
Title = "A.Movie.1998", Title = "A.Movie.1998",
Size = 200 Size = 200,
DownloadProtocol = downloadProtocol
} }
}; };
@ -91,6 +95,25 @@ public void should_only_download_movie_once()
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 @@ public void should_not_grab_if_pending()
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 @@ public void should_not_add_to_pending_if_movie_was_grabbed()
[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 @@ public void completed_download_should_have_required_properties()
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 @@ 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()
{ {
GivenTvDirectory(); GivenMovieDirectory();
GivenSuccessfulDownload(); GivenSuccessfulDownload();
var remoteMovie = CreateRemoteMovie(); var remoteMovie = CreateRemoteMovie();
@ -84,7 +84,7 @@ public void Download_with_TvDirectory_should_force_directory()
[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 @@ public void Download_with_category_should_force_directory()
[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 @@ 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.Completed, false)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, false)]
@ -207,7 +207,7 @@ public void should_return_status_with_outputdirs()
[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 @@ public void should_exclude_items_not_in_category()
[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 @@ public void should_ignore_negative_eta(int eta)
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 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 @@ public void Setup()
{ {
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 @@ public void Setup()
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 @@ protected void PrepareClientToReturnFailedItem()
}); });
} }
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 @@ protected void PrepareClientToReturnMagnetItem()
_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 @@ public void Download_should_return_unique_id()
[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 @@ public void Download_with_TvDirectory_should_force_directory()
[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 @@ public void Download_with_category_should_force_directory()
[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 @@ public void should_return_status_with_outputdirs()
[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 @@ public void should_exclude_items_not_in_category()
[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.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 @@ public void should_not_delete_metadata_files_that_have_a_coresponding_movie_file
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 @@ public class ReleaseGroupParserFixture : CoreTest
[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 @@ public class ReleaseGroupParserFixture : CoreTest
[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 @@ public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCrit
} }
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); _logger.Warn("{0} has no runtime information using median movie runtime of 110 minutes.", subject.Movie);
subject.Movie.Runtime = 110; 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

@ -35,17 +35,8 @@ public TransmissionBase(ITransmissionProxy proxy,
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 @@ public override IEnumerable<DownloadClientItem> GetItems()
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 @@ public override IEnumerable<DownloadClientItem> GetItems()
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,7 +159,7 @@ public override void RemoveItem(string downloadId, bool deleteData)
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())
{ {
@ -197,7 +227,7 @@ protected string GetDownloadDirectory()
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 @@ public interface ITransmissionProxy
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 @@ public string GetProtocolVersion(TransmissionSettings settings)
{ {
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 @@ private TransmissionResponse GetTorrentStatus(IEnumerable<string> hashStrings, T
"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 class TransmissionTorrent
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 @@ public static class 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)\]$",