mirror of
https://github.com/Prowlarr/Prowlarr
synced 2026-01-01 05:14:52 +01:00
Compare commits
No commits in common. "develop" and "v2.1.2.5186" have entirely different histories.
develop
...
v2.1.2.518
22 changed files with 70 additions and 186 deletions
|
|
@ -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: '2.3.2'
|
majorVersion: '2.1.2'
|
||||||
minorVersion: $[counter('minorVersion', 1)]
|
minorVersion: $[counter('minorVersion', 1)]
|
||||||
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
||||||
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
||||||
|
|
@ -18,9 +18,9 @@ variables:
|
||||||
dotnetVersion: '8.0.405'
|
dotnetVersion: '8.0.405'
|
||||||
nodeVersion: '20.X'
|
nodeVersion: '20.X'
|
||||||
innoVersion: '6.2.2'
|
innoVersion: '6.2.2'
|
||||||
windowsImage: 'windows-2025'
|
windowsImage: 'windows-2022'
|
||||||
linuxImage: 'ubuntu-24.04'
|
linuxImage: 'ubuntu-22.04'
|
||||||
macImage: 'macOS-15'
|
macImage: 'macOS-13'
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branches:
|
branches:
|
||||||
|
|
@ -1158,7 +1158,7 @@ stages:
|
||||||
extraProperties: |
|
extraProperties: |
|
||||||
sonar.exclusions=**/obj/**,**/*.dll,**/NzbDrone.Core.Test/Files/**/*,./frontend/**,**/ExternalModules/**,./src/Libraries/**
|
sonar.exclusions=**/obj/**,**/*.dll,**/NzbDrone.Core.Test/Files/**/*,./frontend/**,**/ExternalModules/**,./src/Libraries/**
|
||||||
sonar.coverage.exclusions=**/Prowlarr.Api.V1/**/*
|
sonar.coverage.exclusions=**/Prowlarr.Api.V1/**/*
|
||||||
sonar.cs.cobertura.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.cobertura.xml
|
sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml
|
||||||
sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml
|
sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml
|
||||||
- bash: |
|
- bash: |
|
||||||
./build.sh --backend -f net8.0 -r win-x64
|
./build.sh --backend -f net8.0 -r win-x64
|
||||||
|
|
@ -1170,11 +1170,10 @@ stages:
|
||||||
- task: reportgenerator@5
|
- task: reportgenerator@5
|
||||||
displayName: Generate Coverage Report
|
displayName: Generate Coverage Report
|
||||||
inputs:
|
inputs:
|
||||||
reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.cobertura.xml'
|
reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml'
|
||||||
targetdir: '$(Build.SourcesDirectory)/CoverageResults/combined'
|
targetdir: '$(Build.SourcesDirectory)/CoverageResults/combined'
|
||||||
reporttypes: 'HtmlInline_AzurePipelines;Cobertura;Badges'
|
reporttypes: 'HtmlInline_AzurePipelines;Cobertura;Badges'
|
||||||
publishCodeCoverageResults: true
|
publishCodeCoverageResults: true
|
||||||
sourcedirs: src
|
|
||||||
|
|
||||||
- stage: Report_Out
|
- stage: Report_Out
|
||||||
dependsOn:
|
dependsOn:
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
.modal {
|
.modal {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
max-width: 90%;
|
|
||||||
max-height: 90%;
|
max-height: 90%;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import AppState from 'App/State/AppState';
|
|
||||||
import themes from 'Styles/Themes';
|
|
||||||
|
|
||||||
function createThemeSelector() {
|
|
||||||
return createSelector(
|
|
||||||
(state: AppState) => state.settings.ui.item.theme || window.Prowlarr.theme,
|
|
||||||
(theme) => theme
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const useTheme = () => {
|
|
||||||
const selectedTheme = useSelector(createThemeSelector());
|
|
||||||
const [resolvedTheme, setResolvedTheme] = useState(selectedTheme);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (selectedTheme !== 'auto') {
|
|
||||||
setResolvedTheme(selectedTheme);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const applySystemTheme = () => {
|
|
||||||
setResolvedTheme(
|
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
||||||
? 'dark'
|
|
||||||
: 'light'
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
applySystemTheme();
|
|
||||||
|
|
||||||
window
|
|
||||||
.matchMedia('(prefers-color-scheme: dark)')
|
|
||||||
.addEventListener('change', applySystemTheme);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window
|
|
||||||
.matchMedia('(prefers-color-scheme: dark)')
|
|
||||||
.removeEventListener('change', applySystemTheme);
|
|
||||||
};
|
|
||||||
}, [selectedTheme]);
|
|
||||||
|
|
||||||
return resolvedTheme;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useTheme;
|
|
||||||
|
|
||||||
export const useThemeColor = (color: string) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const themeVariables = themes[theme];
|
|
||||||
|
|
||||||
// @ts-expect-error - themeVariables is a string indexable type
|
|
||||||
return themeVariables[color];
|
|
||||||
};
|
|
||||||
|
|
@ -84,7 +84,7 @@
|
||||||
|
|
||||||
<Deterministic Condition="$(AssemblyVersion.EndsWith('*'))">False</Deterministic>
|
<Deterministic Condition="$(AssemblyVersion.EndsWith('*'))">False</Deterministic>
|
||||||
|
|
||||||
<PathMap>$(MSBuildThisFileDirectory)=./</PathMap>
|
<PathMap>$(MSBuildProjectDirectory)=./$(MSBuildProjectName)/</PathMap>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Set the AssemblyConfiguration attribute for projects -->
|
<!-- Set the AssemblyConfiguration attribute for projects -->
|
||||||
|
|
@ -123,11 +123,14 @@
|
||||||
|
|
||||||
<!-- Standard testing packages -->
|
<!-- Standard testing packages -->
|
||||||
<ItemGroup Condition="'$(TestProject)'=='true'">
|
<ItemGroup Condition="'$(TestProject)'=='true'">
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.14.0" />
|
<PackageReference Include="NUnit" Version="3.14.0" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="5.1.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
<PackageReference Include="NunitXml.TestLogger" Version="3.1.20" />
|
<PackageReference Include="NunitXml.TestLogger" Version="3.0.131" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(TestProject)'=='true' and '$(TargetFramework)'=='net8.0'">
|
||||||
|
<PackageReference Include="coverlet.collector" Version="3.0.4-preview.27.ge7cb7c3b40" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(ProwlarrProject)'=='true' and '$(EnableAnalyzers)'=='false'">
|
<PropertyGroup Condition="'$(ProwlarrProject)'=='true' and '$(EnableAnalyzers)'=='false'">
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||||
<add key="dotnet-bsd-crossbuild" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/dotnet-bsd-crossbuild/nuget/v3/index.json" />
|
<add key="dotnet-bsd-crossbuild" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/dotnet-bsd-crossbuild/nuget/v3/index.json" />
|
||||||
<add key="Mono.Posix.NETStandard" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/Mono.Posix.NETStandard/nuget/v3/index.json" />
|
<add key="Mono.Posix.NETStandard" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/Mono.Posix.NETStandard/nuget/v3/index.json" />
|
||||||
|
<add key="SQLite" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/SQLite/nuget/v3/index.json" />
|
||||||
|
<add key="coverlet-nightly" value="https://pkgs.dev.azure.com/Servarr/coverlet/_packaging/coverlet-nightly/nuget/v3/index.json" />
|
||||||
<add key="FluentMigrator" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/FluentMigrator/nuget/v3/index.json" />
|
<add key="FluentMigrator" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/FluentMigrator/nuget/v3/index.json" />
|
||||||
</packageSources>
|
</packageSources>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<PackageReference Include="IPAddressRange" Version="6.2.0" />
|
<PackageReference Include="IPAddressRange" Version="6.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="NLog" Version="5.4.0" />
|
<PackageReference Include="NLog" Version="5.4.0" />
|
||||||
<PackageReference Include="NLog.Layouts.ClefJsonLayout" Version="1.0.3" />
|
<PackageReference Include="NLog.Layouts.ClefJsonLayout" Version="1.0.3" />
|
||||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
|
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
|
||||||
|
|
@ -16,11 +16,9 @@
|
||||||
<PackageReference Include="Sentry" Version="4.0.2" />
|
<PackageReference Include="Sentry" Version="4.0.2" />
|
||||||
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageReference Include="SourceGear.sqlite3" Version="3.50.4.2" />
|
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||||
<PackageReference Include="System.Data.SQLite" Version="2.0.2" />
|
|
||||||
<PackageReference Include="System.Private.Uri" Version="4.3.2" />
|
|
||||||
<PackageReference Include="System.Text.Json" Version="8.0.6" />
|
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.6.1" />
|
<PackageReference Include="System.ValueTuple" Version="4.6.1" />
|
||||||
|
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.1" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.1" />
|
||||||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
|
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
|
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
|
||||||
|
|
|
||||||
|
|
@ -15,24 +15,24 @@ private HttpProxySettings GetProxySettings()
|
||||||
return new HttpProxySettings(ProxyType.Socks5, "localhost", 8080, "*.httpbin.org,google.com,172.16.0.0/12", true, null, null);
|
return new HttpProxySettings(ProxyType.Socks5, "localhost", 8080, "*.httpbin.org,google.com,172.16.0.0/12", true, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("http://eu.httpbin.org/get")]
|
[Test]
|
||||||
[TestCase("http://google.com/get")]
|
public void should_bypass_proxy()
|
||||||
[TestCase("http://localhost:8654/get")]
|
|
||||||
[TestCase("http://172.21.0.1:8989/api/v3/indexer/schema")]
|
|
||||||
public void should_bypass_proxy(string url)
|
|
||||||
{
|
{
|
||||||
var settings = GetProxySettings();
|
var settings = GetProxySettings();
|
||||||
|
|
||||||
Subject.ShouldProxyBeBypassed(settings, new HttpUri(url)).Should().BeTrue();
|
Subject.ShouldProxyBeBypassed(settings, new HttpUri("http://eu.httpbin.org/get")).Should().BeTrue();
|
||||||
|
Subject.ShouldProxyBeBypassed(settings, new HttpUri("http://google.com/get")).Should().BeTrue();
|
||||||
|
Subject.ShouldProxyBeBypassed(settings, new HttpUri("http://localhost:8654/get")).Should().BeTrue();
|
||||||
|
Subject.ShouldProxyBeBypassed(settings, new HttpUri("http://172.21.0.1:8989/api/v3/indexer/schema")).Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("http://bing.com/get")]
|
[Test]
|
||||||
[TestCase("http://172.3.0.1:8989/api/v3/indexer/schema")]
|
public void should_not_bypass_proxy()
|
||||||
public void should_not_bypass_proxy(string url)
|
|
||||||
{
|
{
|
||||||
var settings = GetProxySettings();
|
var settings = GetProxySettings();
|
||||||
|
|
||||||
Subject.ShouldProxyBeBypassed(settings, new HttpUri(url)).Should().BeFalse();
|
Subject.ShouldProxyBeBypassed(settings, new HttpUri("http://bing.com/get")).Should().BeFalse();
|
||||||
|
Subject.ShouldProxyBeBypassed(settings, new HttpUri("http://172.3.0.1:8989/api/v3/indexer/schema")).Should().BeFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||||
<PackageReference Include="NBuilder" Version="6.1.0" />
|
<PackageReference Include="NBuilder" Version="6.1.0" />
|
||||||
|
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||||
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Data.SQLite;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Common.Instrumentation;
|
|
||||||
using NzbDrone.Core.Datastore.Events;
|
using NzbDrone.Core.Datastore.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using Polly;
|
|
||||||
using Polly.Retry;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Datastore
|
namespace NzbDrone.Core.Datastore
|
||||||
{
|
{
|
||||||
|
|
@ -45,31 +40,12 @@ public interface IBasicRepository<TModel>
|
||||||
public class BasicRepository<TModel> : IBasicRepository<TModel>
|
public class BasicRepository<TModel> : IBasicRepository<TModel>
|
||||||
where TModel : ModelBase, new()
|
where TModel : ModelBase, new()
|
||||||
{
|
{
|
||||||
private static readonly ILogger Logger = NzbDroneLogger.GetLogger(typeof(BasicRepository<TModel>));
|
|
||||||
|
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly PropertyInfo _keyProperty;
|
private readonly PropertyInfo _keyProperty;
|
||||||
private readonly List<PropertyInfo> _properties;
|
private readonly List<PropertyInfo> _properties;
|
||||||
private readonly string _updateSql;
|
private readonly string _updateSql;
|
||||||
private readonly string _insertSql;
|
private readonly string _insertSql;
|
||||||
|
|
||||||
private static ResiliencePipeline RetryStrategy => new ResiliencePipelineBuilder()
|
|
||||||
.AddRetry(new RetryStrategyOptions
|
|
||||||
{
|
|
||||||
ShouldHandle = new PredicateBuilder().Handle<SQLiteException>(ex => ex.ResultCode == SQLiteErrorCode.Busy),
|
|
||||||
Delay = TimeSpan.FromMilliseconds(100),
|
|
||||||
MaxRetryAttempts = 3,
|
|
||||||
BackoffType = DelayBackoffType.Exponential,
|
|
||||||
UseJitter = true,
|
|
||||||
OnRetry = args =>
|
|
||||||
{
|
|
||||||
Logger.Warn(args.Outcome.Exception, "Failed writing to database. Retry #{0}", args.AttemptNumber);
|
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
protected readonly IDatabase _database;
|
protected readonly IDatabase _database;
|
||||||
protected readonly string _table;
|
protected readonly string _table;
|
||||||
|
|
||||||
|
|
@ -210,9 +186,7 @@ private string GetInsertSql()
|
||||||
private TModel Insert(IDbConnection connection, IDbTransaction transaction, TModel model)
|
private TModel Insert(IDbConnection connection, IDbTransaction transaction, TModel model)
|
||||||
{
|
{
|
||||||
SqlBuilderExtensions.LogQuery(_insertSql, model);
|
SqlBuilderExtensions.LogQuery(_insertSql, model);
|
||||||
|
var multi = connection.QueryMultiple(_insertSql, model, transaction);
|
||||||
var multi = RetryStrategy.Execute(static (state, _) => state.connection.QueryMultiple(state._insertSql, state.model, state.transaction), (connection, _insertSql, model, transaction));
|
|
||||||
|
|
||||||
var multiRead = multi.Read();
|
var multiRead = multi.Read();
|
||||||
var id = (int)(multiRead.First().id ?? multiRead.First().Id);
|
var id = (int)(multiRead.First().id ?? multiRead.First().Id);
|
||||||
_keyProperty.SetValue(model, id);
|
_keyProperty.SetValue(model, id);
|
||||||
|
|
@ -409,7 +383,7 @@ private void UpdateFields(IDbConnection connection, IDbTransaction transaction,
|
||||||
|
|
||||||
SqlBuilderExtensions.LogQuery(sql, model);
|
SqlBuilderExtensions.LogQuery(sql, model);
|
||||||
|
|
||||||
RetryStrategy.Execute(static (state, _) => state.connection.Execute(state.sql, state.model, transaction: state.transaction), (connection, sql, model, transaction));
|
connection.Execute(sql, model, transaction: transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateFields(IDbConnection connection, IDbTransaction transaction, IList<TModel> models, List<PropertyInfo> propertiesToUpdate)
|
private void UpdateFields(IDbConnection connection, IDbTransaction transaction, IList<TModel> models, List<PropertyInfo> propertiesToUpdate)
|
||||||
|
|
@ -421,7 +395,7 @@ private void UpdateFields(IDbConnection connection, IDbTransaction transaction,
|
||||||
SqlBuilderExtensions.LogQuery(sql, model);
|
SqlBuilderExtensions.LogQuery(sql, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
RetryStrategy.Execute(static (state, _) => state.connection.Execute(state.sql, state.models, transaction: state.transaction), (connection, sql, models, transaction));
|
connection.Execute(sql, models, transaction: transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual SqlBuilder PagedBuilder() => Builder();
|
protected virtual SqlBuilder PagedBuilder() => Builder();
|
||||||
|
|
|
||||||
|
|
@ -424,8 +424,8 @@ private void AuthenticateClient(HttpRequestBuilder requestBuilder, QBittorrentSe
|
||||||
}
|
}
|
||||||
catch (HttpException ex)
|
catch (HttpException ex)
|
||||||
{
|
{
|
||||||
_logger.Debug(ex, "qbitTorrent authentication failed.");
|
_logger.Debug("qbitTorrent authentication failed.");
|
||||||
if (ex.Response.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden)
|
if (ex.Response.StatusCode == HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
throw new DownloadClientAuthenticationException("Failed to authenticate with qBittorrent.", ex);
|
throw new DownloadClientAuthenticationException("Failed to authenticate with qBittorrent.", ex);
|
||||||
}
|
}
|
||||||
|
|
@ -437,9 +437,9 @@ private void AuthenticateClient(HttpRequestBuilder requestBuilder, QBittorrentSe
|
||||||
throw new DownloadClientUnavailableException("Failed to connect to qBittorrent, please check your settings.", ex);
|
throw new DownloadClientUnavailableException("Failed to connect to qBittorrent, please check your settings.", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns "Fails." on bad login
|
if (response.Content != "Ok.")
|
||||||
if (response.Content.IsNotNullOrWhiteSpace() && response.Content != "Ok.")
|
|
||||||
{
|
{
|
||||||
|
// returns "Fails." on bad login
|
||||||
_logger.Debug("qbitTorrent authentication failed.");
|
_logger.Debug("qbitTorrent authentication failed.");
|
||||||
throw new DownloadClientAuthenticationException("Failed to authenticate with qBittorrent.");
|
throw new DownloadClientAuthenticationException("Failed to authenticate with qBittorrent.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -669,7 +669,7 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||||
{
|
{
|
||||||
var advancedSeasonRegex = new Regex(@"\b(?:(?<season>\d+)(?:st|nd|rd|th) Season|Season (?<season>\d+))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
var advancedSeasonRegex = new Regex(@"\b(?:(?<season>\d+)(?:st|nd|rd|th) Season|Season (?<season>\d+))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
var seasonCharactersRegex = new Regex(@"(I{2,})$", RegexOptions.Compiled);
|
var seasonCharactersRegex = new Regex(@"(I{2,})$", RegexOptions.Compiled);
|
||||||
var seasonNumberRegex = new Regex(@"\b(?<!(Part|No\.)[- ._])(?<!\d[/])(?<!\#)(?:S)?(?<season>[2-9])$", RegexOptions.Compiled);
|
var seasonNumberRegex = new Regex(@"\b(?<!Part[- ._])(?<!\d[/])(?:S)?(?<season>[2-9])$", RegexOptions.Compiled);
|
||||||
|
|
||||||
foreach (var title in titles)
|
foreach (var title in titles)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using System;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers.Definitions.Gazelle;
|
using NzbDrone.Core.Indexers.Definitions.Gazelle;
|
||||||
|
|
@ -6,7 +5,6 @@
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Definitions;
|
namespace NzbDrone.Core.Indexers.Definitions;
|
||||||
|
|
||||||
[Obsolete("Moved to YML for Cardigann")]
|
|
||||||
public class CGPeers : GazelleBase<GazelleSettings>
|
public class CGPeers : GazelleBase<GazelleSettings>
|
||||||
{
|
{
|
||||||
public override string Name => "CGPeers";
|
public override string Name => "CGPeers";
|
||||||
|
|
|
||||||
|
|
@ -35,16 +35,6 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||||
throw new RequestLimitReachedException(indexerResponse, "PTP Query Limit Reached. Please try again later.");
|
throw new RequestLimitReachedException(indexerResponse, "PTP Query Limit Reached. Please try again later.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (httpResponse.StatusCode == HttpStatusCode.TooManyRequests && indexerResponse.Content.Contains("We are not a TV indexer"))
|
|
||||||
{
|
|
||||||
throw new IndexerException(indexerResponse, "Invalid indexer request: We are not a TV indexer", HttpStatusCode.BadRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (httpResponse.StatusCode == HttpStatusCode.TooManyRequests)
|
|
||||||
{
|
|
||||||
throw new RequestLimitReachedException(indexerResponse, "PTP Request Limit Reached. Please try again later.");
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerResponse.HttpResponse.StatusCode} code from indexer request");
|
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerResponse.HttpResponse.StatusCode} code from indexer request");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
|
@ -116,7 +115,6 @@ private IEnumerable<IndexerRequest> GetRequest(string searchTerm, SearchCriteria
|
||||||
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
|
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
|
||||||
request.HttpRequest.Headers.Add("ApiUser", _settings.APIUser);
|
request.HttpRequest.Headers.Add("ApiUser", _settings.APIUser);
|
||||||
request.HttpRequest.Headers.Add("ApiKey", _settings.APIKey);
|
request.HttpRequest.Headers.Add("ApiKey", _settings.APIKey);
|
||||||
request.HttpRequest.SuppressHttpErrorStatusCodes = new[] { HttpStatusCode.TooManyRequests };
|
|
||||||
|
|
||||||
yield return request;
|
yield return request;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,7 @@ public class RevolutionTT : TorrentIndexerBase<UserPassTorrentBaseSettings>
|
||||||
{
|
{
|
||||||
public override string Name => "RevolutionTT";
|
public override string Name => "RevolutionTT";
|
||||||
|
|
||||||
public override string[] IndexerUrls => new[] { "https://revott.me/" };
|
public override string[] IndexerUrls => new[] { "https://revolutiontt.me/" };
|
||||||
public override string[] LegacyUrls => new[] { "https://revolutiontt.me/" };
|
|
||||||
public override string Description => "The Revolution has begun";
|
public override string Description => "The Revolution has begun";
|
||||||
private string LoginUrl => Settings.BaseUrl + "takelogin.php";
|
private string LoginUrl => Settings.BaseUrl + "takelogin.php";
|
||||||
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
||||||
|
|
|
||||||
|
|
@ -1541,7 +1541,7 @@ private IEnumerable<IndexerRequest> GetPagedRequests(string term, string[] track
|
||||||
|
|
||||||
if (season != 0)
|
if (season != 0)
|
||||||
{
|
{
|
||||||
searchString += " ТВ | Сезон: " + season;
|
searchString += " Сезон: " + season;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters.Set("nm", searchString);
|
parameters.Set("nm", searchString);
|
||||||
|
|
@ -1712,8 +1712,6 @@ public class RuTrackerTitleParser
|
||||||
private readonly Regex _tvTitleRusSeasonRegex = new(@"Сезон\s*[:]*\s+(\d+(?:-\d+)?)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private readonly Regex _tvTitleRusSeasonRegex = new(@"Сезон\s*[:]*\s+(\d+(?:-\d+)?)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
private readonly Regex _tvTitleRusEpisodeOfRegex = new(@"(?:Серии|Эпизод|Выпуски)+\s*[:]*\s+(\d+(?:-\d+)?)\s*из\s*([\w?])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private readonly Regex _tvTitleRusEpisodeOfRegex = new(@"(?:Серии|Эпизод|Выпуски)+\s*[:]*\s+(\d+(?:-\d+)?)\s*из\s*([\w?])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
private readonly Regex _tvTitleRusEpisodeRegex = new(@"(?:Серии|Эпизод|Выпуски)+\s*[:]*\s+(\d+(?:-\d+)?)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private readonly Regex _tvTitleRusEpisodeRegex = new(@"(?:Серии|Эпизод|Выпуски)+\s*[:]*\s+(\d+(?:-\d+)?)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
private readonly Regex _tvTitleRusSeasonAnimeRegex = new(@"ТВ[-]*(?:(\d+))", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
|
||||||
private readonly Regex _tvTitleRusEpisodeAnimeOfRegex = new(@"\[(\d+(\+\d+)?)\s+из\s+(\d+(\+\d+)?)\]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
|
||||||
|
|
||||||
public string Parse(string title,
|
public string Parse(string title,
|
||||||
ICollection<IndexerCategory> categories,
|
ICollection<IndexerCategory> categories,
|
||||||
|
|
@ -1738,8 +1736,6 @@ public string Parse(string title,
|
||||||
title = _tvTitleRusSeasonRegex.Replace(title, "S$1");
|
title = _tvTitleRusSeasonRegex.Replace(title, "S$1");
|
||||||
title = _tvTitleRusEpisodeOfRegex.Replace(title, "E$1 of $2");
|
title = _tvTitleRusEpisodeOfRegex.Replace(title, "E$1 of $2");
|
||||||
title = _tvTitleRusEpisodeRegex.Replace(title, "E$1");
|
title = _tvTitleRusEpisodeRegex.Replace(title, "E$1");
|
||||||
title = _tvTitleRusSeasonAnimeRegex.Replace(title, "S$1");
|
|
||||||
title = _tvTitleRusEpisodeAnimeOfRegex.Replace(title, "E$1 of $3");
|
|
||||||
}
|
}
|
||||||
else if (IsAnyMovieCategory(categories))
|
else if (IsAnyMovieCategory(categories))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,7 @@ namespace NzbDrone.Core.Indexers.Definitions;
|
||||||
public class Shazbat : TorrentIndexerBase<ShazbatSettings>
|
public class Shazbat : TorrentIndexerBase<ShazbatSettings>
|
||||||
{
|
{
|
||||||
public override string Name => "Shazbat";
|
public override string Name => "Shazbat";
|
||||||
public override string[] IndexerUrls => new[] { "https://www.shazbat.tube/" };
|
public override string[] IndexerUrls => new[] { "https://www.shazbat.tv/" };
|
||||||
public override string[] LegacyUrls => new[] { "https://www.shazbat.tv/" };
|
|
||||||
public override string Description => "Shazbat is a PRIVATE Torrent Tracker with highly curated TV content";
|
public override string Description => "Shazbat is a PRIVATE Torrent Tracker with highly curated TV content";
|
||||||
public override string Language => "en-US";
|
public override string Language => "en-US";
|
||||||
public override Encoding Encoding => Encoding.UTF8;
|
public override Encoding Encoding => Encoding.UTF8;
|
||||||
|
|
@ -69,8 +68,8 @@ protected override async Task DoLogin()
|
||||||
.AddFormParameter("referer", "")
|
.AddFormParameter("referer", "")
|
||||||
.AddFormParameter("query", "")
|
.AddFormParameter("query", "")
|
||||||
.AddFormParameter("tv_timezone", "0")
|
.AddFormParameter("tv_timezone", "0")
|
||||||
.AddFormParameter("username", Settings.Username)
|
.AddFormParameter("tv_login", Settings.Username)
|
||||||
.AddFormParameter("password", Settings.Password)
|
.AddFormParameter("tv_password", Settings.Password)
|
||||||
.SetHeader("Content-Type", "application/x-www-form-urlencoded")
|
.SetHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||||
.SetHeader("Referer", loginUrl)
|
.SetHeader("Referer", loginUrl)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
@ -92,9 +91,9 @@ protected override async Task DoLogin()
|
||||||
_logger.Debug("Authentication succeeded.");
|
_logger.Debug("Authentication succeeded.");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
|
protected override bool CheckIfLoginNeeded(HttpResponse response)
|
||||||
{
|
{
|
||||||
return (httpResponse.HasHttpRedirect && httpResponse.RedirectUrl.ContainsIgnoreCase("login")) || httpResponse.Content.ContainsIgnoreCase("sign in now");
|
return response.Content.ContainsIgnoreCase("sign in now");
|
||||||
}
|
}
|
||||||
|
|
||||||
private IndexerCapabilities SetCapabilities()
|
private IndexerCapabilities SetCapabilities()
|
||||||
|
|
@ -202,7 +201,7 @@ private static string FixSearchTerm(string term)
|
||||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class ShazbatParser : IParseIndexerResponse
|
public class ShazbatParser : IParseIndexerResponse
|
||||||
{
|
{
|
||||||
private readonly ProviderDefinition _definition;
|
private readonly ProviderDefinition _definition;
|
||||||
private readonly ShazbatSettings _settings;
|
private readonly ShazbatSettings _settings;
|
||||||
|
|
@ -210,10 +209,8 @@ public partial class ShazbatParser : IParseIndexerResponse
|
||||||
private readonly IIndexerHttpClient _httpClient;
|
private readonly IIndexerHttpClient _httpClient;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
private readonly HashSet<string> _hdResolutions = ["1080p", "1080i", "720p"];
|
private readonly Regex _torrentInfoRegex = new(@"\((?<size>\d+)\):(?<seeders>\d+) \/ :(?<leechers>\d+)$", RegexOptions.Compiled);
|
||||||
|
private readonly HashSet<string> _hdResolutions = new() { "1080p", "1080i", "720p" };
|
||||||
[GeneratedRegex(@"\((?<size>\d+)\)\s*:(?<seeders>\d+) \/ :(?<leechers>\d+)$", RegexOptions.Compiled)]
|
|
||||||
private static partial Regex TorrentInfoRegex();
|
|
||||||
|
|
||||||
public ShazbatParser(ProviderDefinition definition, ShazbatSettings settings, TimeSpan rateLimit, IIndexerHttpClient httpClient, Logger logger)
|
public ShazbatParser(ProviderDefinition definition, ShazbatSettings settings, TimeSpan rateLimit, IIndexerHttpClient httpClient, Logger logger)
|
||||||
{
|
{
|
||||||
|
|
@ -280,8 +277,7 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||||
var releaseRequest = new IndexerRequest(showRequest);
|
var releaseRequest = new IndexerRequest(showRequest);
|
||||||
var releaseResponse = new IndexerResponse(releaseRequest, _httpClient.ExecuteProxied(releaseRequest.HttpRequest, _definition));
|
var releaseResponse = new IndexerResponse(releaseRequest, _httpClient.ExecuteProxied(releaseRequest.HttpRequest, _definition));
|
||||||
|
|
||||||
if ((releaseResponse.HttpResponse.HasHttpRedirect && releaseResponse.HttpResponse.RedirectUrl.ContainsIgnoreCase("login")) ||
|
if (releaseResponse.HttpResponse.Content.ContainsIgnoreCase("sign in now"))
|
||||||
releaseResponse.HttpResponse.Content.ContainsIgnoreCase("sign in now"))
|
|
||||||
{
|
{
|
||||||
// Remove cookie cache
|
// Remove cookie cache
|
||||||
CookiesUpdater(null, null);
|
CookiesUpdater(null, null);
|
||||||
|
|
@ -327,15 +323,13 @@ private IList<ReleaseInfo> ParseResults(IndexerResponse indexerResponse, bool ha
|
||||||
var title = ParseTitle(row.QuerySelector("td:nth-of-type(3)"));
|
var title = ParseTitle(row.QuerySelector("td:nth-of-type(3)"));
|
||||||
|
|
||||||
var infoString = row.QuerySelector("td:nth-of-type(4)")?.TextContent.Trim() ?? string.Empty;
|
var infoString = row.QuerySelector("td:nth-of-type(4)")?.TextContent.Trim() ?? string.Empty;
|
||||||
var matchInfo = TorrentInfoRegex().Match(infoString);
|
var matchInfo = _torrentInfoRegex.Match(infoString);
|
||||||
var size = matchInfo.Groups["size"].Success && long.TryParse(matchInfo.Groups["size"].Value, out var outSize) ? outSize : 0;
|
var size = matchInfo.Groups["size"].Success && long.TryParse(matchInfo.Groups["size"].Value, out var outSize) ? outSize : 0;
|
||||||
var seeders = matchInfo.Groups["seeders"].Success && int.TryParse(matchInfo.Groups["seeders"].Value, out var outSeeders) ? outSeeders : 0;
|
var seeders = matchInfo.Groups["seeders"].Success && int.TryParse(matchInfo.Groups["seeders"].Value, out var outSeeders) ? outSeeders : 0;
|
||||||
var leechers = matchInfo.Groups["leechers"].Success && int.TryParse(matchInfo.Groups["leechers"].Value, out var outLeechers) ? outLeechers : 0;
|
var leechers = matchInfo.Groups["leechers"].Success && int.TryParse(matchInfo.Groups["leechers"].Value, out var outLeechers) ? outLeechers : 0;
|
||||||
|
|
||||||
var dateTimestamp = row.QuerySelector(".datetime[data-timestamp]")?.GetAttribute("data-timestamp");
|
var dateTimestamp = row.QuerySelector(".datetime[data-timestamp]")?.GetAttribute("data-timestamp");
|
||||||
publishDate = dateTimestamp != null && ParseUtil.TryCoerceLong(dateTimestamp, out var timestamp)
|
publishDate = dateTimestamp != null && ParseUtil.TryCoerceDouble(dateTimestamp, out var timestamp) ? DateTimeUtil.UnixTimestampToDateTime(timestamp) : publishDate.AddMinutes(-1);
|
||||||
? DateTimeUtil.UnixTimestampToDateTime(timestamp)
|
|
||||||
: publishDate.AddMinutes(-1);
|
|
||||||
|
|
||||||
var release = new TorrentInfo
|
var release = new TorrentInfo
|
||||||
{
|
{
|
||||||
|
|
@ -369,10 +363,10 @@ private static string ParseTitle(IElement titleRow)
|
||||||
return title?.TextContent.Trim();
|
return title?.TextContent.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IndexerCategory> ParseCategories(string title)
|
protected virtual List<IndexerCategory> ParseCategories(string title)
|
||||||
{
|
{
|
||||||
return
|
var categories = new List<IndexerCategory>
|
||||||
[
|
{
|
||||||
NewznabStandardCategory.TV,
|
NewznabStandardCategory.TV,
|
||||||
title switch
|
title switch
|
||||||
{
|
{
|
||||||
|
|
@ -380,7 +374,9 @@ _ when _hdResolutions.Any(title.Contains) => NewznabStandardCategory.TVHD,
|
||||||
_ when title.Contains("2160p") => NewznabStandardCategory.TVUHD,
|
_ when title.Contains("2160p") => NewznabStandardCategory.TVUHD,
|
||||||
_ => NewznabStandardCategory.TVSD
|
_ => NewznabStandardCategory.TVSD
|
||||||
}
|
}
|
||||||
];
|
};
|
||||||
|
|
||||||
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -662,13 +662,5 @@
|
||||||
"DownloadClientFloodSettingsTagsHelpText": "Initiële tags van een download. Om herkend te worden, moet een download alle initiële tags hebben. Dit voorkomt conflicten met niet-gerelateerde downloads.",
|
"DownloadClientFloodSettingsTagsHelpText": "Initiële tags van een download. Om herkend te worden, moet een download alle initiële tags hebben. Dit voorkomt conflicten met niet-gerelateerde downloads.",
|
||||||
"IndexerNewznabSettingsVipExpirationHelpText": "Voer de datum in (jjjj-mm-dd) voor VIP-vervaldatum of laat leeg. {appName} zal 1 week voor het verstrijken van de VIP-periode een melding geven",
|
"IndexerNewznabSettingsVipExpirationHelpText": "Voer de datum in (jjjj-mm-dd) voor VIP-vervaldatum of laat leeg. {appName} zal 1 week voor het verstrijken van de VIP-periode een melding geven",
|
||||||
"DownloadClientSettingsDefaultCategorySubFolderHelpText": "Standaard fallback-categorie als er geen gekoppelde categorie bestaat voor een release. Het toevoegen van een categorie specifiek voor {appName} voorkomt conflicten met niet-gerelateerde downloads die niet van {appName} zijn. Het gebruik van een categorie is optioneel, maar wordt sterk aanbevolen. Er wordt een [categorie]-submap aangemaakt in de uitvoermap.",
|
"DownloadClientSettingsDefaultCategorySubFolderHelpText": "Standaard fallback-categorie als er geen gekoppelde categorie bestaat voor een release. Het toevoegen van een categorie specifiek voor {appName} voorkomt conflicten met niet-gerelateerde downloads die niet van {appName} zijn. Het gebruik van een categorie is optioneel, maar wordt sterk aanbevolen. Er wordt een [categorie]-submap aangemaakt in de uitvoermap.",
|
||||||
"IndexerPassThePopcornSettingsApiUserHelpText": "Deze instellingen vind je in je PassThePopcorn beveiligingsinstellingen (Profiel bewerken > Beveiliging).",
|
"IndexerPassThePopcornSettingsApiUserHelpText": "Deze instellingen vind je in je PassThePopcorn beveiligingsinstellingen (Profiel bewerken > Beveiliging)."
|
||||||
"IndexerGazelleGamesSettingsFreeleechOnlyHelpText": "Doorzoek alleen freeleech releases",
|
|
||||||
"UsenetBlackholeNzbFolder": "Nzb map",
|
|
||||||
"IndexerSettingsAppsMinimumSeedersHelpText": "Minimum aantal vereiste seeders door de applicaties voordat de indexer iets ophaalt. Leeg laten gebruikt de standaardwaarde van het synchronisatieprofiel",
|
|
||||||
"IndexerBeyondHDSettingsFreeleechOnlyHelpText": "Doorzoek alleen freeleech releases",
|
|
||||||
"IndexerTorrentSyndikatSettingsApiKeyHelpText": "Site API-sleutel",
|
|
||||||
"SearchTypes": "Zoek types",
|
|
||||||
"IndexerAlphaRatioSettingsFreeleechOnlyHelpText": "Doorzoek alleen freeleech releases",
|
|
||||||
"IndexerAvistazSettingsFreeleechOnlyHelpText": "Doorzoek alleen freeleech releases"
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
"Album": "專輯",
|
"Album": "專輯",
|
||||||
"Authentication": "認證",
|
"Authentication": "認證",
|
||||||
"AutomaticSearch": "自動搜尋",
|
"AutomaticSearch": "自動搜尋",
|
||||||
"BackupFolderHelpText": "相對路徑將位於 {appName} 的 AppData 目錄下",
|
"BackupFolderHelpText": "相對路徑將位於Radarr的AppData目錄下",
|
||||||
"BackupNow": "馬上備份",
|
"BackupNow": "馬上備份",
|
||||||
"BackupRetentionHelpText": "超過保留期的自動備份將被自動清理",
|
"BackupRetentionHelpText": "超過保留期的自動備份將被自動清理",
|
||||||
"BindAddress": "綁定地址(Bind Address)",
|
"BindAddress": "綁定地址(Bind Address)",
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
"Theme": "主題",
|
"Theme": "主題",
|
||||||
"ApiKeyValidationHealthCheckMessage": "請將您的API金鑰更新為至少{length}個字元長。您可以通過設定或配置文件進行此操作。",
|
"ApiKeyValidationHealthCheckMessage": "請將您的API金鑰更新為至少{length}個字元長。您可以通過設定或配置文件進行此操作。",
|
||||||
"AppDataLocationHealthCheckMessage": "為了避免在更新過程中刪除AppData,將無法進行更新。",
|
"AppDataLocationHealthCheckMessage": "為了避免在更新過程中刪除AppData,將無法進行更新。",
|
||||||
"AuthenticationMethodHelpText": "需要使用者名稱和密碼才能存取 {appName}",
|
"AuthenticationMethodHelpText": "需要使用者名稱和密碼來存取Radarr",
|
||||||
"Backup": "備份",
|
"Backup": "備份",
|
||||||
"Enable": "啟用",
|
"Enable": "啟用",
|
||||||
"Grabs": "抓取",
|
"Grabs": "抓取",
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
"Seeders": "種子",
|
"Seeders": "種子",
|
||||||
"Settings": "設定",
|
"Settings": "設定",
|
||||||
"DownloadClients": "下載用戶端",
|
"DownloadClients": "下載用戶端",
|
||||||
"AnalyticsEnabledHelpText": "傳送匿名使用和錯誤資訊到 {appName} 的伺服器。這包括您的瀏覽器資訊、您使用的 {appName} WebUI 頁面、錯誤報告以及作業系統和執行階段版本。我們將使用這些資訊來優先處理功能和錯誤修正。",
|
"AnalyticsEnabledHelpText": "將使用和錯誤資訊匿名傳送至Radarr的伺服器。這些資訊包括您的瀏覽器資訊、使用的Radarr WebUI頁面、錯誤報告,以及作業系統和執行時版本。我們將使用這些資訊來優先處理功能和錯誤修復。",
|
||||||
"ApiKey": "API 金鑰",
|
"ApiKey": "API 金鑰",
|
||||||
"AppDataDirectory": "AppData 路徑",
|
"AppDataDirectory": "AppData 路徑",
|
||||||
"Applications": "應用程式",
|
"Applications": "應用程式",
|
||||||
|
|
@ -135,7 +135,7 @@
|
||||||
"IndexerHDBitsSettingsCodecs": "編解碼器",
|
"IndexerHDBitsSettingsCodecs": "編解碼器",
|
||||||
"Directory": "目錄",
|
"Directory": "目錄",
|
||||||
"BuiltIn": "內建的",
|
"BuiltIn": "內建的",
|
||||||
"AllSearchResultsHiddenByFilter": "根據所使用的篩選器已將所有結果隱藏。",
|
"AllSearchResultsHiddenByFilter": "根據所使用的篩選器已將所有結果隱藏",
|
||||||
"AptUpdater": "使用apt安裝更新",
|
"AptUpdater": "使用apt安裝更新",
|
||||||
"Discord": "Discord",
|
"Discord": "Discord",
|
||||||
"Any": "任何",
|
"Any": "任何",
|
||||||
|
|
|
||||||
|
|
@ -6,23 +6,23 @@
|
||||||
<PackageReference Include="AngleSharp.Xml" Version="1.0.0" />
|
<PackageReference Include="AngleSharp.Xml" Version="1.0.0" />
|
||||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||||
<PackageReference Include="Diacritical.Net" Version="1.0.4" />
|
<PackageReference Include="Diacritical.Net" Version="1.0.4" />
|
||||||
<PackageReference Include="MailKit" Version="4.14.0" />
|
<PackageReference Include="MailKit" Version="4.12.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.16" />
|
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.16" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.16" />
|
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.16" />
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.1" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
|
||||||
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||||
<PackageReference Include="Npgsql" Version="9.0.3" />
|
<PackageReference Include="Npgsql" Version="9.0.3" />
|
||||||
<PackageReference Include="Polly" Version="8.6.4" />
|
<PackageReference Include="Polly" Version="8.6.0" />
|
||||||
<PackageReference Include="Servarr.FluentMigrator.Runner" Version="3.3.2.9" />
|
<PackageReference Include="Servarr.FluentMigrator.Runner" Version="3.3.2.9" />
|
||||||
<PackageReference Include="Servarr.FluentMigrator.Runner.Postgres" Version="3.3.2.9" />
|
<PackageReference Include="Servarr.FluentMigrator.Runner.Postgres" Version="3.3.2.9" />
|
||||||
<PackageReference Include="Servarr.FluentMigrator.Runner.SQLite" Version="3.3.2.9" />
|
<PackageReference Include="Servarr.FluentMigrator.Runner.SQLite" Version="3.3.2.9" />
|
||||||
<PackageReference Include="System.Drawing.Common" Version="8.0.19" />
|
|
||||||
<PackageReference Include="System.Memory" Version="4.6.3" />
|
<PackageReference Include="System.Memory" Version="4.6.3" />
|
||||||
<PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" />
|
<PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" />
|
||||||
<PackageReference Include="FluentValidation" Version="9.5.4" />
|
<PackageReference Include="FluentValidation" Version="9.5.4" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="NLog" Version="5.4.0" />
|
<PackageReference Include="NLog" Version="5.4.0" />
|
||||||
<PackageReference Include="System.Text.Json" Version="8.0.6" />
|
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||||
|
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||||
<PackageReference Include="MonoTorrent" Version="2.0.7" />
|
<PackageReference Include="MonoTorrent" Version="2.0.7" />
|
||||||
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
||||||
<PackageReference Include="AngleSharp" Version="1.3.0" />
|
<PackageReference Include="AngleSharp" Version="1.3.0" />
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
|
@ -32,7 +31,6 @@
|
||||||
using Prowlarr.Http.ErrorManagement;
|
using Prowlarr.Http.ErrorManagement;
|
||||||
using Prowlarr.Http.Frontend;
|
using Prowlarr.Http.Frontend;
|
||||||
using Prowlarr.Http.Middleware;
|
using Prowlarr.Http.Middleware;
|
||||||
using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;
|
|
||||||
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
||||||
|
|
||||||
namespace NzbDrone.Host
|
namespace NzbDrone.Host
|
||||||
|
|
@ -61,11 +59,8 @@ public void ConfigureServices(IServiceCollection services)
|
||||||
services.Configure<ForwardedHeadersOptions>(options =>
|
services.Configure<ForwardedHeadersOptions>(options =>
|
||||||
{
|
{
|
||||||
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
|
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
|
||||||
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
|
options.KnownNetworks.Clear();
|
||||||
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12));
|
options.KnownProxies.Clear();
|
||||||
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16));
|
|
||||||
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("fc00::"), 7));
|
|
||||||
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("fe80::"), 10));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddRouting(options => options.LowercaseUrls = true);
|
services.AddRouting(options => options.LowercaseUrls = true);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<DataCollectors>
|
<DataCollectors>
|
||||||
<DataCollector friendlyName="XPlat code coverage">
|
<DataCollector friendlyName="XPlat code coverage">
|
||||||
<Configuration>
|
<Configuration>
|
||||||
<Format>cobertura</Format>
|
<Format>opencover</Format>
|
||||||
<Exclude>[Prowlarr.*.Test]*,[Prowlarr.Test.*]*,[Prowlarr.Api*]*</Exclude>
|
<Exclude>[Prowlarr.*.Test]*,[Prowlarr.Test.*]*,[Prowlarr.Api*]*</Exclude>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
</DataCollector>
|
</DataCollector>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue