diff --git a/.gitignore b/.gitignore index ed6772d69..eeab2f98f 100644 --- a/.gitignore +++ b/.gitignore @@ -127,6 +127,12 @@ coverage*.json setup/Output/ *.~is +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + #VS outout folders bin obj diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c168ca80b..ce2d564d6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -11,11 +11,6 @@ variables: minorVersion: $[counter('minorVersion', 1076)] lidarrVersion: '$(majorVersion).$(minorVersion)' buildName: '$(Build.SourceBranchName).$(lidarrVersion)' - windowsInstaller: 'Lidarr.$(buildName).windows-installer.exe' - windowsZip: 'Lidarr.$(buildName).windows.zip' - macOsApp: 'Lidarr.$(buildName).osx-app.zip' - macOsTar: 'Lidarr.$(buildName).osx.tar.gz' - linuxTar: 'Lidarr.$(buildName).linux.tar.gz' sentryOrg: 'lidarr' dotnetVersion: '3.0.100' @@ -44,7 +39,7 @@ stages: imageName: 'macos-10.14' Windows: osName: 'Windows' - imageName: 'vs2017-win2016' + imageName: 'windows-2019' pool: vmImage: $(imageName) @@ -59,6 +54,7 @@ stages: displayName: 'Install .net core 3.0' inputs: version: $(dotnetVersion) + condition: ne(variables['osName'], 'Windows') - bash: ./build.sh --backend displayName: Build Lidarr Backend - bash: | @@ -66,22 +62,25 @@ stages: find ${OUTPUTFOLDER} -depth -empty -type d -exec rm -r "{}" \; find ${TESTSFOLDER} -type f ! -path "*/publish/*" -exec rm -rf {} \; find ${TESTSFOLDER} -depth -empty -type d -exec rm -r "{}" \; - ls -lR displayName: Clean up intermediate output - publish: $(outputFolder) artifact: '$(osName)Backend' displayName: Publish Backend condition: and(succeeded(), eq(variables['osName'], 'Windows')) - - publish: '$(testsFolder)/net462/win-x64/publish' - artifact: WindowsTests + - publish: '$(testsFolder)/netcoreapp3.0/win-x64/publish' + artifact: WindowsCoreTests displayName: Publish Windows Test Package condition: and(succeeded(), eq(variables['osName'], 'Windows')) - publish: '$(testsFolder)/net462/linux-x64/publish' artifact: LinuxTests displayName: Publish Linux Test Package condition: and(succeeded(), eq(variables['osName'], 'Windows')) - - publish: '$(testsFolder)/net462/osx-x64/publish' - artifact: MacTests + - publish: '$(testsFolder)/netcoreapp3.0/linux-x64/publish' + artifact: LinuxCoreTests + displayName: Publish Linux Test Package + condition: and(succeeded(), eq(variables['osName'], 'Windows')) + - publish: '$(testsFolder)/netcoreapp3.0/osx-x64/publish' + artifact: MacCoreTests displayName: Publish MacOS Test Package condition: and(succeeded(), eq(variables['osName'], 'Windows')) @@ -101,7 +100,7 @@ stages: imageName: 'macos-10.14' Windows: osName: 'Windows' - imageName: 'vs2017-win2016' + imageName: 'windows-2019' pool: vmImage: $(imageName) steps: @@ -129,7 +128,7 @@ stages: - job: Windows_Installer displayName: Create Installer pool: - vmImage: 'vs2017-win2016' + vmImage: 'windows-2019' steps: - checkout: self fetchDepth: 1 @@ -148,9 +147,9 @@ stages: - bash: ./build.sh --packages displayName: Create Packages - bash: | - ./setup/inno/ISCC.exe "./setup/lidarr.iss" - cp ./setup/output/Lidarr.*windows.exe ${BUILD_ARTIFACTSTAGINGDIRECTORY}/${WINDOWSINSTALLER} - displayName: Create Windows installer + setup/inno/ISCC.exe setup/lidarr.iss //DFramework=netcoreapp3.0 + cp setup/output/Lidarr.*windows.netcoreapp3.0.exe ${BUILD_ARTIFACTSTAGINGDIRECTORY}/Lidarr.${BUILDNAME}.windows-core-x64-installer.exe + displayName: Create .NET Core Windows installer - publish: $(Build.ArtifactStagingDirectory) artifact: 'WindowsInstaller' displayName: Publish Installer @@ -184,37 +183,62 @@ stages: - bash: | find . -name "fpcalc" -exec chmod a+x {} \; find . -name "Lidarr" -exec chmod a+x {} \; - displayName: Set Mac executable bits + find . -name "Lidarr.Update" -exec chmod a+x {} \; + displayName: Set executable bits - task: ArchiveFiles@2 - displayName: Create Windows zip + displayName: Create Windows Core zip inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/$(windowsZip)' + archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).windows-core-x64.zip' archiveType: 'zip' includeRootFolder: false - rootFolderOrFile: $(artifactsFolder)/windows/net462 + rootFolderOrFile: $(artifactsFolder)/windows/netcoreapp3.0 - task: ArchiveFiles@2 - displayName: Create MacOS app + displayName: Create MacOS Core app inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/$(macOsApp)' + archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).osx-app-core-x64.zip' archiveType: 'zip' includeRootFolder: false - rootFolderOrFile: $(artifactsFolder)/macos-app/net462 + rootFolderOrFile: $(artifactsFolder)/macos-app/netcoreapp3.0 + - task: ArchiveFiles@2 + displayName: Create MacOS Core tar + inputs: + archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).osx-core-x64.tar.gz' + archiveType: 'tar' + tarCompression: 'gz' + includeRootFolder: false + rootFolderOrFile: $(artifactsFolder)/macos/netcoreapp3.0 + - task: ArchiveFiles@2 + displayName: Create Linux Mono tar + inputs: + archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).linux.tar.gz' + archiveType: 'tar' + tarCompression: 'gz' + includeRootFolder: false + rootFolderOrFile: $(artifactsFolder)/linux-x64/net462 - task: ArchiveFiles@2 - displayName: Create MacOS tar + displayName: Create Linux Core tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/$(macOsTar)' + archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).linux-core-x64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false - rootFolderOrFile: $(artifactsFolder)/macos/net462 + rootFolderOrFile: $(artifactsFolder)/linux-x64/netcoreapp3.0 - task: ArchiveFiles@2 - displayName: Create Linux tar + displayName: Create ARM32 Core tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/$(linuxTar)' + archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).linux-core-arm.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false - rootFolderOrFile: $(artifactsFolder)/linux/net462 + rootFolderOrFile: $(artifactsFolder)/linux-arm/netcoreapp3.0 + - task: ArchiveFiles@2 + displayName: Create Linux Core tar + inputs: + archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).linux-core-arm64.tar.gz' + archiveType: 'tar' + tarCompression: 'gz' + includeRootFolder: false + rootFolderOrFile: $(artifactsFolder)/linux-arm64/netcoreapp3.0 - publish: $(Build.ArtifactStagingDirectory) artifact: 'Packages' displayName: Publish Packages @@ -250,9 +274,19 @@ stages: displayName: Unit Native strategy: matrix: - Windows: + MacCore: + osName: 'Mac' + testName: 'MacCore' + imageName: 'macos-10.13' + WindowsCore: osName: 'Windows' - imageName: 'vs2017-win2016' + testName: 'WindowsCore' + imageName: 'windows-2019' + LinuxCore: + osName: 'Linux' + testName: 'LinuxCore' + imageName: 'ubuntu-16.04' + pattern: 'Lidarr.**.linux-core-x64.tar.gz' pool: vmImage: $(imageName) @@ -263,15 +297,21 @@ stages: displayName: 'Install .net core 3.0' inputs: version: $(dotnetVersion) + condition: ne(variables['osName'], 'Windows') - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' - artifactName: '$(osName)Tests' + artifactName: '$(testName)Tests' targetPath: $(testsFolder) - powershell: Set-Service SCardSvr -StartupType Manual displayName: Enable Windows Test Service condition: and(succeeded(), eq(variables['osName'], 'Windows')) + - bash: | + wget https://github.com/acoustid/chromaprint/releases/download/v1.4.3/chromaprint-fpcalc-1.4.3-linux-x86_64.tar.gz + sudo tar xf chromaprint-fpcalc-1.4.3-linux-x86_64.tar.gz --strip-components=1 --directory /usr/bin + displayName: Install fpcalc + condition: and(succeeded(), eq(variables['osName'], 'Linux')) - bash: | SYMLINK=5_18_1 MONOPREFIX=/Library/Frameworks/Mono.framework/Versions/$SYMLINK @@ -296,7 +336,7 @@ stages: inputs: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' - testRunTitle: '$(osName) Unit Tests' + testRunTitle: '$(testName) Unit Tests' failTaskOnFailedTests: true - job: Unit_Docker @@ -314,7 +354,10 @@ stages: containerImage: servarr/testimages:mono-6.10 mono604: testName: 'Mono 6.4' - containerImage: servarr/testimages:mono-6.12 + containerImage: lidarr/testimages:mono-6.4 + mono606: + testName: 'Mono 6.6' + containerImage: lidarr/testimages:mono-6.6 pool: vmImage: 'ubuntu-16.04' @@ -326,12 +369,17 @@ stages: steps: - bash: mono --version displayName: Check Mono version + - task: UseDotNet@2 + displayName: 'Install .net core 3.0' + inputs: + version: $(dotnetVersion) + condition: ne(variables['osName'], 'Windows') - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' - artifactName: WindowsTests + artifactName: LinuxTests targetPath: $(testsFolder) - task: Bash@3 displayName: Run Tests @@ -356,10 +404,21 @@ stages: displayName: Integration Native strategy: matrix: - Windows: + MacCore: + osName: 'Mac' + testName: 'MacCore' + imageName: 'macos-10.13' + pattern: 'Lidarr.**.osx-core-x64.tar.gz' + WindowsCore: osName: 'Windows' - imageName: 'vs2017-win2016' - pattern: 'Lidarr.**.windows.zip' + testName: 'WindowsCore' + imageName: 'windows-2019' + pattern: 'Lidarr.**.windows-core-x64.zip' + LinuxCore: + osName: 'Linux' + testName: 'LinuxCore' + imageName: 'ubuntu-16.04' + pattern: 'Lidarr.**.linux-core-x64.tar.gz' pool: vmImage: $(imageName) @@ -377,12 +436,13 @@ stages: displayName: 'Install .net core 3.0' inputs: version: $(dotnetVersion) + condition: ne(variables['osName'], 'Windows') - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' - artifactName: '$(osName)Tests' + artifactName: '$(testName)Tests' targetPath: $(testsFolder) - task: DownloadPipelineArtifact@2 displayName: Download Build Artifact @@ -410,7 +470,7 @@ stages: inputs: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' - testRunTitle: '$(osName) Integration Tests' + testRunTitle: '$(testName) Integration Tests' failTaskOnFailedTests: true displayName: Publish Test Results @@ -429,7 +489,10 @@ stages: containerImage: servarr/testimages:mono-6.10 mono604: testName: 'Mono 6.4' - containerImage: servarr/testimages:mono-6.12 + containerImage: lidarr/testimages:mono-6.4 + mono606: + testName: 'Mono 6.6' + containerImage: lidarr/testimages:mono-6.6 variables: pattern: 'Lidarr.**.linux.tar.gz' @@ -444,12 +507,17 @@ stages: steps: - bash: mono --version displayName: Check Mono version + - task: UseDotNet@2 + displayName: 'Install .net core 3.0' + inputs: + version: $(dotnetVersion) + condition: ne(variables['osName'], 'Windows') - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' - artifactName: WindowsTests + artifactName: LinuxTests targetPath: $(testsFolder) - task: DownloadPipelineArtifact@2 displayName: Download Build Artifact @@ -466,7 +534,6 @@ stages: - bash: | mkdir -p ./bin/ cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Lidarr/. ./bin/ - ls -lR displayName: Move Package Contents - task: Bash@3 displayName: Run Integration Tests @@ -493,17 +560,17 @@ stages: Linux: osName: 'Linux' imageName: 'ubuntu-16.04' - pattern: 'Lidarr.**.linux.tar.gz' + pattern: 'Lidarr.**.linux-core-x64.tar.gz' failBuild: true Mac: osName: 'Mac' - imageName: 'macos-10.14' # Fails due to firefox not being installed on image - pattern: 'Lidarr.**.osx.tar.gz' + imageName: 'macos-10.13' # Fails due to firefox not being installed on image + pattern: 'Lidarr.**.osx-core-x64.tar.gz' failBuild: false Windows: osName: 'Windows' - imageName: 'vs2017-win2016' - pattern: 'Lidarr.**.windows.zip' + imageName: 'windows-2019' + pattern: 'Lidarr.**.windows-core-x64.zip' failBuild: true pool: @@ -514,12 +581,13 @@ stages: displayName: 'Install .net core 3.0' inputs: version: $(dotnetVersion) + condition: ne(variables['osName'], 'Windows') - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' - artifactName: '$(osName)Tests' + artifactName: '$(osName)CoreTests' targetPath: $(testsFolder) - task: DownloadPipelineArtifact@2 displayName: Download Build Artifact @@ -551,7 +619,6 @@ stages: mv geckodriver _tests displayName: Install Gecko Driver condition: and(succeeded(), ne(variables['osName'], 'Windows')) - - bash: ls -lR - task: Bash@3 displayName: Run Automation Tests inputs: @@ -581,7 +648,7 @@ stages: imageName: 'ubuntu-16.04' Windows: osName: 'Windows' - imageName: 'vs2017-win2016' + imageName: 'windows-2019' pool: vmImage: $(imageName) steps: @@ -600,7 +667,7 @@ stages: - job: Analyze_Frontend displayName: Frontend pool: - vmImage: vs2017-win2016 + vmImage: windows-2019 steps: - checkout: self # Need history for Sonar analysis - task: SonarCloudPrepare@1 @@ -620,10 +687,14 @@ stages: - job: Analyze_Backend displayName: Backend pool: - vmImage: vs2017-win2016 + vmImage: windows-2019 + variables: + disable.coverage.autogenerate: 'true' steps: - checkout: self # Need history for Sonar analysis submodules: true + - powershell: Set-Service SCardSvr -StartupType Manual + displayName: Enable Windows Test Service - task: SonarCloudPrepare@1 inputs: SonarCloud: 'SonarCloud' @@ -635,22 +706,23 @@ stages: extraProperties: | sonar.exclusions=**/obj/**,**/*.dll,**/NzbDrone.Core.Test/Files/**/*,./frontend/**,**/ExternalModules/**,./src/Libraries/** sonar.coverage.exclusions=**/Lidarr.Api.V1/**/*,**/MonoTorrent/**/*,**/Marr.Data/**/* - sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/_tests/CoverageResults/coverage.opencover.xml + sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml - - task: DotNetCoreCLI@2 - displayName: Build backend - inputs: - command: 'build' - projects: 'src/Lidarr.Windows.sln' - - task: Bash@3 + - bash: | + ./build.sh --backend -f netcoreapp3.0 -r win-x64 + TEST_DIR=_tests/netcoreapp3.0/win-x64/publish/ ./test.sh Windows Unit Coverage displayName: Coverage Unit Tests + - task: SonarCloudAnalyze@1 + displayName: Publish SonarCloud Results + - task: reportgenerator@4 + displayName: Generate Coverage Report inputs: - targetType: 'filePath' - filePath: ./test.sh - arguments: Windows Unit Coverage + reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml' + targetdir: '$(Build.SourcesDirectory)/CoverageResults/combined' + reporttypes: 'HtmlInline_AzurePipelines;Cobertura;Badges' - task: PublishCodeCoverageResults@1 - displayName: Publish Coverage Results + displayName: Publish Coverage Report inputs: codeCoverageTool: 'cobertura' - summaryFileLocation: './_tests/CoverageResults/coverage.cobertura.xml' - - task: SonarCloudAnalyze@1 + summaryFileLocation: './CoverageResults/combined/Cobertura.xml' + reportDirectory: './CoverageResults/combined/' diff --git a/build.sh b/build.sh index 212a3df87..30c74986c 100755 --- a/build.sh +++ b/build.sh @@ -1,23 +1,11 @@ #! /bin/bash -outputFolder='./_output' -testPackageFolder='./_tests/' -sourceFolder='./src' +set -e -#Artifact variables -artifactsFolder="./_artifacts"; - -nuget='tools/nuget/nuget.exe'; +outputFolder='_output' +testPackageFolder='_tests' -CheckExitCode() -{ - "$@" - local status=$? - if [ $status -ne 0 ]; then - echo "error with $1" >&2 - exit 1 - fi - return $status -} +#Artifact variables +artifactsFolder="_artifacts"; ProgressStart() { @@ -33,9 +21,9 @@ UpdateVersionNumber() { if [ "$LIDARRVERSION" != "" ]; then echo "Updating Version Info" - sed -i "s/[0-9.*]\+<\/AssemblyVersion>/$LIDARRVERSION<\/AssemblyVersion>/g" ./src/Directory.Build.props - sed -i "s/[\$()A-Za-z-]\+<\/AssemblyConfiguration>/${BUILD_SOURCEBRANCHNAME}<\/AssemblyConfiguration>/g" ./src/Directory.Build.props - sed -i "s/10.0.0.0<\/string>/$LIDARRVERSION<\/string>/g" ./macOS/Lidarr.app/Contents/Info.plist + sed -i'' -e "s/[0-9.*]\+<\/AssemblyVersion>/$LIDARRVERSION<\/AssemblyVersion>/g" src/Directory.Build.props + sed -i'' -e "s/[\$()A-Za-z-]\+<\/AssemblyConfiguration>/${BUILD_SOURCEBRANCHNAME}<\/AssemblyConfiguration>/g" src/Directory.Build.props + sed -i'' -e "s/10.0.0.0<\/string>/$LIDARRVERSION<\/string>/g" macOS/Lidarr.app/Contents/Info.plist fi } @@ -59,14 +47,14 @@ CleanFolder() LintUI() { ProgressStart 'ESLint' - CheckExitCode yarn lint + yarn lint ProgressEnd 'ESLint' ProgressStart 'Stylelint' if [ "$os" = "windows" ]; then - CheckExitCode yarn stylelint-windows + yarn stylelint-windows else - CheckExitCode yarn stylelint-linux + yarn stylelint-linux fi ProgressEnd 'Stylelint' } @@ -79,14 +67,20 @@ Build() rm -rf $testPackageFolder if [ $os = "windows" ]; then - slnFile=$sourceFolder/Lidarr.Windows.sln + slnFile=src/Lidarr.Windows.sln else - slnFile=$sourceFolder/Lidarr.Posix.sln + slnFile=src/Lidarr.Posix.sln fi - CheckExitCode dotnet clean $slnFile -c Debug - CheckExitCode dotnet clean $slnFile -c Release - CheckExitCode dotnet msbuild -restore $slnFile -p:Configuration=Release -t:PublishAllRids + dotnet clean $slnFile -c Debug + dotnet clean $slnFile -c Release + + if [[ -z "$RID" || -z "$FRAMEWORK" ]]; + then + dotnet msbuild -restore $slnFile -p:Configuration=Release -t:PublishAllRids + else + dotnet msbuild -restore $slnFile -p:Configuration=Release -p:RuntimeIdentifiers=$RID -t:PublishAllRids + fi ProgressEnd 'Build' } @@ -95,14 +89,13 @@ YarnInstall() { ProgressStart 'yarn install' yarn install - #npm-cache install npm || CheckExitCode npm install --no-optional --no-bin-links ProgressEnd 'yarn install' } RunGulp() { ProgressStart 'Running gulp' - CheckExitCode yarn run build --production + yarn run build --production ProgressEnd 'Running gulp' } @@ -127,12 +120,13 @@ PackageFiles() PackageLinux() { local framework="$1" + local runtime="$2" - ProgressStart "Creating Linux Package for $framework" + ProgressStart "Creating $runtime Package for $framework" - local folder=$artifactsFolder/linux/$framework/Lidarr + local folder=$artifactsFolder/$runtime/$framework/Lidarr - PackageFiles "$folder" $framework $runtime "linux-x64" + PackageFiles "$folder" "$framework" "$runtime" echo "Removing Service helpers" rm -f $folder/ServiceUninstall.* @@ -143,8 +137,12 @@ PackageLinux() echo "Adding Lidarr.Mono to UpdatePackage" cp $folder/Lidarr.Mono.* $folder/Lidarr.Update + if [ "$framework" = "netcoreapp3.0" ]; then + cp $folder/Mono.Posix.NETStandard.* $folder/Lidarr.Update + cp $folder/libMonoPosixHelper.* $folder/Lidarr.Update + fi - ProgressEnd "Creating Linux Package for $framework" + ProgressEnd "Creating $runtime Package for $framework" } PackageMacOS() @@ -157,8 +155,10 @@ PackageMacOS() PackageFiles "$folder" "$framework" "osx-x64" - echo "Adding Startup script" - cp ./macOS/Lidarr $folder + if [ "$framework" = "net462" ]; then + echo "Adding Startup script" + cp macOS/Lidarr $folder + fi echo "Removing Service helpers" rm -f $folder/ServiceUninstall.* @@ -169,6 +169,10 @@ PackageMacOS() echo "Adding Lidarr.Mono to UpdatePackage" cp $folder/Lidarr.Mono.* $folder/Lidarr.Update + if [ "$framework" = "netcoreapp3.0" ]; then + cp $folder/Mono.Posix.NETStandard.* $folder/Lidarr.Update + cp $folder/libMonoPosixHelper.* $folder/Lidarr.Update + fi ProgressEnd 'Creating MacOS Package' } @@ -183,7 +187,7 @@ PackageMacOSApp() rm -rf $folder mkdir -p $folder - cp -r ./macOS/Lidarr.app $folder + cp -r macOS/Lidarr.app $folder mkdir -p $folder/Lidarr.app/Contents/MacOS echo "Copying Binaries" @@ -195,36 +199,6 @@ PackageMacOSApp() ProgressEnd 'Creating macOS App Package' } -PackageTests() -{ - ProgressStart 'Creating Test Package' - - cp ./test.sh $testPackageFolder/net462/win-x64/publish - cp ./test.sh $testPackageFolder/net462/linux-x64/publish - cp ./test.sh $testPackageFolder/net462/osx-x64/publish - - if [ $os = "windows" ] ; then - $nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolder/net462/win-x64/publish - $nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolder/net462/linux-x64/publish - $nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolder/net462/osx-x64/publish - else - mono $nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolder/net462/win-x64/publish - mono $nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolder/net462/linux-x64/publish - mono $nuget install NUnit.ConsoleRunner -Version 3.10.0 -Output $testPackageFolder/net462/osx-x64/publish - fi - - rm -f $testPackageFolder/*.log.config - - # geckodriver.exe isn't copied by dotnet publish - curl -Lo gecko.zip "https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-win64.zip" - unzip -o gecko.zip - cp geckodriver.exe $testPackageFolder/net462/win-x64/publish - - CleanFolder $testPackageFolder - - ProgressEnd 'Creating Test Package' -} - PackageWindows() { local framework="$1" @@ -237,6 +211,8 @@ PackageWindows() echo "Removing Lidarr.Mono" rm -f $folder/Lidarr.Mono.* + rm -f $folder/Mono.Posix.NETStandard.* + rm -f $folder/libMonoPosixHelper.* echo "Adding Lidarr.Windows to UpdatePackage" cp $folder/Lidarr.Windows.* $folder/Lidarr.Update @@ -244,6 +220,50 @@ PackageWindows() ProgressEnd 'Creating Windows Package' } +Package() +{ + local framework="$1" + local runtime="$2" + local SPLIT + + IFS='-' read -ra SPLIT <<< "$runtime" + + case "${SPLIT[0]}" in + linux) + PackageLinux "$framework" "$runtime" + ;; + win) + PackageWindows "$framework" + ;; + osx) + PackageMacOS "$framework" + PackageMacOSApp "$framework" + ;; + esac +} + +PackageTests() +{ + local framework="$1" + local runtime="$2" + + cp test.sh "$testPackageFolder/$framework/$runtime/publish" + + rm -f $testPackageFolder/$framework/$runtime/*.log.config + + # geckodriver.exe isn't copied by dotnet publish + if [ "$runtime" = "win-x64" ]; + then + curl -Lso gecko.zip "https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-win64.zip" + unzip -o gecko.zip + cp geckodriver.exe "$testPackageFolder/$framework/win-x64/publish" + fi + + CleanFolder "$testPackageFolder/$framework/$runtime" + + ProgressEnd 'Creating Test Package' +} + # Use mono or .net depending on OS case "$(uname -s)" in CYGWIN*|MINGW32*|MINGW64*|MSYS*) @@ -275,6 +295,16 @@ case $key in BACKEND=YES shift # past argument ;; + -r|--runtime) + RID="$2" + shift # past argument + shift # past value + ;; + -f|--framework) + FRAMEWORK="$2" + shift # past argument + shift # past value + ;; --frontend) FRONTEND=YES shift # past argument @@ -306,7 +336,15 @@ if [ "$BACKEND" = "YES" ]; then UpdateVersionNumber Build - PackageTests + if [[ -z "$RID" || -z "$FRAMEWORK" ]]; + then + PackageTests "netcoreapp3.0" "win-x64" + PackageTests "netcoreapp3.0" "linux-x64" + PackageTests "netcoreapp3.0" "osx-x64" + PackageTests "net462" "linux-x64" + else + PackageTests "$FRAMEWORK" "$RID" + fi fi if [ "$FRONTEND" = "YES" ]; @@ -328,8 +366,16 @@ fi if [ "$PACKAGES" = "YES" ]; then UpdateVersionNumber - PackageWindows "net462" - PackageLinux "net462" - PackageMacOS "net462" - PackageMacOSApp "net462" + + if [[ -z "$RID" || -z "$FRAMEWORK" ]]; + then + Package "netcoreapp3.0" "win-x64" + Package "netcoreapp3.0" "linux-x64" + Package "netcoreapp3.0" "linux-arm64" + Package "netcoreapp3.0" "linux-arm" + Package "netcoreapp3.0" "osx-x64" + Package "net462" "linux-x64" + else + Package "$FRAMEWORK" "$RID" + fi fi diff --git a/frontend/src/Components/SignalRConnector.js b/frontend/src/Components/SignalRConnector.js index 171bd859e..437afbbcb 100644 --- a/frontend/src/Components/SignalRConnector.js +++ b/frontend/src/Components/SignalRConnector.js @@ -1,4 +1,4 @@ -import * as signalR from '@aspnet/signalr/dist/browser/signalr.js'; +import * as signalR from '@microsoft/signalr/dist/browser/signalr.js'; import PropTypes from 'prop-types'; import { Component } from 'react'; import { connect } from 'react-redux'; @@ -54,6 +54,37 @@ const mapDispatchToProps = { dispatchFetchTagDetails: fetchTagDetails }; +function Logger(minimumLogLevel) { + this.minimumLogLevel = minimumLogLevel; +} + +Logger.prototype.cleanse = function(message) { + const apikey = new RegExp(`access_token=${window.Lidarr.apiKey}`, 'g'); + return message.replace(apikey, 'access_token=(removed)'); +}; + +Logger.prototype.log = function(logLevel, message) { + // see https://github.com/aspnet/AspNetCore/blob/21c9e2cc954c10719878839cd3f766aca5f57b34/src/SignalR/clients/ts/signalr/src/Utils.ts#L147 + if (logLevel >= this.minimumLogLevel) { + switch (logLevel) { + case signalR.LogLevel.Critical: + case signalR.LogLevel.Error: + console.error(`[signalR] ${signalR.LogLevel[logLevel]}: ${this.cleanse(message)}`); + break; + case signalR.LogLevel.Warning: + console.warn(`[signalR] ${signalR.LogLevel[logLevel]}: ${this.cleanse(message)}`); + break; + case signalR.LogLevel.Information: + console.info(`[signalR] ${signalR.LogLevel[logLevel]}: ${this.cleanse(message)}`); + break; + default: + // console.debug only goes to attached debuggers in Node, so we use console.log for Trace and Debug + console.log(`[signalR] ${signalR.LogLevel[logLevel]}: ${this.cleanse(message)}`); + break; + } + } +}; + class SignalRConnector extends Component { // @@ -71,6 +102,7 @@ class SignalRConnector extends Component { const url = `${window.Lidarr.urlBase}/signalr/messages`; this.connection = new signalR.HubConnectionBuilder() + .configureLogging(new Logger(signalR.LogLevel.Information)) .withUrl(`${url}?access_token=${window.Lidarr.apiKey}`) .withAutomaticReconnect({ nextRetryDelayInMilliseconds: (retryContext) => { diff --git a/frontend/src/Settings/General/GeneralSettings.js b/frontend/src/Settings/General/GeneralSettings.js index 923f7a8d7..da381420c 100644 --- a/frontend/src/Settings/General/GeneralSettings.js +++ b/frontend/src/Settings/General/GeneralSettings.js @@ -97,7 +97,6 @@ class GeneralSettings extends Component { settings, hasSettings, isResettingApiKey, - isMono, isWindows, isWindowsService, isDocker, @@ -163,7 +162,7 @@ class GeneralSettings extends Component { @@ -205,7 +204,6 @@ GeneralSettings.propTypes = { settings: PropTypes.object.isRequired, isResettingApiKey: PropTypes.bool.isRequired, hasSettings: PropTypes.bool.isRequired, - isMono: PropTypes.bool.isRequired, isWindows: PropTypes.bool.isRequired, isWindowsService: PropTypes.bool.isRequired, isDocker: PropTypes.bool.isRequired, diff --git a/frontend/src/Settings/General/GeneralSettingsConnector.js b/frontend/src/Settings/General/GeneralSettingsConnector.js index 1c64b5724..9f2ec7da1 100644 --- a/frontend/src/Settings/General/GeneralSettingsConnector.js +++ b/frontend/src/Settings/General/GeneralSettingsConnector.js @@ -24,7 +24,6 @@ function createMapStateToProps() { return { advancedSettings, isResettingApiKey, - isMono: systemStatus.isMono, isWindows: systemStatus.isWindows, isWindowsService: systemStatus.isWindows && systemStatus.mode === 'service', isDocker: systemStatus.isDocker, diff --git a/frontend/src/Settings/General/HostSettings.js b/frontend/src/Settings/General/HostSettings.js index 8f74cb27a..1fdeb4862 100644 --- a/frontend/src/Settings/General/HostSettings.js +++ b/frontend/src/Settings/General/HostSettings.js @@ -88,7 +88,7 @@ function HostSettings(props) { { - enableSsl.value && + enableSsl.value ? - + : + null } { - enableSsl.value && + enableSsl.value ? - + : + null } { - enableSsl.value && + enableSsl.value ? - + : + null } { diff --git a/frontend/src/Settings/General/UpdateSettings.js b/frontend/src/Settings/General/UpdateSettings.js index d41f95f35..590eb9647 100644 --- a/frontend/src/Settings/General/UpdateSettings.js +++ b/frontend/src/Settings/General/UpdateSettings.js @@ -15,7 +15,7 @@ function UpdateSettings(props) { const { advancedSettings, settings, - isMono, + isWindows, isDocker, onInputChange } = props; @@ -64,7 +64,7 @@ function UpdateSettings(props) { { - isMono && + !isWindows &&
{ - isMono && + !isWindows && { - advancedSettings && isMono && + advancedSettings && !isWindows &&
@@ -445,7 +445,7 @@ MediaManagement.propTypes = { error: PropTypes.object, settings: PropTypes.object.isRequired, hasSettings: PropTypes.bool.isRequired, - isMono: PropTypes.bool.isRequired, + isWindows: PropTypes.bool.isRequired, onSavePress: PropTypes.func.isRequired, onInputChange: PropTypes.func.isRequired }; diff --git a/frontend/src/Settings/MediaManagement/MediaManagementConnector.js b/frontend/src/Settings/MediaManagement/MediaManagementConnector.js index 5a6250392..782505599 100644 --- a/frontend/src/Settings/MediaManagement/MediaManagementConnector.js +++ b/frontend/src/Settings/MediaManagement/MediaManagementConnector.js @@ -22,7 +22,7 @@ function createMapStateToProps() { advancedSettings, ...sectionSettings, hasPendingChanges: !_.isEmpty(namingSettings.pendingChanges) || sectionSettings.hasPendingChanges, - isMono: systemStatus.isMono + isWindows: systemStatus.isWindows }; } ); diff --git a/frontend/src/System/Status/About/About.js b/frontend/src/System/Status/About/About.js index 12ec88157..7751068a9 100644 --- a/frontend/src/System/Status/About/About.js +++ b/frontend/src/System/Status/About/About.js @@ -15,7 +15,8 @@ class About extends Component { render() { const { version, - isMonoRuntime, + isNetCore, + isMono, isDocker, runtimeVersion, migrationVersion, @@ -36,18 +37,26 @@ class About extends Component { /> { - isMonoRuntime && + isMono && } + { + isNetCore && + + } + { isDocker && } @@ -90,7 +99,8 @@ class About extends Component { About.propTypes = { version: PropTypes.string.isRequired, - isMonoRuntime: PropTypes.bool.isRequired, + isNetCore: PropTypes.bool.isRequired, + isMono: PropTypes.bool.isRequired, runtimeVersion: PropTypes.string.isRequired, isDocker: PropTypes.bool.isRequired, migrationVersion: PropTypes.number.isRequired, diff --git a/package.json b/package.json index de74b817a..5d879dac3 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "license": "GPL-3.0", "readmeFilename": "readme.md", "dependencies": { - "@aspnet/signalr": "1.1.4", "@babel/core": "7.5.5", "@babel/plugin-proposal-class-properties": "7.5.5", "@babel/plugin-proposal-decorators": "7.4.4", @@ -39,6 +38,7 @@ "@fortawesome/free-regular-svg-icons": "5.10.2", "@fortawesome/free-solid-svg-icons": "5.10.2", "@fortawesome/react-fontawesome": "0.1.4", + "@microsoft/signalr": "3.0.0", "@sentry/browser": "5.6.3", "@sentry/integrations": "5.6.1", "ansi-colors": "4.1.1", diff --git a/setup/lidarr.iss b/setup/lidarr.iss index e263a8c03..94ad7ac9b 100644 --- a/setup/lidarr.iss +++ b/setup/lidarr.iss @@ -26,7 +26,7 @@ DefaultDirName={commonappdata}\Lidarr\bin DisableDirPage=yes DefaultGroupName={#AppName} DisableProgramGroupPage=yes -OutputBaseFilename=Lidarr.{#BranchName}.{#BuildVersion}.windows +OutputBaseFilename=Lidarr.{#BranchName}.{#BuildVersion}.windows.{#Framework} SolidCompression=yes AppCopyright=Creative Commons 3.0 License AllowUNCPath=False @@ -48,8 +48,8 @@ Name: "startupShortcut"; Description: "Create shortcut in Startup folder (Starts Name: "none"; Description: "Do not start automatically"; GroupDescription: "Start automatically"; Flags: exclusive unchecked [Files] -Source: "..\_artifacts\windows\net462\Lidarr\Lidarr.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\_artifacts\windows\net462\Lidarr\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +Source: "..\_artifacts\windows\{#Framework}\Lidarr\Lidarr.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\_artifacts\windows\{#Framework}\Lidarr\*"; Excludes: "Lidarr.Update"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 8ea3a8c5f..1b7e14a07 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,7 +5,8 @@ AnyCPU true - win-x64;osx-x64;linux-x64 + win-x64;osx-x64;linux-x64;linux-arm;linux-arm64 + win-x64:net462;osx-x64:net462;linux-arm:net462;linux-arm64:net462 $(MSBuildThisFileDirectory)..\ diff --git a/src/Libraries/Interop.NetFwTypeLib.dll b/src/Libraries/Interop.NetFwTypeLib.dll index 7eae191e5..1a809435f 100644 Binary files a/src/Libraries/Interop.NetFwTypeLib.dll and b/src/Libraries/Interop.NetFwTypeLib.dll differ diff --git a/src/Libraries/Mono.Posix.dll b/src/Libraries/Mono.Posix.dll deleted file mode 100644 index 8e219445f..000000000 Binary files a/src/Libraries/Mono.Posix.dll and /dev/null differ diff --git a/src/Lidarr.Api.V1/Lidarr.Api.V1.csproj b/src/Lidarr.Api.V1/Lidarr.Api.V1.csproj index 8c605d1f5..fa7dbe8e9 100644 --- a/src/Lidarr.Api.V1/Lidarr.Api.V1.csproj +++ b/src/Lidarr.Api.V1/Lidarr.Api.V1.csproj @@ -1,6 +1,6 @@  - net462 + net462;netcoreapp3.0 @@ -17,6 +17,6 @@ - + diff --git a/src/Lidarr.Api.V1/System/SystemModule.cs b/src/Lidarr.Api.V1/System/SystemModule.cs index 81cf57d34..dfa625b08 100644 --- a/src/Lidarr.Api.V1/System/SystemModule.cs +++ b/src/Lidarr.Api.V1/System/SystemModule.cs @@ -59,7 +59,7 @@ namespace Lidarr.Api.V1.System AppData = _appFolderInfo.GetAppDataPath(), OsName = _osInfo.Name, OsVersion = _osInfo.Version, - IsMonoRuntime = PlatformInfo.IsMono, + IsNetCore = PlatformInfo.IsNetCore, IsMono = PlatformInfo.IsMono, IsLinux = OsInfo.IsLinux, IsOsx = OsInfo.IsOsx, diff --git a/src/Lidarr.Http/Extensions/Pipelines/GZipPipeline.cs b/src/Lidarr.Http/Extensions/Pipelines/GZipPipeline.cs index 26d27aacb..a26c368c3 100644 --- a/src/Lidarr.Http/Extensions/Pipelines/GZipPipeline.cs +++ b/src/Lidarr.Http/Extensions/Pipelines/GZipPipeline.cs @@ -6,7 +6,6 @@ using Nancy; using Nancy.Bootstrapper; using NLog; using NzbDrone.Common.EnvironmentInfo; -using NzbDrone.Common.Extensions; namespace Lidarr.Http.Extensions.Pipelines { @@ -81,7 +80,7 @@ namespace Lidarr.Http.Extensions.Pipelines private static bool ContentLengthIsTooSmall(Response response) { - var contentLength = response.Headers.GetValueOrDefault("Content-Length"); + var contentLength = response.Headers.TryGetValue("Content-Length", out var value) ? value : null; if (contentLength != null && long.Parse(contentLength) < 1024) { @@ -93,7 +92,7 @@ namespace Lidarr.Http.Extensions.Pipelines private static bool AlreadyGzipEncoded(Response response) { - var contentEncoding = response.Headers.GetValueOrDefault("Content-Encoding"); + var contentEncoding = response.Headers.TryGetValue("Content-Encoding", out var value) ? value : null; if (contentEncoding == "gzip") { diff --git a/src/Lidarr.Http/Lidarr.Http.csproj b/src/Lidarr.Http/Lidarr.Http.csproj index d3e46dd94..246994fa0 100644 --- a/src/Lidarr.Http/Lidarr.Http.csproj +++ b/src/Lidarr.Http/Lidarr.Http.csproj @@ -1,6 +1,6 @@  - net462 + net462;netcoreapp3.0 diff --git a/src/Marr.Data/DataMapper.cs b/src/Marr.Data/DataMapper.cs index 51423b988..b8ee4fed0 100644 --- a/src/Marr.Data/DataMapper.cs +++ b/src/Marr.Data/DataMapper.cs @@ -38,15 +38,6 @@ namespace Marr.Data private DbCommand _command; - /// - /// Initializes a DataMapper for the given provider type and connection string. - /// - /// Ex: - /// The database connection string. - public DataMapper(string providerName, string connectionString) - : this(DbProviderFactories.GetFactory(providerName), connectionString) - { } - /// /// A database provider agnostic initialization. /// diff --git a/src/Marr.Data/Marr.Data.csproj b/src/Marr.Data/Marr.Data.csproj index a1180d1b4..8f92f948d 100644 --- a/src/Marr.Data/Marr.Data.csproj +++ b/src/Marr.Data/Marr.Data.csproj @@ -1,6 +1,6 @@  - net462 + netstandard2.0 3.17.0.0 false diff --git a/src/Marr.Data/Parameters/OleDbTypeBuilder.cs b/src/Marr.Data/Parameters/OleDbTypeBuilder.cs deleted file mode 100644 index d8af140a4..000000000 --- a/src/Marr.Data/Parameters/OleDbTypeBuilder.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2008 - 2011 Jordan Marr - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 3 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library. If not, see . */ - -using System; -using System.Data; -using System.Data.OleDb; - -namespace Marr.Data.Parameters -{ - public class OleDbTypeBuilder : IDbTypeBuilder - { - public Enum GetDbType(Type type) - { - if (type == typeof(String)) - return OleDbType.VarChar; - - if (type == typeof(Int32)) - return OleDbType.Integer; - - if (type == typeof(Decimal)) - return OleDbType.Decimal; - - if (type == typeof(DateTime)) - return OleDbType.DBTimeStamp; - - if (type == typeof(Boolean)) - return OleDbType.Boolean; - - if (type == typeof(Int16)) - return OleDbType.SmallInt; - - if (type == typeof(Int64)) - return OleDbType.BigInt; - - if (type == typeof(Double)) - return OleDbType.Double; - - if (type == typeof(Byte)) - return OleDbType.Binary; - - if (type == typeof(Byte[])) - return OleDbType.VarBinary; - - if (type == typeof(Guid)) - return OleDbType.Guid; - - return OleDbType.Variant; - } - - public void SetDbType(IDbDataParameter param, Enum dbType) - { - var oleDbParam = (OleDbParameter)param; - oleDbParam.OleDbType = (OleDbType)dbType; - } - } -} diff --git a/src/Marr.Data/Parameters/SqlDbTypeBuilder.cs b/src/Marr.Data/Parameters/SqlDbTypeBuilder.cs deleted file mode 100644 index 39d2fdaae..000000000 --- a/src/Marr.Data/Parameters/SqlDbTypeBuilder.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2008 - 2011 Jordan Marr - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 3 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library. If not, see . */ - -using System; -using System.Data; -using System.Data.SqlClient; - -namespace Marr.Data.Parameters -{ - public class SqlDbTypeBuilder : IDbTypeBuilder - { - public Enum GetDbType(Type type) - { - if (type == typeof(String)) - return SqlDbType.VarChar; - - if (type == typeof(Int32)) - return SqlDbType.Int; - - if (type == typeof(Decimal)) - return SqlDbType.Decimal; - - if (type == typeof(DateTime)) - return SqlDbType.DateTime; - - if (type == typeof(Boolean)) - return SqlDbType.Bit; - - if (type == typeof(Int16)) - return SqlDbType.SmallInt; - - if (type == typeof(Int64)) - return SqlDbType.BigInt; - - if (type == typeof(Double)) - return SqlDbType.Float; - - if (type == typeof(Char)) - return SqlDbType.Char; - - if (type == typeof(Byte)) - return SqlDbType.Binary; - - if (type == typeof(Byte[])) - return SqlDbType.VarBinary; - - if (type == typeof(Guid)) - return SqlDbType.UniqueIdentifier; - - return SqlDbType.Variant; - } - - public void SetDbType(IDbDataParameter param, Enum dbType) - { - var sqlDbParam = (SqlParameter)param; - sqlDbParam.SqlDbType = (SqlDbType)dbType; - } - } -} diff --git a/src/MonoTorrent/MonoTorrent.csproj b/src/MonoTorrent/MonoTorrent.csproj index 13621bc33..4d5b70a11 100644 --- a/src/MonoTorrent/MonoTorrent.csproj +++ b/src/MonoTorrent/MonoTorrent.csproj @@ -1,6 +1,6 @@  - net462 + netstandard2.0 9.0.21022 diff --git a/src/NzbDrone.Api.Test/Lidarr.Api.Test.csproj b/src/NzbDrone.Api.Test/Lidarr.Api.Test.csproj index b70ceb000..8e10eea94 100644 --- a/src/NzbDrone.Api.Test/Lidarr.Api.Test.csproj +++ b/src/NzbDrone.Api.Test/Lidarr.Api.Test.csproj @@ -1,10 +1,17 @@  - net462 + net462;netcoreapp3.0 + + + + + + + diff --git a/src/NzbDrone.Automation.Test/Lidarr.Automation.Test.csproj b/src/NzbDrone.Automation.Test/Lidarr.Automation.Test.csproj index 291e37581..ef6bb1850 100644 --- a/src/NzbDrone.Automation.Test/Lidarr.Automation.Test.csproj +++ b/src/NzbDrone.Automation.Test/Lidarr.Automation.Test.csproj @@ -1,8 +1,12 @@  - net462 + net462;netcoreapp3.0 + + + + diff --git a/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs b/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs index 1c7a8ca7a..e062b92c4 100644 --- a/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs +++ b/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs @@ -170,7 +170,7 @@ namespace NzbDrone.Common.Test.Http var response = Subject.Get(request); response.Resource.Headers["Accept-Encoding"].ToString().Should().Be(compression); - response.Headers.ContentLength.Should().BeLessOrEqualTo(response.Content.Length); + response.Resource.Gzipped.Should().BeTrue(); } [TestCase(HttpStatusCode.Unauthorized)] @@ -723,6 +723,7 @@ namespace NzbDrone.Common.Test.Http public string Origin { get; set; } public string Url { get; set; } public string Data { get; set; } + public bool Gzipped { get; set; } } public class HttpCookieResource diff --git a/src/NzbDrone.Common.Test/Lidarr.Common.Test.csproj b/src/NzbDrone.Common.Test/Lidarr.Common.Test.csproj index 8cd5bed59..b6104de09 100644 --- a/src/NzbDrone.Common.Test/Lidarr.Common.Test.csproj +++ b/src/NzbDrone.Common.Test/Lidarr.Common.Test.csproj @@ -1,13 +1,22 @@  - net462 + net462;netcoreapp3.0 + + + + + + + + + - + diff --git a/src/NzbDrone.Common.Test/PathExtensionFixture.cs b/src/NzbDrone.Common.Test/PathExtensionFixture.cs index 04d21dda3..3b0db0f79 100644 --- a/src/NzbDrone.Common.Test/PathExtensionFixture.cs +++ b/src/NzbDrone.Common.Test/PathExtensionFixture.cs @@ -224,7 +224,7 @@ namespace NzbDrone.Common.Test public void get_actual_casing_should_return_actual_casing_for_local_dir_in_windows() { WindowsOnly(); - var path = Directory.GetCurrentDirectory().Replace("c:\\","C:\\").Replace("system32", "System32"); + var path = Directory.GetCurrentDirectory().Replace("c:\\","C:\\").Replace("d:\\","D:\\").Replace("system32", "System32"); path.ToUpper().GetActualCasing().Should().Be(path); path.ToLower().GetActualCasing().Should().Be(path); @@ -281,7 +281,7 @@ namespace NzbDrone.Common.Test [Test] public void GetUpdateClientExePath() { - GetIAppDirectoryInfo().GetUpdateClientExePath(new Version("0.7.1.1381")).Should().BeEquivalentTo(@"C:\Temp\lidarr_update\Lidarr.Update.exe".AsOsAgnostic()); + GetIAppDirectoryInfo().GetUpdateClientExePath(PlatformType.DotNet).Should().BeEquivalentTo(@"C:\Temp\lidarr_update\Lidarr.Update.exe".AsOsAgnostic()); } [Test] diff --git a/src/NzbDrone.Common.Test/ProcessProviderFixture.cs b/src/NzbDrone.Common.Test/ProcessProviderFixture.cs index 8487a8d2a..d00fd9d1b 100644 --- a/src/NzbDrone.Common.Test/ProcessProviderFixture.cs +++ b/src/NzbDrone.Common.Test/ProcessProviderFixture.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Model; using NzbDrone.Common.Processes; using NzbDrone.Test.Common; @@ -123,7 +124,17 @@ namespace NzbDrone.Common.Test { var processStarted = new ManualResetEventSlim(); - var path = Path.Combine(TestContext.CurrentContext.TestDirectory, DummyApp.DUMMY_PROCCESS_NAME + ".exe"); + string suffix; + if (OsInfo.IsWindows || PlatformInfo.IsMono) + { + suffix = ".exe"; + } + else + { + suffix = ""; + } + + var path = Path.Combine(TestContext.CurrentContext.TestDirectory, DummyApp.DUMMY_PROCCESS_NAME + suffix); var process = Subject.Start(path, onOutputDataReceived: (string data) => { if (data.StartsWith("Dummy process. ID:")) { diff --git a/src/NzbDrone.Common.Test/ServiceProviderFixture.cs b/src/NzbDrone.Common.Test/ServiceProviderFixture.cs index ecbc420d6..7039a48c7 100644 --- a/src/NzbDrone.Common.Test/ServiceProviderFixture.cs +++ b/src/NzbDrone.Common.Test/ServiceProviderFixture.cs @@ -4,13 +4,13 @@ using System.ServiceProcess; using FluentAssertions; using NUnit.Framework; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Processes; using NzbDrone.Test.Common; using NzbDrone.Test.Common.Categories; namespace NzbDrone.Common.Test { [TestFixture] - [Timeout(15000)] public class ServiceProviderFixture : TestBase { private const string ALWAYS_INSTALLED_SERVICE = "SCardSvr"; //Smart Card @@ -20,6 +20,9 @@ namespace NzbDrone.Common.Test public void Setup() { WindowsOnly(); + + Mocker.SetConstant(Mocker.Resolve()); + CleanupService(); } diff --git a/src/NzbDrone.Common/Composition/ContainerBuilderBase.cs b/src/NzbDrone.Common/Composition/ContainerBuilderBase.cs index 7323c06f9..c23cd077f 100644 --- a/src/NzbDrone.Common/Composition/ContainerBuilderBase.cs +++ b/src/NzbDrone.Common/Composition/ContainerBuilderBase.cs @@ -6,6 +6,12 @@ using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Messaging; using TinyIoC; +#if NETCOREAPP3_0 +using System.IO; +using System.Runtime.Loader; +using System.Runtime.InteropServices; +#endif + namespace NzbDrone.Common.Composition { public abstract class ContainerBuilderBase @@ -21,15 +27,67 @@ namespace NzbDrone.Common.Composition assemblies.Add(OsInfo.IsWindows ? "Lidarr.Windows" : "Lidarr.Mono"); assemblies.Add("Lidarr.Common"); +#if !NETCOREAPP3_0 foreach (var assembly in assemblies) { _loadedTypes.AddRange(Assembly.Load(assembly).GetTypes()); } +#else + var _startupPath = AppDomain.CurrentDomain.BaseDirectory; + + foreach (var assemblyName in assemblies) + { + _loadedTypes.AddRange(AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(_startupPath, $"{assemblyName}.dll")).GetTypes()); + } + + AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ContainerResolveEventHandler); + RegisterSQLiteResolver(); +#endif Container = new Container(new TinyIoCContainer(), _loadedTypes); AutoRegisterInterfaces(); Container.Register(args); - } + } + +#if NETCOREAPP3_0 + private static Assembly ContainerResolveEventHandler(object sender, ResolveEventArgs args) + { + var _resolver = new AssemblyDependencyResolver(args.RequestingAssembly.Location); + var assemblyPath = _resolver.ResolveAssemblyToPath(new AssemblyName(args.Name)); + + if (assemblyPath == null) + { + return null; + } + + return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath); + } + + public static void RegisterSQLiteResolver() + { + // This ensures we look for sqlite3 using libsqlite3.so.0 on Linux and not libsqlite3.so which + // is less likely to exist. + var sqliteAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath( + Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "System.Data.SQLite.dll") + ); + + try + { + NativeLibrary.SetDllImportResolver(sqliteAssembly, LoadSqliteNativeLib); + } + catch (InvalidOperationException) + { + // This can only be set once per assembly + // Catch required for NzbDrone.Host tests + } + } + + private static IntPtr LoadSqliteNativeLib(string libraryName, Assembly assembly, DllImportSearchPath? dllImportSearchPath) + { + var mappedName = OsInfo.IsLinux && libraryName == "sqlite3" ? "libsqlite3.so.0" : libraryName; + return NativeLibrary.Load(mappedName, assembly, dllImportSearchPath); + } +#endif private void AutoRegisterInterfaces() { diff --git a/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs b/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs index 1b8e38b8c..0a9baa4e3 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs @@ -74,21 +74,26 @@ namespace NzbDrone.Common.EnvironmentInfo try { - var configHome = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - if (configHome == "/.config" || + // It seems that DoNotVerify is the mono behaviour even though .net docs specify a blank string + // should be returned if the data doesn't exist. For compatibility with .net core, explicitly + // set DoNotVerify (which makes sense given we're explicitly checking that the folder exists) + var configHome = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.DoNotVerify); + if (configHome.IsNullOrWhiteSpace() || + configHome == "/.config" || configHome.EndsWith("/.config") && !_diskProvider.FolderExists(configHome.GetParentPath()) || !_diskProvider.FolderExists(configHome)) { - // Tell mono to use appData/.config as ApplicationData folder. + // Tell mono/netcore to use appData/.config as ApplicationData folder. Environment.SetEnvironmentVariable("XDG_CONFIG_HOME", Path.Combine(_appFolderInfo.AppDataFolder, ".config")); } - var dataHome = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - if (dataHome == "/.local/share" || + var dataHome = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.DoNotVerify); + if (dataHome.IsNullOrWhiteSpace() || + dataHome == "/.local/share" || dataHome.EndsWith("/.local/share") && !_diskProvider.FolderExists(dataHome.GetParentPath().GetParentPath()) || !_diskProvider.FolderExists(dataHome)) { - // Tell mono to use appData/.config/share as LocalApplicationData folder. + // Tell mono/netcore to use appData/.config/share as LocalApplicationData folder. Environment.SetEnvironmentVariable("XDG_DATA_HOME", Path.Combine(_appFolderInfo.AppDataFolder, ".config/share")); } } diff --git a/src/NzbDrone.Common/EnvironmentInfo/AppFolderInfo.cs b/src/NzbDrone.Common/EnvironmentInfo/AppFolderInfo.cs index b43199902..8ad24d56c 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/AppFolderInfo.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/AppFolderInfo.cs @@ -34,7 +34,7 @@ namespace NzbDrone.Common.EnvironmentInfo } else { - AppDataFolder = Path.Combine(Environment.GetFolderPath(DATA_SPECIAL_FOLDER, Environment.SpecialFolderOption.None), "Lidarr"); + AppDataFolder = Path.Combine(Environment.GetFolderPath(DATA_SPECIAL_FOLDER, Environment.SpecialFolderOption.DoNotVerify), "Lidarr"); } StartUpFolder = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName; @@ -47,4 +47,4 @@ namespace NzbDrone.Common.EnvironmentInfo public string TempFolder { get; } } -} \ No newline at end of file +} diff --git a/src/NzbDrone.Common/EnvironmentInfo/PlatformInfo.cs b/src/NzbDrone.Common/EnvironmentInfo/PlatformInfo.cs index c8469ef09..85fdb2f8a 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/PlatformInfo.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/PlatformInfo.cs @@ -9,7 +9,8 @@ namespace NzbDrone.Common.EnvironmentInfo public enum PlatformType { DotNet = 0, - Mono = 1 + Mono = 1, + NetCore = 2 } public interface IPlatformInfo @@ -26,6 +27,10 @@ namespace NzbDrone.Common.EnvironmentInfo static PlatformInfo() { +#if NETCOREAPP3_0 + _platform = PlatformType.NetCore; + _version = new Version("3.0"); +#else if (Type.GetType("Mono.Runtime") != null) { _platform = PlatformType.Mono; @@ -36,11 +41,13 @@ namespace NzbDrone.Common.EnvironmentInfo _platform = PlatformType.DotNet; _version = GetDotNetVersion(); } +#endif } public static PlatformType Platform => _platform; public static bool IsMono => Platform == PlatformType.Mono; public static bool IsDotNet => Platform == PlatformType.DotNet; + public static bool IsNetCore => Platform == PlatformType.NetCore; public static string PlatformName { @@ -50,8 +57,14 @@ namespace NzbDrone.Common.EnvironmentInfo { return ".NET"; } - - return "Mono"; + else if (IsMono) + { + return "Mono"; + } + else + { + return ".NET Core"; + } } } diff --git a/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs b/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs index fa017bfe3..bed249ea2 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs @@ -7,6 +7,10 @@ using System.ServiceProcess; using NLog; using NzbDrone.Common.Processes; +#if NETCOREAPP3_0 +using Microsoft.Extensions.Hosting.WindowsServices; +#endif + namespace NzbDrone.Common.EnvironmentInfo { public class RuntimeInfo : IRuntimeInfo @@ -57,7 +61,12 @@ namespace NzbDrone.Common.EnvironmentInfo } } +#if !NETCOREAPP3_0 public static bool IsUserInteractive => Environment.UserInteractive; +#else + // Note that Environment.UserInteractive is always true on net core: https://stackoverflow.com/a/57325783 + public static bool IsUserInteractive => OsInfo.IsWindows && !WindowsServiceHelpers.IsWindowsService(); +#endif bool IRuntimeInfo.IsUserInteractive => IsUserInteractive; @@ -65,6 +74,11 @@ namespace NzbDrone.Common.EnvironmentInfo { get { + if (OsInfo.IsNotWindows) + { + return false; + } + try { var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); diff --git a/src/NzbDrone.Common/Exceptions/ServiceProviderException.cs b/src/NzbDrone.Common/Exceptions/ServiceProviderException.cs new file mode 100644 index 000000000..6c3ec7b15 --- /dev/null +++ b/src/NzbDrone.Common/Exceptions/ServiceProviderException.cs @@ -0,0 +1,29 @@ +using System; + +namespace NzbDrone.Common.Exceptions +{ + public class ServiceProviderException : NzbDroneException + { + public ServiceProviderException(string message, params object[] args) + : base(string.Format(message, args)) + { + + } + + public ServiceProviderException(string message) + : base(message) + { + + } + + public ServiceProviderException(Exception innerException, string message, params object[] args) + : base(string.Format(message, args), innerException) + { + } + + public ServiceProviderException(Exception innerException, string message) + : base(message, innerException) + { + } + } +} diff --git a/src/NzbDrone.Common/Extensions/DictionaryExtensions.cs b/src/NzbDrone.Common/Extensions/DictionaryExtensions.cs index d92005875..646e657aa 100644 --- a/src/NzbDrone.Common/Extensions/DictionaryExtensions.cs +++ b/src/NzbDrone.Common/Extensions/DictionaryExtensions.cs @@ -6,11 +6,13 @@ namespace NzbDrone.Common.Extensions { public static class DictionaryExtensions { - public static TValue GetValueOrDefault(this IDictionary dictionary, TKey key, TValue defaultValue = default(TValue)) +#if !NETCOREAPP3_0 + public static TValue GetValueOrDefault(this IReadOnlyDictionary dictionary, TKey key, TValue defaultValue = default(TValue)) { TValue value; return dictionary.TryGetValue(key, out value) ? value : defaultValue; } +#endif public static Dictionary Merge(this Dictionary first, Dictionary second) { diff --git a/src/NzbDrone.Common/Extensions/GzipExtensions.cs b/src/NzbDrone.Common/Extensions/GzipExtensions.cs new file mode 100644 index 000000000..7dc63d93d --- /dev/null +++ b/src/NzbDrone.Common/Extensions/GzipExtensions.cs @@ -0,0 +1,30 @@ +using System.IO; +using System.IO.Compression; + +namespace NzbDrone.Common.Extensions +{ + public static class GzipExtensions + { + public static byte[] Decompress(this byte[] data) + { + using (var compressedStream = new MemoryStream(data)) + using (var gzip = new GZipStream(compressedStream, CompressionMode.Decompress)) + using (var decompressedStream = new MemoryStream()) + { + gzip.CopyTo(decompressedStream); + return decompressedStream.ToArray(); + } + } + + public static byte[] Compress(this byte[] data) + { + using (var compressedStream = new MemoryStream()) + using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) + { + zipStream.Write(data, 0, data.Length); + zipStream.Close(); + return compressedStream.ToArray(); + } + } + } +} diff --git a/src/NzbDrone.Common/Extensions/PathExtensions.cs b/src/NzbDrone.Common/Extensions/PathExtensions.cs index aa01263de..5591cd731 100644 --- a/src/NzbDrone.Common/Extensions/PathExtensions.cs +++ b/src/NzbDrone.Common/Extensions/PathExtensions.cs @@ -217,12 +217,9 @@ namespace NzbDrone.Common.Extensions return null; } - public static string ProcessNameToExe(this string processName, Version version) + public static string ProcessNameToExe(this string processName, PlatformType runtime) { - // Windows always has exe (but is shunted to net core) - // Linux is kept on mono pending manual upgrade to net core so has .exe - // macOS is shunted to net core and does not have .exe - if (OsInfo.IsWindows || OsInfo.IsLinux || (version.Major == 0 && version.Minor == 7)) + if (OsInfo.IsWindows || runtime != PlatformType.NetCore) { processName += ".exe"; } @@ -230,6 +227,11 @@ namespace NzbDrone.Common.Extensions return processName; } + public static string ProcessNameToExe(this string processName) + { + return processName.ProcessNameToExe(PlatformInfo.Platform); + } + public static string GetAppDataPath(this IAppFolderInfo appFolderInfo) { return appFolderInfo.AppDataFolder; @@ -290,9 +292,9 @@ namespace NzbDrone.Common.Extensions return Path.Combine(GetUpdatePackageFolder(appFolderInfo), UPDATE_CLIENT_FOLDER_NAME); } - public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo, Version version) + public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo, PlatformType runtime) { - return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE_NAME).ProcessNameToExe(version); + return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE_NAME).ProcessNameToExe(runtime); } public static string GetDatabase(this IAppFolderInfo appFolderInfo) diff --git a/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs b/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs index 7cd8e6d9b..44bbeea8b 100644 --- a/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs +++ b/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.IO.Compression; using System.Net; using System.Reflection; using NLog; @@ -125,14 +124,7 @@ namespace NzbDrone.Common.Http.Dispatchers if (PlatformInfo.IsMono && httpWebResponse.ContentEncoding == "gzip") { - using (var compressedStream = new MemoryStream(data)) - using (var gzip = new GZipStream(compressedStream, CompressionMode.Decompress)) - using (var decompressedStream = new MemoryStream()) - { - gzip.CopyTo(decompressedStream); - data = decompressedStream.ToArray(); - } - + data = data.Decompress(); httpWebResponse.Headers.Remove("Content-Encoding"); } } diff --git a/src/NzbDrone.Common/Lidarr.Common.csproj b/src/NzbDrone.Common/Lidarr.Common.csproj index f4a5572d0..33eb2aaf7 100644 --- a/src/NzbDrone.Common/Lidarr.Common.csproj +++ b/src/NzbDrone.Common/Lidarr.Common.csproj @@ -1,6 +1,6 @@  - net462 + net462;netcoreapp3.0 @@ -8,12 +8,18 @@ - + - - + + + + + + + + diff --git a/src/NzbDrone.Common/ServiceProvider.cs b/src/NzbDrone.Common/ServiceProvider.cs index 2819c2736..0e788e79f 100644 --- a/src/NzbDrone.Common/ServiceProvider.cs +++ b/src/NzbDrone.Common/ServiceProvider.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Specialized; -using System.Configuration.Install; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using NLog; +using NzbDrone.Common.Exceptions; using NzbDrone.Common.Extensions; using NzbDrone.Common.Processes; @@ -62,30 +61,36 @@ namespace NzbDrone.Common public virtual void Install(string serviceName) { - _logger.Info("Installing service '{0}'", serviceName); + _logger.Info("Installing service '{0}'", serviceName); - var installer = new ServiceProcessInstaller - { - Account = ServiceAccount.LocalService - }; + var args = $"create {serviceName} " + + $"DisplayName= \"{serviceName}\" " + + $"binpath= \"{Process.GetCurrentProcess().MainModule.FileName}\" " + + "start= auto " + + "depend= EventLog/Tcpip/http " + + "obj= \"NT AUTHORITY\\LocalService\""; - var serviceInstaller = new ServiceInstaller(); + _logger.Info(args); + var installOutput = _processProvider.StartAndCapture("sc.exe", args); - string[] cmdline = { @"/assemblypath=" + Process.GetCurrentProcess().MainModule.FileName }; + if (installOutput.ExitCode != 0) + { + _logger.Error($"Failed to install service: {installOutput.Lines.Select(x => x.Content).ConcatToString("\n")}"); + throw new ServiceProviderException("Failed to install service"); + } - var context = new InstallContext("service_install.log", cmdline); - serviceInstaller.Context = context; - serviceInstaller.DisplayName = serviceName; - serviceInstaller.ServiceName = serviceName; - serviceInstaller.Description = "Lidarr Application Server"; - serviceInstaller.StartType = ServiceStartMode.Automatic; - serviceInstaller.ServicesDependedOn = new[] { "EventLog", "Tcpip", "http" }; + _logger.Info(installOutput.Lines.Select(x => x.Content).ConcatToString("\n")); - serviceInstaller.Parent = installer; + var descOutput = _processProvider.StartAndCapture("sc.exe", $"description {serviceName} \"Lidarr Application Server\""); + if (descOutput.ExitCode != 0) + { + _logger.Error($"Failed to install service: {descOutput.Lines.Select(x => x.Content).ConcatToString("\n")}"); + throw new ServiceProviderException("Failed to install service"); + } - serviceInstaller.Install(new ListDictionary()); + _logger.Info(descOutput.Lines.Select(x => x.Content).ConcatToString("\n")); _logger.Info("Service Has installed successfully."); } @@ -96,12 +101,8 @@ namespace NzbDrone.Common Stop(serviceName); - var serviceInstaller = new ServiceInstaller(); - - var context = new InstallContext("service_uninstall.log", null); - serviceInstaller.Context = context; - serviceInstaller.ServiceName = serviceName; - serviceInstaller.Uninstall(null); + var output = _processProvider.StartAndCapture("sc.exe", $"delete {serviceName}"); + _logger.Info(output.Lines.Select(x => x.Content).ConcatToString("\n")); _logger.Info("{0} successfully uninstalled", serviceName); } diff --git a/src/NzbDrone.Console/Lidarr.Console.csproj b/src/NzbDrone.Console/Lidarr.Console.csproj index 8ffeed355..52f785be5 100644 --- a/src/NzbDrone.Console/Lidarr.Console.csproj +++ b/src/NzbDrone.Console/Lidarr.Console.csproj @@ -1,7 +1,7 @@  Exe - net462 + net462;netcoreapp3.0 ..\NzbDrone.Host\NzbDrone.ico app.manifest diff --git a/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs b/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs index 38df5626d..4ba13fd85 100644 --- a/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Download/DownloadServiceFixture.cs @@ -163,7 +163,7 @@ namespace NzbDrone.Core.Test.Download Mocker.GetMock() .Verify(v => v.RecordFailure(It.IsAny(), - It.IsInRange(TimeSpan.FromMinutes(4.9), TimeSpan.FromMinutes(5.1), Range.Inclusive)), Times.Once()); + It.IsInRange(TimeSpan.FromMinutes(4.9), TimeSpan.FromMinutes(5.1), Moq.Range.Inclusive)), Times.Once()); } [Test] diff --git a/src/NzbDrone.Core.Test/Files/Fingerprinting/AcoustidResponses.json b/src/NzbDrone.Core.Test/Files/Fingerprinting/AcoustidResponses.json index 729492cbd..d3d4a9d5a 100644 --- a/src/NzbDrone.Core.Test/Files/Fingerprinting/AcoustidResponses.json +++ b/src/NzbDrone.Core.Test/Files/Fingerprinting/AcoustidResponses.json @@ -1,26 +1,30 @@ [ { - "requestContent": "1F-8B-08-00-00-00-00-00-00-03-15-54-CB-B6-B2-BC-12-7C-9B-6F-C6-59-5E-22-C2-60-0F-72-83-84-8B-21-20-2A-4E-58-8A-40-40-11-B7-BA-0D-F2-F4-3F-27-C3-4E-52-D5-5D-55-AB-8B-5B-53-DE-DF-3F-12-6E-2E-A6-D5-36-F3-E0-5F-D5-3F-BB-D3-FB-A7-7D-F5-F7-7F-5D-F9-3E-FD-3C-CB-A2-7F-5E-9A-7B-DD-5C-5E-FF-CE-A7-77-A1-7E-E6-FF-2E-7F-CF-D3-BB-E9-EF-FF-9B-FD-58-AB-7F-D5-74-5B-3E-1F-CF-E6-FE-9E-0A-50-42-DC-F5-5D-E2-D1-6F-12-6F-78-C2-F0-C9-1C-89-32-85-C8-55-9F-56-4F-60-15-1F-46-AC-A5-E1-C1-47-16-98-8E-D5-E3-90-7D-6E-35-30-7F-05-CB-AA-35-98-05-E6-E9-55-6C-F2-AA-9D-69-65-CF-4E-64-21-30-98-3B-D8-A0-43-35-E3-9F-08-F9-5F-66-FE-6E-84-1B-D0-FA-89-86-03-5E-6A-10-36-0E-5A-78-86-81-8B-12-14-D9-E1-11-68-F7-40-63-13-C4-6C-90-C3-76-0E-16-A5-E7-84-65-00-66-75-CE-92-73-AA-D6-CA-1C-C4-46-FD-91-A3-B1-DA-3C-06-E7-F9-D0-15-7E-26-3D-78-B4-39-F5-32-D6-97-EA-33-B6-25-2B-CE-77-E2-F6-82-2D-67-FB-88-66-25-1D-97-03-5F-2F-A2-D9-2B-88-37-13-36-B0-39-CA-F9-61-00-79-C3-56-5F-C7-60-E2-32-2C-9C-9E-5A-F1-CA-60-E1-42-79-9D-70-4C-E5-24-87-B1-89-D8-E5-3D-74-41-27-57-2F-3F-63-63-FF-E7-B4-B7-B0-BF-56-02-DD-8B-D7-89-DA-F3-2E-EA-65-1E-16-EF-2D-FE-8D-0F-36-A6-F7-B1-11-F9-A8-0A-1C-5D-F3-48-74-A2-1F-AD-BF-B9-2F-A4-69-34-EA-34-D6-27-A6-6D-71-8A-6E-03-FC-74-7E-45-54-FA-28-F6-2C-0F-37-67-F4-34-48-3F-2B-33-B6-7E-18-AB-E8-D7-89-D2-33-59-6D-FD-45-6F-3E-66-79-58-46-16-2F-84-9E-15-06-B3-CA-F8-38-E0-36-BE-37-D4-62-75-A4-6E-BE-3F-FC-76-57-D0-DE-4F-8D-E5-1D-91-B0-93-28-3C-FD-39-B4-14-6C-28-85-D3-E6-C6-E6-55-3B-97-13-1B-F8-38-58-51-38-CA-F8-25-AB-38-00-2E-FB-F4-CD-26-B8-EB-03-31-FF-A0-E1-0D-39-69-42-60-EC-D5-EA-8E-D2-49-1E-EB-43-C3-37-7A-9B-33-BD-D7-72-D9-A9-75-FF-A1-F3-08-77-27-16-5E-06-1B-36-22-B4-12-E7-10-56-3B-9C-F7-DB-9E-DC-4C-F0-FA-4D-5E-55-B3-41-FF-C7-C8-9B-2D-18-2A-83-58-17-65-46-ED-00-23-13-47-56-D5-CA-CA-AE-55-38-33-6D-9E-55-7A-A8-2C-BC-2A-E4-45-17-07-BC-32-70-B4-69-22-60-ED-91-AF-F2-06-D8-64-03-C8-68-62-6B-11-0F-56-27-D9-DA-D0-F5-78-7B-AD-76-64-BC-47-6A-04-11-1A-72-08-9F-C6-84-BD-43-2C-45-C6-89-C9-DB-65-D1-EF-2B-29-C8-5D-F4-7E-11-1C-D6-CD-1E-54-0C-39-45-35-B0-48-D4-93-D0-EF-9C-B5-D4-23-FD-AF-5D-F8-0C-80-FB-57-7E-2B-DC-A2-B2-DC-A1-08-EC-68-5A-7D-F8-47-73-FE-57-A6-D9-7E-EB-7D-1A-87-E5-B7-21-9F-B4-94-6B-ED-CE-5F-CD-59-6F-DC-60-DD-AB-DC-74-47-B9-75-7D-7E-75-3A-13-60-6A-CC-B7-4D-C6-72-53-EC-D9-41-E7-44-19-0B-32-F9-B6-AD-63-B0-EC-C4-A1-15-E2-2A-5C-75-BC-F8-2C-62-0D-FF-D4-DF-05-CB-67-83-77-7B-C9-29-33-7F-C0-AA-37-79-DE-C4-AB-BC-45-AC-5D-A7-A6-6E-76-EF-6F-6B-F7-65-27-46-2B-88-73-74-32-78-68-ED-0E-24-C2-DE-3C-42-F1-25-8C-BF-AA-B4-4E-D9-D1-60-D1-32-06-56-85-3E-17-5C-B2-D0-8E-D7-F2-53-02-4B-BD-FF-C2-3E-99-95-4D-6C-E4-ED-D0-93-6B-16-B4-7D-E9-D9-24-4D-F3-06-82-F1-09-C0-58-16-20-A7-22-2A-2E-DB-12-36-67-90-C6-51-14-E0-E8-FE-2A-EF-4D-1A-CC-88-C9-12-56-D9-43-3F-2E-35-FA-3A-EB-25-2F-8C-1D-CC-8D-2A-53-79-19-69-99-17-EE-4D-12-E3-F4-30-5A-C2-04-7D-1C-E8-66-AF-9F-F4-1B-85-E5-9C-5B-65-C4-C6-FC-2B-47-C3-22-53-FC-9E-FC-3C-F6-EB-3F-C7-E0-C5-5F-AF-AE-C7-03-7A-7C-99-65-B7-77-E8-39-13-CB-8A-44-76-BC-AA-D4-CC-21-4F-04-16-9D-7B-1A-5B-E3-7C-56-A3-49-F4-49-B9-89-FF-3B-CD-E0-EA-61-69-50-FE-3A-DF-95-A1-2F-99-00-59-32-71-58-42-BE-C6-21-0A-93-48-BD-AA-25-9B-32-38-6E-71-AC-F4-D3-AC-E7-D5-10-C1-B2-05-E0-3D-54-81-D2-A6-D7-44-CD-AB-3A-83-40-8D-37-F2-9D-1D-89-6A-57-9B-5F-DE-2F-0D-9D-A7-D0-C4-F7-85-EB-5F-4D-C5-DE-05-9C-B2-E6-31-50-90-4D-72-2D-59-62-7F-99-9D-0F-A0-F8-4A-F3-CB-CB-2E-5C-0D-A8-AC-06-9B-E1-5F-77-6B-08-36-0E-E2-44-74-59-05-95-7E-A0-EA-3B-ED-BB-28-B7-F1-B1-B7-AC-D7-9D-46-82-DD-0C-CA-EE-40-86-C9-C5-38-C0-CD-62-EA-C9-62-17-74-63-76-12-3C-C7-CE-64-CC-50-FE-EC-B2-EA-F0-53-F4-AD-6D-84-61-B9-54-4F-F5-2D-22-1A-B7-DA-36-B2-A2-F1-D8-30-81-5A-C5-F6-15-7F-84-5E-09-C1-DA-47-9B-CD-C1-97-B6-B3-6F-71-46-C3-31-3D-D0-1D-43-8B-15-7A-86-20-2C-84-C2-5A-63-4C-EA-76-5A-EA-0E-17-3D-E4-1C-73-99-40-D9-20-E2-D0-00-D2-53-96-86-E1-1B-FA-75-9A-40-8C-EE-B1-47-25-75-31-2C-61-1F-C7-5C-CA-5B-E3-C0-D7-2E-73-5D-E1-F3-82-66-10-F2-5D-5C-B7-35-F4-C8-C6-F5-33-9C-A2-9A-73-3F-D0-03-9E-D2-8A-77-C4-A5-38-FB-83-2F-0F-4D-EB-2C-41-CA-55-18-62-D7-F7-05-A5-69-CA-01-84-03-83-57-87-49-0A-E5-BE-94-1E-CC-78-E6-CA-14-D6-08-D5-1B-17-86-90-CA-10-A2-D8-D3-32-21-8B-1A-BB-90-87-50-A4-3C-53-12-F9-1A-B5-08-FB-DD-0D-73-04-21-4E-B3-2E-F3-8E-70-56-C7-A4-46-98-10-BD-97-45-0C-A7-13-7B-03-C4-BD-F3-87-20-12-D3-3B-AE-6F-D9-4A-02-A4-25-A4-53-CF-24-F3-8F-AE-D4-7D-CD-BF-52-27-10-39-9D-43-18-C1-D0-87-69-A8-FB-3E-9B-44-42-B4-86-38-A2-90-8A-B8-90-12-9C-20-AC-19-8A-D1-C3-71-42-8A-D3-3E-F5-E4-F1-05-60-9C-20-EA-D4-29-F3-45-EA-42-98-C9-95-1C-A0-FC-42-07-12-72-9B-B4-F4-C3-14-72-89-86-87-6C-11-09-38-DA-60-E8-FA-2F-8E-64-1C-CB-24-D1-ED-D5-B9-E2-88-50-41-25-4F-B5-EF-79-CD-57-43-A2-DE-CC-9D-FC-98-7A-41-30-19-E2-18-0D-A8-C6-C4-41-D0-CF-F6-10-5E-F9-44-23-25-82-D7-00-39-14-FA-94-97-03-CD-06-99-29-07-D5-AA-81-94-50-8C-21-0A-E5-34-B5-9A-4F-F6-C2-E9-F3-B4-BB-69-7A-9C-4A-50-3F-86-0C-12-67-84-1C-52-2E-A9-BE-42-C9-A1-A7-F4-F7-46-6F-8A-6F-12-11-52-0A-B5-AE-6B-6F-97-C0-96-B5-35-92-9C-16-A1-2C-52-18-23-2F-DE-5A-D0-47-F5-E4-90-EB-87-1C-22-3E-F1-EE-B4-82-18-3A-67-1F-C2-94-C2-A2-80-31-D0-5D-7C-83-2D-6E-28-75-43-77-8A-0B-94-D9-11-27-78-8B-F9-1D-C9-FF-00-37-12-B7-2F-AA-08-00-00", + "request": "client=QANd68ji1L&format=json&meta=recordingids&batch=1&duration.0=85&fingerprint.0=AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ", "response": "{\"fingerprints\": [{\"index\": \"0\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}], \"status\": \"ok\"}" }, { - "requestContent": "1F-8B-08-00-00-00-00-00-00-03-15-54-CB-B6-B2-BC-12-7C-9B-6F-C6-59-5E-22-C2-60-0F-72-83-84-8B-21-20-2A-4E-58-8A-40-40-11-B7-BA-0D-F2-F4-3F-27-C3-4E-52-D5-5D-55-AB-8B-5B-53-DE-DF-3F-12-6E-2E-A6-D5-36-F3-E0-5F-D5-3F-BB-D3-FB-A7-7D-F5-F7-7F-5D-F9-3E-FD-3C-CB-A2-7F-5E-9A-7B-DD-5C-5E-FF-CE-A7-77-A1-7E-E6-FF-2E-7F-CF-D3-BB-E9-EF-FF-9B-FD-58-AB-7F-D5-74-5B-3E-1F-CF-E6-FE-9E-0A-50-42-DC-F5-5D-E2-D1-6F-12-6F-78-C2-F0-C9-1C-89-32-85-C8-55-9F-56-4F-60-15-1F-46-AC-A5-E1-C1-47-16-98-8E-D5-E3-90-7D-6E-35-30-7F-05-CB-AA-35-98-05-E6-E9-55-6C-F2-AA-9D-69-65-CF-4E-64-21-30-98-3B-D8-A0-43-35-E3-9F-08-F9-5F-66-FE-6E-84-1B-D0-FA-89-86-03-5E-6A-10-36-0E-5A-78-86-81-8B-12-14-D9-E1-11-68-F7-40-63-13-C4-6C-90-C3-76-0E-16-A5-E7-84-65-00-66-75-CE-92-73-AA-D6-CA-1C-C4-46-FD-91-A3-B1-DA-3C-06-E7-F9-D0-15-7E-26-3D-78-B4-39-F5-32-D6-97-EA-33-B6-25-2B-CE-77-E2-F6-82-2D-67-FB-88-66-25-1D-97-03-5F-2F-A2-D9-2B-88-37-13-36-B0-39-CA-F9-61-00-79-C3-56-5F-C7-60-E2-32-2C-9C-9E-5A-F1-CA-60-E1-42-79-9D-70-4C-E5-24-87-B1-89-D8-E5-3D-74-41-27-57-2F-3F-63-63-FF-E7-B4-B7-B0-BF-56-02-DD-8B-D7-89-DA-F3-2E-EA-65-1E-16-EF-2D-FE-8D-0F-36-A6-F7-B1-11-F9-A8-0A-1C-5D-F3-48-74-A2-1F-AD-BF-B9-2F-A4-69-34-EA-34-D6-27-A6-6D-71-8A-6E-03-FC-74-7E-45-54-FA-28-F6-2C-0F-37-67-F4-34-48-3F-2B-33-B6-7E-18-AB-E8-D7-89-D2-33-59-6D-FD-45-6F-3E-66-79-58-46-16-2F-84-9E-15-06-B3-CA-F8-38-E0-36-BE-37-D4-62-75-A4-6E-BE-3F-FC-76-57-D0-DE-4F-8D-E5-1D-91-B0-93-28-3C-FD-39-B4-14-6C-28-85-D3-E6-C6-E6-55-3B-97-13-1B-F8-38-58-51-38-CA-F8-25-AB-38-00-2E-FB-F4-CD-26-B8-EB-03-31-FF-A0-E1-0D-39-69-42-60-EC-D5-EA-8E-D2-49-1E-EB-43-C3-37-7A-9B-33-BD-D7-72-D9-A9-75-FF-A1-F3-08-77-27-16-5E-06-1B-36-22-B4-12-E7-10-56-3B-9C-F7-DB-9E-DC-4C-F0-FA-4D-5E-55-B3-41-FF-C7-C8-9B-2D-18-2A-83-58-17-65-46-ED-00-23-13-47-56-D5-CA-CA-AE-55-38-33-6D-9E-55-7A-A8-2C-BC-2A-E4-45-17-07-BC-32-70-B4-69-22-60-ED-91-AF-F2-06-D8-64-03-C8-68-62-6B-11-0F-56-27-D9-DA-D0-F5-78-7B-AD-76-64-BC-47-6A-04-11-1A-72-08-9F-C6-84-BD-43-2C-45-C6-89-C9-DB-65-D1-EF-2B-29-C8-5D-F4-7E-11-1C-D6-CD-1E-54-0C-39-45-35-B0-48-D4-93-D0-EF-9C-B5-D4-23-FD-AF-5D-F8-0C-80-FB-57-7E-2B-DC-A2-B2-DC-A1-08-EC-68-5A-7D-F8-47-73-FE-57-A6-D9-7E-EB-7D-1A-87-E5-B7-21-9F-B4-94-6B-ED-CE-5F-CD-59-6F-DC-60-DD-AB-DC-74-47-B9-75-7D-7E-75-3A-13-60-6A-CC-B7-4D-C6-72-53-EC-D9-41-E7-44-19-0B-32-F9-B6-AD-63-B0-EC-C4-A1-15-E2-2A-5C-75-BC-F8-2C-62-0D-FF-D4-DF-05-CB-67-83-77-7B-C9-29-33-7F-C0-AA-37-79-DE-C4-AB-BC-45-AC-5D-A7-A6-6E-76-EF-6F-6B-F7-65-27-46-2B-88-73-74-32-78-68-ED-0E-24-C2-DE-3C-42-F1-25-8C-BF-AA-B4-4E-D9-D1-60-D1-32-06-56-85-3E-17-5C-B2-D0-8E-D7-F2-53-02-4B-BD-FF-C2-3E-99-95-4D-6C-E4-ED-D0-93-6B-16-B4-7D-E9-D9-24-4D-F3-06-82-F1-09-C0-58-16-20-A7-22-2A-2E-DB-12-36-67-90-C6-51-14-E0-E8-FE-2A-EF-4D-1A-CC-88-C9-12-56-D9-43-3F-2E-35-FA-3A-EB-25-2F-8C-1D-CC-8D-2A-53-79-19-69-99-17-EE-4D-12-E3-F4-30-5A-C2-04-7D-1C-E8-66-AF-9F-F4-1B-85-E5-9C-5B-65-C4-C6-FC-2B-47-C3-22-53-FC-9E-FC-3C-F6-EB-3F-C7-E0-C5-5F-AF-AE-C7-03-7A-7C-99-65-B7-77-E8-39-13-CB-8A-44-76-BC-AA-D4-CC-21-4F-04-16-9D-7B-1A-5B-E3-7C-56-A3-49-F4-49-B9-89-FF-3B-CD-E0-EA-61-69-50-FE-3A-DF-95-A1-2F-99-00-59-32-71-58-42-BE-C6-21-0A-93-48-BD-AA-25-9B-32-38-6E-71-AC-F4-D3-AC-E7-D5-10-C1-B2-05-E0-3D-54-81-D2-A6-D7-44-CD-AB-3A-83-40-8D-37-F2-9D-1D-89-6A-57-9B-5F-DE-2F-0D-9D-A7-D0-C4-F7-85-EB-5F-4D-C5-DE-05-9C-B2-E6-31-50-90-4D-72-2D-59-62-7F-99-9D-0F-A0-F8-4A-F3-CB-CB-2E-5C-0D-A8-AC-06-9B-E1-5F-77-6B-08-36-0E-E2-44-74-59-05-95-7E-A0-EA-3B-ED-BB-28-B7-F1-B1-B7-AC-D7-9D-46-82-DD-0C-CA-EE-40-86-C9-C5-38-C0-CD-62-EA-C9-62-17-74-63-76-12-3C-C7-CE-64-CC-50-FE-EC-B2-EA-F0-53-F4-AD-6D-84-61-B9-54-4F-F5-2D-22-1A-B7-DA-36-B2-A2-F1-D8-30-81-5A-C5-F6-15-7F-84-5E-09-C1-DA-47-9B-CD-C1-97-B6-B3-6F-71-46-C3-31-3D-D0-1D-43-8B-15-7A-86-20-2C-84-C2-5A-63-4C-EA-76-5A-EA-0E-17-3D-E4-1C-73-99-40-D9-20-E2-D0-00-D2-53-96-86-E1-1B-FA-75-9A-40-8C-EE-B1-47-25-75-31-2C-61-1F-C7-5C-CA-5B-E3-C0-D7-2E-73-5D-E1-F3-82-66-10-F2-5D-5C-B7-35-F4-C8-C6-F5-33-9C-A2-9A-73-3F-D0-03-9E-D2-8A-77-C4-A5-38-FB-83-2F-0F-4D-EB-2C-41-CA-55-18-62-D7-F7-05-A5-69-CA-01-84-03-83-57-87-49-0A-E5-BE-94-1E-CC-78-E6-CA-14-D6-08-D5-1B-17-86-90-CA-10-A2-D8-D3-32-21-8B-1A-BB-90-87-50-A4-3C-53-12-F9-1A-B5-08-FB-DD-0D-73-04-21-4E-B3-2E-F3-8E-70-56-C7-A4-46-98-10-BD-97-45-0C-A7-13-7B-03-C4-BD-F3-87-20-12-D3-3B-AE-6F-D9-4A-02-A4-25-A4-53-CF-24-F3-8F-AE-D4-7D-CD-BF-52-27-10-39-9D-43-18-C1-D0-87-69-A8-FB-3E-9B-44-42-B4-86-38-A2-90-8A-B8-90-12-9C-20-AC-19-8A-D1-C3-71-42-8A-D3-3E-F5-E4-F1-05-60-9C-20-EA-D4-29-F3-45-EA-42-98-C9-95-1C-A0-FC-42-07-12-72-9B-B4-F4-C3-14-72-89-86-87-6C-11-09-38-DA-60-E8-FA-2F-8E-64-1C-CB-24-D1-ED-D5-B9-E2-88-50-41-25-4F-B5-EF-79-CD-57-43-A2-DE-CC-9D-FC-98-7A-41-30-19-E2-18-0D-A8-C6-C4-41-D0-CF-F6-10-5E-F9-44-23-25-82-D7-00-39-14-FA-94-97-03-CD-06-99-29-07-D5-AA-81-94-50-8C-21-0A-E5-34-B5-9A-4F-F6-C2-E9-F3-B4-BB-69-7A-9C-4A-50-3F-86-0C-12-67-84-1C-52-2E-A9-BE-42-C9-A1-A7-F4-F7-46-6F-8A-6F-12-11-52-0A-B5-AE-6B-6F-97-C0-96-B5-35-92-9C-16-A1-2C-52-18-23-2F-DE-5A-D0-47-F5-E4-90-EB-87-1C-22-3E-F1-EE-B4-82-18-3A-67-1F-C2-94-C2-A2-80-31-D0-5D-7C-83-2D-6E-28-75-43-77-8A-0B-94-D9-11-27-78-8B-F9-1D-C9-FF-00-37-12-B7-2F-AA-08-00-00", - "response": "{\"fingerprints\": [{\"index\": \"0\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}], \"status\": \"ok\"}" + "request": "client=QANd68ji1L&format=json&meta=recordingids&batch=1&duration.0=85&fingerprint.0=AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ&duration.1=85&fingerprint.1=AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ", + "response": "{\"fingerprints\": [{\"index\": \"0\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}, {\"index\": \"1\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}], \"status\": \"ok\"}" }, { - "requestContent": "1F-8B-08-00-00-00-00-00-00-03-ED-96-CB-B6-AA-30-12-86-DF-E6-CC-E8-E5-25-22-0E-CE-20-37-48-40-0C-01-51-71-C2-52-04-02-8A-B8-BD-05-78-FA-A6-47-7D-19-F7-70-67-46-42-AA-2A-7F-FD-AB-D6-97-DD-AA-FC-FE-FE-2B-E1-E6-62-5A-75-35-5D-FF-29-DA-67-73-7A-FF-AD-5F-ED-FD-4F-93-BF-4F-7F-9F-79-D6-3E-2F-D5-BD-AC-2E-AF-3F-E7-D3-3B-53-7F-A7-7F-2E-9F-E7-E9-5D-B5-F7-7F-4C-FE-5A-8B-3F-C5-78-9A-3F-1F-CF-EA-FE-1E-37-A0-84-B8-69-9B-C8-A5-7D-14-6E-78-C4-F0-C9-1C-88-32-85-48-55-1B-17-4F-60-65-5F-46-AC-B9-E1-C2-47-B2-36-6D-AB-C5-3E-FB-DE-4A-60-FE-08-96-14-4B-30-59-9B-A7-57-B6-49-8B-7A-A2-D5-6A-72-22-33-81-C1-D4-C6-06-ED-8A-09-FF-06-C8-EB-99-F9-B3-11-CE-9A-96-4F-D4-1D-F0-5C-03-BF-B2-D1-CC-35-0C-9C-E5-20-4B-0E-8F-B5-76-0E-34-34-41-C8-3A-D9-6D-A7-60-96-BB-B6-9F-AF-C1-A4-4C-59-74-8E-D5-52-99-9D-D8-A8-0F-39-1A-8B-CD-A3-B3-9F-0F-5D-E0-67-D4-82-47-9D-52-37-61-6D-AE-BE-43-9D-B3-EC-7C-27-4E-2B-D8-7C-B2-0F-68-92-D3-61-DE-F1-E5-2C-98-BC-D6-E1-66-8C-0D-56-1C-A5-FC-D0-81-B4-62-8B-DE-36-98-B8-74-33-BB-A5-56-B8-30-98-3F-53-6E-23-6C-53-D9-D1-61-A8-02-76-79-77-CD-BA-91-8B-97-97-B0-A1-FD-D8-F5-CD-6F-AF-85-40-F7-EC-75-A2-AB-69-13-B4-32-F5-B3-F7-16-FF-84-87-15-A6-F7-A1-12-E9-A0-32-1C-5C-D3-40-34-A2-1D-AC-CF-D4-13-D2-34-2A-75-1A-CA-13-D3-2B-71-0A-6E-1D-FC-36-5E-41-54-FC-C8-F6-2C-F5-37-67-F4-34-48-3B-C9-13-B6-7C-18-8B-E0-C7-0E-E2-33-59-6C-BD-59-6B-3E-26-A9-9F-07-16-CF-84-9E-64-06-B3-F2-F0-D8-E1-3A-BC-57-D4-62-65-A0-6E-9E-D7-FD-34-57-50-DF-4F-95-E5-1E-91-58-45-81-7F-FA-D8-34-17-AC-CB-85-5D-A7-C6-E6-55-DA-97-13-EB-F8-D0-59-81-3F-C8-F0-25-8B-70-0D-1C-F6-6D-AB-CD-FA-AE-0F-C4-FC-40-C3-ED-52-52-F9-C0-D8-AB-C5-1D-C5-A3-3C-D6-97-FA-6F-F4-36-27-7A-AF-E5-BC-51-CB-F6-4B-A7-01-6E-4E-CC-BF-74-2B-58-09-DF-8A-EC-83-5F-EC-70-DA-6E-5B-72-33-C1-EB-27-7A-15-D5-06-FD-2B-46-5A-6D-41-57-18-C4-BA-28-33-A8-3B-18-98-38-B0-8A-5A-16-AB-52-F9-13-73-C5-93-42-77-85-85-17-99-BC-E8-EC-80-17-06-0E-36-55-00-AC-3D-F2-54-5A-81-15-D9-00-32-98-D8-9A-85-9D-D5-48-B6-34-74-39-DC-5E-8B-1D-19-EE-81-1A-40-80-BA-14-C2-A7-31-C6-DE-21-16-23-E3-C4-E4-ED-32-6B-F7-85-14-E4-2E-5A-2F-5B-1F-96-D5-1E-14-0C-D9-59-D1-B1-40-94-A3-D0-EF-94-D5-D4-25-ED-CF-2A-F3-18-00-F7-5E-F6-05-AE-51-9E-EF-50-00-76-34-2E-BE-FC-AB-39-FF-E4-71-B2-DF-BA-DF-CA-66-E9-AD-4B-47-2D-E5-52-3B-D3-57-75-D6-1B-67-BD-6C-55-6A-3A-83-DC-3A-1E-BF-DA-8D-09-30-35-A6-DB-2A-61-A9-29-F6-EC-A0-53-A2-8C-19-19-FB-B6-2D-43-30-6F-C4-A1-16-E2-2A-1C-75-BC-78-2C-60-15-FF-96-FD-8C-A5-93-CE-BD-BD-E4-E8-99-0F-B0-CA-4D-9A-56-E1-22-AD-11-AB-97-B1-A9-AB-DD-BB-AF-57-6D-DE-88-C1-5A-87-29-3A-19-DC-B7-76-07-12-60-77-1A-A0-F0-E2-87-BD-CA-AD-53-72-34-58-30-0F-81-55-A0-EF-05-E7-CC-5F-85-4B-F9-CD-81-A5-DE-1F-BF-8D-26-79-15-1A-69-DD-B5-E4-9A-AC-EB-36-77-57-24-8E-D3-0A-82-E1-09-C0-90-67-20-A5-22-C8-2E-DB-1C-56-67-10-87-41-B0-C6-C1-FD-95-DF-AB-78-3D-21-26-8B-58-B1-EA-DA-61-AE-51-6F-2F-E7-3C-33-76-30-35-8A-44-A5-79-A0-65-9A-39-37-49-8C-D3-C3-A8-09-13-F4-71-A0-9B-BD-7E-D2-3E-F0-F3-29-B7-F2-80-0D-69-2F-07-C3-22-A3-FD-9E-FC-3C-B4-CB-8F-6D-F0-EC-D3-AA-EB-F1-80-1E-3D-B3-56-F5-1D-BA-F6-98-65-41-82-55-B8-28-D4-C4-26-4F-04-66-8D-73-1A-6A-E3-7C-56-83-49-F4-49-39-91-F7-33-BE-C1-D1-DD-DC-A0-FC-75-BE-2B-43-5F-12-01-92-68-CC-61-09-F9-1A-BA-C0-8F-02-F5-2A-E6-6C-F4-E0-B0-C5-A1-D2-4F-B3-9C-16-5D-00-F3-1A-80-77-57-AC-95-36-DD-2A-A8-5E-C5-19-AC-D5-70-23-FD-E4-48-54-BD-D8-FC-F0-76-6E-E8-34-86-26-BE-CF-1C-EF-6A-2A-F6-CE-E0-E8-35-97-81-8C-6C-A2-6B-CE-A2-55-CF-56-69-07-B2-5E-9A-3D-CF-1B-7F-D1-A1-BC-E8-56-0C-FF-38-5B-43-B0-A1-13-27-A2-F3-62-5D-E8-07-2A-FA-71-DE-05-E9-0A-1F-5B-CB-7A-DD-69-20-D8-CD-A0-EC-0E-A4-1F-5D-8C-03-DC-CC-C6-9A-2C-76-41-37-B6-8A-D6-CF-A1-31-19-33-94-37-B9-2C-1A-FC-14-6D-BD-32-7C-3F-9F-AB-A7-EA-B3-80-86-B5-5E-19-49-56-B9-AC-1B-83-5A-D9-F6-15-7E-85-5E-08-C1-EA-47-9D-4C-41-4F-EB-49-9F-9D-51-77-8C-0F-74-C7-D0-6C-81-9E-3E-F0-33-A1-B0-D6-18-93-B2-1E-87-BA-CD-45-0B-39-C7-5C-46-50-56-88-D8-74-0D-E9-29-89-7D-FF-0D-BD-32-8E-20-46-F7-D0-A5-92-3A-18-E6-B0-0D-43-2E-E5-AD-B2-E1-6B-97-38-8E-F0-78-46-13-08-F9-2E-2C-EB-12-BA-64-E3-78-09-8E-51-C9-B9-B7-D6-1D-1E-DD-8A-77-C4-A1-38-F9-C0-97-8B-C6-71-16-21-E5-28-0C-B1-E3-79-82-D2-38-E6-00-C2-8E-C1-AB-CD-24-85-72-9F-4B-17-26-3C-71-64-0C-4B-84-CA-8D-03-7D-48-A5-0F-51-E8-6A-19-91-59-89-1D-C8-7D-28-62-9E-28-89-3C-8D-6A-84-BD-E6-86-39-82-10-C7-49-93-B8-47-38-29-43-52-22-4C-88-DE-CB-2C-84-E3-0A-DD-0E-E2-D6-FE-20-88-C4-F8-1F-D7-B7-64-21-01-D2-12-D2-B1-66-92-78-47-47-EA-B6-E4-BD-D4-11-44-76-63-13-46-30-F4-60-EC-EB-B6-4D-46-91-10-2D-21-0E-28-A4-22-CC-A4-04-27-08-4B-86-42-F4-B0-6D-9F-E2-B8-8D-5D-79-7C-01-18-46-88-DA-65-CC-3C-11-3B-10-26-72-21-3B-28-7B-68-43-42-6E-A3-96-9E-1F-43-2E-51-F7-90-35-22-6B-8E-36-18-3A-DE-8B-23-19-86-32-8A-74-7D-B5-AF-38-20-54-50-C9-63-ED-B9-6E-D5-6B-48-D4-9B-39-63-3F-C6-5A-10-8C-BA-30-44-1D-2A-31-B1-11-F4-92-3D-84-57-3E-A6-91-12-C1-EB-1A-D9-14-7A-94-E7-1D-4D-3A-99-28-1B-95-AA-82-94-50-8C-21-F2-E5-F8-6A-35-1D-DB-0B-C7-CB-E3-EC-A6-F1-71-DC-82-FA-D1-25-90-D8-03-E4-90-72-49-F5-15-4A-0E-5D-A5-FB-1B-BD-29-BE-89-84-4F-29-D4-BA-2C-DD-5D-04-6B-56-97-48-72-9A-F9-32-8B-61-88-DC-70-6B-41-0F-95-63-87-1C-CF-E7-10-F1-31-EF-4E-2B-88-A1-7D-F6-20-8C-29-CC-32-18-02-DD-84-37-58-E3-8A-52-C7-77-46-BB-40-99-1C-71-84-B7-98-DF-91-FC-37-72-4C-FF-17-39-A6-BF-C8-F1-8B-1C-BF-C8-F1-8B-1C-BF-C8-F1-8B-1C-BF-C8-F1-8B-1C-FF-77-E4-98-FD-9D-FE-17-71-CC-FE-FE-C7-D7-3F-01-83-40-10-23-44-11-00-00", + "request": "client=QANd68ji1L&format=json&meta=recordingids&batch=1&duration.0=1&fingerprint.0=fingerprint", + "response": "{\"error\": {\"code\": 3, \"message\": \"invalid fingerprint\"}, \"status\": \"error\"}" + }, + { + "request": "client=QANd68ji1L&format=json&meta=recordingids&batch=1&duration.0=85&fingerprint.0=AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ&duration.1=85&fingerprint.1=AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ&duration.2=1&fingerprint.2=fingerprint", "response": "{\"fingerprints\": [{\"index\": \"0\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}, {\"index\": \"1\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}], \"status\": \"ok\"}" }, { - "requestContent": "1F-8B-08-00-00-00-00-00-00-03-4D-C9-3B-0A-80-30-0C-00-D0-DB-64-14-BB-88-4B-06-77-11-3C-42-EC-47-53-6C-2A-69-BC-BF-1D-1D-1F-CF-DF-1C-C5-70-5F-B6-30-CD-99-DD-0A-A9-6A-21-C3-DC-AA-40-89-46-A8-D1-57-0D-2C-27-87-06-07-99-BF-D0-41-78-95-8C-AB-0C-23-8E-90-7A-46-7D-94-C5-BA-7F-FA-00-8B-C4-FF-AB-5E-00-00-00", + "request": "client=QANd68ji1L&format=json&meta=recordingids&batch=1&duration.0=0&fingerprint.0=fingerprint", "response": "{\"error\": {\"code\": 2, \"message\": \"missing required parameter \\\"duration.0\\\"\"}, \"status\": \"error\"}" }, { - "requestContent": "1F-8B-08-00-00-00-00-00-00-03-ED-96-CB-D2-B2-BA-12-86-EF-E6-9F-B1-CA-43-44-1C-FC-83-9C-20-01-31-04-44-C5-09-A5-08-04-14-F1-F3-14-E0-EA-37-7B-B4-AB-F6-78-0D-BF-0C-73-E8-EE-BC-FD-56-D7-93-DD-AA-FC-FE-FE-2B-E1-E6-62-5A-75-35-5D-FF-29-DA-67-73-7A-FF-AD-5F-ED-FD-4F-93-BF-4F-7F-9F-79-D6-3E-2F-D5-BD-AC-2E-AF-3F-E7-D3-3B-53-7F-A7-7F-2E-9F-E7-E9-5D-B5-F7-7F-26-7F-AD-C5-9F-62-3C-CD-9F-8F-67-75-7F-8F-1B-50-42-DC-B4-4D-E4-D2-3E-0A-37-3C-62-F8-64-0E-44-99-42-A4-AA-8D-8B-27-B0-B2-2F-23-D6-DC-70-E1-23-59-9B-B6-D5-62-9F-7D-6F-25-30-7F-04-4B-8A-25-98-AC-CD-D3-2B-DB-A4-45-3D-D1-6A-35-39-91-99-C0-60-6A-63-83-76-C5-84-7F-03-E4-F5-CC-FC-D9-08-67-4D-CB-27-EA-0E-78-AE-81-5F-D9-68-E6-1A-06-CE-72-90-25-87-C7-5A-3B-07-1A-9A-20-64-9D-EC-B6-53-30-CB-5D-DB-CF-D7-60-52-A6-2C-3A-C7-6A-A9-CC-4E-6C-D4-87-1C-8D-C5-E6-D1-D9-CF-87-2E-F0-33-6A-C1-A3-4E-A9-9B-B0-36-57-DF-A1-CE-59-76-BE-13-A7-15-6C-3E-D9-07-34-C9-E9-30-EF-F8-72-16-4C-5E-EB-70-33-C6-06-2B-8E-52-7E-E8-40-5A-B1-45-6F-1B-4C-5C-BA-99-DD-52-2B-5C-18-CC-9F-29-B7-11-B6-A9-EC-E8-30-54-01-BB-BC-BB-66-DD-C8-C5-CB-4B-D8-D0-7E-EC-FA-E6-B7-D7-42-A0-7B-F6-3A-D1-D5-B4-09-5A-99-FA-D9-7B-8B-7F-C2-C3-0A-D3-FB-50-89-74-50-19-0E-AE-69-20-1A-D1-0E-D6-67-EA-09-69-1A-95-3A-0D-E5-89-E9-95-38-05-B7-0E-7E-1B-AF-20-2A-7E-64-7B-96-FA-9B-33-7A-1A-A4-9D-E4-09-5B-3E-8C-45-F0-63-07-F1-99-2C-B6-DE-AC-35-1F-93-D4-CF-03-8B-67-42-4F-32-83-59-79-78-EC-70-1D-DE-2B-6A-B1-32-50-37-CF-EB-7E-9A-2B-A8-EF-A7-CA-72-8F-48-AC-A2-C0-3F-7D-6C-9A-0B-D6-E5-C2-AE-53-63-F3-2A-ED-CB-89-75-7C-E8-AC-C0-1F-64-F8-92-45-B8-06-0E-FB-B6-D5-66-7D-D7-07-62-7E-A0-E1-76-29-A9-7C-60-EC-D5-E2-8E-E2-51-1E-EB-4B-FD-37-7A-9B-13-BD-D7-72-DE-A8-65-FB-A5-D3-00-37-27-E6-5F-BA-15-AC-84-6F-45-F6-C1-2F-76-38-6D-B7-2D-B9-99-E0-F5-13-BD-8A-6A-83-FE-1B-23-AD-B6-A0-2B-0C-62-5D-94-19-D4-1D-0C-4C-1C-58-45-2D-8B-55-A9-FC-89-B9-E2-49-A1-BB-C2-C2-8B-4C-5E-74-76-C0-0B-03-07-9B-2A-00-D6-1E-79-2A-AD-C0-8A-6C-00-19-4C-6C-CD-C2-CE-6A-24-5B-1A-BA-1C-6E-AF-C5-8E-0C-F7-40-0D-20-40-5D-0A-E1-D3-18-63-EF-10-8B-91-71-62-F2-76-99-B5-FB-42-0A-72-17-AD-97-AD-0F-CB-6A-0F-0A-86-EC-AC-E8-58-20-CA-51-E8-77-CA-6A-EA-92-F6-67-95-79-0C-80-7B-2F-FB-02-D7-28-CF-77-28-00-3B-1A-17-5F-FE-D5-9C-7F-F2-38-D9-6F-DD-6F-65-B3-F4-D6-A5-A3-96-72-A9-9D-E9-AB-3A-EB-8D-B3-5E-B6-2A-35-9D-41-6E-1D-8F-5F-ED-C6-04-98-1A-D3-6D-95-B0-D4-14-7B-76-D0-29-51-C6-8C-8C-7D-DB-96-21-98-37-E2-50-0B-71-15-8E-3A-5E-3C-16-B0-8A-7F-CB-7E-C6-D2-49-E7-DE-5E-72-F4-CC-07-58-E5-26-4D-AB-70-91-D6-88-D5-CB-D8-D4-D5-EE-DD-D7-AB-36-6F-C4-60-AD-C3-14-9D-0C-EE-5B-BB-03-09-B0-3B-0D-50-78-F1-C3-5E-E5-D6-29-39-1A-2C-98-87-C0-2A-D0-F7-82-73-E6-AF-C2-A5-FC-E6-C0-52-EF-8F-DF-46-93-BC-0A-8D-B4-EE-5A-72-4D-D6-75-9B-BB-2B-12-C7-69-05-C1-F0-04-60-C8-33-90-52-11-64-97-6D-0E-AB-33-88-C3-20-58-E3-E0-FE-CA-EF-55-BC-9E-10-93-45-AC-58-75-ED-30-D7-A8-B7-97-73-9E-19-3B-98-1A-45-A2-D2-3C-D0-32-CD-9C-9B-24-C6-E9-61-D4-84-09-FA-38-D0-CD-5E-3F-69-1F-F8-F9-94-5B-79-C0-86-B4-97-83-61-91-D1-7E-4F-7E-1E-DA-E5-C7-36-78-F6-69-D5-F5-78-40-8F-9E-59-AB-FA-0E-5D-7B-CC-B2-20-C1-2A-5C-14-6A-62-93-27-02-B3-C6-39-0D-B5-71-3E-AB-C1-24-FA-A4-9C-C8-FB-19-FF-E0-E8-6E-6E-50-FE-3A-DF-95-A1-2F-89-00-49-34-E6-B0-84-7C-0D-5D-E0-47-81-7A-15-73-36-7A-70-D8-E2-50-E9-A7-59-4E-8B-2E-80-79-0D-C0-BB-2B-D6-4A-9B-6E-15-54-AF-E2-0C-D6-6A-B8-91-7E-72-24-AA-5E-6C-7E-78-3B-37-74-1A-43-13-DF-67-8E-77-35-15-7B-67-70-F4-9A-CB-40-46-36-D1-35-67-D1-AA-67-AB-B4-03-59-2F-CD-9E-E7-8D-BF-E8-50-5E-74-2B-86-7F-9C-AD-21-D8-D0-89-13-D1-79-B1-2E-F4-03-15-FD-38-EF-82-74-85-8F-AD-65-BD-EE-34-10-EC-66-50-76-07-D2-8F-2E-C6-01-6E-66-63-4D-16-BB-A0-1B-5B-45-EB-E7-D0-98-8C-19-CA-9B-5C-16-0D-7E-8A-B6-5E-19-BE-9F-CF-D5-53-F5-59-40-C3-5A-AF-8C-24-AB-5C-D6-8D-41-AD-6C-FB-0A-BF-42-2F-84-60-F5-A3-4E-A6-A0-A7-F5-A4-CF-CE-A8-3B-C6-07-BA-63-68-B6-40-4F-1F-F8-99-50-58-6B-8C-49-59-8F-43-DD-E6-A2-85-9C-63-2E-23-28-2B-44-6C-BA-86-F4-94-C4-BE-FF-86-5E-19-47-10-A3-7B-E8-52-49-1D-0C-73-D8-86-21-97-F2-56-D9-F0-B5-4B-1C-47-78-3C-A3-09-84-7C-17-96-75-09-5D-B2-71-BC-04-C7-A8-E4-DC-5B-EB-0E-8F-6E-C5-3B-E2-50-9C-7C-E0-CB-45-E3-38-8B-90-72-14-86-D8-F1-3C-41-69-1C-73-00-61-C7-E0-D5-66-92-42-B9-CF-A5-0B-13-9E-38-32-86-25-42-E5-C6-81-3E-A4-D2-87-28-74-B5-8C-C8-AC-C4-0E-E4-3E-14-31-4F-94-44-9E-46-35-C2-5E-73-C3-1C-41-88-E3-A4-49-DC-23-9C-94-21-29-11-26-44-EF-65-16-C2-71-85-6E-07-71-6B-7F-10-44-62-BC-C7-F5-2D-59-48-80-B4-84-74-AC-99-24-DE-D1-91-BA-2D-79-2F-75-04-91-DD-D8-84-11-0C-3D-18-FB-BA-6D-93-51-24-44-4B-88-03-0A-A9-08-33-29-C1-09-C2-92-A1-10-3D-6C-DB-A7-38-6E-63-57-1E-5F-00-86-11-A2-76-19-33-4F-C4-0E-84-89-5C-C8-0E-CA-1E-DA-90-90-DB-A8-A5-E7-C7-90-4B-D4-3D-64-8D-C8-9A-A3-0D-86-8E-F7-E2-48-86-A1-8C-22-5D-5F-ED-2B-0E-08-15-54-F2-58-7B-AE-5B-F5-1A-12-F5-66-CE-D8-8F-B1-16-04-A3-2E-0C-51-87-4A-4C-6C-04-BD-64-0F-E1-95-8F-69-A4-44-F0-BA-46-36-85-1E-E5-79-47-93-4E-26-CA-46-A5-AA-20-25-14-63-88-7C-39-FE-5A-4D-C7-F6-C2-F1-F1-38-BB-69-7C-1C-B7-A0-7E-74-09-24-F6-00-39-A4-5C-52-7D-85-92-43-57-E9-FE-46-6F-8A-6F-22-E1-53-0A-B5-2E-4B-77-17-C1-9A-D5-25-92-9C-66-BE-CC-62-18-22-37-DC-5A-D0-43-E5-D8-21-C7-F3-39-44-7C-CC-BB-D3-0A-62-68-9F-3D-08-63-0A-B3-0C-86-40-37-E1-0D-D6-B8-A2-D4-F1-9D-D1-2E-50-26-47-1C-E1-2D-E6-77-24-FF-87-1C-D3-FF-47-8E-E9-2F-72-FC-22-C7-2F-72-FC-22-C7-2F-72-FC-22-C7-2F-72-FC-22-C7-BF-84-1C-FF-01-01-46-31-86-1D-11-00-00", + "request": "client=QANd68ji1L&format=json&meta=recordingids&batch=1&duration.0=85&fingerprint.0=AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ&duration.1=85&fingerprint.1=AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ", "response": "{\"fingerprints\": [{\"index\": \"0\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}, {\"index\": \"1\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}], \"status\": \"ok\"}" }, { - "requestContent": "1F-8B-08-00-00-00-00-00-00-03-4D-C9-31-0E-80-20-0C-00-C0-DF-30-1A-59-8C-4B-07-77-63-E2-13-90-16-2D-91-62-4A-FD-BF-8C-8E-97-8B-37-93-18-EC-CB-86-D3-9C-D9-AF-2E-55-2D-C1-20-B7-2A-AE-90-05-50-8A-55-91-E5-64-6C-EE-08-16-2F-F0-0E-5F-0D-C6-55-86-B1-23-F5-24-7D-94-C5-BA-7F-FA-00-CA-DF-73-C5-5E-00-00-00", - "response": "{\"error\": {\"code\": 3, \"message\": \"invalid fingerprint\"}, \"status\": \"error\"}" + "request": "client=QANd68ji1L&format=json&meta=recordingids&batch=1&duration.0=85&fingerprint.0=AQACmomSJEySRNISHCa6zDh6OO_hoUfr48cvHD83-JApYL6F8oCMHvlg46qOHYf740L6ascN_fj0wh90aD2OC41FC-Exf0IvPBKyH6qNOGLEgrBxXC3w4MiFB2J--Cce4cYXpLwGXER64RHxQxT142eJFMeL40g_HSbUh7h6xONhuDZ-5NpxFrpwfCrSo4pj_EJYHoehvzjeHcbnDGoOH30WPEYeEz3xI72P0sLRNRHx49IB_IXx4_iH5yF-HOdx2FoE8R5-HM2hJmOF6hFSXziPHdtxmLmQ5sKYHzouFjlMokfOBncsaE91mPoQ_MctTCqRX9CEnziO_zhcCPk_POmOoz8u1KOQ6-ihazgaHw9OaPlxAvmKfDhUpcWH_MNbBr-Do0eYH7p-5PqFPUbD5TK2o6p0_MeP8IcOw0c-H8eRZxCjRniE8HgPhlKKxqmk4jnai8JZBO9SPMauFEeOHxeOFj_-NsgFdaHxIzx8PMzQRsQfRL4GHvoiNLnwXD6uA-Jx_DiM4-Wh5nBUIXx8vEMtBt60wWwQ3mh7ovE1PCmaHMdx9AiOM8SFXMfVC_oToDl64sqSsfiNB-Wh5_iT4xf-D8dh6PjxAP6CP8fjQf9ghM069IYfwxf8C5cQdwcXC5-CPNiP48WBKh_i49DN4Dz6C82Rx8mQH7-wgzls5VDznPhz4PBx_AAr-PjxVBHUB-aHQld2oWfQODnOoKcLX7iW4fHBFcfxHPOgH_Mt_HjEJDoq9cKH44nyQyfCjBeeVBP4VEUfvIvwIIueUYWTJviFH_lx_EeOQ7wG1sibwNGL7oh_6GzQTGKIkFm64CE-1TiYH_6OWHXw_Dh-2Dp0_TgR43mOXjOOkOGhZdKHPHiIvgy2H_0xJlsQX9Cu48gN__iR5_jBHj7U6wiVtyj9oemOz8LR_Ba-IM8VXDPCJ1PBRdMRyhe8aYZ-HP3R48fBvdCeHM9R7Qve48htuMoS0eiR-_jxoDkYLjoeJ9DUU_iA4zr44zec4_EOPcdTeAib4URPPLCPnseniUL0D6HSHf9xoz3wByF73Ic-VA_-fYh_ePwQ_cGlQD-ap-jDHOEpXENWwrEyPMe1I8ePHz_yQz-8D_-NrIbzo7uF-IcuohkZXBpyH89jnAJFHSH5DP9R5fh0FDrB42mGazj-bbhz6DwahGSKq_jxGwx3-EIsbnh-wdYO4YSPHz8OQszxPMSPhsf3HDl6zTCRhwr6g1fxPAej44txfLhw6JiPisfb4LhzlDy0ZDhj5NqIo3-w_UA6Cn2GKk6hHtcAH7-JH4cDNSkeHS9yH9_x4cyQ6yIemM5xBefx9HCqGT-OHzxOaDwefLfwpBfyC-EP_9CZo88snEPOHl-EHn4QMSd-XAN2PAe8HdBlH9SLrzm6HH-hK0d5mCrOoj9-MMe3hrhycPERjw9-YciJHx-EP8cTsRvOw5OOHjpjY14yEj0ycbBxZUXEVHB25BrM4McOhCwwCCDgjAQAFIOoAIICIQSAQiBDFELAEaYUMMtAKgUSACBnRJEQEGCAeAoRRIQQliFAsVYGGOKIcEYAAIVRgjgAJDNGKYCUBgIIKLwxCBHjCVDGECYuAsJBDhUSBhGhCACGKKOEEUUI4AAxHAkFHQEAQWeQJAYIYGQUAgBBgNGAMAEQMABRJwQSD2gCGAIMAOUIYhQBKwBjBCKmlCIBAACUYmYJZA0gRDgBCDDwWQcRAAAARJxACoFuBABOAACIwlY5Q4BwQAEAJDDYKZGQwogIyQwSABFmFDHDCAKAUMwooYAQABEgACPEAEORcQQ4aAAgHBRBpFFMECUoUJQZs4ARSBEFgUHKOUGAAYQ5QxAQyAFADDlAKgKMUAIQBxpQjBDLIBNCAGKsIBQRRQSSwjkFkCPDEOEQIUwKJJiywADhtHGAEaKAUBASxRRBxBgCDFBAKYWAAkIAYQQQBAkLBFEAKEIexEYxQYhFBghiAEDECCABMQAACh1QiBAgCDBUIEUZQAAAwpxYADFzAIAEIQEwkAQIAJhwylElhINSOMEEAwwggJVSAjHjgBQIEcMQcUARBJRT8AKBgAMAGKMIABIxQYVwhACAFbKAAUEAccAR4wmRlAjCiEEGMGIcEAQYZCSCTCInBQ", + "response": "{\"fingerprints\": [{\"index\": \"0\", \"results\": [{\"id\": \"a9b004fe-e161-417c-9f9e-443e4525334d\", \"recordings\": [{\"id\": \"209a4536-97ac-4e8a-aff1-1d39d029044b\"}, {\"id\": \"30f3f33e-8d0c-4e69-8539-cbd701d18f28\"}], \"score\": 0.940997}, {\"id\": \"fe0a9bec-2633-4c37-89be-b5d295b68a00\", \"score\": 0.763876}, {\"id\": \"18eab869-51dc-4948-83f7-4d8d441d5a1b\", \"score\": 0.490447}]}], \"status\": \"ok\"}" } ] diff --git a/src/NzbDrone.Core.Test/HealthCheck/Checks/DotnetVersionCheckFixture.cs b/src/NzbDrone.Core.Test/HealthCheck/Checks/DotnetVersionCheckFixture.cs deleted file mode 100644 index 2f7386b48..000000000 --- a/src/NzbDrone.Core.Test/HealthCheck/Checks/DotnetVersionCheckFixture.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using NUnit.Framework; -using NzbDrone.Common.EnvironmentInfo; -using NzbDrone.Core.HealthCheck.Checks; -using NzbDrone.Core.Test.Framework; - -namespace NzbDrone.Core.Test.HealthCheck.Checks -{ - [TestFixture] - public class DotnetVersionCheckFixture : CoreTest - { - private void GivenOutput(string version) - { - WindowsOnly(); - - Mocker.GetMock() - .SetupGet(s => s.Version) - .Returns(new Version(version)); - } - - [TestCase("4.7.2")] - [TestCase("4.8")] - public void should_return_ok(string version) - { - GivenOutput(version); - - Subject.Check().ShouldBeOk(); - } - - [TestCase("4.6.2")] - [TestCase("4.7")] - [TestCase("4.7.1")] - public void should_return_notice(string version) - { - GivenOutput(version); - - Subject.Check().ShouldBeNotice(); - } - - public void should_return_warning(string version) - { - GivenOutput(version); - - Subject.Check().ShouldBeWarning(); - } - - [TestCase("4.5")] - [TestCase("4.5.2")] - [TestCase("4.6.1")] - public void should_return_error(string version) - { - GivenOutput(version); - - Subject.Check().ShouldBeError(); - } - - [Test] - public void should_return_ok_for_net462_on_Win1511() - { - Mocker.GetMock() - .SetupGet(v => v.Version) - .Returns("10.0.14392"); - - GivenOutput("4.6.2"); - - Subject.Check().ShouldBeOk(); - } - } -} diff --git a/src/NzbDrone.Core.Test/Lidarr.Core.Test.csproj b/src/NzbDrone.Core.Test/Lidarr.Core.Test.csproj index 260dc13a5..7413fa2ea 100644 --- a/src/NzbDrone.Core.Test/Lidarr.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/Lidarr.Core.Test.csproj @@ -1,12 +1,20 @@  - net462 + net462;netcoreapp3.0 + + + + + - + + + + diff --git a/src/NzbDrone.Core.Test/ParserTests/FingerprintingServiceFixture.cs b/src/NzbDrone.Core.Test/ParserTests/FingerprintingServiceFixture.cs index 7ca575cdd..6f6508f4f 100644 --- a/src/NzbDrone.Core.Test/ParserTests/FingerprintingServiceFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/FingerprintingServiceFixture.cs @@ -3,11 +3,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; +using System.Text; using FluentAssertions; using Moq; using Newtonsoft.Json; using NUnit.Framework; -using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Extensions; using NzbDrone.Common.Http; using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; @@ -22,7 +23,7 @@ namespace NzbDrone.Core.Test.ParserTests { public class FingerPrintTest { - public string RequestContent { get; set; } + public string Request { get; set; } public string Response { get; set; } } @@ -30,7 +31,7 @@ namespace NzbDrone.Core.Test.ParserTests public void UseAcoustidResponses() { // responses were generated by editing HttpClient to write out the content bytes as a string - // using BitConverter.ToString(request.ContentData) + // using System.Text.Encoding.UTF8.GetString(request.ContentData.Decompress()); var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Fingerprinting", "AcoustidResponses.json"); var responses = JsonConvert.DeserializeObject>(File.ReadAllText(path)); @@ -38,16 +39,13 @@ namespace NzbDrone.Core.Test.ParserTests { Mocker.GetMock() .Setup(o => o.Post( - It.Is(v => - v.Url.Equals(new HttpUri("https://api.acoustid.org/v2/lookup")) && - v.Headers.Contains(new KeyValuePair("Content-Encoding", "gzip")) && - v.Headers.ContentType == "application/x-www-form-urlencoded" && - // Skip past the first bit of gzip header which varies by OS: - // http://www.onicos.com/staff/iz/formats/gzip.html - BitConverter.ToString(v.ContentData).Substring(31) == response.RequestContent.Substring(31) - ))) + It.Is(v => + v.Url.Equals(new HttpUri("https://api.acoustid.org/v2/lookup")) && + v.Headers.Contains(new KeyValuePair("Content-Encoding", "gzip")) && + v.Headers.ContentType == "application/x-www-form-urlencoded" && + Encoding.UTF8.GetString(v.ContentData.Decompress()) == response.Request + ))) .Returns(r => new HttpResponse(new HttpResponse(r, new HttpHeader(), response.Response))); - } } diff --git a/src/NzbDrone.Core.Test/UpdateTests/UpdatePackageProviderFixture.cs b/src/NzbDrone.Core.Test/UpdateTests/UpdatePackageProviderFixture.cs index c2af4ede7..3a88bda18 100644 --- a/src/NzbDrone.Core.Test/UpdateTests/UpdatePackageProviderFixture.cs +++ b/src/NzbDrone.Core.Test/UpdateTests/UpdatePackageProviderFixture.cs @@ -25,6 +25,7 @@ namespace NzbDrone.Core.Test.UpdateTests } [Test] + [Platform(Exclude="NetCore")] public void finds_update_when_version_lower() { UseRealHttp(); diff --git a/src/NzbDrone.Core/Blacklisting/BlacklistService.cs b/src/NzbDrone.Core/Blacklisting/BlacklistService.cs index 731391fdd..9df920ac1 100644 --- a/src/NzbDrone.Core/Blacklisting/BlacklistService.cs +++ b/src/NzbDrone.Core/Blacklisting/BlacklistService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using NzbDrone.Common.Extensions; using NzbDrone.Core.Datastore; diff --git a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs index 1067af9cd..27165ac11 100644 --- a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs +++ b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Collections.Generic; using NzbDrone.Common.Disk; using NzbDrone.Common.Http; -using NzbDrone.Common.Extensions; using NzbDrone.Core.MediaFiles.TorrentInfo; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Configuration; @@ -12,6 +11,7 @@ using NLog; using FluentValidation.Results; using System.Net; using NzbDrone.Core.RemotePathMappings; +using NzbDrone.Common.Extensions; namespace NzbDrone.Core.Download.Clients.Deluge { diff --git a/src/NzbDrone.Core/Download/Clients/Hadouken/HadoukenProxy.cs b/src/NzbDrone.Core/Download/Clients/Hadouken/HadoukenProxy.cs index 8d2fc9238..fc684b375 100644 --- a/src/NzbDrone.Core/Download/Clients/Hadouken/HadoukenProxy.cs +++ b/src/NzbDrone.Core/Download/Clients/Hadouken/HadoukenProxy.cs @@ -12,7 +12,7 @@ namespace NzbDrone.Core.Download.Clients.Hadouken { HadoukenSystemInfo GetSystemInfo(HadoukenSettings settings); HadoukenTorrent[] GetTorrents(HadoukenSettings settings); - IDictionary GetConfig(HadoukenSettings settings); + IReadOnlyDictionary GetConfig(HadoukenSettings settings); string AddTorrentFile(HadoukenSettings settings, byte[] fileContent); void AddTorrentUri(HadoukenSettings settings, string torrentUrl); void RemoveTorrent(HadoukenSettings settings, string downloadId); @@ -42,9 +42,9 @@ namespace NzbDrone.Core.Download.Clients.Hadouken return GetTorrents(result.Torrents); } - public IDictionary GetConfig(HadoukenSettings settings) + public IReadOnlyDictionary GetConfig(HadoukenSettings settings) { - return ProcessRequest>(settings, "webui.getSettings"); + return ProcessRequest>(settings, "webui.getSettings"); } public string AddTorrentFile(HadoukenSettings settings, byte[] fileContent) diff --git a/src/NzbDrone.Core/Lidarr.Core.csproj b/src/NzbDrone.Core/Lidarr.Core.csproj index 8b2709f18..168574e23 100644 --- a/src/NzbDrone.Core/Lidarr.Core.csproj +++ b/src/NzbDrone.Core/Lidarr.Core.csproj @@ -1,16 +1,18 @@  - net462 + net462;netcoreapp3.0 + + - + @@ -22,7 +24,7 @@ - + diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs index 4bdb6b2d6..711d5d429 100644 --- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs +++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs @@ -6,8 +6,8 @@ using System.Linq; using System.Text.RegularExpressions; using NLog; using NzbDrone.Common.Cache; -using NzbDrone.Common.EnsureThat; using NzbDrone.Common.Extensions; +using NzbDrone.Common.EnsureThat; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Profiles.Releases; using NzbDrone.Core.Qualities; diff --git a/src/NzbDrone.Core/Parser/FingerprintingService.cs b/src/NzbDrone.Core/Parser/FingerprintingService.cs index 981c6dc77..271e7df0f 100644 --- a/src/NzbDrone.Core/Parser/FingerprintingService.cs +++ b/src/NzbDrone.Core/Parser/FingerprintingService.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.IO.Compression; using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -318,17 +317,6 @@ namespace NzbDrone.Core.Parser return null; } - private static byte[] Compress(byte[] data) - { - using (var compressedStream = new MemoryStream()) - using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) - { - zipStream.Write(data, 0, data.Length); - zipStream.Close(); - return compressedStream.ToArray(); - } - } - public void Lookup(List tracks, double threshold) { if (!IsSetup()) @@ -365,7 +353,7 @@ namespace NzbDrone.Core.Parser } // they prefer a gzipped body - httpRequest.SetContent(Compress(Encoding.UTF8.GetBytes(sb.ToString()))); + httpRequest.SetContent(Encoding.UTF8.GetBytes(sb.ToString()).Compress()); httpRequest.Headers.Add("Content-Encoding", "gzip"); httpRequest.Headers.ContentType = "application/x-www-form-urlencoded"; httpRequest.SuppressHttpError = true; diff --git a/src/NzbDrone.Core/Update/InstallUpdateService.cs b/src/NzbDrone.Core/Update/InstallUpdateService.cs index 9ca2cc128..4f66d286a 100644 --- a/src/NzbDrone.Core/Update/InstallUpdateService.cs +++ b/src/NzbDrone.Core/Update/InstallUpdateService.cs @@ -132,6 +132,7 @@ namespace NzbDrone.Core.Update _diskTransferService.TransferFolder(_appFolderInfo.GetUpdateClientFolder(), updateSandboxFolder, TransferMode.Move, false); // Set executable flag on update app +<<<<<<< HEAD if (OsInfo.IsOsx) { _diskProvider.SetPermissions(_appFolderInfo.GetUpdateClientExePath(updatePackage.Version), "0755", null, null); @@ -141,6 +142,17 @@ namespace NzbDrone.Core.Update _logger.ProgressInfo("Lidarr will restart shortly."); _processProvider.Start(_appFolderInfo.GetUpdateClientExePath(updatePackage.Version), GetUpdaterArgs(updateSandboxFolder)); +======= + if (OsInfo.IsOsx || (OsInfo.IsLinux && PlatformInfo.IsNetCore)) + { + _diskProvider.SetPermissions(_appFolderInfo.GetUpdateClientExePath(updatePackage.Runtime), "0755", null, null); + } + + _logger.Info("Starting update client {0}", _appFolderInfo.GetUpdateClientExePath(updatePackage.Runtime)); + _logger.ProgressInfo("Lidarr will restart shortly."); + + _processProvider.Start(_appFolderInfo.GetUpdateClientExePath(updatePackage.Runtime), GetUpdaterArgs(updateSandboxFolder)); +>>>>>>> 4346c76d4... New: Multi target net framework 4.6.2 and net core 3.0 } private void EnsureValidBranch(UpdatePackage package) diff --git a/src/NzbDrone.Core/Update/UpdatePackage.cs b/src/NzbDrone.Core/Update/UpdatePackage.cs index 1583280cb..016398d0f 100644 --- a/src/NzbDrone.Core/Update/UpdatePackage.cs +++ b/src/NzbDrone.Core/Update/UpdatePackage.cs @@ -1,5 +1,5 @@ using System; - +using NzbDrone.Common.EnvironmentInfo; namespace NzbDrone.Core.Update { @@ -12,5 +12,6 @@ namespace NzbDrone.Core.Update public UpdateChanges Changes { get; set; } public string Hash { get; set; } public string Branch { get; set; } + public PlatformType Runtime { get; set; } } } diff --git a/src/NzbDrone.Core/Update/UpdatePackageProvider.cs b/src/NzbDrone.Core/Update/UpdatePackageProvider.cs index fbbafacfc..caa2185a7 100644 --- a/src/NzbDrone.Core/Update/UpdatePackageProvider.cs +++ b/src/NzbDrone.Core/Update/UpdatePackageProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using NzbDrone.Common.Cloud; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Http; @@ -34,6 +35,8 @@ namespace NzbDrone.Core.Update .Resource("/update/{branch}") .AddQueryParam("version", currentVersion) .AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant()) + .AddQueryParam("arch", RuntimeInformation.OSArchitecture) + .AddQueryParam("runtime", PlatformInfo.Platform.ToString().ToLowerInvariant()) .AddQueryParam("runtimeVer", _platformInfo.Version) .SetSegment("branch", branch); @@ -70,4 +73,4 @@ namespace NzbDrone.Core.Update return updates.Resource; } } -} \ No newline at end of file +} diff --git a/src/NzbDrone.Host.Test/Lidarr.Host.Test.csproj b/src/NzbDrone.Host.Test/Lidarr.Host.Test.csproj index ffcea820d..f033a2aff 100644 --- a/src/NzbDrone.Host.Test/Lidarr.Host.Test.csproj +++ b/src/NzbDrone.Host.Test/Lidarr.Host.Test.csproj @@ -1,12 +1,21 @@  - net462 + net462;netcoreapp3.0 + + + + + + + + + - + diff --git a/src/NzbDrone.Host/Lidarr.Host.csproj b/src/NzbDrone.Host/Lidarr.Host.csproj index e10f3fb81..d7d1c95c4 100644 --- a/src/NzbDrone.Host/Lidarr.Host.csproj +++ b/src/NzbDrone.Host/Lidarr.Host.csproj @@ -1,13 +1,19 @@ - + - net462 + net462;netcoreapp3.0 + Library - - + + + + + + + diff --git a/src/NzbDrone.Host/WebHost/Middleware/SignalRMiddleware.cs b/src/NzbDrone.Host/WebHost/Middleware/SignalRMiddleware.cs index d595b7281..a31c1e3ce 100644 --- a/src/NzbDrone.Host/WebHost/Middleware/SignalRMiddleware.cs +++ b/src/NzbDrone.Host/WebHost/Middleware/SignalRMiddleware.cs @@ -15,6 +15,7 @@ namespace NzbDrone.Host.Middleware private readonly IContainer _container; private readonly Logger _logger; private static string API_KEY; + private static string URL_BASE; public int Order => 1; public SignalRMiddleware(IContainer container, @@ -24,6 +25,7 @@ namespace NzbDrone.Host.Middleware _container = container; _logger = logger; API_KEY = configFileProvider.ApiKey; + URL_BASE = configFileProvider.UrlBase; } public void Attach(IApplicationBuilder appBuilder) @@ -53,11 +55,17 @@ namespace NzbDrone.Host.Middleware } }); - appBuilder.UseSignalR(routes => +#if NETCOREAPP3_0 + appBuilder.UseEndpoints(x => { - routes.MapHub("/signalr/messages"); + x.MapHub(URL_BASE + "/signalr/messages"); }); - +#else + appBuilder.UseSignalR(x => + { + x.MapHub("/signalr/messages"); + }); +#endif // This is a side effect of haing multiple IoC containers, TinyIoC and whatever // Kestrel/SignalR is using. Ideally we'd have one IoC container, but that's non-trivial with TinyIoC // TODO: Use a single IoC container if supported for TinyIoC or if we switch to another system (ie Autofac). diff --git a/src/NzbDrone.Host/WebHost/WebHostController.cs b/src/NzbDrone.Host/WebHost/WebHostController.cs index 986447da7..718fb0cfb 100644 --- a/src/NzbDrone.Host/WebHost/WebHostController.cs +++ b/src/NzbDrone.Host/WebHost/WebHostController.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog; @@ -77,6 +76,10 @@ namespace NzbDrone.Host }); } }) + .ConfigureKestrel(serverOptions => + { + serverOptions.AllowSynchronousIO = true; + }) .ConfigureLogging(logging => { logging.AddProvider(new NLogLoggerProvider()); @@ -86,15 +89,23 @@ namespace NzbDrone.Host { services .AddSignalR() - .AddJsonProtocol(options => +#if !NETCOREAPP3_0 + .AddJsonProtocol( +#else + .AddNewtonsoftJsonProtocol( +#endif + options => { options.PayloadSerializerSettings = Json.GetSerializerSettings(); }); }) .Configure(app => { - app.UsePathBase(_configFileProvider.UrlBase); +#if NETCOREAPP3_0 + app.UseRouting(); +#endif app.Properties["host.AppName"] = BuildInfo.AppName; + app.UsePathBase(_configFileProvider.UrlBase); foreach (var middleWare in _middlewares.OrderBy(c => c.Order)) { diff --git a/src/NzbDrone.Integration.Test/ApiTests/FileSystemFixture.cs b/src/NzbDrone.Integration.Test/ApiTests/FileSystemFixture.cs index a94071764..f49d86dbf 100644 --- a/src/NzbDrone.Integration.Test/ApiTests/FileSystemFixture.cs +++ b/src/NzbDrone.Integration.Test/ApiTests/FileSystemFixture.cs @@ -8,6 +8,7 @@ using NzbDrone.Common.Disk; using System.Reflection; using System.IO; using System.Collections.Generic; +using NzbDrone.Common; namespace NzbDrone.Integration.Test.ApiTests { @@ -61,7 +62,7 @@ namespace NzbDrone.Integration.Test.ApiTests result.Directories.Should().NotBeNullOrEmpty(); result.Files.Should().NotBeNullOrEmpty(); - result.Files.Should().Contain(v => v.Path == _file && v.Type == FileSystemEntityType.File); + result.Files.Should().Contain(v => PathEqualityComparer.Instance.Equals(v.Path, _file) && v.Type == FileSystemEntityType.File); } [Test] diff --git a/src/NzbDrone.Integration.Test/ApiTests/RootFolderFixture.cs b/src/NzbDrone.Integration.Test/ApiTests/RootFolderFixture.cs index ae3f50ae9..7030b29d8 100644 --- a/src/NzbDrone.Integration.Test/ApiTests/RootFolderFixture.cs +++ b/src/NzbDrone.Integration.Test/ApiTests/RootFolderFixture.cs @@ -15,6 +15,7 @@ namespace NzbDrone.Integration.Test.ApiTests } [Test] + [Ignore("SignalR on CI seems unstable")] public void should_add_and_delete_root_folders() { ConnectSignalR().Wait(); diff --git a/src/NzbDrone.Integration.Test/Lidarr.Integration.Test.csproj b/src/NzbDrone.Integration.Test/Lidarr.Integration.Test.csproj index a65ea4b76..162b53554 100644 --- a/src/NzbDrone.Integration.Test/Lidarr.Integration.Test.csproj +++ b/src/NzbDrone.Integration.Test/Lidarr.Integration.Test.csproj @@ -1,10 +1,20 @@ - + - net462 + net462;netcoreapp3.0 + Library + + + + + + + + + diff --git a/src/NzbDrone.Libraries.Test/Lidarr.Libraries.Test.csproj b/src/NzbDrone.Libraries.Test/Lidarr.Libraries.Test.csproj index f4d526455..3bdd9a6ab 100644 --- a/src/NzbDrone.Libraries.Test/Lidarr.Libraries.Test.csproj +++ b/src/NzbDrone.Libraries.Test/Lidarr.Libraries.Test.csproj @@ -1,7 +1,16 @@  - net462 + net462;netcoreapp3.0 + + + + + + + + + diff --git a/src/NzbDrone.Mono.Test/Lidarr.Mono.Test.csproj b/src/NzbDrone.Mono.Test/Lidarr.Mono.Test.csproj index c04c9dd3a..c882fa8b0 100644 --- a/src/NzbDrone.Mono.Test/Lidarr.Mono.Test.csproj +++ b/src/NzbDrone.Mono.Test/Lidarr.Mono.Test.csproj @@ -1,17 +1,29 @@  - net462 + net462;netcoreapp3.0 + + + + + + + + + + + + + + - - - ..\Libraries\Mono.Posix.dll - - PreserveNewest diff --git a/src/NzbDrone.Mono/Lidarr.Mono.csproj b/src/NzbDrone.Mono/Lidarr.Mono.csproj index b55247a38..19a270fdc 100644 --- a/src/NzbDrone.Mono/Lidarr.Mono.csproj +++ b/src/NzbDrone.Mono/Lidarr.Mono.csproj @@ -1,17 +1,22 @@  - net462 + net462;netcoreapp3.0 - + - - + + + + + + - - ..\Libraries\Mono.Posix.dll - + diff --git a/src/NzbDrone.SignalR/Lidarr.SignalR.csproj b/src/NzbDrone.SignalR/Lidarr.SignalR.csproj index ee4f0d725..a34df9c4e 100644 --- a/src/NzbDrone.SignalR/Lidarr.SignalR.csproj +++ b/src/NzbDrone.SignalR/Lidarr.SignalR.csproj @@ -1,8 +1,9 @@ - + - net462 + net462;netcoreapp3.0 + Library - + diff --git a/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs b/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs index 04e3de3a7..d63f07c60 100644 --- a/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs +++ b/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs @@ -9,6 +9,7 @@ using System.Runtime.CompilerServices; using Unity; using Moq; using Moq.Language.Flow; +using NzbDrone.Common.Composition; using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Test.Common.AutoMoq.Unity; @@ -150,6 +151,10 @@ namespace NzbDrone.Test.Common.AutoMoq RegisterPlatformLibrary(container); AddTheAutoMockingContainerExtensionToTheContainer(container); + +#if NETCOREAPP3_0 + ContainerBuilderBase.RegisterSQLiteResolver(); +#endif } private static void AddTheAutoMockingContainerExtensionToTheContainer(IUnityContainer container) diff --git a/src/NzbDrone.Test.Common/Lidarr.Test.Common.csproj b/src/NzbDrone.Test.Common/Lidarr.Test.Common.csproj index 009f3b32f..3f8c9211c 100644 --- a/src/NzbDrone.Test.Common/Lidarr.Test.Common.csproj +++ b/src/NzbDrone.Test.Common/Lidarr.Test.Common.csproj @@ -1,6 +1,6 @@  - net462 + net462;netcoreapp3.0 @@ -10,7 +10,7 @@ - + diff --git a/src/NzbDrone.Test.Common/NzbDroneRunner.cs b/src/NzbDrone.Test.Common/NzbDroneRunner.cs index de7752232..26535d0a3 100644 --- a/src/NzbDrone.Test.Common/NzbDroneRunner.cs +++ b/src/NzbDrone.Test.Common/NzbDroneRunner.cs @@ -33,17 +33,29 @@ namespace NzbDrone.Test.Common Directory.CreateDirectory(AppData); GenerateConfigFile(); - - var lidarrConsoleExe = OsInfo.IsWindows ? "Lidarr.Console.exe" : "Lidarr.exe"; - var frameworkFolder = "net462"; + + string lidarrConsoleExe; + if (OsInfo.IsWindows) + { + lidarrConsoleExe = "Lidarr.Console.exe"; + } + else if (PlatformInfo.IsMono) + { + lidarrConsoleExe = "Lidarr.exe"; + } + else + { + lidarrConsoleExe = "Lidarr"; + } if (BuildInfo.IsDebug) { + var frameworkFolder = PlatformInfo.IsNetCore ? "netcoreapp3.0" : "net462"; Start(Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "..", "_output", frameworkFolder, lidarrConsoleExe)); } else { - Start(Path.Combine("bin", lidarrConsoleExe)); + Start(Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "bin", lidarrConsoleExe)); } while (true) diff --git a/src/NzbDrone.Test.Dummy/Lidarr.Test.Dummy.csproj b/src/NzbDrone.Test.Dummy/Lidarr.Test.Dummy.csproj index 8c54330b4..55a744097 100644 --- a/src/NzbDrone.Test.Dummy/Lidarr.Test.Dummy.csproj +++ b/src/NzbDrone.Test.Dummy/Lidarr.Test.Dummy.csproj @@ -1,6 +1,6 @@  Exe - net462 + net462;netcoreapp3.0 diff --git a/src/NzbDrone.Update.Test/Lidarr.Update.Test.csproj b/src/NzbDrone.Update.Test/Lidarr.Update.Test.csproj index bda20ae5b..67c19d920 100644 --- a/src/NzbDrone.Update.Test/Lidarr.Update.Test.csproj +++ b/src/NzbDrone.Update.Test/Lidarr.Update.Test.csproj @@ -1,7 +1,16 @@  - net462 + net462;netcoreapp3.0 + + + + + + + + + diff --git a/src/NzbDrone.Update.Test/StartNzbDroneService.cs b/src/NzbDrone.Update.Test/StartNzbDroneService.cs index 439cac23a..7855c76b8 100644 --- a/src/NzbDrone.Update.Test/StartNzbDroneService.cs +++ b/src/NzbDrone.Update.Test/StartNzbDroneService.cs @@ -3,6 +3,7 @@ using Moq; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Extensions; using NzbDrone.Common.Processes; using NzbDrone.Test.Common; using NzbDrone.Update.UpdateEngine; @@ -27,7 +28,7 @@ namespace NzbDrone.Update.Test public void should_start_console_if_app_type_was_service_but_start_failed_because_of_permissions() { string targetFolder = "c:\\Lidarr\\".AsOsAgnostic(); - string targetProcess = "c:\\Lidarr\\Lidarr.Console.exe".AsOsAgnostic(); + string targetProcess = "c:\\Lidarr\\Lidarr.Console".AsOsAgnostic().ProcessNameToExe(); Mocker.GetMock().Setup(c => c.Start(ServiceProvider.SERVICE_NAME)).Throws(new InvalidOperationException()); diff --git a/src/NzbDrone.Update.Test/UpdateProviderStartFixture.cs b/src/NzbDrone.Update.Test/UpdateProviderStartFixture.cs deleted file mode 100644 index 6e6456b59..000000000 --- a/src/NzbDrone.Update.Test/UpdateProviderStartFixture.cs +++ /dev/null @@ -1,241 +0,0 @@ -/* -using System.Collections.Generic; -using System.IO; -using System.Linq; -using FizzWare.NBuilder; -using Moq; -using NUnit.Framework; -using NzbDrone.Common; -using NzbDrone.Common.Model; -using NzbDrone.Test.Common; -using NzbDrone.Update.UpdateEngine; - -namespace NzbDrone.Update.Test -{ - [TestFixture] - public class UpdateProviderStartFixture : TestBase - { - private const string UPDATE_FOLDER = @"C:\Temp\nzbdrone_update\nzbdrone\"; - private const string BACKUP_FOLDER = @"C:\Temp\nzbdrone_update\nzbdrone_backup\"; - private const string TARGET_FOLDER = @"C:\NzbDrone\"; - - Mock _IAppDirectoryInfo; - - - [SetUp] - public void Setup() - { - - _IAppDirectoryInfo = Mocker.GetMock(); - - _IAppDirectoryInfo.SetupGet(c => c.SystemTemp).Returns(@"C:\Temp\"); - - Mocker.GetMock() - .Setup(c => c.FolderExists(UPDATE_FOLDER)) - .Returns(true); - - Mocker.GetMock() - .Setup(c => c.FolderExists(TARGET_FOLDER)) - .Returns(true); - } - - private void WithInstalledService() - { - Mocker.GetMock() - .Setup(c => c.ServiceExist(ServiceProvider.NZBDRONE_SERVICE_NAME)) - .Returns(true); - } - - private void WithServiceRunning(bool state) - { - Mocker.GetMock() - .Setup(c => c.IsServiceRunning(ServiceProvider.NZBDRONE_SERVICE_NAME)).Returns(state); - } - - [Test] - public void should_stop_nzbdrone_service_if_installed_and_running() - { - WithInstalledService(); - WithServiceRunning(true); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - Mocker.GetMock().Verify(c => c.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME), Times.Once()); - } - - [Test] - public void should_not_stop_nzbdrone_service_if_installed_but_not_running() - { - WithInstalledService(); - WithServiceRunning(false); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - Mocker.GetMock().Verify(c => c.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME), Times.Never()); - } - - [Test] - public void should_not_stop_nzbdrone_service_if_service_isnt_installed() - { - - Mocker.Resolve().Start(TARGET_FOLDER); - - - Mocker.GetMock().Verify(c => c.Stop(It.IsAny()), Times.Never()); - } - - [Test] - public void should_kill_nzbdrone_process_if_running() - { - var proccesses = Builder.CreateListOfSize(2).Build().ToList(); - - Mocker.GetMock() - .Setup(c => c.GetProcessByName(ProcessProvider.NzbDroneProcessName)) - .Returns(proccesses); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - Mocker.GetMock().Verify(c => c.KillAll(ProcessProvider.NzbDroneProcessName), Times.Once()); - } - - [Test] - public void should_not_kill_nzbdrone_process_not_running() - { - Mocker.GetMock() - .Setup(c => c.GetProcessByName(ProcessProvider.NzbDroneProcessName)) - .Returns(new List()); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - Mocker.GetMock().Verify(c => c.Kill(It.IsAny()), Times.Never()); - } - - [Test] - public void should_create_backup_of_current_installation() - { - Mocker.GetMock() - .Setup(c => c.CopyDirectory(TARGET_FOLDER, BACKUP_FOLDER)); - - Mocker.Resolve().Start(TARGET_FOLDER); - } - - [Test] - public void should_copy_update_package_to_target() - { - Mocker.GetMock() - .Setup(c => c.CopyDirectory(UPDATE_FOLDER, TARGET_FOLDER)); - - Mocker.GetMock() - .Setup(c => c.DeleteFolder(UPDATE_FOLDER, true)); - - Mocker.Resolve().Start(TARGET_FOLDER); - } - - [Test] - public void should_restore_if_update_fails() - { - Mocker.GetMock() - .Setup(c => c.CopyDirectory(UPDATE_FOLDER, TARGET_FOLDER)) - .Throws(new IOException()); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - Mocker.GetMock() - .Verify(c => c.CopyDirectory(BACKUP_FOLDER, TARGET_FOLDER), Times.Once()); - ExceptionVerification.ExpectedFatals(1); - } - - [Test] - public void should_restart_service_if_service_was_running() - { - WithInstalledService(); - WithServiceRunning(true); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - VerifyServiceRestart(); - } - - [Test] - public void should_restart_process_if_service_was_not_running() - { - WithInstalledService(); - WithServiceRunning(false); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - VerifyProcessRestart(); - } - - [Test] - public void should_restart_service_if_service_was_running_and_update_fails() - { - WithInstalledService(); - WithServiceRunning(true); - - Mocker.GetMock() - .Setup(c => c.CopyDirectory(UPDATE_FOLDER, TARGET_FOLDER)) - .Throws(new IOException()); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - VerifyServiceRestart(); - ExceptionVerification.ExpectedFatals(1); - } - - [Test] - public void should_restart_process_if_service_was_not_running_and_update_fails() - { - WithInstalledService(); - WithServiceRunning(false); - - Mocker.GetMock() - .Setup(c => c.CopyDirectory(UPDATE_FOLDER, TARGET_FOLDER)) - .Throws(new IOException()); - - - Mocker.Resolve().Start(TARGET_FOLDER); - - - VerifyProcessRestart(); - ExceptionVerification.ExpectedFatals(1); - } - - private void VerifyServiceRestart() - { - Mocker.GetMock() - .Verify(c => c.Start(ServiceProvider.NZBDRONE_SERVICE_NAME), Times.Once()); - - Mocker.GetMock() - .Verify(c => c.Start(It.IsAny()), Times.Never()); - } - - private void VerifyProcessRestart() - { - Mocker.GetMock() - .Verify(c => c.Start(It.IsAny()), Times.Never()); - - Mocker.GetMock() - .Verify(c => c.Start(TARGET_FOLDER + "NzbDrone.exe"), Times.Once()); - } - - - } -} -*/ diff --git a/src/NzbDrone.Update/Lidarr.Update.csproj b/src/NzbDrone.Update/Lidarr.Update.csproj index 246ca8b4b..a71c04eef 100644 --- a/src/NzbDrone.Update/Lidarr.Update.csproj +++ b/src/NzbDrone.Update/Lidarr.Update.csproj @@ -1,7 +1,7 @@  WinExe - net462 + net462;netcoreapp3.0 diff --git a/src/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs b/src/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs index 9b7240ab2..6a2ffda00 100644 --- a/src/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs +++ b/src/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs @@ -114,7 +114,7 @@ namespace NzbDrone.Update.UpdateEngine _diskTransferService.MirrorFolder(_appFolderInfo.GetUpdatePackageFolder(), installationFolder); // Set executable flag on Lidarr app - if (OsInfo.IsOsx) + if (OsInfo.IsOsx || (OsInfo.IsLinux && PlatformInfo.IsNetCore)) { _diskProvider.SetPermissions(Path.Combine(installationFolder, "Lidarr"), "0755", null, null); } diff --git a/src/NzbDrone.Update/UpdateEngine/StartNzbDrone.cs b/src/NzbDrone.Update/UpdateEngine/StartNzbDrone.cs index cadd1ac15..1ae411bbe 100644 --- a/src/NzbDrone.Update/UpdateEngine/StartNzbDrone.cs +++ b/src/NzbDrone.Update/UpdateEngine/StartNzbDrone.cs @@ -3,6 +3,7 @@ using System.IO; using NLog; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Common.Extensions; using NzbDrone.Common.Processes; using IServiceProvider = NzbDrone.Common.IServiceProvider; @@ -62,12 +63,12 @@ namespace NzbDrone.Update.UpdateEngine private void StartWinform(string installationFolder) { - Start(installationFolder, "Lidarr.exe"); + Start(installationFolder, "Lidarr".ProcessNameToExe()); } private void StartConsole(string installationFolder) { - Start(installationFolder, "Lidarr.Console.exe"); + Start(installationFolder, "Lidarr.Console".ProcessNameToExe()); } private void Start(string installationFolder, string fileName) @@ -83,4 +84,4 @@ namespace NzbDrone.Update.UpdateEngine _processProvider.SpawnNewProcess(path, _startupContext.PreservedArguments); } } -} \ No newline at end of file +} diff --git a/src/NzbDrone.Windows.Test/DiskProviderTests/DiskProviderFixture.cs b/src/NzbDrone.Windows.Test/DiskProviderTests/DiskProviderFixture.cs index 847e03b92..ac1b5bb6f 100644 --- a/src/NzbDrone.Windows.Test/DiskProviderTests/DiskProviderFixture.cs +++ b/src/NzbDrone.Windows.Test/DiskProviderTests/DiskProviderFixture.cs @@ -25,15 +25,17 @@ namespace NzbDrone.Windows.Test.DiskProviderTests if (Directory.Exists(path)) { - var ds = Directory.GetAccessControl(path); + var directory = new DirectoryInfo(path); + var ds = directory.GetAccessControl(); ds.SetAccessRule(new FileSystemAccessRule(owner, FileSystemRights.Write, accessControlType)); - Directory.SetAccessControl(path, ds); + directory.SetAccessControl(ds); } else { - var fs = File.GetAccessControl(path); + var file = new FileInfo(path); + var fs = file.GetAccessControl(); fs.SetAccessRule(new FileSystemAccessRule(owner, FileSystemRights.Write, accessControlType)); - File.SetAccessControl(path, fs); + file.SetAccessControl(fs); } } } diff --git a/src/NzbDrone.Windows.Test/EnvironmentInfo/DotNetPlatformInfoFixture.cs b/src/NzbDrone.Windows.Test/EnvironmentInfo/DotNetPlatformInfoFixture.cs index 2d12a3f8f..f88119ad3 100644 --- a/src/NzbDrone.Windows.Test/EnvironmentInfo/DotNetPlatformInfoFixture.cs +++ b/src/NzbDrone.Windows.Test/EnvironmentInfo/DotNetPlatformInfoFixture.cs @@ -6,7 +6,7 @@ using NzbDrone.Test.Common; namespace NzbDrone.Windows.Test.EnvironmentInfo { [TestFixture] - [Platform("Win")] + [Platform("Net")] public class DotNetPlatformInfoFixture : TestBase { [Test] diff --git a/src/NzbDrone.Windows.Test/Lidarr.Windows.Test.csproj b/src/NzbDrone.Windows.Test/Lidarr.Windows.Test.csproj index 36e633f66..302cef1a9 100644 --- a/src/NzbDrone.Windows.Test/Lidarr.Windows.Test.csproj +++ b/src/NzbDrone.Windows.Test/Lidarr.Windows.Test.csproj @@ -1,7 +1,16 @@  - net462 + net462;netcoreapp3.0 + + + + + + + + + diff --git a/src/NzbDrone.Windows/Disk/DiskProvider.cs b/src/NzbDrone.Windows/Disk/DiskProvider.cs index 18b286526..1ded18049 100644 --- a/src/NzbDrone.Windows/Disk/DiskProvider.cs +++ b/src/NzbDrone.Windows/Disk/DiskProvider.cs @@ -2,6 +2,7 @@ using System.IO; using System.IO.Abstractions; using System.Runtime.InteropServices; +using System.Security.AccessControl; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.EnsureThat; @@ -50,9 +51,10 @@ namespace NzbDrone.Windows.Disk { Ensure.That(filename, () => filename).IsValidPath(); - var fs = File.GetAccessControl(filename); + var file = _fileSystem.FileInfo.FromFileName(filename); + var fs = file.GetAccessControl(); fs.SetAccessRuleProtection(false, false); - File.SetAccessControl(filename, fs); + file.SetAccessControl(fs); } public override void SetPermissions(string path, string mask, string user, string group) diff --git a/src/NzbDrone.Windows/Lidarr.Windows.csproj b/src/NzbDrone.Windows/Lidarr.Windows.csproj index 108ebd993..aff5f065d 100644 --- a/src/NzbDrone.Windows/Lidarr.Windows.csproj +++ b/src/NzbDrone.Windows/Lidarr.Windows.csproj @@ -1,9 +1,10 @@  - net462 + net462;netcoreapp3.0 + diff --git a/src/NzbDrone/Lidarr.csproj b/src/NzbDrone/Lidarr.csproj index 3edb903d1..da38debce 100644 --- a/src/NzbDrone/Lidarr.csproj +++ b/src/NzbDrone/Lidarr.csproj @@ -1,8 +1,9 @@ - + WinExe - net462 + net462;netcoreapp3.0 win-x64 + true ..\NzbDrone.Host\NzbDrone.ico app.manifest true @@ -13,7 +14,7 @@ - + diff --git a/src/PublishAllRids.targets b/src/PublishAllRids.targets index c6c99be98..e43dd7bfe 100644 --- a/src/PublishAllRids.targets +++ b/src/PublishAllRids.targets @@ -10,21 +10,22 @@ - - - - %(Runtimes.Identity) - - - + %(Frameworks.Identity) - + + + + %(Identity) + %(Framework) + + + - - RuntimeIdentifier=%(Combined2.Runtime);TargetFramework=%(Combined2.Framework) + + RuntimeIdentifier=%(Renamed.Runtime);TargetFramework=%(Renamed.Framework) diff --git a/src/ServiceHelpers/ServiceInstall/ServiceInstall.csproj b/src/ServiceHelpers/ServiceInstall/ServiceInstall.csproj index 8c54330b4..8a735f3bf 100644 --- a/src/ServiceHelpers/ServiceInstall/ServiceInstall.csproj +++ b/src/ServiceHelpers/ServiceInstall/ServiceInstall.csproj @@ -1,6 +1,9 @@  - Exe - net462 + WinExe + net462;netcoreapp3.0 + + + diff --git a/src/ServiceHelpers/ServiceUninstall/ServiceUninstall.csproj b/src/ServiceHelpers/ServiceUninstall/ServiceUninstall.csproj index 8c54330b4..69ed0d676 100644 --- a/src/ServiceHelpers/ServiceUninstall/ServiceUninstall.csproj +++ b/src/ServiceHelpers/ServiceUninstall/ServiceUninstall.csproj @@ -1,6 +1,9 @@  - Exe - net462 + WinExe + net462;netcoreapp3.0 + + + diff --git a/src/coverlet.runsettings b/src/coverlet.runsettings new file mode 100644 index 000000000..72987228b --- /dev/null +++ b/src/coverlet.runsettings @@ -0,0 +1,21 @@ + + + + + + + opencover + [Lidarr.*.Test]*,[Lidarr.Test.*]*,[Lidarr.Api.V1]*,[Marr.Data]*,[MonoTorrent]* + + + + + + + + + + diff --git a/test.sh b/test.sh index f22ea3b6d..b048addf5 100755 --- a/test.sh +++ b/test.sh @@ -2,7 +2,7 @@ PLATFORM=$1 TYPE=$2 COVERAGE=$3 -WHERE="cat != ManualTest" +WHERE="Category!=ManualTest" TEST_PATTERN="*Test.dll" ASSEMBLIES="" TEST_LOG_FILE="TestLog.txt" @@ -16,16 +16,12 @@ if [ -d "$TEST_DIR/_tests" ]; then TEST_DIR="$TEST_DIR/_tests" fi -COVERAGE_RESULT_DIRECTORY="$TEST_DIR/CoverageResults/" - rm -f "$TEST_LOG_FILE" # Uncomment to log test output to a file instead of the console export LIDARR_TESTS_LOG_OUTPUT="File" -NUNIT="$TEST_DIR/NUnit.ConsoleRunner.3.10.0/tools/nunit3-console.exe" -NUNIT_COMMAND="$NUNIT" -NUNIT_PARAMS="--workers=1" +VSTEST_PARAMS="--Platform:x64 --logger:nunit;LogFilePath=TestResult.xml" if [ "$PLATFORM" = "Mac" ]; then @@ -39,22 +35,21 @@ fi if [ "$PLATFORM" = "Windows" ]; then mkdir -p "$ProgramData/Lidarr" - WHERE="$WHERE && cat != LINUX" + WHERE="$WHERE&Category!=LINUX" elif [ "$PLATFORM" = "Linux" ] || [ "$PLATFORM" = "Mac" ] ; then mkdir -p ~/.config/Lidarr - WHERE="$WHERE && cat != WINDOWS" - NUNIT_COMMAND="mono --debug --runtime=v4.0 $NUNIT" + WHERE="$WHERE&Category!=WINDOWS" else echo "Platform must be provided as first arguement: Windows, Linux or Mac" exit 1 fi if [ "$TYPE" = "Unit" ]; then - WHERE="$WHERE && cat != IntegrationTest && cat != AutomationTest" + WHERE="$WHERE&Category!=IntegrationTest&Category!=AutomationTest" elif [ "$TYPE" = "Integration" ] || [ "$TYPE" = "int" ] ; then - WHERE="$WHERE && cat == IntegrationTest" + WHERE="$WHERE&Category=IntegrationTest" elif [ "$TYPE" = "Automation" ] ; then - WHERE="$WHERE && cat == AutomationTest" + WHERE="$WHERE&Category=AutomationTest" else echo "Type must be provided as second argument: Unit, Integration or Automation" exit 2 @@ -64,19 +59,13 @@ for i in `find $TEST_DIR -name "$TEST_PATTERN"`; do ASSEMBLIES="$ASSEMBLIES $i" done +DOTNET_PARAMS="$ASSEMBLIES --TestCaseFilter:$WHERE $VSTEST_PARAMS" + if [ "$COVERAGE" = "Coverage" ]; then - if [ "$PLATFORM" = "Windows" ] || [ "$PLATFORM" = "Linux" ]; then - dotnet tool install coverlet.console --tool-path="$TEST_DIR/coverlet/" - mkdir $COVERAGE_RESULT_DIRECTORY - OPEN_COVER="$TEST_DIR/coverlet/coverlet" - $OPEN_COVER "$TEST_DIR/" --verbosity "detailed" --format "cobertura" --format "opencover" --output "$COVERAGE_RESULT_DIRECTORY" --exclude "[Lidarr.*.Test]*" --exclude "[Lidarr.Test.*]*" --exclude "[Lidarr.Api.V1]*" --exclude "[Marr.Data]*" --exclude "[MonoTorrent]*" --exclude "[CurlSharp]*" --target "$NUNIT" --targetargs "$NUNIT_PARAMS --where=\"$WHERE\" $ASSEMBLIES"; - EXIT_CODE=$? - else - echo "Coverage only supported on Windows and Linux" - exit 3 - fi + dotnet vstest $DOTNET_PARAMS --settings:"src/coverlet.runsettings" --ResultsDirectory:./CoverageResults + EXIT_CODE=$? elif [ "$COVERAGE" = "Test" ] ; then - $NUNIT_COMMAND --where "$WHERE" $NUNIT_PARAMS $ASSEMBLIES; + dotnet vstest $DOTNET_PARAMS EXIT_CODE=$? else echo "Run Type must be provided as third argument: Coverage or Test" diff --git a/tools/nuget/nuget.exe b/tools/nuget/nuget.exe deleted file mode 100644 index e00ef51e1..000000000 Binary files a/tools/nuget/nuget.exe and /dev/null differ diff --git a/tools/pdb2mdb/Mono.Cecil.Mdb.dll b/tools/pdb2mdb/Mono.Cecil.Mdb.dll deleted file mode 100644 index 5b119cb49..000000000 Binary files a/tools/pdb2mdb/Mono.Cecil.Mdb.dll and /dev/null differ diff --git a/tools/pdb2mdb/Mono.Cecil.dll b/tools/pdb2mdb/Mono.Cecil.dll deleted file mode 100644 index 4b5646655..000000000 Binary files a/tools/pdb2mdb/Mono.Cecil.dll and /dev/null differ diff --git a/tools/pdb2mdb/Mono.CompilerServices.SymbolWriter.dll b/tools/pdb2mdb/Mono.CompilerServices.SymbolWriter.dll deleted file mode 100644 index 2d20022ee..000000000 Binary files a/tools/pdb2mdb/Mono.CompilerServices.SymbolWriter.dll and /dev/null differ diff --git a/tools/pdb2mdb/pdb2mdb.exe b/tools/pdb2mdb/pdb2mdb.exe deleted file mode 100644 index 054648355..000000000 Binary files a/tools/pdb2mdb/pdb2mdb.exe and /dev/null differ diff --git a/tools/vswhere/vswhere.exe b/tools/vswhere/vswhere.exe deleted file mode 100644 index e1b511803..000000000 Binary files a/tools/vswhere/vswhere.exe and /dev/null differ diff --git a/yarn.lock b/yarn.lock index cb2998213..24e37b0a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,15 +2,6 @@ # yarn lockfile v1 -"@aspnet/signalr@1.1.4": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@aspnet/signalr/-/signalr-1.1.4.tgz#417cf808f4074a8aec45d27f03c4b8df9d96bb0b" - integrity sha512-Jp9nPc8hmmhbG9OKiHe2fOKskBHfg+3Y9foSKHxjgGtyI743hXjGFv3uFlUg503K9f8Ilu63gQt3fDkLICBRyg== - dependencies: - eventsource "^1.0.7" - request "^2.88.0" - ws "^6.0.0" - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" @@ -912,6 +903,15 @@ normalize-path "^2.0.1" through2 "^2.0.3" +"@microsoft/signalr@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@microsoft/signalr/-/signalr-3.0.0.tgz#df03564f900957db0a62469cad576eb573368c9d" + integrity sha512-M0KMWvJ62yZuizPxFLZakitJb4aOZkJH6epXTLvp5LednJZdzacRDxWT3La7Cexp1cHxVbldBFtc3jrdfwmtxw== + dependencies: + eventsource "^1.0.7" + request "^2.88.0" + ws "^6.0.0" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"