From b68a9912f8da9e58415f0b5fda2ded5ace0cdf0b Mon Sep 17 00:00:00 2001 From: Michael Feinbier Date: Sat, 23 Sep 2023 09:54:10 +0200 Subject: [PATCH] Small refactorings --- .../PutioTests/PutioFixture.cs | 50 ++++++++++++++++--- .../Download/Clients/Putio/Putio.cs | 28 +++++++---- .../Download/Clients/Putio/PutioProxy.cs | 2 + .../Download/Clients/Putio/PutioSettings.cs | 9 ++-- .../Download/Clients/Putio/PutioTorrent.cs | 38 +++++++------- 5 files changed, 88 insertions(+), 39 deletions(-) diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/PutioTests/PutioFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/PutioTests/PutioFixture.cs index 763e7ef26..ef849b8c3 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/PutioTests/PutioFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/PutioTests/PutioFixture.cs @@ -32,6 +32,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.PutioTests _queued = new PutioTorrent { Hash = "HASH", + Id = 1, Status = PutioTorrentStatus.InQueue, Name = _title, Size = 1000, @@ -42,6 +43,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.PutioTests _downloading = new PutioTorrent { Hash = "HASH", + Id = 2, Status = PutioTorrentStatus.Downloading, Name = _title, Size = 1000, @@ -52,6 +54,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.PutioTests _failed = new PutioTorrent { Hash = "HASH", + Id = 3, Status = PutioTorrentStatus.Error, ErrorMessage = "Torrent has reached the maximum number of inactive days.", Name = _title, @@ -64,6 +67,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.PutioTests { Hash = "HASH", Status = PutioTorrentStatus.Completed, + Id = 4, Name = _title, Size = 1000, Downloaded = 1000, @@ -74,6 +78,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.PutioTests _completed_different_parent = new PutioTorrent { Hash = "HASH", + Id = 5, Status = PutioTorrentStatus.Completed, Name = _title, Size = 1000, @@ -85,10 +90,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.PutioTests _seeding = new PutioTorrent { Hash = "HASH", + Id = 6, Status = PutioTorrentStatus.Seeding, Name = _title, Size = 1000, Downloaded = 1000, + Uploaded = 1300, SaveParentId = 1, FileId = 2 }; @@ -137,17 +144,37 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.PutioTests .Returns(torrents); } + protected virtual void GivenMetadata(List metadata) + { + metadata ??= new List(); + var result = new Dictionary(); + foreach (var item in metadata) + { + result.Add(item.Id.ToString(), item); + } + + Mocker.GetMock() + .Setup(s => s.GetAllTorrentMetadata(It.IsAny())) + .Returns(result); + } + [Test] public void getItems_contains_all_items() { GivenTorrents(new List { - _queued, - _downloading, - _failed, - _completed, - _seeding, - _completed_different_parent + _queued, + _downloading, + _failed, + _completed, + _seeding, + _completed_different_parent + }); + GivenMetadata(new List + { + PutioTorrentMetadata.fromTorrent(_completed, true), + PutioTorrentMetadata.fromTorrent(_seeding, true), + PutioTorrentMetadata.fromTorrent(_completed_different_parent, true), }); var items = Subject.GetItems(); @@ -198,10 +225,21 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.PutioTests { _queued }); + GivenMetadata(new List { PutioTorrentMetadata.fromTorrent(_queued, true) }); var item = Subject.GetItems().Single(); item.Status.Should().Be(expectedItemStatus); } + + [Test] + public void test_getItems_marks_non_existing_local_download_as_downloading() + { + GivenTorrents(new List { _completed }); + GivenMetadata(new List { PutioTorrentMetadata.fromTorrent(_completed, false) }); + + var item = Subject.GetItems().Single(); + VerifyDownloading(item); + } } } diff --git a/src/NzbDrone.Core/Download/Clients/Putio/Putio.cs b/src/NzbDrone.Core/Download/Clients/Putio/Putio.cs index 24cafb093..a385d68d4 100644 --- a/src/NzbDrone.Core/Download/Clients/Putio/Putio.cs +++ b/src/NzbDrone.Core/Download/Clients/Putio/Putio.cs @@ -8,6 +8,7 @@ using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Core.Configuration; using NzbDrone.Core.MediaFiles.TorrentInfo; +using NzbDrone.Core.Organizer; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.RemotePathMappings; using NzbDrone.Core.Validation; @@ -54,24 +55,24 @@ namespace NzbDrone.Core.Download.Clients.Putio public override IEnumerable GetItems() { List torrents; + Dictionary metadata; try { torrents = _proxy.GetTorrents(Settings); + metadata = _proxy.GetAllTorrentMetadata(Settings); } catch (DownloadClientException ex) { _logger.Error(ex, ex.Message); - return Enumerable.Empty(); + yield break; } - var items = new List(); - foreach (var torrent in torrents) { - // If totalsize == 0 the torrent is a magnet downloading metadata if (torrent.Size == 0) { + // If totalsize == 0 the torrent is a magnet downloading metadata continue; } @@ -88,7 +89,11 @@ namespace NzbDrone.Core.Download.Clients.Putio Title = torrent.Name, TotalSize = torrent.Size, RemainingSize = torrent.Size - torrent.Downloaded, - DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this) + DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this), + SeedRatio = torrent.Ratio, + + // Initial status, might change later + Status = GetDownloadItemStatus(torrent) }; try @@ -97,6 +102,10 @@ namespace NzbDrone.Core.Download.Clients.Putio { // How needs the output path need to look if we have remote files? + // check if we need to download the torrent from the remote + var title = FileNameBuilder.CleanFileName(torrent.Name); + + // _diskProvider.FileExists(new OsPath()) /* var file = _proxy.GetFile(torrent.FileId, Settings); var torrentPath = "/completed/" + file.Name; @@ -126,21 +135,17 @@ namespace NzbDrone.Core.Download.Clients.Putio item.RemainingTime = TimeSpan.FromSeconds(torrent.EstimatedTime); } - item.Status = GetStatus(torrent); - if (!torrent.ErrorMessage.IsNullOrWhiteSpace()) { item.Status = DownloadItemStatus.Warning; item.Message = torrent.ErrorMessage; } - items.Add(item); + yield return item; } - - return items; } - private DownloadItemStatus GetStatus(PutioTorrent torrent) + private DownloadItemStatus GetDownloadItemStatus(PutioTorrent torrent) { if (torrent.Status == PutioTorrentStatus.Completed || torrent.Status == PutioTorrentStatus.Seeding) @@ -176,6 +181,7 @@ namespace NzbDrone.Core.Download.Clients.Putio protected override void Test(List failures) { + failures.AddIfNotNull(TestFolder(Settings.DownloadPath, "DownloadPath")); failures.AddIfNotNull(TestConnection()); if (failures.Any()) { diff --git a/src/NzbDrone.Core/Download/Clients/Putio/PutioProxy.cs b/src/NzbDrone.Core/Download/Clients/Putio/PutioProxy.cs index 7e071d3c5..902cc90f1 100644 --- a/src/NzbDrone.Core/Download/Clients/Putio/PutioProxy.cs +++ b/src/NzbDrone.Core/Download/Clients/Putio/PutioProxy.cs @@ -15,6 +15,8 @@ namespace NzbDrone.Core.Download.Clients.Putio void AddTorrentFromData(byte[] torrentData, PutioSettings settings); void RemoveTorrent(string hash, PutioSettings settings); void GetAccountSettings(PutioSettings settings); + public PutioTorrentMetadata GetTorrentMetadata(PutioTorrent torrent, PutioSettings settings); + public Dictionary GetAllTorrentMetadata(PutioSettings settings); } public class PutioProxy : IPutioProxy diff --git a/src/NzbDrone.Core/Download/Clients/Putio/PutioSettings.cs b/src/NzbDrone.Core/Download/Clients/Putio/PutioSettings.cs index 6077447ad..8654c91f9 100644 --- a/src/NzbDrone.Core/Download/Clients/Putio/PutioSettings.cs +++ b/src/NzbDrone.Core/Download/Clients/Putio/PutioSettings.cs @@ -24,6 +24,7 @@ namespace NzbDrone.Core.Download.Clients.Putio public PutioSettings() { Url = "https://api.put.io/v2"; + DeleteImported = false; } public string Url { get; } @@ -34,12 +35,12 @@ namespace NzbDrone.Core.Download.Clients.Putio [FieldDefinition(1, Label = "Save Parent Folder ID", Type = FieldType.Textbox, HelpText = "Adding a parent folder ID specific to Sonarr avoids conflicts with unrelated non-Sonarr downloads. Using a parent folder is optional, but strongly recommended.")] public string SaveParentId { get; set; } - [FieldDefinition(2, Label = "Download completed transfers", Type = FieldType.Checkbox, HelpText = "If enabled, Sonarr will download completed files from Put.io. If you manually sync with rclone or similar, disable this")] - public bool DownloadFiles { get; set; } - - [FieldDefinition(3, Label = "Download Path", Type = FieldType.Path, HelpText = "Path were Put.io is downloading to or if downloading is disabled where the mounts are expected")] + [FieldDefinition(2, Label = "Download Path", Type = FieldType.Path, HelpText = "Path were Sonarr will expect the files to get downloaded to. Note: This client does not download finished transfers automatically. Instead make sure that you download them outside of Sonarr e.g. with rclone")] public string DownloadPath { get; set; } + [FieldDefinition(3, Label = "Delete imported files", Type = FieldType.Checkbox, HelpText = "Delete the files on put.io when Sonarr marks them as successfully imported")] + public bool DeleteImported { get; set; } + public NzbDroneValidationResult Validate() { return new NzbDroneValidationResult(Validator.Validate(this)); diff --git a/src/NzbDrone.Core/Download/Clients/Putio/PutioTorrent.cs b/src/NzbDrone.Core/Download/Clients/Putio/PutioTorrent.cs index e15d4bdab..196a1080a 100644 --- a/src/NzbDrone.Core/Download/Clients/Putio/PutioTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/Putio/PutioTorrent.cs @@ -4,39 +4,41 @@ namespace NzbDrone.Core.Download.Clients.Putio { public class PutioTorrent { - public long Downloaded { get; set; } - - [JsonProperty(PropertyName = "error_message")] - public string ErrorMessage { get; set; } - - [JsonProperty(PropertyName = "estimated_time")] - public long EstimatedTime { get; set; } - - [JsonProperty(PropertyName = "file_id")] - public long FileId { get; set; } - public int Id { get; set; } - + public string Hash { get; set; } public string Name { get; set; } + public long Downloaded { get; set; } + public long Uploaded { get; set; } + [JsonProperty(PropertyName = "error_message")] + public string ErrorMessage { get; set; } + [JsonProperty(PropertyName = "estimated_time")] + public long EstimatedTime { get; set; } + [JsonProperty(PropertyName = "file_id")] + public long FileId { get; set; } [JsonProperty(PropertyName = "percent_done")] public int PercentDone { get; set; } - [JsonProperty(PropertyName = "seconds_seeding")] public long SecondsSeeding { get; set; } - public long Size { get; set; } - public string Status { get; set; } - [JsonProperty(PropertyName = "save_parent_id")] public long SaveParentId { get; set; } - - public string Hash { get; set; } + [JsonProperty(PropertyName = "current_ratio")] + public double Ratio { get; set; } } public class PutioTorrentMetadata { + public static PutioTorrentMetadata fromTorrent(PutioTorrent torrent, bool downloaded = false) + { + return new PutioTorrentMetadata + { + Downloaded = downloaded, + Id = torrent.Id + }; + } + public bool Downloaded { get; set; } public long Id { get; set; }