From 291d792810d071f28c389d100b9642854d7cd70e Mon Sep 17 00:00:00 2001 From: Bogdan Date: Thu, 1 Aug 2024 08:17:10 +0300 Subject: [PATCH] Fixed: Moving files on import for usenet clients Closes #7043 --- .../ImportApprovedEpisodesFixture.cs | 44 ------------------- .../Download/Clients/Aria2/Aria2.cs | 9 ++-- .../Clients/Blackhole/TorrentBlackhole.cs | 13 +++--- .../Download/Clients/Deluge/Deluge.cs | 1 + .../DownloadStation/TorrentDownloadStation.cs | 8 ++-- .../Download/Clients/Flood/Flood.cs | 4 +- .../FreeboxDownload/TorrentFreeboxDownload.cs | 2 +- .../Download/Clients/Hadouken/Hadouken.cs | 5 ++- .../Clients/QBittorrent/QBittorrent.cs | 7 ++- .../Clients/Transmission/TransmissionBase.cs | 2 +- .../Download/Clients/rTorrent/RTorrent.cs | 2 +- .../Download/Clients/uTorrent/UTorrent.cs | 1 + .../EpisodeImport/ImportApprovedEpisodes.cs | 2 +- 13 files changed, 35 insertions(+), 65 deletions(-) diff --git a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/ImportApprovedEpisodesFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/ImportApprovedEpisodesFixture.cs index 86ee8e2dd..e5f9ea2a6 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/ImportApprovedEpisodesFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/EpisodeImport/ImportApprovedEpisodesFixture.cs @@ -75,7 +75,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport _downloadClientItem = Builder.CreateNew() .With(d => d.OutputPath = new OsPath(outputPath)) - .With(d => d.DownloadClientInfo = new DownloadClientItemClientInfo()) .Build(); } @@ -202,7 +201,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport GivenNewDownload(); _downloadClientItem.Title = "30.Rock.S01E01"; _downloadClientItem.CanMoveFiles = false; - _downloadClientItem.DownloadClientInfo = null; Subject.Import(new List { _approvedDecisions.First() }, true, _downloadClientItem); @@ -210,48 +208,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport .Verify(v => v.UpgradeEpisodeFile(It.IsAny(), _approvedDecisions.First().LocalEpisode, true), Times.Once()); } - [Test] - public void should_copy_when_remove_completed_downloads_is_disabled_and_can_move_files() - { - GivenNewDownload(); - _downloadClientItem.Title = "30.Rock.S01E01"; - _downloadClientItem.CanMoveFiles = true; - _downloadClientItem.DownloadClientInfo.RemoveCompletedDownloads = false; - - Subject.Import(new List { _approvedDecisions.First() }, true, _downloadClientItem); - - Mocker.GetMock() - .Verify(v => v.UpgradeEpisodeFile(It.IsAny(), _approvedDecisions.First().LocalEpisode, true), Times.Once()); - } - - [Test] - public void should_copy_when_remove_completed_downloads_is_enabled_and_cannot_move_files() - { - GivenNewDownload(); - _downloadClientItem.Title = "30.Rock.S01E01"; - _downloadClientItem.CanMoveFiles = false; - _downloadClientItem.DownloadClientInfo.RemoveCompletedDownloads = true; - - Subject.Import(new List { _approvedDecisions.First() }, true, _downloadClientItem); - - Mocker.GetMock() - .Verify(v => v.UpgradeEpisodeFile(It.IsAny(), _approvedDecisions.First().LocalEpisode, true), Times.Once()); - } - - [Test] - public void should_move_when_remove_completed_downloads_is_enabled_and_can_move_files() - { - GivenNewDownload(); - _downloadClientItem.Title = "30.Rock.S01E01"; - _downloadClientItem.CanMoveFiles = true; - _downloadClientItem.DownloadClientInfo.RemoveCompletedDownloads = true; - - Subject.Import(new List { _approvedDecisions.First() }, true, _downloadClientItem); - - Mocker.GetMock() - .Verify(v => v.UpgradeEpisodeFile(It.IsAny(), _approvedDecisions.First().LocalEpisode, false), Times.Once()); - } - [Test] public void should_use_override_importmode() { diff --git a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs index 970d09d35..6b91b2a63 100644 --- a/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs +++ b/src/NzbDrone.Core/Download/Clients/Aria2/Aria2.cs @@ -129,10 +129,8 @@ namespace NzbDrone.Core.Download.Clients.Aria2 var outputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(GetOutputPath(torrent))); - yield return new DownloadClientItem + var queueItem = new DownloadClientItem { - CanMoveFiles = false, - CanBeRemoved = torrent.Status == "complete", Category = null, DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = torrent.InfoHash?.ToUpper(), @@ -146,7 +144,12 @@ namespace NzbDrone.Core.Download.Clients.Aria2 Status = status, Title = title, TotalSize = totalLength, + CanMoveFiles = false }; + + queueItem.CanBeRemoved = queueItem.DownloadClientInfo.RemoveCompletedDownloads && torrent.Status == "complete"; + + yield return queueItem; } } diff --git a/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs b/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs index 8364a1fb2..eca8dc2f2 100644 --- a/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs +++ b/src/NzbDrone.Core/Download/Clients/Blackhole/TorrentBlackhole.cs @@ -89,7 +89,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole { foreach (var item in _scanWatchFolder.GetItems(Settings.WatchFolder, ScanGracePeriod)) { - yield return new DownloadClientItem + var queueItem = new DownloadClientItem { DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), DownloadId = Definition.Name + "_" + item.DownloadId, @@ -101,11 +101,14 @@ namespace NzbDrone.Core.Download.Clients.Blackhole OutputPath = item.OutputPath, - Status = item.Status, - - CanMoveFiles = !Settings.ReadOnly, - CanBeRemoved = !Settings.ReadOnly + Status = item.Status }; + + queueItem.CanMoveFiles = queueItem.CanBeRemoved = + queueItem.DownloadClientInfo.RemoveCompletedDownloads && + !Settings.ReadOnly; + + yield return queueItem; } } diff --git a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs index f2f8ff7d6..44d78e311 100644 --- a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs +++ b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs @@ -190,6 +190,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge // Here we detect if Deluge is managing the torrent and whether the seed criteria has been met. // This allows Sonarr to delete the torrent as appropriate. item.CanMoveFiles = item.CanBeRemoved = + item.DownloadClientInfo.RemoveCompletedDownloads && torrent.IsAutoManaged && torrent.StopAtRatio && torrent.Ratio >= torrent.StopRatio && diff --git a/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs b/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs index 42efcaedf..59288d3b5 100644 --- a/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs +++ b/src/NzbDrone.Core/Download/Clients/DownloadStation/TorrentDownloadStation.cs @@ -88,7 +88,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation } } - var item = new DownloadClientItem() + var item = new DownloadClientItem { Category = Settings.TvCategory, DownloadClientInfo = DownloadClientItemClientInfo.FromDownloadClient(this, false), @@ -99,11 +99,11 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation RemainingTime = GetRemainingTime(torrent), SeedRatio = GetSeedRatio(torrent), Status = GetStatus(torrent), - Message = GetMessage(torrent), - CanMoveFiles = IsFinished(torrent), - CanBeRemoved = IsFinished(torrent) + Message = GetMessage(torrent) }; + item.CanMoveFiles = item.CanBeRemoved = item.DownloadClientInfo.RemoveCompletedDownloads && IsFinished(torrent); + if (item.Status == DownloadItemStatus.Completed || item.Status == DownloadItemStatus.Failed) { item.OutputPath = GetOutputPath(outputPath, torrent, serialNumber); diff --git a/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs b/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs index 60b153441..0fa02446b 100644 --- a/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs +++ b/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs @@ -153,7 +153,7 @@ namespace NzbDrone.Core.Download.Clients.Flood item.Status = DownloadItemStatus.Downloading; } - if (item.Status == DownloadItemStatus.Completed) + if (item.DownloadClientInfo.RemoveCompletedDownloads && item.Status == DownloadItemStatus.Completed) { // Grab cached seedConfig var seedConfig = _downloadSeedConfigProvider.GetSeedConfiguration(item.DownloadId); @@ -165,7 +165,7 @@ namespace NzbDrone.Core.Download.Clients.Flood // Check if seed ratio reached item.CanMoveFiles = item.CanBeRemoved = true; } - else if (properties.DateFinished != null && properties.DateFinished > 0) + else if (properties.DateFinished is > 0) { // Check if seed time reached if ((DateTimeOffset.Now - DateTimeOffset.FromUnixTimeSeconds((long)properties.DateFinished)) >= seedConfig.SeedTime) diff --git a/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs b/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs index 88248e4b5..365cab274 100644 --- a/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs +++ b/src/NzbDrone.Core/Download/Clients/FreeboxDownload/TorrentFreeboxDownload.cs @@ -119,7 +119,7 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload break; } - item.CanBeRemoved = item.CanMoveFiles = torrent.Status == FreeboxDownloadTaskStatus.Done; + item.CanBeRemoved = item.CanMoveFiles = item.DownloadClientInfo.RemoveCompletedDownloads && torrent.Status == FreeboxDownloadTaskStatus.Done; queueItems.Add(item); } diff --git a/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs b/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs index 59f28e34d..59ee6c923 100644 --- a/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs +++ b/src/NzbDrone.Core/Download/Clients/Hadouken/Hadouken.cs @@ -92,7 +92,10 @@ namespace NzbDrone.Core.Download.Clients.Hadouken item.Status = DownloadItemStatus.Downloading; } - item.CanMoveFiles = item.CanBeRemoved = torrent.IsFinished && torrent.State == HadoukenTorrentState.Paused; + item.CanMoveFiles = item.CanBeRemoved = + item.DownloadClientInfo.RemoveCompletedDownloads && + torrent.IsFinished && + torrent.State == HadoukenTorrentState.Paused; items.Add(item); } diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs index 56eb302fe..8bec2d2fd 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs @@ -225,7 +225,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent foreach (var torrent in torrents) { - var item = new DownloadClientItem() + var item = new DownloadClientItem { DownloadId = torrent.Hash.ToUpper(), Category = torrent.Category.IsNotNullOrWhiteSpace() ? torrent.Category : torrent.Label, @@ -239,7 +239,10 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent // Avoid removing torrents that haven't reached the global max ratio. // Removal also requires the torrent to be paused, in case a higher max ratio was set on the torrent itself (which is not exposed by the api). - item.CanMoveFiles = item.CanBeRemoved = torrent.State is "pausedUP" or "stoppedUP" && HasReachedSeedLimit(torrent, config); + item.CanMoveFiles = item.CanBeRemoved = + item.DownloadClientInfo.RemoveCompletedDownloads && + torrent.State is "pausedUP" or "stoppedUP" && + HasReachedSeedLimit(torrent, config); switch (torrent.State) { diff --git a/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs b/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs index 180c6094a..87810d016 100644 --- a/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs +++ b/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs @@ -117,7 +117,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission item.Status = DownloadItemStatus.Downloading; } - item.CanBeRemoved = HasReachedSeedLimit(torrent, item.SeedRatio, configFunc); + item.CanBeRemoved = item.DownloadClientInfo.RemoveCompletedDownloads && HasReachedSeedLimit(torrent, item.SeedRatio, configFunc); item.CanMoveFiles = item.CanBeRemoved && torrent.Status == TransmissionTorrentStatus.Stopped; items.Add(item); diff --git a/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs b/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs index fd91a3833..88fb3ef86 100644 --- a/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs @@ -185,7 +185,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent // Grab cached seedConfig var seedConfig = _downloadSeedConfigProvider.GetSeedConfiguration(torrent.Hash); - if (torrent.IsFinished && seedConfig != null) + if (item.DownloadClientInfo.RemoveCompletedDownloads && torrent.IsFinished && seedConfig != null) { var canRemove = false; diff --git a/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs b/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs index 5b93a1d5d..f99229b0e 100644 --- a/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs @@ -167,6 +167,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent // 'Started' without 'Queued' is when the torrent is 'forced seeding' item.CanMoveFiles = item.CanBeRemoved = + item.DownloadClientInfo.RemoveCompletedDownloads && !torrent.Status.HasFlag(UTorrentTorrentStatus.Queued) && !torrent.Status.HasFlag(UTorrentTorrentStatus.Started); diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs index df2198fb1..b4f62addc 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs @@ -140,7 +140,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport { default: case ImportMode.Auto: - copyOnly = downloadClientItem is { CanMoveFiles: false } or { DownloadClientInfo.RemoveCompletedDownloads: false }; + copyOnly = downloadClientItem is { CanMoveFiles: false }; break; case ImportMode.Move: copyOnly = false;