1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-18 21:35:51 -04:00

Compare commits

...

39 Commits

Author SHA1 Message Date
ta264 354d247314 Try disabling response compression 2022-05-25 21:51:13 +01:00
ta264 c032f3fa7a try to fix build 2022-05-16 21:51:56 +01:00
ta264 1de454de17 New: Support older ARMv7 CPUs
Eg armada370 ad armadaxp
2022-05-16 21:21:48 +01:00
ta264 879668eb61 New: .NET 6.0.5 2022-05-15 21:48:23 +01:00
bakerboy448 097b46c49f New: Parse QxR Group r00t
Fixes #7290
2022-05-15 12:45:31 -05:00
Servarr ddeb3a7840 Automated API Docs update 2022-05-13 17:45:11 -05:00
Qstick 50018d0325 New: Instance name in System/Status API endpoint 2022-05-13 23:37:53 +01:00
Qstick a37fc0dc1f New: Instance name for Page Title 2022-05-13 23:37:53 +01:00
Robin Dadswell 39ad315e73 New: Instance Name used for Syslog 2022-05-13 23:37:53 +01:00
Robin Dadswell 0559996566 New: Set Instance Name 2022-05-13 23:37:53 +01:00
Stevie Robinson e7d4429fe4 New: Add optional Source Title column to history
(cherry picked from commit 581fb2cb3d47d62fe16b840081647056ec77043d)
Fixes #7159
2022-05-12 21:48:22 -05:00
bakerboy448 6c494e9a92 New: Support for new Nyaa RSS Feed format
(cherry picked from commit 40ecdbc12de8b320a4d650aea65a36e8edea77d8)
2022-05-12 19:16:46 -05:00
Qstick 62faa1aad8 Fixed: Don't try to add MovieMeta if mapping fails for list items 2022-05-11 19:46:41 -05:00
Mark McDowall 907950e309 Fixed: Importing file from UNC shared folder without job folder
(cherry picked from commit 9183c6b84638e3654c3f90a80e560a06575606bb)
2022-05-08 19:05:31 -05:00
Qstick 1caced614e Fixed: No restart requirement for Refresh Monitored interval change 2022-05-08 16:11:53 -05:00
Qstick 5824ba963b Fixed: Correct User-Agent api logging 2022-05-06 08:25:34 -05:00
Qstick 7f2d5d8d10 Delete nan.json 2022-05-01 22:30:00 -05:00
Qstick 81bffe243a Delete zh_Hans.json 2022-05-01 22:29:50 -05:00
Weblate 2d6fde282a Translated using Weblate (Chinese (Simplified)) [skip ci]
Currently translated at 28.6% (320 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 28.6% (320 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 4.6% (52 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 97.2% (1086 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 19.1% (214 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 4.5% (51 of 1117 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 95.9% (1072 of 1117 strings)

Update translation files  [skip ci]

Updated by "Remove blank strings" hook in Weblate.

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 3.5% (40 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 2.0% (23 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 99.5% (1112 of 1117 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 97.9% (1094 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 19.0% (213 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 19.0% (213 of 1117 strings)

Translated using Weblate (Chinese (Simplified)) [skip ci]

Currently translated at 1.1% (13 of 1117 strings)

Translated using Weblate (Arabic) [skip ci]

Currently translated at 93.9% (1049 of 1117 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Thai) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Bulgarian) [skip ci]

Currently translated at 91.3% (1020 of 1117 strings)

Translated using Weblate (Hindi) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Romanian) [skip ci]

Currently translated at 93.0% (1039 of 1117 strings)

Translated using Weblate (Vietnamese) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Turkish) [skip ci]

Currently translated at 93.2% (1042 of 1117 strings)

Translated using Weblate (Swedish) [skip ci]

Currently translated at 93.8% (1048 of 1117 strings)

Translated using Weblate (Russian) [skip ci]

Currently translated at 98.8% (1104 of 1117 strings)

Translated using Weblate (Portuguese) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Polish) [skip ci]

Currently translated at 93.3% (1043 of 1117 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 95.7% (1070 of 1117 strings)

Translated using Weblate (Korean) [skip ci]

Currently translated at 22.2% (248 of 1117 strings)

Translated using Weblate (Japanese) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Icelandic) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Hebrew) [skip ci]

Currently translated at 93.4% (1044 of 1117 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 100.0% (1117 of 1117 strings)

Translated using Weblate (Greek) [skip ci]

Currently translated at 93.3% (1043 of 1117 strings)

Translated using Weblate (Danish) [skip ci]

Currently translated at 93.1% (1041 of 1117 strings)

Translated using Weblate (Czech) [skip ci]

Currently translated at 94.1% (1052 of 1117 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 96.5% (1078 of 1117 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 97.9% (1094 of 1117 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.8% (1115 of 1117 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.8% (1115 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 15.7% (176 of 1117 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 15.7% (176 of 1117 strings)

Co-authored-by: AnlakHui <AnlakHui@gmail.com>
Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: EldestBard <449734150@qq.com>
Co-authored-by: Florian <sephrat.flo@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: M1C <webnar@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Zalhera <tobias.bechen@gmail.com>
Co-authored-by: andrey4korop <andrey999@i.ua>
Co-authored-by: jianjam <jianjam@qq.com>
Co-authored-by: killsover <w904202822@163.com>
Co-authored-by: lhquark <lhquark@gmail.com>
Co-authored-by: marcosteam <wdy71608161@gmail.com>
Co-authored-by: minermartijn <minermartijn@gmail.com>
Co-authored-by: neoestremi <remidu34070@hotmail.fr>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_Hans/
Translation: Servarr/Radarr
2022-04-29 10:59:36 -05:00
Qstick 3125b038d5 Fixed: Wrong translation mapping can be used for file naming and metadata
Fixes #7243
2022-04-26 19:27:07 -05:00
Qstick 89e25a6241 Fixed: Translated fields are mapped incorrectly for existing search results 2022-04-26 18:29:15 -05:00
Qstick 4db6688fe0 Fixed: UI hiding search results with duplicate GUIDs
Closes #7241

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2022-04-24 13:16:20 -05:00
Qstick 4ac1aeaf06 Fixed: QBittorrent unknown download state: forcedMetaDL
Closes #7242

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2022-04-24 13:14:58 -05:00
Qstick e2ae743ee1 Fix migration 207 distinct on tmdbid only for list movie insert 2022-04-24 13:13:05 -05:00
Robin Dadswell 9ad316a6f5 Fix metadata migration 2022-04-23 16:41:43 -05:00
Servarr b643d2e23d Automated API Docs update 2022-04-23 20:35:25 +01:00
Qstick 6a03eddda9 Rework Movie Metadata data model 2022-04-23 13:14:03 -05:00
ta264 1576bf1f17 Temporarily ignore update tests until linux-x86 released 2022-04-23 02:25:39 -05:00
ta264 6325b70e27 New: Add linux-x86 builds
[common]
2022-04-23 02:25:39 -05:00
Qstick 24206ad0a3 New: Support Plex API Path Scan (Similar to autoscan)
Closes #4640
Closes #5527
2022-04-21 22:49:09 -05:00
Mark McDowall 2fc7cbff89 Fixed: Interactive Search Filter not filtering multiple qualities in the same filter row
(cherry picked from commit c93f63cd204bf62dab3dffef6e29c8dd4c408cab)
2022-04-18 21:07:50 -05:00
Tristan Kennedy 55ef505d74 Added padding to search tab to maintain visual consistancy 2022-04-15 23:58:45 -05:00
Qstick cabdad6306 Fixed: Update ScheduledTask cache LastStartTime on command execution 2022-04-15 18:16:01 -05:00
Qstick 8d4b2dd21b Bump Version to 4.2 2022-04-15 16:47:28 -05:00
Qstick ad04031c99 Bump webpack packages 2022-04-14 21:08:10 -05:00
Qstick e9a5f87e45 Remove old DotNetVersion method and dep 2022-04-14 21:06:29 -05:00
Qstick bc6ac0cd4b Bump Monotorrent to 2.0.5
Fixes #7206
2022-04-11 19:18:01 -05:00
Qstick c2328e4b79 Fixed: Don't die if Plex watchlist guid node is missing or null
Fixes #7213
2022-04-11 08:30:39 -05:00
Servarr 36119facf0 Automated API Docs update 2022-04-10 22:10:41 -05:00
182 changed files with 3780 additions and 2736 deletions
+106 -54
View File
@@ -9,13 +9,13 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '4.1.0'
majorVersion: '4.2.0'
minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.201'
dotnetVersion: '6.0.300'
nodeVersion: '16.X'
innoVersion: '6.2.0'
windowsImage: 'windows-2022'
@@ -95,17 +95,25 @@ stages:
inputs:
version: $(dotnetVersion)
- bash: |
BUNDLEDVERSIONS=${AGENT_TOOLSDIRECTORY}/dotnet/sdk/${DOTNETVERSION}/Microsoft.NETCoreSdk.BundledVersions.props
echo $BUNDLEDVERSIONS
grep osx-x64 $BUNDLEDVERSIONS
if grep -q freebsd-x64 $BUNDLEDVERSIONS; then
echo "BSD already enabled"
else
echo "Enabling BSD support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64/' $BUNDLEDVERSIONS
SDK_PATH="${AGENT_TOOLSDIRECTORY}/dotnet/sdk/${DOTNETVERSION}"
BUNDLEDVERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
if ! grep -q freebsd-x64 $BUNDLEDVERSIONS; then
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64;linux-x86;linux-arm-vfpv3d16/' $BUNDLEDVERSIONS
fi
displayName: Enable FreeBSD Support
- bash: ./build.sh --backend --enable-bsd
grep freebsd-x64 $BUNDLEDVERSIONS
displayName: Extra Platform Support - Generic
- bash: |
SDK_PATH="${AGENT_TOOLSDIRECTORY}/dotnet/sdk/${DOTNETVERSION}"
RUNTIMEIDENTIFIERGRAPH="${SDK_PATH}/RuntimeIdentifierGraph.json"
if ! grep -q linux-arm-vfpv3d16 "${RUNTIMEIDENTIFIERGRAPH}"; then
sed -i.ORI '/"runtimes":/a \ \ \ \ "linux-arm-vfpv3d16": {"#import": ["linux-arm"]},' "${RUNTIMEIDENTIFIERGRAPH}"
fi
grep -A5 -B5 linux-arm-vfpv3d16 $RUNTIMEIDENTIFIERGRAPH
displayName: Enable Extra Platform Support - Windows
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- bash: ./build.sh --backend --enable-extra-platforms
displayName: Build Radarr Backend
- bash: |
find ${OUTPUTFOLDER} -type f ! -path "*/publish/*" -exec rm -rf {} \;
@@ -119,24 +127,28 @@ stages:
displayName: Publish Backend
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/win-x64/publish'
artifact: WindowsCoreTests
displayName: Publish Windows Test Package
artifact: win-x64-tests
displayName: Publish win-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-x64/publish'
artifact: LinuxCoreTests
displayName: Publish Linux Test Package
artifact: linux-x64-tests
displayName: Publish linux-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-x86/publish'
artifact: linux-x86-tests
displayName: Publish linux-x86 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-musl-x64/publish'
artifact: LinuxMuslCoreTests
displayName: Publish Linux Musl Test Package
artifact: linux-musl-x64-tests
displayName: Publish linux-musl-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/freebsd-x64/publish'
artifact: FreebsdCoreTests
displayName: Publish FreeBSD Test Package
artifact: freebsd-x64-tests
displayName: Publish freebsd-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/osx-x64/publish'
artifact: MacCoreTests
displayName: Publish MacOS Test Package
artifact: osx-x64-tests
displayName: Publish osx-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- stage: Build_Frontend
@@ -240,7 +252,7 @@ stages:
artifactName: WindowsFrontend
targetPath: _output
displayName: Fetch Frontend
- bash: ./build.sh --packages --enable-bsd
- bash: ./build.sh --packages --enable-extra-platforms
displayName: Create Packages
- bash: |
find . -name "ffprobe" -exec chmod a+x {} \;
@@ -248,28 +260,28 @@ stages:
find . -name "Radarr.Update" -exec chmod a+x {} \;
displayName: Set executable bits
- task: ArchiveFiles@2
displayName: Create Windows Core zip
displayName: Create win-x64 zip
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).windows-core-x64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/win-x64/net6.0
- task: ArchiveFiles@2
displayName: Create Windows x86 Core zip
displayName: Create win-x86 zip
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).windows-core-x86.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/win-x86/net6.0
- task: ArchiveFiles@2
displayName: Create MacOS x64 Core app
displayName: Create osx-x64 app
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-app-core-x64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-x64-app/net6.0
- task: ArchiveFiles@2
displayName: Create MacOS x64 Core tar
displayName: Create osx-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-core-x64.tar.gz'
archiveType: 'tar'
@@ -277,14 +289,14 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-x64/net6.0
- task: ArchiveFiles@2
displayName: Create MacOS arm64 Core app
displayName: Create osx-arm64 app
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-app-core-arm64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-arm64-app/net6.0
- task: ArchiveFiles@2
displayName: Create MacOS arm64 Core tar
displayName: Create osx-arm64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-core-arm64.tar.gz'
archiveType: 'tar'
@@ -292,7 +304,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create Linux Core tar
displayName: Create linux-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-x64.tar.gz'
archiveType: 'tar'
@@ -300,7 +312,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-x64/net6.0
- task: ArchiveFiles@2
displayName: Create Linux Musl Core tar
displayName: Create linux-musl-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-x64.tar.gz'
archiveType: 'tar'
@@ -308,7 +320,15 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/net6.0
- task: ArchiveFiles@2
displayName: Create ARM32 Linux Core tar
displayName: Create linux-x86 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-x86.tar.gz'
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-x86/net6.0
- task: ArchiveFiles@2
displayName: Create linux-arm tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm.tar.gz'
archiveType: 'tar'
@@ -316,7 +336,15 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm/net6.0
- task: ArchiveFiles@2
displayName: Create ARM32 Linux Musl Core tar
displayName: Create linux-arm-vfpv3d16 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm-vfpv3d16.tar.gz'
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm-vfpv3d16/net6.0
- task: ArchiveFiles@2
displayName: Create linux-musl-arm tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-arm.tar.gz'
archiveType: 'tar'
@@ -324,7 +352,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm/net6.0
- task: ArchiveFiles@2
displayName: Create ARM64 Linux Core tar
displayName: Create linux-arm64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm64.tar.gz'
archiveType: 'tar'
@@ -332,7 +360,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create ARM64 Linux Musl Core tar
displayName: Create linux-musl-arm64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-arm64.tar.gz'
archiveType: 'tar'
@@ -340,7 +368,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create FreeBSD Core Core tar
displayName: Create freebsd-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).freebsd-core-x64.tar.gz'
archiveType: 'tar'
@@ -407,22 +435,22 @@ stages:
matrix:
MacCore:
osName: 'Mac'
testName: 'MacCore'
testName: 'osx-x64'
poolName: 'Azure Pipelines'
imageName: ${{ variables.macImage }}
WindowsCore:
osName: 'Windows'
testName: 'WindowsCore'
testName: 'win-x64'
poolName: 'Azure Pipelines'
imageName: ${{ variables.windowsImage }}
LinuxCore:
osName: 'Linux'
testName: 'LinuxCore'
testName: 'linux-x64'
poolName: 'Azure Pipelines'
imageName: ${{ variables.linuxImage }}
FreebsdCore:
osName: 'Linux'
testName: 'FreebsdCore'
testName: 'freebsd-x64'
poolName: 'FreeBSD'
imageName:
@@ -441,7 +469,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(testName)Tests'
artifactName: '$(testName)-tests'
targetPath: $(testsFolder)
- powershell: Set-Service SCardSvr -StartupType Manual
displayName: Enable Windows Test Service
@@ -475,8 +503,12 @@ stages:
matrix:
alpine:
testName: 'Musl Net Core'
artifactName: LinuxMuslCoreTests
artifactName: linux-musl-x64-tests
containerImage: ghcr.io/servarr/testimages:alpine
linux-x86:
testName: 'linux-x86'
artifactName: linux-x86-tests
containerImage: ghcr.io/servarr/testimages:linux-x86
pool:
vmImage: ${{ variables.linuxImage }}
@@ -487,9 +519,15 @@ stages:
steps:
- task: UseDotNet@2
displayName: 'Install .net core'
displayName: 'Install .NET'
inputs:
version: $(dotnetVersion)
condition: and(succeeded(), ne(variables['testName'], 'linux-x86'))
- bash: |
SDKURL=$(curl -s https://api.github.com/repos/Servarr/dotnet-linux-x86/releases | jq -rc '.[].assets[].browser_download_url' | grep sdk-${DOTNETVERSION}.*gz$)
curl -fsSL $SDKURL | tar xzf - -C /opt/dotnet
displayName: 'Install .NET'
condition: and(succeeded(), eq(variables['testName'], 'linux-x86'))
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
@@ -522,7 +560,7 @@ stages:
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
variables:
pattern: 'Radarr.*.linux-core-x64.tar.gz'
artifactName: LinuxCoreTests
artifactName: linux-x64-tests
Radarr__Postgres__Host: 'localhost'
Radarr__Postgres__Port: '5432'
Radarr__Postgres__User: 'radarr'
@@ -597,17 +635,17 @@ stages:
matrix:
MacCore:
osName: 'Mac'
testName: 'MacCore'
testName: 'osx-x64'
imageName: ${{ variables.macImage }}
pattern: 'Radarr.*.osx-core-x64.tar.gz'
WindowsCore:
osName: 'Windows'
testName: 'WindowsCore'
testName: 'win-x64'
imageName: ${{ variables.windowsImage }}
pattern: 'Radarr.*.windows-core-x64.zip'
LinuxCore:
osName: 'Linux'
testName: 'LinuxCore'
testName: 'linux-x64'
imageName: ${{ variables.linuxImage }}
pattern: 'Radarr.*.linux-core-x64.tar.gz'
@@ -624,7 +662,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(testName)Tests'
artifactName: '$(testName)-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
@@ -678,7 +716,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: 'LinuxCoreTests'
artifactName: 'linux-x64-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
@@ -732,7 +770,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: 'FreebsdCoreTests'
artifactName: 'freebsd-x64-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
@@ -768,10 +806,15 @@ stages:
strategy:
matrix:
alpine:
testName: 'Musl Net Core'
artifactName: LinuxMuslCoreTests
testName: 'linux-musl-x64'
artifactName: linux-musl-x64-tests
containerImage: ghcr.io/servarr/testimages:alpine
pattern: 'Radarr.*.linux-musl-core-x64.tar.gz'
linux-x86:
testName: 'linux-x86'
artifactName: linux-x86-tests
containerImage: ghcr.io/servarr/testimages:linux-x86
pattern: 'Radarr.*.linux-core-x86.tar.gz'
pool:
vmImage: ${{ variables.linuxImage }}
@@ -781,9 +824,15 @@ stages:
steps:
- task: UseDotNet@2
displayName: 'Install .net core'
displayName: 'Install .NET'
inputs:
version: $(dotnetVersion)
condition: and(succeeded(), ne(variables['testName'], 'linux-x86'))
- bash: |
SDKURL=$(curl -s https://api.github.com/repos/Servarr/dotnet-linux-x86/releases | jq -rc '.[].assets[].browser_download_url' | grep sdk-${DOTNETVERSION}.*gz$)
curl -fsSL $SDKURL | tar xzf - -C /opt/dotnet
displayName: 'Install .NET'
condition: and(succeeded(), eq(variables['testName'], 'linux-x86'))
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
@@ -829,16 +878,19 @@ stages:
matrix:
Linux:
osName: 'Linux'
artifactName: 'linux-x64'
imageName: ${{ variables.linuxImage }}
pattern: 'Radarr.*.linux-core-x64.tar.gz'
failBuild: true
Mac:
osName: 'Mac'
artifactName: 'osx-x64'
imageName: ${{ variables.macImage }}
pattern: 'Radarr.*.osx-core-x64.tar.gz'
failBuild: true
Windows:
osName: 'Windows'
artifactName: 'win-x64'
imageName: ${{ variables.windowsImage }}
pattern: 'Radarr.*.windows-core-x64.zip'
failBuild: true
@@ -856,7 +908,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(osName)CoreTests'
artifactName: '$(artifactName)-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
+40 -15
View File
@@ -25,14 +25,26 @@ UpdateVersionNumber()
fi
}
EnableBsdSupport()
EnableExtraPlatformsInSDK()
{
#todo enable sdk with
#SDK_PATH=$(dotnet --list-sdks | grep -P '5\.\d\.\d+' | head -1 | sed 's/\(5\.[0-9]*\.[0-9]*\).*\[\(.*\)\]/\2\/\1/g')
# BUNDLED_VERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
SDK_PATH=$(dotnet --list-sdks | grep '6\.[0-9]\.[0-9]\{3\}' | tail -1 | sed 's/\(6\.[0-9]*\.[0-9]*\).*\[\(.*\)\]/\2\/\1/g')
BUNDLEDVERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
if ! grep -q freebsd-x64 "${BUNDLEDVERSIONS}"; then
echo "Enabling extra platform support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64;linux-x86;linux-arm-vfpv3d16/' "${BUNDLEDVERSIONS}"
fi
RUNTIMEIDENTIFIERGRAPH="${SDK_PATH}/RuntimeIdentifierGraph.json"
if ! grep -q linux-arm-vfpv3d16 "${RUNTIMEIDENTIFIERGRAPH}"; then
sed -i.ORI '/"runtimes":/a \ \ \ \ "linux-arm-vfpv3d16": {"#import": ["linux-arm"]},' "${RUNTIMEIDENTIFIERGRAPH}"
fi
}
if grep -qv freebsd-x64 src/Directory.Build.props; then
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64</RuntimeIdentifiers>^g" src/Directory.Build.props
EnableExtraPlatforms()
{
if ! grep -q freebsd-x64 src/Directory.Build.props; then
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64;linux-x86;linux-arm-vfpv3d16</RuntimeIdentifiers>^g" src/Directory.Build.props
fi
}
@@ -66,8 +78,8 @@ Build()
platform=Posix
fi
dotnet clean $slnFile -c Debug
dotnet clean $slnFile -c Release
#dotnet clean $slnFile -c Debug
#dotnet clean $slnFile -c Release
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
then
@@ -292,7 +304,8 @@ if [ $# -eq 0 ]; then
PACKAGES=YES
INSTALLER=NO
LINT=YES
ENABLE_BSD=NO
ENABLE_EXTRA_PLATFORMS=NO
ENABLE_EXTRA_PLATFORMS_IN_SDK=NO
fi
while [[ $# -gt 0 ]]
@@ -304,8 +317,12 @@ case $key in
BACKEND=YES
shift # past argument
;;
--enable-bsd)
ENABLE_BSD=YES
--enable-bsd|--enable-extra-platforms)
ENABLE_EXTRA_PLATFORMS=YES
shift # past argument
;;
--enable-extra-platforms-in-sdk)
ENABLE_EXTRA_PLATFORMS_IN_SDK=YES
shift # past argument
;;
-r|--runtime)
@@ -349,12 +366,17 @@ esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
if [ "$ENABLE_EXTRA_PLATFORMS_IN_SDK" = "YES" ];
then
EnableExtraPlatformsInSDK
fi
if [ "$BACKEND" = "YES" ];
then
UpdateVersionNumber
if [ "$ENABLE_BSD" = "YES" ];
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
then
EnableBsdSupport
EnableExtraPlatforms
fi
Build
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
@@ -364,9 +386,10 @@ then
PackageTests "net6.0" "linux-x64"
PackageTests "net6.0" "linux-musl-x64"
PackageTests "net6.0" "osx-x64"
if [ "$ENABLE_BSD" = "YES" ];
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
then
PackageTests "net6.0" "freebsd-x64"
PackageTests "net6.0" "linux-x86"
fi
else
PackageTests "$FRAMEWORK" "$RID"
@@ -405,9 +428,11 @@ then
Package "net6.0" "linux-musl-arm"
Package "net6.0" "osx-x64"
Package "net6.0" "osx-arm64"
if [ "$ENABLE_BSD" = "YES" ];
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
then
Package "net6.0" "freebsd-x64"
Package "net6.0" "linux-x86"
Package "net6.0" "linux-arm-vfpv3d16"
fi
else
Package "$FRAMEWORK" "$RID"
@@ -179,6 +179,16 @@ class HistoryRow extends Component {
);
}
if (name === 'sourceTitle') {
return (
<TableRowCell
key={name}
>
{sourceTitle}
</TableRowCell>
);
}
if (name === 'details') {
return (
<TableRowCell
+1 -1
View File
@@ -8,7 +8,7 @@ import AppRoutes from './AppRoutes';
function App({ store, history }) {
return (
<DocumentTitle title="Radarr">
<DocumentTitle title={window.Radarr.instanceName}>
<Provider store={store}>
<ConnectedRouter history={history}>
<PageConnector>
+1 -1
View File
@@ -14,7 +14,7 @@ function PageContent(props) {
return (
<ErrorBoundary errorComponent={PageContentError}>
<DocumentTitle title={title ? `${title} - Radarr` : 'Radarr'}>
<DocumentTitle title={title ? `${title} - ${window.Radarr.instanceName}` : window.Radarr.instanceName}>
<div className={className}>
{children}
</div>
@@ -7,3 +7,9 @@
.filteredMessage {
margin-top: 10px;
}
.blankpad {
padding-top: 10px;
padding-bottom: 10px;
padding-left: 2em;
}
@@ -127,21 +127,21 @@ function InteractiveSearchContent(props) {
{
!isFetching && !!error &&
<div>
<div className={styles.blankpad}>
{translate('UnableToLoadResultsIntSearch')}
</div>
}
{
!isFetching && isPopulated && !totalReleasesCount &&
<div>
<div className={styles.blankpad}>
{translate('NoResultsFound')}
</div>
}
{
!!totalReleasesCount && isPopulated && !items.length &&
<div>
<div className={styles.blankpad}>
{translate('AllResultsHiddenFilter')}
</div>
}
@@ -159,7 +159,7 @@ function InteractiveSearchContent(props) {
items.map((item) => {
return (
<InteractiveSearchRowConnector
key={item.guid}
key={`${item.indexerId}-${item.guid}`}
{...item}
searchPayload={searchPayload}
longDateFormat={longDateFormat}
@@ -65,10 +65,10 @@ function DownloadClientOptions(props) {
<FormInputGroup
type={inputTypes.NUMBER}
name="checkForFinishedDownloadInterval"
min={0}
min={1}
max={120}
unit="minutes"
helpText={translate('HelpText')}
helpText={translate('RefreshMonitoredIntervalHelpText')}
onChange={onInputChange}
{...settings.checkForFinishedDownloadInterval}
/>
@@ -20,6 +20,7 @@ function HostSettings(props) {
bindAddress,
port,
urlBase,
instanceName,
enableSsl,
sslPort,
sslCertPath,
@@ -73,6 +74,22 @@ function HostSettings(props) {
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>{translate('InstanceName')}</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="instanceName"
helpText={translate('InstanceNameHelpText')}
helpTextWarning={translate('RestartRequiredHelpTextWarning')}
onChange={onInputChange}
{...instanceName}
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
@@ -116,7 +116,7 @@ function IndexerOptions(props) {
min={0}
max={120}
unit="minutes"
helpText={translate('HelpText')}
helpText={translate('RssSyncHelpText')}
helpTextWarning={translate('RSSSyncIntervalHelpTextWarning')}
helpLink="https://wiki.servarr.com/radarr/faq#how-does-radarr-work"
onChange={onInputChange}
@@ -116,10 +116,11 @@ class NamingModal extends Component {
const movieTokens = [
{ token: '{Movie Title}', example: 'Movie\'s Title' },
{ token: '{Movie Title:DE}', example: 'Filetitle' },
{ token: '{Movie Title:DE}', example: 'Titel des Films' },
{ token: '{Movie CleanTitle}', example: 'Movies Title' },
{ token: '{Movie TitleThe}', example: 'Movie\'s Title, The' },
{ token: '{Movie OriginalTitle}', example: 'Τίτλος ταινίας' },
{ token: '{Movie CleanOriginalTitle}', example: 'Τίτλος ταινίας' },
{ token: '{Movie TitleFirstCharacter}', example: 'M' },
{ token: '{Movie Collection}', example: 'The Movie Collection' },
{ token: '{Movie Certification}', example: 'R' },
@@ -79,6 +79,11 @@ export const defaultState = {
label: translate('ReleaseGroup'),
isVisible: false
},
{
name: 'sourceTitle',
label: translate('SourceTitle'),
isVisible: false
},
{
name: 'details',
columnLabel: translate('Details'),
@@ -44,7 +44,14 @@ function filter(items, state) {
const predicate = filterPredicates[key];
if (Array.isArray(value)) {
accepted = value.some((v) => predicate(item, v, type));
if (
type === filterTypes.NOT_CONTAINS ||
type === filterTypes.NOT_EQUAL
) {
accepted = value.every((v) => predicate(item, v, type));
} else {
accepted = value.some((v) => predicate(item, v, type));
}
} else {
accepted = predicate(item, value, type);
}
+11 -11
View File
@@ -30,7 +30,7 @@
"@fortawesome/free-regular-svg-icons": "6.1.0",
"@fortawesome/free-solid-svg-icons": "6.1.0",
"@fortawesome/react-fontawesome": "0.1.18",
"@microsoft/signalr": "6.0.3",
"@microsoft/signalr": "6.0.5",
"@sentry/browser": "6.18.2",
"@sentry/integrations": "6.18.2",
"classnames": "2.3.1",
@@ -45,7 +45,7 @@
"jquery": "3.6.0",
"lodash": "4.17.21",
"mobile-detect": "1.4.5",
"moment": "2.29.1",
"moment": "2.29.2",
"mousetrap": "1.6.5",
"normalize.css": "8.0.1",
"prop-types": "15.7.2",
@@ -99,8 +99,8 @@
"babel-loader": "8.2.3",
"babel-plugin-inline-classnames": "2.0.1",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
"core-js": "3.11.0",
"css-loader": "5.2.4",
"core-js": "3.12.1",
"css-loader": "6.5.1",
"eslint": "8.11.0",
"eslint-plugin-filenames": "1.3.2",
"eslint-plugin-import": "2.25.4",
@@ -115,22 +115,22 @@
"mini-css-extract-plugin": "1.5.0",
"postcss": "8.2.12",
"postcss-color-function": "4.1.0",
"postcss-loader": "5.2.0",
"postcss-mixins": "7.0.3",
"postcss-nested": "5.0.5",
"postcss-loader": "6.2.0",
"postcss-mixins": "8.1.0",
"postcss-nested": "5.0.6",
"postcss-simple-vars": "6.0.3",
"postcss-url": "10.1.3",
"require-nocache": "1.0.0",
"rimraf": "3.0.2",
"run-sequence": "2.2.1",
"streamqueue": "1.1.2",
"style-loader": "2.0.0",
"style-loader": "3.3.1",
"stylelint": "14.6.0",
"stylelint-order": "5.0.0",
"url-loader": "4.1.1",
"webpack": "5.35.1",
"webpack-cli": "4.6.0",
"webpack-livereload-plugin": "3.0.1",
"webpack": "5.64.2",
"webpack-cli": "4.9.1",
"webpack-livereload-plugin": "3.0.2",
"worker-loader": "3.0.8"
}
}
+6 -1
View File
@@ -90,7 +90,7 @@
<!-- Standard testing packages -->
<ItemGroup Condition="'$(TestProject)'=='true'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />
@@ -154,4 +154,9 @@
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
</PropertyGroup>
<!-- Define constant so we can identify the non-standard arch arm-vfpv3d16 -->
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'linux-arm-vfpv3d16'">
<DefineConstants>ARM_VFPV3D16</DefineConstants>
</PropertyGroup>
</Project>
@@ -1,5 +1,4 @@
using System;
using Microsoft.Win32;
namespace NzbDrone.Common.EnvironmentInfo
{
@@ -51,78 +50,5 @@ namespace NzbDrone.Common.EnvironmentInfo
{
return _version;
}
private static Version GetDotNetVersion()
{
try
{
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (var ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
{
if (ndpKey == null)
{
return new Version(4, 0);
}
var releaseKey = (int)ndpKey.GetValue("Release");
if (releaseKey >= 528040)
{
return new Version(4, 8, 0);
}
if (releaseKey >= 461808)
{
return new Version(4, 7, 2);
}
if (releaseKey >= 461308)
{
return new Version(4, 7, 1);
}
if (releaseKey >= 460798)
{
return new Version(4, 7);
}
if (releaseKey >= 394802)
{
return new Version(4, 6, 2);
}
if (releaseKey >= 394254)
{
return new Version(4, 6, 1);
}
if (releaseKey >= 393295)
{
return new Version(4, 6);
}
if (releaseKey >= 379893)
{
return new Version(4, 5, 2);
}
if (releaseKey >= 378675)
{
return new Version(4, 5, 1);
}
if (releaseKey >= 378389)
{
return new Version(4, 5);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Couldnt get .NET framework version: " + ex.ToString());
}
return new Version(4, 0);
}
}
}
+1 -2
View File
@@ -13,14 +13,13 @@
<PackageReference Include="Sentry" Version="3.15.0" />
<PackageReference Include="NLog.Targets.Syslog" Version="6.0.3" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.Text.Json" Version="6.0.2" />
<PackageReference Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="6.0.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="EnsureThat\Resources\ExceptionMessages.Designer.cs">
@@ -0,0 +1,347 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class movie_metadataFixture : MigrationTest<movie_metadata>
{
[Test]
public void should_add_metadata_from_movie_and_link_back_to_movie()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_credits()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("Credits").Row(new
{
MovieId = 5,
CreditTmdbId = 123,
PersonTmdbId = 456,
Order = 1,
Type = 1,
Name = "Some Person",
Images = new[] { new { CoverType = "Poster" } }.ToJson()
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Credits\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_alt_title()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("AlternativeTitles").Row(new
{
MovieId = 5,
Title = "Some Alt",
CleanTitle = "somealt",
SourceType = 1,
SourceId = 1,
Votes = 0,
VoteCount = 0,
Language = 1
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"AlternativeTitles\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_translation()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("MovieTranslations").Row(new
{
MovieId = 5,
Title = "Some Trans",
Language = 1
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"MovieTranslations\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_add_metadata_from_list_and_link_back()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_not_duplicate_metadata()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 123456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
var listMovies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
listMovies.Should().HaveCount(1);
listMovies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_not_duplicate_metadata_from_lists()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Overview = "Overview 1",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Overview = "Overview 2",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 5,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var listMovies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
listMovies.Should().HaveCount(2);
listMovies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
}
public class MovieMetadata207
{
public int Id { get; set; }
public int TmdbId { get; set; }
public string Title { get; set; }
public bool Monitored { get; set; }
}
public class Movie207
{
public int Id { get; set; }
public int MovieMetadataId { get; set; }
}
}
@@ -27,6 +27,11 @@ namespace NzbDrone.Core.Test.Datastore
return new WhereBuilderPostgres(filter, true, 0);
}
private WhereBuilderPostgres WhereMeta(Expression<Func<MovieMetadata, bool>> filter)
{
return new WhereBuilderPostgres(filter, true, 0);
}
[Test]
public void postgres_where_equal_const()
{
@@ -86,36 +91,36 @@ namespace NzbDrone.Core.Test.Datastore
[Test]
public void postgres_where_string_is_null()
{
_subject = Where(x => x.CleanTitle == null);
_subject = WhereMeta(x => x.CleanTitle == null);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_string_is_null_value()
{
string cleanTitle = null;
_subject = Where(x => x.CleanTitle == cleanTitle);
_subject = WhereMeta(x => x.CleanTitle == cleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_equal_null_property()
{
var movie = new Movie { CleanTitle = null };
_subject = Where(x => x.CleanTitle == movie.CleanTitle);
var movie = new MovieMetadata { CleanTitle = null };
_subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_column_contains_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.Contains(test));
_subject = WhereMeta(x => x.CleanTitle.Contains(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE '%' || @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE '%' || @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -123,9 +128,9 @@ namespace NzbDrone.Core.Test.Datastore
public void postgres_where_string_contains_column()
{
var test = "small";
_subject = Where(x => test.Contains(x.CleanTitle));
_subject = WhereMeta(x => test.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(@Clause1_P1 ILIKE '%' || \"Movies\".\"CleanTitle\" || '%')");
_subject.ToString().Should().Be($"(@Clause1_P1 ILIKE '%' || \"MovieMetadata\".\"CleanTitle\" || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -133,9 +138,9 @@ namespace NzbDrone.Core.Test.Datastore
public void postgres_where_column_starts_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.StartsWith(test));
_subject = WhereMeta(x => x.CleanTitle.StartsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -143,9 +148,9 @@ namespace NzbDrone.Core.Test.Datastore
public void postgres_where_column_ends_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.EndsWith(test));
_subject = WhereMeta(x => x.CleanTitle.EndsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE '%' || @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE '%' || @Clause1_P1)");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -162,9 +167,9 @@ namespace NzbDrone.Core.Test.Datastore
public void postgres_where_in_list_2()
{
var list = new List<int> { 1, 2, 3 };
_subject = Where(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject = WhereMeta(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject.ToString().Should().Be($"((\"Movies\".\"CleanTitle\" = @Clause1_P1) AND (\"Movies\".\"Id\" = ANY (('{{1, 2, 3}}'))))");
_subject.ToString().Should().Be($"((\"MovieMetadata\".\"CleanTitle\" = @Clause1_P1) AND (\"MovieMetadata\".\"Id\" = ANY (('{{1, 2, 3}}'))))");
}
[Test]
@@ -172,35 +177,35 @@ namespace NzbDrone.Core.Test.Datastore
{
var list = new List<string> { "first", "second", "third" };
_subject = Where(x => list.Contains(x.CleanTitle));
_subject = WhereMeta(x => list.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" = ANY (@Clause1_P1))");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" = ANY (@Clause1_P1))");
}
[Test]
public void enum_as_int()
{
_subject = Where(x => x.Status == MovieStatusType.Announced);
_subject = WhereMeta(x => x.Status == MovieStatusType.Announced);
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = @Clause1_P1)");
}
[Test]
public void enum_in_list()
{
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = ANY (@Clause1_P1))");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = ANY (@Clause1_P1))");
}
[Test]
public void enum_in_array()
{
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = ANY (@Clause1_P1))");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = ANY (@Clause1_P1))");
}
}
}
@@ -27,6 +27,11 @@ namespace NzbDrone.Core.Test.Datastore
return new WhereBuilderSqlite(filter, true, 0);
}
private WhereBuilderSqlite WhereMeta(Expression<Func<MovieMetadata, bool>> filter)
{
return new WhereBuilderSqlite(filter, true, 0);
}
[Test]
public void where_equal_const()
{
@@ -86,36 +91,36 @@ namespace NzbDrone.Core.Test.Datastore
[Test]
public void where_string_is_null()
{
_subject = Where(x => x.CleanTitle == null);
_subject = WhereMeta(x => x.CleanTitle == null);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_string_is_null_value()
{
string cleanTitle = null;
_subject = Where(x => x.CleanTitle == cleanTitle);
_subject = WhereMeta(x => x.CleanTitle == cleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_equal_null_property()
{
var movie = new Movie { CleanTitle = null };
_subject = Where(x => x.CleanTitle == movie.CleanTitle);
var movie = new MovieMetadata { CleanTitle = null };
_subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_column_contains_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.Contains(test));
_subject = WhereMeta(x => x.CleanTitle.Contains(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE '%' || @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE '%' || @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -123,9 +128,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_string_contains_column()
{
var test = "small";
_subject = Where(x => test.Contains(x.CleanTitle));
_subject = WhereMeta(x => test.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(@Clause1_P1 LIKE '%' || \"Movies\".\"CleanTitle\" || '%')");
_subject.ToString().Should().Be($"(@Clause1_P1 LIKE '%' || \"MovieMetadata\".\"CleanTitle\" || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -133,9 +138,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_column_starts_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.StartsWith(test));
_subject = WhereMeta(x => x.CleanTitle.StartsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -143,9 +148,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_column_ends_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.EndsWith(test));
_subject = WhereMeta(x => x.CleanTitle.EndsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE '%' || @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE '%' || @Clause1_P1)");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@@ -164,9 +169,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_in_list_2()
{
var list = new List<int> { 1, 2, 3 };
_subject = Where(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject = WhereMeta(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject.ToString().Should().Be($"((\"Movies\".\"CleanTitle\" = @Clause1_P1) AND (\"Movies\".\"Id\" IN (1, 2, 3)))");
_subject.ToString().Should().Be($"((\"MovieMetadata\".\"CleanTitle\" = @Clause1_P1) AND (\"MovieMetadata\".\"Id\" IN (1, 2, 3)))");
}
[Test]
@@ -174,35 +179,35 @@ namespace NzbDrone.Core.Test.Datastore
{
var list = new List<string> { "first", "second", "third" };
_subject = Where(x => list.Contains(x.CleanTitle));
_subject = WhereMeta(x => list.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IN @Clause1_P1)");
}
[Test]
public void enum_as_int()
{
_subject = Where(x => x.Status == MovieStatusType.Announced);
_subject = WhereMeta(x => x.Status == MovieStatusType.Announced);
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = @Clause1_P1)");
}
[Test]
public void enum_in_list()
{
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" IN @Clause1_P1)");
}
[Test]
public void enum_in_array()
{
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" IN @Clause1_P1)");
}
}
}
@@ -53,7 +53,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[TestCase(60, 1000, false)]
public void single_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
{
_movie.Runtime = runtime;
_movie.MovieMetadata.Value.Runtime = runtime;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = sizeInMegaBytes.Megabytes();
@@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_size_is_zero()
{
_movie.Runtime = 120;
_movie.MovieMetadata.Value.Runtime = 120;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 0;
_qualityType.MinSize = 10;
@@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_unlimited_30_minute()
{
_movie.Runtime = 30;
_movie.MovieMetadata.Value.Runtime = 30;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 18457280000;
_qualityType.MaxSize = null;
@@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_unlimited_60_minute()
{
_movie.Runtime = 60;
_movie.MovieMetadata.Value.Runtime = 60;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 36857280000;
_qualityType.MaxSize = null;
@@ -97,7 +97,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_use_110_minutes_if_runtime_is_0()
{
_movie.Runtime = 0;
_movie.MovieMetadata.Value.Runtime = 0;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 1095.Megabytes();
@@ -31,7 +31,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
Language = Language.English
},
OriginalLanguage = Language.French
MovieMetadata = new MovieMetadata
{
OriginalLanguage = Language.French
}
}
};
}
@@ -66,7 +66,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
MinFormatScore = 0
})
.With(m => m.Title = "A Movie")
.With(m => m.Runtime = runtime).Build();
.With(m => m.MovieMetadata.Value.Runtime = runtime).Build();
remoteMovie.Release = new ReleaseInfo();
remoteMovie.Release.PublishDate = DateTime.Now.AddDays(-age);
@@ -0,0 +1,66 @@
<rss xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:nyaa="https://nyaa.si/xmlns/nyaa" version="2.0">
<channel>
<title>Nyaa - Home - Torrent File RSS</title>
<description>RSS Feed for Home</description>
<link>https://nyaa.si/</link>
<atom:link href="https://nyaa.si/?page=rss" rel="self" type="application/rss+xml"/>
<item>
<title>[Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv</title>
<link>https://nyaa.si/download/1424896.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424896</guid>
<pubDate>Tue, 24 Aug 2021 22:18:46 -0000</pubDate>
<nyaa:seeders>4</nyaa:seeders>
<nyaa:leechers>3</nyaa:leechers>
<nyaa:downloads>2</nyaa:downloads>
<nyaa:infoHash>e8ca5e20eca876339f41c3d9e95ea66c1d7caaee</nyaa:infoHash>
<nyaa:categoryId>1_3</nyaa:categoryId>
<nyaa:category>Anime - Non-English-translated</nyaa:category>
<nyaa:size>609.6 MiB</nyaa:size>
<nyaa:comments>0</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424896">#1424896 | [Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv</a> | 609.6 MiB | Anime - Non-English-translated | E8CA5E20ECA876339F41C3D9E95EA66C1D7CAAEE ]]>
</description>
</item>
<item>
<title>Macross Zero (BDRip 1920x1080p x265 HEVC TrueHD, FLAC 5.1+2.0)[sxales]</title>
<link>https://nyaa.si/download/1424895.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424895</guid>
<pubDate>Tue, 24 Aug 2021 22:03:11 -0000</pubDate>
<nyaa:seeders>23</nyaa:seeders>
<nyaa:leechers>32</nyaa:leechers>
<nyaa:downloads>17</nyaa:downloads>
<nyaa:infoHash>26f37f26d5b3475b41a98dc575fabfa6f8d32a76</nyaa:infoHash>
<nyaa:categoryId>1_2</nyaa:categoryId>
<nyaa:category>Anime - English-translated</nyaa:category>
<nyaa:size>5.7 GiB</nyaa:size>
<nyaa:comments>2</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424895">#1424895 | Macross Zero (BDRip 1920x1080p x265 HEVC TrueHD, FLAC 5.1+2.0)[sxales]</a> | 5.7 GiB | Anime - English-translated | 26F37F26D5B3475B41A98DC575FABFA6F8D32A76 ]]>
</description>
</item>
<item>
<title>Fumetsu no Anata e - 19 [WEBDL 1080p] Ukr DVO</title>
<link>https://nyaa.si/download/1424887.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424887</guid>
<pubDate>Tue, 24 Aug 2021 21:23:06 -0000</pubDate>
<nyaa:seeders>5</nyaa:seeders>
<nyaa:leechers>4</nyaa:leechers>
<nyaa:downloads>4</nyaa:downloads>
<nyaa:infoHash>3e4300e24b39983802162877755aab4380bd137a</nyaa:infoHash>
<nyaa:categoryId>1_3</nyaa:categoryId>
<nyaa:category>Anime - Non-English-translated</nyaa:category>
<nyaa:size>1.4 GiB</nyaa:size>
<nyaa:comments>0</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424887">#1424887 | Fumetsu no Anata e - 19 [WEBDL 1080p] Ukr DVO</a> | 1.4 GiB | Anime - Non-English-translated | 3E4300E24B39983802162877755AAB4380BD137A ]]>
</description>
</item>
</channel>
</rss>
@@ -35,6 +35,11 @@
"title": "Avengers: Endgame",
"year": 2019,
"Guid": []
},
{
"type": "movie",
"title": "Avengers",
"year": 2005
}
]
}
@@ -32,16 +32,16 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
{
movie = Builder<Movie>.CreateListOfSize(amount)
.All()
.With(v => v.Status = MovieStatusType.Released)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Released)
.BuildList();
}
else
{
movie = Builder<Movie>.CreateListOfSize(amount)
.All()
.With(v => v.Status = MovieStatusType.Released)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Released)
.Random(deleted)
.With(v => v.Status = MovieStatusType.Deleted)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Deleted)
.BuildList();
}
@@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_alternative_title_items()
{
var altTitle = Builder<AlternativeTitle>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.BuildNew();
@@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_alternative_title_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var altTitle = Builder<AlternativeTitle>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(altTitle);
@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_credit_items()
{
var credit = Builder<Credit>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Name = "Some Credit")
.BuildNew();
@@ -27,14 +27,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_credit_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var credit = Builder<Credit>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Name = "Some Credit")
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(credit);
@@ -0,0 +1,60 @@
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Housekeeping.Housekeepers;
using NzbDrone.Core.ImportLists.ImportListMovies;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Translations;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
{
[TestFixture]
public class CleanupOrphanedMovieMetadataFixture : DbTest<CleanupOrphanedMovieMetadata, MovieMetadata>
{
[Test]
public void should_delete_orphaned_movie_metadata_items()
{
var metadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(metadata);
Subject.Clean();
AllStoredModels.Should().BeEmpty();
}
[Test]
public void should_not_delete_unorphaned_movie_metadata_items()
{
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movieMetadata);
var movie = Builder<Movie>.CreateNew()
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(movie);
Subject.Clean();
AllStoredModels.Should().HaveCount(1);
}
[Test]
public void should_not_delete_unorphaned_movie_metadata_items_for_lists()
{
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movieMetadata);
var movie = Builder<ImportListMovie>.CreateNew()
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(movie);
Subject.Clean();
AllStoredModels.Should().HaveCount(1);
}
}
}
@@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_movie_translation_items()
{
var translation = Builder<MovieTranslation>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.BuildNew();
@@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_movie_translation_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var translation = Builder<MovieTranslation>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(translation);
@@ -38,8 +38,8 @@ namespace NzbDrone.Core.Test.ImportListTests
.Build().ToList();
Mocker.GetMock<ISearchForNewMovie>()
.Setup(v => v.MapMovieToTmdbMovie(It.IsAny<Movie>()))
.Returns<Movie>(m => new Movie { TmdbId = m.TmdbId });
.Setup(v => v.MapMovieToTmdbMovie(It.IsAny<MovieMetadata>()))
.Returns<MovieMetadata>(m => new MovieMetadata { TmdbId = m.TmdbId });
}
private void GivenList(int id, bool enabled, bool enabledAuto, ImportListFetchResult fetchResult)
@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
.Returns(_movie);
Mocker.GetMock<IMovieTranslationService>()
.Setup(s => s.GetAllTranslationsForMovie(It.IsAny<int>()))
.Setup(s => s.GetAllTranslationsForMovieMetadata(It.IsAny<int>()))
.Returns(new List<MovieTranslation>());
}
@@ -25,7 +25,9 @@ namespace NzbDrone.Core.Test.IndexerTests.NyaaTests
};
}
[Test]
/* [Test]
// Legacy Nyaa feed test
public void should_parse_recent_feed_from_Nyaa()
{
var recentFeed = ReadAllText(@"Files/Indexers/Nyaa/Nyaa.xml");
@@ -53,6 +55,35 @@ namespace NzbDrone.Core.Test.IndexerTests.NyaaTests
torrentInfo.MagnetUrl.Should().Be(null);
torrentInfo.Peers.Should().Be(2 + 1);
torrentInfo.Seeders.Should().Be(1);
}*/
[Test]
public void should_parse_2021_recent_feed_from_Nyaa()
{
var recentFeed = ReadAllText(@"Files/Indexers/Nyaa/Nyaa2021.xml");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(3);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Title.Should().Be("[Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("https://nyaa.si/download/1424896.torrent");
torrentInfo.InfoUrl.Should().Be("https://nyaa.si/view/1424896");
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("Tue, 24 Aug 2021 22:18:46"));
torrentInfo.Size.Should().Be(639211930); //609.6 MiB
torrentInfo.MagnetUrl.Should().Be(null);
torrentInfo.Seeders.Should().Be(4);
torrentInfo.Peers.Should().Be(3 + 4);
}
}
}
@@ -27,7 +27,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
_movie = Builder<Movie>.CreateNew()
.With(v => v.Id = 2)
.With(v => v.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
.With(v => v.MovieMetadata.Value.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
.Build();
Mocker.GetMock<IMovieService>().Setup(m => m.GetMovie(It.Is<int>(id => id == _movie.Id))).Returns(_movie);
@@ -255,7 +255,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(imported.Select(i => new ImportResult(i)).ToList());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);
@@ -324,7 +324,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(imported.Select(i => new ImportResult(i)).ToList());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);
@@ -431,7 +431,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(new List<ImportResult>());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
.With(m => m.OriginalLanguage = Language.English)
.With(m => m.MovieMetadata.Value.OriginalLanguage = Language.English)
.Build();
_localMovie = Builder<LocalMovie>.CreateNew()
@@ -72,7 +72,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators
{
var result = Subject.Aggregate(_localMovie, null, false);
result.Languages.Should().Contain(_movie.OriginalLanguage);
result.Languages.Should().Contain(_movie.MovieMetadata.Value.OriginalLanguage);
}
[Test]
@@ -16,20 +16,20 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
[TestFixture]
public class DetectSampleFixture : CoreTest<DetectSample>
{
private Movie _movie;
private MovieMetadata _movie;
private LocalMovie _localMovie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(s => s.Runtime = 30)
.Build();
_localMovie = new LocalMovie
{
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi",
Movie = _movie,
Movie = new Movie { MovieMetadata = _movie },
Quality = new QualityModel(Quality.HDTV720p)
};
}
@@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
{
GivenRuntime(120);
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path);
Mocker.GetMock<IVideoFileInfoReader>().Verify(v => v.GetRunTime(It.IsAny<string>()), Times.Once());
@@ -152,7 +152,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
.Setup(s => s.GetRunTime(It.IsAny<string>()))
.Returns((TimeSpan?)null);
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.Indeterminate);
ExceptionVerification.ExpectedErrors(1);
@@ -160,13 +160,13 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
private void ShouldBeSample()
{
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.Sample);
}
private void ShouldBeNotSample()
{
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.NotSample);
}
}
@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
details.Title.Should().Be(title);
}
private void ValidateMovie(Movie movie)
private void ValidateMovie(MovieMetadata movie)
{
movie.Should().NotBeNull();
movie.Title.Should().NotBeNullOrWhiteSpace();
@@ -41,7 +41,6 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
movie.ImdbId.Should().NotBeNullOrWhiteSpace();
movie.Studio.Should().NotBeNullOrWhiteSpace();
movie.Runtime.Should().BeGreaterThan(0);
movie.TitleSlug.Should().NotBeNullOrWhiteSpace();
//series.TvRageId.Should().BeGreaterThan(0);
movie.TmdbId.Should().BeGreaterThan(0);
@@ -20,14 +20,13 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class AddMovieFixture : CoreTest<AddMovieService>
{
private Movie _fakeMovie;
private MovieMetadata _fakeMovie;
[SetUp]
public void Setup()
{
_fakeMovie = Builder<Movie>
_fakeMovie = Builder<MovieMetadata>
.CreateNew()
.With(s => s.Path = null)
.Build();
}
@@ -35,7 +34,7 @@ namespace NzbDrone.Core.Test.MovieTests
{
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(tmdbId))
.Returns(new Tuple<Movie, List<Credit>>(_fakeMovie, new List<Credit>()));
.Returns(new Tuple<MovieMetadata, List<Credit>>(_fakeMovie, new List<Credit>()));
}
private void GivenValidPath()
@@ -18,16 +18,17 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private AlternativeTitle _title2;
private AlternativeTitle _title3;
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
var titles = Builder<AlternativeTitle>.CreateListOfSize(3).All().With(t => t.MovieId = 0).Build();
var titles = Builder<AlternativeTitle>.CreateListOfSize(3).All().With(t => t.MovieMetadataId = 0).Build();
_title1 = titles[0];
_title2 = titles[1];
_title3 = titles[2];
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(m => m.CleanTitle = "myothertitle")
.With(m => m.Id = 1)
.Build();
@@ -35,7 +36,7 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private void GivenExistingTitles(params AlternativeTitle[] titles)
{
Mocker.GetMock<IAlternativeTitleRepository>().Setup(r => r.FindByMovieId(_movie.Id))
Mocker.GetMock<IAlternativeTitleRepository>().Setup(r => r.FindByMovieMetadataId(_movie.Id))
.Returns(titles.ToList());
}
@@ -72,7 +73,7 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
{
GivenExistingTitles();
var titles = new List<AlternativeTitle> { _title1 };
var movie = Builder<Movie>.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build();
var movie = Builder<MovieMetadata>.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build();
Subject.UpdateTitles(titles, movie);
@@ -87,8 +88,8 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
Subject.UpdateTitles(titles, _movie);
_title1.MovieId.Should().Be(_movie.Id);
_title2.MovieId.Should().Be(_movie.Id);
_title1.MovieMetadataId.Should().Be(_movie.Id);
_title2.MovieMetadataId.Should().Be(_movie.Id);
}
[Test]
@@ -32,18 +32,18 @@ namespace NzbDrone.Core.Test.MovieTests.CreditTests
var credits = Builder<Credit>.CreateListOfSize(5)
.TheFirst(1)
.With(c => c.Id = 0)
.With(c => c.MovieId = _movie2.Id)
.With(c => c.MovieMetadataId = _movie2.Id)
.TheRest()
.With(c => c.Id = 0)
.With(c => c.MovieId = _movie1.Id)
.With(c => c.MovieMetadataId = _movie1.Id)
.BuildListOfNew();
Db.InsertMany(credits);
Subject.DeleteForMovies(new List<int> { _movie1.Id });
var removedMovieCredits = Subject.FindByMovieId(_movie1.Id);
var nonRemovedMovieCredits = Subject.FindByMovieId(_movie2.Id);
var removedMovieCredits = Subject.FindByMovieMetadataId(_movie1.Id);
var nonRemovedMovieCredits = Subject.FindByMovieMetadataId(_movie2.Id);
removedMovieCredits.Should().HaveCount(0);
nonRemovedMovieCredits.Should().HaveCount(1);
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
@@ -18,25 +18,25 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private Credit _credit2;
private Credit _credit3;
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
var credits = Builder<Credit>.CreateListOfSize(3)
.All()
.With(t => t.MovieId = 0).Build();
.With(t => t.MovieMetadataId = 0).Build();
_credit1 = credits[0];
_credit2 = credits[1];
_credit3 = credits[2];
_movie = Builder<Movie>.CreateNew().With(m => m.Id = 1).Build();
_movie = Builder<MovieMetadata>.CreateNew().With(m => m.Id = 1).Build();
}
private void GivenExistingCredits(params Credit[] credits)
{
Mocker.GetMock<ICreditRepository>().Setup(r => r.FindByMovieId(_movie.Id))
Mocker.GetMock<ICreditRepository>().Setup(r => r.FindByMovieMetadataId(_movie.Id))
.Returns(credits.ToList());
}
@@ -77,8 +77,8 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
Subject.UpdateCredits(titles, _movie);
_credit1.MovieId.Should().Be(_movie.Id);
_credit2.MovieId.Should().Be(_movie.Id);
_credit1.MovieMetadataId.Should().Be(_movie.Id);
_credit2.MovieMetadataId.Should().Be(_movie.Id);
}
[Test]
@@ -21,9 +21,9 @@ namespace NzbDrone.Core.Test.MovieTests
private void SetMovieProperties(DateTime? cinema, DateTime? physical, DateTime? digital, MovieStatusType minimumAvailability)
{
_movie.InCinemas = cinema;
_movie.PhysicalRelease = physical;
_movie.DigitalRelease = digital;
_movie.MovieMetadata.Value.InCinemas = cinema;
_movie.MovieMetadata.Value.PhysicalRelease = physical;
_movie.MovieMetadata.Value.DigitalRelease = digital;
_movie.MinimumAvailability = minimumAvailability;
}
@@ -0,0 +1,62 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.MovieTests.MovieMetadataRepositoryTests
{
[TestFixture]
public class MovieMetadataRepositoryFixture : DbTest<MovieMetadataRepository, MovieMetadata>
{
private MovieMetadataRepository _movieMetadataRepo;
private List<MovieMetadata> _metadataList;
[SetUp]
public void Setup()
{
_movieMetadataRepo = Mocker.Resolve<MovieMetadataRepository>();
_metadataList = Builder<MovieMetadata>.CreateListOfSize(10).All().With(x => x.Id = 0).BuildList();
}
[Test]
public void upsert_many_should_insert_list_of_new()
{
var updated = _movieMetadataRepo.UpsertMany(_metadataList);
AllStoredModels.Should().HaveCount(_metadataList.Count);
updated.Should().BeTrue();
}
[Test]
public void upsert_many_should_upsert_existing_with_id_0()
{
var clone = _metadataList.JsonClone();
var updated = _movieMetadataRepo.UpsertMany(clone);
updated.Should().BeTrue();
AllStoredModels.Should().HaveCount(_metadataList.Count);
updated = _movieMetadataRepo.UpsertMany(_metadataList);
updated.Should().BeFalse();
AllStoredModels.Should().HaveCount(_metadataList.Count);
}
[Test]
public void upsert_many_should_upsert_mixed_list_of_old_and_new()
{
var clone = _metadataList.Take(5).ToList().JsonClone();
var updated = _movieMetadataRepo.UpsertMany(clone);
updated.Should().BeTrue();
AllStoredModels.Should().HaveCount(clone.Count);
updated = _movieMetadataRepo.UpsertMany(_metadataList);
updated.Should().BeTrue();
AllStoredModels.Should().HaveCount(_metadataList.Count);
}
}
}
@@ -19,15 +19,15 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
{
_candidates = Builder<Movie>.CreateListOfSize(3)
.TheFirst(1)
.With(x => x.CleanTitle = "batman")
.With(x => x.MovieMetadata.Value.CleanTitle = "batman")
.With(x => x.Year = 2000)
.TheNext(1)
.With(x => x.CleanTitle = "batman")
.With(x => x.MovieMetadata.Value.CleanTitle = "batman")
.With(x => x.Year = 1999)
.TheRest()
.With(x => x.CleanTitle = "darkknight")
.With(x => x.MovieMetadata.Value.CleanTitle = "darkknight")
.With(x => x.Year = 2008)
.With(x => x.AlternativeTitles = new List<AlternativeTitle>
.With(x => x.MovieMetadata.Value.AlternativeTitles = new List<AlternativeTitle>
{
new AlternativeTitle
{
@@ -1,79 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MovieTests
{
[TestFixture]
public class MovieTitleSlugValidatorFixture : CoreTest<MovieTitleSlugValidator>
{
private List<Movie> _movies;
private TestValidator<Movie> _validator;
[SetUp]
public void Setup()
{
_movies = Builder<Movie>.CreateListOfSize(1)
.Build()
.ToList();
_validator = new TestValidator<Movie>
{
v => v.RuleFor(s => s.TitleSlug).SetValidator(Subject)
};
Mocker.GetMock<IMovieService>()
.Setup(s => s.AllMovieTitleSlugs())
.Returns(_movies.ToDictionary(m => m.Id, m => m.TitleSlug));
}
[Test]
public void should_not_be_valid_if_there_is_an_existing_movie_with_the_same_title_slug()
{
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovie(_movies.First().Id))
.Returns(_movies.First());
var movie = Builder<Movie>.CreateNew()
.With(s => s.Id = 100)
.With(s => s.TitleSlug = _movies.First().TitleSlug)
.Build();
_validator.Validate(movie).IsValid.Should().BeFalse();
}
[Test]
public void should_be_valid_if_there_is_not_an_existing_movie_with_the_same_title_slug()
{
var movie = Builder<Movie>.CreateNew()
.With(s => s.TitleSlug = "MyTitleSlug")
.Build();
_validator.Validate(movie).IsValid.Should().BeTrue();
}
[Test]
public void should_be_valid_if_there_is_an_existing_movie_with_a_null_title_slug()
{
_movies.First().TitleSlug = null;
var movie = Builder<Movie>.CreateNew()
.With(s => s.TitleSlug = "MyTitleSlug")
.Build();
_validator.Validate(movie).IsValid.Should().BeTrue();
}
[Test]
public void should_be_valid_when_updating_an_existing_movie()
{
_validator.Validate(_movies.First().JsonClone()).IsValid.Should().BeTrue();
}
}
}
@@ -18,17 +18,26 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class RefreshMovieServiceFixture : CoreTest<RefreshMovieService>
{
private Movie _movie;
private MovieMetadata _movie;
private Movie _existingMovie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(s => s.Status = MovieStatusType.Released)
.Build();
_existingMovie = Builder<Movie>.CreateNew()
.With(s => s.MovieMetadata.Value.Status = MovieStatusType.Released)
.Build();
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovie(_movie.Id))
.Returns(_existingMovie);
Mocker.GetMock<IMovieMetadataService>()
.Setup(s => s.Get(_movie.Id))
.Returns(_movie);
Mocker.GetMock<IProvideMovieInfo>()
@@ -36,11 +45,11 @@ namespace NzbDrone.Core.Test.MovieTests
.Callback<int>((i) => { throw new MovieNotFoundException(i); });
}
private void GivenNewMovieInfo(Movie movie)
private void GivenNewMovieInfo(MovieMetadata movie)
{
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(_movie.TmdbId))
.Returns(new Tuple<Movie, List<Credit>>(movie, new List<Credit>()));
.Returns(new Tuple<MovieMetadata, List<Credit>>(movie, new List<Credit>()));
}
[Test]
@@ -53,8 +62,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.First().ImdbId == newMovieInfo.ImdbId), true));
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.ImdbId == newMovieInfo.ImdbId)));
}
[Test]
@@ -62,8 +71,8 @@ namespace NzbDrone.Core.Test.MovieTests
{
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<Movie>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
ExceptionVerification.ExpectedErrors(1);
}
@@ -78,8 +87,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.First().TmdbId == newMovieInfo.TmdbId), true));
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.TmdbId == newMovieInfo.TmdbId)));
ExceptionVerification.ExpectedWarns(1);
}
@@ -89,8 +98,8 @@ namespace NzbDrone.Core.Test.MovieTests
{
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<Movie>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
ExceptionVerification.ExpectedErrors(1);
}
@@ -102,8 +111,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.IsAny<Movie>()), Times.Never());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.IsAny<MovieMetadata>()), Times.Never());
ExceptionVerification.ExpectedErrors(1);
}
@@ -10,12 +10,12 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class ShouldRefreshMovieFixture : TestBase<ShouldRefreshMovie>
{
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(v => v.Status = MovieStatusType.InCinemas)
.With(m => m.PhysicalRelease = DateTime.Today.AddDays(-100))
.Build();
@@ -50,7 +50,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
_movie = Builder<Movie>
.CreateNew()
.With(s => s.Title = "South Park")
.With(s => s.OriginalTitle = "South of the Park")
.With(s => s.MovieMetadata.Value.OriginalTitle = "South of the Park")
.Build();
_namingConfig = NamingConfig.Default;
@@ -70,7 +70,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
.Returns(new List<CustomFormat>());
Mocker.GetMock<IMovieTranslationService>()
.Setup(v => v.GetAllTranslationsForMovie(It.IsAny<int>()))
.Setup(v => v.GetAllTranslationsForMovieMetadata(It.IsAny<int>()))
.Returns(_movieTranslations);
}
@@ -206,7 +206,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_original_title()
{
_namingConfig.StandardMovieFormat = "{Movie OriginalTitle}";
_movie.OriginalTitle = "South of the Park";
_movie.MovieMetadata.Value.OriginalTitle = "South of the Park";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("South of the Park");
@@ -216,7 +216,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_certification()
{
_namingConfig.StandardMovieFormat = "{Movie Certification}";
_movie.Certification = "R";
_movie.MovieMetadata.Value.Certification = "R";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("R");
@@ -226,7 +226,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_collection()
{
_namingConfig.StandardMovieFormat = "{Movie Collection}";
_movie.Collection = new MovieCollection { Name = "South Part Collection" };
_movie.MovieMetadata.Value.Collection = new MovieCollection { Name = "South Part Collection" };
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("South Part Collection");
@@ -16,7 +16,10 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
var releaseInfo = new ParsedMovieInfo();
var movie = new Movies.Movie
{
OriginalLanguage = Language.English
MovieMetadata = new Movies.MovieMetadata
{
OriginalLanguage = Language.English
}
};
var result = Subject.AugmentMovieInfo(releaseInfo, movie);
result.ExtraInfo.Should().ContainKey("OriginalLanguage");
@@ -36,11 +36,11 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
{
_movie = Builder<Movie>.CreateNew()
.With(m => m.Title = "Fack Ju Göthe 2")
.With(m => m.CleanTitle = "fackjugoethe2")
.With(m => m.MovieMetadata.Value.CleanTitle = "fackjugoethe2")
.With(m => m.Year = 2015)
.With(m => m.AlternativeTitles = new List<AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })
.With(m => m.Translations = new List<MovieTranslation> { new MovieTranslation { Title = "Translated Title", CleanTitle = "translatedtitle" } })
.With(m => m.OriginalLanguage = Language.English)
.With(m => m.MovieMetadata.Value.AlternativeTitles = new List<AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })
.With(m => m.MovieMetadata.Value.Translations = new List<MovieTranslation> { new MovieTranslation { Title = "Translated Title", CleanTitle = "translatedtitle" } })
.With(m => m.MovieMetadata.Value.OriginalLanguage = Language.English)
.Build();
_parsedMovieInfo = new ParsedMovieInfo
@@ -66,14 +66,14 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
_alternativeTitleInfo = new ParsedMovieInfo
{
MovieTitles = new List<string> { _movie.AlternativeTitles.First().Title },
MovieTitles = new List<string> { _movie.MovieMetadata.Value.AlternativeTitles.First().Title },
Languages = new List<Language> { Language.English },
Year = _movie.Year,
};
_translationTitleInfo = new ParsedMovieInfo
{
MovieTitles = new List<string> { _movie.Translations.First().Title },
MovieTitles = new List<string> { _movie.MovieMetadata.Value.Translations.First().Title },
Languages = new List<Language> { Language.English },
Year = _movie.Year,
};
@@ -99,6 +99,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Crappy Anime Movie Name 2017 [RH] [Blu-ray][MKV][h264 10-bit][1080p][FLAC 5.1][Dual Audio][Softsubs (RH)]", "RH")]
[TestCase("Yet Another Anime Movie 2012 [Kametsu] [Blu-ray][MKV][h264 10-bit][1080p][FLAC 5.1][Dual Audio][Softsubs (Kametsu)]", "Kametsu")]
[TestCase("Another.Anime.Film.Name.2016.JPN.Blu-Ray.Remux.AVC.DTS-MA.BluDragon", "BluDragon")]
[TestCase("A Movie in the Name (1964) (1080p BluRay x265 r00t)", "r00t")]
public void should_parse_exception_release_group(string title, string expected)
{
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);
@@ -24,6 +24,7 @@ namespace NzbDrone.Core.Test.UpdateTests
Subject.GetLatestUpdate("develop", new Version(10, 0)).Should().BeNull();
}
[Ignore("Pending linux-x86 release")]
[Test]
public void finds_update_when_version_lower()
{
@@ -39,6 +40,7 @@ namespace NzbDrone.Core.Test.UpdateTests
Subject.GetLatestUpdate("invalid_branch", new Version(0, 2)).Should().NotBeNull();
}
[Ignore("Pending linux-x86 release")]
[Test]
public void should_get_recent_updates()
{
@@ -45,11 +45,13 @@ namespace NzbDrone.Core.Configuration
string SslCertPassword { get; }
string UrlBase { get; }
string UiFolder { get; }
string InstanceName { get; }
bool UpdateAutomatically { get; }
UpdateMechanism UpdateMechanism { get; }
string UpdateScriptPath { get; }
string SyslogServer { get; }
int SyslogPort { get; }
string SyslogLevel { get; }
string PostgresHost { get; }
int PostgresPort { get; }
string PostgresUser { get; }
@@ -223,6 +225,7 @@ namespace NzbDrone.Core.Configuration
}
public string UiFolder => BuildInfo.IsDebug ? Path.Combine("..", "UI") : "UI";
public string InstanceName => GetValue("InstanceName", BuildInfo.AppName);
public bool UpdateAutomatically => GetValueBoolean("UpdateAutomatically", false, false);
@@ -231,8 +234,11 @@ namespace NzbDrone.Core.Configuration
public string UpdateScriptPath => GetValue("UpdateScriptPath", "", false);
public string SyslogServer => GetValue("SyslogServer", "", persist: false);
public int SyslogPort => GetValueInt("SyslogPort", 514, persist: false);
public string SyslogLevel => GetValue("SyslogLevel", LogLevel, false).ToLowerInvariant();
public int GetValueInt(string key, int defaultValue, bool persist = true)
{
return Convert.ToInt32(GetValue(key, defaultValue, persist));
@@ -76,20 +76,20 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movieFile.Movie.Title },
MovieTitles = new List<string>() { movieFile.Movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = sceneName.SimplifyReleaseTitle(),
Quality = movieFile.Quality,
Languages = movieFile.Languages,
ReleaseGroup = movieFile.ReleaseGroup,
Edition = movieFile.Edition,
Year = movieFile.Movie.Year,
ImdbId = movieFile.Movie.ImdbId,
Year = movieFile.Movie.MovieMetadata.Value.Year,
ImdbId = movieFile.Movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", movieFile.IndexerFlags },
{ "Size", movieFile.Size },
{ "Filename", Path.GetFileName(movieFile.RelativePath) },
{ "OriginalLanguage", movieFile.Movie.OriginalLanguage }
{ "OriginalLanguage", movieFile.Movie.MovieMetadata.Value.OriginalLanguage }
}
};
@@ -114,14 +114,14 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.Title },
MovieTitles = new List<string>() { movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? blocklist.SourceTitle.SimplifyReleaseTitle(),
Quality = blocklist.Quality,
Languages = blocklist.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
Edition = parsed?.Edition,
Year = movie.Year,
ImdbId = movie.ImdbId,
Year = movie.MovieMetadata.Value.Year,
ImdbId = movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", blocklist.IndexerFlags },
@@ -142,14 +142,14 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.Title },
MovieTitles = new List<string>() { movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? history.SourceTitle.SimplifyReleaseTitle(),
Quality = history.Quality,
Languages = history.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
Edition = parsed?.Edition,
Year = movie.Year,
ImdbId = movie.ImdbId,
Year = movie.MovieMetadata.Value.Year,
ImdbId = movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", flags },
@@ -47,13 +47,6 @@ namespace NzbDrone.Core.Datastore
return builder.Where(wb.ToString(), wb.Parameters);
}
public static SqlBuilder WherePostgres<TModel>(this SqlBuilder builder, Expression<Func<TModel, bool>> filter)
{
var wb = new WhereBuilderPostgres(filter, true, builder.Sequence);
return builder.Where(wb.ToString(), wb.Parameters);
}
public static SqlBuilder OrWhere<TModel>(this SqlBuilder builder, Expression<Func<TModel, bool>> filter)
{
var wb = GetWhereBuilder(builder.DatabaseType, filter, true, builder.Sequence);
@@ -0,0 +1,151 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(207)]
public class movie_metadata : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.TableForModel("MovieMetadata")
.WithColumn("TmdbId").AsInt32().Unique()
.WithColumn("ImdbId").AsString().Nullable()
.WithColumn("Images").AsString()
.WithColumn("Genres").AsString().Nullable()
.WithColumn("Title").AsString()
.WithColumn("SortTitle").AsString().Nullable()
.WithColumn("CleanTitle").AsString().Nullable().Indexed()
.WithColumn("OriginalTitle").AsString().Nullable()
.WithColumn("CleanOriginalTitle").AsString().Nullable().Indexed()
.WithColumn("OriginalLanguage").AsInt32()
.WithColumn("Status").AsInt32()
.WithColumn("LastInfoSync").AsDateTime().Nullable()
.WithColumn("Runtime").AsInt32()
.WithColumn("InCinemas").AsDateTime().Nullable()
.WithColumn("PhysicalRelease").AsDateTime().Nullable()
.WithColumn("DigitalRelease").AsDateTime().Nullable()
.WithColumn("Year").AsInt32().Nullable()
.WithColumn("SecondaryYear").AsInt32().Nullable()
.WithColumn("Ratings").AsString().Nullable()
.WithColumn("Recommendations").AsString()
.WithColumn("Certification").AsString().Nullable()
.WithColumn("YouTubeTrailerId").AsString().Nullable()
.WithColumn("Collection").AsString().Nullable()
.WithColumn("Studio").AsString().Nullable()
.WithColumn("Overview").AsString().Nullable()
.WithColumn("Website").AsString().Nullable()
.WithColumn("Popularity").AsFloat().Nullable();
// Transfer metadata from Movies to MovieMetadata
Execute.Sql(@"INSERT INTO ""MovieMetadata"" (""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""CleanTitle"", ""OriginalTitle"", ""CleanOriginalTitle"", ""OriginalLanguage"", ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""SecondaryYear"", ""Recommendations"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website"")
SELECT ""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""CleanTitle"", ""OriginalTitle"", ""CleanTitle"", ""OriginalLanguage"", ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""SecondaryYear"", ""Recommendations"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website""
FROM ""Movies""");
// Transfer metadata from ImportListMovies to MovieMetadata if not already in
Execute.Sql(@"INSERT INTO ""MovieMetadata"" (""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""CleanTitle"", ""OriginalTitle"", ""CleanOriginalTitle"", ""OriginalLanguage"", ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""Recommendations"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website"")
SELECT ""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""Title"", ""OriginalTitle"", ""OriginalTitle"", 1, ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", '[]', ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website""
FROM ""ImportListMovies""
WHERE ""ImportListMovies"".""TmdbId"" NOT IN ( SELECT ""MovieMetadata"".""TmdbId"" FROM ""MovieMetadata"" )
AND ""ImportListMovies"".""Id"" IN ( SELECT MIN(""Id"") FROM ""ImportListMovies"" GROUP BY ""TmdbId"" )");
// Add an MovieMetadataId column to Movies
Alter.Table("Movies").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);
Alter.Table("AlternativeTitles").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);
Alter.Table("Credits").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);
Alter.Table("MovieTranslations").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);
Alter.Table("ImportListMovies").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0).Indexed();
// Update MovieMetadataId
Execute.Sql(@"UPDATE ""Movies""
SET ""MovieMetadataId"" = (SELECT ""MovieMetadata"".""Id""
FROM ""MovieMetadata""
WHERE ""MovieMetadata"".""TmdbId"" = ""Movies"".""TmdbId"")");
Execute.Sql(@"UPDATE ""AlternativeTitles""
SET ""MovieMetadataId"" = (SELECT ""Movies"".""MovieMetadataId""
FROM ""Movies""
WHERE ""Movies"".""Id"" = ""AlternativeTitles"".""MovieId"")");
Execute.Sql(@"UPDATE ""Credits""
SET ""MovieMetadataId"" = (SELECT ""Movies"".""MovieMetadataId""
FROM ""Movies""
WHERE ""Movies"".""Id"" = ""Credits"".""MovieId"")");
Execute.Sql(@"UPDATE ""MovieTranslations""
SET ""MovieMetadataId"" = (SELECT ""Movies"".""MovieMetadataId""
FROM ""Movies""
WHERE ""Movies"".""Id"" = ""MovieTranslations"".""MovieId"")");
Execute.Sql(@"UPDATE ""ImportListMovies""
SET ""MovieMetadataId"" = (SELECT ""MovieMetadata"".""Id""
FROM ""MovieMetadata""
WHERE ""MovieMetadata"".""TmdbId"" = ""ImportListMovies"".""TmdbId"")");
// Alter MovieMetadataId column to be unique on Movies
Alter.Table("Movies").AlterColumn("MovieMetadataId").AsInt32().Unique();
// Remove Movie Link from Metadata Tables
Delete.Column("MovieId").FromTable("AlternativeTitles");
Delete.Column("MovieId").FromTable("Credits");
Delete.Column("MovieId").FromTable("MovieTranslations");
// Remove the columns in Movies now in MovieMetadata
Delete.Column("TmdbId")
.Column("ImdbId")
.Column("Title")
.Column("SortTitle")
.Column("CleanTitle")
.Column("OriginalTitle")
.Column("OriginalLanguage")
.Column("Overview")
.Column("Status")
.Column("LastInfoSync")
.Column("Images")
.Column("Genres")
.Column("Ratings")
.Column("Runtime")
.Column("InCinemas")
.Column("PhysicalRelease")
.Column("DigitalRelease")
.Column("Year")
.Column("SecondaryYear")
.Column("Recommendations")
.Column("Certification")
.Column("YouTubeTrailerId")
.Column("Studio")
.Column("Collection")
.Column("Website")
// as well as the ones no longer used
.Column("LastDiskSync")
.Column("TitleSlug")
.FromTable("Movies");
// Remove the columns in ImportListMovies now in MovieMetadata
Delete.Column("TmdbId")
.Column("ImdbId")
.Column("Title")
.Column("SortTitle")
.Column("Overview")
.Column("Status")
.Column("LastInfoSync")
.Column("OriginalTitle")
.Column("Translations")
.Column("Images")
.Column("Genres")
.Column("Ratings")
.Column("Runtime")
.Column("InCinemas")
.Column("PhysicalRelease")
.Column("DigitalRelease")
.Column("Year")
.Column("Certification")
.Column("YouTubeTrailerId")
.Column("Studio")
.Column("Collection")
.Column("Website")
.FromTable("ImportListMovies");
}
}
}
+14 -2
View File
@@ -109,9 +109,18 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<Movie>("Movies").RegisterModel()
.Ignore(s => s.RootFolderPath)
.Ignore(s => s.Translations);
.Ignore(s => s.Title)
.Ignore(s => s.Year)
.Ignore(s => s.TmdbId)
.Ignore(s => s.ImdbId)
.HasOne(a => a.MovieMetadata, a => a.MovieMetadataId);
Mapper.Entity<ImportListMovie>("ImportListMovies").RegisterModel();
Mapper.Entity<ImportListMovie>("ImportListMovies").RegisterModel()
.Ignore(s => s.Title)
.Ignore(s => s.Year)
.Ignore(s => s.TmdbId)
.Ignore(s => s.ImdbId)
.HasOne(a => a.MovieMetadata, a => a.MovieMetadataId);
Mapper.Entity<AlternativeTitle>("AlternativeTitles").RegisterModel();
@@ -156,6 +165,9 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<DownloadHistory>("DownloadHistory").RegisterModel();
Mapper.Entity<UpdateHistory>("UpdateHistory").RegisterModel();
Mapper.Entity<MovieMetadata>("MovieMetadata").RegisterModel()
.Ignore(s => s.Translations);
}
private static void RegisterMappers()
@@ -174,9 +174,9 @@ namespace NzbDrone.Core.DecisionEngine
var preferredSize = _qualityDefinitionService.Get(remoteMovie.ParsedMovieInfo.Quality.Quality).PreferredSize;
// If no value for preferred it means unlimited so fallback to sort largest is best
if (preferredSize.HasValue && remoteMovie.Movie.Runtime > 0)
if (preferredSize.HasValue && remoteMovie.Movie.MovieMetadata.Value.Runtime > 0)
{
var preferredMovieSize = remoteMovie.Movie.Runtime * preferredSize.Value.Megabytes();
var preferredMovieSize = remoteMovie.Movie.MovieMetadata.Value.Runtime * preferredSize.Value.Megabytes();
// Calculate closest to the preferred size
return Math.Abs((remoteMovie.Release.Size - preferredMovieSize).Round(200.Megabytes())) * (-1);
@@ -34,10 +34,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
var qualityDefinition = _qualityDefinitionService.Get(quality);
if (subject.Movie.Runtime == 0)
if (subject.Movie.MovieMetadata.Value.Runtime == 0)
{
_logger.Warn("{0} has no runtime information using median movie runtime of 110 minutes.", subject.Movie);
subject.Movie.Runtime = 110;
subject.Movie.MovieMetadata.Value.Runtime = 110;
}
if (qualityDefinition.MinSize.HasValue)
@@ -45,7 +45,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
var minSize = qualityDefinition.MinSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime
minSize = minSize * subject.Movie.Runtime;
minSize = minSize * subject.Movie.MovieMetadata.Value.Runtime;
//If the parsed size is smaller than minSize we don't want it
if (subject.Release.Size < minSize)
@@ -61,7 +61,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{
_logger.Debug("Max size is unlimited, skipping check");
}
else if (subject.Movie.Runtime == 0)
else if (subject.Movie.MovieMetadata.Value.Runtime == 0)
{
_logger.Debug("Movie runtime is 0, unable to validate size until it is available, rejecting");
return Decision.Reject("Movie runtime is 0, unable to validate size until it is available");
@@ -71,7 +71,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
var maxSize = qualityDefinition.MaxSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime
maxSize = maxSize * subject.Movie.Runtime;
maxSize = maxSize * subject.Movie.MovieMetadata.Value.Runtime;
//If the parsed size is greater than maxSize we don't want it
if (subject.Release.Size > maxSize)
@@ -27,7 +27,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
return Decision.Accept();
}
var originalLanguage = subject.Movie.OriginalLanguage;
var originalLanguage = subject.Movie.MovieMetadata.Value.OriginalLanguage;
if (wantedLanguage == Language.Original)
{
@@ -68,7 +68,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
_proxy.SetTorrentLabel(actualHash, Settings.MovieCategory, Settings);
}
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)DelugePriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)DelugePriority.First))
@@ -95,7 +95,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
_proxy.SetTorrentLabel(actualHash, Settings.MovieCategory, Settings);
}
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)DelugePriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)DelugePriority.First))
@@ -52,7 +52,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
switch (additionalTag)
{
case (int)AdditionalTags.Collection:
result.Add(remoteMovie.Movie.Collection.Name);
result.Add(remoteMovie.Movie.MovieMetadata.Value.Collection.Name);
break;
case (int)AdditionalTags.Quality:
result.Add(remoteMovie.ParsedMovieInfo.Quality.Quality.ToString());
@@ -70,7 +70,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
result.Add(remoteMovie.Release.Indexer);
break;
case (int)AdditionalTags.Studio:
result.Add(remoteMovie.Movie.Studio);
result.Add(remoteMovie.Movie.MovieMetadata.Value.Studio);
break;
default:
throw new DownloadClientException("Unexpected additional tag ID");
@@ -34,7 +34,7 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents)
{
var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var response = _proxy.DownloadNzb(fileContents, filename, priority, Settings);
@@ -40,7 +40,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
var category = Settings.MovieCategory;
var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var addpaused = Settings.AddPaused;
var response = _proxy.DownloadNzb(fileContent, filename, category, priority, addpaused, Settings);
@@ -73,7 +73,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
var setShareLimits = remoteMovie.SeedConfiguration != null && (remoteMovie.SeedConfiguration.Ratio.HasValue || remoteMovie.SeedConfiguration.SeedTime.HasValue);
var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1);
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
var moveToTop = (isRecentMovie && Settings.RecentMoviePriority == (int)QBittorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)QBittorrentPriority.First);
var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart;
@@ -132,7 +132,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
{
var setShareLimits = remoteMovie.SeedConfiguration != null && (remoteMovie.SeedConfiguration.Ratio.HasValue || remoteMovie.SeedConfiguration.SeedTime.HasValue);
var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1);
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
var moveToTop = (isRecentMovie && Settings.RecentMoviePriority == (int)QBittorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)QBittorrentPriority.First);
var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart;
@@ -288,7 +288,8 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
break;
case "forcedDL": //torrent is being downloaded, and was forced started
case "forcedDL": // torrent is being downloaded, and was forced started
case "forcedMetaDL": // torrent metadata is being forcibly downloaded
case "moving": // torrent is being moved from a folder
case "downloading": // torrent is being downloaded and data is being transferred
item.Status = DownloadItemStatus.Downloading;
@@ -40,7 +40,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContent)
{
var category = Settings.MovieCategory;
var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var response = _proxy.DownloadNzb(fileContent, filename, category, priority, Settings);
@@ -194,7 +194,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteMovie.SeedConfiguration, Settings);
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)TransmissionPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)TransmissionPriority.First))
@@ -210,7 +210,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteMovie.SeedConfiguration, Settings);
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)TransmissionPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)TransmissionPriority.First))
@@ -72,7 +72,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
var priority = (RTorrentPriority)(remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority);
var priority = (RTorrentPriority)(remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority);
_proxy.AddTorrentFromUrl(magnetLink, Settings.MovieCategory, priority, Settings.MovieDirectory, Settings);
@@ -92,7 +92,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
{
var priority = (RTorrentPriority)(remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority);
var priority = (RTorrentPriority)(remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority);
_proxy.AddTorrentFromFile(filename, fileContent, Settings.MovieCategory, priority, Settings.MovieDirectory, Settings);
@@ -64,7 +64,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
}
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)UTorrentPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)UTorrentPriority.First))
@@ -87,7 +87,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
}
var isRecentEpisode = remoteMovie.Movie.IsRecentMovie;
var isRecentEpisode = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentEpisode && Settings.RecentMoviePriority == (int)UTorrentPriority.First) ||
(!isRecentEpisode && Settings.OlderMoviePriority == (int)UTorrentPriority.First))
@@ -120,7 +120,7 @@ namespace NzbDrone.Core.Download
return;
}
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.ImportItem);
if (VerifyImport(trackedDownload, importResults))
{
@@ -67,19 +67,19 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.MediaBrowser
{
var movieElement = new XElement("Movie");
movieElement.Add(new XElement("id", movie.ImdbId));
movieElement.Add(new XElement("Status", movie.Status));
movieElement.Add(new XElement("id", movie.MovieMetadata.Value.ImdbId));
movieElement.Add(new XElement("Status", movie.MovieMetadata.Value.Status));
movieElement.Add(new XElement("Added", movie.Added.ToString("MM/dd/yyyy HH:mm:ss tt")));
movieElement.Add(new XElement("LockData", "false"));
movieElement.Add(new XElement("Overview", movie.Overview));
movieElement.Add(new XElement("Overview", movie.MovieMetadata.Value.Overview));
movieElement.Add(new XElement("LocalTitle", movie.Title));
movieElement.Add(new XElement("Rating", movie.Ratings.Tmdb?.Value ?? 0));
movieElement.Add(new XElement("Rating", movie.MovieMetadata.Value.Ratings.Tmdb?.Value ?? 0));
movieElement.Add(new XElement("ProductionYear", movie.Year));
movieElement.Add(new XElement("RunningTime", movie.Runtime));
movieElement.Add(new XElement("IMDB", movie.ImdbId));
movieElement.Add(new XElement("Genres", movie.Genres.Select(genre => new XElement("Genre", genre))));
movieElement.Add(new XElement("RunningTime", movie.MovieMetadata.Value.Runtime));
movieElement.Add(new XElement("IMDB", movie.MovieMetadata.Value.ImdbId));
movieElement.Add(new XElement("Genres", movie.MovieMetadata.Value.Genres.Select(genre => new XElement("Genre", genre))));
var doc = new XDocument(movieElement);
doc.Save(xw);
@@ -118,9 +118,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox
var details = new XElement("video");
details.Add(new XElement("title", movie.Title));
details.Add(new XElement("genre", string.Join(" / ", movie.Genres)));
details.Add(new XElement("description", movie.Overview));
details.Add(new XElement("length", movie.Runtime));
details.Add(new XElement("genre", string.Join(" / ", movie.MovieMetadata.Value.Genres)));
details.Add(new XElement("description", movie.MovieMetadata.Value.Overview));
details.Add(new XElement("length", movie.MovieMetadata.Value.Runtime));
doc.Add(details);
doc.Save(xw);
@@ -139,7 +139,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox
return new List<ImageFileResult>();
}
var image = movie.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.Images.FirstOrDefault();
var image = movie.MovieMetadata.Value.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.MovieMetadata.Value.Images.FirstOrDefault();
if (image == null)
{
_logger.Trace("Failed to find suitable Movie image for movie {0}.", movie.Title);
@@ -113,8 +113,8 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Wdtv
var details = new XElement("details");
details.Add(new XElement("id", movie.Id));
details.Add(new XElement("title", movie.Title));
details.Add(new XElement("genre", string.Join(" / ", movie.Genres)));
details.Add(new XElement("overview", movie.Overview));
details.Add(new XElement("genre", string.Join(" / ", movie.MovieMetadata.Value.Genres)));
details.Add(new XElement("overview", movie.MovieMetadata.Value.Overview));
doc.Add(details);
doc.Save(xw);
@@ -136,7 +136,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Wdtv
}
//Because we only support one image, attempt to get the Poster type, then if that fails grab the first
var image = movie.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.Images.FirstOrDefault();
var image = movie.MovieMetadata.Value.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.MovieMetadata.Value.Images.FirstOrDefault();
if (image == null)
{
_logger.Trace("Failed to find suitable Movie image for movie {0}.", movie.Title);
@@ -123,14 +123,14 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
_logger.Debug("Generating Movie Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath));
var movieMetadataLanguage = (Settings.MovieMetadataLanguage == (int)Language.Original) ?
(int)movie.OriginalLanguage :
(int)movie.MovieMetadata.Value.OriginalLanguage :
Settings.MovieMetadataLanguage;
var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovie(movie.Id);
var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovieMetadata(movie.MovieMetadataId);
var selectedSettingsLanguage = Language.FindById(movieMetadataLanguage);
var movieTranslation = movieTranslations.FirstOrDefault(mt => mt.Language == selectedSettingsLanguage);
var credits = _creditService.GetAllCreditsForMovie(movie.Id);
var credits = _creditService.GetAllCreditsForMovieMetadata(movie.MovieMetadataId);
var watched = GetExistingWatchedStatus(movie, movieFile.RelativePath);
@@ -142,44 +142,44 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
using (var xw = XmlWriter.Create(sb, xws))
{
var doc = new XDocument();
var thumbnail = movie.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot);
var posters = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Poster);
var fanarts = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart);
var thumbnail = movie.MovieMetadata.Value.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot);
var posters = movie.MovieMetadata.Value.Images.Where(i => i.CoverType == MediaCoverTypes.Poster);
var fanarts = movie.MovieMetadata.Value.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart);
var details = new XElement("movie");
details.Add(new XElement("title", movieTranslation?.Title ?? movie.Title));
details.Add(new XElement("originaltitle", movie.OriginalTitle));
details.Add(new XElement("originaltitle", movie.MovieMetadata.Value.OriginalTitle));
details.Add(new XElement("sorttitle", movie.SortTitle));
details.Add(new XElement("sorttitle", movie.MovieMetadata.Value.SortTitle));
if (movie.Ratings.Tmdb?.Votes > 0 || movie.Ratings.Imdb?.Votes > 0)
if (movie.MovieMetadata.Value.Ratings.Tmdb?.Votes > 0 || movie.MovieMetadata.Value.Ratings.Imdb?.Votes > 0)
{
var setRating = new XElement("ratings");
if (movie.Ratings.Tmdb?.Votes > 0)
if (movie.MovieMetadata.Value.Ratings.Tmdb?.Votes > 0)
{
var setRatethemoviedb = new XElement("rating", new XAttribute("name", "themoviedb"), new XAttribute("max", "10"), new XAttribute("default", "true"));
setRatethemoviedb.Add(new XElement("value", movie.Ratings.Tmdb.Value));
setRatethemoviedb.Add(new XElement("votes", movie.Ratings.Tmdb.Votes));
setRatethemoviedb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Tmdb.Value));
setRatethemoviedb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Tmdb.Votes));
setRating.Add(setRatethemoviedb);
}
if (movie.Ratings.Imdb?.Votes > 0)
if (movie.MovieMetadata.Value.Ratings.Imdb?.Votes > 0)
{
var setRateImdb = new XElement("rating", new XAttribute("name", "imdb"), new XAttribute("max", "10"));
setRateImdb.Add(new XElement("value", movie.Ratings.Imdb.Value));
setRateImdb.Add(new XElement("votes", movie.Ratings.Imdb.Votes));
setRateImdb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Imdb.Value));
setRateImdb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Imdb.Votes));
setRating.Add(setRateImdb);
}
details.Add(setRating);
}
if (movie.Ratings?.Tmdb?.Votes > 0)
if (movie.MovieMetadata.Value.Ratings?.Tmdb?.Votes > 0)
{
details.Add(new XElement("rating", movie.Ratings.Tmdb.Value));
details.Add(new XElement("rating", movie.MovieMetadata.Value.Ratings.Tmdb.Value));
}
details.Add(new XElement("userrating"));
@@ -188,11 +188,11 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
details.Add(new XElement("outline"));
details.Add(new XElement("plot", movieTranslation?.Overview ?? movie.Overview));
details.Add(new XElement("plot", movieTranslation?.Overview ?? movie.MovieMetadata.Value.Overview));
details.Add(new XElement("tagline"));
details.Add(new XElement("runtime", movie.Runtime));
details.Add(new XElement("runtime", movie.MovieMetadata.Value.Runtime));
if (thumbnail != null)
{
@@ -221,9 +221,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
details.Add(fanartElement);
}
if (movie.Certification.IsNotNullOrWhiteSpace())
if (movie.MovieMetadata.Value.Certification.IsNotNullOrWhiteSpace())
{
details.Add(new XElement("mpaa", movie.Certification));
details.Add(new XElement("mpaa", movie.MovieMetadata.Value.Certification));
}
details.Add(new XElement("playcount"));
@@ -237,25 +237,25 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
uniqueId.SetAttributeValue("default", true);
details.Add(uniqueId);
if (movie.ImdbId.IsNotNullOrWhiteSpace())
if (movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace())
{
var imdbId = new XElement("uniqueid", movie.ImdbId);
var imdbId = new XElement("uniqueid", movie.MovieMetadata.Value.ImdbId);
imdbId.SetAttributeValue("type", "imdb");
details.Add(imdbId);
}
foreach (var genre in movie.Genres)
foreach (var genre in movie.MovieMetadata.Value.Genres)
{
details.Add(new XElement("genre", genre));
}
details.Add(new XElement("country"));
if (movie.Collection?.Name != null)
if (movie.MovieMetadata.Value.Collection?.Name != null)
{
var setElement = new XElement("set");
setElement.Add(new XElement("name", movie.Collection.Name));
setElement.Add(new XElement("name", movie.MovieMetadata.Value.Collection.Name));
setElement.Add(new XElement("overview"));
details.Add(setElement);
@@ -284,16 +284,16 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
}
}
if (movie.InCinemas.HasValue)
if (movie.MovieMetadata.Value.InCinemas.HasValue)
{
details.Add(new XElement("premiered", movie.InCinemas.Value.ToString("yyyy-MM-dd")));
details.Add(new XElement("premiered", movie.MovieMetadata.Value.InCinemas.Value.ToString("yyyy-MM-dd")));
}
details.Add(new XElement("year", movie.Year));
details.Add(new XElement("studio", movie.Studio));
details.Add(new XElement("studio", movie.MovieMetadata.Value.Studio));
details.Add(new XElement("trailer", "plugin://plugin.video.youtube/play/?video_id=" + movie.YouTubeTrailerId));
details.Add(new XElement("trailer", "plugin://plugin.video.youtube/play/?video_id=" + movie.MovieMetadata.Value.YouTubeTrailerId));
if (movieFile.MediaInfo != null)
{
@@ -369,10 +369,10 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
if (Settings.MovieMetadataURL)
{
xmlResult += "https://www.themoviedb.org/movie/" + movie.TmdbId;
xmlResult += "https://www.themoviedb.org/movie/" + movie.MovieMetadata.Value.TmdbId;
xmlResult += Environment.NewLine;
xmlResult += "https://www.imdb.com/title/" + movie.ImdbId;
xmlResult += "https://www.imdb.com/title/" + movie.MovieMetadata.Value.ImdbId;
xmlResult += Environment.NewLine;
}
@@ -393,7 +393,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
private IEnumerable<ImageFileResult> ProcessMovieImages(Movie movie)
{
foreach (var image in movie.Images)
foreach (var image in movie.MovieMetadata.Value.Images)
{
var source = _mediaCoverService.GetCoverPath(movie.Id, image.CoverType);
var destination = image.CoverType.ToString().ToLowerInvariant() + Path.GetExtension(source);
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
public override HealthCheck Check()
{
var deletedMovie = _movieService.GetAllMovies().Where(v => v.Status == MovieStatusType.Deleted).ToList();
var deletedMovie = _movieService.GetAllMovies().Where(v => v.MovieMetadata.Value.Status == MovieStatusType.Deleted).ToList();
if (deletedMovie.Empty())
{
@@ -40,12 +40,12 @@ namespace NzbDrone.Core.HealthCheck.Checks
public bool ShouldCheckOnEvent(MoviesDeletedEvent message)
{
return message.Movies.Any(m => m.Status == MovieStatusType.Deleted);
return message.Movies.Any(m => m.MovieMetadata.Value.Status == MovieStatusType.Deleted);
}
public bool ShouldCheckOnEvent(MovieUpdatedEvent message)
{
return message.Movie.Status == MovieStatusType.Deleted;
return message.Movie.MovieMetadata.Value.Status == MovieStatusType.Deleted;
}
}
}
@@ -1,4 +1,4 @@
using Dapper;
using Dapper;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Housekeeping.Housekeepers
@@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
mapper.Execute(@"DELETE FROM ""AlternativeTitles""
WHERE ""Id"" IN (
SELECT ""AlternativeTitles"".""Id"" FROM ""AlternativeTitles""
LEFT OUTER JOIN ""Movies""
ON ""AlternativeTitles"".""MovieId"" = ""Movies"".""Id""
WHERE ""Movies"".""Id"" IS NULL)");
LEFT OUTER JOIN ""MovieMetadata""
ON ""AlternativeTitles"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""MovieMetadata"".""Id"" IS NULL)");
}
}
}
@@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
mapper.Execute(@"DELETE FROM ""Credits""
WHERE ""Id"" IN (
SELECT ""Credits"".""Id"" FROM ""Credits""
LEFT OUTER JOIN ""Movies""
ON ""Credits"".""MovieId"" = ""Movies"".""Id""
WHERE ""Movies"".""Id"" IS NULL)");
LEFT OUTER JOIN ""MovieMetadata""
ON ""Credits"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""MovieMetadata"".""Id"" IS NULL)");
}
}
}
@@ -0,0 +1,28 @@
using Dapper;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Housekeeping.Housekeepers
{
public class CleanupOrphanedMovieMetadata : IHousekeepingTask
{
private readonly IMainDatabase _database;
public CleanupOrphanedMovieMetadata(IMainDatabase database)
{
_database = database;
}
public void Clean()
{
using (var mapper = _database.OpenConnection())
{
mapper.Execute(@"DELETE FROM ""MovieMetadata""
WHERE ""Id"" IN (
SELECT ""MovieMetadata"".""Id"" FROM ""MovieMetadata""
LEFT OUTER JOIN ""Movies"" ON ""Movies"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
LEFT OUTER JOIN ""ImportListMovies"" ON ""ImportListMovies"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""Movies"".""Id"" IS NULL AND ""ImportListMovies"".""Id"" IS NULL)");
}
}
}
}
@@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
mapper.Execute(@"DELETE FROM ""MovieTranslations""
WHERE ""Id"" IN (
SELECT ""MovieTranslations"".""Id"" FROM ""MovieTranslations""
LEFT OUTER JOIN ""Movies""
ON ""MovieTranslations"".""MovieId"" = ""Movies"".""Id""
WHERE ""Movies"".""Id"" IS NULL)");
LEFT OUTER JOIN ""MovieMetadata""
ON ""MovieTranslations"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""MovieMetadata"".""Id"" IS NULL)");
}
}
}
@@ -24,18 +24,21 @@ namespace NzbDrone.Core.ImportLists
private readonly IImportListStatusService _importListStatusService;
private readonly IImportListMovieService _listMovieService;
private readonly ISearchForNewMovie _movieSearch;
private readonly IMovieMetadataService _movieMetadataService;
private readonly Logger _logger;
public FetchAndParseImportListService(IImportListFactory importListFactory,
IImportListStatusService importListStatusService,
IImportListMovieService listMovieService,
ISearchForNewMovie movieSearch,
IMovieMetadataService movieMetadataService,
Logger logger)
{
_importListFactory = importListFactory;
_importListStatusService = importListStatusService;
_listMovieService = listMovieService;
_movieSearch = movieSearch;
_movieMetadataService = movieMetadataService;
_logger = logger;
}
@@ -173,33 +176,16 @@ namespace NzbDrone.Core.ImportLists
private ImportListMovie MapMovieReport(ImportListMovie report)
{
var mappedMovie = _movieSearch.MapMovieToTmdbMovie(new Movie { Title = report.Title, TmdbId = report.TmdbId, ImdbId = report.ImdbId, Year = report.Year });
var mappedMovie = _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = report.Title, TmdbId = report.TmdbId, ImdbId = report.ImdbId, Year = report.Year });
var mappedListMovie = new ImportListMovie { ListId = report.ListId };
if (mappedMovie != null)
{
mappedListMovie.TmdbId = mappedMovie.TmdbId;
mappedListMovie.ImdbId = mappedMovie.ImdbId;
mappedListMovie.Title = mappedMovie.Title;
mappedListMovie.SortTitle = mappedMovie?.SortTitle;
mappedListMovie.Year = mappedMovie.Year;
mappedListMovie.Overview = mappedMovie.Overview;
mappedListMovie.Ratings = mappedMovie.Ratings;
mappedListMovie.Studio = mappedMovie.Studio;
mappedListMovie.Certification = mappedMovie.Certification;
mappedListMovie.Collection = mappedMovie.Collection;
mappedListMovie.Status = mappedMovie.Status;
mappedListMovie.Images = mappedMovie.Images;
mappedListMovie.Website = mappedMovie.Website;
mappedListMovie.YouTubeTrailerId = mappedMovie.YouTubeTrailerId;
mappedListMovie.Translations = mappedMovie.Translations;
mappedListMovie.InCinemas = mappedMovie.InCinemas;
mappedListMovie.PhysicalRelease = mappedMovie.PhysicalRelease;
mappedListMovie.DigitalRelease = mappedMovie.DigitalRelease;
mappedListMovie.Genres = mappedMovie.Genres;
mappedListMovie.Runtime = mappedMovie.Runtime;
mappedListMovie.OriginalTitle = mappedMovie.OriginalTitle;
_movieMetadataService.Upsert(mappedMovie);
mappedListMovie.MovieMetadata = mappedMovie;
mappedListMovie.MovieMetadataId = mappedMovie.Id;
}
return mappedListMovie;
@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Translations;
namespace NzbDrone.Core.ImportLists.ImportListMovies
{
@@ -10,37 +7,35 @@ namespace NzbDrone.Core.ImportLists.ImportListMovies
{
public ImportListMovie()
{
Images = new List<MediaCover.MediaCover>();
Genres = new List<string>();
Translations = new List<MovieTranslation>();
Ratings = new Ratings();
MovieMetadata = new MovieMetadata();
}
public int TmdbId { get; set; }
public string ImdbId { get; set; }
public string Title { get; set; }
public string SortTitle { get; set; }
public MovieStatusType Status { get; set; }
public string Overview { get; set; }
public DateTime? LastInfoSync { get; set; }
public int Runtime { get; set; }
public List<MediaCover.MediaCover> Images { get; set; }
public string Website { get; set; }
public int Year { get; set; }
public Ratings Ratings { get; set; }
public List<string> Genres { get; set; }
public MovieCollection Collection { get; set; }
public string Certification { get; set; }
public DateTime? InCinemas { get; set; }
public DateTime? PhysicalRelease { get; set; }
public DateTime? DigitalRelease { get; set; }
public List<MovieTranslation> Translations { get; set; }
public string YouTubeTrailerId { get; set; }
public string Studio { get; set; }
public string OriginalTitle { get; set; }
public int ListId { get; set; }
public int MovieMetadataId { get; set; }
public LazyLoaded<MovieMetadata> MovieMetadata { get; set; }
public string Title
{
get { return MovieMetadata.Value.Title; }
set { MovieMetadata.Value.Title = value; }
}
public int TmdbId
{
get { return MovieMetadata.Value.TmdbId; }
set { MovieMetadata.Value.TmdbId = value; }
}
public string ImdbId
{
get { return MovieMetadata.Value.ImdbId; }
set { MovieMetadata.Value.ImdbId = value; }
}
public int Year
{
get { return MovieMetadata.Value.Year; }
set { MovieMetadata.Value.Year = value; }
}
}
}
@@ -73,7 +73,7 @@ namespace NzbDrone.Core.ImportLists.Plex
{
var scheme = $"{prefix}://";
return guids.FirstOrDefault((guid) => guid.Id.StartsWith(scheme))?.Id.Replace(scheme, "");
return guids?.FirstOrDefault((guid) => guid.Id.StartsWith(scheme))?.Id.Replace(scheme, "");
}
}
}
@@ -48,11 +48,6 @@ namespace NzbDrone.Core.ImportLists.Radarr
{
TmdbId = remoteMovie.TmdbId,
Title = remoteMovie.Title,
SortTitle = remoteMovie.SortTitle,
Overview = remoteMovie.Overview,
Images = remoteMovie.Images.Select(x => MapImage(x, Settings.BaseUrl)).ToList(),
PhysicalRelease = remoteMovie.PhysicalRelease,
InCinemas = remoteMovie.InCinemas,
Year = remoteMovie.Year
});
}
@@ -36,10 +36,7 @@ namespace NzbDrone.Core.ImportLists.TMDb
var movie = new ImportListMovie
{
TmdbId = movieResult.Id,
Overview = movieResult.Overview,
Title = movieResult.Title,
SortTitle = Parser.Parser.NormalizeTitle(movieResult.Title),
Images = new List<MediaCover.MediaCover>(),
};
if (movieResult.ReleaseDate.IsNotNullOrWhiteSpace())
@@ -48,8 +45,6 @@ namespace NzbDrone.Core.ImportLists.TMDb
movie.Year = releaseDate.Year;
}
movie.Images.AddIfNotNull(MapPosterImage(movieResult.PosterPath));
return movie;
}
@@ -49,7 +49,7 @@ namespace NzbDrone.Core.IndexerSearch
public List<DownloadDecision> MovieSearch(int movieId, bool userInvokedSearch, bool interactiveSearch)
{
var movie = _movieService.GetMovie(movieId);
movie.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
movie.MovieMetadata.Value.Translations = _movieTranslationService.GetAllTranslationsForMovieMetadata(movie.MovieMetadataId);
return MovieSearch(movie, userInvokedSearch, interactiveSearch);
}
@@ -77,12 +77,12 @@ namespace NzbDrone.Core.IndexerSearch
};
var wantedLanguages = _profileService.GetAcceptableLanguages(movie.ProfileId);
var translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
var translations = _movieTranslationService.GetAllTranslationsForMovieMetadata(movie.MovieMetadataId);
var queryTranlations = new List<string>
{
movie.Title,
movie.OriginalTitle
movie.MovieMetadata.Value.Title,
movie.MovieMetadata.Value.OriginalTitle
};
//Add Translation of wanted languages to search query
@@ -12,6 +12,10 @@ namespace NzbDrone.Core.Indexers
UseGuidInfoUrl = true;
UseEnclosureLength = false;
UseEnclosureUrl = true;
SeedsElementName = "seeds";
InfoHashElementName = "infoHash";
SizeElementName = "contentLength";
MagnetElementName = "magnetURI";
}
protected override bool PreProcess(IndexerResponse indexerResponse)
@@ -26,51 +30,5 @@ namespace NzbDrone.Core.Indexers
return base.PreProcess(indexerResponse);
}
protected override long GetSize(XElement item)
{
var contentLength = item.FindDecendants("contentLength").SingleOrDefault();
if (contentLength != null)
{
return (long)contentLength;
}
return base.GetSize(item);
}
protected override string GetInfoHash(XElement item)
{
var infoHash = item.FindDecendants("infoHash").SingleOrDefault();
return (string)infoHash;
}
protected override string GetMagnetUrl(XElement item)
{
var magnetURI = item.FindDecendants("magnetURI").SingleOrDefault();
return (string)magnetURI;
}
protected override int? GetSeeders(XElement item)
{
var seeds = item.FindDecendants("seeds").SingleOrDefault();
if (seeds != null)
{
return (int)seeds;
}
return base.GetSeeders(item);
}
protected override int? GetPeers(XElement item)
{
var peers = item.FindDecendants("peers").SingleOrDefault();
if (peers != null)
{
return (int)peers;
}
return base.GetPeers(item);
}
}
}
@@ -24,9 +24,9 @@ namespace NzbDrone.Core.Indexers.FileList
{
var pageableRequests = new IndexerPageableRequestChain();
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace())
{
pageableRequests.Add(GetRequest("search-torrents", string.Format("&type=imdb&query={0}", searchCriteria.Movie.ImdbId)));
pageableRequests.Add(GetRequest("search-torrents", string.Format("&type=imdb&query={0}", searchCriteria.Movie.MovieMetadata.Value.ImdbId)));
}
else
{
@@ -35,12 +35,12 @@ namespace NzbDrone.Core.Indexers.HDBits
private bool TryAddSearchParameters(TorrentQuery query, SearchCriteriaBase searchCriteria)
{
if (searchCriteria.Movie.ImdbId.IsNullOrWhiteSpace())
if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNullOrWhiteSpace())
{
return false;
}
var imdbId = int.Parse(searchCriteria.Movie.ImdbId.Substring(2));
var imdbId = int.Parse(searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2));
if (imdbId != 0)
{
@@ -115,8 +115,8 @@ namespace NzbDrone.Core.Indexers.Newznab
private void AddMovieIdPageableRequests(IndexerPageableRequestChain chain, int maxPages, IEnumerable<int> categories, SearchCriteriaBase searchCriteria)
{
var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.TmdbId > 0;
var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace();
var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.MovieMetadata.Value.TmdbId > 0;
var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace();
if (SupportsAggregatedIdSearch && (includeTmdbSearch || includeImdbSearch))
{
@@ -124,12 +124,12 @@ namespace NzbDrone.Core.Indexers.Newznab
if (includeTmdbSearch)
{
ids += "&tmdbid=" + searchCriteria.Movie.TmdbId;
ids += "&tmdbid=" + searchCriteria.Movie.MovieMetadata.Value.TmdbId;
}
if (includeImdbSearch)
{
ids += "&imdbid=" + searchCriteria.Movie.ImdbId.Substring(2);
ids += "&imdbid=" + searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2);
}
chain.Add(GetPagedRequests(maxPages, categories, "movie", ids));
@@ -141,14 +141,14 @@ namespace NzbDrone.Core.Indexers.Newznab
chain.Add(GetPagedRequests(maxPages,
categories,
"movie",
string.Format("&tmdbid={0}", searchCriteria.Movie.TmdbId)));
string.Format("&tmdbid={0}", searchCriteria.Movie.MovieMetadata.Value.TmdbId)));
}
else if (includeImdbSearch)
{
chain.Add(GetPagedRequests(maxPages,
categories,
"movie",
string.Format("&imdbid={0}", searchCriteria.Movie.ImdbId.Substring(2))));
string.Format("&imdbid={0}", searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2))));
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Indexers.Nyaa
public override IParseIndexerResponse GetParser()
{
return new TorrentRssParser() { UseGuidInfoUrl = true, ParseSizeInDescription = true, ParseSeedersInDescription = true };
return new TorrentRssParser() { UseGuidInfoUrl = true, SizeElementName = "size", InfoHashElementName = "infoHash", PeersElementName = "leechers", CalculatePeersAsSum = true, SeedsElementName = "seeders" };
}
}
}
@@ -29,9 +29,9 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{
var pageableRequests = new IndexerPageableRequestChain();
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace())
{
pageableRequests.Add(GetRequest(searchCriteria.Movie.ImdbId));
pageableRequests.Add(GetRequest(searchCriteria.Movie.MovieMetadata.Value.ImdbId));
}
else if (searchCriteria.Movie.Year > 0)
{
@@ -87,11 +87,11 @@ namespace NzbDrone.Core.Indexers.Rarbg
requestBuilder.AddQueryParam("mode", "search");
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace())
{
requestBuilder.AddQueryParam("search_imdb", searchCriteria.Movie.ImdbId);
requestBuilder.AddQueryParam("search_imdb", searchCriteria.Movie.MovieMetadata.Value.ImdbId);
}
else if (searchCriteria.Movie.TmdbId > 0)
else if (searchCriteria.Movie.MovieMetadata.Value.TmdbId > 0)
{
requestBuilder.AddQueryParam("search_themoviedb", searchCriteria.Movie.TmdbId);
}
+63 -7
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using MonoTorrent;
@@ -9,12 +10,27 @@ namespace NzbDrone.Core.Indexers
{
public class TorrentRssParser : RssParser
{
// Use to sum/calculate Peers as Leechers+Seeders
public bool CalculatePeersAsSum { get; set; } = false;
// Use the specified element name to determine the Infohash
public string InfoHashElementName { get; set; }
// Parse various seeder/leecher/peers formats in the description element to determine number of seeders.
public bool ParseSeedersInDescription { get; set; }
// Use the specified element name to determine the size
// Use the specified element name to determine the Peers
public string PeersElementName { get; set; }
// Use the specified element name to determine the Seeds
public string SeedsElementName { get; set; }
// Use the specified element name to determine the Size
public string SizeElementName { get; set; }
// Use the specified element name to determine the Magnet link
public string MagnetElementName { get; set; }
public TorrentRssParser()
{
PreferredEnclosureMimeTypes = TorrentEnclosureMimeTypes;
@@ -40,14 +56,28 @@ namespace NzbDrone.Core.Indexers
result.InfoHash = GetInfoHash(item);
result.MagnetUrl = GetMagnetUrl(item);
result.Seeders = GetSeeders(item);
result.Peers = GetPeers(item);
if (CalculatePeersAsSum)
{
result.Peers = GetPeers(item) + result.Seeders;
}
else
{
result.Peers = GetPeers(item);
}
return result;
}
protected virtual string GetInfoHash(XElement item)
{
if (InfoHashElementName.IsNotNullOrWhiteSpace())
{
return item.FindDecendants(InfoHashElementName).FirstOrDefault().Value;
}
var magnetUrl = GetMagnetUrl(item);
if (magnetUrl.IsNotNullOrWhiteSpace())
{
try
@@ -64,10 +94,21 @@ namespace NzbDrone.Core.Indexers
protected virtual string GetMagnetUrl(XElement item)
{
var downloadUrl = GetDownloadUrl(item);
if (downloadUrl.IsNotNullOrWhiteSpace() && downloadUrl.StartsWith("magnet:"))
if (MagnetElementName.IsNotNullOrWhiteSpace())
{
return downloadUrl;
var magnetURL = item.FindDecendants(MagnetElementName).FirstOrDefault().Value;
if (magnetURL.IsNotNullOrWhiteSpace() && magnetURL.StartsWith("magnet:"))
{
return magnetURL;
}
}
else
{
var downloadUrl = GetDownloadUrl(item);
if (downloadUrl.IsNotNullOrWhiteSpace() && downloadUrl.StartsWith("magnet:"))
{
return downloadUrl;
}
}
return null;
@@ -75,6 +116,8 @@ namespace NzbDrone.Core.Indexers
protected virtual int? GetSeeders(XElement item)
{
// safe to always use the element if it's present (and valid)
// fall back to description if ParseSeedersInDescription is enabled
if (ParseSeedersInDescription && item.Element("description") != null)
{
var matchSeeders = ParseSeedersRegex.Match(item.Element("description").Value);
@@ -93,6 +136,12 @@ namespace NzbDrone.Core.Indexers
}
}
var seeds = item.FindDecendants(SeedsElementName).SingleOrDefault();
if (seeds != null)
{
return (int)seeds;
}
return null;
}
@@ -116,6 +165,12 @@ namespace NzbDrone.Core.Indexers
}
}
if (PeersElementName.IsNotNullOrWhiteSpace())
{
var itempeers = item.FindDecendants(PeersElementName).SingleOrDefault();
return int.Parse(itempeers.Value);
}
return null;
}
@@ -124,9 +179,10 @@ namespace NzbDrone.Core.Indexers
var size = base.GetSize(item);
if (size == 0 && SizeElementName.IsNotNullOrWhiteSpace())
{
if (item.Element(SizeElementName) != null)
var itemsize = item.FindDecendants(SizeElementName).SingleOrDefault();
if (itemsize != null)
{
size = ParseSize(item.Element(SizeElementName).Value, true);
size = ParseSize(itemsize.Value, true);
}
}
@@ -44,7 +44,8 @@ namespace NzbDrone.Core.Instrumentation
if (_configFileProvider.SyslogServer.IsNotNullOrWhiteSpace())
{
SetSyslogParameters(_configFileProvider.SyslogServer, _configFileProvider.SyslogPort, minimumLogLevel);
var syslogLevel = LogLevel.FromString(_configFileProvider.SyslogLevel);
SetSyslogParameters(_configFileProvider.SyslogServer, _configFileProvider.SyslogPort, syslogLevel);
}
var rules = LogManager.Configuration.LoggingRules;
@@ -118,7 +119,7 @@ namespace NzbDrone.Core.Instrumentation
syslogTarget.MessageSend.Udp.Server = syslogServer;
syslogTarget.MessageSend.Udp.ReconnectInterval = 500;
syslogTarget.MessageCreation.Rfc = RfcNumber.Rfc5424;
syslogTarget.MessageCreation.Rfc5424.AppName = BuildInfo.AppName;
syslogTarget.MessageCreation.Rfc5424.AppName = _configFileProvider.InstanceName;
var loggingRule = new LoggingRule("*", minimumLogLevel, syslogTarget);
+16 -2
View File
@@ -121,7 +121,7 @@ namespace NzbDrone.Core.Jobs
new ScheduledTask
{
Interval = Math.Max(_configService.CheckForFinishedDownloadInterval, 1),
Interval = GetRefreshMonitoredInterval(),
TypeName = typeof(RefreshMonitoredDownloadsCommand).FullName,
Priority = CommandPriority.High
}
@@ -192,6 +192,18 @@ namespace NzbDrone.Core.Jobs
return interval;
}
private int GetRefreshMonitoredInterval()
{
var interval = _configService.CheckForFinishedDownloadInterval;
if (interval < 1)
{
return 1;
}
return interval;
}
private int GetImportListSyncInterval()
{
//Enforce 6 hour min on list sync
@@ -212,6 +224,7 @@ namespace NzbDrone.Core.Jobs
_scheduledTaskRepository.SetLastExecutionTime(scheduledTask.Id, lastExecution, message.Command.StartedAt.Value);
_cache.Find(scheduledTask.TypeName).LastExecution = lastExecution;
_cache.Find(scheduledTask.TypeName).LastStartTime = message.Command.StartedAt.Value;
}
}
@@ -227,13 +240,14 @@ namespace NzbDrone.Core.Jobs
backup.Interval = GetBackupInterval();
var refreshMonitoredDownloads = _scheduledTaskRepository.GetDefinition(typeof(RefreshMonitoredDownloadsCommand));
refreshMonitoredDownloads.Interval = _configService.CheckForFinishedDownloadInterval;
refreshMonitoredDownloads.Interval = GetRefreshMonitoredInterval();
_scheduledTaskRepository.UpdateMany(new List<ScheduledTask> { rss, importList, refreshMonitoredDownloads, backup });
_cache.Find(rss.TypeName).Interval = rss.Interval;
_cache.Find(importList.TypeName).Interval = importList.Interval;
_cache.Find(backup.TypeName).Interval = backup.Interval;
_cache.Find(refreshMonitoredDownloads.TypeName).Interval = refreshMonitoredDownloads.Interval;
}
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -269,7 +269,7 @@
"Size": "Koko",
"SuggestTranslationChange": "Ehdota käännösmuutosta",
"Queued": "Jonossa",
"TMDb": "TMDb",
"TMDb": "TMDB",
"UnableToLoadAltTitle": "Vaihtoehtoisten nimikkeiden lataus epäonnistui.",
"Released": "Julkaistu",
"ReleasedMsg": "Elokuva julkaistaan",
+35 -26
View File
@@ -1,6 +1,6 @@
{
"IndexerStatusCheckAllClientMessage": "Tous les indexeurs sont indisponibles en raison d'échecs",
"IndexerSearchCheckNoInteractiveMessage": "Aucun indexeur disponible avec la recherche interactive activée, Radarr ne fournira aucun résultat de recherche interactif",
"IndexerSearchCheckNoInteractiveMessage": "Aucun indexeur disponible avec la recherche interactive activée, Radarr ne fournira aucun résultat de recherche interactive",
"IndexerSearchCheckNoAvailableIndexersMessage": "Tous les indexeurs compatibles avec la recherche sont temporairement indisponibles en raison d'erreurs d'indexation récentes",
"IndexerSearchCheckNoAutomaticMessage": "Aucun indexeur disponible avec la recherche automatique activée, Radarr ne fournira aucun résultat de recherche automatique",
"Indexers": "Indexeurs",
@@ -26,7 +26,7 @@
"Edit": "Éditer",
"Downloaded": "Téléchargé",
"DownloadClientStatusCheckAllClientMessage": "Aucun client de téléchargement n'est disponible en raison d'échecs",
"DownloadClients": "Clients Télécharg.",
"DownloadClients": "Clients de téléchargement",
"DownloadClientCheckNoneAvailableMessage": "Aucun client de téléchargement n'est disponible",
"Dates": "Dates",
"Date": "Date",
@@ -36,7 +36,7 @@
"Delete": "Supprimer",
"DelayProfiles": "Profils de retard",
"Day": "Jour",
"CustomFormats": "Formats Persos",
"CustomFormats": "Formats personnalisés",
"CustomFilters": "Filtres personnalisés",
"Crew": "Équipe",
"Connections": "Connexions",
@@ -48,7 +48,7 @@
"Calendar": "Calendrier",
"BackupNow": "Sauvegarder maintenant",
"Backup": "Sauvegarde",
"AppDataLocationHealthCheckMessage": "Mettre à jour ne sera pas possible pour éviter la suppression AppData lors de la mise à jour",
"AppDataLocationHealthCheckMessage": "Mettre à jour ne sera pas possible afin d'éviter de supprimer le dossier AppData lors de la mise à jour",
"Analytics": "Analytique",
"All": "Tout",
"AddNewTmdbIdMessage": "Vous pouvez également effectuer une recherche à l'aide de l'identifiant TMDb d'un film. exemple. tmdb:71663",
@@ -59,7 +59,7 @@
"Activity": "Activité",
"About": "À propos",
"CustomFormatsSettingsSummary": "Paramètres et Formats personnalisés",
"IndexerStatusCheckSingleClientMessage": "Indexeurs indisponibles en raison d'échecs: {0}",
"IndexerStatusCheckSingleClientMessage": "Indexeurs indisponibles en raison d'échecs : {0}",
"DownloadClientStatusCheckSingleClientMessage": "Clients de Téléchargement indisponibles en raison d'échecs: {0}",
"SetTags": "Définir Tags",
"ReleaseTitle": "Titre de la version",
@@ -292,7 +292,7 @@
"RecentFolders": "Dossiers récents",
"QuickImport": "Déplacer automatiquement",
"PosterSize": "Taille des posters",
"Posters": "Posters",
"Posters": "Affiches",
"PosterOptions": "Options des posters",
"PendingChangesStayReview": "Rester et vérifier les changements",
"PendingChangesMessage": "Vous avez effectué des changements non sauvegardés, souhaitez vous quitter cette page?",
@@ -322,7 +322,7 @@
"CertificateValidation": "Validation du certificat",
"BypassProxyForLocalAddresses": "Contourner le proxy pour les adresses locales",
"Branch": "Branche",
"BindAddressHelpText": "Adresse IP4 valide ou '*' pour toutes les interfaces",
"BindAddressHelpText": "Adresse IPv4 valide ou '*' pour toutes les interfaces",
"BindAddress": "Adresse d'attache",
"Backups": "Sauvegardes",
"BackupRetentionHelpText": "Les sauvegardes automatiques plus anciennes que la période de conservation seront automatiquement effacées",
@@ -385,7 +385,7 @@
"Enable": "Activer",
"EditPerson": "Éditer la personne",
"EditMovie": "Éditer le film",
"Edition": "Edition",
"Edition": "Édition",
"DownloadWarningCheckDownloadClientForMoreDetails": "Avertissement téléchargement : voir le client de téléchargement pour plus de détails",
"DownloadFailedCheckDownloadClientForMoreDetails": "Téléchargement échoué : voir le client de téléchargement pour plus de détails",
"DownloadClientSettings": "Réglages Clients de téléchargement",
@@ -455,7 +455,7 @@
"CopyToClipboard": "Copier dans le presse-papier",
"GoToInterp": "Aller à {0}",
"ForMoreInformationOnTheIndividualImportListsClinkOnTheInfoButtons": "Pour plus d'informations sur les listes d'importation individuelles, cliquez sur les boutons d'information.",
"ForMoreInformationOnTheIndividualDownloadClients": "Pour plus d'informations sur les clients de téléchargement individuels, cliquez sur les boutons d'information.",
"ForMoreInformationOnTheIndividualDownloadClients": "Pour plus d'informations sur chaque client de téléchargement, cliquez sur les boutons plus d'information.",
"FilterPlaceHolder": "Chercher les films",
"FailedLoadingSearchResults": "Échec du chargement des résultats de la recherche, veuillez réessayer.",
"Excluded": "Exclu",
@@ -573,7 +573,7 @@
"ProxyBypassFilterHelpText": "Utiliser ',' comme séparateur et '*.' comme caractère générique pour les sous-domaines",
"OnGrabHelpText": "À la Récupération",
"NegateHelpText": "Si coché, le format personnalisé ne s'appliquera pas si cette condition {0} correspond.",
"LastDuration": "dernière Durée",
"LastDuration": "Dernière durée",
"IncludeCustomFormatWhenRenamingHelpText": "Inclus dans {Custom Formats} renommer le format",
"GrabReleaseMessageText": "Radarr n'a pas été en mesure de déterminer à quel film cette version était destinée. Radarr peut être incapable d'importer automatiquement cette version. Voulez-vous récupérer '{0}' ?",
"ExtraFileExtensionsHelpTexts1": "Liste séparée par des virgules des fichiers supplémentaires à importer (.nfo sera importé en tant que .nfo-orig)",
@@ -586,7 +586,7 @@
"UpgradeUntilThisQualityIsMetOrExceeded": "Mettre à niveau jusqu'à ce que cette qualité soit atteinte ou dépassée",
"UpgradeAllowedHelpText": "Ne sera pas mis à jour si la qualité est désactivée",
"UpdateScriptPathHelpText": "Chemin vers un script personnalisé qui prend un package de mise à jour extraite et gère le reste du processus de mise à jour",
"UpdateMechanismHelpText": "Utiliser le programme de mise à jour intégré dans Radarr ou un script",
"UpdateMechanismHelpText": "Utiliser le programme de mise à jour intégré de Radarr ou un script",
"UpdateAutomaticallyHelpText": "Télécharger et installer automatiquement les mises à jour. Vous pourrez toujours installer à partir de System : Updates",
"Unreleased": "Indisponible",
"UnmonitoredHelpText": "Inclure les films non surveillés dans le flux iCal",
@@ -828,7 +828,7 @@
"EditQualityProfile": "Modifier les profils",
"ErrorRestoringBackup": "Erreur lors de la restauration de la sauvegarde",
"ExternalUpdater": "Radarr est configuré pour utiliser un système de mise à jour ad-hoc",
"FileWasDeletedByViaUI": "Le fichier à été supprimé via l'interface",
"FileWasDeletedByViaUI": "Le fichier a été supprimé via l'interface",
"Announced": "Annoncé",
"ChmodFolder": "chmod Dossier",
"ChmodFolderHelpText": "Nombre, appliqué durant l'import/renommage vers les dossiers et fichiers multimédias (sans exécuter les bits)",
@@ -848,7 +848,7 @@
"AllResultsHiddenFilter": "Tous les résultats ont été dissimulés par le filtre actuellement appliqué",
"Always": "Toujours",
"AptUpdater": "Utiliser apt pour installer la mise à jour",
"AreYouSureYouWantToRemoveSelectedItemsFromQueue": "Êtes-vous sûr de vouloir désinstaller {0} objet{1} de la file d'attente ?",
"AreYouSureYouWantToRemoveSelectedItemsFromQueue": "Êtes-vous sûr de vouloir supprimer {0} objet(s) de la file d'attente ?",
"AuthBasic": "Authentification de base (popup)",
"AuthForm": "Authentification par formulaire (page de connexion)",
"AreYouSureYouWantToDeleteFormat": "Êtes-vous sûr de vouloir supprimer le tag {0} ?",
@@ -894,7 +894,7 @@
"HomePage": "Page d'accueil",
"HttpHttps": "HTTP(S)",
"ImportLibrary": "Import bibliothèque",
"MissingFromDisk": "Radarr n'a pas pu trouver le fichier sur le disque, il a donc été supprimé",
"MissingFromDisk": "Radarr n'a pas pu trouver le fichier sur le disque, il a donc été supprimé dans la base de donnée",
"MovieIsRecommend": "Le film est recommandé en fonction de l'ajout récent",
"NoAltTitle": "Pas de titres alternatifs.",
"NoLinks": "Aucun liens",
@@ -912,7 +912,7 @@
"InteractiveImportErrQuality": "La qualité doit être choisie pour chaque fichier sélectionné",
"LowerCase": "Minuscules",
"ManualImportSelectMovie": "Importation manuelle - Sélectionnez un film",
"MappedDrivesRunningAsService": "Les lecteurs réseau mappés ne sont pas disponibles lorsqu'ils sont exécutés en tant que service Windows. Veuillez consulter la FAQ pour plus d'informations",
"MappedDrivesRunningAsService": "Les lecteurs réseau mappés ne sont pas disponibles en fonctionnement en tant que service Windows. Veuillez consulter la FAQ pour plus d'informations",
"RequiredRestrictionHelpText": "La version doit contenir au moins un de ces termes (insensible à la casse)",
"InvalidFormat": "Format invalide",
"LastExecution": "Dernière exécution",
@@ -994,7 +994,7 @@
"SearchCutoffUnmet": "Limite de recherche non satisfaite",
"SearchMissing": "Recherche manquante",
"Seconds": "Secondes",
"SelectDotDot": "'Sélectionner...",
"SelectDotDot": "Sélectionner...",
"SelectLanguage": "Choisir la langue",
"SelectMovie": "Sélectionnez un film",
"SelectQuality": "Sélectionnez la qualité",
@@ -1005,7 +1005,7 @@
"Sunday": "dimanche",
"TagDetails": "Détails du tag - {0}",
"TheLogLevelDefault": "Le niveau de journalisation est par défaut «Info» et peut être modifié dans",
"ThisCannotBeCancelled": "Cela ne peut pas être annulé une fois démarré sans redémarrer Radarr.",
"ThisCannotBeCancelled": "Cela ne peut pas être annulé une fois démarré sans désactiver tous vos indexeurs.",
"TorrentDelayTime": "Retard du torrent : {0}",
"TorrentsDisabled": "Torrents désactivés",
"Trace": "Trace",
@@ -1048,7 +1048,7 @@
"DownloadClientCheckDownloadingToRoot": "Le client de téléchargement {0} place les téléchargements dans le dossier racine {1}. Vous ne devez pas télécharger dans un dossier racine.",
"DeleteFileLabel": "Supprimer {0} fichiers",
"NotificationTriggersHelpText": "Sélectionnez les événements qui doivent déclencher cette notification",
"From": "De",
"From": "de",
"UpdateAvailable": "Une nouvelle mise à jour est disponible",
"RemotePathMappingCheckImportFailed": "Radarr a échoué en important un Film. Vérifier vos logs pour plus de détails.",
"RemotePathMappingCheckDownloadPermissions": "Radarr peut voir mais ne peut accéder au film téléchargé {0}. Il s'agit probablement d'une erreur de permissions.",
@@ -1074,22 +1074,22 @@
"RemotePathMappingCheckFilesGenericPermissions": "Le client de téléchargement {0} met les téléchargements dans {1} mais Radarr ne peut voir ce répertoire. Il est possible que vous ayez besoin d'ajuster les permissions de ce dossier.",
"RemotePathMappingCheckFilesLocalWrongOSPath": "Le client de téléchargement {0} met les téléchargements dans {1} mais il ne s'agit pas d'un chemin {2} valide. Vérifiez les paramètres de votre client de téléchargement.",
"BypassDelayIfHighestQualityHelpText": "Outrepasser le délai quand la version a la plus haute qualité activée dans le profil de qualité avec le protocole préféré",
"ClickToChangeReleaseGroup": "Cliquez pour changer de release group",
"ClickToChangeReleaseGroup": "Cliquer pour changer le groupe de publication",
"AnnouncedMsg": "Le film est annoncé",
"Filters": "Filtres",
"IndexerDownloadClientHelpText": "Précisez quel client de téléchargement est utilisé pour cet indexer",
"IndexerDownloadClientHelpText": "Spécifiez quel client de téléchargement est utilisé pour cet indexeur",
"TmdbRating": "Note TMDb",
"IndexerTagHelpText": "Utiliser seulement cet indexeur pour les films avec au moins un tag correspondant. Laissez vide pour l'utiliser avec tous les films.",
"IndexerJackettAll": "Les indexeurs utilisant le endpoint 'all' de Jackett: {0}",
"IndexerJackettAll": "Indexeurs utilisant le endpoint non supporté 'all' de Jackett : {0}",
"ManualImportSetReleaseGroup": "Import manuel - Spécifier le groupe de Release",
"TmdbVotes": "Votes TMDb",
"ImdbRating": "Note IMDb",
"ImdbVotes": "Votes IMDb",
"LocalPath": "Chemin local",
"DiscordUrlInSlackNotification": "Vous avez une configuration de notification Discord en tant que notification Slack. Configurez cela comme une notification Discord pour une meilleure fonctionnalité. Les notifications affectées sont: {0}",
"RemotePathMappingCheckDockerFolderMissing": "Vous utilisez docker; {0} enregistre les téléchargements dans {1} mais ce dossier n'est pas présent dans ce conteneur. Vérifiez vos paramètres de dossier distant et les paramètres de votre conteneur docker.",
"DiscordUrlInSlackNotification": "Vous avez une configuration de notification Discord en tant que notification Slack. Configurez cela comme une notification Discord pour un meilleur fonctionnement. Les notifications affectées sont : {0}",
"RemotePathMappingCheckDockerFolderMissing": "Vous utilisez docker; {0} enregistre les téléchargements dans {1} mais ce dossier n'est pas présent dans ce conteneur. Vérifiez vos paramètres de dossier distant et les paramètres de votre conteneur docker.",
"RemotePathMappingCheckRemoteDownloadClient": "Le client de téléchargement distant {0} met les téléchargements dans {1} mais ce chemin ne semble pas exister. Vérifiez vos paramètres de chemins distants.",
"RemotePathMappingCheckBadDockerPath": "Vous utilisez docker; {0} enregistre les téléchargements dans {1} mais ce n'est pas un dossier valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckBadDockerPath": "Vous utilisez docker ; le client de téléchargement {0} enregistre les téléchargements dans {1} mais ce n'est pas un chemin valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckFilesWrongOSPath": "Le client de téléchargement distant {0} met les téléchargements dans {1} mais il ne s'agit pas d'un chemin {2} valide. Vérifiez les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckLocalFolderMissing": "Le client de téléchargement distant {0} met les téléchargements dans {1} mais ce chemin ne semble pas exister. Vérifiez vos paramètres de chemins distants.",
"OnApplicationUpdate": "Lors de la mise à jour de l'app",
@@ -1102,9 +1102,18 @@
"OriginalLanguage": "Langue d'origine",
"Rating": "Note",
"RemotePath": "Dossier distant",
"RemotePathMappingCheckFilesBadDockerPath": "Vous utilisez docker; {0} signifie les téléchargement dans {1} mais ce n'est pas un dossier valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckFilesBadDockerPath": "Vous utilisez docker; {0} signifie les téléchargement dans {1} mais ce n'est pas un dossier valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckWrongOSPath": "Le client de téléchargement distant {0} met les téléchargements dans {1} mais ce chemin {2} est invalide. Vérifiez vos paramètres de chemins distants et les paramètres de votre client de téléchargement.",
"RemoveCompleted": "Supprimer les complétés",
"Database": "Base de données",
"SelectLanguages": "Choisir la langue"
"SelectLanguages": "Choisir la/les langue(s)",
"RemoveDownloadsAlert": "Les paramètres de suppression ont été déplacés dans les réglages de chaque client de téléchargement dans le tableau ci-dessus.",
"SizeLimit": "Limite de taille",
"Started": "Démarré",
"Waiting": "En attente",
"RemoveFailed": "Echec de la suppression",
"RemoveSelectedItem": "Supprimer l'élément sélectionné",
"RemoveSelectedItems": "Supprimer les éléments sélectionnés",
"SelectReleaseGroup": "Sélectionner le groupe de publication",
"SetReleaseGroup": "Régler le groupe de publication"
}
@@ -1 +0,0 @@
{}

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