diff --git a/src/NzbDrone.Core.Test/Download/DownloadClientTests/QBittorrentTests/QBittorrentFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadClientTests/QBittorrentTests/QBittorrentFixture.cs index 524a8ee1e..b98636a5f 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadClientTests/QBittorrentTests/QBittorrentFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadClientTests/QBittorrentTests/QBittorrentFixture.cs @@ -253,13 +253,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests [Test] public void should_return_status_with_outputdirs() { - var configItems = new Dictionary(); - - configItems.Add("save_path", @"C:\Downloads\Finished\QBittorrent".AsOsAgnostic()); + var config = new QBittorrentPreferences + { + SavePath = @"C:\Downloads\Finished\QBittorrent".AsOsAgnostic() + }; Mocker.GetMock() .Setup(v => v.GetConfig(It.IsAny())) - .Returns(configItems); + .Returns(config); var result = Subject.GetStatus(); diff --git a/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrent.cs b/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrent.cs index 61e88bc7e..942cbdaf6 100644 --- a/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrent.cs @@ -80,20 +80,14 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent } } - public override ProviderMessage Message - { - get - { - return new ProviderMessage("Sonarr is unable to remove torrents that have finished seeding when using qBittorrent", ProviderMessageType.Warning); - } - } - public override IEnumerable GetItems() { + QBittorrentPreferences config; List torrents; try { + config = _proxy.GetConfig(Settings); torrents = _proxy.GetTorrents(Settings); } catch (DownloadClientException ex) @@ -116,11 +110,10 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent item.RemainingTime = TimeSpan.FromSeconds(torrent.Eta); item.OutputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, new OsPath(torrent.SavePath)); - - // At the moment there isn't an easy way to detect if the torrent has - // reached the seeding limit, We would need to check the preferences - // and still not be completely sure if that torrent has a limit set for it - item.IsReadOnly = true; + + // 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.IsReadOnly = (config.MaxRatioEnabled && config.MaxRatio > torrent.Ratio) || torrent.State != "pausedUP"; if (!item.OutputPath.IsEmpty && item.OutputPath.FileName != torrent.Name) { @@ -178,7 +171,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent { var config = _proxy.GetConfig(Settings); - var destDir = new OsPath((string)config.GetValueOrDefault("save_path")); + var destDir = new OsPath(config.SavePath); return new DownloadClientStatus { @@ -227,6 +220,16 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent DetailedDescription = "Sonarr will not attempt to import completed downloads without a category." }; } + + // Complain if qBittorrent is configured to remove torrents on max ratio + var config = _proxy.GetConfig(Settings); + if (config.MaxRatioEnabled && config.RemoveOnMaxRatio) + { + return new NzbDroneValidationFailure(String.Empty, "QBittorrent is configured to remove torrents when they reach their Share Ratio Limit") + { + DetailedDescription = "Sonarr will be unable to perform Completed Download Handling as configured. You can fix this in qBittorrent ('Tools -> Options...' in the menu) by changing 'Options -> BitTorrent -> Share Ratio Limiting' from 'Remove them' to 'Pause them'." + }; + } } catch (DownloadClientAuthenticationException ex) { diff --git a/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentPreferences.cs b/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentPreferences.cs new file mode 100644 index 000000000..9fddb1116 --- /dev/null +++ b/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentPreferences.cs @@ -0,0 +1,20 @@ +using Newtonsoft.Json; + +namespace NzbDrone.Core.Download.Clients.QBittorrent +{ + // qbittorrent settings from the list returned by /query/preferences + public class QBittorrentPreferences + { + [JsonProperty(PropertyName = "save_path")] + public string SavePath { get; set; } // Default save path for torrents, separated by slashes + + [JsonProperty(PropertyName = "max_ratio_enabled")] + public bool MaxRatioEnabled { get; set; } // True if share ratio limit is enabled + + [JsonProperty(PropertyName = "max_ratio")] + public float MaxRatio { get; set; } // Get the global share ratio limit + + [JsonProperty(PropertyName = "max_ratio_act")] + public bool RemoveOnMaxRatio { get; set; } // Action performed when a torrent reaches the maximum share ratio. [false = pause, true = remove] + } +} diff --git a/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentProxy.cs b/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentProxy.cs index e65785f03..e00c57585 100644 --- a/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentProxy.cs +++ b/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentProxy.cs @@ -14,7 +14,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent public interface IQBittorrentProxy { int GetVersion(QBittorrentSettings settings); - Dictionary GetConfig(QBittorrentSettings settings); + QBittorrentPreferences GetConfig(QBittorrentSettings settings); List GetTorrents(QBittorrentSettings settings); void AddTorrentFromUrl(string torrentUrl, QBittorrentSettings settings); @@ -47,10 +47,10 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent return response; } - public Dictionary GetConfig(QBittorrentSettings settings) + public QBittorrentPreferences GetConfig(QBittorrentSettings settings) { var request = BuildRequest(settings).Resource("/query/preferences"); - var response = ProcessRequest>(request, settings); + var response = ProcessRequest(request, settings); return response; } diff --git a/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentTorrent.cs b/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentTorrent.cs index ae4963e65..7577345a8 100644 --- a/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/qBittorrent/QBittorrentTorrent.cs @@ -21,5 +21,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent [JsonProperty(PropertyName = "save_path")] public string SavePath { get; set; } // Torrent save path + + public float Ratio { get; set; } // Torrent share ratio } } diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index c333a4492..c305553da 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -401,6 +401,7 @@ +