mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-18 21:34:28 -04:00
Compare commits
1 Commits
v0.4.5.269
...
sonarr-pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17f28a10d5 |
@@ -9,7 +9,7 @@ variables:
|
|||||||
testsFolder: './_tests'
|
testsFolder: './_tests'
|
||||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||||
majorVersion: '0.4.5'
|
majorVersion: '0.4.4'
|
||||||
minorVersion: $[counter('minorVersion', 1)]
|
minorVersion: $[counter('minorVersion', 1)]
|
||||||
readarrVersion: '$(majorVersion).$(minorVersion)'
|
readarrVersion: '$(majorVersion).$(minorVersion)'
|
||||||
buildName: '$(Build.SourceBranchName).$(readarrVersion)'
|
buildName: '$(Build.SourceBranchName).$(readarrVersion)'
|
||||||
@@ -1211,7 +1211,7 @@ stages:
|
|||||||
- task: SonarCloudAnalyze@2
|
- task: SonarCloudAnalyze@2
|
||||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||||
displayName: Publish SonarCloud Results
|
displayName: Publish SonarCloud Results
|
||||||
- task: reportgenerator@5.3.11
|
- task: reportgenerator@5
|
||||||
displayName: Generate Coverage Report
|
displayName: Generate Coverage Report
|
||||||
inputs:
|
inputs:
|
||||||
reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml'
|
reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml'
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ module.exports = (env) => {
|
|||||||
const config = {
|
const config = {
|
||||||
mode: isProduction ? 'production' : 'development',
|
mode: isProduction ? 'production' : 'development',
|
||||||
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
||||||
target: 'web',
|
|
||||||
|
|
||||||
stats: {
|
stats: {
|
||||||
children: false
|
children: false
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PackageVersion Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
<PackageVersion Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
||||||
<PackageVersion Include="Equ" Version="2.3.0" />
|
<PackageVersion Include="Equ" Version="2.3.0" />
|
||||||
<PackageVersion Include="FluentAssertions" Version="5.10.3" />
|
<PackageVersion Include="FluentAssertions" Version="5.10.3" />
|
||||||
<PackageVersion Include="Polly" Version="8.5.0" />
|
<PackageVersion Include="Polly" Version="8.4.2" />
|
||||||
<PackageVersion Include="Servarr.FluentMigrator.Runner" Version="3.3.2.9" />
|
<PackageVersion Include="Servarr.FluentMigrator.Runner" Version="3.3.2.9" />
|
||||||
<PackageVersion Include="Servarr.FluentMigrator.Runner.SQLite" Version="3.3.2.9" />
|
<PackageVersion Include="Servarr.FluentMigrator.Runner.SQLite" Version="3.3.2.9" />
|
||||||
<PackageVersion Include="Servarr.FluentMigrator.Runner.Postgres" Version="3.3.2.9" />
|
<PackageVersion Include="Servarr.FluentMigrator.Runner.Postgres" Version="3.3.2.9" />
|
||||||
@@ -34,18 +34,18 @@
|
|||||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.2.3" />
|
<PackageVersion Include="NLog.Extensions.Logging" Version="5.2.3" />
|
||||||
<PackageVersion Include="NLog" Version="5.1.4" />
|
<PackageVersion Include="NLog" Version="5.1.4" />
|
||||||
<PackageVersion Include="NLog.Targets.Syslog" Version="7.0.0" />
|
<PackageVersion Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||||
<PackageVersion Include="Npgsql" Version="7.0.9" />
|
<PackageVersion Include="Npgsql" Version="7.0.8" />
|
||||||
<PackageVersion Include="NUnit3TestAdapter" Version="4.2.1" />
|
<PackageVersion Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
<PackageVersion Include="NUnit" Version="3.14.0" />
|
<PackageVersion Include="NUnit" Version="3.14.0" />
|
||||||
<PackageVersion Include="NunitXml.TestLogger" Version="3.0.117" />
|
<PackageVersion Include="NunitXml.TestLogger" Version="3.0.117" />
|
||||||
<PackageVersion Include="PdfSharpCore" Version="1.3.65" />
|
<PackageVersion Include="PdfSharpCore" Version="1.3.32" />
|
||||||
<PackageVersion Include="RestSharp.Serializers.SystemTextJson" Version="106.15.0" />
|
<PackageVersion Include="RestSharp.Serializers.SystemTextJson" Version="106.15.0" />
|
||||||
<PackageVersion Include="RestSharp" Version="106.15.0" />
|
<PackageVersion Include="RestSharp" Version="106.15.0" />
|
||||||
<PackageVersion Include="Selenium.Support" Version="3.141.0" />
|
<PackageVersion Include="Selenium.Support" Version="3.141.0" />
|
||||||
<PackageVersion Include="Selenium.WebDriver.ChromeDriver" Version="91.0.4472.10100" />
|
<PackageVersion Include="Selenium.WebDriver.ChromeDriver" Version="91.0.4472.10100" />
|
||||||
<PackageVersion Include="Sentry" Version="3.31.0" />
|
<PackageVersion Include="Sentry" Version="3.31.0" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.6" />
|
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.1.118" />
|
<PackageVersion Include="StyleCop.Analyzers" Version="1.1.118" />
|
||||||
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
|
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
|
||||||
<PackageVersion Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.6.2" />
|
<PackageVersion Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.6.2" />
|
||||||
|
|||||||
@@ -21,28 +21,9 @@ namespace NzbDrone.Common.Test.ExtensionTests
|
|||||||
[TestCase("1.2.3.4")]
|
[TestCase("1.2.3.4")]
|
||||||
[TestCase("172.55.0.1")]
|
[TestCase("172.55.0.1")]
|
||||||
[TestCase("192.55.0.1")]
|
[TestCase("192.55.0.1")]
|
||||||
[TestCase("100.64.0.1")]
|
|
||||||
[TestCase("100.127.255.254")]
|
|
||||||
public void should_return_false_for_public_ip_address(string ipAddress)
|
public void should_return_false_for_public_ip_address(string ipAddress)
|
||||||
{
|
{
|
||||||
IPAddress.Parse(ipAddress).IsLocalAddress().Should().BeFalse();
|
IPAddress.Parse(ipAddress).IsLocalAddress().Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("100.64.0.1")]
|
|
||||||
[TestCase("100.127.255.254")]
|
|
||||||
[TestCase("100.100.100.100")]
|
|
||||||
public void should_return_true_for_cgnat_ip_address(string ipAddress)
|
|
||||||
{
|
|
||||||
IPAddress.Parse(ipAddress).IsCgnatIpAddress().Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("1.2.3.4")]
|
|
||||||
[TestCase("192.168.5.1")]
|
|
||||||
[TestCase("100.63.255.255")]
|
|
||||||
[TestCase("100.128.0.0")]
|
|
||||||
public void should_return_false_for_non_cgnat_ip_address(string ipAddress)
|
|
||||||
{
|
|
||||||
IPAddress.Parse(ipAddress).IsCgnatIpAddress().Should().BeFalse();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@@ -316,5 +317,14 @@ namespace NzbDrone.Common.Test
|
|||||||
result[2].Should().Be(@"Music");
|
result[2].Should().Be(@"Music");
|
||||||
result[3].Should().Be(@"Author Title");
|
result[3].Should().Be(@"Author Title");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_equal_with_different_unicode_representations()
|
||||||
|
{
|
||||||
|
var path1 = @"C:\Test\file.mkv".AsOsAgnostic().Normalize(NormalizationForm.FormC);
|
||||||
|
var path2 = @"C:\Test\file.mkv".AsOsAgnostic().Normalize(NormalizationForm.FormD);
|
||||||
|
|
||||||
|
path1.PathEquals(path2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,24 +39,18 @@ namespace NzbDrone.Common.Extensions
|
|||||||
private static bool IsLocalIPv4(byte[] ipv4Bytes)
|
private static bool IsLocalIPv4(byte[] ipv4Bytes)
|
||||||
{
|
{
|
||||||
// Link local (no IP assigned by DHCP): 169.254.0.0 to 169.254.255.255 (169.254.0.0/16)
|
// Link local (no IP assigned by DHCP): 169.254.0.0 to 169.254.255.255 (169.254.0.0/16)
|
||||||
var isLinkLocal = ipv4Bytes[0] == 169 && ipv4Bytes[1] == 254;
|
bool IsLinkLocal() => ipv4Bytes[0] == 169 && ipv4Bytes[1] == 254;
|
||||||
|
|
||||||
// Class A private range: 10.0.0.0 – 10.255.255.255 (10.0.0.0/8)
|
// Class A private range: 10.0.0.0 – 10.255.255.255 (10.0.0.0/8)
|
||||||
var isClassA = ipv4Bytes[0] == 10;
|
bool IsClassA() => ipv4Bytes[0] == 10;
|
||||||
|
|
||||||
// Class B private range: 172.16.0.0 – 172.31.255.255 (172.16.0.0/12)
|
// Class B private range: 172.16.0.0 – 172.31.255.255 (172.16.0.0/12)
|
||||||
var isClassB = ipv4Bytes[0] == 172 && ipv4Bytes[1] >= 16 && ipv4Bytes[1] <= 31;
|
bool IsClassB() => ipv4Bytes[0] == 172 && ipv4Bytes[1] >= 16 && ipv4Bytes[1] <= 31;
|
||||||
|
|
||||||
// Class C private range: 192.168.0.0 – 192.168.255.255 (192.168.0.0/16)
|
// Class C private range: 192.168.0.0 – 192.168.255.255 (192.168.0.0/16)
|
||||||
var isClassC = ipv4Bytes[0] == 192 && ipv4Bytes[1] == 168;
|
bool IsClassC() => ipv4Bytes[0] == 192 && ipv4Bytes[1] == 168;
|
||||||
|
|
||||||
return isLinkLocal || isClassA || isClassC || isClassB;
|
return IsLinkLocal() || IsClassA() || IsClassC() || IsClassB();
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsCgnatIpAddress(this IPAddress ipAddress)
|
|
||||||
{
|
|
||||||
var bytes = ipAddress.GetAddressBytes();
|
|
||||||
return bytes.Length == 4 && bytes[0] == 100 && bytes[1] >= 64 && bytes[1] <= 127;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,10 @@ namespace NzbDrone.Common.Extensions
|
|||||||
|
|
||||||
public static bool PathEquals(this string firstPath, string secondPath, StringComparison? comparison = null)
|
public static bool PathEquals(this string firstPath, string secondPath, StringComparison? comparison = null)
|
||||||
{
|
{
|
||||||
|
// Normalize paths to ensure unicode characters are represented the same way
|
||||||
|
firstPath = firstPath.Normalize();
|
||||||
|
secondPath = secondPath?.Normalize();
|
||||||
|
|
||||||
if (!comparison.HasValue)
|
if (!comparison.HasValue)
|
||||||
{
|
{
|
||||||
comparison = DiskProviderBase.PathStringComparison;
|
comparison = DiskProviderBase.PathStringComparison;
|
||||||
|
|||||||
@@ -6,5 +6,4 @@ public class AuthOptions
|
|||||||
public bool? Enabled { get; set; }
|
public bool? Enabled { get; set; }
|
||||||
public string Method { get; set; }
|
public string Method { get; set; }
|
||||||
public string Required { get; set; }
|
public string Required { get; set; }
|
||||||
public bool? TrustCgnatIpAddresses { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ namespace NzbDrone.Common
|
|||||||
{
|
{
|
||||||
if (OsInfo.IsWindows)
|
if (OsInfo.IsWindows)
|
||||||
{
|
{
|
||||||
return obj.CleanFilePath().ToLower().GetHashCode();
|
return obj.CleanFilePath().Normalize().ToLower().GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.CleanFilePath().GetHashCode();
|
return obj.CleanFilePath().Normalize().GetHashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,9 +178,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
VerifyWarning(item);
|
VerifyWarning(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedDL")]
|
[Test]
|
||||||
[TestCase("stoppedDL")]
|
public void paused_item_should_have_required_properties()
|
||||||
public void paused_item_should_have_required_properties(string state)
|
|
||||||
{
|
{
|
||||||
var torrent = new QBittorrentTorrent
|
var torrent = new QBittorrentTorrent
|
||||||
{
|
{
|
||||||
@@ -189,7 +188,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
Size = 1000,
|
Size = 1000,
|
||||||
Progress = 0.7,
|
Progress = 0.7,
|
||||||
Eta = 8640000,
|
Eta = 8640000,
|
||||||
State = state,
|
State = "pausedDL",
|
||||||
Label = "",
|
Label = "",
|
||||||
SavePath = ""
|
SavePath = ""
|
||||||
};
|
};
|
||||||
@@ -201,7 +200,6 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[TestCase("pausedUP")]
|
||||||
[TestCase("stoppedUP")]
|
|
||||||
[TestCase("queuedUP")]
|
[TestCase("queuedUP")]
|
||||||
[TestCase("uploading")]
|
[TestCase("uploading")]
|
||||||
[TestCase("stalledUP")]
|
[TestCase("stalledUP")]
|
||||||
@@ -399,9 +397,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
result.OutputPath.FullPath.Should().Be(Path.Combine(torrent.SavePath, "Droned.S01.12"));
|
result.OutputPath.FullPath.Should().Be(Path.Combine(torrent.SavePath, "Droned.S01.12"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void api_261_should_use_content_path()
|
||||||
public void api_261_should_use_content_path(string state)
|
|
||||||
{
|
{
|
||||||
var torrent = new QBittorrentTorrent
|
var torrent = new QBittorrentTorrent
|
||||||
{
|
{
|
||||||
@@ -410,7 +407,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
Size = 1000,
|
Size = 1000,
|
||||||
Progress = 0.7,
|
Progress = 0.7,
|
||||||
Eta = 8640000,
|
Eta = 8640000,
|
||||||
State = state,
|
State = "pausedUP",
|
||||||
Label = "",
|
Label = "",
|
||||||
SavePath = @"C:\Torrents".AsOsAgnostic(),
|
SavePath = @"C:\Torrents".AsOsAgnostic(),
|
||||||
ContentPath = @"C:\Torrents\Droned.S01.12".AsOsAgnostic()
|
ContentPath = @"C:\Torrents\Droned.S01.12".AsOsAgnostic()
|
||||||
@@ -687,48 +684,44 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
item.CanMoveFiles.Should().BeFalse();
|
item.CanMoveFiles.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_is_not_set()
|
||||||
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_is_not_set(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(-1);
|
GivenGlobalSeedLimits(-1);
|
||||||
GivenCompletedTorrent(state, ratio: 1.0f);
|
GivenCompletedTorrent("pausedUP", ratio: 1.0f);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeFalse();
|
item.CanBeRemoved.Should().BeFalse();
|
||||||
item.CanMoveFiles.Should().BeFalse();
|
item.CanMoveFiles.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_be_removable_and_should_allow_move_files_if_max_ratio_reached_and_paused()
|
||||||
public void should_be_removable_and_should_allow_move_files_if_max_ratio_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(1.0f);
|
GivenGlobalSeedLimits(1.0f);
|
||||||
GivenCompletedTorrent(state, ratio: 1.0f);
|
GivenCompletedTorrent("pausedUP", ratio: 1.0f);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeTrue();
|
item.CanBeRemoved.Should().BeTrue();
|
||||||
item.CanMoveFiles.Should().BeTrue();
|
item.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_be_removable_and_should_allow_move_files_if_overridden_max_ratio_reached_and_paused()
|
||||||
public void should_be_removable_and_should_allow_move_files_if_overridden_max_ratio_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(2.0f);
|
GivenGlobalSeedLimits(2.0f);
|
||||||
GivenCompletedTorrent(state, ratio: 1.0f, ratioLimit: 0.8f);
|
GivenCompletedTorrent("pausedUP", ratio: 1.0f, ratioLimit: 0.8f);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeTrue();
|
item.CanBeRemoved.Should().BeTrue();
|
||||||
item.CanMoveFiles.Should().BeTrue();
|
item.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_not_be_removable_if_overridden_max_ratio_not_reached_and_paused()
|
||||||
public void should_not_be_removable_if_overridden_max_ratio_not_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(0.2f);
|
GivenGlobalSeedLimits(0.2f);
|
||||||
GivenCompletedTorrent(state, ratio: 0.5f, ratioLimit: 0.8f);
|
GivenCompletedTorrent("pausedUP", ratio: 0.5f, ratioLimit: 0.8f);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeFalse();
|
item.CanBeRemoved.Should().BeFalse();
|
||||||
@@ -746,36 +739,33 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
item.CanMoveFiles.Should().BeFalse();
|
item.CanMoveFiles.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_be_removable_and_should_allow_move_files_if_max_seedingtime_reached_and_paused()
|
||||||
public void should_be_removable_and_should_allow_move_files_if_max_seedingtime_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(-1, 20);
|
GivenGlobalSeedLimits(-1, 20);
|
||||||
GivenCompletedTorrent(state, ratio: 2.0f, seedingTime: 20);
|
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 20);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeTrue();
|
item.CanBeRemoved.Should().BeTrue();
|
||||||
item.CanMoveFiles.Should().BeTrue();
|
item.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_be_removable_and_should_allow_move_files_if_overridden_max_seedingtime_reached_and_paused()
|
||||||
public void should_be_removable_and_should_allow_move_files_if_overridden_max_seedingtime_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(-1, 40);
|
GivenGlobalSeedLimits(-1, 40);
|
||||||
GivenCompletedTorrent(state, ratio: 2.0f, seedingTime: 20, seedingTimeLimit: 10);
|
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 20, seedingTimeLimit: 10);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeTrue();
|
item.CanBeRemoved.Should().BeTrue();
|
||||||
item.CanMoveFiles.Should().BeTrue();
|
item.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_not_be_removable_if_overridden_max_seedingtime_not_reached_and_paused()
|
||||||
public void should_not_be_removable_if_overridden_max_seedingtime_not_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(-1, 20);
|
GivenGlobalSeedLimits(-1, 20);
|
||||||
GivenCompletedTorrent(state, ratio: 2.0f, seedingTime: 30, seedingTimeLimit: 40);
|
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 30, seedingTimeLimit: 40);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeFalse();
|
item.CanBeRemoved.Should().BeFalse();
|
||||||
@@ -793,72 +783,66 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
item.CanMoveFiles.Should().BeFalse();
|
item.CanMoveFiles.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_be_removable_and_should_allow_move_files_if_max_inactive_seedingtime_reached_and_paused()
|
||||||
public void should_be_removable_and_should_allow_move_files_if_max_inactive_seedingtime_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 20);
|
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 20);
|
||||||
GivenCompletedTorrent(state, ratio: 2.0f, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(25)).ToUnixTimeSeconds());
|
GivenCompletedTorrent("pausedUP", ratio: 2.0f, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(25)).ToUnixTimeSeconds());
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeTrue();
|
item.CanBeRemoved.Should().BeTrue();
|
||||||
item.CanMoveFiles.Should().BeTrue();
|
item.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_be_removable_and_should_allow_move_files_if_overridden_max_inactive_seedingtime_reached_and_paused()
|
||||||
public void should_be_removable_and_should_allow_move_files_if_overridden_max_inactive_seedingtime_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 40);
|
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 40);
|
||||||
GivenCompletedTorrent(state, ratio: 2.0f, seedingTime: 20, inactiveSeedingTimeLimit: 10, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(15)).ToUnixTimeSeconds());
|
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 20, inactiveSeedingTimeLimit: 10, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(15)).ToUnixTimeSeconds());
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeTrue();
|
item.CanBeRemoved.Should().BeTrue();
|
||||||
item.CanMoveFiles.Should().BeTrue();
|
item.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_not_be_removable_if_overridden_max_inactive_seedingtime_not_reached_and_paused()
|
||||||
public void should_not_be_removable_if_overridden_max_inactive_seedingtime_not_reached_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 20);
|
GivenGlobalSeedLimits(-1, maxInactiveSeedingTime: 20);
|
||||||
GivenCompletedTorrent(state, ratio: 2.0f, seedingTime: 30, inactiveSeedingTimeLimit: 40, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(30)).ToUnixTimeSeconds());
|
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 30, inactiveSeedingTimeLimit: 40, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(30)).ToUnixTimeSeconds());
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeFalse();
|
item.CanBeRemoved.Should().BeFalse();
|
||||||
item.CanMoveFiles.Should().BeFalse();
|
item.CanMoveFiles.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_be_removable_and_should_allow_move_files_if_max_seedingtime_reached_but_ratio_not_and_paused()
|
||||||
public void should_be_removable_and_should_allow_move_files_if_max_seedingtime_reached_but_ratio_not_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(2.0f, 20);
|
GivenGlobalSeedLimits(2.0f, 20);
|
||||||
GivenCompletedTorrent(state, ratio: 1.0f, seedingTime: 30);
|
GivenCompletedTorrent("pausedUP", ratio: 1.0f, seedingTime: 30);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeTrue();
|
item.CanBeRemoved.Should().BeTrue();
|
||||||
item.CanMoveFiles.Should().BeTrue();
|
item.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_be_removable_and_should_allow_move_files_if_max_inactive_seedingtime_reached_but_ratio_not_and_paused()
|
||||||
public void should_be_removable_and_should_allow_move_files_if_max_inactive_seedingtime_reached_but_ratio_not_and_paused(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(2.0f, maxInactiveSeedingTime: 20);
|
GivenGlobalSeedLimits(2.0f, maxInactiveSeedingTime: 20);
|
||||||
GivenCompletedTorrent(state, ratio: 1.0f, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(25)).ToUnixTimeSeconds());
|
GivenCompletedTorrent("pausedUP", ratio: 1.0f, lastActivity: DateTimeOffset.UtcNow.Subtract(TimeSpan.FromMinutes(25)).ToUnixTimeSeconds());
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeTrue();
|
item.CanBeRemoved.Should().BeTrue();
|
||||||
item.CanMoveFiles.Should().BeTrue();
|
item.CanMoveFiles.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_not_fetch_details_twice()
|
||||||
public void should_not_fetch_details_twice(string state)
|
|
||||||
{
|
{
|
||||||
GivenGlobalSeedLimits(-1, 30);
|
GivenGlobalSeedLimits(-1, 30);
|
||||||
GivenCompletedTorrent(state, ratio: 2.0f, seedingTime: 20);
|
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 20);
|
||||||
|
|
||||||
var item = Subject.GetItems().Single();
|
var item = Subject.GetItems().Single();
|
||||||
item.CanBeRemoved.Should().BeFalse();
|
item.CanBeRemoved.Should().BeFalse();
|
||||||
@@ -870,9 +854,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
.Verify(p => p.GetTorrentProperties(It.IsAny<string>(), It.IsAny<QBittorrentSettings>()), Times.Once());
|
.Verify(p => p.GetTorrentProperties(It.IsAny<string>(), It.IsAny<QBittorrentSettings>()), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_get_category_from_the_category_if_set()
|
||||||
public void should_get_category_from_the_category_if_set(string state)
|
|
||||||
{
|
{
|
||||||
const string category = "music-readarr";
|
const string category = "music-readarr";
|
||||||
GivenGlobalSeedLimits(1.0f);
|
GivenGlobalSeedLimits(1.0f);
|
||||||
@@ -884,7 +867,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
Size = 1000,
|
Size = 1000,
|
||||||
Progress = 1.0,
|
Progress = 1.0,
|
||||||
Eta = 8640000,
|
Eta = 8640000,
|
||||||
State = state,
|
State = "pausedUP",
|
||||||
Category = category,
|
Category = category,
|
||||||
SavePath = "",
|
SavePath = "",
|
||||||
Ratio = 1.0f
|
Ratio = 1.0f
|
||||||
@@ -896,9 +879,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
item.Category.Should().Be(category);
|
item.Category.Should().Be(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("pausedUP")]
|
[Test]
|
||||||
[TestCase("stoppedUP")]
|
public void should_get_category_from_the_label_if_the_category_is_not_available()
|
||||||
public void should_get_category_from_the_label_if_the_category_is_not_available(string state)
|
|
||||||
{
|
{
|
||||||
const string category = "music-readarr";
|
const string category = "music-readarr";
|
||||||
GivenGlobalSeedLimits(1.0f);
|
GivenGlobalSeedLimits(1.0f);
|
||||||
@@ -910,7 +892,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
|||||||
Size = 1000,
|
Size = 1000,
|
||||||
Progress = 1.0,
|
Progress = 1.0,
|
||||||
Eta = 8640000,
|
Eta = 8640000,
|
||||||
State = state,
|
State = "pausedUP",
|
||||||
Label = category,
|
Label = category,
|
||||||
SavePath = "",
|
SavePath = "",
|
||||||
Ratio = 1.0f
|
Ratio = 1.0f
|
||||||
|
|||||||
@@ -478,37 +478,6 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
downloadClientInfo.RemovesCompletedDownloads.Should().BeTrue();
|
downloadClientInfo.RemovesCompletedDownloads.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("all", 0)]
|
|
||||||
[TestCase("days-archive", 15)]
|
|
||||||
[TestCase("days-delete", 15)]
|
|
||||||
public void should_set_history_removes_completed_downloads_false_for_separate_properties(string option, int number)
|
|
||||||
{
|
|
||||||
_config.Misc.history_retention_option = option;
|
|
||||||
_config.Misc.history_retention_number = number;
|
|
||||||
|
|
||||||
var downloadClientInfo = Subject.GetStatus();
|
|
||||||
|
|
||||||
downloadClientInfo.RemovesCompletedDownloads.Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("number-archive", 10)]
|
|
||||||
[TestCase("number-delete", 10)]
|
|
||||||
[TestCase("number-archive", 0)]
|
|
||||||
[TestCase("number-delete", 0)]
|
|
||||||
[TestCase("days-archive", 3)]
|
|
||||||
[TestCase("days-delete", 3)]
|
|
||||||
[TestCase("all-archive", 0)]
|
|
||||||
[TestCase("all-delete", 0)]
|
|
||||||
public void should_set_history_removes_completed_downloads_true_for_separate_properties(string option, int number)
|
|
||||||
{
|
|
||||||
_config.Misc.history_retention_option = option;
|
|
||||||
_config.Misc.history_retention_number = number;
|
|
||||||
|
|
||||||
var downloadClientInfo = Subject.GetStatus();
|
|
||||||
|
|
||||||
downloadClientInfo.RemovesCompletedDownloads.Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads", @"Y:\nzbget\root\completed\downloads\vv")]
|
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads", @"Y:\nzbget\root\completed\downloads\vv")]
|
||||||
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed", @"Y:\nzbget\root\completed\vv")]
|
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed", @"Y:\nzbget\root\completed\vv")]
|
||||||
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads", @"/nzbget/root/completed/downloads/vv")]
|
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads", @"/nzbget/root/completed/downloads/vv")]
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
|||||||
|
|
||||||
[TestCase("Harry Potter and the sorcerer's stone a detailed summary", 72245296)]
|
[TestCase("Harry Potter and the sorcerer's stone a detailed summary", 72245296)]
|
||||||
[TestCase("B0192CTMYG", 61209488)]
|
[TestCase("B0192CTMYG", 61209488)]
|
||||||
[TestCase("9780439554930", 3)]
|
[TestCase("9780439554930", 48517161)]
|
||||||
public void successful_book_search(string title, int expected)
|
public void successful_book_search(string title, int expected)
|
||||||
{
|
{
|
||||||
var result = Subject.Search(title);
|
var result = Subject.Search(title);
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ namespace NzbDrone.Core.Configuration
|
|||||||
string SyslogServer { get; }
|
string SyslogServer { get; }
|
||||||
int SyslogPort { get; }
|
int SyslogPort { get; }
|
||||||
string SyslogLevel { get; }
|
string SyslogLevel { get; }
|
||||||
string Theme { get; }
|
|
||||||
string PostgresHost { get; }
|
string PostgresHost { get; }
|
||||||
int PostgresPort { get; }
|
int PostgresPort { get; }
|
||||||
string PostgresUser { get; }
|
string PostgresUser { get; }
|
||||||
@@ -61,7 +60,7 @@ namespace NzbDrone.Core.Configuration
|
|||||||
string PostgresMainDb { get; }
|
string PostgresMainDb { get; }
|
||||||
string PostgresLogDb { get; }
|
string PostgresLogDb { get; }
|
||||||
string PostgresCacheDb { get; }
|
string PostgresCacheDb { get; }
|
||||||
bool TrustCgnatIpAddresses { get; }
|
string Theme { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ConfigFileProvider : IConfigFileProvider
|
public class ConfigFileProvider : IConfigFileProvider
|
||||||
@@ -463,7 +462,5 @@ namespace NzbDrone.Core.Configuration
|
|||||||
{
|
{
|
||||||
SetValue("ApiKey", GenerateApiKey());
|
SetValue("ApiKey", GenerateApiKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TrustCgnatIpAddresses => _authOptions.TrustCgnatIpAddresses ?? GetValueBoolean("TrustCgnatIpAddresses", false, persist: false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -404,12 +404,6 @@ namespace NzbDrone.Core.Configuration
|
|||||||
|
|
||||||
public string ApplicationUrl => GetValue("ApplicationUrl", string.Empty);
|
public string ApplicationUrl => GetValue("ApplicationUrl", string.Empty);
|
||||||
|
|
||||||
public bool TrustCgnatIpAddresses
|
|
||||||
{
|
|
||||||
get { return GetValueBoolean("TrustCgnatIpAddresses", false); }
|
|
||||||
set { SetValue("TrustCgnatIpAddresses", value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetValue(string key)
|
private string GetValue(string key)
|
||||||
{
|
{
|
||||||
return GetValue(key, string.Empty);
|
return GetValue(key, string.Empty);
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
|
|
||||||
// Avoid removing torrents that haven't reached the global max ratio.
|
// 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).
|
// 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 = torrent.State == "pausedUP" && HasReachedSeedLimit(torrent, config);
|
||||||
|
|
||||||
switch (torrent.State)
|
switch (torrent.State)
|
||||||
{
|
{
|
||||||
@@ -248,8 +248,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
item.Message = "qBittorrent is reporting an error";
|
item.Message = "qBittorrent is reporting an error";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "stoppedDL": // torrent is stopped and has NOT finished downloading
|
case "pausedDL": // torrent is paused and has NOT finished downloading
|
||||||
case "pausedDL": // torrent is paused and has NOT finished downloading (qBittorrent < 5)
|
|
||||||
item.Status = DownloadItemStatus.Paused;
|
item.Status = DownloadItemStatus.Paused;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -260,8 +259,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
item.Status = DownloadItemStatus.Queued;
|
item.Status = DownloadItemStatus.Queued;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "pausedUP": // torrent is paused and has finished downloading (qBittorent < 5)
|
case "pausedUP": // torrent is paused and has finished downloading
|
||||||
case "stoppedUP": // torrent is stopped and has finished downloading
|
|
||||||
case "uploading": // torrent is being seeded and data is being transferred
|
case "uploading": // torrent is being seeded and data is being transferred
|
||||||
case "stalledUP": // torrent is being seeded, but no connection were made
|
case "stalledUP": // torrent is being seeded, but no connection were made
|
||||||
case "queuedUP": // queuing is enabled and torrent is queued for upload
|
case "queuedUP": // queuing is enabled and torrent is queued for upload
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
Dictionary<string, QBittorrentLabel> GetLabels(QBittorrentSettings settings);
|
Dictionary<string, QBittorrentLabel> GetLabels(QBittorrentSettings settings);
|
||||||
void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, QBittorrentSettings settings);
|
void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, QBittorrentSettings settings);
|
||||||
void MoveTorrentToTopInQueue(string hash, QBittorrentSettings settings);
|
void MoveTorrentToTopInQueue(string hash, QBittorrentSettings settings);
|
||||||
|
void PauseTorrent(string hash, QBittorrentSettings settings);
|
||||||
|
void ResumeTorrent(string hash, QBittorrentSettings settings);
|
||||||
void SetForceStart(string hash, bool enabled, QBittorrentSettings settings);
|
void SetForceStart(string hash, bool enabled, QBittorrentSettings settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
{
|
{
|
||||||
request.AddFormParameter("paused", false);
|
request.AddFormParameter("paused", false);
|
||||||
}
|
}
|
||||||
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Stop)
|
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Pause)
|
||||||
{
|
{
|
||||||
request.AddFormParameter("paused", true);
|
request.AddFormParameter("paused", true);
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
{
|
{
|
||||||
request.AddFormParameter("paused", false);
|
request.AddFormParameter("paused", false);
|
||||||
}
|
}
|
||||||
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Stop)
|
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Pause)
|
||||||
{
|
{
|
||||||
request.AddFormParameter("paused", true);
|
request.AddFormParameter("paused", true);
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
catch (DownloadClientException ex)
|
catch (DownloadClientException ex)
|
||||||
{
|
{
|
||||||
// if setCategory fails due to method not being found, then try older setLabel command for qBittorrent < v.3.3.5
|
// if setCategory fails due to method not being found, then try older setLabel command for qBittorrent < v.3.3.5
|
||||||
if (ex.InnerException is HttpException httpException && httpException.Response.StatusCode == HttpStatusCode.NotFound)
|
if (ex.InnerException is HttpException && (ex.InnerException as HttpException).Response.StatusCode == HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
var setLabelRequest = BuildRequest(settings).Resource("/command/setLabel")
|
var setLabelRequest = BuildRequest(settings).Resource("/command/setLabel")
|
||||||
.Post()
|
.Post()
|
||||||
@@ -257,7 +257,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
catch (DownloadClientException ex)
|
catch (DownloadClientException ex)
|
||||||
{
|
{
|
||||||
// qBittorrent rejects all Prio commands with 403: Forbidden if Options -> BitTorrent -> Torrent Queueing is not enabled
|
// qBittorrent rejects all Prio commands with 403: Forbidden if Options -> BitTorrent -> Torrent Queueing is not enabled
|
||||||
if (ex.InnerException is HttpException httpException && httpException.Response.StatusCode == HttpStatusCode.Forbidden)
|
if (ex.InnerException is HttpException && (ex.InnerException as HttpException).Response.StatusCode == HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -266,6 +266,22 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PauseTorrent(string hash, QBittorrentSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest(settings).Resource("/command/pause")
|
||||||
|
.Post()
|
||||||
|
.AddFormParameter("hash", hash);
|
||||||
|
ProcessRequest(request, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResumeTorrent(string hash, QBittorrentSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest(settings).Resource("/command/resume")
|
||||||
|
.Post()
|
||||||
|
.AddFormParameter("hash", hash);
|
||||||
|
ProcessRequest(request, settings);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetForceStart(string hash, bool enabled, QBittorrentSettings settings)
|
public void SetForceStart(string hash, bool enabled, QBittorrentSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings).Resource("/command/setForceStart")
|
var request = BuildRequest(settings).Resource("/command/setForceStart")
|
||||||
|
|||||||
@@ -246,20 +246,14 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
request.AddFormParameter("category", settings.MusicCategory);
|
request.AddFormParameter("category", settings.MusicCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid extraneous API version check if initial state is ForceStart
|
// Note: ForceStart is handled by separate api call
|
||||||
if ((QBittorrentState)settings.InitialState is QBittorrentState.Start or QBittorrentState.Stop)
|
if ((QBittorrentState)settings.InitialState == QBittorrentState.Start)
|
||||||
{
|
{
|
||||||
var stoppedParameterName = GetApiVersion(settings) >= new Version(2, 11, 0) ? "stopped" : "paused";
|
request.AddFormParameter("paused", false);
|
||||||
|
}
|
||||||
// Note: ForceStart is handled by separate api call
|
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Pause)
|
||||||
if ((QBittorrentState)settings.InitialState == QBittorrentState.Start)
|
{
|
||||||
{
|
request.AddFormParameter("paused", true);
|
||||||
request.AddFormParameter(stoppedParameterName, false);
|
|
||||||
}
|
|
||||||
else if ((QBittorrentState)settings.InitialState == QBittorrentState.Stop)
|
|
||||||
{
|
|
||||||
request.AddFormParameter(stoppedParameterName, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.SequentialOrder)
|
if (settings.SequentialOrder)
|
||||||
@@ -297,7 +291,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
catch (DownloadClientException ex)
|
catch (DownloadClientException ex)
|
||||||
{
|
{
|
||||||
// setShareLimits was added in api v2.0.1 so catch it case of the unlikely event that someone has api v2.0
|
// setShareLimits was added in api v2.0.1 so catch it case of the unlikely event that someone has api v2.0
|
||||||
if (ex.InnerException is HttpException httpException && httpException.Response.StatusCode == HttpStatusCode.NotFound)
|
if (ex.InnerException is HttpException && (ex.InnerException as HttpException).Response.StatusCode == HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -319,7 +313,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
catch (DownloadClientException ex)
|
catch (DownloadClientException ex)
|
||||||
{
|
{
|
||||||
// qBittorrent rejects all Prio commands with 409: Conflict if Options -> BitTorrent -> Torrent Queueing is not enabled
|
// qBittorrent rejects all Prio commands with 409: Conflict if Options -> BitTorrent -> Torrent Queueing is not enabled
|
||||||
if (ex.InnerException is HttpException httpException && httpException.Response.StatusCode == HttpStatusCode.Conflict)
|
if (ex.InnerException is HttpException && (ex.InnerException as HttpException).Response.StatusCode == HttpStatusCode.Conflict)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -328,6 +322,22 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PauseTorrent(string hash, QBittorrentSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest(settings).Resource("/api/v2/torrents/pause")
|
||||||
|
.Post()
|
||||||
|
.AddFormParameter("hashes", hash);
|
||||||
|
ProcessRequest(request, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResumeTorrent(string hash, QBittorrentSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest(settings).Resource("/api/v2/torrents/resume")
|
||||||
|
.Post()
|
||||||
|
.AddFormParameter("hashes", hash);
|
||||||
|
ProcessRequest(request, settings);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetForceStart(string hash, bool enabled, QBittorrentSettings settings)
|
public void SetForceStart(string hash, bool enabled, QBittorrentSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest(settings).Resource("/api/v2/torrents/setForceStart")
|
var request = BuildRequest(settings).Resource("/api/v2/torrents/setForceStart")
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
using NzbDrone.Core.Annotations;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.QBittorrent
|
namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||||
{
|
{
|
||||||
public enum QBittorrentState
|
public enum QBittorrentState
|
||||||
{
|
{
|
||||||
[FieldOption(Label = "Started")]
|
|
||||||
Start = 0,
|
Start = 0,
|
||||||
|
|
||||||
[FieldOption(Label = "Force Started")]
|
|
||||||
ForceStart = 1,
|
ForceStart = 1,
|
||||||
|
Pause = 2
|
||||||
[FieldOption(Label = "Stopped")]
|
|
||||||
Stop = 2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,7 +263,20 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
status.OutputRootFolders = new List<OsPath> { _remotePathMappingService.RemapRemoteToLocal(Settings.Host, category.FullPath) };
|
status.OutputRootFolders = new List<OsPath> { _remotePathMappingService.RemapRemoteToLocal(Settings.Host, category.FullPath) };
|
||||||
}
|
}
|
||||||
|
|
||||||
status.RemovesCompletedDownloads = RemovesCompletedDownloads(config);
|
if (config.Misc.history_retention.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
status.RemovesCompletedDownloads = false;
|
||||||
|
}
|
||||||
|
else if (config.Misc.history_retention.EndsWith("d"))
|
||||||
|
{
|
||||||
|
int.TryParse(config.Misc.history_retention.AsSpan(0, config.Misc.history_retention.Length - 1),
|
||||||
|
out var daysRetention);
|
||||||
|
status.RemovesCompletedDownloads = daysRetention < 14;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status.RemovesCompletedDownloads = config.Misc.history_retention != "0";
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -505,43 +518,6 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
return categories.Contains(category);
|
return categories.Contains(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RemovesCompletedDownloads(SabnzbdConfig config)
|
|
||||||
{
|
|
||||||
var retention = config.Misc.history_retention;
|
|
||||||
var option = config.Misc.history_retention_option;
|
|
||||||
var number = config.Misc.history_retention_number;
|
|
||||||
|
|
||||||
switch (option)
|
|
||||||
{
|
|
||||||
case "all":
|
|
||||||
return false;
|
|
||||||
case "number-archive":
|
|
||||||
case "number-delete":
|
|
||||||
return true;
|
|
||||||
case "days-archive":
|
|
||||||
case "days-delete":
|
|
||||||
return number < 14;
|
|
||||||
case "all-archive":
|
|
||||||
case "all-delete":
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove these checks once support for SABnzbd < 4.3 is removed
|
|
||||||
if (retention.IsNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retention.EndsWith("d"))
|
|
||||||
{
|
|
||||||
int.TryParse(config.Misc.history_retention.AsSpan(0, config.Misc.history_retention.Length - 1),
|
|
||||||
out var daysRetention);
|
|
||||||
return daysRetention < 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retention != "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidatePath(DownloadClientItem downloadClientItem)
|
private bool ValidatePath(DownloadClientItem downloadClientItem)
|
||||||
{
|
{
|
||||||
var downloadItemOutputPath = downloadClientItem.OutputPath;
|
var downloadItemOutputPath = downloadClientItem.OutputPath;
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
public bool enable_date_sorting { get; set; }
|
public bool enable_date_sorting { get; set; }
|
||||||
public bool pre_check { get; set; }
|
public bool pre_check { get; set; }
|
||||||
public string history_retention { get; set; }
|
public string history_retention { get; set; }
|
||||||
public string history_retention_option { get; set; }
|
|
||||||
public int history_retention_number { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SabnzbdCategory
|
public class SabnzbdCategory
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace NzbDrone.Host
|
|||||||
License = new OpenApiLicense
|
License = new OpenApiLicense
|
||||||
{
|
{
|
||||||
Name = "GPL-3.0",
|
Name = "GPL-3.0",
|
||||||
Url = new Uri("https://github.com/Readarr/Readarr/blob/develop/LICENSE.md")
|
Url = new Uri("https://github.com/Readarr/Readarr/blob/develop/LICENSE")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ namespace Readarr.Api.V1.Config
|
|||||||
public string BackupFolder { get; set; }
|
public string BackupFolder { get; set; }
|
||||||
public int BackupInterval { get; set; }
|
public int BackupInterval { get; set; }
|
||||||
public int BackupRetention { get; set; }
|
public int BackupRetention { get; set; }
|
||||||
public bool TrustCgnatIpAddresses { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HostConfigResourceMapper
|
public static class HostConfigResourceMapper
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"description": "Readarr API docs",
|
"description": "Readarr API docs",
|
||||||
"license": {
|
"license": {
|
||||||
"name": "GPL-3.0",
|
"name": "GPL-3.0",
|
||||||
"url": "https://github.com/Readarr/Readarr/blob/develop/LICENSE.md"
|
"url": "https://github.com/Readarr/Readarr/blob/develop/LICENSE"
|
||||||
},
|
},
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -27,13 +27,10 @@ namespace NzbDrone.Http.Authentication
|
|||||||
if (_authenticationRequired == AuthenticationRequiredType.DisabledForLocalAddresses)
|
if (_authenticationRequired == AuthenticationRequiredType.DisabledForLocalAddresses)
|
||||||
{
|
{
|
||||||
if (context.Resource is HttpContext httpContext &&
|
if (context.Resource is HttpContext httpContext &&
|
||||||
IPAddress.TryParse(httpContext.GetRemoteIP(), out var ipAddress))
|
IPAddress.TryParse(httpContext.GetRemoteIP(), out var ipAddress) &&
|
||||||
|
ipAddress.IsLocalAddress())
|
||||||
{
|
{
|
||||||
if (ipAddress.IsLocalAddress() ||
|
context.Succeed(requirement);
|
||||||
(_configService.TrustCgnatIpAddresses && ipAddress.IsCgnatIpAddress()))
|
|
||||||
{
|
|
||||||
context.Succeed(requirement);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user