Compare commits

...

56 Commits

Author SHA1 Message Date
Bogdan 950949e4bc Bump Polly to 8.6.0 2025-06-12 09:56:52 +03:00
Bogdan fe198352a3 Fixed: Fallback to Forms for removed Basic auth method 2025-06-11 20:13:03 +03:00
Bogdan 88502cd020 Fixed: (AnimeTosho) Mapping of Subcategory as Parent 2025-06-11 10:32:21 +03:00
Bogdan 4924b45b56 Fix various typos 2025-06-10 18:36:14 +03:00
Bogdan aea8b7cd7e Fixed: Redirect loop for removed basic auth method 2025-06-10 12:33:52 +03:00
Bogdan aafadb6111 Fix fullscreen automation screenshots 2025-06-09 22:08:00 +03:00
Mark McDowall c82f904d49 New: Add exception to SSL Certificate validation message
(cherry picked from commit d84c4500949a530fac92d73f7f2f8e8462b37244)
2025-06-08 16:37:52 +03:00
Servarr 60740fa259 Automated API Docs update 2025-06-08 10:33:02 +03:00
Mark McDowall d36b32f414 New: Remove Basic Auth
(cherry picked from commit 0f9e063e2146812f6e963363eee70a524612f354)
2025-06-07 19:23:03 +03:00
Bogdan 14ccd6d2a5 Fixed: Validation for tags label 2025-06-07 19:23:03 +03:00
Bogdan bdc3b63df2 Upgrade StyleCop.Analyzers to Unstable 1.2.0.556 2025-06-07 19:23:03 +03:00
Bogdan 8eec321a0e Bump Swashbuckle to 8.1.4 2025-06-07 19:23:03 +03:00
Bogdan 06de2313ab Bump version to 2.0.0 2025-06-07 19:23:03 +03:00
Bogdan a3f713bad8 New: Support removed for linux-x86 2025-06-07 19:23:03 +03:00
Bogdan 7a1fca5e23 New: Migrate appdata folder for .NET 8 on OSX 2025-06-07 19:23:03 +03:00
Bogdan 21c408a7da New: Bump to .NET 8 2025-06-07 19:23:03 +03:00
Weblate 0e92108970 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Ilbebino <tommasobellandi08@gmail.com>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2025-06-06 14:41:02 +03:00
Bogdan 7d813ef97a Bump version to 1.38.0 2025-06-04 14:05:21 +03:00
Bogdan c87995250a Fixed: Sync indexers with basic search to Radarr and Sonarr
Fixes #2404
2025-06-03 14:26:09 +03:00
Bogdan a9f7a376c7 Bump version to 1.37.0 2025-05-25 17:00:17 +03:00
Bogdan c3ee3f2320 Fix jump to character for Search page 2025-05-25 14:04:33 +03:00
Weblate e8c26d0fea Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: thelooter <evekolb2204@gmail.com>
Co-authored-by: warkurre86 <tom.novo.86@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translation: Servarr/Prowlarr
2025-05-25 12:05:56 +03:00
Bogdan 9c936121e8 Fixed: Sync indexers with basic search to Lidarr and Readarr
Fixes #2402
2025-05-22 13:30:41 +03:00
Bogdan 40d2e40d94 Fail build on missing test results
Ignore missing test results failure on FreeBSD
2025-05-18 18:01:13 +03:00
Weblate 837f50c91c Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Hugoren Martinako <aumpfbahn@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2025-05-18 14:10:34 +03:00
Bogdan f0a0202e5c Bump version to 1.36.3 2025-05-18 14:10:14 +03:00
Bogdan 708c94bc56 Fixed PTP test 2025-05-15 00:47:46 +03:00
Bogdan 5ed82eaf09 Fixed: (PTP) Download torrent files with API credentials 2025-05-14 22:44:26 +03:00
Bogdan 7d77ad68fd Bump caniuse db 2025-05-14 21:25:20 +03:00
Bogdan 6725358db5 Bump babel, fontawesome icons, react-use-measure, react-virtualized and react-window 2025-05-14 21:25:20 +03:00
Bogdan c410e23460 Bump core-js to 3.42 2025-05-14 21:25:20 +03:00
Bogdan 903b86b9a2 Bump version to 1.36.2 2025-05-11 14:48:48 +03:00
Weblate 52a49e6a34 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Discover999 <13189912235@163.com>
Co-authored-by: GkhnGRBZ <gkhn.gurbuz@hotmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: ZijiYu <ziji.yu@stonybrook.edu>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_Hans/
Translation: Servarr/Prowlarr
2025-05-11 00:07:11 +03:00
Bogdan a7d99f351c Fixed: Parsing user agents without a version
Fixes #2392
2025-05-11 00:05:29 +03:00
Bogdan b0212dd780 Add hourly limits as defaults for PTP 2025-05-10 11:55:11 +03:00
Bogdan c8f5099423 Use the thrown exception in http timeout handling 2025-05-09 15:58:02 +03:00
Bogdan 5cc4c3f302 Bump version to 1.36.1 2025-05-04 21:06:28 +03:00
Bogdan c0d2cb42e9 Fixed: (PTP) Sorting releases by time added 2025-05-01 17:06:17 +03:00
Bogdan 8081f13052 Clean logging messages in AppriseProxy 2025-05-01 12:12:47 +03:00
Bogdan 84b672e617 Fixed: Sync indexers to apps only if search is available 2025-05-01 01:34:09 +03:00
Bogdan ed586c2d72 Update fixture file for PTP 2025-05-01 00:30:55 +03:00
Bogdan 233176e321 Improve error message when BHD's API responds with HTML 2025-04-30 22:12:30 +03:00
Bogdan d1e3390bae Fixed: (PTP) Category mapping for search results 2025-04-30 22:12:30 +03:00
Bogdan 1cd60c7a40 Bump version to 1.36.0 2025-04-30 14:03:05 +03:00
Bogdan c61cfcd312 Avoid logging the whole response in the exception when not finding JSON selectors in Cardigann 2025-04-30 12:36:34 +03:00
Weblate 5eb4d112ca Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translation: Servarr/Prowlarr
2025-04-29 11:05:21 +03:00
Mark McDowall 70f2361d69 Improve messaging when NZB contains invalid XML
(cherry picked from commit 728df146ada115a367bf1ce808482a4625e6098d)
2025-04-29 10:58:31 +03:00
Bogdan 1d6babaa15 Bump caniuse db 2025-04-29 10:23:51 +03:00
Bogdan 0427add8d0 Bump core-js to 3.41 2025-04-29 10:23:15 +03:00
Bogdan 010c2b836d Clean up formatted strings in log messages 2025-04-29 10:16:59 +03:00
Bogdan 22c4c1fc9a Pass messages with arguments to NLog in LoggerExtensions
(cherry picked from commit 9683b0af35220bb0af801779a06d73feaeba809a)
2025-04-29 10:14:32 +03:00
Bogdan d5f6cc94b8 Fixed: (PTP) TV search capabilities removed 2025-04-29 10:04:40 +03:00
Bogdan 411e96ef2a New: Redirect enabled by default when adding new usenet indexers 2025-04-28 21:52:09 +03:00
Bogdan 2b0e52ebca Update default log level message 2025-04-27 21:22:37 +03:00
Bogdan c6fa26ca7b Bump version to 1.35.1 2025-04-27 11:48:50 +03:00
blu3 c85f170d41 Bump license year 2025-04-23 11:34:19 +03:00
219 changed files with 1955 additions and 1630 deletions
+2 -2
View File
@@ -2,11 +2,11 @@
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
{
"name": "Prowlarr",
"image": "mcr.microsoft.com/devcontainers/dotnet:1-6.0",
"image": "mcr.microsoft.com/devcontainers/dotnet:1-8.0",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"nodeGypDependencies": true,
"version": "16",
"version": "20",
"nvmVersion": "latest"
}
},
+1 -1
View File
@@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build dotnet",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/_output/net6.0/Prowlarr",
"program": "${workspaceFolder}/_output/net8.0/Prowlarr",
"args": [],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
+1 -1
View File
@@ -78,6 +78,6 @@ Thank you to [<img src="https://resources.jetbrains.com/storage/products/company
### License
- [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
- Copyright 2010-2024
- Copyright 2010-2025
Icon Credit - [Box vector created by freepik - www.freepik.com](https://www.freepik.com/vectors/box)
+34 -58
View File
@@ -9,13 +9,13 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '1.35.0'
majorVersion: '2.0.0'
minorVersion: $[counter('minorVersion', 1)]
prowlarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.427'
dotnetVersion: '8.0.405'
nodeVersion: '20.X'
innoVersion: '6.2.2'
windowsImage: 'windows-2022'
@@ -106,7 +106,7 @@ stages:
echo "Extra platforms already enabled"
else
echo "Enabling extra platform support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64;linux-x86/' $BUNDLEDVERSIONS
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64/' "$BUNDLEDVERSIONS"
fi
displayName: Enable Extra Platform Support
- bash: ./build.sh --backend --enable-extra-platforms
@@ -122,27 +122,23 @@ stages:
artifact: '$(osName)Backend'
displayName: Publish Backend
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/win-x64/publish'
- publish: '$(testsFolder)/net8.0/win-x64/publish'
artifact: win-x64-tests
displayName: Publish win-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-x64/publish'
- publish: '$(testsFolder)/net8.0/linux-x64/publish'
artifact: linux-x64-tests
displayName: Publish linux-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-x86/publish'
artifact: linux-x86-tests
displayName: Publish linux-x86 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-musl-x64/publish'
- publish: '$(testsFolder)/net8.0/linux-musl-x64/publish'
artifact: linux-musl-x64-tests
displayName: Publish linux-musl-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/freebsd-x64/publish'
- publish: '$(testsFolder)/net8.0/freebsd-x64/publish'
artifact: freebsd-x64-tests
displayName: Publish freebsd-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/osx-x64/publish'
- publish: '$(testsFolder)/net8.0/osx-x64/publish'
artifact: osx-x64-tests
displayName: Publish osx-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
@@ -259,21 +255,21 @@ stages:
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).windows-core-x64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/win-x64/net6.0
rootFolderOrFile: $(artifactsFolder)/win-x64/net8.0
- task: ArchiveFiles@2
displayName: Create win-x86 zip
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).windows-core-x86.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/win-x86/net6.0
rootFolderOrFile: $(artifactsFolder)/win-x86/net8.0
- task: ArchiveFiles@2
displayName: Create osx-x64 app
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).osx-app-core-x64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-x64-app/net6.0
rootFolderOrFile: $(artifactsFolder)/osx-x64-app/net8.0
- task: ArchiveFiles@2
displayName: Create osx-x64 tar
inputs:
@@ -281,14 +277,14 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-x64/net6.0
rootFolderOrFile: $(artifactsFolder)/osx-x64/net8.0
- task: ArchiveFiles@2
displayName: Create osx-arm64 app
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).osx-app-core-arm64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-arm64-app/net6.0
rootFolderOrFile: $(artifactsFolder)/osx-arm64-app/net8.0
- task: ArchiveFiles@2
displayName: Create osx-arm64 tar
inputs:
@@ -296,7 +292,7 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-arm64/net6.0
rootFolderOrFile: $(artifactsFolder)/osx-arm64/net8.0
- task: ArchiveFiles@2
displayName: Create linux-x64 tar
inputs:
@@ -304,7 +300,7 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-x64/net6.0
rootFolderOrFile: $(artifactsFolder)/linux-x64/net8.0
- task: ArchiveFiles@2
displayName: Create linux-musl-x64 tar
inputs:
@@ -312,15 +308,7 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/net6.0
- task: ArchiveFiles@2
displayName: Create linux-x86 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).linux-core-x86.tar.gz'
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-x86/net6.0
rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/net8.0
- task: ArchiveFiles@2
displayName: Create linux-arm tar
inputs:
@@ -328,7 +316,7 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm/net6.0
rootFolderOrFile: $(artifactsFolder)/linux-arm/net8.0
- task: ArchiveFiles@2
displayName: Create linux-musl-arm tar
inputs:
@@ -336,7 +324,7 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm/net6.0
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm/net8.0
- task: ArchiveFiles@2
displayName: Create linux-arm64 tar
inputs:
@@ -344,7 +332,7 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm64/net6.0
rootFolderOrFile: $(artifactsFolder)/linux-arm64/net8.0
- task: ArchiveFiles@2
displayName: Create linux-musl-arm64 tar
inputs:
@@ -352,7 +340,7 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/net6.0
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/net8.0
- task: ArchiveFiles@2
displayName: Create freebsd-x64 tar
inputs:
@@ -360,7 +348,7 @@ stages:
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/freebsd-x64/net6.0
rootFolderOrFile: $(artifactsFolder)/freebsd-x64/net8.0
- publish: $(Build.ArtifactStagingDirectory)
artifact: 'Packages'
displayName: Publish Packages
@@ -476,6 +464,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(testName) Unit Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: ne(variables['testName'], 'freebsd-x64')
- job: Unit_Docker
displayName: Unit Docker
@@ -487,10 +476,6 @@ stages:
testName: 'Musl Net Core'
artifactName: linux-musl-x64-tests
containerImage: ghcr.io/servarr/testimages:alpine
linux-x86:
testName: 'linux-x86'
artifactName: linux-x86-tests
containerImage: ghcr.io/servarr/testimages:linux-x86
pool:
vmImage: ${{ variables.linuxImage }}
@@ -504,12 +489,6 @@ stages:
displayName: 'Install .NET'
inputs:
version: $(dotnetVersion)
condition: and(succeeded(), ne(variables['testName'], 'linux-x86'))
- bash: |
SDKURL=$(curl -s https://api.github.com/repos/Servarr/dotnet-linux-x86/releases | jq -rc '.[].assets[].browser_download_url' | grep sdk-${DOTNETVERSION}.*gz$)
curl -fsSL $SDKURL | tar xzf - -C /opt/dotnet
displayName: 'Install .NET'
condition: and(succeeded(), eq(variables['testName'], 'linux-x86'))
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
@@ -532,6 +511,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(testName) Unit Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: true
- job: Unit_LinuxCore_Postgres14
displayName: Unit Native LinuxCore with Postgres14 Database
@@ -585,6 +565,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'LinuxCore Postgres14 Unit Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: true
- job: Unit_LinuxCore_Postgres15
displayName: Unit Native LinuxCore with Postgres15 Database
@@ -638,6 +619,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'LinuxCore Postgres15 Unit Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: true
- stage: Integration
displayName: Integration
@@ -720,6 +702,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(testName) Integration Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: true
displayName: Publish Test Results
- job: Integration_LinuxCore_Postgres14
@@ -782,6 +765,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'Integration LinuxCore Postgres14 Database Integration Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: true
displayName: Publish Test Results
@@ -845,6 +829,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'Integration LinuxCore Postgres15 Database Integration Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: true
displayName: Publish Test Results
- job: Integration_FreeBSD
@@ -891,6 +876,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'FreeBSD Integration Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: false
displayName: Publish Test Results
- job: Integration_Docker
@@ -904,11 +890,6 @@ stages:
artifactName: linux-musl-x64-tests
containerImage: ghcr.io/servarr/testimages:alpine
pattern: 'Prowlarr.*.linux-musl-core-x64.tar.gz'
linux-x86:
testName: 'linux-x86'
artifactName: linux-x86-tests
containerImage: ghcr.io/servarr/testimages:linux-x86
pattern: 'Prowlarr.*.linux-core-x86.tar.gz'
pool:
vmImage: ${{ variables.linuxImage }}
@@ -921,12 +902,6 @@ stages:
displayName: 'Install .NET'
inputs:
version: $(dotnetVersion)
condition: and(succeeded(), ne(variables['testName'], 'linux-x86'))
- bash: |
SDKURL=$(curl -s https://api.github.com/repos/Servarr/dotnet-linux-x86/releases | jq -rc '.[].assets[].browser_download_url' | grep sdk-${DOTNETVERSION}.*gz$)
curl -fsSL $SDKURL | tar xzf - -C /opt/dotnet
displayName: 'Install .NET'
condition: and(succeeded(), eq(variables['testName'], 'linux-x86'))
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
@@ -960,6 +935,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(testName) Integration Tests'
failTaskOnFailedTests: true
failTaskOnMissingResultsFile: true
displayName: Publish Test Results
- stage: Automation
@@ -1041,6 +1017,7 @@ stages:
testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(osName) Automation Tests'
failTaskOnFailedTests: $(failBuild)
failTaskOnMissingResultsFile: $(failBuild)
displayName: Publish Test Results
- stage: Analyze
@@ -1184,13 +1161,13 @@ stages:
sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml
sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml
- bash: |
./build.sh --backend -f net6.0 -r win-x64
TEST_DIR=_tests/net6.0/win-x64/publish/ ./test.sh Windows Unit Coverage
./build.sh --backend -f net8.0 -r win-x64
TEST_DIR=_tests/net8.0/win-x64/publish/ ./test.sh Windows Unit Coverage
displayName: Coverage Unit Tests
- task: SonarCloudAnalyze@3
condition: eq(variables['System.PullRequest.IsFork'], 'False')
displayName: Publish SonarCloud Results
- task: reportgenerator@5.3.11
- task: reportgenerator@5
displayName: Generate Coverage Report
inputs:
reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml'
@@ -1228,4 +1205,3 @@ stages:
DISCORDCHANNELID: $(discordChannelId)
DISCORDWEBHOOKKEY: $(discordWebhookKey)
DISCORDTHREADID: $(discordThreadId)
+25 -27
View File
@@ -33,14 +33,14 @@ EnableExtraPlatformsInSDK()
echo "Extra platforms already enabled"
else
echo "Enabling extra platform support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64;linux-x86/' $BUNDLEDVERSIONS
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64/' "$BUNDLEDVERSIONS"
fi
}
EnableExtraPlatforms()
{
if grep -qv freebsd-x64 src/Directory.Build.props; then
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64;linux-x86</RuntimeIdentifiers>^g" src/Directory.Build.props
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64</RuntimeIdentifiers>^g" src/Directory.Build.props
fi
}
@@ -79,9 +79,9 @@ Build()
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
then
dotnet msbuild -restore $slnFile -p:Configuration=Release -p:Platform=$platform -t:PublishAllRids
dotnet msbuild -restore $slnFile -p:SelfContained=True -p:Configuration=Release -p:Platform=$platform -t:PublishAllRids
else
dotnet msbuild -restore $slnFile -p:Configuration=Release -p:Platform=$platform -p:RuntimeIdentifiers=$RID -t:PublishAllRids
dotnet msbuild -restore $slnFile -p:SelfContained=True -p:Configuration=Release -p:Platform=$platform -p:RuntimeIdentifiers=$RID -t:PublishAllRids
fi
ProgressEnd 'Build'
@@ -137,7 +137,7 @@ PackageLinux()
echo "Adding Prowlarr.Mono to UpdatePackage"
cp $folder/Prowlarr.Mono.* $folder/Prowlarr.Update
if [ "$framework" = "net6.0" ]; then
if [ "$framework" = "net8.0" ]; then
cp $folder/Mono.Posix.NETStandard.* $folder/Prowlarr.Update
cp $folder/libMonoPosixHelper.* $folder/Prowlarr.Update
fi
@@ -165,7 +165,7 @@ PackageMacOS()
echo "Adding Prowlarr.Mono to UpdatePackage"
cp $folder/Prowlarr.Mono.* $folder/Prowlarr.Update
if [ "$framework" = "net6.0" ]; then
if [ "$framework" = "net8.0" ]; then
cp $folder/Mono.Posix.NETStandard.* $folder/Prowlarr.Update
cp $folder/libMonoPosixHelper.* $folder/Prowlarr.Update
fi
@@ -377,15 +377,14 @@ then
Build
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
then
PackageTests "net6.0" "win-x64"
PackageTests "net6.0" "win-x86"
PackageTests "net6.0" "linux-x64"
PackageTests "net6.0" "linux-musl-x64"
PackageTests "net6.0" "osx-x64"
PackageTests "net8.0" "win-x64"
PackageTests "net8.0" "win-x86"
PackageTests "net8.0" "linux-x64"
PackageTests "net8.0" "linux-musl-x64"
PackageTests "net8.0" "osx-x64"
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
then
PackageTests "net6.0" "freebsd-x64"
PackageTests "net6.0" "linux-x86"
PackageTests "net8.0" "freebsd-x64"
fi
else
PackageTests "$FRAMEWORK" "$RID"
@@ -413,20 +412,19 @@ then
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
then
Package "net6.0" "win-x64"
Package "net6.0" "win-x86"
Package "net6.0" "linux-x64"
Package "net6.0" "linux-musl-x64"
Package "net6.0" "linux-arm64"
Package "net6.0" "linux-musl-arm64"
Package "net6.0" "linux-arm"
Package "net6.0" "linux-musl-arm"
Package "net6.0" "osx-x64"
Package "net6.0" "osx-arm64"
Package "net8.0" "win-x64"
Package "net8.0" "win-x86"
Package "net8.0" "linux-x64"
Package "net8.0" "linux-musl-x64"
Package "net8.0" "linux-arm64"
Package "net8.0" "linux-musl-arm64"
Package "net8.0" "linux-arm"
Package "net8.0" "linux-musl-arm"
Package "net8.0" "osx-x64"
Package "net8.0" "osx-arm64"
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
then
Package "net6.0" "freebsd-x64"
Package "net6.0" "linux-x86"
Package "net8.0" "freebsd-x64"
fi
else
Package "$FRAMEWORK" "$RID"
@@ -436,7 +434,7 @@ fi
if [ "$INSTALLER" = "YES" ];
then
InstallInno
BuildInstaller "net6.0" "win-x64"
BuildInstaller "net6.0" "win-x86"
BuildInstaller "net8.0" "win-x64"
BuildInstaller "net8.0" "win-x86"
RemoveInno
fi
+2 -2
View File
@@ -1,7 +1,7 @@
#!/bin/bash
set -e
FRAMEWORK="net6.0"
FRAMEWORK="net8.0"
PLATFORM=$1
ARCHITECTURE="${2:-x64}"
@@ -38,7 +38,7 @@ dotnet clean $slnFile -c Release
dotnet msbuild -restore $slnFile -p:Configuration=Debug -p:Platform=$platform -p:RuntimeIdentifiers=$RUNTIME -t:PublishAllRids
dotnet new tool-manifest
dotnet tool install --version 7.3.2 Swashbuckle.AspNetCore.Cli
dotnet tool install --version 8.1.4 Swashbuckle.AspNetCore.Cli
dotnet tool run swagger tofile --output ./src/Prowlarr.Api.V1/openapi.json "$outputFolder/$FRAMEWORK/$RUNTIME/$application" v1 &
+1 -1
View File
@@ -170,7 +170,7 @@ module.exports = (env) => {
loose: true,
debug: false,
useBuiltIns: 'entry',
corejs: '3.39'
corejs: '3.42'
}
]
]
+15 -2
View File
@@ -65,17 +65,30 @@ class VirtualTable extends Component {
if (this._grid && scrollTop !== undefined && scrollTop !== 0 && !scrollRestored) {
this.setState({ scrollRestored: true });
this._grid.scrollToPosition({ scrollTop });
this._gridScrollToPosition({ scrollTop });
}
if (scrollIndex != null && scrollIndex !== prevProps.scrollIndex) {
this._grid.scrollToCell({
this._gridScrollToCell({
rowIndex: scrollIndex,
columnIndex: 0
});
}
}
_gridScrollToCell = ({ rowIndex = 0, columnIndex = 0 }) => {
const scrollOffset = this._grid.getOffsetForCell({
rowIndex,
columnIndex
});
this._gridScrollToPosition(scrollOffset);
};
_gridScrollToPosition = ({ scrollTop = 0, scrollLeft = 0 }) => {
this.props.scroller?.scrollTo({ top: scrollTop, left: scrollLeft });
};
//
// Control
@@ -21,7 +21,7 @@ function createMapStateToProps() {
) => {
// If a release is deleted this selector may fire before the parent
// selecors, which will result in an undefined release, if that happens
// selectors, which will result in an undefined release, if that happens
// we want to return early here and again in the render function to avoid
// trying to show a release that has no information available.
@@ -30,7 +30,9 @@ export const authenticationMethodOptions = [
key: 'basic',
get value() {
return translate('AuthBasic');
}
},
isDisabled: true,
isHidden: true
},
{
key: 'forms',
+1 -1
View File
@@ -419,7 +419,7 @@ export const reducers = createHandleActions({
const items = newState.items;
const index = items.findIndex((item) => item.guid === guid);
// Don't try to update if there isnt a matching item (the user closed the modal)
// Don't try to update if there isn't a matching item (the user closed the modal)
if (index >= 0) {
const item = Object.assign({}, items[index], payload);
@@ -2,8 +2,8 @@ import { createSelector } from 'reselect';
import { isCommandExecuting } from 'Utilities/Command';
import createCommandSelector from './createCommandSelector';
function createCommandExecutingSelector(name: string, contraints = {}) {
return createSelector(createCommandSelector(name, contraints), (command) => {
function createCommandExecutingSelector(name: string, constraints = {}) {
return createSelector(createCommandSelector(name, constraints), (command) => {
return isCommandExecuting(command);
});
}
@@ -2,9 +2,9 @@ import { createSelector } from 'reselect';
import { findCommand } from 'Utilities/Command';
import createCommandsSelector from './createCommandsSelector';
function createCommandSelector(name: string, contraints = {}) {
function createCommandSelector(name: string, constraints = {}) {
return createSelector(createCommandsSelector(), (commands) => {
return findCommand(commands, { name, ...contraints });
return findCommand(commands, { name, ...constraints });
});
}
+5
View File
@@ -0,0 +1,5 @@
{
"sdk": {
"version": "8.0.405"
}
}
+16 -16
View File
@@ -23,17 +23,17 @@
"defaults"
],
"dependencies": {
"@fortawesome/fontawesome-free": "6.7.1",
"@fortawesome/fontawesome-svg-core": "6.7.1",
"@fortawesome/free-regular-svg-icons": "6.7.1",
"@fortawesome/free-solid-svg-icons": "6.7.1",
"@fortawesome/fontawesome-free": "6.7.2",
"@fortawesome/fontawesome-svg-core": "6.7.2",
"@fortawesome/free-regular-svg-icons": "6.7.2",
"@fortawesome/free-solid-svg-icons": "6.7.2",
"@fortawesome/react-fontawesome": "0.2.2",
"@juggle/resize-observer": "3.4.0",
"@microsoft/signalr": "6.0.25",
"@microsoft/signalr": "8.0.7",
"@sentry/browser": "7.119.1",
"@sentry/integrations": "7.119.1",
"@types/node": "20.16.11",
"@types/react": "18.2.79",
"@types/react": "18.3.21",
"@types/react-dom": "18.2.25",
"chart.js": "4.4.4",
"classnames": "2.5.1",
@@ -71,9 +71,9 @@
"react-router-dom": "5.2.0",
"react-tabs": "4.3.0",
"react-text-truncate": "0.19.0",
"react-use-measure": "2.1.1",
"react-virtualized": "9.21.1",
"react-window": "1.8.10",
"react-use-measure": "2.1.7",
"react-virtualized": "9.22.6",
"react-window": "1.8.11",
"redux": "4.2.1",
"redux-actions": "2.6.5",
"redux-batched-actions": "0.5.0",
@@ -84,13 +84,13 @@
"typescript": "5.7.2"
},
"devDependencies": {
"@babel/core": "7.26.0",
"@babel/eslint-parser": "7.25.9",
"@babel/plugin-proposal-export-default-from": "7.25.9",
"@babel/core": "7.27.1",
"@babel/eslint-parser": "7.27.1",
"@babel/plugin-proposal-export-default-from": "7.27.1",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/preset-env": "7.26.0",
"@babel/preset-react": "7.26.3",
"@babel/preset-typescript": "7.26.0",
"@babel/preset-env": "7.27.2",
"@babel/preset-react": "7.27.1",
"@babel/preset-typescript": "7.27.1",
"@types/lodash": "4.14.195",
"@types/react-document-title": "2.0.10",
"@types/react-router-dom": "5.3.3",
@@ -104,7 +104,7 @@
"babel-loader": "9.2.1",
"babel-plugin-inline-classnames": "2.0.1",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
"core-js": "3.39.0",
"core-js": "3.42.0",
"css-loader": "6.7.3",
"css-modules-typescript-loader": "4.0.1",
"eslint": "8.57.1",
+3 -10
View File
@@ -99,13 +99,6 @@
<RootNamespace Condition="'$(ProwlarrProject)'=='true'">$(MSBuildProjectName.Replace('Prowlarr','NzbDrone'))</RootNamespace>
</PropertyGroup>
<ItemGroup Condition="'$(TestProject)'!='true'">
<!-- Annotates .NET assemblies with repository information including SHA -->
<!-- Sentry uses this to link directly to GitHub at the exact version/file/line -->
<!-- This is built-in on .NET 8 and can be removed once the project is updated -->
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>
<!-- Sentry specific configuration: Only in Release mode -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<!-- https://docs.sentry.io/platforms/dotnet/configuration/msbuild/ -->
@@ -136,7 +129,7 @@
<PackageReference Include="NunitXml.TestLogger" Version="3.0.131" />
</ItemGroup>
<ItemGroup Condition="'$(TestProject)'=='true' and '$(TargetFramework)'=='net6.0'">
<ItemGroup Condition="'$(TestProject)'=='true' and '$(TargetFramework)'=='net8.0'">
<PackageReference Include="coverlet.collector" Version="3.0.4-preview.27.ge7cb7c3b40" />
</ItemGroup>
@@ -148,9 +141,9 @@
<!-- Set up stylecop -->
<ItemGroup Condition="'$(ProwlarrProject)'=='true' and '$(EnableAnalyzers)'!='false'">
<!-- StyleCop analysis -->
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.556">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<AdditionalFiles Include="$(SolutionDir)stylecop.json" />
</ItemGroup>
@@ -39,15 +39,16 @@ namespace NzbDrone.Automation.Test
var service = ChromeDriverService.CreateDefaultService();
// Timeout as windows automation tests seem to take alot longer to get going
driver = new ChromeDriver(service, options, new TimeSpan(0, 3, 0));
driver = new ChromeDriver(service, options, TimeSpan.FromMinutes(3));
driver.Manage().Window.Size = new System.Drawing.Size(1920, 1080);
driver.Manage().Window.FullScreen();
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), null);
_runner.KillAll();
_runner.Start(true);
driver.Url = "http://localhost:9696";
driver.Navigate().GoToUrl("http://localhost:9696");
var page = new PageBase(driver);
page.WaitForNoSpinner();
@@ -67,7 +68,7 @@ namespace NzbDrone.Automation.Test
{
try
{
var image = ((ITakesScreenshot)driver).GetScreenshot();
var image = (driver as ITakesScreenshot).GetScreenshot();
image.SaveAsFile($"./{name}_test_screenshot.png", ScreenshotImageFormat.Png);
}
catch (Exception ex)
@@ -7,12 +7,11 @@ namespace NzbDrone.Automation.Test.PageModel
{
public class PageBase
{
private readonly WebDriver _driver;
private readonly IWebDriver _driver;
public PageBase(WebDriver driver)
public PageBase(IWebDriver driver)
{
_driver = driver;
driver.Manage().Window.Maximize();
}
public IWebElement FindByClass(string className, int timeout = 5)
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Selenium.Support" Version="4.1.0" />
@@ -10,13 +10,13 @@ namespace NzbDrone.Common.Test.EnvironmentInfo
[Test]
public void should_return_version()
{
BuildInfo.Version.Major.Should().BeOneOf(0, 1, 10);
BuildInfo.Version.Major.Should().BeOneOf(0, 2, 10);
}
[Test]
public void should_get_branch()
{
BuildInfo.Branch.Should().NotBe("unknow");
BuildInfo.Branch.Should().NotBe("unknown");
BuildInfo.Branch.Should().NotBeNullOrWhiteSpace();
}
}
@@ -16,6 +16,8 @@ namespace NzbDrone.Common.Test.Http
[TestCase("Readarr/1.0.0.2300 (ubuntu 20.04)", "Readarr")]
[TestCase("Sonarr/3.0.6.9999 (ubuntu 20.04)", "Sonarr")]
[TestCase("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", "Other")]
[TestCase("appbrr", "appbrr")]
[TestCase(" appbrr ", "appbrr")]
public void should_parse_user_agent(string userAgent, string parsedAgent)
{
UserAgentParser.ParseSource(userAgent).Should().Be(parsedAgent);
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Host\Prowlarr.Host.csproj" />
@@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Runtime.Serialization;
namespace NzbDrone.Common.Disk
{
@@ -24,10 +23,5 @@ namespace NzbDrone.Common.Disk
: base(message, innerException)
{
}
protected DestinationAlreadyExistsException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}
@@ -75,6 +75,17 @@ namespace NzbDrone.Common.EnvironmentInfo
{
try
{
if (OsInfo.IsOsx)
{
var userAppDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile, Environment.SpecialFolderOption.DoNotVerify), ".config", "Prowlarr");
if (_diskProvider.FolderExists(userAppDataFolder) && !_diskProvider.FileExists(_appFolderInfo.GetConfigPath()))
{
_diskTransferService.MirrorFolder(userAppDataFolder, _appFolderInfo.AppDataFolder);
_diskProvider.DeleteFolder(userAppDataFolder, true);
}
}
var oldDbFile = Path.Combine(_appFolderInfo.AppDataFolder, "nzbdrone.db");
if (_startupContext.Args.ContainsKey(StartupContext.APPDATA))
@@ -115,7 +126,7 @@ namespace NzbDrone.Common.EnvironmentInfo
catch (Exception ex)
{
_logger.Debug(ex, ex.Message);
throw new ProwlarrStartupException("Unable to migrate DB from nzbdrone.db to {0}. Migrate manually", _appFolderInfo.GetDatabase());
throw new ProwlarrStartupException(ex, "Unable to migrate DB from nzbdrone.db to {0}. Migrate manually", _appFolderInfo.GetDatabase());
}
}
@@ -15,7 +15,7 @@ namespace NzbDrone.Common.EnvironmentInfo
var attributes = assembly.GetCustomAttributes(true);
Branch = "unknow";
Branch = "unknown";
var config = attributes.OfType<AssemblyConfigurationAttribute>().FirstOrDefault();
if (config != null)
@@ -31,7 +31,7 @@ namespace NzbDrone.Common.Extensions
}
public static IDictionary<TNewKey, TNewValue> SelectDictionary<TKey, TValue, TNewKey, TNewValue>(this IDictionary<TKey, TValue> dictionary,
Func<KeyValuePair<TKey, TValue>, ValueTuple<TNewKey, TNewValue>> selection)
Func<KeyValuePair<TKey, TValue>, (TNewKey Item1, TNewValue Item2)> selection)
{
return dictionary.Select(selection).ToDictionary(t => t.Item1, t => t.Item2);
}
@@ -167,7 +167,7 @@ namespace NzbDrone.Common.Http.Dispatchers
}
catch (OperationCanceledException ex) when (cts.IsCancellationRequested)
{
throw new WebException("Http request timed out", ex.InnerException, WebExceptionStatus.Timeout, null);
throw new WebException("Http request timed out", ex, WebExceptionStatus.Timeout, null);
}
}
+1 -1
View File
@@ -97,7 +97,7 @@ namespace NzbDrone.Common.Http
// Save to add to final response
var responseCookies = response.Cookies;
// Update cookiecontainer for next request with any cookies recieved on last request
// Update cookie container for next request with any cookies received on last request
var responseContainer = HandleRedirectCookies(request, response);
response = await ExecuteRequestAsync(request, responseContainer);
+5 -9
View File
@@ -1,15 +1,16 @@
using System;
using System.Text.RegularExpressions;
namespace NzbDrone.Common.Http
{
public static class UserAgentParser
{
private static readonly Regex AppSourceRegex = new Regex(@"(?<agent>[a-z0-9]*)\/.*(?:\(.*\))?",
private static readonly Regex AppSourceRegex = new(@"^(?<agent>[a-z0-9]+)(?:\/.+(?:\(.*\))?|$)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static string SimplifyUserAgent(string userAgent)
{
if (userAgent == null || userAgent.StartsWith("Mozilla/5.0"))
if (userAgent == null || userAgent.StartsWith("Mozilla/5.0", StringComparison.Ordinal))
{
return null;
}
@@ -19,14 +20,9 @@ namespace NzbDrone.Common.Http
public static string ParseSource(string userAgent)
{
var match = AppSourceRegex.Match(SimplifyUserAgent(userAgent) ?? string.Empty);
var match = AppSourceRegex.Match(SimplifyUserAgent(userAgent?.Trim()) ?? string.Empty);
if (match.Groups["agent"].Success)
{
return match.Groups["agent"].Value;
}
return "Other";
return match.Groups["agent"].Success ? match.Groups["agent"].Value : "Other";
}
}
}
@@ -4,27 +4,27 @@ namespace NzbDrone.Common.Instrumentation.Extensions
{
public static class LoggerExtensions
{
[MessageTemplateFormatMethod("message")]
public static void ProgressInfo(this Logger logger, string message, params object[] args)
{
var formattedMessage = string.Format(message, args);
LogProgressMessage(logger, LogLevel.Info, formattedMessage);
LogProgressMessage(logger, LogLevel.Info, message, args);
}
[MessageTemplateFormatMethod("message")]
public static void ProgressDebug(this Logger logger, string message, params object[] args)
{
var formattedMessage = string.Format(message, args);
LogProgressMessage(logger, LogLevel.Debug, formattedMessage);
LogProgressMessage(logger, LogLevel.Debug, message, args);
}
[MessageTemplateFormatMethod("message")]
public static void ProgressTrace(this Logger logger, string message, params object[] args)
{
var formattedMessage = string.Format(message, args);
LogProgressMessage(logger, LogLevel.Trace, formattedMessage);
LogProgressMessage(logger, LogLevel.Trace, message, args);
}
private static void LogProgressMessage(Logger logger, LogLevel level, string message)
private static void LogProgressMessage(Logger logger, LogLevel level, string message, object[] parameters)
{
var logEvent = new LogEventInfo(level, logger.Name, message);
var logEvent = new LogEventInfo(level, logger.Name, null, message, parameters);
logEvent.Properties.Add("Status", "");
logger.Log(logEvent);
+7 -7
View File
@@ -1,28 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<DefineConstants Condition="'$(RuntimeIdentifier)' == 'linux-musl-x64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64'">ISMUSL</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
<PackageReference Include="IPAddressRange" Version="6.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="NLog.Layouts.ClefJsonLayout" Version="1.0.3" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
<PackageReference Include="Npgsql" Version="7.0.10" />
<PackageReference Include="Npgsql" Version="9.0.3" />
<PackageReference Include="Sentry" Version="4.0.2" />
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="System.Text.Json" Version="6.0.11" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
<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="6.0.2" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.1" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="6.0.1" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="EnsureThat\Resources\ExceptionMessages.Designer.cs">
@@ -94,7 +94,8 @@ namespace NzbDrone.Common.TPL
{
_currentThreadIsProcessingItems = false;
}
}, null);
},
null);
}
/// <summary>Attempts to execute the specified task on the current thread.</summary>
+2 -1
View File
@@ -20,7 +20,8 @@ namespace NzbDrone.Common.TPL
Logger.Error(exception, "Task Error");
}
}
}, TaskContinuationOptions.OnlyOnFaulted);
},
TaskContinuationOptions.OnlyOnFaulted);
return task;
}
+1 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<ApplicationIcon>..\NzbDrone.Host\Prowlarr.ico</ApplicationIcon>
</PropertyGroup>
File diff suppressed because one or more lines are too long
@@ -11,5 +11,6 @@
</searching>
<categories>
<category id="5070" name="Anime" description="Anime" />
<category id="2020" name="Movies/Other" description="Movies (Anime)" />
</categories>
</caps>
@@ -83,17 +83,18 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
bookCats.Should().Contain("8000");
}
[Test]
public void should_find_sub_categories_as_main_categories()
[TestCase(5070)]
[TestCase(2020)]
public void should_find_sub_categories_as_main_categories(int category)
{
GivenCapsResponse(ReadAllText("Files/Indexers/Torznab/torznab_animetosho_caps.xml"));
var caps = Subject.GetCapabilities(_settings, _definition);
var bookCats = caps.Categories.MapTrackerCatToNewznab("5070");
var indexerCategories = caps.Categories.MapTrackerCatToNewznab(category.ToString());
bookCats.Count.Should().Be(2);
bookCats.First().Id.Should().Be(5070);
indexerCategories.Count.Should().Be(2);
indexerCategories.First().Id.Should().Be(category);
}
[Test]
@@ -50,7 +50,7 @@ namespace NzbDrone.Core.Test.IndexerTests.PTPTests
first.Guid.Should().Be("PassThePopcorn-452135");
first.Title.Should().Be("The.Night.Of.S01.BluRay.AAC2.0.x264-DEPTH");
first.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
first.DownloadUrl.Should().Be("https://passthepopcorn.me/torrents.php?action=download&id=452135&authkey=00000000000000000000000000000000&torrent_pass=00000000000000000000000000000000");
first.DownloadUrl.Should().Be("https://passthepopcorn.me/torrents.php?action=download&id=452135");
first.InfoUrl.Should().Be("https://passthepopcorn.me/torrents.php?id=148131&torrentid=452135");
//first.PublishDate.Should().Be(DateTime.Parse("2017-04-17T12:13:42+0000").ToUniversalTime()); stupid timezones
@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.151" />
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="NBuilder" Version="6.1.0" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="YamlDotNet" Version="13.1.1" />
<PackageReference Include="YamlDotNet" Version="16.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Lidarr
{
var indexerCapabilities = GetIndexerCapabilities(indexer);
if (!indexerCapabilities.MusicSearchAvailable && !indexerCapabilities.SearchAvailable)
{
_logger.Debug("Skipping add for indexer {0} [{1}] due to missing music or basic search support by the indexer", indexer.Name, indexer.Id);
return;
}
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty())
{
_logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
_logger.Debug("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
return;
}
@@ -178,7 +185,8 @@ namespace NzbDrone.Core.Applications.Lidarr
{
_logger.Debug("Syncing remote indexer with current settings");
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
if ((indexerCapabilities.MusicSearchAvailable || indexerCapabilities.SearchAvailable) &&
indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
// Retain user fields not-affiliated with Prowlarr
lidarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => lidarrIndexer.Fields.All(s => s.Name != f.Name)));
@@ -204,7 +212,8 @@ namespace NzbDrone.Core.Applications.Lidarr
{
_appIndexerMapService.Delete(indexerMapping.Id);
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
if ((indexerCapabilities.MusicSearchAvailable || indexerCapabilities.SearchAvailable) &&
indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Lidarr", indexer.Name, indexer.Id);
lidarrIndexer.Id = 0;
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Radarr
{
var indexerCapabilities = GetIndexerCapabilities(indexer);
if (!indexerCapabilities.MovieSearchAvailable && !indexerCapabilities.SearchAvailable)
{
_logger.Debug("Skipping add for indexer {0} [{1}] due to missing movie or basic search support by the indexer", indexer.Name, indexer.Id);
return;
}
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty())
{
_logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
_logger.Debug("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
return;
}
@@ -176,7 +183,8 @@ namespace NzbDrone.Core.Applications.Radarr
if (!radarrIndexer.Equals(remoteIndexer) || forceSync)
{
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
if ((indexerCapabilities.MovieSearchAvailable || indexerCapabilities.SearchAvailable) &&
indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
// Retain user fields not-affiliated with Prowlarr
radarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => radarrIndexer.Fields.All(s => s.Name != f.Name)));
@@ -202,7 +210,8 @@ namespace NzbDrone.Core.Applications.Radarr
{
_appIndexerMapService.Delete(indexerMapping.Id);
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
if ((indexerCapabilities.MovieSearchAvailable || indexerCapabilities.SearchAvailable) &&
indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Radarr", indexer.Name, indexer.Id);
radarrIndexer.Id = 0;
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Readarr
{
var indexerCapabilities = GetIndexerCapabilities(indexer);
if (!indexerCapabilities.BookSearchAvailable && !indexerCapabilities.SearchAvailable)
{
_logger.Debug("Skipping add for indexer {0} [{1}] due to missing book or basic search support by the indexer", indexer.Name, indexer.Id);
return;
}
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty())
{
_logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
_logger.Debug("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
return;
}
@@ -178,7 +185,8 @@ namespace NzbDrone.Core.Applications.Readarr
{
_logger.Debug("Syncing remote indexer with current settings");
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
if ((indexerCapabilities.BookSearchAvailable || indexerCapabilities.SearchAvailable) &&
indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
// Retain user fields not-affiliated with Prowlarr
readarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => readarrIndexer.Fields.All(s => s.Name != f.Name)));
@@ -204,7 +212,8 @@ namespace NzbDrone.Core.Applications.Readarr
{
_appIndexerMapService.Delete(indexerMapping.Id);
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
if ((indexerCapabilities.BookSearchAvailable || indexerCapabilities.SearchAvailable) &&
indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any())
{
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Readarr", indexer.Name, indexer.Id);
readarrIndexer.Id = 0;
@@ -125,10 +125,17 @@ namespace NzbDrone.Core.Applications.Sonarr
{
var indexerCapabilities = GetIndexerCapabilities(indexer);
if (!indexerCapabilities.TvSearchAvailable && !indexerCapabilities.SearchAvailable)
{
_logger.Debug("Skipping add for indexer {0} [{1}] due to missing TV or basic search support by the indexer", indexer.Name, indexer.Id);
return;
}
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty() &&
indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Empty())
{
_logger.Trace("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
_logger.Debug("Skipping add for indexer {0} [{1}] due to no app Sync Categories supported by the indexer", indexer.Name, indexer.Id);
return;
}
@@ -183,7 +190,8 @@ namespace NzbDrone.Core.Applications.Sonarr
{
_logger.Debug("Syncing remote indexer with current settings");
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any())
if ((indexerCapabilities.TvSearchAvailable || indexerCapabilities.SearchAvailable) &&
(indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any()))
{
// Retain user fields not-affiliated with Prowlarr
sonarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => sonarrIndexer.Fields.All(s => s.Name != f.Name)));
@@ -210,7 +218,8 @@ namespace NzbDrone.Core.Applications.Sonarr
{
_appIndexerMapService.Delete(indexerMapping.Id);
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any())
if ((indexerCapabilities.TvSearchAvailable || indexerCapabilities.SearchAvailable) &&
(indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Any() || indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.ToArray()).Any()))
{
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Sonarr", indexer.Name, indexer.Id);
sonarrIndexer.Id = 0;
@@ -1,8 +1,11 @@
using System;
namespace NzbDrone.Core.Authentication
{
public enum AuthenticationType
{
None = 0,
[Obsolete("Use Forms authentication instead")]
Basic = 1,
Forms = 2,
External = 3
@@ -207,8 +207,8 @@ namespace NzbDrone.Core.Configuration
if (enabled)
{
SetValue("AuthenticationMethod", AuthenticationType.Basic);
return AuthenticationType.Basic;
SetValue("AuthenticationMethod", AuthenticationType.Forms);
return AuthenticationType.Forms;
}
return Enum.TryParse<AuthenticationType>(_authOptions.Method, out var enumValue)
@@ -27,7 +27,7 @@ namespace NzbDrone.Core.Datastore
switch (expression.NodeType)
{
case ExpressionType.Lambda:
return VisitLamda((LambdaExpression)expression);
return VisitLambda((LambdaExpression)expression);
case ExpressionType.ArrayLength:
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
@@ -87,7 +87,7 @@ namespace NzbDrone.Core.Datastore
}
/// <summary>
/// Visits the memeber access expression. To be implemented by user.
/// Visits the member access expression. To be implemented by user.
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
@@ -130,11 +130,11 @@ namespace NzbDrone.Core.Datastore
}
/// <summary>
/// Visits the lamda expression.
/// Visits the lambda expression.
/// </summary>
/// <param name="lambdaExpression"></param>
/// <returns></returns>
protected virtual Expression VisitLamda(LambdaExpression lambdaExpression)
protected virtual Expression VisitLambda(LambdaExpression lambdaExpression)
{
Visit(lambdaExpression.Body);
return lambdaExpression;
@@ -1,3 +1,4 @@
using System;
using System.IO;
using System.Linq;
using System.Xml;
@@ -14,10 +15,13 @@ namespace NzbDrone.Core.Download
public class NzbValidationService : IValidateNzbs
{
public void Validate(byte[] fileContent)
{
try
{
var reader = new StreamReader(new MemoryStream(fileContent));
using (var xmlTextReader = XmlReader.Create(reader, new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, IgnoreComments = true }))
using (var xmlTextReader = XmlReader.Create(reader,
new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, IgnoreComments = true }))
{
var xDoc = XDocument.Load(xmlTextReader);
var nzb = xDoc.Root;
@@ -27,7 +31,7 @@ namespace NzbDrone.Core.Download
throw new InvalidNzbException("Invalid NZB: No Root element");
}
// nZEDb has an bug in their error reporting code spitting out invalid http status codes
// nZEDb has a bug in their error reporting code spitting out invalid http status codes
if (nzb.Name.LocalName.Equals("error") &&
nzb.TryGetAttributeValue("code", out var code) &&
nzb.TryGetAttributeValue("description", out var description))
@@ -37,7 +41,8 @@ namespace NzbDrone.Core.Download
if (!nzb.Name.LocalName.Equals("nzb"))
{
throw new InvalidNzbException("Invalid NZB: Unexpected root element. Expected 'nzb' found '{0}'", nzb.Name.LocalName);
throw new InvalidNzbException(
"Invalid NZB: Unexpected root element. Expected 'nzb' found '{0}'", nzb.Name.LocalName);
}
var ns = nzb.Name.Namespace;
@@ -49,5 +54,15 @@ namespace NzbDrone.Core.Download
}
}
}
catch (InvalidNzbException)
{
// Throw the original exception
throw;
}
catch (Exception ex)
{
throw new InvalidNzbException("Invalid NZB: Unable to parse", ex);
}
}
}
}
@@ -237,13 +237,13 @@ namespace NzbDrone.Core.Indexers.Definitions
return _categories.MapTrackerCatDescToNewznab("OVA/ONA/Special");
}
// Check movies then, cause some of releases could be movies dorama and should go to movies category
// Check movies then, cause some of the releases could be movies dorama and should go to movies category
if (CategorieMovieRegex.IsMatch(rName) || CategorieMovieRegex.IsMatch(rDesc))
{
return _categories.MapTrackerCatDescToNewznab("Movies");
}
// Check dorama. Most of doramas are flaged as doramas in type info, but type info could have a lot of types at same time (movie, etc)
// Check dorama. Most of doramas are flagged as doramas in type info, but type info could have a lot of types at same time (movie, etc)
if (CategorieDoramaRegex.IsMatch(rName) || CategorieDoramaRegex.IsMatch(type))
{
return _categories.MapTrackerCatDescToNewznab("Dorama");
@@ -255,6 +255,11 @@ namespace NzbDrone.Core.Indexers.Definitions
throw new IndexerException(indexerResponse, $"Unexpected response status {indexerHttpResponse.StatusCode} code from indexer request");
}
if (indexerHttpResponse.Headers.ContentType.Contains("text/html"))
{
throw new IndexerException(indexerResponse, $"Indexer responded with HTML content. {(indexerHttpResponse.Content.ContainsIgnoreCase("site maintenance") ? "Site is under maintenance." : "Site is likely blocked or unavailable.")}");
}
if (!indexerHttpResponse.Headers.ContentType.Contains(HttpAccept.Json.Value))
{
throw new IndexerException(indexerResponse, $"Unexpected response header {indexerHttpResponse.Headers.ContentType} from indexer request, expected {HttpAccept.Json.Value}");
@@ -227,7 +227,9 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
{
if (required)
{
throw new Exception($"Selector \"{selectorSelector}\" didn't match {parentObj.ToString(Formatting.None)}");
var jsonContent = parentObj.ToString(Formatting.None);
throw new Exception($"Selector \"{selectorSelector}\" didn't match JSON content").WithData("JsonContent", jsonContent[..Math.Min(jsonContent.Length, 5 * 1024)]);
}
return null;
@@ -260,7 +262,9 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
{
if (required)
{
throw new Exception($"None of the case selectors \"{string.Join(",", selector.Case)}\" matched {parentObj.ToString(Formatting.None)}");
var jsonContent = parentObj.ToString(Formatting.None);
throw new Exception($"None of the case selectors \"{string.Join(",", selector.Case)}\" matched JSON content").WithData("JsonContent", jsonContent[..Math.Min(jsonContent.Length, 5 * 1024)]);
}
return null;
@@ -706,15 +710,15 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
var diacriticsOp = (string)filter.Args;
if (diacriticsOp == "replace")
{
// Should replace diacritics charcaters with their base character
// Should replace diacritics characters with their base character
// It's not perfect, e.g. "ŠĐĆŽ - šđčćž" becomes "SĐCZ-sđccz"
var stFormD = data.Normalize(NormalizationForm.FormD);
var len = stFormD.Length;
var sb = new StringBuilder();
for (var i = 0; i < len; i++)
{
var uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(stFormD[i]);
if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
var uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[i]);
if (uc != UnicodeCategory.NonSpacingMark)
{
sb.Append(stFormD[i]);
}
@@ -739,7 +743,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
case "hexdump":
// this is mainly for debugging invisible special char related issues
var hexData = string.Join("", data.Select(c => c + "(" + ((int)c).ToString("X2") + ")"));
_logger.Debug(string.Format("CardigannIndexer ({0}): strdump: {1}", _definition.Id, hexData));
_logger.Debug("CardigannIndexer ({0}): strdump: {1}", _definition.Id, hexData);
break;
case "strdump":
// for debugging
@@ -775,7 +779,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
return headers;
}
// FIXME: fix jackett header handling (allow it to specifiy the same header multipe times)
// FIXME: fix jackett header handling (allow it to specify the same header multiple times)
foreach (var header in customHeaders)
{
headers.Add(header.Key, ApplyGoTemplateText(header.Value[0], variables));
@@ -915,7 +919,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
break;
default:
_logger.Error(string.Format("CardigannIndexer ({0}): Unsupported selector: {1}", _definition.Id, rowSelector));
_logger.Error("CardigannIndexer ({0}): Unsupported selector: {1}", _definition.Id, rowSelector);
continue;
}
}
@@ -226,7 +226,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
{
results = ApplyFilters(results, search.Preprocessingfilters, variables);
searchResultDocument = searchResultParser.ParseDocument(results);
_logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results));
_logger.Trace("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results);
}
var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables);
@@ -241,7 +241,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
{
results = ApplyFilters(results, search.Preprocessingfilters, variables);
searchResultDocument = searchResultParser.ParseDocument(results);
_logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results));
_logger.Trace("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results);
}
var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables);
@@ -1203,7 +1203,7 @@ namespace NzbDrone.Core.Indexers.Definitions.Cardigann
Encoding = _encoding
};
// Add FormData for searchs that POST
// Add FormData for searches that POST
if (method == HttpMethod.Post)
{
foreach (var param in queryCollection)
@@ -148,7 +148,8 @@ namespace NzbDrone.Core.Indexers.Newznab
SupportsSearch = SupportsSearch,
SupportsRedirect = SupportsRedirect,
SupportsPagination = SupportsPagination,
Capabilities = caps
Capabilities = caps,
Redirect = true
};
}
@@ -224,24 +224,28 @@ namespace NzbDrone.Core.Indexers.Newznab
foreach (var xmlCategory in xmlCategories.Elements("category"))
{
var parentName = xmlCategory.Attribute("name").Value;
var parentNameLower = parentName?.ToLowerInvariant();
var parentId = int.Parse(xmlCategory.Attribute("id").Value);
var mappedCat = NewznabStandardCategory.ParentCats.FirstOrDefault(x => parentNameLower.Contains(x.Name.ToLower()));
var mappedCat = NewznabStandardCategory.ParentCats.FirstOrDefault(x => parentName.Equals(x.Name, StringComparison.OrdinalIgnoreCase));
if (mappedCat == null)
if (mappedCat is null)
{
// Try to find name and Id in AllCats for sub cats that are mapped as parents
mappedCat = NewznabStandardCategory.AllCats.FirstOrDefault(x => x.Id == parentId && x.Name.ToLower().Contains(parentNameLower));
// Try to find name and ID in AllCats for sub cats that are mapped as parents
mappedCat = NewznabStandardCategory.AllCats.FirstOrDefault(x => x.Id == parentId && x.Name.Contains(parentName, StringComparison.OrdinalIgnoreCase));
}
if (mappedCat == null)
if (mappedCat is null)
{
mappedCat = NewznabStandardCategory.ParentCats.FirstOrDefault(x => parentName.Contains(x.Name, StringComparison.OrdinalIgnoreCase));
}
if (mappedCat is null)
{
// Try by parent id if name fails
mappedCat = NewznabStandardCategory.ParentCats.FirstOrDefault(x => x.Id == parentId);
}
if (mappedCat == null)
if (mappedCat is null)
{
// Fallback to Other
mappedCat = NewznabStandardCategory.Other;
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Messaging.Events;
@@ -36,7 +38,19 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
public override IParseIndexerResponse GetParser()
{
return new PassThePopcornParser(Settings);
return new PassThePopcornParser(Settings, Capabilities.Categories);
}
protected override Task<HttpRequest> GetDownloadRequest(Uri link)
{
var requestBuilder = new HttpRequestBuilder(link.AbsoluteUri);
var request = requestBuilder
.SetHeader("ApiUser", Settings.APIUser)
.SetHeader("ApiKey", Settings.APIKey)
.Build();
return Task.FromResult(request);
}
private IndexerCapabilities SetCapabilities()
@@ -45,10 +59,6 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
{
LimitsDefault = PageSize,
LimitsMax = PageSize,
TvSearchParams = new List<TvSearchParam>
{
TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep, TvSearchParam.ImdbId
},
MovieSearchParams = new List<MovieSearchParam>
{
MovieSearchParam.Q, MovieSearchParam.ImdbId
@@ -63,7 +73,7 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
caps.Categories.AddCategoryMapping(1, NewznabStandardCategory.Movies, "Feature Film");
caps.Categories.AddCategoryMapping(2, NewznabStandardCategory.Movies, "Short Film");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.TV, "Miniseries");
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.Movies, "Miniseries");
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.Movies, "Stand-up Comedy");
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.Movies, "Live Performance");
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.Movies, "Movie Collection");
@@ -5,21 +5,20 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
public class PassThePopcornResponse
{
public string TotalResults { get; set; }
public List<PassThePopcornMovie> Movies { get; set; }
public IReadOnlyCollection<PassThePopcornMovie> Movies { get; set; }
public string Page { get; set; }
public string AuthKey { get; set; }
public string PassKey { get; set; }
}
public class PassThePopcornMovie
{
public string GroupId { get; set; }
public string CategoryId { get; set; }
public string Title { get; set; }
public string Year { get; set; }
public string Cover { get; set; }
public List<string> Tags { get; set; }
public IReadOnlyCollection<string> Tags { get; set; }
public string ImdbId { get; set; }
public List<PassThePopcornTorrent> Torrents { get; set; }
public IReadOnlyCollection<PassThePopcornTorrent> Torrents { get; set; }
}
public class PassThePopcornTorrent
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
@@ -14,12 +14,12 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
public class PassThePopcornParser : IParseIndexerResponse
{
private readonly PassThePopcornSettings _settings;
private readonly IndexerCapabilitiesCategories _categories;
private static Regex SeasonRegex => new (@"\bS\d{2,3}(E\d{2,3})?\b", RegexOptions.Compiled);
public PassThePopcornParser(PassThePopcornSettings settings)
public PassThePopcornParser(PassThePopcornSettings settings, IndexerCapabilitiesCategories categories)
{
_settings = settings;
_categories = categories;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
@@ -84,13 +84,6 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
flags.Add(PassThePopcornFlag.Approved);
}
var categories = new List<IndexerCategory> { NewznabStandardCategory.Movies };
if (title != null && SeasonRegex.Match(title).Success)
{
categories.Add(NewznabStandardCategory.TV);
}
var uploadVolumeFactor = torrent.FreeleechType?.ToUpperInvariant() switch
{
"NEUTRAL LEECH" => 0,
@@ -103,8 +96,8 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
Title = title,
Year = int.Parse(result.Year),
InfoUrl = GetInfoUrl(result.GroupId, id),
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
Categories = categories,
DownloadUrl = GetDownloadUrl(id),
Categories = _categories.MapTrackerCatToNewznab(result.CategoryId),
Size = long.Parse(torrent.Size),
Grabs = int.Parse(torrent.Snatched),
Seeders = int.Parse(torrent.Seeders),
@@ -117,7 +110,7 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
UploadVolumeFactor = uploadVolumeFactor,
MinimumRatio = 1,
MinimumSeedTime = 345600,
Genres = result.Tags ?? new List<string>(),
Genres = result.Tags?.ToList() ?? new List<string>(),
PosterUrl = GetPosterUrl(result.Cover)
});
}
@@ -128,14 +121,12 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
private string GetDownloadUrl(int torrentId, string authKey, string passKey)
private string GetDownloadUrl(int torrentId)
{
var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php")
.AddQueryParam("action", "download")
.AddQueryParam("id", torrentId)
.AddQueryParam("authkey", authKey)
.AddQueryParam("torrent_pass", passKey);
.AddQueryParam("id", torrentId);
return url.FullUri;
}
@@ -78,6 +78,8 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
{ "action", "advanced" },
{ "json", "noredirect" },
{ "grouping", "0" },
{ "order_by", "time" },
{ "order_way", "desc" },
{ "searchstr", searchTerm }
};
@@ -18,6 +18,12 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
{
private static readonly PassThePopcornSettingsValidator Validator = new();
public PassThePopcornSettings()
{
BaseSettings.QueryLimit = 150;
BaseSettings.LimitsUnit = (int)IndexerLimitsUnit.Hour;
}
[FieldDefinition(2, Label = "IndexerSettingsApiUser", HelpText = "IndexerPassThePopcornSettingsApiUserHelpText", Privacy = PrivacyLevel.UserName)]
public string APIUser { get; set; }
@@ -138,7 +138,7 @@ namespace NzbDrone.Core.Indexers.Definitions
}
else if (!string.IsNullOrWhiteSpace(searchString))
{
// Suffix the first occurence of `s01` surrounded by whitespace with *
// Suffix the first occurrence of `s01` surrounded by whitespace with *
// That way we also search for single episodes in a whole season search
var regex = new Regex(@"(^|\s)(s\d{2})(\s|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
queryCollection.Add("searchstring", regex.Replace(searchString.Trim(), @"$1$2*$3"));
+1 -1
View File
@@ -195,7 +195,7 @@ namespace NzbDrone.Core.Indexers
}
else if (settings.BaseUrl.IsNotNullOrWhiteSpace() && LegacyUrls.Contains(settings.BaseUrl))
{
_logger.Debug(string.Format("Changing legacy site link from {0} to {1}", settings.BaseUrl, defaultLink));
_logger.Debug("Changing legacy site link from {0} to {1}", settings.BaseUrl, defaultLink);
settings.BaseUrl = defaultLink;
}
@@ -92,7 +92,6 @@ namespace NzbDrone.Core.Indexers
public static readonly IndexerCategory[] ParentCats =
{
ZedOther,
Console,
Movies,
Audio,
@@ -100,7 +99,8 @@ namespace NzbDrone.Core.Indexers
TV,
XXX,
Books,
Other
Other,
ZedOther
};
public static readonly IndexerCategory[] AllCats =
+71 -4
View File
@@ -362,11 +362,11 @@
"Theme": "Tema",
"Track": "Pista",
"Year": "Any",
"UpdateAvailableHealthCheckMessage": "Nova actualització disponible",
"UpdateAvailableHealthCheckMessage": "Nova actualització disponible: {version}",
"ConnectionLostReconnect": "{appName} intentarà connectar-se automàticament, o podeu fer clic a recarregar.",
"ConnectionLostToBackend": "{appName} ha perdut la connexió amb el backend i s'haurà de tornar a carregar per a restaurar la funcionalitat.",
"RecentChanges": "Canvis recents",
"WhatsNew": "Novetats",
"WhatsNew": "Què hi ha de nou?",
"minutes": "minuts",
"DeleteAppProfileMessageText": "Esteu segur que voleu suprimir el perfil de l'aplicació '{name}'?",
"NotificationStatusSingleClientHealthCheckMessage": "Notificacions no disponibles a causa d'errors: {notificationNames}",
@@ -496,7 +496,7 @@
"Logout": "Tanca la sessió",
"NoEventsFound": "No s'han trobat esdeveniments",
"RestartReloadNote": "Nota: {appName} es reiniciarà i tornarà a carregar automàticament la interfície d'usuari durant el procés de restauració.",
"TheLogLevelDefault": "El nivell de registre per defecte és \"Info\" i es pot canviar a [Configuració general](/configuració/general)",
"TheLogLevelDefault": "El nivell de registre per defecte és \"Debug\" i es pot canviar a [Configuració general](/settings/general)",
"UpdateAppDirectlyLoadError": "No es pot actualitzar {appName} directament,",
"WouldYouLikeToRestoreBackup": "Voleu restaurar la còpia de seguretat '{name}'?",
"InstallLatest": "Instal·la l'últim",
@@ -740,5 +740,72 @@
"SelectedCountOfCountReleases": "S'han seleccionat {selectedCount} de les versions {itemCount}",
"SettingsLogRotate": "Rotació del registre",
"AreYouSureYouWantToDeleteCategory": "Esteu segur que voleu suprimir la categoria assignada?",
"Book": "Llibre"
"Book": "Llibre",
"IndexerSettingsCookie": "Cookie",
"DownloadClientFreeboxSettingsAppIdHelpText": "ID d'aplicació indicat en crear accés a l'API de Freebox (ex: 'app_id')",
"DownloadClientFreeboxSettingsHostHelpText": "Nom d'amfitrió o adreça IP de l'amfitrió del Freebox, per defecte a '{url}' (només funcionarà si es troba a la mateixa xarxa)",
"DownloadClientFreeboxSettingsPortHelpText": "Port utilitzat per accedir a la interfície Freebox, per defecte a '{port}'",
"DownloadClientRTorrentSettingsUrlPath": "Camí de l'Url",
"IndexerHDBitsSettingsMediumsHelpText": "Si no s'especifica, s'utilitzen totes les opcions.",
"NotificationsEmailSettingsUseEncryptionHelpText": "Si s'ha de preferir l'ús de l'encriptatge si es configura al servidor, per utilitzar sempre l'encriptatge mitjançant SSL (només Port 465) o StartTLS (qualsevol altre port) o per no utilitzar mai l'encriptatge",
"DownloadClientQbittorrentSettingsFirstAndLastFirst": "Primer i últim",
"DownloadClientFloodSettingsTagsHelpText": "Etiquetes inicials d'una baixada. Per ser reconegut, una baixada ha de tenir totes les etiquetes inicials. Això evita conflictes amb baixades no relacionades.",
"DownloadClientQbittorrentSettingsSequentialOrder": "Ordre seqüencial",
"DownloadClientSettingsUseSslHelpText": "Usa una connexió segura quan es connecti a {clientName}",
"InstallMajorVersionUpdate": "Instal·la l'actualització",
"InstallMajorVersionUpdateMessageLink": "Si us plau, comproveu [{domain}]({url}) per a més informació.",
"OverrideGrabModalTitle": "Sobreescriu i Captura - {title}",
"SecretToken": "Testimoni secret",
"TorrentBlackholeSaveMagnetFilesExtension": "Desa l'extensió dels fitxers magnètics",
"FailedToFetchSettings": "No s'ha pogut recuperar la configuració",
"DownloadClientFreeboxSettingsApiUrlHelpText": "Defineix l'URL base de l'API de Freebox amb la versió de l'API, p. ex. '{url}', per defecte a '{defaultApiUrl}'",
"IndexerSettingsSeedTime": "Temps de la llavor",
"DownloadClientDownloadStationSettingsDirectoryHelpText": "Carpeta compartida opcional per posar les baixades, deixeu en blanc per utilitzar la ubicació predeterminada de l'estació de baixada",
"DownloadClientPneumaticSettingsNzbFolderHelpText": "Aquesta carpeta haurà de ser accessible des de XBMC",
"DownloadClientPneumaticSettingsStrmFolder": "Carpeta Strm",
"DownloadClientSettingsDestinationHelpText": "Especifica manualment la destinació de la baixada, deixeu-ho en blanc per a utilitzar el predeterminat",
"DownloadClientTransmissionSettingsUrlBaseHelpText": "Afegeix un prefix a l'URL rpc de {clientName}, ex. {url}, per defecte a {defaultUrl}",
"IndexerSettingsApiPathHelpText": "Camí a l'api, normalment {url}",
"LogSizeLimitHelpText": "Mida màxima del fitxer de registre en MB abans d'arxivar. Per defecte és 1MB.",
"IndexerNewznabSettingsAdditionalParametersHelpText": "Paràmetres addicionals de Newznab",
"InstallMajorVersionUpdateMessage": "Aquesta actualització instal·larà una nova versió principal i pot no ser compatible amb el vostre sistema. Esteu segur que voleu instal·lar aquesta actualització?",
"PackageVersionInfo": "{packageVersion} per {packageAuthor}",
"UpdaterLogFiles": "Fitxers de registre de l'actualitzador",
"NotificationsEmailSettingsUseEncryption": "Utilitza l'encriptatge",
"NotificationsTelegramSettingsIncludeAppNameHelpText": "Opcionalment prefixa el títol del missatge amb {appName} per diferenciar les notificacions de diferents aplicacions",
"DownloadClientSettingsInitialState": "Estat inicial",
"DownloadClientSettingsInitialStateHelpText": "Estat inicial dels torrents afegits a {clientName}",
"IndexerPassThePopcornSettingsApiUserHelpText": "Aquests paràmetres es troben a la configuració de seguretat de PassThePopcorn (Edita el perfil > Seguretat).",
"DownloadClientRTorrentSettingsUrlPathHelpText": "Camí al extrem XMLRPC, vegeu {url}. Normalment és RPC2 o [camí a ruTorrent]{url2} quan s'utilitza ruTorrent.",
"IndexerSettingsApiPath": "Camí de l'API",
"IndexerHDBitsSettingsCodecsHelpText": "Si no s'especifica, s'utilitzen totes les opcions.",
"IndexerSettingsApiUser": "Usuari de l'API",
"IndexerSettingsSeedTimeHelpText": "El temps en què s'ha de sembrar un torrent abans d'aturar-lo, el buit utilitza el valor per defecte del client de baixada",
"IndexerSettingsSeedRatio": "Ràtio de la llavor",
"IndexerSettingsSeedRatioHelpText": "Ràtio a la qual ha d'arribar un torrent abans d'aturar-se, buit utilitza el valor per defecte del client de baixada. La relació ha de ser com a mínim 1.0 i seguir les regles dels indexadors",
"IndexerSettingsAdditionalParameters": "Paràmetres addicionals",
"DownloadClientFloodSettingsAdditionalTagsHelpText": "Afegeix les propietats dels suports com a etiquetes. Els consells són exemples.",
"DownloadClientFloodSettingsUrlBaseHelpText": "Afegeix un prefix a l'API de Flood, com ara {url}",
"DownloadClientFreeboxSettingsAppToken": "Testimoni d'aplicació",
"DownloadClientNzbgetSettingsAddPausedHelpText": "Aquesta opció requereix com a mínim la versió 16.0 de NzbGet",
"DownloadClientPneumaticSettingsNzbFolder": "Carpeta Nzb",
"DownloadClientPneumaticSettingsStrmFolderHelpText": "Els fitxers .strm d'aquesta carpeta s'importaran amb el dron",
"DownloadClientQbittorrentSettingsFirstAndLastFirstHelpText": "Baixeu primer i primer les últimes peces (qBittorrent 4.1.0+)",
"DownloadClientQbittorrentSettingsSequentialOrderHelpText": "Baixada en ordre seqüencial (qBittorrent 4.1.0+)",
"LabelIsRequired": "L'etiqueta és necessària",
"NotificationsTelegramSettingsIncludeAppName": "Inclou {appName} al títol",
"TorrentBlackholeSaveMagnetFiles": "Desa els fitxers Magnet",
"TorrentBlackholeSaveMagnetFilesExtensionHelpText": "Extensió a utilitzar per als enllaços magnet, per defecte és '.magnet'",
"TorrentBlackholeSaveMagnetFilesHelpText": "Desa l'enllaç magnet si no hi ha cap fitxer .torrent disponible (només útil si el client de baixada admet magnets desats a un fitxer)",
"TorrentBlackholeTorrentFolder": "Carpeta torrent",
"UseSsl": "Usa SSL",
"UsenetBlackholeNzbFolder": "Carpeta Nzb",
"XmlRpcPath": "Camí RPC XML",
"DownloadClientRTorrentSettingsAddStopped": "Afegeix aturat",
"DownloadClientRTorrentSettingsAddStoppedHelpText": "En activar s'afegiran torrents i imants a rTorrent en un estat aturat. Això pot trencar els fitxers magnet.",
"DownloadClientFreeboxSettingsAppTokenHelpText": "S'ha recuperat el testimoni de l'aplicació en crear l'accés a l'API de Freebox (ex: 'app_token')",
"DownloadClientUTorrentProviderMessage": "uTorrent té un historial d'inclusió de criptominers, programari maliciós i anuncis, us animem a triar un client diferent.",
"DownloadClientQbittorrentSettingsInitialStateHelpText": "Estat inicial dels torrents afegits a qBittorrent. Tingueu en compte que els torrents forçats no compleixen amb les restriccions de llavors",
"LogSizeLimit": "Límit de la mida del registre",
"SelectDownloadClientModalTitle": "{modalTitle} - Seleccioneu el client de baixada"
}
+1 -1
View File
@@ -296,7 +296,7 @@
"Title": "Titul",
"Today": "Dnes",
"Tomorrow": "Zítra",
"Torrent": "Torrenty",
"Torrent": "Torrent",
"Torrents": "Torrenty",
"Type": "Typ",
"UI": "UI",
+11 -10
View File
@@ -118,7 +118,7 @@
"ElapsedTime": "Vergangene Zeit",
"Enable": "Aktivieren",
"EnableAutomaticSearch": "Automatische Suche einschalten",
"EnableAutomaticSearchHelpText": "Wird verwendet, wenn die automatische Suche über die Benutzeroberfläche oder durch {appName} durchgeführt wird.",
"EnableAutomaticSearchHelpText": "Wird verwendet, wenn die automatische Suche über die Benutzeroberfläche oder durch {appName} durchgeführt wird",
"EnableIndexer": "Indexer aktivieren",
"EnableInteractiveSearch": "Interaktive Suche einschalten",
"EnableInteractiveSearchHelpText": "Wird verwendet, wenn die interaktive Suche verwendet wird",
@@ -179,7 +179,7 @@
"IndexerLongTermStatusAllUnavailableHealthCheckMessage": "Alle Indexer sind aufgrund von Fehlern länger als 6 Stunden nicht verfügbar",
"IndexerLongTermStatusUnavailableHealthCheckMessage": "Indexer sind aufgrund von Fehlern länger als 6 Stunden nicht verfügbar: {indexerNames}",
"IndexerName": "Indexer-Name",
"IndexerNoDefinitionCheckHealthCheckMessage": "Indexer haben keine Definition und werden nicht funktionieren: {indexerNames}. Bitte entferne und (oder) füge diese neu zu {appName} hinzu",
"IndexerNoDefinitionCheckHealthCheckMessage": "Indexer haben keine Definition und werden nicht funktionieren: {indexerNames}. Bitte entferne und (oder) füge diese neu zu {appName} hinzu.",
"IndexerObsoleteCheckMessage": "Indexer sind nicht mehr verfügbar oder wurden aktualiiert: {0}. Bitte enfernen und (oder) neu zu {appName} hinzufügen",
"IndexerPriority": "Indexer-Priorität",
"IndexerPriorityHelpText": "Indexer Priorität von 1 (höchste) bis 50 (niedrigste). Standard: 25.",
@@ -496,7 +496,7 @@
"RecentChanges": "Kürzliche Änderungen",
"WhatsNew": "Was ist neu?",
"minutes": "Minuten",
"DeleteAppProfileMessageText": "Qualitätsprofil '{0}' wirklich löschen?",
"DeleteAppProfileMessageText": "Qualitätsprofil '{name}' wirklich löschen?",
"AddConnection": "Verbindung hinzufügen",
"NotificationStatusAllClientHealthCheckMessage": "Alle Benachrichtigungen sind aufgrund von Fehlern nicht verfügbar",
"NotificationStatusSingleClientHealthCheckMessage": "Benachrichtigungen nicht verfügbar wegen Fehlern: {notificationNames}",
@@ -563,7 +563,7 @@
"IndexerBeyondHDSettingsSearchTypes": "Suchtyp",
"DownloadClientFloodSettingsUrlBaseHelpText": "Fügt der Flood-API ein Präfix hinzu, z. B. {url}",
"DownloadClientFreeboxSettingsApiUrl": "API-URL",
"DownloadClientFreeboxSettingsApiUrlHelpText": "Definiere die Freebox-API-Basis-URL mit der API-Version, z. B. '{url}', standardmäßig '{defaultApiUrl}'.",
"DownloadClientFreeboxSettingsApiUrlHelpText": "Definiere die Freebox-API-Basis-URL mit der API-Version, z. B. '{url}', standardmäßig '{defaultApiUrl}'",
"DownloadClientRTorrentSettingsUrlPathHelpText": "Pfad zum XMLRPC-Endpunkt, siehe {url}. Dies ist normalerweise RPC2 oder [Pfad zu ruTorrent]{url2}, wenn ruTorrent verwendet wird.",
"DownloadClientSettingsAddPaused": "Pausiert hinzufügen",
"SelectDownloadClientModalTitle": "{modalTitle} Wähle Download-Client",
@@ -596,7 +596,7 @@
"TorrentBlackholeTorrentFolder": "Torrent-Ordner",
"UseSsl": "SSL verwenden",
"UsenetBlackholeNzbFolder": "NZB-Ordner",
"TorrentBlackholeSaveMagnetFilesExtensionHelpText": "Für Magnet-Links zu verwendende Erweiterung, standardmäßig „.magnet“.",
"TorrentBlackholeSaveMagnetFilesExtensionHelpText": "Für Magnet-Links zu verwendende Erweiterung, standardmäßig „.magnet“",
"XmlRpcPath": "XML-RPC-Pfad",
"ProxyValidationBadRequest": "Proxy konnte nicht getestet werden. StatusCode: {statusCode}",
"SecretToken": "Geheimer Token",
@@ -612,15 +612,15 @@
"BuiltIn": "Eingebaut",
"PublishedDate": "Veröffentlichungsdatum",
"Redirected": "Umleiten",
"AllSearchResultsHiddenByFilter": "Alle Ergebnisse werden durch den angewendeten Filter ausgeblendet",
"AllSearchResultsHiddenByFilter": "Alle Ergebnisse werden durch den angewendeten Filter ausgeblendet.",
"DockerUpdater": "Aktualisieren Sie den Docker-Container, um das Update zu erhalten",
"Download": "Herunterladen",
"ErrorRestoringBackup": "Fehler beim Wiederherstellen der Sicherung",
"ExternalUpdater": "{appName} ist so konfiguriert, dass es einen externen Aktualisierungsmechanismus verwendet",
"NoEventsFound": "Keine Ereignisse gefunden",
"RestartReloadNote": "Hinweis: {appName} startet während des Wiederherstellungsvorgangs automatisch neu und lädt die Benutzeroberfläche neu.",
"TheLogLevelDefault": "Die Protokollebene ist standardmäßig auf „Info“ eingestellt und kann unter „Allgemeine Einstellungen“ (/settings/general) geändert werden.",
"UpdateAppDirectlyLoadError": "{appName} kann nicht direkt aktualisiert werden.",
"TheLogLevelDefault": "Die Protokollebene ist standardmäßig auf „Debug“ eingestellt und kann unter „Allgemeine Einstellungen“ (/settings/general) geändert werden",
"UpdateAppDirectlyLoadError": "{appName} kann nicht direkt aktualisiert werden,",
"UpdaterLogFiles": "Updater-Protokolldateien",
"WouldYouLikeToRestoreBackup": "Willst du das Backup '{name}' wiederherstellen?",
"AptUpdater": "Verwenden Sie apt, um das Update zu installieren",
@@ -658,7 +658,7 @@
"IndexerSettingsApiPath": "API-Pfad",
"IndexerSettingsApiPathHelpText": "Pfad zur API, normalerweise {url}",
"DownloadClientTransmissionSettingsUrlBaseHelpText": "Fügt der {clientName}-rpc-URL ein Präfix hinzu, z. B. {url}, standardmäßig '{defaultUrl}'",
"IndexerSettingsSeedRatioHelpText": "Das Verhältnis, das ein Torrent erreichen muss, bevor er gestoppt wird. Leer verwendet das Standardverhältnis des Download-Clients. Das Verhältnis sollte mindestens 1,0 betragen und den Regeln des Indexers folgen.",
"IndexerSettingsSeedRatioHelpText": "Das Verhältnis, das ein Torrent erreichen muss, bevor er gestoppt wird. Leer verwendet das Standardverhältnis des Download-Clients. Das Verhältnis sollte mindestens 1,0 betragen und den Regeln des Indexers folgen",
"IndexerSettingsSeedTimeHelpText": "Die Zeit, die ein Torrent gesät werden sollte, bevor er gestoppt wird. Leer verwendet die Standardzeit des Download-Clients",
"InstallMajorVersionUpdate": "Update installieren",
"InstallMajorVersionUpdateMessage": "Dieses Update wird eine neue Hauptversion installieren und ist möglicherweise nicht mit deinem System kompatibel. Bist du sicher, dass du dieses Update installieren möchtest?",
@@ -806,5 +806,6 @@
"IndexerSettingsBaseUrlHelpText": "Wähle die Basis-Url aus, die {appName} für Anfragen an die Seite verwenden soll",
"RepeatSearch": "Suche wiederholen",
"AverageResponseTimesMs": "Durchschnittliche Indexer-Antwortzeiten (ms)",
"BasicSearch": "Einfache Suche"
"BasicSearch": "Einfache Suche",
"DownloadClientUTorrentProviderMessage": "uTorrent ist dafür bekannt, dass es Kryptominer, Malware und Werbung enthält. Wir empfehlen dringend einen anderen Client zu wählen."
}
+1 -1
View File
@@ -485,7 +485,7 @@
"Theme": "Θέμα",
"Track": "Ιχνος",
"Year": "Ετος",
"UpdateAvailableHealthCheckMessage": "Νέα ενημέρωση είναι διαθέσιμη",
"UpdateAvailableHealthCheckMessage": "Νέα ενημέρωση είναι διαθέσιμη: {version}",
"Artist": "Καλλιτέχνης",
"Author": "Συγγραφέας",
"Book": "Βιβλίο",
+1 -1
View File
@@ -724,7 +724,7 @@
"TestAllApps": "Test All Apps",
"TestAllClients": "Test All Clients",
"TestAllIndexers": "Test All Indexers",
"TheLogLevelDefault": "The log level defaults to 'Info' and can be changed in [General Settings](/settings/general)",
"TheLogLevelDefault": "The log level defaults to 'Debug' and can be changed in [General Settings](/settings/general)",
"Theme": "Theme",
"ThemeHelpText": "Change Application UI Theme, 'Auto' Theme will use your OS Theme to set Light or Dark mode. Inspired by {inspiredBy}.",
"Time": "Time",
+3 -2
View File
@@ -710,7 +710,7 @@
"Logout": "Kirjaudu ulos",
"NoEventsFound": "Tapahtumia ei löytynyt",
"RestartReloadNote": "Huomioi: {appName} käynnistyy palautusprosessin aikana automaattisesti uudelleen.",
"TheLogLevelDefault": "Lokikirjauksen oletusarvoinen laajuus on \"Informatiivinen\". Laajuutta voidaan muuttaa [Yleisistä asetuksista](/settings/general).",
"TheLogLevelDefault": "Lokikirjauksen oletusarvoinen laajuus on \"Vianselvitys\". Laajuutta voidaan muuttaa [Yleisistä asetuksista](/settings/general).",
"UpdateAppDirectlyLoadError": "{appName}ia ei voida päivittää suoraan,",
"UpdaterLogFiles": "Päivittäjän lokitiedostot",
"WouldYouLikeToRestoreBackup": "Haluatko palauttaa varmuuskopion \"{name}\"?",
@@ -806,5 +806,6 @@
"IndexerPassThePopcornSettingsGoldenPopcornOnlyHelpText": "Etsi vain ns. kultaisella pocornilla merkittyjä julkaisuja.",
"IndexerSettingsFreeleechOnly": "Vain \"Freeleech\"",
"IndexerSettingsCookieHelpText": "Jos sivusto vaatii kirjautumisevästeen, on se noudettava selaimen avulla.",
"IndexerAvistazSettingsPasswordHelpText": "Sivuston salasana"
"IndexerAvistazSettingsPasswordHelpText": "Sivuston salasana",
"DownloadClientUTorrentProviderMessage": "Koska uTorrent on tullut tunnetuksi kryptolouhinnasta sekä haitta- ja mainossisällöstä, suosittelemme valitsemaan jonkin muun työkalun."
}
+1 -1
View File
@@ -481,7 +481,7 @@
"Genre": "Műfajok",
"Theme": "Téma",
"Track": "Dal",
"UpdateAvailableHealthCheckMessage": "Új frissítés elérhető",
"UpdateAvailableHealthCheckMessage": "Új frissítés elérhető: {version}",
"Year": "Év",
"Book": "Könyv",
"Season": "Évad",
+8 -2
View File
@@ -482,7 +482,7 @@
"More": "Altro",
"Season": "Stagione",
"Year": "Anno",
"UpdateAvailableHealthCheckMessage": "Nuovo aggiornamento disponibile",
"UpdateAvailableHealthCheckMessage": "Nuovo aggiornamento disponibile: {version}",
"Author": "Autore",
"ApplyChanges": "Applica Cambiamenti",
"ApiKeyValidationHealthCheckMessage": "Aggiorna la tua chiave API in modo che abbia una lunghezza di almeno {length} caratteri. Puoi farlo dalle impostazioni o dal file di configurazione",
@@ -661,5 +661,11 @@
"InstallLatest": "Installa il più recente",
"CurrentlyInstalled": "Attualmente Installato",
"PreviouslyInstalled": "Precedentemente Installato",
"Mixed": "Fissato"
"Mixed": "Fissato",
"ApplicationTagsHelpText": "Sincronizza gli indexer con questa applicazione se hanno uno o più tag corrispondenti. Se non sono elencati tag, nessun indexer verrà escluso dalla sincronizzazione a causa dei propri tag.",
"ApplicationTagsHelpTextWarning": "I tag devono essere usati con cautela, poiché possono avere effetti indesiderati. Un'app con un tag si sincronizzerà solo con gli indexer che hanno lo stesso tag.",
"AuthQueries": "Query di autenticazione",
"ApplicationSettingsSyncRejectBlocklistedTorrentHashesHelpText": "Se un torrent è bloccato tramite hash, potrebbe non essere correttamente rifiutato durante luso di RSS/Ricerca con alcuni indexer. Abilitando questa opzione, il torrent verrà rifiutato dopo essere stato acquisito, ma prima di essere inviato al client.",
"AppsMinimumSeedersHelpText": "Numero minimo di seeders richiesti dallapplicazione affinché lindexer possa acquisire il torrent; se vuoto, viene utilizzato il valore predefinito del profilo di sincronizzazione",
"IndexerSettingsAppsMinimumSeedersHelpText": "Numero minimo di seeders richiesti dallapplicazione affinché lindexer possa acquisire il torrent; se vuoto, viene utilizzato il valore predefinito del profilo di sincronizzazione"
}
@@ -161,5 +161,6 @@
"Discord": "Discord",
"AddCustomFilter": "Legg til eget filter",
"Clone": "Lukk",
"AddDownloadClientImplementation": "Ny Nedlastingsklient - {implementationName}"
"AddDownloadClientImplementation": "Ny Nedlastingsklient - {implementationName}",
"History": "Historikk"
}
+1 -1
View File
@@ -438,7 +438,7 @@
"DownloadClientPriorityHelpText": "Geef prioriteit aan meerdere downloaders. Round-Robin wordt gebruikt voor downloaders met dezelfde prioriteit.",
"Genre": "Genres",
"Year": "Jaar",
"UpdateAvailableHealthCheckMessage": "Nieuwe update is beschikbaar",
"UpdateAvailableHealthCheckMessage": "Nieuwe update is beschikbaar: {version}",
"Label": "Label",
"Publisher": "Uitgever",
"ApplyChanges": "Pas Wijzigingen Toe",
+1 -1
View File
@@ -357,7 +357,7 @@
"DeleteSelectedIndexersMessageText": "Czy na pewno chcesz usunąć indeksator „{0}”?",
"DownloadClientPriorityHelpText": "Nadaj priorytet wielu klientom pobierania. W przypadku klientów o tym samym priorytecie używane jest działanie okrężne.",
"Track": "Ślad",
"UpdateAvailableHealthCheckMessage": "Dostępna jest aktualizacja",
"UpdateAvailableHealthCheckMessage": "Dostępna jest aktualizacja: {version}",
"Genre": "Gatunki",
"ApplyChanges": "Zastosuj zmiany",
"ApiKeyValidationHealthCheckMessage": "Zaktualizuj swój klucz API aby był długi na co najmniej {length} znaków. Możesz to zrobić poprzez ustawienia lub plik konfiguracyjny",
+7 -2
View File
@@ -431,7 +431,7 @@
"Season": "Temporada",
"Theme": "Tema",
"Track": "Rastreio",
"UpdateAvailableHealthCheckMessage": "Nova atualização disponível",
"UpdateAvailableHealthCheckMessage": "Nova atualização disponível: {version}",
"Label": "Rótulo",
"ConnectionLostReconnect": "O {appName} tentará ligar-se automaticamente, ou você pode clicar em Recarregar abaixo.",
"ConnectionLostToBackend": "O {appName} perdeu a ligação com o back-end e precisará ser recarregado para restaurar a funcionalidade.",
@@ -503,5 +503,10 @@
"UpdateAppDirectlyLoadError": "Não foi possível atualizar o {appName} diretamente,",
"InstallLatest": "Instalar o mais recente",
"CurrentlyInstalled": "Atualmente instalado",
"Mixed": "Corrigido"
"Mixed": "Corrigido",
"FailedToFetchSettings": "Falha ao obter as definições",
"FailedToFetchUpdates": "Falha a obter atualizações",
"External": "Externo",
"Categories": "Categorias",
"days": "dias"
}
@@ -794,7 +794,7 @@
"LogFilesLocation": "Os arquivos de log estão localizados em: {location}",
"Logout": "Sair",
"NoEventsFound": "Nenhum evento encontrado",
"TheLogLevelDefault": "O nível de registro é padronizado como 'Info' e pode ser alterado em [Configurações Gerais](/settings/general)",
"TheLogLevelDefault": "O nível de log padrão é ' Debug ' e pode ser alterado em [ Configurações gerais](/ configurações/geral)",
"UpdateAppDirectlyLoadError": "Incapaz de atualizar o {appName} diretamente,",
"UpdaterLogFiles": "Arquivos de log do atualizador",
"WouldYouLikeToRestoreBackup": "Gostaria de restaurar o backup '{name}'?",
+1 -1
View File
@@ -544,7 +544,7 @@
"LogFilesLocation": "Log kayıtlarının bulunduğu konum: {location}",
"NoEventsFound": "Etkinlik bulunamadı",
"RestartReloadNote": "Not: {appName} geri yükleme işlemi sırasında otomatik olarak yeniden başlatılacak ve kullanıcı arayüzünü yeniden yükleyecektir.",
"TheLogLevelDefault": "Log seviyesi varsayılan olarak 'Bilgi' şeklindedir ve [Genel Ayarlar](/ayarlar/genel) bölümünden değiştirilebilir",
"TheLogLevelDefault": "Günlük düzeyi varsayılan olarak 'Hata Ayıklama'dır ve [Genel Ayarlar](/ayarlar/genel) bölümünden değiştirilebilir",
"UpdateAppDirectlyLoadError": "{appName} doğrudan güncellenemiyor,",
"DockerUpdater": "Güncellemeyi almak için docker konteynerini güncelleyin",
"FailedToFetchUpdates": "Güncellemeler alınamadı",
+100 -2
View File
@@ -353,7 +353,7 @@
"More": "Більше",
"Track": "Трасувати",
"Year": "Рік",
"UpdateAvailableHealthCheckMessage": "Доступне нове оновлення",
"UpdateAvailableHealthCheckMessage": "Доступне нове оновлення: {version}",
"Genre": "Жанри",
"ConnectionLostReconnect": "{appName} спробує підключитися автоматично, або ви можете натиснути «Перезавантажити» нижче.",
"ConnectionLostToBackend": "{appName} втратив з’єднання з серверною частиною, і його потрібно перезавантажити, щоб відновити роботу.",
@@ -449,5 +449,103 @@
"Author": "Автор",
"OnHealthRestoredHelpText": "При відновленні стану",
"IndexerHDBitsSettingsOriginsHelpText": "Якщо не вказано, використовуються всі параметри.",
"days": "дні(в)"
"days": "дні(в)",
"XmlRpcPath": "Шлях XML RPC",
"Directory": "Тека",
"DownloadClientFreeboxSettingsAppId": "ID додатку",
"DownloadClientQbittorrentSettingsFirstAndLastFirst": "Перше і останнє спочатку",
"FailedToFetchUpdates": "Не вдалося завантажити оновлення",
"OverrideGrabModalTitle": "Перевизначити та захопити - {title}",
"UpdaterLogFiles": "Файли журналу оновлення",
"UseSsl": "Використовувати SSL",
"WouldYouLikeToRestoreBackup": "Бажаєте відновити резервну копію '{name}'?",
"DownloadClientSettingsInitialState": "Початковий стан",
"Install": "Встановити",
"InstallMajorVersionUpdateMessage": "Це оновлення встановить нову основну версію і може бути несумісним з вашою системою. Ви впевнені, що хочете встановити це оновлення?",
"Logout": "Завершити сеанс",
"NoDownloadClientsFound": "Клієнти завантаження не знайдено",
"PackageVersionInfo": "{packageVersion} створено {packageAuthor}",
"SecretToken": "Таємний токен",
"DownloadClientFloodSettingsAdditionalTagsHelpText": "Додає властивості мультимедіа у вигляді тегів. Підказки є прикладами.",
"DownloadClientRTorrentSettingsUrlPathHelpText": "Шлях до кінцевої точки XMLRPC див. {url}. Зазвичай це RPC2 або [шлях до ruTorrent]{url2}, коли використовується ruTorrent.",
"DownloadClientSettingsAddPaused": "Додати призупинені",
"FailedToFetchSettings": "Не вдалося отримати налаштування",
"IndexerNewznabSettingsAdditionalParametersHelpText": "Додаткові параметри Newznab",
"DownloadClientPneumaticSettingsNzbFolderHelpText": "Ця тека повинна бути доступна з XBMC",
"DownloadClientPneumaticSettingsStrmFolder": "Тека STRM",
"DownloadClientPneumaticSettingsStrmFolderHelpText": "Файли .strm у цій теці будуть імпортовані дроном",
"InfoUrl": "URL-адреса інформації",
"DownloadClientUTorrentProviderMessage": "uTorrent має історію включення криптомайнерів, шкідливого програмного забезпечення та реклами. Ми наполегливо рекомендуємо вибрати інший клієнт.",
"EditSelectedDownloadClients": "Редагувати вибрані клієнти завантаження",
"IndexerHDBitsSettingsMediumsHelpText": "Якщо не вказано, використовуються всі параметри.",
"IndexerSettingsAdditionalParameters": "Додаткові параметри",
"IndexerSettingsCookie": "Cookie",
"InstallMajorVersionUpdateMessageLink": "Будь ласка, перевірте [{domain}]({url}) для отримання додаткової інформації.",
"InvalidUILanguage": "У вашому інтерфейсі встановлена недопустима мова. Виправте її та збережіть налаштування",
"LogFilesLocation": "Файли журналу знаходяться в: {location}",
"Menu": "Меню",
"OnHealthRestored": "При відновленні стану",
"PasswordConfirmation": "Підтвердження пароля",
"PreviouslyInstalled": "Раніше встановлений",
"LogSizeLimit": "Обмеження розміру журналу",
"LogSizeLimitHelpText": "Максимальний розмір файлу журналу в МБ перед архівацією. За замовчуванням - 1 МБ.",
"SelectDownloadClientModalTitle": "{modalTitle} - Вибрати клієнт завантаження",
"IndexerSettingsApiPath": "Шлях API",
"IndexerSettingsApiPathHelpText": "Шлях до API, зазвичай {url}",
"IndexerSettingsApiUser": "API Користувач",
"Implementation": "Реалізація",
"ManageDownloadClients": "Керування клієнтами завантаження",
"No": "Ні",
"IndexerSettingsSeedRatioHelpText": "Рейтинг, якого має досягти торрент перед зупинкою. Якщо порожньо — використовується значення за замовчуванням клієнта завантаження. Рейтинг має бути не менше 1,0 і відповідати правилам індексаторів",
"IndexerSettingsSeedTimeHelpText": "Час, протягом якого торрент має залишатися на роздачі перед зупинкою, якщо порожньо — використовується значення клієнта завантаження за замовчуванням",
"NotificationsTelegramSettingsIncludeAppName": "Включити {appName} у заголовок",
"NotificationsTelegramSettingsIncludeAppNameHelpText": "При необхідності додати до заголовка повідомлення префікс {appName}, щоб відрізняти сповіщення від різних додатків",
"DownloadClientQbittorrentSettingsContentLayout": "Макет контента",
"External": "Зовнішній",
"TorrentBlackholeTorrentFolder": "Тека торрента",
"Donate": "Задонатити",
"EditSelectedIndexers": "Редагувати вибраний індексатор",
"IndexerSettingsSeedTime": "Час сидіння",
"Label": "Мітка",
"LabelIsRequired": "Необхідна мітка",
"UsenetBlackholeNzbFolder": "Тека NZB",
"NoHistoryFound": "Історія не знайдена",
"NoIndexersFound": "Индексаторі не знайдено",
"DownloadClientNzbgetSettingsAddPausedHelpText": "Для роботи цього параметра потрібна версія NzbGet не нижче 16.0",
"DownloadClientPneumaticSettingsNzbFolder": "Тека NZB",
"IndexerHDBitsSettingsCodecsHelpText": "Якщо не вказано, використовуються всі параметри.",
"DefaultNameCopiedProfile": "{name} - Копіювати",
"Destination": "Місце призначення",
"DownloadClientFloodSettingsTagsHelpText": "Початкові теги завантаження. Щоб бути розпізнаним, завантаження повинно мати всі початкові теги. Це запобігає конфліктам з незв'язаними завантаженнями.",
"DownloadClientFreeboxSettingsAppIdHelpText": "ID програми, отримане під час створення доступу до Freebox API (наприклад, 'app_id')",
"DownloadClientFreeboxSettingsAppToken": "Токен додатку",
"DownloadClientFreeboxSettingsAppTokenHelpText": "Токен додатку, отриманий під час створення доступу до Freebox API (наприклад, 'app_token')",
"DownloadClientFreeboxSettingsHostHelpText": "Ім'я хоста або IP-адреса хоста Freebox, за замовчуванням — '{url}' (працює тільки якщо знаходиться в тій самій мережі)",
"DownloadClientFreeboxSettingsPortHelpText": "Порт, що використовується для доступу до інтерфейсу Freebox, за замовчуванням — '{port}'",
"DownloadClientQbittorrentSettingsInitialStateHelpText": "Початковий стан торрентів, доданих до qBittorrent. Зверніть увагу, що примусові торренти не дотримуються обмежень на роздачу",
"DownloadClientQbittorrentSettingsSequentialOrder": "Завантажувати послідовно",
"DownloadClientRTorrentSettingsAddStopped": "Додати зупинені",
"DownloadClientRTorrentSettingsAddStoppedHelpText": "Увімкнення додасть торренти та магнет-посилання в rTorrent у зупиненому стані. Це може призвести до пошкодження магнет-файлів.",
"DownloadClientRTorrentSettingsUrlPath": "URL-путь",
"NotificationsEmailSettingsUseEncryptionHelpText": "Виберіть режим шифрування: віддавати перевагу шифруванню, якщо воно налаштоване на сервері; завжди використовувати шифрування через SSL (тільки порт 465) або StartTLS (будь-який інший порт); ніколи не використовувати шифрування",
"DownloadClientFreeboxSettingsApiUrlHelpText": "Вкажіть базову URL-адресу Freebox API з версією API, наприклад, '{url}', за замовчуванням — '{defaultApiUrl}'",
"DownloadClientSettingsDestinationHelpText": "Ручне налаштування місця для завантаження, залиште порожнім для використання значення за замовчуванням",
"DownloadClientSettingsUseSslHelpText": "Використовувати захищене з'єднання при підключенні до {clientName}",
"HealthMessagesInfoBox": "Додаткову інформацію про причину появи цих повідомлень перевірки працездатності можна знайти, перейшовши за посиланням wiki (іконка книги) в кінці рядка або перевірити [журнали]({link}). Якщо у вас виникли труднощі з розумінням цих повідомлень, ви можете звернутися до нашої служби підтримки за посиланнями нижче.",
"IndexerDownloadClientHealthCheckMessage": "Індексатори з недопустимими клієнтами завантаження: {indexerNames}.",
"Episode": "Епізод",
"InstallMajorVersionUpdate": "Встановити оновлення",
"ManageClients": "Керування клієнтами",
"PrioritySettings": "Пріоритет: {0}",
"IndexerPassThePopcornSettingsApiUserHelpText": "Ці налаштування можна знайти в налаштуваннях безпеки вашого PassThePopcorn (Редагувати профіль > Безпека).",
"NotificationsEmailSettingsUseEncryption": "Використовувати шифрування",
"TorrentBlackholeSaveMagnetFiles": "Зберігати магнітні файли",
"TorrentBlackholeSaveMagnetFilesExtension": "Зберегти магнет-файли з розширенням",
"TorrentBlackholeSaveMagnetFilesExtensionHelpText": "Розширення для магнет-посилань, за замовчуванням '.magnet'",
"TorrentBlackholeSaveMagnetFilesHelpText": "Зберегти магнет-посилання, якщо файл .torrent недоступний (корисно тільки в разі, якщо клієнт завантаження підтримує магнет-посилання, збережені у файлі)",
"DownloadClientDelugeSettingsUrlBaseHelpText": "Додає префікс до URL-адреси json, {url}",
"DownloadClientTransmissionSettingsUrlBaseHelpText": "Додає префікс до URL-адреси RPC {clientName}, наприклад {url}, за замовчуванням — '{defaultUrl}'",
"IndexerSettingsSeedRatio": "Коефіцієнт роздачі",
"ManualGrab": "Захват вручну",
"StopSelecting": "Скасувати вибір"
}
@@ -464,7 +464,7 @@
"UnsavedChanges": "未保存更改",
"UnselectAll": "取消全选",
"UpdateAutomaticallyHelpText": "自动下载并安装更新。您还可以在「“系统”->“更新”」中安装",
"UpdateAvailableHealthCheckMessage": "有新的更新可用",
"UpdateAvailableHealthCheckMessage": "有新的更新可用: {version}",
"UpdateStartupNotWritableHealthCheckMessage": "无法安装更新,因为用户“{userName}”对于启动文件夹“{startupFolder}”没有写入权限。",
"UpdateStartupTranslocationHealthCheckMessage": "无法安装更新,因为启动文件夹“{0}”在一个应用程序迁移文件夹。Cannot install update because startup folder '{startupFolder}' is in an App Translocation folder.",
"UpdateUiNotWritableHealthCheckMessage": "无法安装升级,因为用户“{userName}”不可写入界面文件夹“{uiFolder}”。",
@@ -754,5 +754,6 @@
"IndexerPassThePopcornSettingsFreeleechOnlyHelpText": "只搜索免费发布",
"IndexerFileListSettingsFreeleechOnlyHelpText": "只搜索免费发布",
"IndexerFileListSettingsUsernameHelpText": "网站用户名",
"IndexerBeyondHDSettingsRefundOnlyHelpText": "Search refund only"
"IndexerBeyondHDSettingsRefundOnlyHelpText": "Search refund only",
"DownloadClientUTorrentProviderMessage": "由于uTorrent以加密软件、恶意软件和广告而闻名,我们建议切换到更好的客户端,例如qBittorrent、Deluge或ruTorrent。"
}
@@ -3,5 +3,7 @@
"Add": "添加",
"Analytics": "分析",
"Username": "用户名",
"AcceptConfirmationModal": "中文"
"AcceptConfirmationModal": "中文",
"Backup": "备份",
"BackupNow": "立即备份"
}
@@ -106,7 +106,8 @@ namespace NzbDrone.Core.Messaging.Events
_taskFactory.StartNew(() =>
{
handlerLocal.HandleAsync(@event);
}, TaskCreationOptions.PreferFairness)
},
TaskCreationOptions.PreferFairness)
.LogExceptions();
}
@@ -119,7 +120,8 @@ namespace NzbDrone.Core.Messaging.Events
_logger.Trace("{0} ~> {1}", eventName, handlerLocal.GetType().Name);
handlerLocal.HandleAsync(@event);
_logger.Trace("{0} <~ {1}", eventName, handlerLocal.GetType().Name);
}, TaskCreationOptions.PreferFairness)
},
TaskCreationOptions.PreferFairness)
.LogExceptions();
}
}
@@ -91,7 +91,7 @@ namespace NzbDrone.Core.Notifications.Apprise
{
if (httpException.Response.StatusCode == HttpStatusCode.Unauthorized)
{
_logger.Error(ex, $"HTTP Auth credentials are invalid: {0}", ex.Message);
_logger.Error(ex, "HTTP Auth credentials are invalid: {0}", ex.Message);
return new ValidationFailure("AuthUsername", $"HTTP Auth credentials are invalid: {ex.Message}");
}
@@ -99,7 +99,7 @@ namespace NzbDrone.Core.Notifications.Apprise
{
var error = Json.Deserialize<AppriseError>(httpException.Response.Content);
_logger.Error(ex, $"Unable to send test message. Response from API: {0}", error.Error);
_logger.Error(ex, "Unable to send test message. Response from API: {0}", error.Error);
return new ValidationFailure(string.Empty, $"Unable to send test message. Response from API: {error.Error}");
}
@@ -44,7 +44,7 @@ namespace NzbDrone.Core.Notifications.Mailgun
const string body = "This is a test message from Prowlarr, though Mailgun.";
_proxy.SendNotification(title, body, Settings);
_logger.Info("Successsfully sent email though Mailgun.");
_logger.Info("Successfully sent email though Mailgun.");
}
catch (Exception ex)
{
@@ -34,7 +34,7 @@ namespace NzbDrone.Core.Notifications.Mailgun
{
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
{
_logger.Error("Unathorized - ApiKey is invalid");
_logger.Error("Unauthorized - ApiKey is invalid");
throw new MailgunException("Unauthorized - ApiKey is invalid");
}
@@ -77,7 +77,7 @@ namespace NzbDrone.Core.Notifications.Twitter
using (var reader = new StreamReader(responseStream))
{
var responseBody = reader.ReadToEnd();
_logger.Trace("Reponse: {0} Status Code: {1}", responseBody, httpResponse.StatusCode);
_logger.Trace("Response: {0} Status Code: {1}", responseBody, httpResponse.StatusCode);
throw new TwitterException("Error received from Twitter: " + responseBody, ex);
}
}
+12 -12
View File
@@ -1,31 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AngleSharp.Xml" Version="1.0.0" />
<PackageReference Include="Dapper" Version="2.0.151" />
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Diacritical.Net" Version="1.0.4" />
<PackageReference Include="MailKit" Version="4.8.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="6.0.35" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="2.1.7" />
<PackageReference Include="MailKit" Version="4.12.1" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.16" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.16" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
<PackageReference Include="Npgsql" Version="7.0.10" />
<PackageReference Include="Polly" Version="8.5.2" />
<PackageReference Include="Npgsql" Version="9.0.3" />
<PackageReference Include="Polly" Version="8.6.0" />
<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.SQLite" Version="3.3.2.9" />
<PackageReference Include="System.Memory" Version="4.6.3" />
<PackageReference Include="System.ServiceModel.Syndication" Version="6.0.0" />
<PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" />
<PackageReference Include="FluentValidation" Version="9.5.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="System.Text.Json" Version="6.0.11" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
<PackageReference Include="MonoTorrent" Version="2.0.7" />
<PackageReference Include="YamlDotNet" Version="13.1.1" />
<PackageReference Include="AngleSharp" Version="1.2.0" />
<PackageReference Include="YamlDotNet" Version="16.3.0" />
<PackageReference Include="AngleSharp" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Common\Prowlarr.Common.csproj" />
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Host\Prowlarr.Host.csproj" />
+4 -4
View File
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="7.3.2" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="8.1.4" />
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
</ItemGroup>
+1 -1
View File
@@ -76,7 +76,7 @@ namespace NzbDrone.Host
case ApplicationModes.RegisterUrl:
{
_logger.Debug("Regiser URL selected");
_logger.Debug("Register URL selected");
_remoteAccessAdapter.MakeAccessible(false);
break;
@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.35" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.16" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mono.Posix.NETStandard" Version="5.20.1.34-servarr20" />
+1 -1
View File
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
@@ -112,7 +112,8 @@ namespace NzbDrone.Test.Common.AutoMoq
var mock = (Mock)r.Resolve(mockType);
SetMock(serviceType, mock);
return mock.Object;
}, Reuse.Singleton);
},
Reuse.Singleton);
return new[] { new DynamicRegistration(mockFactory, IfAlreadyRegistered.Keep) };
}
+1 -1
View File
@@ -55,7 +55,7 @@ namespace NzbDrone.Test.Common
if (BuildInfo.IsDebug)
{
var frameworkFolder = "net6.0";
var frameworkFolder = "net8.0";
Start(Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "..", "_output", frameworkFolder, consoleExe));
}
else
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="FluentValidation" Version="9.5.4" />
<PackageReference Include="Moq" Version="4.17.2" />
<PackageReference Include="NLog" Version="5.4.0" />
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
</Project>
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
+1 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NzbDrone.Common.Test\Prowlarr.Common.Test.csproj" />

Some files were not shown because too many files have changed in this diff Show More