mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2026-04-18 21:55:12 -04:00
Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 950949e4bc | |||
| fe198352a3 | |||
| 88502cd020 | |||
| 4924b45b56 | |||
| aea8b7cd7e | |||
| aafadb6111 | |||
| c82f904d49 | |||
| 60740fa259 | |||
| d36b32f414 | |||
| 14ccd6d2a5 | |||
| bdc3b63df2 | |||
| 8eec321a0e | |||
| 06de2313ab | |||
| a3f713bad8 | |||
| 7a1fca5e23 | |||
| 21c408a7da | |||
| 0e92108970 | |||
| 7d813ef97a | |||
| c87995250a | |||
| a9f7a376c7 | |||
| c3ee3f2320 | |||
| e8c26d0fea | |||
| 9c936121e8 | |||
| 40d2e40d94 | |||
| 837f50c91c | |||
| f0a0202e5c | |||
| 708c94bc56 | |||
| 5ed82eaf09 | |||
| 7d77ad68fd | |||
| 6725358db5 | |||
| c410e23460 | |||
| 903b86b9a2 | |||
| 52a49e6a34 | |||
| a7d99f351c | |||
| b0212dd780 | |||
| c8f5099423 | |||
| 5cc4c3f302 | |||
| c0d2cb42e9 | |||
| 8081f13052 | |||
| 84b672e617 | |||
| ed586c2d72 | |||
| 233176e321 | |||
| d1e3390bae | |||
| 1cd60c7a40 | |||
| c61cfcd312 | |||
| 5eb4d112ca | |||
| 70f2361d69 | |||
| 1d6babaa15 | |||
| 0427add8d0 | |||
| 010c2b836d | |||
| 22c4c1fc9a | |||
| d5f6cc94b8 | |||
| 411e96ef2a | |||
| 2b0e52ebca | |||
| c6fa26ca7b | |||
| c85f170d41 | |||
| 48a658571b | |||
| 0b3a5c9bc4 | |||
| 356d07ef34 | |||
| 0322d70d63 | |||
| 362f3fe223 | |||
| 075fd24f96 | |||
| 4ba72ea7f3 | |||
| 46f73c51bb | |||
| 3287d45661 | |||
| 71937fa44c | |||
| 6aefd46cd4 | |||
| c8370c9e00 | |||
| 6be4203b41 | |||
| 1339373e43 | |||
| fc9dfb0cf7 | |||
| 48301055ea | |||
| 8a9518c9c1 | |||
| de099c6770 | |||
| 07711da4e0 | |||
| 7cb70716d0 | |||
| 548dedad5c | |||
| 7008626358 | |||
| f6f2a3b00d | |||
| 2b16d93095 | |||
| e63ee13d23 | |||
| 5c5a163151 | |||
| 023eec0ec0 | |||
| 5bc5f0e6b8 | |||
| 5cbacc01eb | |||
| f4f1b38324 | |||
| 758dddd4ad | |||
| 73ee695633 | |||
| 27fbd7ef7e | |||
| 5125f256fb | |||
| b99e8d0d65 | |||
| d20b2cc9c0 | |||
| 8a1787bdb6 | |||
| a19b8ea997 | |||
| 10ea6cd753 | |||
| 2c1b464715 | |||
| 3263454041 |
@@ -2,11 +2,11 @@
|
|||||||
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
|
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
|
||||||
{
|
{
|
||||||
"name": "Prowlarr",
|
"name": "Prowlarr",
|
||||||
"image": "mcr.microsoft.com/devcontainers/dotnet:1-6.0",
|
"image": "mcr.microsoft.com/devcontainers/dotnet:1-8.0",
|
||||||
"features": {
|
"features": {
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
"nodeGypDependencies": true,
|
"nodeGypDependencies": true,
|
||||||
"version": "16",
|
"version": "20",
|
||||||
"nvmVersion": "latest"
|
"nvmVersion": "latest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Vendored
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build dotnet",
|
"preLaunchTask": "build dotnet",
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
// 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": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
|
|||||||
@@ -78,6 +78,6 @@ Thank you to [<img src="https://resources.jetbrains.com/storage/products/company
|
|||||||
### License
|
### License
|
||||||
|
|
||||||
- [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
- [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)
|
Icon Credit - [Box vector created by freepik - www.freepik.com](https://www.freepik.com/vectors/box)
|
||||||
|
|||||||
+53
-77
@@ -9,17 +9,17 @@ variables:
|
|||||||
testsFolder: './_tests'
|
testsFolder: './_tests'
|
||||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||||
majorVersion: '1.32.1'
|
majorVersion: '2.0.0'
|
||||||
minorVersion: $[counter('minorVersion', 1)]
|
minorVersion: $[counter('minorVersion', 1)]
|
||||||
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
||||||
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
||||||
sentryOrg: 'servarr'
|
sentryOrg: 'servarr'
|
||||||
sentryUrl: 'https://sentry.servarr.com'
|
sentryUrl: 'https://sentry.servarr.com'
|
||||||
dotnetVersion: '6.0.427'
|
dotnetVersion: '8.0.405'
|
||||||
nodeVersion: '20.X'
|
nodeVersion: '20.X'
|
||||||
innoVersion: '6.2.2'
|
innoVersion: '6.2.2'
|
||||||
windowsImage: 'windows-2022'
|
windowsImage: 'windows-2022'
|
||||||
linuxImage: 'ubuntu-20.04'
|
linuxImage: 'ubuntu-22.04'
|
||||||
macImage: 'macOS-13'
|
macImage: 'macOS-13'
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
@@ -106,7 +106,7 @@ stages:
|
|||||||
echo "Extra platforms already enabled"
|
echo "Extra platforms already enabled"
|
||||||
else
|
else
|
||||||
echo "Enabling extra platform support"
|
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
|
fi
|
||||||
displayName: Enable Extra Platform Support
|
displayName: Enable Extra Platform Support
|
||||||
- bash: ./build.sh --backend --enable-extra-platforms
|
- bash: ./build.sh --backend --enable-extra-platforms
|
||||||
@@ -122,27 +122,23 @@ stages:
|
|||||||
artifact: '$(osName)Backend'
|
artifact: '$(osName)Backend'
|
||||||
displayName: Publish Backend
|
displayName: Publish Backend
|
||||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
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
|
artifact: win-x64-tests
|
||||||
displayName: Publish win-x64 Test Package
|
displayName: Publish win-x64 Test Package
|
||||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
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
|
artifact: linux-x64-tests
|
||||||
displayName: Publish linux-x64 Test Package
|
displayName: Publish linux-x64 Test Package
|
||||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
||||||
- publish: '$(testsFolder)/net6.0/linux-x86/publish'
|
- publish: '$(testsFolder)/net8.0/linux-musl-x64/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'
|
|
||||||
artifact: linux-musl-x64-tests
|
artifact: linux-musl-x64-tests
|
||||||
displayName: Publish linux-musl-x64 Test Package
|
displayName: Publish linux-musl-x64 Test Package
|
||||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
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
|
artifact: freebsd-x64-tests
|
||||||
displayName: Publish freebsd-x64 Test Package
|
displayName: Publish freebsd-x64 Test Package
|
||||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
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
|
artifact: osx-x64-tests
|
||||||
displayName: Publish osx-x64 Test Package
|
displayName: Publish osx-x64 Test Package
|
||||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
||||||
@@ -189,7 +185,7 @@ stages:
|
|||||||
artifact: '$(osName)Frontend'
|
artifact: '$(osName)Frontend'
|
||||||
displayName: Publish Frontend
|
displayName: Publish Frontend
|
||||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
||||||
|
|
||||||
- stage: Installer
|
- stage: Installer
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- Build_Backend
|
- Build_Backend
|
||||||
@@ -259,21 +255,21 @@ stages:
|
|||||||
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).windows-core-x64.zip'
|
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).windows-core-x64.zip'
|
||||||
archiveType: 'zip'
|
archiveType: 'zip'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/win-x64/net6.0
|
rootFolderOrFile: $(artifactsFolder)/win-x64/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create win-x86 zip
|
displayName: Create win-x86 zip
|
||||||
inputs:
|
inputs:
|
||||||
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).windows-core-x86.zip'
|
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).windows-core-x86.zip'
|
||||||
archiveType: 'zip'
|
archiveType: 'zip'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/win-x86/net6.0
|
rootFolderOrFile: $(artifactsFolder)/win-x86/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create osx-x64 app
|
displayName: Create osx-x64 app
|
||||||
inputs:
|
inputs:
|
||||||
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).osx-app-core-x64.zip'
|
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).osx-app-core-x64.zip'
|
||||||
archiveType: 'zip'
|
archiveType: 'zip'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/osx-x64-app/net6.0
|
rootFolderOrFile: $(artifactsFolder)/osx-x64-app/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create osx-x64 tar
|
displayName: Create osx-x64 tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -281,14 +277,14 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/osx-x64/net6.0
|
rootFolderOrFile: $(artifactsFolder)/osx-x64/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create osx-arm64 app
|
displayName: Create osx-arm64 app
|
||||||
inputs:
|
inputs:
|
||||||
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).osx-app-core-arm64.zip'
|
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).osx-app-core-arm64.zip'
|
||||||
archiveType: 'zip'
|
archiveType: 'zip'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/osx-arm64-app/net6.0
|
rootFolderOrFile: $(artifactsFolder)/osx-arm64-app/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create osx-arm64 tar
|
displayName: Create osx-arm64 tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -296,7 +292,7 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/osx-arm64/net6.0
|
rootFolderOrFile: $(artifactsFolder)/osx-arm64/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create linux-x64 tar
|
displayName: Create linux-x64 tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -304,7 +300,7 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/linux-x64/net6.0
|
rootFolderOrFile: $(artifactsFolder)/linux-x64/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create linux-musl-x64 tar
|
displayName: Create linux-musl-x64 tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -312,15 +308,7 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/net6.0
|
rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/net8.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
|
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create linux-arm tar
|
displayName: Create linux-arm tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -328,7 +316,7 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/linux-arm/net6.0
|
rootFolderOrFile: $(artifactsFolder)/linux-arm/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create linux-musl-arm tar
|
displayName: Create linux-musl-arm tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -336,7 +324,7 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm/net6.0
|
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create linux-arm64 tar
|
displayName: Create linux-arm64 tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -344,7 +332,7 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/linux-arm64/net6.0
|
rootFolderOrFile: $(artifactsFolder)/linux-arm64/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create linux-musl-arm64 tar
|
displayName: Create linux-musl-arm64 tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -352,7 +340,7 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/net6.0
|
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/net8.0
|
||||||
- task: ArchiveFiles@2
|
- task: ArchiveFiles@2
|
||||||
displayName: Create freebsd-x64 tar
|
displayName: Create freebsd-x64 tar
|
||||||
inputs:
|
inputs:
|
||||||
@@ -360,7 +348,7 @@ stages:
|
|||||||
archiveType: 'tar'
|
archiveType: 'tar'
|
||||||
tarCompression: 'gz'
|
tarCompression: 'gz'
|
||||||
includeRootFolder: false
|
includeRootFolder: false
|
||||||
rootFolderOrFile: $(artifactsFolder)/freebsd-x64/net6.0
|
rootFolderOrFile: $(artifactsFolder)/freebsd-x64/net8.0
|
||||||
- publish: $(Build.ArtifactStagingDirectory)
|
- publish: $(Build.ArtifactStagingDirectory)
|
||||||
artifact: 'Packages'
|
artifact: 'Packages'
|
||||||
displayName: Publish Packages
|
displayName: Publish Packages
|
||||||
@@ -391,7 +379,7 @@ stages:
|
|||||||
SENTRY_AUTH_TOKEN: $(sentryAuthTokenServarr)
|
SENTRY_AUTH_TOKEN: $(sentryAuthTokenServarr)
|
||||||
SENTRY_ORG: $(sentryOrg)
|
SENTRY_ORG: $(sentryOrg)
|
||||||
SENTRY_URL: $(sentryUrl)
|
SENTRY_URL: $(sentryUrl)
|
||||||
|
|
||||||
- stage: Unit_Test
|
- stage: Unit_Test
|
||||||
displayName: Unit Tests
|
displayName: Unit Tests
|
||||||
dependsOn: Build_Backend
|
dependsOn: Build_Backend
|
||||||
@@ -476,6 +464,7 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: '$(testName) Unit Tests'
|
testRunTitle: '$(testName) Unit Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: ne(variables['testName'], 'freebsd-x64')
|
||||||
|
|
||||||
- job: Unit_Docker
|
- job: Unit_Docker
|
||||||
displayName: Unit Docker
|
displayName: Unit Docker
|
||||||
@@ -487,29 +476,19 @@ stages:
|
|||||||
testName: 'Musl Net Core'
|
testName: 'Musl Net Core'
|
||||||
artifactName: linux-musl-x64-tests
|
artifactName: linux-musl-x64-tests
|
||||||
containerImage: ghcr.io/servarr/testimages:alpine
|
containerImage: ghcr.io/servarr/testimages:alpine
|
||||||
linux-x86:
|
|
||||||
testName: 'linux-x86'
|
|
||||||
artifactName: linux-x86-tests
|
|
||||||
containerImage: ghcr.io/servarr/testimages:linux-x86
|
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: ${{ variables.linuxImage }}
|
vmImage: ${{ variables.linuxImage }}
|
||||||
|
|
||||||
container: $[ variables['containerImage'] ]
|
container: $[ variables['containerImage'] ]
|
||||||
|
|
||||||
timeoutInMinutes: 10
|
timeoutInMinutes: 10
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
displayName: 'Install .NET'
|
displayName: 'Install .NET'
|
||||||
inputs:
|
inputs:
|
||||||
version: $(dotnetVersion)
|
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
|
- checkout: none
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
displayName: Download Test Artifact
|
displayName: Download Test Artifact
|
||||||
@@ -532,7 +511,8 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: '$(testName) Unit Tests'
|
testRunTitle: '$(testName) Unit Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: true
|
||||||
|
|
||||||
- job: Unit_LinuxCore_Postgres14
|
- job: Unit_LinuxCore_Postgres14
|
||||||
displayName: Unit Native LinuxCore with Postgres14 Database
|
displayName: Unit Native LinuxCore with Postgres14 Database
|
||||||
dependsOn: Prepare
|
dependsOn: Prepare
|
||||||
@@ -549,7 +529,7 @@ stages:
|
|||||||
vmImage: ${{ variables.linuxImage }}
|
vmImage: ${{ variables.linuxImage }}
|
||||||
|
|
||||||
timeoutInMinutes: 10
|
timeoutInMinutes: 10
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
displayName: 'Install .net core'
|
displayName: 'Install .net core'
|
||||||
@@ -585,6 +565,7 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: 'LinuxCore Postgres14 Unit Tests'
|
testRunTitle: 'LinuxCore Postgres14 Unit Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: true
|
||||||
|
|
||||||
- job: Unit_LinuxCore_Postgres15
|
- job: Unit_LinuxCore_Postgres15
|
||||||
displayName: Unit Native LinuxCore with Postgres15 Database
|
displayName: Unit Native LinuxCore with Postgres15 Database
|
||||||
@@ -597,12 +578,12 @@ stages:
|
|||||||
Prowlarr__Postgres__Port: '5432'
|
Prowlarr__Postgres__Port: '5432'
|
||||||
Prowlarr__Postgres__User: 'prowlarr'
|
Prowlarr__Postgres__User: 'prowlarr'
|
||||||
Prowlarr__Postgres__Password: 'prowlarr'
|
Prowlarr__Postgres__Password: 'prowlarr'
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: ${{ variables.linuxImage }}
|
vmImage: ${{ variables.linuxImage }}
|
||||||
|
|
||||||
timeoutInMinutes: 10
|
timeoutInMinutes: 10
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
displayName: 'Install .net core'
|
displayName: 'Install .net core'
|
||||||
@@ -638,6 +619,7 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: 'LinuxCore Postgres15 Unit Tests'
|
testRunTitle: 'LinuxCore Postgres15 Unit Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: true
|
||||||
|
|
||||||
- stage: Integration
|
- stage: Integration
|
||||||
displayName: Integration
|
displayName: Integration
|
||||||
@@ -681,7 +663,7 @@ stages:
|
|||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: $(imageName)
|
vmImage: $(imageName)
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
displayName: 'Install .net core'
|
displayName: 'Install .net core'
|
||||||
@@ -703,7 +685,7 @@ stages:
|
|||||||
targetPath: $(Build.ArtifactStagingDirectory)
|
targetPath: $(Build.ArtifactStagingDirectory)
|
||||||
- task: ExtractFiles@1
|
- task: ExtractFiles@1
|
||||||
inputs:
|
inputs:
|
||||||
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
||||||
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
||||||
displayName: Extract Package
|
displayName: Extract Package
|
||||||
- bash: |
|
- bash: |
|
||||||
@@ -720,6 +702,7 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: '$(testName) Integration Tests'
|
testRunTitle: '$(testName) Integration Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: true
|
||||||
displayName: Publish Test Results
|
displayName: Publish Test Results
|
||||||
|
|
||||||
- job: Integration_LinuxCore_Postgres14
|
- job: Integration_LinuxCore_Postgres14
|
||||||
@@ -757,7 +740,7 @@ stages:
|
|||||||
targetPath: $(Build.ArtifactStagingDirectory)
|
targetPath: $(Build.ArtifactStagingDirectory)
|
||||||
- task: ExtractFiles@1
|
- task: ExtractFiles@1
|
||||||
inputs:
|
inputs:
|
||||||
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
||||||
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
||||||
displayName: Extract Package
|
displayName: Extract Package
|
||||||
- bash: |
|
- bash: |
|
||||||
@@ -782,6 +765,7 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: 'Integration LinuxCore Postgres14 Database Integration Tests'
|
testRunTitle: 'Integration LinuxCore Postgres14 Database Integration Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: true
|
||||||
displayName: Publish Test Results
|
displayName: Publish Test Results
|
||||||
|
|
||||||
|
|
||||||
@@ -820,7 +804,7 @@ stages:
|
|||||||
targetPath: $(Build.ArtifactStagingDirectory)
|
targetPath: $(Build.ArtifactStagingDirectory)
|
||||||
- task: ExtractFiles@1
|
- task: ExtractFiles@1
|
||||||
inputs:
|
inputs:
|
||||||
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
||||||
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
||||||
displayName: Extract Package
|
displayName: Extract Package
|
||||||
- bash: |
|
- bash: |
|
||||||
@@ -845,6 +829,7 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: 'Integration LinuxCore Postgres15 Database Integration Tests'
|
testRunTitle: 'Integration LinuxCore Postgres15 Database Integration Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: true
|
||||||
displayName: Publish Test Results
|
displayName: Publish Test Results
|
||||||
|
|
||||||
- job: Integration_FreeBSD
|
- job: Integration_FreeBSD
|
||||||
@@ -891,6 +876,7 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: 'FreeBSD Integration Tests'
|
testRunTitle: 'FreeBSD Integration Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: false
|
||||||
displayName: Publish Test Results
|
displayName: Publish Test Results
|
||||||
|
|
||||||
- job: Integration_Docker
|
- job: Integration_Docker
|
||||||
@@ -904,29 +890,18 @@ stages:
|
|||||||
artifactName: linux-musl-x64-tests
|
artifactName: linux-musl-x64-tests
|
||||||
containerImage: ghcr.io/servarr/testimages:alpine
|
containerImage: ghcr.io/servarr/testimages:alpine
|
||||||
pattern: 'Prowlarr.*.linux-musl-core-x64.tar.gz'
|
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:
|
pool:
|
||||||
vmImage: ${{ variables.linuxImage }}
|
vmImage: ${{ variables.linuxImage }}
|
||||||
|
|
||||||
container: $[ variables['containerImage'] ]
|
container: $[ variables['containerImage'] ]
|
||||||
|
|
||||||
timeoutInMinutes: 15
|
timeoutInMinutes: 15
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
displayName: 'Install .NET'
|
displayName: 'Install .NET'
|
||||||
inputs:
|
inputs:
|
||||||
version: $(dotnetVersion)
|
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
|
- checkout: none
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
displayName: Download Test Artifact
|
displayName: Download Test Artifact
|
||||||
@@ -943,7 +918,7 @@ stages:
|
|||||||
targetPath: $(Build.ArtifactStagingDirectory)
|
targetPath: $(Build.ArtifactStagingDirectory)
|
||||||
- task: ExtractFiles@1
|
- task: ExtractFiles@1
|
||||||
inputs:
|
inputs:
|
||||||
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
||||||
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
||||||
displayName: Extract Package
|
displayName: Extract Package
|
||||||
- bash: |
|
- bash: |
|
||||||
@@ -960,12 +935,13 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: '$(testName) Integration Tests'
|
testRunTitle: '$(testName) Integration Tests'
|
||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
|
failTaskOnMissingResultsFile: true
|
||||||
displayName: Publish Test Results
|
displayName: Publish Test Results
|
||||||
|
|
||||||
- stage: Automation
|
- stage: Automation
|
||||||
displayName: Automation
|
displayName: Automation
|
||||||
dependsOn: Packages
|
dependsOn: Packages
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
- job: Automation
|
- job: Automation
|
||||||
strategy:
|
strategy:
|
||||||
@@ -991,7 +967,7 @@ stages:
|
|||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: $(imageName)
|
vmImage: $(imageName)
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
displayName: 'Install .net core'
|
displayName: 'Install .net core'
|
||||||
@@ -1013,7 +989,7 @@ stages:
|
|||||||
targetPath: $(Build.ArtifactStagingDirectory)
|
targetPath: $(Build.ArtifactStagingDirectory)
|
||||||
- task: ExtractFiles@1
|
- task: ExtractFiles@1
|
||||||
inputs:
|
inputs:
|
||||||
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
||||||
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
||||||
displayName: Extract Package
|
displayName: Extract Package
|
||||||
- bash: |
|
- bash: |
|
||||||
@@ -1041,6 +1017,7 @@ stages:
|
|||||||
testResultsFiles: '**/TestResult.xml'
|
testResultsFiles: '**/TestResult.xml'
|
||||||
testRunTitle: '$(osName) Automation Tests'
|
testRunTitle: '$(osName) Automation Tests'
|
||||||
failTaskOnFailedTests: $(failBuild)
|
failTaskOnFailedTests: $(failBuild)
|
||||||
|
failTaskOnMissingResultsFile: $(failBuild)
|
||||||
displayName: Publish Test Results
|
displayName: Publish Test Results
|
||||||
|
|
||||||
- stage: Analyze
|
- stage: Analyze
|
||||||
@@ -1116,7 +1093,7 @@ stages:
|
|||||||
- checkout: self
|
- checkout: self
|
||||||
submodules: true
|
submodules: true
|
||||||
persistCredentials: true
|
persistCredentials: true
|
||||||
fetchDepth: 1
|
fetchDepth: 1
|
||||||
- bash: ./docs.sh Windows
|
- bash: ./docs.sh Windows
|
||||||
displayName: Create openapi.json
|
displayName: Create openapi.json
|
||||||
- bash: |
|
- bash: |
|
||||||
@@ -1184,13 +1161,13 @@ stages:
|
|||||||
sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml
|
sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml
|
||||||
sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml
|
sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml
|
||||||
- bash: |
|
- bash: |
|
||||||
./build.sh --backend -f net6.0 -r win-x64
|
./build.sh --backend -f net8.0 -r win-x64
|
||||||
TEST_DIR=_tests/net6.0/win-x64/publish/ ./test.sh Windows Unit Coverage
|
TEST_DIR=_tests/net8.0/win-x64/publish/ ./test.sh Windows Unit Coverage
|
||||||
displayName: Coverage Unit Tests
|
displayName: Coverage Unit Tests
|
||||||
- task: SonarCloudAnalyze@3
|
- task: SonarCloudAnalyze@3
|
||||||
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
condition: eq(variables['System.PullRequest.IsFork'], 'False')
|
||||||
displayName: Publish SonarCloud Results
|
displayName: Publish SonarCloud Results
|
||||||
- task: reportgenerator@5.3.11
|
- task: reportgenerator@5
|
||||||
displayName: Generate Coverage Report
|
displayName: Generate Coverage Report
|
||||||
inputs:
|
inputs:
|
||||||
reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml'
|
reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml'
|
||||||
@@ -1228,4 +1205,3 @@ stages:
|
|||||||
DISCORDCHANNELID: $(discordChannelId)
|
DISCORDCHANNELID: $(discordChannelId)
|
||||||
DISCORDWEBHOOKKEY: $(discordWebhookKey)
|
DISCORDWEBHOOKKEY: $(discordWebhookKey)
|
||||||
DISCORDTHREADID: $(discordThreadId)
|
DISCORDTHREADID: $(discordThreadId)
|
||||||
|
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ EnableExtraPlatformsInSDK()
|
|||||||
echo "Extra platforms already enabled"
|
echo "Extra platforms already enabled"
|
||||||
else
|
else
|
||||||
echo "Enabling extra platform support"
|
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
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
EnableExtraPlatforms()
|
EnableExtraPlatforms()
|
||||||
{
|
{
|
||||||
if grep -qv freebsd-x64 src/Directory.Build.props; then
|
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
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,9 +79,9 @@ Build()
|
|||||||
|
|
||||||
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
||||||
then
|
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
|
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
|
fi
|
||||||
|
|
||||||
ProgressEnd 'Build'
|
ProgressEnd 'Build'
|
||||||
@@ -137,7 +137,7 @@ PackageLinux()
|
|||||||
|
|
||||||
echo "Adding Prowlarr.Mono to UpdatePackage"
|
echo "Adding Prowlarr.Mono to UpdatePackage"
|
||||||
cp $folder/Prowlarr.Mono.* $folder/Prowlarr.Update
|
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/Mono.Posix.NETStandard.* $folder/Prowlarr.Update
|
||||||
cp $folder/libMonoPosixHelper.* $folder/Prowlarr.Update
|
cp $folder/libMonoPosixHelper.* $folder/Prowlarr.Update
|
||||||
fi
|
fi
|
||||||
@@ -165,7 +165,7 @@ PackageMacOS()
|
|||||||
|
|
||||||
echo "Adding Prowlarr.Mono to UpdatePackage"
|
echo "Adding Prowlarr.Mono to UpdatePackage"
|
||||||
cp $folder/Prowlarr.Mono.* $folder/Prowlarr.Update
|
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/Mono.Posix.NETStandard.* $folder/Prowlarr.Update
|
||||||
cp $folder/libMonoPosixHelper.* $folder/Prowlarr.Update
|
cp $folder/libMonoPosixHelper.* $folder/Prowlarr.Update
|
||||||
fi
|
fi
|
||||||
@@ -377,15 +377,14 @@ then
|
|||||||
Build
|
Build
|
||||||
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
||||||
then
|
then
|
||||||
PackageTests "net6.0" "win-x64"
|
PackageTests "net8.0" "win-x64"
|
||||||
PackageTests "net6.0" "win-x86"
|
PackageTests "net8.0" "win-x86"
|
||||||
PackageTests "net6.0" "linux-x64"
|
PackageTests "net8.0" "linux-x64"
|
||||||
PackageTests "net6.0" "linux-musl-x64"
|
PackageTests "net8.0" "linux-musl-x64"
|
||||||
PackageTests "net6.0" "osx-x64"
|
PackageTests "net8.0" "osx-x64"
|
||||||
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
|
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
|
||||||
then
|
then
|
||||||
PackageTests "net6.0" "freebsd-x64"
|
PackageTests "net8.0" "freebsd-x64"
|
||||||
PackageTests "net6.0" "linux-x86"
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
PackageTests "$FRAMEWORK" "$RID"
|
PackageTests "$FRAMEWORK" "$RID"
|
||||||
@@ -413,20 +412,19 @@ then
|
|||||||
|
|
||||||
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
|
||||||
then
|
then
|
||||||
Package "net6.0" "win-x64"
|
Package "net8.0" "win-x64"
|
||||||
Package "net6.0" "win-x86"
|
Package "net8.0" "win-x86"
|
||||||
Package "net6.0" "linux-x64"
|
Package "net8.0" "linux-x64"
|
||||||
Package "net6.0" "linux-musl-x64"
|
Package "net8.0" "linux-musl-x64"
|
||||||
Package "net6.0" "linux-arm64"
|
Package "net8.0" "linux-arm64"
|
||||||
Package "net6.0" "linux-musl-arm64"
|
Package "net8.0" "linux-musl-arm64"
|
||||||
Package "net6.0" "linux-arm"
|
Package "net8.0" "linux-arm"
|
||||||
Package "net6.0" "linux-musl-arm"
|
Package "net8.0" "linux-musl-arm"
|
||||||
Package "net6.0" "osx-x64"
|
Package "net8.0" "osx-x64"
|
||||||
Package "net6.0" "osx-arm64"
|
Package "net8.0" "osx-arm64"
|
||||||
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
|
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
|
||||||
then
|
then
|
||||||
Package "net6.0" "freebsd-x64"
|
Package "net8.0" "freebsd-x64"
|
||||||
Package "net6.0" "linux-x86"
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
Package "$FRAMEWORK" "$RID"
|
Package "$FRAMEWORK" "$RID"
|
||||||
@@ -436,7 +434,7 @@ fi
|
|||||||
if [ "$INSTALLER" = "YES" ];
|
if [ "$INSTALLER" = "YES" ];
|
||||||
then
|
then
|
||||||
InstallInno
|
InstallInno
|
||||||
BuildInstaller "net6.0" "win-x64"
|
BuildInstaller "net8.0" "win-x64"
|
||||||
BuildInstaller "net6.0" "win-x86"
|
BuildInstaller "net8.0" "win-x86"
|
||||||
RemoveInno
|
RemoveInno
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
FRAMEWORK="net6.0"
|
FRAMEWORK="net8.0"
|
||||||
PLATFORM=$1
|
PLATFORM=$1
|
||||||
ARCHITECTURE="${2:-x64}"
|
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 msbuild -restore $slnFile -p:Configuration=Debug -p:Platform=$platform -p:RuntimeIdentifiers=$RUNTIME -t:PublishAllRids
|
||||||
|
|
||||||
dotnet new tool-manifest
|
dotnet new tool-manifest
|
||||||
dotnet tool install --version 6.6.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 &
|
dotnet tool run swagger tofile --output ./src/Prowlarr.Api.V1/openapi.json "$outputFolder/$FRAMEWORK/$RUNTIME/$application" v1 &
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ module.exports = (env) => {
|
|||||||
loose: true,
|
loose: true,
|
||||||
debug: false,
|
debug: false,
|
||||||
useBuiltIns: 'entry',
|
useBuiltIns: 'entry',
|
||||||
corejs: '3.39'
|
corejs: '3.42'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
composes: link;
|
composes: link;
|
||||||
|
|
||||||
padding: 10px 24px;
|
padding: 10px 24px;
|
||||||
|
padding-left: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.isActiveLink {
|
.isActiveLink {
|
||||||
@@ -41,10 +42,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.noIcon {
|
|
||||||
margin-left: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status {
|
.status {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ interface CssExports {
|
|||||||
'isActiveParentLink': string;
|
'isActiveParentLink': string;
|
||||||
'item': string;
|
'item': string;
|
||||||
'link': string;
|
'link': string;
|
||||||
'noIcon': string;
|
|
||||||
'status': string;
|
'status': string;
|
||||||
}
|
}
|
||||||
export const cssExports: CssExports;
|
export const cssExports: CssExports;
|
||||||
|
|||||||
@@ -63,9 +63,7 @@ class PageSidebarItem extends Component {
|
|||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span className={isChildItem ? styles.noIcon : null}>
|
{typeof title === 'function' ? title() : title}
|
||||||
{typeof title === 'function' ? title() : title}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{
|
{
|
||||||
!!StatusComponent &&
|
!!StatusComponent &&
|
||||||
|
|||||||
@@ -22,11 +22,14 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
color: var(--toolbarLabelColor);
|
color: var(--toolbarLabelColor);
|
||||||
font-size: $extraSmallFontSize;
|
font-size: $extraSmallFontSize;
|
||||||
line-height: calc($extraSmallFontSize + 1px);
|
line-height: calc($extraSmallFontSize + 1px);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ function PageToolbarButton(props) {
|
|||||||
isDisabled && styles.isDisabled
|
isDisabled && styles.isDisabled
|
||||||
)}
|
)}
|
||||||
isDisabled={isDisabled || isSpinning}
|
isDisabled={isDisabled || isSpinning}
|
||||||
|
title={label}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
|
|||||||
@@ -65,17 +65,30 @@ class VirtualTable extends Component {
|
|||||||
|
|
||||||
if (this._grid && scrollTop !== undefined && scrollTop !== 0 && !scrollRestored) {
|
if (this._grid && scrollTop !== undefined && scrollTop !== 0 && !scrollRestored) {
|
||||||
this.setState({ scrollRestored: true });
|
this.setState({ scrollRestored: true });
|
||||||
this._grid.scrollToPosition({ scrollTop });
|
this._gridScrollToPosition({ scrollTop });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scrollIndex != null && scrollIndex !== prevProps.scrollIndex) {
|
if (scrollIndex != null && scrollIndex !== prevProps.scrollIndex) {
|
||||||
this._grid.scrollToCell({
|
this._gridScrollToCell({
|
||||||
rowIndex: scrollIndex,
|
rowIndex: scrollIndex,
|
||||||
columnIndex: 0
|
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
|
// Control
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function createMapStateToProps() {
|
|||||||
) => {
|
) => {
|
||||||
|
|
||||||
// If a release is deleted this selector may fire before the parent
|
// 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
|
// we want to return early here and again in the render function to avoid
|
||||||
// trying to show a release that has no information available.
|
// trying to show a release that has no information available.
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ export const authenticationMethodOptions = [
|
|||||||
key: 'basic',
|
key: 'basic',
|
||||||
get value() {
|
get value() {
|
||||||
return translate('AuthBasic');
|
return translate('AuthBasic');
|
||||||
}
|
},
|
||||||
|
isDisabled: true,
|
||||||
|
isHidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'forms',
|
key: 'forms',
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ export const reducers = createHandleActions({
|
|||||||
const items = newState.items;
|
const items = newState.items;
|
||||||
const index = items.findIndex((item) => item.guid === guid);
|
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) {
|
if (index >= 0) {
|
||||||
const item = Object.assign({}, items[index], payload);
|
const item = Object.assign({}, items[index], payload);
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { createSelector } from 'reselect';
|
|||||||
import { isCommandExecuting } from 'Utilities/Command';
|
import { isCommandExecuting } from 'Utilities/Command';
|
||||||
import createCommandSelector from './createCommandSelector';
|
import createCommandSelector from './createCommandSelector';
|
||||||
|
|
||||||
function createCommandExecutingSelector(name: string, contraints = {}) {
|
function createCommandExecutingSelector(name: string, constraints = {}) {
|
||||||
return createSelector(createCommandSelector(name, contraints), (command) => {
|
return createSelector(createCommandSelector(name, constraints), (command) => {
|
||||||
return isCommandExecuting(command);
|
return isCommandExecuting(command);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { createSelector } from 'reselect';
|
|||||||
import { findCommand } from 'Utilities/Command';
|
import { findCommand } from 'Utilities/Command';
|
||||||
import createCommandsSelector from './createCommandsSelector';
|
import createCommandsSelector from './createCommandsSelector';
|
||||||
|
|
||||||
function createCommandSelector(name: string, contraints = {}) {
|
function createCommandSelector(name: string, constraints = {}) {
|
||||||
return createSelector(createCommandsSelector(), (commands) => {
|
return createSelector(createCommandsSelector(), (commands) => {
|
||||||
return findCommand(commands, { name, ...contraints });
|
return findCommand(commands, { name, ...constraints });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "8.0.405"
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-16
@@ -23,17 +23,17 @@
|
|||||||
"defaults"
|
"defaults"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "6.7.1",
|
"@fortawesome/fontawesome-free": "6.7.2",
|
||||||
"@fortawesome/fontawesome-svg-core": "6.7.1",
|
"@fortawesome/fontawesome-svg-core": "6.7.2",
|
||||||
"@fortawesome/free-regular-svg-icons": "6.7.1",
|
"@fortawesome/free-regular-svg-icons": "6.7.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "6.7.1",
|
"@fortawesome/free-solid-svg-icons": "6.7.2",
|
||||||
"@fortawesome/react-fontawesome": "0.2.2",
|
"@fortawesome/react-fontawesome": "0.2.2",
|
||||||
"@juggle/resize-observer": "3.4.0",
|
"@juggle/resize-observer": "3.4.0",
|
||||||
"@microsoft/signalr": "6.0.25",
|
"@microsoft/signalr": "8.0.7",
|
||||||
"@sentry/browser": "7.119.1",
|
"@sentry/browser": "7.119.1",
|
||||||
"@sentry/integrations": "7.119.1",
|
"@sentry/integrations": "7.119.1",
|
||||||
"@types/node": "20.16.11",
|
"@types/node": "20.16.11",
|
||||||
"@types/react": "18.2.79",
|
"@types/react": "18.3.21",
|
||||||
"@types/react-dom": "18.2.25",
|
"@types/react-dom": "18.2.25",
|
||||||
"chart.js": "4.4.4",
|
"chart.js": "4.4.4",
|
||||||
"classnames": "2.5.1",
|
"classnames": "2.5.1",
|
||||||
@@ -71,9 +71,9 @@
|
|||||||
"react-router-dom": "5.2.0",
|
"react-router-dom": "5.2.0",
|
||||||
"react-tabs": "4.3.0",
|
"react-tabs": "4.3.0",
|
||||||
"react-text-truncate": "0.19.0",
|
"react-text-truncate": "0.19.0",
|
||||||
"react-use-measure": "2.1.1",
|
"react-use-measure": "2.1.7",
|
||||||
"react-virtualized": "9.21.1",
|
"react-virtualized": "9.22.6",
|
||||||
"react-window": "1.8.10",
|
"react-window": "1.8.11",
|
||||||
"redux": "4.2.1",
|
"redux": "4.2.1",
|
||||||
"redux-actions": "2.6.5",
|
"redux-actions": "2.6.5",
|
||||||
"redux-batched-actions": "0.5.0",
|
"redux-batched-actions": "0.5.0",
|
||||||
@@ -84,13 +84,13 @@
|
|||||||
"typescript": "5.7.2"
|
"typescript": "5.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.26.0",
|
"@babel/core": "7.27.1",
|
||||||
"@babel/eslint-parser": "7.25.9",
|
"@babel/eslint-parser": "7.27.1",
|
||||||
"@babel/plugin-proposal-export-default-from": "7.25.9",
|
"@babel/plugin-proposal-export-default-from": "7.27.1",
|
||||||
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||||
"@babel/preset-env": "7.26.0",
|
"@babel/preset-env": "7.27.2",
|
||||||
"@babel/preset-react": "7.26.3",
|
"@babel/preset-react": "7.27.1",
|
||||||
"@babel/preset-typescript": "7.26.0",
|
"@babel/preset-typescript": "7.27.1",
|
||||||
"@types/lodash": "4.14.195",
|
"@types/lodash": "4.14.195",
|
||||||
"@types/react-document-title": "2.0.10",
|
"@types/react-document-title": "2.0.10",
|
||||||
"@types/react-router-dom": "5.3.3",
|
"@types/react-router-dom": "5.3.3",
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
"babel-loader": "9.2.1",
|
"babel-loader": "9.2.1",
|
||||||
"babel-plugin-inline-classnames": "2.0.1",
|
"babel-plugin-inline-classnames": "2.0.1",
|
||||||
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
|
"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-loader": "6.7.3",
|
||||||
"css-modules-typescript-loader": "4.0.1",
|
"css-modules-typescript-loader": "4.0.1",
|
||||||
"eslint": "8.57.1",
|
"eslint": "8.57.1",
|
||||||
|
|||||||
@@ -99,13 +99,6 @@
|
|||||||
<RootNamespace Condition="'$(ProwlarrProject)'=='true'">$(MSBuildProjectName.Replace('Prowlarr','NzbDrone'))</RootNamespace>
|
<RootNamespace Condition="'$(ProwlarrProject)'=='true'">$(MSBuildProjectName.Replace('Prowlarr','NzbDrone'))</RootNamespace>
|
||||||
</PropertyGroup>
|
</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 -->
|
<!-- Sentry specific configuration: Only in Release mode -->
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||||
<!-- https://docs.sentry.io/platforms/dotnet/configuration/msbuild/ -->
|
<!-- https://docs.sentry.io/platforms/dotnet/configuration/msbuild/ -->
|
||||||
@@ -136,7 +129,7 @@
|
|||||||
<PackageReference Include="NunitXml.TestLogger" Version="3.0.131" />
|
<PackageReference Include="NunitXml.TestLogger" Version="3.0.131" />
|
||||||
</ItemGroup>
|
</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" />
|
<PackageReference Include="coverlet.collector" Version="3.0.4-preview.27.ge7cb7c3b40" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -148,9 +141,9 @@
|
|||||||
<!-- Set up stylecop -->
|
<!-- Set up stylecop -->
|
||||||
<ItemGroup Condition="'$(ProwlarrProject)'=='true' and '$(EnableAnalyzers)'!='false'">
|
<ItemGroup Condition="'$(ProwlarrProject)'=='true' and '$(EnableAnalyzers)'!='false'">
|
||||||
<!-- StyleCop analysis -->
|
<!-- StyleCop analysis -->
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.556">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<AdditionalFiles Include="$(SolutionDir)stylecop.json" />
|
<AdditionalFiles Include="$(SolutionDir)stylecop.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -39,15 +39,16 @@ namespace NzbDrone.Automation.Test
|
|||||||
var service = ChromeDriverService.CreateDefaultService();
|
var service = ChromeDriverService.CreateDefaultService();
|
||||||
|
|
||||||
// Timeout as windows automation tests seem to take alot longer to get going
|
// 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.Size = new System.Drawing.Size(1920, 1080);
|
||||||
|
driver.Manage().Window.FullScreen();
|
||||||
|
|
||||||
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), null);
|
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), null);
|
||||||
_runner.KillAll();
|
_runner.KillAll();
|
||||||
_runner.Start(true);
|
_runner.Start(true);
|
||||||
|
|
||||||
driver.Url = "http://localhost:9696";
|
driver.Navigate().GoToUrl("http://localhost:9696");
|
||||||
|
|
||||||
var page = new PageBase(driver);
|
var page = new PageBase(driver);
|
||||||
page.WaitForNoSpinner();
|
page.WaitForNoSpinner();
|
||||||
@@ -67,7 +68,7 @@ namespace NzbDrone.Automation.Test
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var image = ((ITakesScreenshot)driver).GetScreenshot();
|
var image = (driver as ITakesScreenshot).GetScreenshot();
|
||||||
image.SaveAsFile($"./{name}_test_screenshot.png", ScreenshotImageFormat.Png);
|
image.SaveAsFile($"./{name}_test_screenshot.png", ScreenshotImageFormat.Png);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -7,12 +7,11 @@ namespace NzbDrone.Automation.Test.PageModel
|
|||||||
{
|
{
|
||||||
public class PageBase
|
public class PageBase
|
||||||
{
|
{
|
||||||
private readonly WebDriver _driver;
|
private readonly IWebDriver _driver;
|
||||||
|
|
||||||
public PageBase(WebDriver driver)
|
public PageBase(IWebDriver driver)
|
||||||
{
|
{
|
||||||
_driver = driver;
|
_driver = driver;
|
||||||
driver.Manage().Window.Maximize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IWebElement FindByClass(string className, int timeout = 5)
|
public IWebElement FindByClass(string className, int timeout = 5)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Selenium.Support" Version="4.1.0" />
|
<PackageReference Include="Selenium.Support" Version="4.1.0" />
|
||||||
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="99.0.4844.5100" />
|
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="134.0.6998.16500" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
|
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ namespace NzbDrone.Common.Test.EnvironmentInfo
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_return_version()
|
public void should_return_version()
|
||||||
{
|
{
|
||||||
BuildInfo.Version.Major.Should().BeOneOf(0, 1, 10);
|
BuildInfo.Version.Major.Should().BeOneOf(0, 2, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_get_branch()
|
public void should_get_branch()
|
||||||
{
|
{
|
||||||
BuildInfo.Branch.Should().NotBe("unknow");
|
BuildInfo.Branch.Should().NotBe("unknown");
|
||||||
BuildInfo.Branch.Should().NotBeNullOrWhiteSpace();
|
BuildInfo.Branch.Should().NotBeNullOrWhiteSpace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace NzbDrone.Common.Test.Http
|
|||||||
private string _httpBinHost;
|
private string _httpBinHost;
|
||||||
private string _httpBinHost2;
|
private string _httpBinHost2;
|
||||||
|
|
||||||
private System.Net.Http.HttpClient _httpClient = new ();
|
private System.Net.Http.HttpClient _httpClient = new();
|
||||||
|
|
||||||
[OneTimeSetUp]
|
[OneTimeSetUp]
|
||||||
public void FixtureSetUp()
|
public void FixtureSetUp()
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ namespace NzbDrone.Common.Test.Http
|
|||||||
[TestCase("Readarr/1.0.0.2300 (ubuntu 20.04)", "Readarr")]
|
[TestCase("Readarr/1.0.0.2300 (ubuntu 20.04)", "Readarr")]
|
||||||
[TestCase("Sonarr/3.0.6.9999 (ubuntu 20.04)", "Sonarr")]
|
[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("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)
|
public void should_parse_user_agent(string userAgent, string parsedAgent)
|
||||||
{
|
{
|
||||||
UserAgentParser.ParseSource(userAgent).Should().Be(parsedAgent);
|
UserAgentParser.ParseSource(userAgent).Should().Be(parsedAgent);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\NzbDrone.Host\Prowlarr.Host.csproj" />
|
<ProjectReference Include="..\NzbDrone.Host\Prowlarr.Host.csproj" />
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace NzbDrone.Common.Disk
|
namespace NzbDrone.Common.Disk
|
||||||
{
|
{
|
||||||
@@ -24,10 +23,5 @@ namespace NzbDrone.Common.Disk
|
|||||||
: base(message, innerException)
|
: base(message, innerException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DestinationAlreadyExistsException(SerializationInfo info, StreamingContext context)
|
|
||||||
: base(info, context)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ namespace NzbDrone.Common.Disk
|
|||||||
return _path.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
|
return _path.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OsPath Null => new (null);
|
public static OsPath Null => new(null);
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,6 +75,17 @@ namespace NzbDrone.Common.EnvironmentInfo
|
|||||||
{
|
{
|
||||||
try
|
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");
|
var oldDbFile = Path.Combine(_appFolderInfo.AppDataFolder, "nzbdrone.db");
|
||||||
|
|
||||||
if (_startupContext.Args.ContainsKey(StartupContext.APPDATA))
|
if (_startupContext.Args.ContainsKey(StartupContext.APPDATA))
|
||||||
@@ -115,7 +126,7 @@ namespace NzbDrone.Common.EnvironmentInfo
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Debug(ex, ex.Message);
|
_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);
|
var attributes = assembly.GetCustomAttributes(true);
|
||||||
|
|
||||||
Branch = "unknow";
|
Branch = "unknown";
|
||||||
|
|
||||||
var config = attributes.OfType<AssemblyConfigurationAttribute>().FirstOrDefault();
|
var config = attributes.OfType<AssemblyConfigurationAttribute>().FirstOrDefault();
|
||||||
if (config != null)
|
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,
|
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);
|
return dictionary.Select(selection).ToDictionary(t => t.Item1, t => t.Item2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace NzbDrone.Common.Http
|
|||||||
{
|
{
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
||||||
// NOTE: we are not checking non-ascii characters and we should
|
// NOTE: we are not checking non-ascii characters and we should
|
||||||
private static readonly Regex CookieRegex = new (@"([^\(\)<>@,;:\\""/\[\]\?=\{\}\s]+)=([^,;\\""\s]+)");
|
private static readonly Regex CookieRegex = new(@"([^\(\)<>@,;:\\""/\[\]\?=\{\}\s]+)=([^,;\\""\s]+)");
|
||||||
private static readonly string[] FilterProps = { "COMMENT", "COMMENTURL", "DISCORD", "DOMAIN", "EXPIRES", "MAX-AGE", "PATH", "PORT", "SECURE", "VERSION", "HTTPONLY", "SAMESITE" };
|
private static readonly string[] FilterProps = { "COMMENT", "COMMENTURL", "DISCORD", "DOMAIN", "EXPIRES", "MAX-AGE", "PATH", "PORT", "SECURE", "VERSION", "HTTPONLY", "SAMESITE" };
|
||||||
private static readonly char[] InvalidKeyChars = { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t', '\n' };
|
private static readonly char[] InvalidKeyChars = { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t', '\n' };
|
||||||
private static readonly char[] InvalidValueChars = { '"', ',', ';', '\\', ' ', '\t', '\n' };
|
private static readonly char[] InvalidValueChars = { '"', ',', ';', '\\', ' ', '\t', '\n' };
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ namespace NzbDrone.Common.Http.Dispatchers
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException ex) when (cts.IsCancellationRequested)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ namespace NzbDrone.Common.Http
|
|||||||
// Save to add to final response
|
// Save to add to final response
|
||||||
var responseCookies = response.Cookies;
|
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);
|
var responseContainer = HandleRedirectCookies(request, response);
|
||||||
|
|
||||||
response = await ExecuteRequestAsync(request, responseContainer);
|
response = await ExecuteRequestAsync(request, responseContainer);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace NzbDrone.Common.Http
|
|||||||
{
|
{
|
||||||
public class HttpResponse
|
public class HttpResponse
|
||||||
{
|
{
|
||||||
private static readonly Regex RegexRefresh = new ("^(.*?url)=(.*?)(?:;|$)", RegexOptions.Compiled);
|
private static readonly Regex RegexRefresh = new("^(.*?url)=(.*?)(?:;|$)", RegexOptions.Compiled);
|
||||||
|
|
||||||
public HttpResponse(HttpRequest request, HttpHeader headers, CookieCollection cookies, byte[] binaryData, long elapsedTime = 0, HttpStatusCode statusCode = HttpStatusCode.OK, Version version = null)
|
public HttpResponse(HttpRequest request, HttpHeader headers, CookieCollection cookies, byte[] binaryData, long elapsedTime = 0, HttpStatusCode statusCode = HttpStatusCode.OK, Version version = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
|
using System;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Http
|
namespace NzbDrone.Common.Http
|
||||||
{
|
{
|
||||||
public static class UserAgentParser
|
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);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
public static string SimplifyUserAgent(string userAgent)
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -19,14 +20,9 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
public static string ParseSource(string userAgent)
|
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"].Success ? match.Groups["agent"].Value : "Other";
|
||||||
{
|
|
||||||
return match.Groups["agent"].Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Other";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,64 +10,64 @@ namespace NzbDrone.Common.Instrumentation
|
|||||||
private static readonly Regex[] CleansingRules =
|
private static readonly Regex[] CleansingRules =
|
||||||
{
|
{
|
||||||
// Url
|
// Url
|
||||||
new (@"(?<=[?&: ;])(apikey|api_key|(?:(?:access|api)[-_]?)?token|pass(?:key|wd)?|auth|authkey|rsskey|user|u?id|api|[a-z_]*apikey|account|pid|pwd)=(?<secret>[^&=""]+?)(?=[ ""&=]|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?<=[?&: ;])(apikey|api_key|(?:(?:access|api)[-_]?)?token|pass(?:key|wd)?|auth|authkey|rsskey|user|u?id|api|[a-z_]*apikey|account|pid|pwd)=(?<secret>[^&=""]+?)(?=[ ""&=]|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"(?<=[?& ;])[^=]*?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?<=[?& ;])[^=]*?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"rss(24h)?\.torrentleech\.org/(?!rss)(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"rss(24h)?\.torrentleech\.org/(?!rss)(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"torrentleech\.org/rss/download/[0-9]+/(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"torrentleech\.org/rss/download/[0-9]+/(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
|
new(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
|
||||||
new (@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"getnzb.*?(?<=\?|&)(r)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"\b(\w*)?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"\b(\w*)?(_?(?<!use|get_)token|username|passwo?rd)=(?<secret>[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"(?<=authkey = "")(?<secret>[^&=]+?)(?="")", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?<=authkey = "")(?<secret>[^&=]+?)(?="")", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"(?<=beyond-hd\.[a-z]+/api/torrents/)(?<secret>[^&=][a-z0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?<=beyond-hd\.[a-z]+/api/torrents/)(?<secret>[^&=][a-z0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"(?<=beyond-hd\.[a-z]+/torrent/download/[\w\d-]+[.]\d+[.])(?<secret>[a-z0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?<=beyond-hd\.[a-z]+/torrent/download/[\w\d-]+[.]\d+[.])(?<secret>[a-z0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"(?:sharewood)\.[a-z]{2,3}/api/(?<secret>[a-z0-9]{16,})/", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?:sharewood)\.[a-z]{2,3}/api/(?<secret>[a-z0-9]{16,})/", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// UNIT3D
|
// UNIT3D
|
||||||
new (@"(?<=[a-z0-9-]+\.[a-z]+/torrent/download/\d+\.)(?<secret>[^&=][a-z0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?<=[a-z0-9-]+\.[a-z]+/torrent/download/\d+\.)(?<secret>[^&=][a-z0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Path
|
// Path
|
||||||
new (@"""C:\\Users\\(?<secret>[^\""]+?)(\\|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"""C:\\Users\\(?<secret>[^\""]+?)(\\|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"""/(home|Users)/(?<secret>[^/""]+?)(/|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"""/(home|Users)/(?<secret>[^/""]+?)(/|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Trackers Announce Keys; Designed for Qbit Json; should work for all in theory
|
// Trackers Announce Keys; Designed for Qbit Json; should work for all in theory
|
||||||
new (@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?<secret>[a-z0-9]{16,})|(?<secret>[a-z0-9]{16,})(/|%2f)announce", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?<secret>[a-z0-9]{16,})|(?<secret>[a-z0-9]{16,})(/|%2f)announce", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// NzbGet
|
// NzbGet
|
||||||
new (@"""Name""\s*:\s*""[^""]*(username|password)""\s*,\s*""Value""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"""Name""\s*:\s*""[^""]*(username|password)""\s*,\s*""Value""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Sabnzbd
|
// Sabnzbd
|
||||||
new (@"""[^""]*(username|password|api_?key|nzb_key)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"""[^""]*(username|password|api_?key|nzb_key)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"""email_(account|to|from|pwd)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"""email_(account|to|from|pwd)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// uTorrent
|
// uTorrent
|
||||||
new (@"\[""[a-z._]*(username|password)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"\[""[a-z._]*(username|password)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"\[""(boss_key|boss_key_salt|proxy\.proxy)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"\[""(boss_key|boss_key_salt|proxy\.proxy)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Deluge
|
// Deluge
|
||||||
new (@"auth.login\(""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"auth.login\(""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// BroadcastheNet (;torrent_pass|torrents_notify_ is for MTV)
|
// BroadcastheNet (;torrent_pass|torrents_notify_ is for MTV)
|
||||||
new (@"""?method""?\s*:\s*""(getTorrents)"",\s*""?params""?\s*:\s*\[\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"""?method""?\s*:\s*""(getTorrents)"",\s*""?params""?\s*:\s*\[\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"getTorrents\(""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"getTorrents\(""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"(?<=\?|&|;|=)(authkey|torrent_pass|torrents_notify)[_=](?<secret>[^&=]+?)(?=""|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?<=\?|&|;|=)(authkey|torrent_pass|torrents_notify)[_=](?<secret>[^&=]+?)(?=""|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Plex
|
// Plex
|
||||||
new (@"(?<=\?|&)(X-Plex-Client-Identifier|X-Plex-Token)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?<=\?|&)(X-Plex-Client-Identifier|X-Plex-Token)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Indexer Responses
|
// Indexer Responses
|
||||||
new (@"(?:avistaz|exoticaz|cinemaz|privatehd)\.[a-z]{2,3}/rss/download/(?<secret>[^&=]+?)/(?<secret>[^&=]+?)\.torrent", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?:avistaz|exoticaz|cinemaz|privatehd)\.[a-z]{2,3}/rss/download/(?<secret>[^&=]+?)/(?<secret>[^&=]+?)\.torrent", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"(?:animebytes)\.[a-z]{2,3}/torrent/[0-9]+/download/(?<secret>[^&=]+?)[""]", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"(?:animebytes)\.[a-z]{2,3}/torrent/[0-9]+/download/(?<secret>[^&=]+?)[""]", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
new (@"""(info_hash|token|((pass|rss)[- _]?key))"":""(?<secret>[^&=]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"""(info_hash|token|((pass|rss)[- _]?key))"":""(?<secret>[^&=]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Applications
|
// Applications
|
||||||
new (@"""name"":""apikey"",""value"":""(?<secret>[^&=]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new(@"""name"":""apikey"",""value"":""(?<secret>[^&=]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Discord
|
// Discord
|
||||||
new (@"discord.com/api/webhooks/((?<secret>[\w-]+)/)?(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase)
|
new(@"discord.com/api/webhooks/((?<secret>[\w-]+)/)?(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Regex CleanseRemoteIPRegex = new (@"(?:Auth-\w+(?<!Failure|Unauthorized) ip|from) (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", RegexOptions.Compiled);
|
private static readonly Regex CleanseRemoteIPRegex = new(@"(?:Auth-\w+(?<!Failure|Unauthorized) ip|from) (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", RegexOptions.Compiled);
|
||||||
|
|
||||||
public static string Cleanse(string message)
|
public static string Cleanse(string message)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,27 +4,27 @@ namespace NzbDrone.Common.Instrumentation.Extensions
|
|||||||
{
|
{
|
||||||
public static class LoggerExtensions
|
public static class LoggerExtensions
|
||||||
{
|
{
|
||||||
|
[MessageTemplateFormatMethod("message")]
|
||||||
public static void ProgressInfo(this Logger logger, string message, params object[] args)
|
public static void ProgressInfo(this Logger logger, string message, params object[] args)
|
||||||
{
|
{
|
||||||
var formattedMessage = string.Format(message, args);
|
LogProgressMessage(logger, LogLevel.Info, message, args);
|
||||||
LogProgressMessage(logger, LogLevel.Info, formattedMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MessageTemplateFormatMethod("message")]
|
||||||
public static void ProgressDebug(this Logger logger, string message, params object[] args)
|
public static void ProgressDebug(this Logger logger, string message, params object[] args)
|
||||||
{
|
{
|
||||||
var formattedMessage = string.Format(message, args);
|
LogProgressMessage(logger, LogLevel.Debug, message, args);
|
||||||
LogProgressMessage(logger, LogLevel.Debug, formattedMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MessageTemplateFormatMethod("message")]
|
||||||
public static void ProgressTrace(this Logger logger, string message, params object[] args)
|
public static void ProgressTrace(this Logger logger, string message, params object[] args)
|
||||||
{
|
{
|
||||||
var formattedMessage = string.Format(message, args);
|
LogProgressMessage(logger, LogLevel.Trace, message, args);
|
||||||
LogProgressMessage(logger, LogLevel.Trace, formattedMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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", "");
|
logEvent.Properties.Add("Status", "");
|
||||||
|
|
||||||
logger.Log(logEvent);
|
logger.Log(logEvent);
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ namespace NzbDrone.Common.Instrumentation
|
|||||||
private const string FileLogLayout = @"${date:format=yyyy-MM-dd HH\:mm\:ss.f}|${level}|${logger}|${message}${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}${exception:format=Data}${newline}}";
|
private const string FileLogLayout = @"${date:format=yyyy-MM-dd HH\:mm\:ss.f}|${level}|${logger}|${message}${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}${exception:format=Data}${newline}}";
|
||||||
private const string ConsoleFormat = "[${level}] ${logger}: ${message} ${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}${exception:format=Data}${newline}}";
|
private const string ConsoleFormat = "[${level}] ${logger}: ${message} ${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}${exception:format=Data}${newline}}";
|
||||||
|
|
||||||
private static readonly CleansingConsoleLogLayout CleansingConsoleLayout = new (ConsoleFormat);
|
private static readonly CleansingConsoleLogLayout CleansingConsoleLayout = new(ConsoleFormat);
|
||||||
private static readonly CleansingClefLogLayout ClefLogLayout = new ();
|
private static readonly CleansingClefLogLayout ClefLogLayout = new();
|
||||||
|
|
||||||
private static bool _isConfigured;
|
private static bool _isConfigured;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.ComponentModel;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Model;
|
using NzbDrone.Common.Model;
|
||||||
@@ -117,7 +118,9 @@ namespace NzbDrone.Common.Processes
|
|||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardInput = true
|
RedirectStandardInput = true,
|
||||||
|
StandardOutputEncoding = Encoding.UTF8,
|
||||||
|
StandardErrorEncoding = Encoding.UTF8
|
||||||
};
|
};
|
||||||
|
|
||||||
if (environmentVariables != null)
|
if (environmentVariables != null)
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
<DefineConstants Condition="'$(RuntimeIdentifier)' == 'linux-musl-x64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64'">ISMUSL</DefineConstants>
|
<DefineConstants Condition="'$(RuntimeIdentifier)' == 'linux-musl-x64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64'">ISMUSL</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
||||||
<PackageReference Include="IPAddressRange" Version="6.1.0" />
|
<PackageReference Include="IPAddressRange" Version="6.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="NLog" Version="5.3.4" />
|
<PackageReference Include="NLog" Version="5.4.0" />
|
||||||
<PackageReference Include="NLog.Layouts.ClefJsonLayout" Version="1.0.0" />
|
<PackageReference Include="NLog.Layouts.ClefJsonLayout" Version="1.0.3" />
|
||||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.15" />
|
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
|
||||||
<PackageReference Include="Npgsql" Version="7.0.9" />
|
<PackageReference Include="Npgsql" Version="9.0.3" />
|
||||||
<PackageReference Include="Sentry" Version="4.0.2" />
|
<PackageReference Include="Sentry" Version="4.0.2" />
|
||||||
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageReference Include="System.Text.Json" Version="6.0.10" />
|
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
<PackageReference Include="System.ValueTuple" Version="4.6.1" />
|
||||||
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.1" />
|
||||||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
|
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
|
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
|
||||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="6.0.1" />
|
<PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="EnsureThat\Resources\ExceptionMessages.Designer.cs">
|
<Compile Update="EnsureThat\Resources\ExceptionMessages.Designer.cs">
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ namespace NzbDrone.Common.TPL
|
|||||||
{
|
{
|
||||||
_currentThreadIsProcessingItems = false;
|
_currentThreadIsProcessingItems = false;
|
||||||
}
|
}
|
||||||
}, null);
|
},
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Attempts to execute the specified task on the current thread.</summary>
|
/// <summary>Attempts to execute the specified task on the current thread.</summary>
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ namespace NzbDrone.Common.TPL
|
|||||||
Logger.Error(exception, "Task Error");
|
Logger.Error(exception, "Task Error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, TaskContinuationOptions.OnlyOnFaulted);
|
},
|
||||||
|
TaskContinuationOptions.OnlyOnFaulted);
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
|
|
||||||
<ApplicationIcon>..\NzbDrone.Host\Prowlarr.ico</ApplicationIcon>
|
<ApplicationIcon>..\NzbDrone.Host\Prowlarr.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,15 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<caps>
|
<caps>
|
||||||
<server version="1.0" title="Anime Tosho" strapline="Anime NZB/DDL mirror" url="https://animetosho.org/"/>
|
<server version="1.0" title="Anime Tosho" strapline="Anime NZB/DDL mirror" url="https://animetosho.org/" />
|
||||||
<limits max="200" default="75"/>
|
<limits max="200" default="75" />
|
||||||
<retention days="9999"/>
|
<retention days="9999" />
|
||||||
<registration available="no" open="yes" />
|
<registration available="no" open="yes" />
|
||||||
<searching>
|
<searching>
|
||||||
<search available="yes" supportedParams="q" />
|
<search available="yes" supportedParams="q" />
|
||||||
<tv-search available="no" supportedParams="q" />
|
<tv-search available="no" supportedParams="q" />
|
||||||
<movie-search available="no" supportedParams="q" />
|
<movie-search available="no" supportedParams="q" />
|
||||||
</searching>
|
</searching>
|
||||||
<categories>
|
<categories>
|
||||||
<category id="5070" name="Anime" description="Anime"/>
|
<category id="5070" name="Anime" description="Anime" />
|
||||||
</categories>
|
<category id="2020" name="Movies/Other" description="Movies (Anime)" />
|
||||||
</caps>
|
</categories>
|
||||||
|
</caps>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.IndexerTests.AvistazTests
|
|||||||
torrentInfo.InfoUrl.Should().Be("https://avistaz.to/torrent/187240-japan-sinks-people-of-hope-2021-s01e05-720p-nf-web-dl-ddp20-x264-seikel");
|
torrentInfo.InfoUrl.Should().Be("https://avistaz.to/torrent/187240-japan-sinks-people-of-hope-2021-s01e05-720p-nf-web-dl-ddp20-x264-seikel");
|
||||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2021-11-14 22:26:21"));
|
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2021-11-14 21:26:21"));
|
||||||
torrentInfo.Size.Should().Be(935127615);
|
torrentInfo.Size.Should().Be(935127615);
|
||||||
torrentInfo.InfoHash.Should().Be("a879261d4e6e792402f92401141a21de70d51bf2");
|
torrentInfo.InfoHash.Should().Be("a879261d4e6e792402f92401141a21de70d51bf2");
|
||||||
torrentInfo.MagnetUrl.Should().Be(null);
|
torrentInfo.MagnetUrl.Should().Be(null);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.IndexerTests.AvistazTests
|
|||||||
torrentInfo.InfoUrl.Should().Be("https://exoticaz.to/torrent/64040-ssis-419-my-first-experience-is-yua-mikami-from-the-day-i-lost-my-virginity-i-was-devoted-to-sex");
|
torrentInfo.InfoUrl.Should().Be("https://exoticaz.to/torrent/64040-ssis-419-my-first-experience-is-yua-mikami-from-the-day-i-lost-my-virginity-i-was-devoted-to-sex");
|
||||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2022-06-11 10:04:50"));
|
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2022-06-11 09:04:50"));
|
||||||
torrentInfo.Size.Should().Be(7085405541);
|
torrentInfo.Size.Should().Be(7085405541);
|
||||||
torrentInfo.InfoHash.Should().Be("asdjfiasdf54asd7f4a2sdf544asdf");
|
torrentInfo.InfoHash.Should().Be("asdjfiasdf54asd7f4a2sdf544asdf");
|
||||||
torrentInfo.MagnetUrl.Should().Be(null);
|
torrentInfo.MagnetUrl.Should().Be(null);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace NzbDrone.Core.Test.IndexerTests.AvistazTests
|
|||||||
torrentInfo.InfoUrl.Should().Be("https://privatehd.to/torrent/78506-godzilla-2014-2160p-uhd-bluray-remux-hdr-hevc-atmos-triton");
|
torrentInfo.InfoUrl.Should().Be("https://privatehd.to/torrent/78506-godzilla-2014-2160p-uhd-bluray-remux-hdr-hevc-atmos-triton");
|
||||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2021-03-21 05:24:49"));
|
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2021-03-21 04:24:49"));
|
||||||
torrentInfo.Size.Should().Be(69914591044);
|
torrentInfo.Size.Should().Be(69914591044);
|
||||||
torrentInfo.InfoHash.Should().Be("a879261d4e6e792402f92401141a21de70d51bf2");
|
torrentInfo.InfoHash.Should().Be("a879261d4e6e792402f92401141a21de70d51bf2");
|
||||||
torrentInfo.MagnetUrl.Should().Be(null);
|
torrentInfo.MagnetUrl.Should().Be(null);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace NzbDrone.Core.Test.IndexerTests.FileListTests
|
|||||||
torrentInfo.InfoUrl.Should().Be("https://filelist.io/details.php?id=665873");
|
torrentInfo.InfoUrl.Should().Be("https://filelist.io/details.php?id=665873");
|
||||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2020-01-25 20:20:19"));
|
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2020-01-25 19:20:19"));
|
||||||
torrentInfo.Size.Should().Be(8300512414);
|
torrentInfo.Size.Should().Be(8300512414);
|
||||||
torrentInfo.InfoHash.Should().Be(null);
|
torrentInfo.InfoHash.Should().Be(null);
|
||||||
torrentInfo.MagnetUrl.Should().Be(null);
|
torrentInfo.MagnetUrl.Should().Be(null);
|
||||||
|
|||||||
+6
-5
@@ -83,17 +83,18 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
|||||||
bookCats.Should().Contain("8000");
|
bookCats.Should().Contain("8000");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCase(5070)]
|
||||||
public void should_find_sub_categories_as_main_categories()
|
[TestCase(2020)]
|
||||||
|
public void should_find_sub_categories_as_main_categories(int category)
|
||||||
{
|
{
|
||||||
GivenCapsResponse(ReadAllText("Files/Indexers/Torznab/torznab_animetosho_caps.xml"));
|
GivenCapsResponse(ReadAllText("Files/Indexers/Torznab/torznab_animetosho_caps.xml"));
|
||||||
|
|
||||||
var caps = Subject.GetCapabilities(_settings, _definition);
|
var caps = Subject.GetCapabilities(_settings, _definition);
|
||||||
|
|
||||||
var bookCats = caps.Categories.MapTrackerCatToNewznab("5070");
|
var indexerCategories = caps.Categories.MapTrackerCatToNewznab(category.ToString());
|
||||||
|
|
||||||
bookCats.Count.Should().Be(2);
|
indexerCategories.Count.Should().Be(2);
|
||||||
bookCats.First().Id.Should().Be(5070);
|
indexerCategories.First().Id.Should().Be(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace NzbDrone.Core.Test.IndexerTests.PTPTests
|
|||||||
first.Guid.Should().Be("PassThePopcorn-452135");
|
first.Guid.Should().Be("PassThePopcorn-452135");
|
||||||
first.Title.Should().Be("The.Night.Of.S01.BluRay.AAC2.0.x264-DEPTH");
|
first.Title.Should().Be("The.Night.Of.S01.BluRay.AAC2.0.x264-DEPTH");
|
||||||
first.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
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.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
|
//first.PublishDate.Should().Be(DateTime.Parse("2017-04-17T12:13:42+0000").ToUniversalTime()); stupid timezones
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dapper" Version="2.0.151" />
|
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||||
<PackageReference Include="NBuilder" Version="6.1.0" />
|
<PackageReference Include="NBuilder" Version="6.1.0" />
|
||||||
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
<PackageReference Include="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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
|
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace NzbDrone.Core.Applications
|
|||||||
protected readonly IAppIndexerMapService _appIndexerMapService;
|
protected readonly IAppIndexerMapService _appIndexerMapService;
|
||||||
protected readonly Logger _logger;
|
protected readonly Logger _logger;
|
||||||
|
|
||||||
protected static readonly Regex AppIndexerRegex = new (@"\/(?<indexer>\d{1,3})(?:\/(?:api)?\/?)?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
protected static readonly Regex AppIndexerRegex = new(@"\/(?<indexer>\d{1,3})(?:\/(?:api)?\/?)?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
public abstract string Name { get; }
|
public abstract string Name { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Applications.LazyLibrarian
|
|||||||
|
|
||||||
public class LazyLibrarianSettings : IApplicationSettings
|
public class LazyLibrarianSettings : IApplicationSettings
|
||||||
{
|
{
|
||||||
private static readonly LazyLibrarianSettingsValidator Validator = new ();
|
private static readonly LazyLibrarianSettingsValidator Validator = new();
|
||||||
|
|
||||||
public LazyLibrarianSettings()
|
public LazyLibrarianSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
{
|
{
|
||||||
var indexerCapabilities = GetIndexerCapabilities(indexer);
|
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())
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -178,7 +185,8 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
{
|
{
|
||||||
_logger.Debug("Syncing remote indexer with current settings");
|
_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
|
// Retain user fields not-affiliated with Prowlarr
|
||||||
lidarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => lidarrIndexer.Fields.All(s => s.Name != f.Name)));
|
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);
|
_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);
|
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Lidarr", indexer.Name, indexer.Id);
|
||||||
lidarrIndexer.Id = 0;
|
lidarrIndexer.Id = 0;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
|
|
||||||
public class LidarrSettings : IApplicationSettings
|
public class LidarrSettings : IApplicationSettings
|
||||||
{
|
{
|
||||||
private static readonly LidarrSettingsValidator Validator = new ();
|
private static readonly LidarrSettingsValidator Validator = new();
|
||||||
|
|
||||||
public LidarrSettings()
|
public LidarrSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Core.Applications.Lidarr
|
|||||||
|
|
||||||
public class LidarrV1Proxy : ILidarrV1Proxy
|
public class LidarrV1Proxy : ILidarrV1Proxy
|
||||||
{
|
{
|
||||||
private static Version MinimumApplicationVersion => new (1, 0, 2, 0);
|
private static Version MinimumApplicationVersion => new(1, 0, 2, 0);
|
||||||
|
|
||||||
private const string AppApiRoute = "/api/v1";
|
private const string AppApiRoute = "/api/v1";
|
||||||
private const string AppIndexerApiRoute = $"{AppApiRoute}/indexer";
|
private const string AppIndexerApiRoute = $"{AppApiRoute}/indexer";
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Applications.Mylar
|
|||||||
|
|
||||||
public class MylarSettings : IApplicationSettings
|
public class MylarSettings : IApplicationSettings
|
||||||
{
|
{
|
||||||
private static readonly MylarSettingsValidator Validator = new ();
|
private static readonly MylarSettingsValidator Validator = new();
|
||||||
|
|
||||||
public MylarSettings()
|
public MylarSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
{
|
{
|
||||||
var indexerCapabilities = GetIndexerCapabilities(indexer);
|
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())
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -176,7 +183,8 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
|
|
||||||
if (!radarrIndexer.Equals(remoteIndexer) || forceSync)
|
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
|
// Retain user fields not-affiliated with Prowlarr
|
||||||
radarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => radarrIndexer.Fields.All(s => s.Name != f.Name)));
|
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);
|
_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);
|
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Radarr", indexer.Name, indexer.Id);
|
||||||
radarrIndexer.Id = 0;
|
radarrIndexer.Id = 0;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
|
|
||||||
public class RadarrSettings : IApplicationSettings
|
public class RadarrSettings : IApplicationSettings
|
||||||
{
|
{
|
||||||
private static readonly RadarrSettingsValidator Validator = new ();
|
private static readonly RadarrSettingsValidator Validator = new();
|
||||||
|
|
||||||
public RadarrSettings()
|
public RadarrSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ namespace NzbDrone.Core.Applications.Radarr
|
|||||||
|
|
||||||
public class RadarrV3Proxy : IRadarrV3Proxy
|
public class RadarrV3Proxy : IRadarrV3Proxy
|
||||||
{
|
{
|
||||||
private static Version MinimumApplicationV4Version => new (4, 0, 4, 0);
|
private static Version MinimumApplicationV4Version => new(4, 0, 4, 0);
|
||||||
private static Version MinimumApplicationV3Version => new (3, 1, 1, 0);
|
private static Version MinimumApplicationV3Version => new(3, 1, 1, 0);
|
||||||
|
|
||||||
private const string AppApiRoute = "/api/v3";
|
private const string AppApiRoute = "/api/v3";
|
||||||
private const string AppIndexerApiRoute = $"{AppApiRoute}/indexer";
|
private const string AppIndexerApiRoute = $"{AppApiRoute}/indexer";
|
||||||
|
|||||||
@@ -121,9 +121,16 @@ namespace NzbDrone.Core.Applications.Readarr
|
|||||||
{
|
{
|
||||||
var indexerCapabilities = GetIndexerCapabilities(indexer);
|
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())
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -178,7 +185,8 @@ namespace NzbDrone.Core.Applications.Readarr
|
|||||||
{
|
{
|
||||||
_logger.Debug("Syncing remote indexer with current settings");
|
_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
|
// Retain user fields not-affiliated with Prowlarr
|
||||||
readarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => readarrIndexer.Fields.All(s => s.Name != f.Name)));
|
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);
|
_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);
|
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Readarr", indexer.Name, indexer.Id);
|
||||||
readarrIndexer.Id = 0;
|
readarrIndexer.Id = 0;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Applications.Readarr
|
|||||||
|
|
||||||
public class ReadarrSettings : IApplicationSettings
|
public class ReadarrSettings : IApplicationSettings
|
||||||
{
|
{
|
||||||
private static readonly ReadarrSettingsValidator Validator = new ();
|
private static readonly ReadarrSettingsValidator Validator = new();
|
||||||
|
|
||||||
public ReadarrSettings()
|
public ReadarrSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -125,10 +125,17 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
{
|
{
|
||||||
var indexerCapabilities = GetIndexerCapabilities(indexer);
|
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() &&
|
if (indexerCapabilities.Categories.SupportedCategories(Settings.SyncCategories.ToArray()).Empty() &&
|
||||||
indexerCapabilities.Categories.SupportedCategories(Settings.AnimeSyncCategories.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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -183,7 +190,8 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
{
|
{
|
||||||
_logger.Debug("Syncing remote indexer with current settings");
|
_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
|
// Retain user fields not-affiliated with Prowlarr
|
||||||
sonarrIndexer.Fields.AddRange(remoteIndexer.Fields.Where(f => sonarrIndexer.Fields.All(s => s.Name != f.Name)));
|
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);
|
_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);
|
_logger.Debug("Remote indexer not found, re-adding {0} [{1}] to Sonarr", indexer.Name, indexer.Id);
|
||||||
sonarrIndexer.Id = 0;
|
sonarrIndexer.Id = 0;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
|
|
||||||
public class SonarrSettings : IApplicationSettings
|
public class SonarrSettings : IApplicationSettings
|
||||||
{
|
{
|
||||||
private static readonly SonarrSettingsValidator Validator = new ();
|
private static readonly SonarrSettingsValidator Validator = new();
|
||||||
|
|
||||||
public SonarrSettings()
|
public SonarrSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Core.Applications.Sonarr
|
|||||||
|
|
||||||
public class SonarrV3Proxy : ISonarrV3Proxy
|
public class SonarrV3Proxy : ISonarrV3Proxy
|
||||||
{
|
{
|
||||||
private static Version MinimumApplicationVersion => new (3, 0, 5, 0);
|
private static Version MinimumApplicationVersion => new(3, 0, 5, 0);
|
||||||
|
|
||||||
private const string AppApiRoute = "/api/v3";
|
private const string AppApiRoute = "/api/v3";
|
||||||
private const string AppIndexerApiRoute = $"{AppApiRoute}/indexer";
|
private const string AppIndexerApiRoute = $"{AppApiRoute}/indexer";
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Applications.Whisparr
|
|||||||
|
|
||||||
public class WhisparrSettings : IApplicationSettings
|
public class WhisparrSettings : IApplicationSettings
|
||||||
{
|
{
|
||||||
private static readonly WhisparrSettingsValidator Validator = new ();
|
private static readonly WhisparrSettingsValidator Validator = new();
|
||||||
|
|
||||||
public WhisparrSettings()
|
public WhisparrSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Authentication
|
namespace NzbDrone.Core.Authentication
|
||||||
{
|
{
|
||||||
public enum AuthenticationType
|
public enum AuthenticationType
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
[Obsolete("Use Forms authentication instead")]
|
||||||
Basic = 1,
|
Basic = 1,
|
||||||
Forms = 2,
|
Forms = 2,
|
||||||
External = 3
|
External = 3
|
||||||
|
|||||||
@@ -207,8 +207,8 @@ namespace NzbDrone.Core.Configuration
|
|||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
SetValue("AuthenticationMethod", AuthenticationType.Basic);
|
SetValue("AuthenticationMethod", AuthenticationType.Forms);
|
||||||
return AuthenticationType.Basic;
|
return AuthenticationType.Forms;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Enum.TryParse<AuthenticationType>(_authOptions.Method, out var enumValue)
|
return Enum.TryParse<AuthenticationType>(_authOptions.Method, out var enumValue)
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
|
|
||||||
protected void Delete(SqlBuilder builder)
|
protected void Delete(SqlBuilder builder)
|
||||||
{
|
{
|
||||||
var sql = builder.AddDeleteTemplate(typeof(TModel)).LogQuery();
|
var sql = builder.AddDeleteTemplate(typeof(TModel));
|
||||||
|
|
||||||
using (var conn = _database.OpenConnection())
|
using (var conn = _database.OpenConnection())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace NzbDrone.Core.Datastore;
|
|||||||
|
|
||||||
public static class DatabaseVersionParser
|
public static class DatabaseVersionParser
|
||||||
{
|
{
|
||||||
private static readonly Regex VersionRegex = new (@"^[^ ]+", RegexOptions.Compiled);
|
private static readonly Regex VersionRegex = new(@"^[^ ]+", RegexOptions.Compiled);
|
||||||
|
|
||||||
public static Version ParseServerVersion(string serverVersion)
|
public static Version ParseServerVersion(string serverVersion)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
switch (expression.NodeType)
|
switch (expression.NodeType)
|
||||||
{
|
{
|
||||||
case ExpressionType.Lambda:
|
case ExpressionType.Lambda:
|
||||||
return VisitLamda((LambdaExpression)expression);
|
return VisitLambda((LambdaExpression)expression);
|
||||||
case ExpressionType.ArrayLength:
|
case ExpressionType.ArrayLength:
|
||||||
case ExpressionType.Convert:
|
case ExpressionType.Convert:
|
||||||
case ExpressionType.ConvertChecked:
|
case ExpressionType.ConvertChecked:
|
||||||
@@ -87,7 +87,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visits the memeber access expression. To be implemented by user.
|
/// Visits the member access expression. To be implemented by user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="expression"></param>
|
/// <param name="expression"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -130,11 +130,11 @@ namespace NzbDrone.Core.Datastore
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visits the lamda expression.
|
/// Visits the lambda expression.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lambdaExpression"></param>
|
/// <param name="lambdaExpression"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected virtual Expression VisitLamda(LambdaExpression lambdaExpression)
|
protected virtual Expression VisitLambda(LambdaExpression lambdaExpression)
|
||||||
{
|
{
|
||||||
Visit(lambdaExpression.Body);
|
Visit(lambdaExpression.Body);
|
||||||
return lambdaExpression;
|
return lambdaExpression;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
@@ -25,8 +26,9 @@ namespace NzbDrone.Core.Download.Clients.Aria2
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||||
@@ -20,8 +21,9 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.Blackhole
|
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||||
@@ -16,8 +17,9 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
|||||||
public UsenetBlackhole(IHttpClient httpClient,
|
public UsenetBlackhole(IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(httpClient, configService, diskProvider, logger)
|
: base(httpClient, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
@@ -23,8 +24,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using NzbDrone.Common.Extensions;
|
|||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Download.Clients.DownloadStation.Proxies;
|
using NzbDrone.Core.Download.Clients.DownloadStation.Proxies;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
@@ -33,8 +34,9 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_dsInfoProxy = dsInfoProxy;
|
_dsInfoProxy = dsInfoProxy;
|
||||||
_dsTaskProxySelector = dsTaskProxySelector;
|
_dsTaskProxySelector = dsTaskProxySelector;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using NzbDrone.Common.Extensions;
|
|||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Download.Clients.DownloadStation.Proxies;
|
using NzbDrone.Core.Download.Clients.DownloadStation.Proxies;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
@@ -31,8 +32,9 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(httpClient, configService, diskProvider, logger)
|
: base(httpClient, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_dsInfoProxy = dsInfoProxy;
|
_dsInfoProxy = dsInfoProxy;
|
||||||
_dsTaskProxySelector = dsTaskProxySelector;
|
_dsTaskProxySelector = dsTaskProxySelector;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using NzbDrone.Common.Extensions;
|
|||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Download.Clients.Flood.Models;
|
using NzbDrone.Core.Download.Clients.Flood.Models;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
@@ -22,8 +23,9 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload
|
|||||||
|
|
||||||
public class FreeboxDownloadSettings : IProviderConfig
|
public class FreeboxDownloadSettings : IProviderConfig
|
||||||
{
|
{
|
||||||
private static readonly FreeboxDownloadSettingsValidator Validator = new ();
|
private static readonly FreeboxDownloadSettingsValidator Validator = new();
|
||||||
|
|
||||||
public FreeboxDownloadSettings()
|
public FreeboxDownloadSettings()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.FreeboxDownload
|
namespace NzbDrone.Core.Download.Clients.FreeboxDownload
|
||||||
@@ -19,8 +20,9 @@ namespace NzbDrone.Core.Download.Clients.FreeboxDownload
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
@@ -20,8 +21,9 @@ namespace NzbDrone.Core.Download.Clients.Hadouken
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
@@ -20,8 +21,9 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
|
|||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(httpClient, configService, diskProvider, logger)
|
: base(httpClient, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using NzbDrone.Common.Extensions;
|
|||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Exceptions;
|
using NzbDrone.Core.Exceptions;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
@@ -18,15 +19,14 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||||||
public class Nzbget : UsenetClientBase<NzbgetSettings>
|
public class Nzbget : UsenetClientBase<NzbgetSettings>
|
||||||
{
|
{
|
||||||
private readonly INzbgetProxy _proxy;
|
private readonly INzbgetProxy _proxy;
|
||||||
private readonly string[] _successStatus = { "SUCCESS", "NONE" };
|
|
||||||
private readonly string[] _deleteFailedStatus = { "HEALTH", "DUPE", "SCAN", "COPY", "BAD" };
|
|
||||||
|
|
||||||
public Nzbget(INzbgetProxy proxy,
|
public Nzbget(INzbgetProxy proxy,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(httpClient, configService, diskProvider, logger)
|
: base(httpClient, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
@@ -17,8 +18,9 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
|
|||||||
{
|
{
|
||||||
public Pneumatic(IConfigService configService,
|
public Pneumatic(IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(configService, diskProvider, logger)
|
: base(configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
@@ -30,8 +31,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
|||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
ICacheManager cacheManager,
|
ICacheManager cacheManager,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxySelector = proxySelector;
|
_proxySelector = proxySelector;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using NzbDrone.Common.Extensions;
|
|||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Exceptions;
|
using NzbDrone.Core.Exceptions;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
@@ -22,8 +23,9 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(httpClient, configService, diskProvider, logger)
|
: base(httpClient, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using NLog;
|
|||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.Transmission
|
namespace NzbDrone.Core.Download.Clients.Transmission
|
||||||
{
|
{
|
||||||
@@ -15,8 +16,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(proxy, torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(proxy, torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
@@ -20,8 +21,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Download.Clients.Transmission;
|
using NzbDrone.Core.Download.Clients.Transmission;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.Vuze
|
namespace NzbDrone.Core.Download.Clients.Vuze
|
||||||
{
|
{
|
||||||
@@ -16,8 +17,9 @@ namespace NzbDrone.Core.Download.Clients.Vuze
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(proxy, torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(proxy, torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using NzbDrone.Core.Configuration;
|
|||||||
using NzbDrone.Core.Download.Clients.rTorrent;
|
using NzbDrone.Core.Download.Clients.rTorrent;
|
||||||
using NzbDrone.Core.Exceptions;
|
using NzbDrone.Core.Exceptions;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
@@ -27,8 +28,9 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
IRTorrentDirectoryValidator rTorrentDirectoryValidator,
|
IRTorrentDirectoryValidator rTorrentDirectoryValidator,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
_rTorrentDirectoryValidator = rTorrentDirectoryValidator;
|
_rTorrentDirectoryValidator = rTorrentDirectoryValidator;
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.ThingiProvider;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.UTorrent
|
namespace NzbDrone.Core.Download.Clients.UTorrent
|
||||||
@@ -21,8 +23,9 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, logger)
|
: base(torrentFileInfoReader, seedConfigProvider, configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_proxy = proxy;
|
||||||
}
|
}
|
||||||
@@ -72,6 +75,9 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "uTorrent";
|
public override string Name => "uTorrent";
|
||||||
|
|
||||||
|
public override ProviderMessage Message => new(_localizationService.GetLocalizedString("DownloadClientUTorrentProviderMessage"), ProviderMessageType.Warning);
|
||||||
|
|
||||||
public override bool SupportsCategories => true;
|
public override bool SupportsCategories => true;
|
||||||
|
|
||||||
protected override void Test(List<ValidationFailure> failures)
|
protected override void Test(List<ValidationFailure> failures)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
@@ -19,6 +20,7 @@ namespace NzbDrone.Core.Download
|
|||||||
{
|
{
|
||||||
protected readonly IConfigService _configService;
|
protected readonly IConfigService _configService;
|
||||||
protected readonly IDiskProvider _diskProvider;
|
protected readonly IDiskProvider _diskProvider;
|
||||||
|
protected readonly ILocalizationService _localizationService;
|
||||||
protected readonly Logger _logger;
|
protected readonly Logger _logger;
|
||||||
|
|
||||||
public abstract string Name { get; }
|
public abstract string Name { get; }
|
||||||
@@ -40,10 +42,12 @@ namespace NzbDrone.Core.Download
|
|||||||
|
|
||||||
protected DownloadClientBase(IConfigService configService,
|
protected DownloadClientBase(IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
|
_localizationService = localizationService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
@@ -15,39 +16,53 @@ namespace NzbDrone.Core.Download
|
|||||||
{
|
{
|
||||||
public void Validate(byte[] fileContent)
|
public void Validate(byte[] fileContent)
|
||||||
{
|
{
|
||||||
var reader = new StreamReader(new MemoryStream(fileContent));
|
try
|
||||||
|
|
||||||
using (var xmlTextReader = XmlReader.Create(reader, new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, IgnoreComments = true }))
|
|
||||||
{
|
{
|
||||||
var xDoc = XDocument.Load(xmlTextReader);
|
var reader = new StreamReader(new MemoryStream(fileContent));
|
||||||
var nzb = xDoc.Root;
|
|
||||||
|
|
||||||
if (nzb == null)
|
using (var xmlTextReader = XmlReader.Create(reader,
|
||||||
|
new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore, IgnoreComments = true }))
|
||||||
{
|
{
|
||||||
throw new InvalidNzbException("Invalid NZB: No Root element");
|
var xDoc = XDocument.Load(xmlTextReader);
|
||||||
}
|
var nzb = xDoc.Root;
|
||||||
|
|
||||||
// nZEDb has an bug in their error reporting code spitting out invalid http status codes
|
if (nzb == null)
|
||||||
if (nzb.Name.LocalName.Equals("error") &&
|
{
|
||||||
nzb.TryGetAttributeValue("code", out var code) &&
|
throw new InvalidNzbException("Invalid NZB: No Root element");
|
||||||
nzb.TryGetAttributeValue("description", out var description))
|
}
|
||||||
{
|
|
||||||
throw new InvalidNzbException("Invalid NZB: Contains indexer error: {0} - {1}", code, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nzb.Name.LocalName.Equals("nzb"))
|
// nZEDb has a bug in their error reporting code spitting out invalid http status codes
|
||||||
{
|
if (nzb.Name.LocalName.Equals("error") &&
|
||||||
throw new InvalidNzbException("Invalid NZB: Unexpected root element. Expected 'nzb' found '{0}'", nzb.Name.LocalName);
|
nzb.TryGetAttributeValue("code", out var code) &&
|
||||||
}
|
nzb.TryGetAttributeValue("description", out var description))
|
||||||
|
{
|
||||||
|
throw new InvalidNzbException("Invalid NZB: Contains indexer error: {0} - {1}", code, description);
|
||||||
|
}
|
||||||
|
|
||||||
var ns = nzb.Name.Namespace;
|
if (!nzb.Name.LocalName.Equals("nzb"))
|
||||||
var files = nzb.Elements(ns + "file").ToList();
|
{
|
||||||
|
throw new InvalidNzbException(
|
||||||
|
"Invalid NZB: Unexpected root element. Expected 'nzb' found '{0}'", nzb.Name.LocalName);
|
||||||
|
}
|
||||||
|
|
||||||
if (files.Empty())
|
var ns = nzb.Name.Namespace;
|
||||||
{
|
var files = nzb.Elements(ns + "file").ToList();
|
||||||
throw new InvalidNzbException("Invalid NZB: No files");
|
|
||||||
|
if (files.Empty())
|
||||||
|
{
|
||||||
|
throw new InvalidNzbException("Invalid NZB: No files");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (InvalidNzbException)
|
||||||
|
{
|
||||||
|
// Throw the original exception
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidNzbException("Invalid NZB: Unable to parse", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using NzbDrone.Common.Extensions;
|
|||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Exceptions;
|
using NzbDrone.Core.Exceptions;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
@@ -24,8 +25,9 @@ namespace NzbDrone.Core.Download
|
|||||||
ISeedConfigProvider seedConfigProvider,
|
ISeedConfigProvider seedConfigProvider,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(configService, diskProvider, logger)
|
: base(configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_torrentFileInfoReader = torrentFileInfoReader;
|
_torrentFileInfoReader = torrentFileInfoReader;
|
||||||
_seedConfigProvider = seedConfigProvider;
|
_seedConfigProvider = seedConfigProvider;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using NzbDrone.Common.Disk;
|
|||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
@@ -19,8 +20,9 @@ namespace NzbDrone.Core.Download
|
|||||||
protected UsenetClientBase(IHttpClient httpClient,
|
protected UsenetClientBase(IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
ILocalizationService localizationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
: base(configService, diskProvider, logger)
|
: base(configService, diskProvider, localizationService, logger)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ namespace NzbDrone.Core.History
|
|||||||
|
|
||||||
if (message.Release.PublishDate != DateTime.MinValue)
|
if (message.Release.PublishDate != DateTime.MinValue)
|
||||||
{
|
{
|
||||||
history.Data.Add("PublishedDate", message.Release.PublishDate.ToString("s") + "Z");
|
history.Data.Add("PublishedDate", message.Release.PublishDate.ToUniversalTime().ToString("s") + "Z");
|
||||||
}
|
}
|
||||||
|
|
||||||
_historyRepository.Insert(history);
|
_historyRepository.Insert(history);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user