mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-18 21:35:51 -04:00
Compare commits
120 Commits
v0.2.0.535
...
v0.2.0.692
| Author | SHA1 | Date | |
|---|---|---|---|
| a0486b54a6 | |||
| 7ed0db10cb | |||
| e94591a290 | |||
| fccd02a0ca | |||
| b49f0e70ed | |||
| fc1585e900 | |||
| b36ac091fc | |||
| ab28bfead2 | |||
| 3ab3fbfd57 | |||
| d133ee3143 | |||
| 98b6932ffe | |||
| 58e81a916c | |||
| 817f48448c | |||
| 1eca179b4e | |||
| b05d505bce | |||
| ace426e69f | |||
| a57c9917cc | |||
| 9e84b4a782 | |||
| 494ef16735 | |||
| 5a0f02007f | |||
| b1025e7229 | |||
| 446d661345 | |||
| 3eb351823e | |||
| 835a7cffa1 | |||
| e728330ce4 | |||
| 6f3118c142 | |||
| b568072140 | |||
| 7db92c6bcf | |||
| f1e8a9acfc | |||
| dae389ce64 | |||
| 7c3d8c8ff9 | |||
| 8ca66fb61a | |||
| 064844ac0c | |||
| 5540594ecf | |||
| 433ae019de | |||
| 10091b9454 | |||
| 475851775f | |||
| 0fff862fd2 | |||
| 23754c49dc | |||
| fbf790e9fd | |||
| 6d00bd0f7a | |||
| 5bf95e0d9e | |||
| 8bb4b02be7 | |||
| b26a036eed | |||
| ef57882291 | |||
| 32a2407ad1 | |||
| 33b48eec95 | |||
| 3790dc9109 | |||
| 343d849536 | |||
| c36b259fa9 | |||
| 6463913f22 | |||
| e39deb4bdc | |||
| 9ca2c21547 | |||
| f376360611 | |||
| 3e966d4d58 | |||
| e036267c33 | |||
| 7d4378ca7a | |||
| ee1ebfd893 | |||
| 403fd0f0c0 | |||
| fc5ac8219f | |||
| 600a433faa | |||
| 5609facd9d | |||
| 36ea6c6b99 | |||
| 56ac87c760 | |||
| 47753c47a5 | |||
| 712c0eb84a | |||
| 8765155223 | |||
| 63d7596e98 | |||
| 640edf0cce | |||
| 280445e756 | |||
| bae8d5e9a4 | |||
| 07254adf91 | |||
| d33ec334f3 | |||
| a80e9f11f2 | |||
| 4a0ef984fb | |||
| 685012280b | |||
| 6963078669 | |||
| 7182081fca | |||
| 87ee360818 | |||
| ad222570be | |||
| 680681c8bd | |||
| e2ae7536ad | |||
| 98c117a460 | |||
| c54f8806b3 | |||
| 454d5c37f9 | |||
| e9f084fd81 | |||
| d1bbcdc039 | |||
| c17deb7d92 | |||
| 7066b078ab | |||
| b4bb8875d3 | |||
| cb596488f2 | |||
| 3403ddf993 | |||
| 17118cf24d | |||
| 27ab70333c | |||
| f4031f1e5f | |||
| a9154559b8 | |||
| 0f2f2e4b32 | |||
| 6deefbb997 | |||
| 43a71da0a7 | |||
| 499e46e10a | |||
| 3f013271c9 | |||
| 529591bc18 | |||
| 79307d3c25 | |||
| 8f79563cf0 | |||
| 0dc67419be | |||
| 066c746e5f | |||
| 31fcac5bd9 | |||
| 1b29b89bf1 | |||
| c593f4250d | |||
| 59c07cc5f3 | |||
| 2b1023e768 | |||
| f10af08f95 | |||
| 18fcda5fd6 | |||
| 1ccfde334f | |||
| 421a191650 | |||
| 35e046bb87 | |||
| 8ece7e8b4d | |||
| fadc5f0099 | |||
| 680430737d | |||
| 5d3750a295 |
@@ -1,5 +1,9 @@
|
|||||||
**Description:**
|
**Description:**
|
||||||
|
|
||||||
|
Check first that your problem is not listed in our wiki section:
|
||||||
|
* https://github.com/Radarr/Radarr/wiki/Common-Problems
|
||||||
|
* https://github.com/Radarr/Radarr/wiki/FAQ
|
||||||
|
|
||||||
Provide a description of the feature request or bug here, the more details the better.
|
Provide a description of the feature request or bug here, the more details the better.
|
||||||
Please also try to include the following if you are reporting a bug
|
Please also try to include the following if you are reporting a bug
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="/Logo/text256.png" alt="Radarr">
|
<img src="/Logo/text256.png" alt="Radarr">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Radarr is an __independent__ fork of [Sonarr](https://github.com/Sonarr/Sonarr) reworked for automatically downloading movies via Usenet and BitTorrent.
|
Radarr is an __independent__ fork of [Sonarr](https://github.com/Sonarr/Sonarr) reworked for automatically downloading movies via Usenet and BitTorrent.
|
||||||
@@ -72,14 +72,21 @@ Radarr is currently undergoing rapid development and pull requests are actively
|
|||||||
* New PassThePopcorn Indexer
|
* New PassThePopcorn Indexer
|
||||||
* QBittorrent, Deluge, rTorrent, Transmission and uTorrent download client (Other clients are coming)
|
* QBittorrent, Deluge, rTorrent, Transmission and uTorrent download client (Other clients are coming)
|
||||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||||
|
* Scanning PreDB to know when a new release is available
|
||||||
|
* Importing movies from various online sources, such as IMDb Watchlists (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114))
|
||||||
|
* Full integration with Kodi, Plex (notification, library update)
|
||||||
* And a beautiful UI
|
* And a beautiful UI
|
||||||
|
|
||||||
### Planned Features
|
### Planned Features
|
||||||
|
|
||||||
* Scanning PreDB to know when a new release is available
|
* Downloading Metadata such as trailers or subtitles (\*)
|
||||||
* Fixing the other Indexers and download clients
|
* Adding metadata such as posters and information for Kodi and others to use (\*)
|
||||||
* Importing movies from various online sources, such as IMDb Watchlists (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114))
|
* Dynamically renaming folders with quality info, etc. (\*)
|
||||||
* Full integration with Kodi, Plex (notification, library update, metadata)
|
* Supporting custom folder structures, such as all movie files in one folder (\*)
|
||||||
|
* Supporting multiple editions per movies (waiting on The Movie Database to finish their implementation)
|
||||||
|
* Supporting collections of movies, such as James Bond
|
||||||
|
|
||||||
|
**Note:** All features marked with (\*) are set to be in the first release of Radarr.
|
||||||
|
|
||||||
#### [Feature Requests](http://feathub.com/Radarr/Radarr)
|
#### [Feature Requests](http://feathub.com/Radarr/Radarr)
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ test:
|
|||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: '_artifacts\*.zip'
|
- path: '_artifacts\*.zip'
|
||||||
|
- path: '_artifacts\*.exe'
|
||||||
- path: '_artifacts\*.tar.gz'
|
- path: '_artifacts\*.tar.gz'
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
@@ -36,9 +37,17 @@ cache:
|
|||||||
pull_requests:
|
pull_requests:
|
||||||
do_not_increment_build_number: true
|
do_not_increment_build_number: true
|
||||||
|
|
||||||
|
on_failure:
|
||||||
|
- ps: Get-ChildItem .\_artifacts\*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
- ps: Get-ChildItem .\_artifacts\*.exe | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
- ps: Get-ChildItem .\_artifacts\*.tar.gz | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
|
||||||
only_commits:
|
only_commits:
|
||||||
files:
|
files:
|
||||||
- src/
|
- src/
|
||||||
- osx/
|
- osx/
|
||||||
- gulp/
|
- gulp/
|
||||||
- logo/
|
- logo/
|
||||||
|
- setup/
|
||||||
|
- appveyor.yml
|
||||||
|
- build-appveyor.cake
|
||||||
|
|||||||
+16
-6
@@ -104,11 +104,13 @@ Task("Compile").Does(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Task("Gulp").Does(() => {
|
Task("Gulp").Does(() => {
|
||||||
Npm
|
NpmInstall(new NpmInstallSettings {
|
||||||
.WithLogLevel(NpmLogLevel.Silent)
|
LogLevel = NpmLogLevel.Silent,
|
||||||
.FromPath(".")
|
WorkingDirectory = "./",
|
||||||
.Install()
|
Production = true
|
||||||
.RunScript("build");
|
});
|
||||||
|
|
||||||
|
NpmRunScript("build");
|
||||||
});
|
});
|
||||||
|
|
||||||
Task("PackageMono").Does(() => {
|
Task("PackageMono").Does(() => {
|
||||||
@@ -167,7 +169,7 @@ Task("PackageOsx").Does(() => {
|
|||||||
CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx);
|
CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx);
|
||||||
|
|
||||||
// Adding Startup script
|
// Adding Startup script
|
||||||
CopyFile("./osx/Sonarr", outputFolderOsx + "/Sonarr");
|
CopyFile("./osx/Radarr", outputFolderOsx + "/Radarr");
|
||||||
});
|
});
|
||||||
|
|
||||||
Task("PackageOsxApp").Does(() => {
|
Task("PackageOsxApp").Does(() => {
|
||||||
@@ -264,6 +266,13 @@ Task("ArtifactsWindows").Does(() => {
|
|||||||
CopyDirectory(outputFolder, artifactsFolderWindows + "/Radarr");
|
CopyDirectory(outputFolder, artifactsFolderWindows + "/Radarr");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Task("ArtifactsWindowsInstaller").Does(() => {
|
||||||
|
InnoSetup("./setup/nzbdrone.iss", new InnoSetupSettings {
|
||||||
|
OutputDirectory = artifactsFolder,
|
||||||
|
ToolPath = "./setup/inno/ISCC.exe"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Task("ArtifactsLinux").Does(() => {
|
Task("ArtifactsLinux").Does(() => {
|
||||||
CopyDirectory(outputFolderMono, artifactsFolderLinux + "/Radarr");
|
CopyDirectory(outputFolderMono, artifactsFolderLinux + "/Radarr");
|
||||||
});
|
});
|
||||||
@@ -293,6 +302,7 @@ Task("CompressArtifacts").Does(() => {
|
|||||||
Task("Artifacts")
|
Task("Artifacts")
|
||||||
.IsDependentOn("CleanArtifacts")
|
.IsDependentOn("CleanArtifacts")
|
||||||
.IsDependentOn("ArtifactsWindows")
|
.IsDependentOn("ArtifactsWindows")
|
||||||
|
.IsDependentOn("ArtifactsWindowsInstaller")
|
||||||
.IsDependentOn("ArtifactsLinux")
|
.IsDependentOn("ArtifactsLinux")
|
||||||
.IsDependentOn("ArtifactsOsx")
|
.IsDependentOn("ArtifactsOsx")
|
||||||
.IsDependentOn("ArtifactsOsxApp")
|
.IsDependentOn("ArtifactsOsxApp")
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ PackageOsx()
|
|||||||
cp $sourceFolder/Libraries/MediaInfo/*.dylib $outputFolderOsx
|
cp $sourceFolder/Libraries/MediaInfo/*.dylib $outputFolderOsx
|
||||||
|
|
||||||
echo "Adding Startup script"
|
echo "Adding Startup script"
|
||||||
cp ./osx/Sonarr $outputFolderOsx
|
cp ./osx/Radarr $outputFolderOsx
|
||||||
|
|
||||||
echo "##teamcity[progressFinish 'Creating OS X Package']"
|
echo "##teamcity[progressFinish 'Creating OS X Package']"
|
||||||
}
|
}
|
||||||
@@ -208,9 +208,9 @@ PackageTests()
|
|||||||
find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \;
|
find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \;
|
||||||
|
|
||||||
if [ $runtime = "dotnet" ] ; then
|
if [ $runtime = "dotnet" ] ; then
|
||||||
$nuget install NUnit.ConsoleRunner -Version 3.2.0 -Output $testPackageFolder
|
$nuget install NUnit.Runners -Version 3.2.1 -Output $testPackageFolder
|
||||||
else
|
else
|
||||||
mono $nuget install NUnit.ConsoleRunner -Version 3.2.0 -Output $testPackageFolder
|
mono $nuget install NUnit.Runners -Version 3.2.1 -Output $testPackageFolder
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp $outputFolder/*.dll $testPackageFolder
|
cp $outputFolder/*.dll $testPackageFolder
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
input1 = """Prometheus.Special.Edition.Fan Edit.2012..BRRip.x264.AAC-m2g
|
||||||
|
Star Wars Episode IV - A New Hope (Despecialized) 1999.mkv
|
||||||
|
Prometheus.(Special.Edition.Remastered).2012.[Bluray-1080p].mkv
|
||||||
|
Prometheus Extended 2012
|
||||||
|
Prometheus Extended Directors Cut Fan Edit 2012
|
||||||
|
Prometheus Director's Cut 2012
|
||||||
|
Prometheus Directors Cut 2012
|
||||||
|
Prometheus.(Extended.Theatrical.Version.IMAX).BluRay.1080p.2012.asdf
|
||||||
|
2001 A Space Odyssey Director's Cut (1968).mkv
|
||||||
|
2001: A Space Odyssey (Extended Directors Cut FanEdit) Bluray 1080p 1968
|
||||||
|
A Fake Movie 2035 Directors 2012.mkv
|
||||||
|
Blade Runner Director's Cut 2049.mkv
|
||||||
|
Prometheus 50th Anniversary Edition 2012.mkv
|
||||||
|
Movie 2in1 2012.mkv
|
||||||
|
Movie IMAX 2012.mkv"""
|
||||||
|
|
||||||
|
output1 = """Special.Edition.Fan Edit BRRip.x264.AAC-m2g
|
||||||
|
Despecialized mkv
|
||||||
|
Special.Edition.Remastered Bluray-1080p].mkv
|
||||||
|
Extended mkv
|
||||||
|
Extended Directors Cut Fan Edit mkv
|
||||||
|
Director's Cut mkv
|
||||||
|
Directors Cut mkv
|
||||||
|
Extended.Theatrical.Version.IMAX asdf
|
||||||
|
Director's Cut mkv
|
||||||
|
Extended Directors Cut FanEdit mkv
|
||||||
|
Directors mkv
|
||||||
|
Director's Cut mkv
|
||||||
|
50th Anniversary Edition mkv
|
||||||
|
2in1 mkv
|
||||||
|
IMAX mkv"""
|
||||||
|
|
||||||
|
inputs = input1.split("\n")
|
||||||
|
outputs = output1.split("\n")
|
||||||
|
real_o = []
|
||||||
|
for output in outputs:
|
||||||
|
real_o.append(output.split(" ")[0].replace(".", " ").strip())
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for inp in inputs:
|
||||||
|
o = real_o[count]
|
||||||
|
print "[TestCase(\"{0}\", \"{1}\")]".format(inp, o)
|
||||||
|
count += 1
|
||||||
@@ -5,7 +5,7 @@ DIR=$(cd "$(dirname "$0")"; pwd)
|
|||||||
|
|
||||||
#change these values to match your app
|
#change these values to match your app
|
||||||
EXE_PATH="$DIR/Radarr.exe"
|
EXE_PATH="$DIR/Radarr.exe"
|
||||||
APPNAME="Sonarr"
|
APPNAME="Radarr"
|
||||||
|
|
||||||
#set up environment
|
#set up environment
|
||||||
if [[ -x '/opt/local/bin/mono' ]]; then
|
if [[ -x '/opt/local/bin/mono' ]]; then
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>English</string>
|
<string>English</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>Sonarr</string>
|
<string>Radarr</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>radarr.icns</string>
|
<string>radarr.icns</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
|||||||
+38
-29
@@ -23,20 +23,19 @@ if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
|
|||||||
DAY="`date +%d`"
|
DAY="`date +%d`"
|
||||||
else
|
else
|
||||||
VERSION=$1
|
VERSION=$1
|
||||||
|
BRANCH=$2
|
||||||
|
BRANCH=${BRANCH#refs\/heads\/}
|
||||||
|
BRANCH=${BRANCH//\//-}
|
||||||
fi
|
fi
|
||||||
outputFolder='./_output'
|
outputFolder='./_output'
|
||||||
outputFolderMono='./_output_mono'
|
outputFolderMono='./_output_mono'
|
||||||
outputFolderOsx='./_output_osx'
|
outputFolderOsx='./_output_osx'
|
||||||
outputFolderOsxApp='./_output_osx_app'
|
outputFolderOsxApp='./_output_osx_app'
|
||||||
|
|
||||||
tr -d "\r" < $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr > $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
|
tr -d "\r" < $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr > $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2
|
||||||
rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr
|
rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr
|
||||||
chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
|
chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2
|
||||||
mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr >& error.log
|
mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr >& error.log
|
||||||
|
|
||||||
cp -r $outputFolder/ Radarr_Windows_$VERSION
|
|
||||||
cp -r $outputFolderMono/ Radarr_Mono_$VERSION
|
|
||||||
cp -r $outputFolderOsxApp/ Radarr_OSX_$VERSION
|
|
||||||
|
|
||||||
if [ $runtime = "dotnet" ] ; then
|
if [ $runtime = "dotnet" ] ; then
|
||||||
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
|
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
|
||||||
@@ -44,25 +43,35 @@ if [ $runtime = "dotnet" ] ; then
|
|||||||
./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz
|
./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz
|
||||||
./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz
|
./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz
|
||||||
else
|
else
|
||||||
zip -r Radarr_Windows_$VERSION.zip Radarr_Windows_$VERSION/* >& /dev/null
|
cp -r $outputFolder/ Radarr
|
||||||
zip -r Radarr_Mono_$VERSION.zip Radarr_Mono_$VERSION/* >& /dev/null #TODO update for tar.gz
|
zip -r Radarr.$BRANCH.$VERSION.windows.zip Radarr
|
||||||
zip -r Radarr_OSX_$VERSION_App.zip Radarr_OSX_$VERSION/* >& /dev/null
|
rm -rf Radarr
|
||||||
|
cp -r $outputFolderMono/ Radarr
|
||||||
|
tar -zcvf Radarr.$BRANCH.$VERSION.linux.tar.gz Radarr
|
||||||
|
rm -rf Radarr
|
||||||
|
cp -r $outputFolderOsx/ Radarr
|
||||||
|
tar -zcvf Radarr.$BRANCH.$VERSION.osx.tar.gz Radarr
|
||||||
|
rm -rf Radarr
|
||||||
|
#TODO update for tar.gz
|
||||||
|
|
||||||
|
cd _output_osx_app/
|
||||||
|
zip -r ../Radarr.$BRANCH.$VERSION.osx-app.zip *
|
||||||
fi
|
fi
|
||||||
ftp -n ftp.leonardogalli.ch << END_SCRIPT
|
# ftp -n ftp.leonardogalli.ch << END_SCRIPT
|
||||||
passive
|
# passive
|
||||||
quote USER $FTP_USER
|
# quote USER $FTP_USER
|
||||||
quote PASS $FTP_PASS
|
# quote PASS $FTP_PASS
|
||||||
mkdir builds
|
# mkdir builds
|
||||||
cd builds
|
# cd builds
|
||||||
mkdir $YEAR
|
# mkdir $YEAR
|
||||||
cd $YEAR
|
# cd $YEAR
|
||||||
mkdir $MONTH
|
# mkdir $MONTH
|
||||||
cd $MONTH
|
# cd $MONTH
|
||||||
mkdir $DAY
|
# mkdir $DAY
|
||||||
cd $DAY
|
# cd $DAY
|
||||||
binary
|
# binary
|
||||||
put Radarr_Windows_$VERSION.zip
|
# put Radarr_Windows_$VERSION.zip
|
||||||
put Radarr_Mono_$VERSION.zip
|
# put Radarr_Mono_$VERSION.zip
|
||||||
put Radarr_OSX_$VERSION.zip
|
# put Radarr_OSX_$VERSION.zip
|
||||||
quit
|
# quit
|
||||||
END_SCRIPT
|
# END_SCRIPT
|
||||||
|
|||||||
+16
-16
@@ -1,35 +1,35 @@
|
|||||||
; Script generated by the Inno Setup Script Wizard.
|
; Script generated by the Inno Setup Script Wizard.
|
||||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||||
|
|
||||||
#define AppName "Sonarr"
|
#define AppName "Radarr"
|
||||||
#define AppPublisher "Team Sonarr"
|
#define AppPublisher "Team Radarr"
|
||||||
#define AppURL "https://sonarr.tv/"
|
#define AppURL "https://radarr.video/"
|
||||||
#define ForumsURL "https://forums.sonarr.tv/"
|
#define ForumsURL "https://github.com/Radarr/Radarr/issues"
|
||||||
#define AppExeName "NzbDrone.exe"
|
#define AppExeName "Radarr.exe"
|
||||||
#define BuildNumber "2.0"
|
#define BuildNumber "2.0"
|
||||||
#define BuildNumber GetEnv('BUILD_NUMBER')
|
#define BuildVersion GetEnv('APPVEYOR_BUILD_VERSION')
|
||||||
#define BranchName GetEnv('branch')
|
#define BranchName GetEnv('APPVEYOR_REPO_BRANCH')
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
; NOTE: The value of AppId uniquely identifies this application.
|
; NOTE: The value of AppId uniquely identifies this application.
|
||||||
; Do not use the same AppId value in installers for other applications.
|
; Do not use the same AppId value in installers for other applications.
|
||||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||||
AppId={{56C1065D-3523-4025-B76D-6F73F67F7F71}
|
AppId={{56C1065D-3523-4025-B76D-6F73F67F7F82}
|
||||||
AppName={#AppName}
|
AppName={#AppName}
|
||||||
AppVersion=2.0
|
AppVersion=0.2
|
||||||
AppPublisher={#AppPublisher}
|
AppPublisher={#AppPublisher}
|
||||||
AppPublisherURL={#AppURL}
|
AppPublisherURL={#AppURL}
|
||||||
AppSupportURL={#ForumsURL}
|
AppSupportURL={#ForumsURL}
|
||||||
AppUpdatesURL={#AppURL}
|
AppUpdatesURL={#AppURL}
|
||||||
DefaultDirName={commonappdata}\NzbDrone\bin
|
DefaultDirName={commonappdata}\Radarr\bin
|
||||||
DisableDirPage=yes
|
DisableDirPage=yes
|
||||||
DefaultGroupName={#AppName}
|
DefaultGroupName={#AppName}
|
||||||
DisableProgramGroupPage=yes
|
DisableProgramGroupPage=yes
|
||||||
OutputBaseFilename=NzbDrone.{#BranchName}.{#BuildNumber}
|
OutputBaseFilename=Radarr.{#BranchName}.{#BuildVersion}.installer
|
||||||
SolidCompression=yes
|
SolidCompression=yes
|
||||||
AppCopyright=Creative Commons 3.0 License
|
AppCopyright=Creative Commons 3.0 License
|
||||||
AllowUNCPath=False
|
AllowUNCPath=False
|
||||||
UninstallDisplayIcon={app}\NzbDrone.exe
|
UninstallDisplayIcon={app}\Radarr.exe
|
||||||
DisableReadyPage=True
|
DisableReadyPage=True
|
||||||
CompressionThreads=2
|
CompressionThreads=2
|
||||||
Compression=lzma2/normal
|
Compression=lzma2/normal
|
||||||
@@ -44,7 +44,7 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
|
|||||||
Name: "windowsService"; Description: "Install as a Windows Service"
|
Name: "windowsService"; Description: "Install as a Windows Service"
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "..\_output\NzbDrone.exe"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\_output\Radarr.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "..\_output\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
Source: "..\_output\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
|
|||||||
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
|
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
|
||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
Filename: "{app}\nzbdrone.console.exe"; Parameters: "/u"; Flags: waituntilterminated;
|
Filename: "{app}\radarr.console.exe"; Parameters: "/u"; Flags: waituntilterminated;
|
||||||
Filename: "{app}\nzbdrone.console.exe"; Parameters: "/i"; Flags: waituntilterminated; Tasks: windowsService
|
Filename: "{app}\radarr.console.exe"; Parameters: "/i"; Flags: waituntilterminated; Tasks: windowsService
|
||||||
|
|
||||||
[UninstallRun]
|
[UninstallRun]
|
||||||
Filename: "{app}\nzbdrone.console.exe"; Parameters: "/u"; Flags: waituntilterminated skipifdoesntexist
|
Filename: "{app}\radarr.console.exe"; Parameters: "/u"; Flags: waituntilterminated skipifdoesntexist
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ namespace NzbDrone.Api.Authentication
|
|||||||
{
|
{
|
||||||
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
||||||
UserMapper = _authenticationService,
|
UserMapper = _authenticationService,
|
||||||
|
Path = _configFileProvider.UrlBase,
|
||||||
CryptographyConfiguration = cryptographyConfiguration
|
CryptographyConfiguration = cryptographyConfiguration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
using NzbDrone.Api.Extensions;
|
using NzbDrone.Api.Extensions;
|
||||||
using NzbDrone.Api.Validation;
|
using NzbDrone.Api.Validation;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
@@ -17,14 +18,17 @@ namespace NzbDrone.Api.Commands
|
|||||||
{
|
{
|
||||||
private readonly IManageCommandQueue _commandQueueManager;
|
private readonly IManageCommandQueue _commandQueueManager;
|
||||||
private readonly IServiceFactory _serviceFactory;
|
private readonly IServiceFactory _serviceFactory;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public CommandModule(IManageCommandQueue commandQueueManager,
|
public CommandModule(IManageCommandQueue commandQueueManager,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster,
|
IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
IServiceFactory serviceFactory)
|
IServiceFactory serviceFactory,
|
||||||
|
Logger logger)
|
||||||
: base(signalRBroadcaster)
|
: base(signalRBroadcaster)
|
||||||
{
|
{
|
||||||
_commandQueueManager = commandQueueManager;
|
_commandQueueManager = commandQueueManager;
|
||||||
_serviceFactory = serviceFactory;
|
_serviceFactory = serviceFactory;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
GetResourceById = GetCommand;
|
GetResourceById = GetCommand;
|
||||||
CreateResource = StartCommand;
|
CreateResource = StartCommand;
|
||||||
@@ -41,7 +45,13 @@ namespace NzbDrone.Api.Commands
|
|||||||
private int StartCommand(CommandResource commandResource)
|
private int StartCommand(CommandResource commandResource)
|
||||||
{
|
{
|
||||||
var commandType = _serviceFactory.GetImplementations(typeof(Command))
|
var commandType = _serviceFactory.GetImplementations(typeof(Command))
|
||||||
.Single(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));
|
.SingleOrDefault(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (commandType == null)
|
||||||
|
{
|
||||||
|
_logger.Error("Found no matching command for {0}", commandResource.Name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
dynamic command = Request.Body.FromJson(commandType);
|
dynamic command = Request.Body.FromJson(commandType);
|
||||||
command.Trigger = CommandTrigger.Manual;
|
command.Trigger = CommandTrigger.Manual;
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ namespace NzbDrone.Api.Config
|
|||||||
public int MinimumAge { get; set; }
|
public int MinimumAge { get; set; }
|
||||||
public int Retention { get; set; }
|
public int Retention { get; set; }
|
||||||
public int RssSyncInterval { get; set; }
|
public int RssSyncInterval { get; set; }
|
||||||
public int AvailabilityDelay { get; set; }
|
public bool PreferIndexerFlags { get; set; }
|
||||||
|
public int AvailabilityDelay { get; set; }
|
||||||
|
public bool AllowHardcodedSubs { get; set; }
|
||||||
|
public string WhitelistedHardcodedSubs { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IndexerConfigResourceMapper
|
public static class IndexerConfigResourceMapper
|
||||||
@@ -20,7 +23,11 @@ namespace NzbDrone.Api.Config
|
|||||||
MinimumAge = model.MinimumAge,
|
MinimumAge = model.MinimumAge,
|
||||||
Retention = model.Retention,
|
Retention = model.Retention,
|
||||||
RssSyncInterval = model.RssSyncInterval,
|
RssSyncInterval = model.RssSyncInterval,
|
||||||
AvailabilityDelay = model.AvailabilityDelay,
|
PreferIndexerFlags = model.PreferIndexerFlags,
|
||||||
|
AvailabilityDelay = model.AvailabilityDelay,
|
||||||
|
AllowHardcodedSubs = model.AllowHardcodedSubs,
|
||||||
|
WhitelistedHardcodedSubs = model.WhitelistedHardcodedSubs,
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ namespace NzbDrone.Api.Config
|
|||||||
public bool AutoDownloadPropers { get; set; }
|
public bool AutoDownloadPropers { get; set; }
|
||||||
public bool CreateEmptySeriesFolders { get; set; }
|
public bool CreateEmptySeriesFolders { get; set; }
|
||||||
public FileDateType FileDate { get; set; }
|
public FileDateType FileDate { get; set; }
|
||||||
|
public bool AutoRenameFolders { get; set; }
|
||||||
|
public bool PathsDefaultStatic { get; set; }
|
||||||
|
|
||||||
public bool SetPermissionsLinux { get; set; }
|
public bool SetPermissionsLinux { get; set; }
|
||||||
public string FileChmod { get; set; }
|
public string FileChmod { get; set; }
|
||||||
@@ -35,6 +37,8 @@ namespace NzbDrone.Api.Config
|
|||||||
AutoDownloadPropers = model.AutoDownloadPropers,
|
AutoDownloadPropers = model.AutoDownloadPropers,
|
||||||
CreateEmptySeriesFolders = model.CreateEmptySeriesFolders,
|
CreateEmptySeriesFolders = model.CreateEmptySeriesFolders,
|
||||||
FileDate = model.FileDate,
|
FileDate = model.FileDate,
|
||||||
|
AutoRenameFolders = model.AutoRenameFolders,
|
||||||
|
PathsDefaultStatic = model.PathsDefaultStatic,
|
||||||
|
|
||||||
SetPermissionsLinux = model.SetPermissionsLinux,
|
SetPermissionsLinux = model.SetPermissionsLinux,
|
||||||
FileChmod = model.FileChmod,
|
FileChmod = model.FileChmod,
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace NzbDrone.Api.Indexers
|
|||||||
public bool DownloadAllowed { get; set; }
|
public bool DownloadAllowed { get; set; }
|
||||||
public int ReleaseWeight { get; set; }
|
public int ReleaseWeight { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<string> IndexerFlags { get; set; }
|
||||||
|
|
||||||
public string MagnetUrl { get; set; }
|
public string MagnetUrl { get; set; }
|
||||||
public string InfoHash { get; set; }
|
public string InfoHash { get; set; }
|
||||||
@@ -132,7 +133,7 @@ namespace NzbDrone.Api.Indexers
|
|||||||
Seeders = torrentInfo.Seeders,
|
Seeders = torrentInfo.Seeders,
|
||||||
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
|
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
|
||||||
Protocol = releaseInfo.DownloadProtocol,
|
Protocol = releaseInfo.DownloadProtocol,
|
||||||
|
IndexerFlags = torrentInfo.IndexerFlags.ToString().Split(new string[] { ", " }, StringSplitOptions.None),
|
||||||
Edition = parsedMovieInfo.Edition,
|
Edition = parsedMovieInfo.Edition,
|
||||||
|
|
||||||
IsDaily = false,
|
IsDaily = false,
|
||||||
|
|||||||
@@ -46,11 +46,14 @@ namespace NzbDrone.Api.EpisodeFiles
|
|||||||
return movie.ToResource();
|
return movie.ToResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SetQuality(MovieFileResource movieFileResource)
|
private void SetQuality(MovieFileResource movieFileResource)
|
||||||
{
|
{
|
||||||
var movieFile = _mediaFileService.GetMovie(movieFileResource.Id);
|
var movieFile = _mediaFileService.GetMovie(movieFileResource.Id);
|
||||||
movieFile.Quality = movieFileResource.Quality;
|
movieFile.Quality = movieFileResource.Quality;
|
||||||
_mediaFileService.Update(movieFile);
|
_mediaFileService.Update(movieFile);
|
||||||
|
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, movieFile.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteMovieFile(int id)
|
private void DeleteMovieFile(int id)
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using FluentValidation;
|
||||||
|
using NzbDrone.Api.ClientSchema;
|
||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Core.NetImport.ImportExclusions;
|
||||||
|
using NzbDrone.Core.Validation.Paths;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.NetImport
|
||||||
|
{
|
||||||
|
public class ImportExclusionsModule : NzbDroneRestModule<ImportExclusionsResource>
|
||||||
|
{
|
||||||
|
private readonly IImportExclusionsService _exclusionService;
|
||||||
|
|
||||||
|
public ImportExclusionsModule(NetImportFactory netImportFactory, IImportExclusionsService exclusionService) : base("exclusions")
|
||||||
|
{
|
||||||
|
_exclusionService = exclusionService;
|
||||||
|
GetResourceAll = GetAll;
|
||||||
|
CreateResource = AddExclusion;
|
||||||
|
DeleteResource = RemoveExclusion;
|
||||||
|
GetResourceById = GetById;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ImportExclusionsResource> GetAll()
|
||||||
|
{
|
||||||
|
return _exclusionService.GetAllExclusions().ToResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportExclusionsResource GetById(int id)
|
||||||
|
{
|
||||||
|
return _exclusionService.GetById(id).ToResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int AddExclusion(ImportExclusionsResource exclusionResource)
|
||||||
|
{
|
||||||
|
var model = exclusionResource.ToModel();
|
||||||
|
|
||||||
|
return _exclusionService.AddExclusion(model).Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveExclusion (int id)
|
||||||
|
{
|
||||||
|
_exclusionService.RemoveExclusion(new ImportExclusion { Id = id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.NetImport
|
||||||
|
{
|
||||||
|
public class ImportExclusionsResource : ProviderResource
|
||||||
|
{
|
||||||
|
//public int Id { get; set; }
|
||||||
|
public int TmdbId { get; set; }
|
||||||
|
public string MovieTitle { get; set; }
|
||||||
|
public int MovieYear { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ImportExclusionsResourceMapper
|
||||||
|
{
|
||||||
|
public static ImportExclusionsResource ToResource(this Core.NetImport.ImportExclusions.ImportExclusion model)
|
||||||
|
{
|
||||||
|
if (model == null) return null;
|
||||||
|
|
||||||
|
return new ImportExclusionsResource
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
TmdbId = model.TmdbId,
|
||||||
|
MovieTitle = model.MovieTitle,
|
||||||
|
MovieYear = model.MovieYear
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ImportExclusionsResource> ToResource(this IEnumerable<Core.NetImport.ImportExclusions.ImportExclusion> exclusions)
|
||||||
|
{
|
||||||
|
return exclusions.Select(ToResource).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Core.NetImport.ImportExclusions.ImportExclusion ToModel(this ImportExclusionsResource resource)
|
||||||
|
{
|
||||||
|
return new Core.NetImport.ImportExclusions.ImportExclusion
|
||||||
|
{
|
||||||
|
TmdbId = resource.TmdbId,
|
||||||
|
MovieTitle = resource.MovieTitle,
|
||||||
|
MovieYear = resource.MovieYear
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -270,6 +270,9 @@
|
|||||||
<Compile Include="Wanted\MissingModule.cs" />
|
<Compile Include="Wanted\MissingModule.cs" />
|
||||||
<Compile Include="Wanted\MovieCutoffModule.cs" />
|
<Compile Include="Wanted\MovieCutoffModule.cs" />
|
||||||
<Compile Include="Wanted\MovieMissingModule.cs" />
|
<Compile Include="Wanted\MovieMissingModule.cs" />
|
||||||
|
<Compile Include="Series\MovieDiscoverModule.cs" />
|
||||||
|
<Compile Include="NetImport\ImportExclusionsModule.cs" />
|
||||||
|
<Compile Include="NetImport\ImportExclusionsResource.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace NzbDrone.Api.Queue
|
|||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
_downloadService.DownloadReport(pendingRelease.RemoteEpisode);
|
_downloadService.DownloadReport(pendingRelease.RemoteMovie);
|
||||||
|
|
||||||
return resource.AsResponse();
|
return resource.AsResponse();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Nancy;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Core.MediaCover;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
public class MovieDiscoverModule : NzbDroneRestModule<MovieResource>
|
||||||
|
{
|
||||||
|
private readonly IDiscoverNewMovies _searchProxy;
|
||||||
|
|
||||||
|
public MovieDiscoverModule(IDiscoverNewMovies searchProxy)
|
||||||
|
: base("/movies/discover")
|
||||||
|
{
|
||||||
|
_searchProxy = searchProxy;
|
||||||
|
Get["/{action?recommendations}"] = x => Search(x.action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response Search(string action)
|
||||||
|
{
|
||||||
|
var imdbResults = _searchProxy.DiscoverNewMovies(action);
|
||||||
|
return MapToResource(imdbResults).AsResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
||||||
|
{
|
||||||
|
foreach (var currentSeries in movies)
|
||||||
|
{
|
||||||
|
var resource = currentSeries.ToResource();
|
||||||
|
var poster = currentSeries.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||||
|
if (poster != null)
|
||||||
|
{
|
||||||
|
resource.RemotePoster = poster.Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,8 @@ using NzbDrone.Core.DataAugmentation.Scene;
|
|||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
using NzbDrone.SignalR;
|
using NzbDrone.SignalR;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
using Microsoft.CSharp.RuntimeBinder;
|
||||||
|
using Nancy;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Movie
|
namespace NzbDrone.Api.Movie
|
||||||
{
|
{
|
||||||
@@ -58,9 +60,12 @@ namespace NzbDrone.Api.Movie
|
|||||||
GetResourceAll = AllMovie;
|
GetResourceAll = AllMovie;
|
||||||
GetResourcePaged = GetMoviePaged;
|
GetResourcePaged = GetMoviePaged;
|
||||||
GetResourceById = GetMovie;
|
GetResourceById = GetMovie;
|
||||||
Get[TITLE_SLUG_ROUTE] = (options) => {
|
Get[TITLE_SLUG_ROUTE] = GetByTitleSlug; /*(options) => {
|
||||||
return ReqResExtensions.AsResponse(GetByTitleSlug(options.slug));
|
return ReqResExtensions.AsResponse(GetByTitleSlug(options.slug), Nancy.HttpStatusCode.OK);
|
||||||
};
|
};*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CreateResource = AddMovie;
|
CreateResource = AddMovie;
|
||||||
UpdateResource = UpdateMovie;
|
UpdateResource = UpdateMovie;
|
||||||
DeleteResource = DeleteMovie;
|
DeleteResource = DeleteMovie;
|
||||||
@@ -118,7 +123,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
pagingSpec.FilterExpression = _moviesService.ConstructFilterExpression(pagingResource.FilterKey, pagingResource.FilterValue, pagingResource.FilterType);
|
pagingSpec.FilterExpression = _moviesService.ConstructFilterExpression(pagingResource.FilterKey, pagingResource.FilterValue, pagingResource.FilterType);
|
||||||
|
|
||||||
return ApplyToPage(_moviesService.Paged, pagingSpec, MovieResourceMapper.ToResource);
|
return ApplyToPage(_moviesService.Paged, pagingSpec, MapToResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MovieResource MapToResource(Core.Tv.Movie movies)
|
protected MovieResource MapToResource(Core.Tv.Movie movies)
|
||||||
@@ -145,9 +150,27 @@ namespace NzbDrone.Api.Movie
|
|||||||
return moviesResources;
|
return moviesResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MovieResource GetByTitleSlug(string slug)
|
private Response GetByTitleSlug(dynamic options)
|
||||||
{
|
{
|
||||||
return MapToResource(_moviesService.FindByTitleSlug(slug));
|
var slug = "";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
slug = options.slug;
|
||||||
|
// do stuff with x
|
||||||
|
}
|
||||||
|
catch (RuntimeBinderException)
|
||||||
|
{
|
||||||
|
return new NotFoundResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return MapToResource(_moviesService.FindByTitleSlug(slug)).AsResponse(Nancy.HttpStatusCode.OK);
|
||||||
|
}
|
||||||
|
catch (ModelNotFoundException)
|
||||||
|
{
|
||||||
|
return new NotFoundResponse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int AddMovie(MovieResource moviesResource)
|
private int AddMovie(MovieResource moviesResource)
|
||||||
@@ -213,7 +236,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics)
|
private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics)
|
||||||
{
|
{
|
||||||
resource.SizeOnDisk = moviesStatistics.SizeOnDisk;
|
//resource.SizeOnDisk = 0;//TODO: incorporate movie statistics moviesStatistics.SizeOnDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateAlternateTitles(List<MovieResource> resources)
|
private void PopulateAlternateTitles(List<MovieResource> resources)
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
//View & Edit
|
//View & Edit
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
public int ProfileId { get; set; }
|
public int ProfileId { get; set; }
|
||||||
|
public MoviePathState PathState { get; set; }
|
||||||
|
|
||||||
//Editing Only
|
//Editing Only
|
||||||
public bool Monitored { get; set; }
|
public bool Monitored { get; set; }
|
||||||
@@ -120,7 +121,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
//TotalEpisodeCount
|
//TotalEpisodeCount
|
||||||
//EpisodeCount
|
//EpisodeCount
|
||||||
//EpisodeFileCount
|
//EpisodeFileCount
|
||||||
//SizeOnDisk
|
SizeOnDisk = size,
|
||||||
Status = model.Status,
|
Status = model.Status,
|
||||||
Overview = model.Overview,
|
Overview = model.Overview,
|
||||||
//NextAiring
|
//NextAiring
|
||||||
@@ -131,6 +132,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
ProfileId = model.ProfileId,
|
ProfileId = model.ProfileId,
|
||||||
|
PathState = model.PathState,
|
||||||
|
|
||||||
Monitored = model.Monitored,
|
Monitored = model.Monitored,
|
||||||
MinimumAvailability = model.MinimumAvailability,
|
MinimumAvailability = model.MinimumAvailability,
|
||||||
@@ -138,7 +140,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
IsAvailable = model.IsAvailable(),
|
IsAvailable = model.IsAvailable(),
|
||||||
FolderName = model.FolderName(),
|
FolderName = model.FolderName(),
|
||||||
|
|
||||||
SizeOnDisk = size,
|
//SizeOnDisk = size,
|
||||||
|
|
||||||
Runtime = model.Runtime,
|
Runtime = model.Runtime,
|
||||||
LastInfoSync = model.LastInfoSync,
|
LastInfoSync = model.LastInfoSync,
|
||||||
@@ -187,6 +189,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
ProfileId = resource.ProfileId,
|
ProfileId = resource.ProfileId,
|
||||||
|
PathState = resource.PathState,
|
||||||
|
|
||||||
Monitored = resource.Monitored,
|
Monitored = resource.Monitored,
|
||||||
MinimumAvailability = resource.MinimumAvailability,
|
MinimumAvailability = resource.MinimumAvailability,
|
||||||
@@ -217,6 +220,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
movie.Path = resource.Path;
|
movie.Path = resource.Path;
|
||||||
movie.ProfileId = resource.ProfileId;
|
movie.ProfileId = resource.ProfileId;
|
||||||
|
movie.PathState = resource.PathState;
|
||||||
|
|
||||||
movie.Monitored = resource.Monitored;
|
movie.Monitored = resource.Monitored;
|
||||||
movie.MinimumAvailability = resource.MinimumAvailability;
|
movie.MinimumAvailability = resource.MinimumAvailability;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace NzbDrone.Common.Test.DiskTests
|
|||||||
public void should_be_able_to_check_space_on_ramdrive()
|
public void should_be_able_to_check_space_on_ramdrive()
|
||||||
{
|
{
|
||||||
MonoOnly();
|
MonoOnly();
|
||||||
Subject.GetAvailableSpace("/run/").Should().NotBe(0);
|
Subject.GetAvailableSpace("/").Should().NotBe(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ namespace NzbDrone.Common.Test
|
|||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("")]
|
[TestCase("")]
|
||||||
[TestCase("http://")]
|
|
||||||
public void DownloadString_should_throw_on_error(string url)
|
public void DownloadString_should_throw_on_error(string url)
|
||||||
{
|
{
|
||||||
Assert.Throws<ArgumentException>(() => Subject.DownloadString(url));
|
Assert.Throws<ArgumentException>(() => Subject.DownloadString(url));
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -80,5 +80,30 @@ namespace NzbDrone.Common.Extensions
|
|||||||
{
|
{
|
||||||
return source.Select(predicate).ToList();
|
return source.Select(predicate).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> DropLast<T>(this IEnumerable<T> source, int n)
|
||||||
|
{
|
||||||
|
if (source == null)
|
||||||
|
throw new ArgumentNullException("source");
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
throw new ArgumentOutOfRangeException("n",
|
||||||
|
"Argument n should be non-negative.");
|
||||||
|
|
||||||
|
return InternalDropLast(source, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<T> InternalDropLast<T>(IEnumerable<T> source, int n)
|
||||||
|
{
|
||||||
|
Queue<T> buffer = new Queue<T>(n + 1);
|
||||||
|
|
||||||
|
foreach (T x in source)
|
||||||
|
{
|
||||||
|
buffer.Enqueue(x);
|
||||||
|
|
||||||
|
if (buffer.Count == n + 1)
|
||||||
|
yield return buffer.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
{
|
{
|
||||||
public static readonly HttpAccept Rss = new HttpAccept("application/rss+xml, text/rss+xml, application/xml, text/xml");
|
public static readonly HttpAccept Rss = new HttpAccept("application/rss+xml, text/rss+xml, application/xml, text/xml");
|
||||||
public static readonly HttpAccept Json = new HttpAccept("application/json");
|
public static readonly HttpAccept Json = new HttpAccept("application/json");
|
||||||
|
public static readonly HttpAccept JsonCharset = new HttpAccept("application/json;charset=utf-8");
|
||||||
public static readonly HttpAccept Html = new HttpAccept("text/html");
|
public static readonly HttpAccept Html = new HttpAccept("text/html");
|
||||||
|
|
||||||
public string Value { get; private set; }
|
public string Value { get; private set; }
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
private RemoteEpisode parseResultMulti;
|
private RemoteEpisode parseResultMulti;
|
||||||
private RemoteEpisode parseResultSingle;
|
private RemoteEpisode parseResultSingle;
|
||||||
private Series series;
|
private Series series;
|
||||||
|
private Movie movie;
|
||||||
|
private RemoteMovie remoteMovie;
|
||||||
private QualityDefinition qualityType;
|
private QualityDefinition qualityType;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
@@ -28,6 +30,16 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
series = Builder<Series>.CreateNew()
|
series = Builder<Series>.CreateNew()
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
movie = Builder<Movie>.CreateNew().Build();
|
||||||
|
|
||||||
|
remoteMovie = new RemoteMovie
|
||||||
|
{
|
||||||
|
Movie = movie,
|
||||||
|
Release = new ReleaseInfo(),
|
||||||
|
ParsedMovieInfo = new ParsedMovieInfo { Quality = new QualityModel(Quality.SDTV, new Revision(version: 2)) },
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
parseResultMultiSet = new RemoteEpisode
|
parseResultMultiSet = new RemoteEpisode
|
||||||
{
|
{
|
||||||
Series = series,
|
Series = series,
|
||||||
@@ -216,5 +228,17 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||||||
|
|
||||||
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_use_110_minutes_if_runtime_is_0()
|
||||||
|
{
|
||||||
|
movie.Runtime = 0;
|
||||||
|
remoteMovie.Movie = movie;
|
||||||
|
remoteMovie.Release.Size = 1095.Megabytes();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(remoteMovie, null).Accepted.Should().Be(true);
|
||||||
|
remoteMovie.Release.Size = 1105.Megabytes();
|
||||||
|
Subject.IsSatisfiedBy(remoteMovie, null).Accepted.Should().Be(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -275,7 +275,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
{ "default_destination", _defaultDestination },
|
{ "default_destination", _defaultDestination },
|
||||||
};
|
};
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationInfoProxy>()
|
||||||
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
|
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
|
||||||
.Returns(_downloadStationConfigItems);
|
.Returns(_downloadStationConfigItems);
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
torrents = new List<DownloadStationTask>();
|
torrents = new List<DownloadStationTask>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>()))
|
.Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>()))
|
||||||
.Returns(torrents);
|
.Returns(torrents);
|
||||||
}
|
}
|
||||||
@@ -330,11 +330,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
.Setup(s => s.Get(It.IsAny<HttpRequest>()))
|
.Setup(s => s.Get(It.IsAny<HttpRequest>()))
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
|
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Setup(s => s.AddTaskFromUrl(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
.Setup(s => s.AddTaskFromUrl(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||||
.Callback(PrepareClientToReturnQueuedItem);
|
.Callback(PrepareClientToReturnQueuedItem);
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
.Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||||
.Callback(PrepareClientToReturnQueuedItem);
|
.Callback(PrepareClientToReturnQueuedItem);
|
||||||
}
|
}
|
||||||
@@ -352,7 +352,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
{
|
{
|
||||||
var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding };
|
var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding };
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Setup(d => d.GetTasks(_settings))
|
.Setup(d => d.GetTasks(_settings))
|
||||||
.Returns(tasks);
|
.Returns(tasks);
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
|
|
||||||
id.Should().NotBeNullOrEmpty();
|
id.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
|
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,7 +389,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
|
|
||||||
id.Should().NotBeNullOrEmpty();
|
id.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
|
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +405,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
|
|
||||||
id.Should().NotBeNullOrEmpty();
|
id.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
|
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +482,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
|
|
||||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
|
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
|
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -177,7 +177,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
{ "default_destination", _defaultDestination },
|
{ "default_destination", _defaultDestination },
|
||||||
};
|
};
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationInfoProxy>()
|
||||||
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
|
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
|
||||||
.Returns(_downloadStationConfigItems);
|
.Returns(_downloadStationConfigItems);
|
||||||
}
|
}
|
||||||
@@ -213,7 +213,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
nzbs = new List<DownloadStationTask>();
|
nzbs = new List<DownloadStationTask>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>()))
|
.Setup(s => s.GetTasks(It.IsAny<DownloadStationSettings>()))
|
||||||
.Returns(nzbs);
|
.Returns(nzbs);
|
||||||
}
|
}
|
||||||
@@ -233,7 +233,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
|
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
.Setup(s => s.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||||
.Callback(PrepareClientToReturnQueuedItem);
|
.Callback(PrepareClientToReturnQueuedItem);
|
||||||
}
|
}
|
||||||
@@ -242,7 +242,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
{
|
{
|
||||||
var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding };
|
var tasks = new List<DownloadStationTask>() { _queued, _completed, _failed, _downloading, _seeding };
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Setup(d => d.GetTasks(_settings))
|
.Setup(d => d.GetTasks(_settings))
|
||||||
.Returns(tasks);
|
.Returns(tasks);
|
||||||
}
|
}
|
||||||
@@ -260,7 +260,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
|
|
||||||
id.Should().NotBeNullOrEmpty();
|
id.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
|
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
|
|
||||||
id.Should().NotBeNullOrEmpty();
|
id.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
|
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
|
|
||||||
id.Should().NotBeNullOrEmpty();
|
id.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
|
.Verify(v => v.AddTaskFromData(It.IsAny<byte[]>(), It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +370,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
|||||||
|
|
||||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
|
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadStationProxy>()
|
Mocker.GetMock<IDownloadStationTaskProxy>()
|
||||||
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
|
.Verify(v => v.AddTaskFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-23
@@ -25,26 +25,26 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
|
|||||||
};
|
};
|
||||||
|
|
||||||
_downloading = new RTorrentTorrent
|
_downloading = new RTorrentTorrent
|
||||||
{
|
{
|
||||||
Hash = "HASH",
|
Hash = "HASH",
|
||||||
IsFinished = false,
|
IsFinished = false,
|
||||||
IsOpen = true,
|
IsOpen = true,
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
Name = _title,
|
Name = _title,
|
||||||
TotalSize = 1000,
|
TotalSize = 1000,
|
||||||
RemainingSize = 500,
|
RemainingSize = 500,
|
||||||
Path = "somepath"
|
Path = "somepath"
|
||||||
};
|
};
|
||||||
|
|
||||||
_completed = new RTorrentTorrent
|
_completed = new RTorrentTorrent
|
||||||
{
|
{
|
||||||
Hash = "HASH",
|
Hash = "HASH",
|
||||||
IsFinished = true,
|
IsFinished = true,
|
||||||
Name = _title,
|
Name = _title,
|
||||||
TotalSize = 1000,
|
TotalSize = 1000,
|
||||||
RemainingSize = 0,
|
RemainingSize = 0,
|
||||||
Path = "somepath"
|
Path = "somepath"
|
||||||
};
|
};
|
||||||
|
|
||||||
Mocker.GetMock<ITorrentFileInfoReader>()
|
Mocker.GetMock<ITorrentFileInfoReader>()
|
||||||
.Setup(s => s.GetHashFromTorrentFile(It.IsAny<byte[]>()))
|
.Setup(s => s.GetHashFromTorrentFile(It.IsAny<byte[]>()))
|
||||||
@@ -54,11 +54,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
|
|||||||
protected void GivenSuccessfulDownload()
|
protected void GivenSuccessfulDownload()
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IRTorrentProxy>()
|
Mocker.GetMock<IRTorrentProxy>()
|
||||||
.Setup(s => s.AddTorrentFromUrl(It.IsAny<string>(), It.IsAny<RTorrentSettings>()))
|
.Setup(s => s.AddTorrentFromUrl(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<RTorrentPriority>(), It.IsAny<string>(), It.IsAny<RTorrentSettings>()))
|
||||||
.Callback(PrepareClientToReturnCompletedItem);
|
.Callback(PrepareClientToReturnCompletedItem);
|
||||||
|
|
||||||
Mocker.GetMock<IRTorrentProxy>()
|
Mocker.GetMock<IRTorrentProxy>()
|
||||||
.Setup(s => s.AddTorrentFromFile(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<RTorrentSettings>()))
|
.Setup(s => s.AddTorrentFromFile(It.IsAny<string>(), It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<RTorrentPriority>(), It.IsAny<string>(), It.IsAny<RTorrentSettings>()))
|
||||||
.Callback(PrepareClientToReturnCompletedItem);
|
.Callback(PrepareClientToReturnCompletedItem);
|
||||||
|
|
||||||
|
|
||||||
@@ -116,11 +116,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
|
|||||||
{
|
{
|
||||||
GivenSuccessfulDownload();
|
GivenSuccessfulDownload();
|
||||||
|
|
||||||
var remoteMovie = CreateRemoteMovie();
|
var remoteEpisode = CreateRemoteMovie();
|
||||||
|
|
||||||
var id = Subject.Download(remoteMovie);
|
var id = Subject.Download(remoteEpisode);
|
||||||
|
|
||||||
id.Should().NotBeNullOrEmpty();
|
id.Should().NotBeNullOrEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+122
-10
@@ -23,6 +23,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
private SabnzbdHistory _failed;
|
private SabnzbdHistory _failed;
|
||||||
private SabnzbdHistory _completed;
|
private SabnzbdHistory _completed;
|
||||||
private SabnzbdConfig _config;
|
private SabnzbdConfig _config;
|
||||||
|
private SabnzbdFullStatus _fullStatus;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
@@ -65,7 +66,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
{
|
{
|
||||||
Status = SabnzbdDownloadStatus.Failed,
|
Status = SabnzbdDownloadStatus.Failed,
|
||||||
Size = 1000,
|
Size = 1000,
|
||||||
Category = "tv",
|
Category = "tv",
|
||||||
Id = "sabnzbd_nzb12345",
|
Id = "sabnzbd_nzb12345",
|
||||||
Title = "Droned.1998.1080p.WEB-DL-DRONE"
|
Title = "Droned.1998.1080p.WEB-DL-DRONE"
|
||||||
}
|
}
|
||||||
@@ -80,7 +81,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
{
|
{
|
||||||
Status = SabnzbdDownloadStatus.Completed,
|
Status = SabnzbdDownloadStatus.Completed,
|
||||||
Size = 1000,
|
Size = 1000,
|
||||||
Category = "tv",
|
Category = "tv",
|
||||||
Id = "sabnzbd_nzb12345",
|
Id = "sabnzbd_nzb12345",
|
||||||
Title = "Droned.1998.1080p.WEB-DL-DRONE",
|
Title = "Droned.1998.1080p.WEB-DL-DRONE",
|
||||||
Storage = "/remote/mount/vv/Droned.1998.1080p.WEB-DL-DRONE"
|
Storage = "/remote/mount/vv/Droned.1998.1080p.WEB-DL-DRONE"
|
||||||
@@ -100,9 +101,29 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Mocker.GetMock<ISabnzbdProxy>()
|
||||||
|
.Setup(v => v.GetVersion(It.IsAny<SabnzbdSettings>()))
|
||||||
|
.Returns("1.2.3");
|
||||||
|
|
||||||
Mocker.GetMock<ISabnzbdProxy>()
|
Mocker.GetMock<ISabnzbdProxy>()
|
||||||
.Setup(s => s.GetConfig(It.IsAny<SabnzbdSettings>()))
|
.Setup(s => s.GetConfig(It.IsAny<SabnzbdSettings>()))
|
||||||
.Returns(_config);
|
.Returns(_config);
|
||||||
|
|
||||||
|
_fullStatus = new SabnzbdFullStatus
|
||||||
|
{
|
||||||
|
CompleteDir = @"Y:\nzbget\root\complete".AsOsAgnostic()
|
||||||
|
};
|
||||||
|
|
||||||
|
Mocker.GetMock<ISabnzbdProxy>()
|
||||||
|
.Setup(s => s.GetFullStatus(It.IsAny<SabnzbdSettings>()))
|
||||||
|
.Returns(_fullStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void GivenVersion(string version)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<ISabnzbdProxy>()
|
||||||
|
.Setup(s => s.GetVersion(It.IsAny<SabnzbdSettings>()))
|
||||||
|
.Returns(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void GivenFailedDownload()
|
protected void GivenFailedDownload()
|
||||||
@@ -166,7 +187,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
|
|
||||||
GivenQueue(_queued);
|
GivenQueue(_queued);
|
||||||
GivenHistory(null);
|
GivenHistory(null);
|
||||||
|
|
||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
VerifyQueued(result);
|
VerifyQueued(result);
|
||||||
@@ -387,23 +408,46 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
result.OutputPath.Should().Be(@"C:\sorted\somewhere\asdfasdf\asdfasdf.mkv".AsOsAgnostic());
|
result.OutputPath.Should().Be(@"C:\sorted\somewhere\asdfasdf\asdfasdf.mkv".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads\vv")]
|
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads", @"Y:\nzbget\root\completed\downloads\vv")]
|
||||||
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed\vv")]
|
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed", @"Y:\nzbget\root\completed\vv")]
|
||||||
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads/vv")]
|
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads", @"/nzbget/root/completed/downloads/vv")]
|
||||||
[TestCase(@"/nzbget/root", @"completed", @"vv", @"/nzbget/root/completed/vv")]
|
[TestCase(@"/nzbget/root", @"completed", @"vv", @"/nzbget/root/completed", @"/nzbget/root/completed/vv")]
|
||||||
public void should_return_status_with_outputdir(string rootFolder, string completeDir, string categoryDir, string expectedDir)
|
public void should_return_status_with_outputdir_for_version_lt_2(string rootFolder, string completeDir, string categoryDir, string fullCompleteDir, string fullCategoryDir)
|
||||||
{
|
{
|
||||||
|
_fullStatus.CompleteDir = null;
|
||||||
_queued.DefaultRootFolder = rootFolder;
|
_queued.DefaultRootFolder = rootFolder;
|
||||||
_config.Misc.complete_dir = completeDir;
|
_config.Misc.complete_dir = completeDir;
|
||||||
_config.Categories.First().Dir = categoryDir;
|
_config.Categories.First().Dir = categoryDir;
|
||||||
|
|
||||||
|
GivenVersion("1.2.1");
|
||||||
GivenQueue(null);
|
GivenQueue(null);
|
||||||
|
|
||||||
var result = Subject.GetStatus();
|
var result = Subject.GetStatus();
|
||||||
|
|
||||||
result.IsLocalhost.Should().BeTrue();
|
result.IsLocalhost.Should().BeTrue();
|
||||||
result.OutputRootFolders.Should().NotBeNull();
|
result.OutputRootFolders.Should().NotBeNull();
|
||||||
result.OutputRootFolders.First().Should().Be(expectedDir);
|
result.OutputRootFolders.First().Should().Be(fullCategoryDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads", @"Y:\nzbget\root\completed\downloads\vv")]
|
||||||
|
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed", @"Y:\nzbget\root\completed\vv")]
|
||||||
|
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads", @"/nzbget/root/completed/downloads/vv")]
|
||||||
|
[TestCase(@"/nzbget/root", @"completed", @"vv", @"/nzbget/root/completed", @"/nzbget/root/completed/vv")]
|
||||||
|
public void should_return_status_with_outputdir_for_version_gte_2(string rootFolder, string completeDir, string categoryDir, string fullCompleteDir, string fullCategoryDir)
|
||||||
|
{
|
||||||
|
_fullStatus.CompleteDir = fullCompleteDir;
|
||||||
|
_queued.DefaultRootFolder = null;
|
||||||
|
_config.Misc.complete_dir = completeDir;
|
||||||
|
_config.Categories.First().Dir = categoryDir;
|
||||||
|
|
||||||
|
GivenVersion("2.0.0beta1");
|
||||||
|
GivenQueue(null);
|
||||||
|
|
||||||
|
var result = Subject.GetStatus();
|
||||||
|
|
||||||
|
result.IsLocalhost.Should().BeTrue();
|
||||||
|
result.OutputRootFolders.Should().NotBeNull();
|
||||||
|
result.OutputRootFolders.First().Should().Be(fullCategoryDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -451,5 +495,73 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
|
|||||||
result.IsValid.Should().BeTrue();
|
result.IsValid.Should().BeTrue();
|
||||||
result.HasWarnings.Should().BeTrue();
|
result.HasWarnings.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_test_success_if_tv_sorting_disabled()
|
||||||
|
{
|
||||||
|
_config.Misc.enable_tv_sorting = false;
|
||||||
|
_config.Misc.tv_categories = null;
|
||||||
|
|
||||||
|
var result = new NzbDroneValidationResult(Subject.Test());
|
||||||
|
|
||||||
|
result.IsValid.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_test_failed_if_tv_sorting_null()
|
||||||
|
{
|
||||||
|
_config.Misc.enable_tv_sorting = true;
|
||||||
|
_config.Misc.tv_categories = null;
|
||||||
|
|
||||||
|
var result = new NzbDroneValidationResult(Subject.Test());
|
||||||
|
|
||||||
|
result.IsValid.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_test_failed_if_tv_sorting_empty()
|
||||||
|
{
|
||||||
|
_config.Misc.enable_tv_sorting = true;
|
||||||
|
_config.Misc.tv_categories = new string[0];
|
||||||
|
|
||||||
|
var result = new NzbDroneValidationResult(Subject.Test());
|
||||||
|
|
||||||
|
result.IsValid.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_test_success_if_tv_sorting_contains_different_category()
|
||||||
|
{
|
||||||
|
_config.Misc.enable_tv_sorting = true;
|
||||||
|
_config.Misc.tv_categories = new[] { "tv-custom" };
|
||||||
|
|
||||||
|
var result = new NzbDroneValidationResult(Subject.Test());
|
||||||
|
|
||||||
|
result.IsValid.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_test_failed_if_tv_sorting_contains_category()
|
||||||
|
{
|
||||||
|
_config.Misc.enable_tv_sorting = true;
|
||||||
|
_config.Misc.tv_categories = new[] { "tv" };
|
||||||
|
|
||||||
|
var result = new NzbDroneValidationResult(Subject.Test());
|
||||||
|
|
||||||
|
result.IsValid.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_test_failed_if_tv_sorting_default_category()
|
||||||
|
{
|
||||||
|
Subject.Definition.Settings.As<SabnzbdSettings>().TvCategory = null;
|
||||||
|
|
||||||
|
_config.Misc.enable_tv_sorting = true;
|
||||||
|
_config.Misc.tv_categories = new[] { "Default" };
|
||||||
|
|
||||||
|
var result = new NzbDroneValidationResult(Subject.Test());
|
||||||
|
|
||||||
|
result.IsValid.Should().BeFalse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -145,8 +145,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
|||||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
||||||
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
|
||||||
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||||
{
|
{
|
||||||
_queued.Status = apiStatus;
|
_queued.Status = apiStatus;
|
||||||
@@ -160,7 +160,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
|||||||
|
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
||||||
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
|
||||||
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||||
{
|
{
|
||||||
_downloading.Status = apiStatus;
|
_downloading.Status = apiStatus;
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class VuzeFixture : TransmissionFixtureBase<Vuze>
|
public class VuzeFixture : TransmissionFixtureBase<Vuze>
|
||||||
{
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup_Vuze()
|
||||||
|
{
|
||||||
|
// Vuze never sets isFinished.
|
||||||
|
_completed.IsFinished = false;
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void queued_item_should_have_required_properties()
|
public void queued_item_should_have_required_properties()
|
||||||
{
|
{
|
||||||
@@ -147,8 +154,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
||||||
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
|
||||||
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||||
{
|
{
|
||||||
_queued.Status = apiStatus;
|
_queued.Status = apiStatus;
|
||||||
@@ -162,7 +169,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
|
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
|
||||||
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
|
||||||
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||||
{
|
{
|
||||||
_downloading.Status = apiStatus;
|
_downloading.Status = apiStatus;
|
||||||
@@ -177,7 +184,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)]
|
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)]
|
||||||
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, true)]
|
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, true)]
|
||||||
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, true)]
|
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, true)]
|
||||||
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, true)]
|
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued, true)]
|
||||||
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, true)]
|
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, true)]
|
||||||
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, true)]
|
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, true)]
|
||||||
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly)
|
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly)
|
||||||
@@ -294,7 +301,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_have_correct_output_directory()
|
public void should_have_correct_output_directory_for_multifile_torrents()
|
||||||
{
|
{
|
||||||
WindowsOnly();
|
WindowsOnly();
|
||||||
|
|
||||||
@@ -311,5 +318,25 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
items.First().OutputPath.Should().Be(@"C:\Downloads\" + _title);
|
items.First().OutputPath.Should().Be(@"C:\Downloads\" + _title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_have_correct_output_directory_for_singlefile_torrents()
|
||||||
|
{
|
||||||
|
WindowsOnly();
|
||||||
|
|
||||||
|
var fileName = _title + ".mkv";
|
||||||
|
_downloading.Name = fileName;
|
||||||
|
_downloading.DownloadDir = @"C:/Downloads";
|
||||||
|
|
||||||
|
GivenTorrents(new List<TransmissionTorrent>
|
||||||
|
{
|
||||||
|
_downloading
|
||||||
|
});
|
||||||
|
|
||||||
|
var items = Subject.GetItems().ToList();
|
||||||
|
|
||||||
|
items.Should().HaveCount(1);
|
||||||
|
items.First().OutputPath.Should().Be(@"C:\Downloads\" + fileName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,57 +1,63 @@
|
|||||||
{
|
{
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
"id": 257142,
|
"id": 257142,
|
||||||
"hash": "EABC50AEF9F53CEDED84ADF14144D3368E586F3A",
|
"hash": "EABC50AEF9F53CEDED84ADF14144D3368E586F3A",
|
||||||
"leechers": 1,
|
"leechers": 1,
|
||||||
"seeders": 46,
|
"seeders": 46,
|
||||||
"name": "Supernatural S10E17 1080p WEB-DL DD5.1 H.264-ECI",
|
"name": "Supernatural S10E17 1080p WEB-DL DD5.1 H.264-ECI",
|
||||||
"times_completed": 49,
|
"times_completed": 49,
|
||||||
"size": 1718009717,
|
"size": 1718009717,
|
||||||
"utadded": 1428179446,
|
"utadded": 1428179446,
|
||||||
"added": "2015-04-04T20:30:46+0000",
|
"added": "2015-04-04T20:30:46+0000",
|
||||||
"comments": 0,
|
"comments": 0,
|
||||||
"numfiles": 1,
|
"numfiles": 1,
|
||||||
"filename": "Supernatural.S10E17.1080p.WEB-DL.DD5.1.H.264-ECI.torrent",
|
"filename": "Supernatural.S10E17.1080p.WEB-DL.DD5.1.H.264-ECI.torrent",
|
||||||
"freeleech": "no",
|
"freeleech": "no",
|
||||||
"type_category": 2,
|
"type_category": 2,
|
||||||
"type_codec": 1,
|
"type_codec": 1,
|
||||||
"type_medium": 6,
|
"type_medium": 6,
|
||||||
"type_origin": 0,
|
"type_origin": 0,
|
||||||
"username": "abc",
|
"username": "abc",
|
||||||
"owner": 1107944,
|
"owner": 1107944,
|
||||||
"tvdb": {
|
"tvdb": {
|
||||||
"id": 78901,
|
"id": 78901,
|
||||||
"season": 10,
|
"season": 10,
|
||||||
"episode": 17
|
"episode": 17
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
"imdb": {
|
||||||
"id": 257140,
|
"id": 78901
|
||||||
"hash": "BE3BA5396B9A30544353B55FDD89EDE46C8FB72A",
|
|
||||||
"leechers": 0,
|
|
||||||
"seeders": 18,
|
|
||||||
"name": "Scandal S04E18 1080p WEB-DL DD5.1 H.264-ECI",
|
|
||||||
"times_completed": 19,
|
|
||||||
"size": 1789106197,
|
|
||||||
"utadded": 1428179128,
|
|
||||||
"added": "2015-04-04T20:25:28+0000",
|
|
||||||
"comments": 0,
|
|
||||||
"numfiles": 1,
|
|
||||||
"filename": "Scandal.2012.S04E18.1080p.WEB-DL.DD5.1.H.264-ECI.torrent",
|
|
||||||
"freeleech": "no",
|
|
||||||
"type_category": 2,
|
|
||||||
"type_codec": 1,
|
|
||||||
"type_medium": 6,
|
|
||||||
"type_origin": 0,
|
|
||||||
"username": "abc",
|
|
||||||
"owner": 1107944,
|
|
||||||
"tvdb": {
|
|
||||||
"id": 248841,
|
|
||||||
"season": 4,
|
|
||||||
"episode": 18
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 257140,
|
||||||
|
"hash": "BE3BA5396B9A30544353B55FDD89EDE46C8FB72A",
|
||||||
|
"leechers": 0,
|
||||||
|
"seeders": 18,
|
||||||
|
"name": "Scandal S04E18 1080p WEB-DL DD5.1 H.264-ECI",
|
||||||
|
"times_completed": 19,
|
||||||
|
"size": 1789106197,
|
||||||
|
"utadded": 1428179128,
|
||||||
|
"added": "2015-04-04T20:25:28+0000",
|
||||||
|
"comments": 0,
|
||||||
|
"numfiles": 1,
|
||||||
|
"filename": "Scandal.2012.S04E18.1080p.WEB-DL.DD5.1.H.264-ECI.torrent",
|
||||||
|
"freeleech": "no",
|
||||||
|
"type_category": 2,
|
||||||
|
"type_codec": 1,
|
||||||
|
"type_medium": 6,
|
||||||
|
"type_origin": 0,
|
||||||
|
"username": "abc",
|
||||||
|
"owner": 1107944,
|
||||||
|
"tvdb": {
|
||||||
|
"id": 248841,
|
||||||
|
"season": 4,
|
||||||
|
"episode": 18
|
||||||
|
},
|
||||||
|
"imdb": {
|
||||||
|
"id": 78901
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,57 +1,63 @@
|
|||||||
{
|
{
|
||||||
"status": 0,
|
"status": 0,
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
"id": "257142",
|
"id": "257142",
|
||||||
"hash": "EABC50AEF9F53CEDED84ADF14144D3368E586F3A",
|
"hash": "EABC50AEF9F53CEDED84ADF14144D3368E586F3A",
|
||||||
"leechers": 1,
|
"leechers": 1,
|
||||||
"seeders": 46,
|
"seeders": 46,
|
||||||
"name": "Supernatural S10E17 1080p WEB-DL DD5.1 H.264-ECI",
|
"name": "Supernatural S10E17 1080p WEB-DL DD5.1 H.264-ECI",
|
||||||
"times_completed": 49,
|
"times_completed": 49,
|
||||||
"size": 1718009717,
|
"size": 1718009717,
|
||||||
"utadded": 1428179446,
|
"utadded": 1428179446,
|
||||||
"added": "2015-04-04T20:30:46+0000",
|
"added": "2015-04-04T20:30:46+0000",
|
||||||
"comments": 0,
|
"comments": 0,
|
||||||
"numfiles": 1,
|
"numfiles": 1,
|
||||||
"filename": "Supernatural.S10E17.1080p.WEB-DL.DD5.1.H.264-ECI.torrent",
|
"filename": "Supernatural.S10E17.1080p.WEB-DL.DD5.1.H.264-ECI.torrent",
|
||||||
"freeleech": "no",
|
"freeleech": "no",
|
||||||
"type_category": 2,
|
"type_category": 2,
|
||||||
"type_codec": 1,
|
"type_codec": 1,
|
||||||
"type_medium": 6,
|
"type_medium": 6,
|
||||||
"type_origin": 0,
|
"type_origin": 0,
|
||||||
"username": "abc",
|
"username": "abc",
|
||||||
"owner": 1107944,
|
"owner": 1107944,
|
||||||
"tvdb": {
|
"tvdb": {
|
||||||
"id": 78901,
|
"id": 78901,
|
||||||
"season": 10,
|
"season": 10,
|
||||||
"episode": 17
|
"episode": 17
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
"imdb": {
|
||||||
"id": "257140",
|
"id": 78901
|
||||||
"hash": "BE3BA5396B9A30544353B55FDD89EDE46C8FB72A",
|
|
||||||
"leechers": 0,
|
|
||||||
"seeders": 18,
|
|
||||||
"name": "Scandal S04E18 1080p WEB-DL DD5.1 H.264-ECI",
|
|
||||||
"times_completed": 19,
|
|
||||||
"size": 1789106197,
|
|
||||||
"utadded": 1428179128,
|
|
||||||
"added": "2015-04-04T20:25:28+0000",
|
|
||||||
"comments": 0,
|
|
||||||
"numfiles": 1,
|
|
||||||
"filename": "Scandal.2012.S04E18.1080p.WEB-DL.DD5.1.H.264-ECI.torrent",
|
|
||||||
"freeleech": "no",
|
|
||||||
"type_category": 2,
|
|
||||||
"type_codec": 1,
|
|
||||||
"type_medium": 6,
|
|
||||||
"type_origin": 0,
|
|
||||||
"username": "abc",
|
|
||||||
"owner": 1107944,
|
|
||||||
"tvdb": {
|
|
||||||
"id": 248841,
|
|
||||||
"season": 4,
|
|
||||||
"episode": 18
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "257140",
|
||||||
|
"hash": "BE3BA5396B9A30544353B55FDD89EDE46C8FB72A",
|
||||||
|
"leechers": 0,
|
||||||
|
"seeders": 18,
|
||||||
|
"name": "Scandal S04E18 1080p WEB-DL DD5.1 H.264-ECI",
|
||||||
|
"times_completed": 19,
|
||||||
|
"size": 1789106197,
|
||||||
|
"utadded": 1428179128,
|
||||||
|
"added": "2015-04-04T20:25:28+0000",
|
||||||
|
"comments": 0,
|
||||||
|
"numfiles": 1,
|
||||||
|
"filename": "Scandal.2012.S04E18.1080p.WEB-DL.DD5.1.H.264-ECI.torrent",
|
||||||
|
"freeleech": "no",
|
||||||
|
"type_category": 2,
|
||||||
|
"type_codec": 1,
|
||||||
|
"type_medium": 6,
|
||||||
|
"type_origin": 0,
|
||||||
|
"username": "abc",
|
||||||
|
"owner": 1107944,
|
||||||
|
"tvdb": {
|
||||||
|
"id": 248841,
|
||||||
|
"season": 4,
|
||||||
|
"episode": 18
|
||||||
|
},
|
||||||
|
"imdb": {
|
||||||
|
"id": 78901
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
File diff suppressed because one or more lines are too long
+6
-6
@@ -11,12 +11,12 @@ using NzbDrone.Core.Qualities;
|
|||||||
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class CleanupOrphanedEpisodeFilesFixture : DbTest<CleanupOrphanedEpisodeFiles, EpisodeFile>
|
public class CleanupOrphanedEpisodeFilesFixture : DbTest<CleanupOrphanedEpisodeFiles, MovieFile>
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void should_delete_orphaned_episode_files()
|
public void should_delete_orphaned_episode_files()
|
||||||
{
|
{
|
||||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
var episodeFile = Builder<MovieFile>.CreateNew()
|
||||||
.With(h => h.Quality = new QualityModel())
|
.With(h => h.Quality = new QualityModel())
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
@@ -28,22 +28,22 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_not_delete_unorphaned_episode_files()
|
public void should_not_delete_unorphaned_episode_files()
|
||||||
{
|
{
|
||||||
var episodeFiles = Builder<EpisodeFile>.CreateListOfSize(2)
|
var episodeFiles = Builder<MovieFile>.CreateListOfSize(2)
|
||||||
.All()
|
.All()
|
||||||
.With(h => h.Quality = new QualityModel())
|
.With(h => h.Quality = new QualityModel())
|
||||||
.BuildListOfNew();
|
.BuildListOfNew();
|
||||||
|
|
||||||
Db.InsertMany(episodeFiles);
|
Db.InsertMany(episodeFiles);
|
||||||
|
|
||||||
var episode = Builder<Episode>.CreateNew()
|
var episode = Builder<Movie>.CreateNew()
|
||||||
.With(e => e.EpisodeFileId = episodeFiles.First().Id)
|
.With(e => e.MovieFileId = episodeFiles.First().Id)
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(episode);
|
Db.Insert(episode);
|
||||||
|
|
||||||
Subject.Clean();
|
Subject.Clean();
|
||||||
AllStoredModels.Should().HaveCount(1);
|
AllStoredModels.Should().HaveCount(1);
|
||||||
Db.All<Episode>().Should().Contain(e => e.EpisodeFileId == AllStoredModels.First().Id);
|
Db.All<Movie>().Should().Contain(e => e.MovieFileId == AllStoredModels.First().Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-1
@@ -1,9 +1,12 @@
|
|||||||
using FluentAssertions;
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Indexers.Newznab;
|
using NzbDrone.Core.Indexers.Newznab;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
||||||
{
|
{
|
||||||
@@ -64,5 +67,35 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
|
|||||||
caps.DefaultPageSize.Should().Be(100);
|
caps.DefaultPageSize.Should().Be(100);
|
||||||
caps.MaxPageSize.Should().Be(100);
|
caps.MaxPageSize.Should().Be(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_throw_if_failed_to_get()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IHttpClient>()
|
||||||
|
.Setup(o => o.Get(It.IsAny<HttpRequest>()))
|
||||||
|
.Throws<Exception>();
|
||||||
|
|
||||||
|
Assert.Throws<Exception>(() => Subject.GetCapabilities(_settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_throw_if_xml_invalid()
|
||||||
|
{
|
||||||
|
GivenCapsResponse(_caps.Replace("<limits", "<>"));
|
||||||
|
|
||||||
|
Assert.Throws<XmlException>(() => Subject.GetCapabilities(_settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_throw_on_xml_data_unexpected()
|
||||||
|
{
|
||||||
|
GivenCapsResponse(_caps.Replace("5030", "asdf"));
|
||||||
|
|
||||||
|
var result = Subject.GetCapabilities(_settings);
|
||||||
|
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
|
||||||
|
ExceptionVerification.ExpectedErrors(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Indexers.PassThePopcorn;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.IndexerTests.PTPTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class PTPFixture : CoreTest<PassThePopcorn>
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
Subject.Definition = new IndexerDefinition()
|
||||||
|
{
|
||||||
|
Name = "PTP",
|
||||||
|
Settings = new PassThePopcornSettings() { Passkey = "fakekey", Username = "asdf", Password = "sad" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Files/Indexers/PTP/imdbsearch.json")]
|
||||||
|
public void should_parse_feed_from_PTP(string fileName)
|
||||||
|
{
|
||||||
|
var authResponse = new PassThePopcornAuthResponse { Result = "Ok" };
|
||||||
|
|
||||||
|
System.IO.StringWriter authStream = new System.IO.StringWriter();
|
||||||
|
Json.Serialize(authResponse, authStream);
|
||||||
|
var responseJson = ReadAllText(fileName);
|
||||||
|
|
||||||
|
Mocker.GetMock<IHttpClient>()
|
||||||
|
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
|
||||||
|
.Returns<HttpRequest>(r => new HttpResponse(r,new HttpHeader(), authStream.ToString()));
|
||||||
|
|
||||||
|
Mocker.GetMock<IHttpClient>()
|
||||||
|
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||||
|
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader {ContentType = HttpAccept.Json.Value}, responseJson));
|
||||||
|
|
||||||
|
var torrents = Subject.FetchRecent();
|
||||||
|
|
||||||
|
torrents.Should().HaveCount(293);
|
||||||
|
torrents.First().Should().BeOfType<PassThePopcornInfo>();
|
||||||
|
|
||||||
|
var first = torrents.First() as TorrentInfo;
|
||||||
|
|
||||||
|
first.Guid.Should().Be("PassThePopcorn-483521");
|
||||||
|
first.Title.Should().Be("The.Night.Of.S01.720p.HDTV.x264-BTN");
|
||||||
|
first.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||||
|
first.DownloadUrl.Should().Be("https://passthepopcorn.me/torrents.php?action=download&id=483521&authkey=00000000000000000000000000000000&torrent_pass=00000000000000000000000000000000");
|
||||||
|
first.InfoUrl.Should().Be("https://passthepopcorn.me/torrents.php?id=148131&torrentid=483521");
|
||||||
|
//first.PublishDate.Should().Be(DateTime.Parse("2017-04-17T12:13:42+0000").ToUniversalTime()); stupid timezones
|
||||||
|
first.Size.Should().Be(9370933376);
|
||||||
|
first.InfoHash.Should().BeNullOrEmpty();
|
||||||
|
first.MagnetUrl.Should().BeNullOrEmpty();
|
||||||
|
first.Peers.Should().Be(3);
|
||||||
|
first.Seeders.Should().Be(1);
|
||||||
|
|
||||||
|
torrents.Any(t => t.IndexerFlags.HasFlag(IndexerFlags.G_Freeleech)).Should().Be(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -296,7 +296,9 @@
|
|||||||
<Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" />
|
<Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" />
|
||||||
<Compile Include="OrganizerTests\FileNameBuilderTests\EpisodeTitleCollapseFixture.cs" />
|
<Compile Include="OrganizerTests\FileNameBuilderTests\EpisodeTitleCollapseFixture.cs" />
|
||||||
<Compile Include="OrganizerTests\FileNameBuilderTests\MultiEpisodeFixture.cs" />
|
<Compile Include="OrganizerTests\FileNameBuilderTests\MultiEpisodeFixture.cs" />
|
||||||
|
<Compile Include="OrganizerTests\GetMovieFolderFixture.cs" />
|
||||||
<Compile Include="ParserTests\MiniSeriesEpisodeParserFixture.cs" />
|
<Compile Include="ParserTests\MiniSeriesEpisodeParserFixture.cs" />
|
||||||
|
<Compile Include="ParserTests\RomanNumeralTests\RomanNumeralConversionFixture.cs" />
|
||||||
<Compile Include="Qualities\RevisionComparableFixture.cs" />
|
<Compile Include="Qualities\RevisionComparableFixture.cs" />
|
||||||
<Compile Include="QueueTests\QueueServiceFixture.cs" />
|
<Compile Include="QueueTests\QueueServiceFixture.cs" />
|
||||||
<Compile Include="RemotePathMappingsTests\RemotePathMappingServiceFixture.cs" />
|
<Compile Include="RemotePathMappingsTests\RemotePathMappingServiceFixture.cs" />
|
||||||
@@ -385,6 +387,13 @@
|
|||||||
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
|
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
|
||||||
<Compile Include="XbmcVersionTests.cs" />
|
<Compile Include="XbmcVersionTests.cs" />
|
||||||
<Compile Include="BulkImport\AddMultiMoviesFixture.cs" />
|
<Compile Include="BulkImport\AddMultiMoviesFixture.cs" />
|
||||||
|
<Content Include="Files\ArabicRomanNumeralDictionary.JSON">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Compile Include="IndexerTests\PTPTests\PTPFixture.cs" />
|
||||||
|
<None Include="Files\Indexers\PTP\imdbsearch.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
|
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
|
||||||
@@ -570,6 +579,8 @@
|
|||||||
<Folder Include="DataAugmentation\SceneNumbering\" />
|
<Folder Include="DataAugmentation\SceneNumbering\" />
|
||||||
<Folder Include="Providers\" />
|
<Folder Include="Providers\" />
|
||||||
<Folder Include="ProviderTests\UpdateProviderTests\" />
|
<Folder Include="ProviderTests\UpdateProviderTests\" />
|
||||||
|
<Folder Include="IndexerTests\PTPTests\" />
|
||||||
|
<Folder Include="Files\Indexers\PTP\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||||
|
|||||||
+3
-1
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
@@ -734,5 +734,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
|
|||||||
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
|
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
|
||||||
.Should().Be(releaseGroup);
|
.Should().Be(releaseGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Organizer;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using FluentAssertions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.OrganizerTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
|
||||||
|
public class GetMovieFolderFixture : CoreTest<FileNameBuilder>
|
||||||
|
{
|
||||||
|
private NamingConfig namingConfig;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
namingConfig = NamingConfig.Default;
|
||||||
|
|
||||||
|
Mocker.GetMock<INamingConfigService>()
|
||||||
|
.Setup(c => c.GetConfig()).Returns(namingConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Arrival", 2016, "{Movie Title} ({Release Year})", "Arrival (2016)")]
|
||||||
|
[TestCase("The Big Short", 2015, "{Movie TitleThe} ({Release Year})", "Big Short, The (2015)")]
|
||||||
|
[TestCase("The Big Short", 2015, "{Movie Title} ({Release Year})", "The Big Short (2015)")]
|
||||||
|
public void should_use_movieFolderFormat_to_build_folder_name(string movieTitle, int year, string format, string expected)
|
||||||
|
{
|
||||||
|
namingConfig.MovieFolderFormat = format;
|
||||||
|
|
||||||
|
var movie = new Movie { Title = movieTitle, Year = year };
|
||||||
|
|
||||||
|
Subject.GetMovieFolder(movie).Should().Be(expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
@@ -74,6 +74,8 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||||||
[TestCase("To.Live.and.Die.in.L.A.1985.1080p.BluRay", "To Live and Die in L.A.")]
|
[TestCase("To.Live.and.Die.in.L.A.1985.1080p.BluRay", "To Live and Die in L.A.")]
|
||||||
[TestCase("A.I.Artificial.Intelligence.(2001)", "A.I. Artificial Intelligence")]
|
[TestCase("A.I.Artificial.Intelligence.(2001)", "A.I. Artificial Intelligence")]
|
||||||
[TestCase("A.Movie.Name.(1998)", "A Movie Name")]
|
[TestCase("A.Movie.Name.(1998)", "A Movie Name")]
|
||||||
|
[TestCase("Thor: The Dark World 2013", "Thor The Dark World")]
|
||||||
|
[TestCase("Resident.Evil.The.Final.Chapter.2016", "Resident Evil The Final Chapter")]
|
||||||
public void should_parse_movie_title(string postTitle, string title)
|
public void should_parse_movie_title(string postTitle, string title)
|
||||||
{
|
{
|
||||||
Parser.Parser.ParseMovieTitle(postTitle).MovieTitle.Should().Be(title);
|
Parser.Parser.ParseMovieTitle(postTitle).MovieTitle.Should().Be(title);
|
||||||
@@ -86,9 +88,48 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("The Danish Girl 2015")]
|
[TestCase("The Danish Girl 2015")]
|
||||||
|
[TestCase("The.Danish.Girl.2015.1080p.BluRay.x264.DTS-HD.MA.5.1-RARBG")]
|
||||||
public void should_not_parse_language_in_movie_title(string postTitle)
|
public void should_not_parse_language_in_movie_title(string postTitle)
|
||||||
{
|
{
|
||||||
Parser.Parser.ParseMovieTitle(postTitle).Language.Should().Be(Language.English);
|
Parser.Parser.ParseMovieTitle(postTitle).Language.Should().Be(Language.English);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase("Prometheus 2012 Directors Cut", "Directors Cut")]
|
||||||
|
[TestCase("Star Wars Episode IV - A New Hope 1999 (Despecialized).mkv", "Despecialized")]
|
||||||
|
[TestCase("Prometheus.2012.(Special.Edition.Remastered).[Bluray-1080p].mkv", "Special Edition Remastered")]
|
||||||
|
[TestCase("Prometheus 2012 Extended", "Extended")]
|
||||||
|
[TestCase("Prometheus 2012 Extended Directors Cut Fan Edit", "Extended Directors Cut Fan Edit")]
|
||||||
|
[TestCase("Prometheus 2012 Director's Cut", "Director's Cut")]
|
||||||
|
[TestCase("Prometheus 2012 Directors Cut", "Directors Cut")]
|
||||||
|
[TestCase("Prometheus.2012.(Extended.Theatrical.Version.IMAX).BluRay.1080p.2012.asdf", "Extended Theatrical Version IMAX")]
|
||||||
|
[TestCase("2001 A Space Odyssey (1968) Director's Cut .mkv", "Director's Cut")]
|
||||||
|
[TestCase("2001: A Space Odyssey 1968 (Extended Directors Cut FanEdit)", "Extended Directors Cut FanEdit")]
|
||||||
|
[TestCase("A Fake Movie 2035 2012 Directors.mkv", "Directors")]
|
||||||
|
[TestCase("Blade Runner 2049 Director's Cut.mkv", "Director's Cut")]
|
||||||
|
[TestCase("Prometheus 2012 50th Anniversary Edition.mkv", "50th Anniversary Edition")]
|
||||||
|
[TestCase("Movie 2012 2in1.mkv", "2in1")]
|
||||||
|
[TestCase("Movie 2012 IMAX.mkv", "IMAX")]
|
||||||
|
[TestCase("Movie 2012 Restored.mkv", "Restored")]
|
||||||
|
[TestCase("Prometheus.Special.Edition.Fan Edit.2012..BRRip.x264.AAC-m2g", "Special Edition Fan Edit")]
|
||||||
|
[TestCase("Star Wars Episode IV - A New Hope (Despecialized) 1999.mkv", "Despecialized")]
|
||||||
|
[TestCase("Prometheus.(Special.Edition.Remastered).2012.[Bluray-1080p].mkv", "Special Edition Remastered")]
|
||||||
|
[TestCase("Prometheus Extended 2012", "Extended")]
|
||||||
|
[TestCase("Prometheus Extended Directors Cut Fan Edit 2012", "Extended Directors Cut Fan Edit")]
|
||||||
|
[TestCase("Prometheus Director's Cut 2012", "Director's Cut")]
|
||||||
|
[TestCase("Prometheus Directors Cut 2012", "Directors Cut")]
|
||||||
|
[TestCase("Prometheus.(Extended.Theatrical.Version.IMAX).BluRay.1080p.2012.asdf", "Extended Theatrical Version IMAX")]
|
||||||
|
[TestCase("2001 A Space Odyssey Director's Cut (1968).mkv", "Director's Cut")]
|
||||||
|
[TestCase("2001: A Space Odyssey (Extended Directors Cut FanEdit) Bluray 1080p 1968", "Extended Directors Cut FanEdit")]
|
||||||
|
[TestCase("A Fake Movie 2035 Directors 2012.mkv", "Directors")]
|
||||||
|
[TestCase("Blade Runner Director's Cut 2049.mkv", "Director's Cut")]
|
||||||
|
[TestCase("Prometheus 50th Anniversary Edition 2012.mkv", "50th Anniversary Edition")]
|
||||||
|
[TestCase("Movie 2in1 2012.mkv", "2in1")]
|
||||||
|
[TestCase("Movie IMAX 2012.mkv", "IMAX")]
|
||||||
|
[TestCase("Fake Movie Final Cut 2016", "Final Cut")]
|
||||||
|
[TestCase("Fake Movie 2016 Final Cut ", "Final Cut")]
|
||||||
|
public void should_parse_edition(string postTitle, string edition)
|
||||||
|
{
|
||||||
|
Parser.Parser.ParseMovieTitle(postTitle).Edition.Should().Be(edition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
private ParsedMovieInfo _wrongYearInfo;
|
private ParsedMovieInfo _wrongYearInfo;
|
||||||
private ParsedMovieInfo _romanTitleInfo;
|
private ParsedMovieInfo _romanTitleInfo;
|
||||||
private ParsedMovieInfo _alternativeTitleInfo;
|
private ParsedMovieInfo _alternativeTitleInfo;
|
||||||
|
private ParsedMovieInfo _umlautInfo;
|
||||||
|
private ParsedMovieInfo _umlautAltInfo;
|
||||||
private MovieSearchCriteria _movieSearchCriteria;
|
private MovieSearchCriteria _movieSearchCriteria;
|
||||||
private List<Episode> _episodes;
|
private List<Episode> _episodes;
|
||||||
private ParsedEpisodeInfo _parsedEpisodeInfo;
|
private ParsedEpisodeInfo _parsedEpisodeInfo;
|
||||||
@@ -37,10 +39,10 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_movie = Builder<Movie>.CreateNew()
|
_movie = Builder<Movie>.CreateNew()
|
||||||
.With(m => m.Title = "Mission Impossible 3")
|
.With(m => m.Title = "Fack Ju Göthe 2")
|
||||||
.With(m => m.CleanTitle = "missionimpossible3")
|
.With(m => m.CleanTitle = "fackjugoethe2")
|
||||||
.With(m => m.Year = 2006)
|
.With(m => m.Year = 2015)
|
||||||
.With(m => m.AlternativeTitles = new List<string> { "Mission Impossible 3: Same same" })
|
.With(m => m.AlternativeTitles = new List<string> { "Fack Ju Göthe 2: Same same" })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_episodes = Builder<Episode>.CreateListOfSize(1)
|
_episodes = Builder<Episode>.CreateListOfSize(1)
|
||||||
@@ -77,10 +79,22 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
|
|
||||||
_romanTitleInfo = new ParsedMovieInfo
|
_romanTitleInfo = new ParsedMovieInfo
|
||||||
{
|
{
|
||||||
MovieTitle = "Mission Impossible III",
|
MovieTitle = "Fack Ju Göthe II",
|
||||||
Year = _movie.Year,
|
Year = _movie.Year,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_umlautInfo = new ParsedMovieInfo
|
||||||
|
{
|
||||||
|
MovieTitle = "Fack Ju Goethe 2",
|
||||||
|
Year = _movie.Year
|
||||||
|
};
|
||||||
|
|
||||||
|
_umlautAltInfo = new ParsedMovieInfo
|
||||||
|
{
|
||||||
|
MovieTitle = "Fack Ju Goethe 2: Same same",
|
||||||
|
Year = _movie.Year
|
||||||
|
};
|
||||||
|
|
||||||
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
|
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
|
||||||
{
|
{
|
||||||
Series = _series,
|
Series = _series,
|
||||||
@@ -148,5 +162,12 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
|||||||
Subject.Map(_romanTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
|
Subject.Map(_romanTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_match_umlauts()
|
||||||
|
{
|
||||||
|
Subject.Map(_umlautInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
|
||||||
|
Subject.Map(_umlautAltInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Parser.RomanNumerals;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.ParserTests.RomanNumeralTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class RomanNumeralConversionFixture
|
||||||
|
{
|
||||||
|
private const string TEST_VALUES = @"Files/ArabicRomanNumeralDictionary.JSON";
|
||||||
|
|
||||||
|
|
||||||
|
private Dictionary<int, string> _arabicToRomanNumeralsMapping;
|
||||||
|
|
||||||
|
[OneTimeSetUp]
|
||||||
|
public void PopulateDictionaryWithProvenValues()
|
||||||
|
{
|
||||||
|
var pathToTestValues = Path.Combine(TestContext.CurrentContext.TestDirectory, Path.Combine(TEST_VALUES.Split('/')));
|
||||||
|
_arabicToRomanNumeralsMapping =
|
||||||
|
JsonConvert.DeserializeObject<Dictionary<int, string>>(File.ReadAllText(pathToTestValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test(Description = "Converts the supported range [1-3999] of Arabic to Roman numerals.")]
|
||||||
|
[Order(0)]
|
||||||
|
public void should_convert_arabic_numeral_to_roman_numeral([Range(1,3999)] int arabicNumeral)
|
||||||
|
{
|
||||||
|
RomanNumeral romanNumeral = new RomanNumeral(arabicNumeral);
|
||||||
|
|
||||||
|
string expectedValue = _arabicToRomanNumeralsMapping[arabicNumeral];
|
||||||
|
|
||||||
|
Assert.AreEqual(romanNumeral.ToRomanNumeral(), expectedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[Order(1)]
|
||||||
|
public void should_convert_roman_numeral_to_arabic_numeral([Range(1, 3999)] int arabicNumeral)
|
||||||
|
{
|
||||||
|
RomanNumeral romanNumeral = new RomanNumeral(_arabicToRomanNumeralsMapping[arabicNumeral]);
|
||||||
|
|
||||||
|
int expectecdValue = arabicNumeral;
|
||||||
|
|
||||||
|
Assert.AreEqual(romanNumeral.ToInt(), expectecdValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -105,11 +105,11 @@ namespace NzbDrone.Core.Configuration
|
|||||||
set { SetValue("RssSyncInterval", value); }
|
set { SetValue("RssSyncInterval", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int AvailabilityDelay
|
public int AvailabilityDelay
|
||||||
{
|
{
|
||||||
get { return GetValueInt("AvailabilityDelay",0); }
|
get { return GetValueInt("AvailabilityDelay",0); }
|
||||||
set { SetValue("AvailabilityDelay", value); }
|
set { SetValue("AvailabilityDelay", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int NetImportSyncInterval
|
public int NetImportSyncInterval
|
||||||
{
|
{
|
||||||
@@ -190,6 +190,27 @@ namespace NzbDrone.Core.Configuration
|
|||||||
set { SetValue("EnableCompletedDownloadHandling", value); }
|
set { SetValue("EnableCompletedDownloadHandling", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool PreferIndexerFlags
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("PreferIndexerFlags", false); }
|
||||||
|
|
||||||
|
set {SetValue("PreferIndexerFlags", value);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AllowHardcodedSubs
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("AllowHardcodedSubs", false); }
|
||||||
|
|
||||||
|
set { SetValue("AllowHardcodedSubs", value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string WhitelistedHardcodedSubs
|
||||||
|
{
|
||||||
|
get { return GetValue("WhitelistedHardcodedSubs", ""); }
|
||||||
|
|
||||||
|
set { SetValue("WhitelistedHardcodedSubs", value); }
|
||||||
|
}
|
||||||
|
|
||||||
public bool RemoveCompletedDownloads
|
public bool RemoveCompletedDownloads
|
||||||
{
|
{
|
||||||
get { return GetValueBoolean("RemoveCompletedDownloads", false); }
|
get { return GetValueBoolean("RemoveCompletedDownloads", false); }
|
||||||
@@ -273,6 +294,20 @@ namespace NzbDrone.Core.Configuration
|
|||||||
set { SetValue("ExtraFileExtensions", value); }
|
set { SetValue("ExtraFileExtensions", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool AutoRenameFolders
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("AutoRenameFolders", false); }
|
||||||
|
|
||||||
|
set { SetValue("AutoRenameFolders", value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool PathsDefaultStatic
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("PathsDefaultStatic", true); }
|
||||||
|
|
||||||
|
set { SetValue("PathsDefaultStatic", value); }
|
||||||
|
}
|
||||||
|
|
||||||
public bool SetPermissionsLinux
|
public bool SetPermissionsLinux
|
||||||
{
|
{
|
||||||
get { return GetValueBoolean("SetPermissionsLinux", false); }
|
get { return GetValueBoolean("SetPermissionsLinux", false); }
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ namespace NzbDrone.Core.Configuration
|
|||||||
bool CopyUsingHardlinks { get; set; }
|
bool CopyUsingHardlinks { get; set; }
|
||||||
bool EnableMediaInfo { get; set; }
|
bool EnableMediaInfo { get; set; }
|
||||||
string ExtraFileExtensions { get; set; }
|
string ExtraFileExtensions { get; set; }
|
||||||
|
bool AutoRenameFolders { get; set; }
|
||||||
|
bool PathsDefaultStatic { get; set; }
|
||||||
|
|
||||||
//Permissions (Media Management)
|
//Permissions (Media Management)
|
||||||
bool SetPermissionsLinux { get; set; }
|
bool SetPermissionsLinux { get; set; }
|
||||||
@@ -46,17 +48,22 @@ namespace NzbDrone.Core.Configuration
|
|||||||
int RssSyncInterval { get; set; }
|
int RssSyncInterval { get; set; }
|
||||||
int MinimumAge { get; set; }
|
int MinimumAge { get; set; }
|
||||||
|
|
||||||
int AvailabilityDelay { get; set; }
|
bool PreferIndexerFlags { get; set; }
|
||||||
|
|
||||||
|
int AvailabilityDelay { get; set; }
|
||||||
|
|
||||||
|
bool AllowHardcodedSubs { get; set; }
|
||||||
|
string WhitelistedHardcodedSubs { get; set; }
|
||||||
|
|
||||||
int NetImportSyncInterval { get; set; }
|
int NetImportSyncInterval { get; set; }
|
||||||
string ListSyncLevel { get; set; }
|
string ListSyncLevel { get; set; }
|
||||||
string ImportExclusions { get; set; }
|
string ImportExclusions { get; set; }
|
||||||
string TraktAuthToken { get; set; }
|
string TraktAuthToken { get; set; }
|
||||||
string TraktRefreshToken { get; set; }
|
string TraktRefreshToken { get; set; }
|
||||||
int TraktTokenExpiry { get; set; }
|
int TraktTokenExpiry { get; set; }
|
||||||
string NewTraktAuthToken { get; set; }
|
string NewTraktAuthToken { get; set; }
|
||||||
string NewTraktRefreshToken {get; set; }
|
string NewTraktRefreshToken {get; set; }
|
||||||
int NewTraktTokenExpiry { get; set; }
|
int NewTraktTokenExpiry { get; set; }
|
||||||
|
|
||||||
//UI
|
//UI
|
||||||
int FirstDayOfWeek { get; set; }
|
int FirstDayOfWeek { get; set; }
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Data;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(136)]
|
||||||
|
public class add_pathstate_to_movies : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("Movies").AddColumn("PathState").AsInt32().WithDefaultValue(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Data;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Globalization;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(137)]
|
||||||
|
public class add_import_exclusions_table : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
if (!this.Schema.Schema("dbo").Table("ImportExclusions").Exists())
|
||||||
|
{
|
||||||
|
Create.TableForModel("ImportExclusions")
|
||||||
|
.WithColumn("TmdbId").AsInt64().NotNullable().Unique().PrimaryKey()
|
||||||
|
.WithColumn("MovieTitle").AsString().Nullable()
|
||||||
|
.WithColumn("MovieYear").AsInt64().Nullable().WithDefault(0);
|
||||||
|
}
|
||||||
|
Execute.WithConnection(AddExisting);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddExisting(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
getSeriesCmd.Transaction = tran;
|
||||||
|
getSeriesCmd.CommandText = @"SELECT Key, Value FROM Config WHERE Key = 'importexclusions'";
|
||||||
|
TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
|
||||||
|
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (seriesReader.Read())
|
||||||
|
{
|
||||||
|
var Key = seriesReader.GetString(0);
|
||||||
|
var Value = seriesReader.GetString(1);
|
||||||
|
|
||||||
|
var importExclusions = Value.Split(',').Select(x => {
|
||||||
|
return string.Format("(\"{0}\", \"{1}\")", Regex.Replace(x, @"^.*\-(.*)$", "$1"),
|
||||||
|
textInfo.ToTitleCase(string.Join(" ", x.Split('-').DropLast(1))));
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateCmd.Transaction = tran;
|
||||||
|
updateCmd.CommandText = "INSERT INTO ImportExclusions (tmdbid, MovieTitle) VALUES " + string.Join(", ", importExclusions);
|
||||||
|
|
||||||
|
updateCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ using NzbDrone.Core.Extras.Others;
|
|||||||
using NzbDrone.Core.Extras.Subtitles;
|
using NzbDrone.Core.Extras.Subtitles;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
using NzbDrone.Core.NetImport;
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Core.NetImport.ImportExclusions;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Datastore
|
namespace NzbDrone.Core.Datastore
|
||||||
{
|
{
|
||||||
@@ -105,6 +106,8 @@ namespace NzbDrone.Core.Datastore
|
|||||||
.Relationship()
|
.Relationship()
|
||||||
.HasOne(s => s.Profile, s => s.ProfileId)
|
.HasOne(s => s.Profile, s => s.ProfileId)
|
||||||
.HasOne(m => m.MovieFile, m => m.MovieFileId);
|
.HasOne(m => m.MovieFile, m => m.MovieFileId);
|
||||||
|
|
||||||
|
Mapper.Entity<ImportExclusion>().RegisterModel("ImportExclusions");
|
||||||
|
|
||||||
|
|
||||||
Mapper.Entity<Episode>().RegisterModel("Episodes")
|
Mapper.Entity<Episode>().RegisterModel("Episodes")
|
||||||
@@ -159,6 +162,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
MapRepository.Instance.RegisterTypeConverter(typeof(List<int>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(List<int>), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(List<string>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(List<string>), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(ParsedEpisodeInfo), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(ParsedEpisodeInfo), new EmbeddedDocumentConverter());
|
||||||
|
MapRepository.Instance.RegisterTypeConverter(typeof(ParsedMovieInfo), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(ReleaseInfo), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(ReleaseInfo), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(HashSet<int>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(HashSet<int>), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(OsPath), new OsPathConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(OsPath), new OsPathConverter());
|
||||||
|
|||||||
@@ -4,18 +4,21 @@ using System.Linq;
|
|||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles.Delay;
|
using NzbDrone.Core.Profiles.Delay;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
public class DownloadDecisionComparer : IComparer<DownloadDecision>
|
public class DownloadDecisionComparer : IComparer<DownloadDecision>
|
||||||
{
|
{
|
||||||
private readonly IDelayProfileService _delayProfileService;
|
private readonly IDelayProfileService _delayProfileService;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y);
|
public delegate int CompareDelegate(DownloadDecision x, DownloadDecision y);
|
||||||
public delegate int CompareDelegate<TSubject, TValue>(DownloadDecision x, DownloadDecision y);
|
public delegate int CompareDelegate<TSubject, TValue>(DownloadDecision x, DownloadDecision y);
|
||||||
|
|
||||||
public DownloadDecisionComparer(IDelayProfileService delayProfileService)
|
public DownloadDecisionComparer(IDelayProfileService delayProfileService, IConfigService configService)
|
||||||
{
|
{
|
||||||
_delayProfileService = delayProfileService;
|
_delayProfileService = delayProfileService;
|
||||||
|
_configService = configService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Compare(DownloadDecision x, DownloadDecision y)
|
public int Compare(DownloadDecision x, DownloadDecision y)
|
||||||
@@ -24,6 +27,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
{
|
{
|
||||||
CompareQuality,
|
CompareQuality,
|
||||||
ComparePreferredWords,
|
ComparePreferredWords,
|
||||||
|
CompareIndexerFlags,
|
||||||
CompareProtocol,
|
CompareProtocol,
|
||||||
ComparePeersIfTorrent,
|
ComparePeersIfTorrent,
|
||||||
CompareAgeIfUsenet,
|
CompareAgeIfUsenet,
|
||||||
@@ -84,7 +88,22 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
return num;
|
return num;
|
||||||
|
|
||||||
});
|
});
|
||||||
; }
|
}
|
||||||
|
|
||||||
|
private int CompareIndexerFlags(DownloadDecision x, DownloadDecision y)
|
||||||
|
{
|
||||||
|
var releaseX = x.RemoteMovie.Release;
|
||||||
|
var releaseY = y.RemoteMovie.Release;
|
||||||
|
|
||||||
|
if (_configService.PreferIndexerFlags)
|
||||||
|
{
|
||||||
|
return CompareBy(x.RemoteMovie.Release, y.RemoteMovie.Release, release => ScoreFlags(release.IndexerFlags));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
|
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
|
||||||
{
|
{
|
||||||
@@ -185,5 +204,34 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
|
|
||||||
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes()));
|
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int ScoreFlags(IndexerFlags flags)
|
||||||
|
{
|
||||||
|
var flagValues = Enum.GetValues(typeof(IndexerFlags));
|
||||||
|
|
||||||
|
var score = 0;
|
||||||
|
|
||||||
|
foreach (IndexerFlags value in flagValues)
|
||||||
|
{
|
||||||
|
if ((flags & value) == value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case IndexerFlags.G_DoubleUpload:
|
||||||
|
case IndexerFlags.G_Freeleech:
|
||||||
|
case IndexerFlags.PTP_Approved:
|
||||||
|
case IndexerFlags.PTP_Golden:
|
||||||
|
case IndexerFlags.HDB_Internal:
|
||||||
|
score += 2;
|
||||||
|
break;
|
||||||
|
case IndexerFlags.G_Halfleech:
|
||||||
|
score += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Instrumentation.Extensions;
|
using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
@@ -21,12 +22,14 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
{
|
{
|
||||||
private readonly IEnumerable<IDecisionEngineSpecification> _specifications;
|
private readonly IEnumerable<IDecisionEngineSpecification> _specifications;
|
||||||
private readonly IParsingService _parsingService;
|
private readonly IParsingService _parsingService;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public DownloadDecisionMaker(IEnumerable<IDecisionEngineSpecification> specifications, IParsingService parsingService, Logger logger)
|
public DownloadDecisionMaker(IEnumerable<IDecisionEngineSpecification> specifications, IParsingService parsingService, IConfigService configService, Logger logger)
|
||||||
{
|
{
|
||||||
_specifications = specifications;
|
_specifications = specifications;
|
||||||
_parsingService = parsingService;
|
_parsingService = parsingService;
|
||||||
|
_configService = configService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,30 +71,50 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
{
|
{
|
||||||
var parsedMovieInfo = Parser.Parser.ParseMovieTitle(report.Title);
|
var parsedMovieInfo = Parser.Parser.ParseMovieTitle(report.Title);
|
||||||
|
|
||||||
if (parsedMovieInfo != null && !parsedMovieInfo.MovieTitle.IsNullOrWhiteSpace())
|
if (parsedMovieInfo != null && !parsedMovieInfo.MovieTitle.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
RemoteMovie remoteMovie = _parsingService.Map(parsedMovieInfo, report.ImdbId.ToString(), searchCriteria);
|
RemoteMovie remoteMovie = _parsingService.Map(parsedMovieInfo, report.ImdbId.ToString(), searchCriteria);
|
||||||
remoteMovie.Release = report;
|
remoteMovie.Release = report;
|
||||||
|
|
||||||
if (remoteMovie.Movie == null)
|
if (remoteMovie.Movie == null)
|
||||||
{
|
{
|
||||||
decision = new DownloadDecision(remoteMovie, new Rejection("Unknown movie. Cannot parse release name."));
|
decision = new DownloadDecision(remoteMovie, new Rejection("Unknown movie. Movie found does not match wanted movie."));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (parsedMovieInfo.Quality.HardcodedSubs.IsNotNullOrWhiteSpace())
|
if (parsedMovieInfo.Quality.HardcodedSubs.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
remoteMovie.DownloadAllowed = true;
|
remoteMovie.DownloadAllowed = true;
|
||||||
decision = new DownloadDecision(remoteMovie, new Rejection("Hardcoded subs found: " + parsedMovieInfo.Quality.HardcodedSubs));
|
if (_configService.AllowHardcodedSubs)
|
||||||
}
|
{
|
||||||
else
|
decision = GetDecisionForReport(remoteMovie, searchCriteria);
|
||||||
{
|
}
|
||||||
remoteMovie.DownloadAllowed = true;
|
else
|
||||||
decision = GetDecisionForReport(remoteMovie, searchCriteria);
|
{
|
||||||
}
|
var whitelisted = _configService.WhitelistedHardcodedSubs.Split(',');
|
||||||
|
_logger.Debug("Testing: {0}", whitelisted);
|
||||||
}
|
if (whitelisted != null && whitelisted.Any(t => (parsedMovieInfo.Quality.HardcodedSubs.ToLower().Contains(t.ToLower()) && t.IsNotNullOrWhiteSpace())))
|
||||||
}
|
{
|
||||||
|
decision = GetDecisionForReport(remoteMovie, searchCriteria);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decision = new DownloadDecision(remoteMovie, new Rejection("Hardcoded subs found: " + parsedMovieInfo.Quality.HardcodedSubs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remoteMovie.DownloadAllowed = true;
|
||||||
|
decision = GetDecisionForReport(remoteMovie, searchCriteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Trace("{0} could not be parsed :(.", report.Title);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Profiles.Delay;
|
using NzbDrone.Core.Profiles.Delay;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
@@ -13,10 +14,12 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision
|
public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision
|
||||||
{
|
{
|
||||||
private readonly IDelayProfileService _delayProfileService;
|
private readonly IDelayProfileService _delayProfileService;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
|
||||||
public DownloadDecisionPriorizationService(IDelayProfileService delayProfileService)
|
public DownloadDecisionPriorizationService(IDelayProfileService delayProfileService, IConfigService configService)
|
||||||
{
|
{
|
||||||
_delayProfileService = delayProfileService;
|
_delayProfileService = delayProfileService;
|
||||||
|
_configService = configService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
|
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
|
||||||
@@ -24,7 +27,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
return decisions.Where(c => c.RemoteEpisode.Series != null)
|
return decisions.Where(c => c.RemoteEpisode.Series != null)
|
||||||
.GroupBy(c => c.RemoteEpisode.Series.Id, (seriesId, downloadDecisions) =>
|
.GroupBy(c => c.RemoteEpisode.Series.Id, (seriesId, downloadDecisions) =>
|
||||||
{
|
{
|
||||||
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
|
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService, _configService));
|
||||||
})
|
})
|
||||||
.SelectMany(c => c)
|
.SelectMany(c => c)
|
||||||
.Union(decisions.Where(c => c.RemoteEpisode.Series == null))
|
.Union(decisions.Where(c => c.RemoteEpisode.Series == null))
|
||||||
@@ -36,7 +39,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
return decisions.Where(c => c.RemoteMovie.Movie != null)
|
return decisions.Where(c => c.RemoteMovie.Movie != null)
|
||||||
.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) =>
|
.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) =>
|
||||||
{
|
{
|
||||||
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
|
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService, _configService));
|
||||||
})
|
})
|
||||||
.SelectMany(c => c)
|
.SelectMany(c => c)
|
||||||
.Union(decisions.Where(c => c.RemoteMovie.Movie == null))
|
.Union(decisions.Where(c => c.RemoteMovie.Movie == null))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
@@ -121,6 +121,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
}
|
}
|
||||||
|
|
||||||
var qualityDefinition = _qualityDefinitionService.Get(quality);
|
var qualityDefinition = _qualityDefinitionService.Get(quality);
|
||||||
|
if (subject.Movie.Runtime == 0)
|
||||||
|
{
|
||||||
|
_logger.Info("{0} has no runtime information using median movie runtime of 110 minutes.", subject.Movie);
|
||||||
|
subject.Movie.Runtime = 110;
|
||||||
|
}
|
||||||
if (qualityDefinition.MinSize.HasValue)
|
if (qualityDefinition.MinSize.HasValue)
|
||||||
{
|
{
|
||||||
var minSize = qualityDefinition.MinSize.Value.Megabytes();
|
var minSize = qualityDefinition.MinSize.Value.Megabytes();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Download.Pending;
|
using NzbDrone.Core.Download.Pending;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
namespace NzbDrone.Core.Download.Clients.DownloadStation
|
namespace NzbDrone.Core.Download.Clients.DownloadStation
|
||||||
{
|
{
|
||||||
public class DiskStationApiInfo
|
public class DiskStationApiInfo
|
||||||
{
|
{
|
||||||
private string _path;
|
private string _path;
|
||||||
|
|
||||||
public int MaxVersion { get; set; }
|
public int MaxVersion { get; set; }
|
||||||
|
|
||||||
public int MinVersion { get; set; }
|
public int MinVersion { get; set; }
|
||||||
|
|
||||||
|
public DiskStationApi Type { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public bool NeedsAuthentication { get; set; }
|
||||||
|
|
||||||
public string Path
|
public string Path
|
||||||
{
|
{
|
||||||
get { return _path; }
|
get { return _path; }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||||
|
|
||||||
@@ -13,20 +14,19 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
|||||||
|
|
||||||
public class DSMInfoProxy : DiskStationProxyBase, IDSMInfoProxy
|
public class DSMInfoProxy : DiskStationProxyBase, IDSMInfoProxy
|
||||||
{
|
{
|
||||||
public DSMInfoProxy(IHttpClient httpClient, Logger logger) :
|
public DSMInfoProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger) :
|
||||||
base(httpClient, logger)
|
base(DiskStationApi.DSMInfo, "SYNO.DSM.Info", httpClient, cacheManager, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetSerialNumber(DownloadStationSettings settings)
|
public string GetSerialNumber(DownloadStationSettings settings)
|
||||||
{
|
{
|
||||||
var arguments = new Dictionary<string, object>() {
|
var info = GetApiInfo(settings);
|
||||||
{ "api", "SYNO.DSM.Info" },
|
|
||||||
{ "version", "2" },
|
var requestBuilder = BuildRequest(settings, "getinfo", info.MinVersion);
|
||||||
{ "method", "getinfo" }
|
|
||||||
};
|
var response = ProcessRequest<DSMInfoResponse>(requestBuilder, "get serial number", settings);
|
||||||
|
|
||||||
var response = ProcessRequest<DSMInfoResponse>(DiskStationApi.DSMInfo, arguments, settings, "get serial number");
|
|
||||||
return response.Data.SerialNumber;
|
return response.Data.SerialNumber;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+141
-127
@@ -1,63 +1,77 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||||
{
|
{
|
||||||
public abstract class DiskStationProxyBase
|
public interface IDiskStationProxy
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<DiskStationApi, string> Resources;
|
DiskStationApiInfo GetApiInfo(DownloadStationSettings settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class DiskStationProxyBase : IDiskStationProxy
|
||||||
|
{
|
||||||
|
protected readonly Logger _logger;
|
||||||
|
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
protected readonly Logger _logger;
|
private readonly ICached<DiskStationApiInfo> _infoCache;
|
||||||
private bool _authenticated;
|
private readonly ICached<string> _sessionCache;
|
||||||
|
private readonly DiskStationApi _apiType;
|
||||||
|
private readonly string _apiName;
|
||||||
|
|
||||||
|
private static readonly DiskStationApiInfo _apiInfo;
|
||||||
|
|
||||||
static DiskStationProxyBase()
|
static DiskStationProxyBase()
|
||||||
{
|
{
|
||||||
Resources = new Dictionary<DiskStationApi, string>
|
_apiInfo = new DiskStationApiInfo()
|
||||||
{
|
{
|
||||||
{ DiskStationApi.Info, "query.cgi" }
|
Type = DiskStationApi.Info,
|
||||||
|
Name = "SYNO.API.Info",
|
||||||
|
Path = "query.cgi",
|
||||||
|
MaxVersion = 1,
|
||||||
|
MinVersion = 1,
|
||||||
|
NeedsAuthentication = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiskStationProxyBase(IHttpClient httpClient, Logger logger)
|
public DiskStationProxyBase(DiskStationApi apiType,
|
||||||
|
string apiName,
|
||||||
|
IHttpClient httpClient,
|
||||||
|
ICacheManager cacheManager,
|
||||||
|
Logger logger)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_infoCache = cacheManager.GetCache<DiskStationApiInfo>(typeof(DiskStationProxyBase), "apiInfo");
|
||||||
|
_sessionCache = cacheManager.GetCache<string>(typeof(DiskStationProxyBase), "sessions");
|
||||||
|
_apiType = apiType;
|
||||||
|
_apiName = apiName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateSessionCacheKey(DownloadStationSettings settings)
|
||||||
protected DiskStationResponse<object> ProcessRequest(DiskStationApi api,
|
|
||||||
Dictionary<string, object> arguments,
|
|
||||||
DownloadStationSettings settings,
|
|
||||||
string operation,
|
|
||||||
HttpMethod method = HttpMethod.GET)
|
|
||||||
{
|
{
|
||||||
return ProcessRequest<object>(api, arguments, settings, operation, method);
|
return $"{settings.Username}@{settings.Host}:{settings.Port}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DiskStationResponse<T> ProcessRequest<T>(DiskStationApi api,
|
protected DiskStationResponse<T> ProcessRequest<T>(HttpRequestBuilder requestBuilder,
|
||||||
Dictionary<string, object> arguments,
|
string operation,
|
||||||
DownloadStationSettings settings,
|
DownloadStationSettings settings) where T : new()
|
||||||
string operation,
|
|
||||||
HttpMethod method = HttpMethod.GET,
|
|
||||||
int retries = 0) where T : new()
|
|
||||||
{
|
{
|
||||||
if (retries == 5)
|
return ProcessRequest<T>(requestBuilder, operation, _apiType, settings);
|
||||||
{
|
}
|
||||||
throw new DownloadClientException("Try to process request to {0} with {1} more than 5 times", api, arguments.ToJson().ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_authenticated && api != DiskStationApi.Info && api != DiskStationApi.DSMInfo)
|
private DiskStationResponse<T> ProcessRequest<T>(HttpRequestBuilder requestBuilder,
|
||||||
{
|
string operation,
|
||||||
AuthenticateClient(settings);
|
DiskStationApi api,
|
||||||
}
|
DownloadStationSettings settings) where T : new()
|
||||||
|
{
|
||||||
var request = BuildRequest(settings, api, arguments, method);
|
var request = requestBuilder.Build();
|
||||||
var response = _httpClient.Execute(request);
|
var response = _httpClient.Execute(request);
|
||||||
|
|
||||||
_logger.Debug("Trying to {0}", operation);
|
_logger.Debug("Trying to {0}", operation);
|
||||||
@@ -77,16 +91,14 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
|||||||
|
|
||||||
if (responseContent.Error.SessionError)
|
if (responseContent.Error.SessionError)
|
||||||
{
|
{
|
||||||
_authenticated = false;
|
_sessionCache.Remove(GenerateSessionCacheKey(settings));
|
||||||
|
|
||||||
if (responseContent.Error.Code == 105)
|
if (responseContent.Error.Code == 105)
|
||||||
{
|
{
|
||||||
throw new DownloadClientAuthenticationException(msg);
|
throw new DownloadClientAuthenticationException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ProcessRequest<T>(api, arguments, settings, operation, method, ++retries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new DownloadClientException(msg);
|
throw new DownloadClientException(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,124 +108,126 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AuthenticateClient(DownloadStationSettings settings)
|
private string AuthenticateClient(DownloadStationSettings settings)
|
||||||
{
|
{
|
||||||
var arguments = new Dictionary<string, object>
|
var authInfo = GetApiInfo(DiskStationApi.Auth, settings);
|
||||||
{
|
|
||||||
{ "api", "SYNO.API.Auth" },
|
|
||||||
{ "version", "1" },
|
|
||||||
{ "method", "login" },
|
|
||||||
{ "account", settings.Username },
|
|
||||||
{ "passwd", settings.Password },
|
|
||||||
{ "format", "cookie" },
|
|
||||||
{ "session", "DownloadStation" },
|
|
||||||
};
|
|
||||||
|
|
||||||
var authLoginRequest = BuildRequest(settings, DiskStationApi.Auth, arguments, HttpMethod.GET);
|
var requestBuilder = BuildRequest(settings, authInfo, "login", 2);
|
||||||
authLoginRequest.StoreResponseCookie = true;
|
requestBuilder.AddQueryParam("account", settings.Username);
|
||||||
|
requestBuilder.AddQueryParam("passwd", settings.Password);
|
||||||
|
requestBuilder.AddQueryParam("format", "sid");
|
||||||
|
requestBuilder.AddQueryParam("session", "DownloadStation");
|
||||||
|
|
||||||
var response = _httpClient.Execute(authLoginRequest);
|
var authResponse = ProcessRequest<DiskStationAuthResponse>(requestBuilder, "login", DiskStationApi.Auth, settings);
|
||||||
|
|
||||||
var downloadStationResponse = Json.Deserialize<DiskStationResponse<DiskStationAuthResponse>>(response.Content);
|
return authResponse.Data.SId;
|
||||||
|
|
||||||
var authResponse = Json.Deserialize<DiskStationResponse<DiskStationAuthResponse>>(response.Content);
|
|
||||||
|
|
||||||
_authenticated = authResponse.Success;
|
|
||||||
|
|
||||||
if (!_authenticated)
|
|
||||||
{
|
|
||||||
throw new DownloadClientAuthenticationException(downloadStationResponse.Error.GetMessage(DiskStationApi.Auth));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequest BuildRequest(DownloadStationSettings settings, DiskStationApi api, Dictionary<string, object> arguments, HttpMethod method)
|
protected HttpRequestBuilder BuildRequest(DownloadStationSettings settings, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
|
||||||
{
|
{
|
||||||
if (!Resources.ContainsKey(api))
|
var info = GetApiInfo(_apiType, settings);
|
||||||
{
|
|
||||||
GetApiVersion(settings, api);
|
|
||||||
}
|
|
||||||
|
|
||||||
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{Resources[api]}");
|
return BuildRequest(settings, info, methodName, apiVersion, httpVerb);
|
||||||
requestBuilder.Method = method;
|
}
|
||||||
|
|
||||||
|
private HttpRequestBuilder BuildRequest(DownloadStationSettings settings, DiskStationApiInfo apiInfo, string methodName, int apiVersion, HttpMethod httpVerb = HttpMethod.GET)
|
||||||
|
{
|
||||||
|
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port).Resource($"webapi/{apiInfo.Path}");
|
||||||
|
requestBuilder.Method = httpVerb;
|
||||||
requestBuilder.LogResponseContent = true;
|
requestBuilder.LogResponseContent = true;
|
||||||
requestBuilder.SuppressHttpError = true;
|
requestBuilder.SuppressHttpError = true;
|
||||||
requestBuilder.AllowAutoRedirect = false;
|
requestBuilder.AllowAutoRedirect = false;
|
||||||
|
requestBuilder.Headers.ContentType = "application/json";
|
||||||
|
|
||||||
if (requestBuilder.Method == HttpMethod.POST)
|
if (apiVersion < apiInfo.MinVersion || apiVersion > apiInfo.MaxVersion)
|
||||||
{
|
{
|
||||||
if (api == DiskStationApi.DownloadStationTask && arguments.ContainsKey("file"))
|
throw new ArgumentOutOfRangeException(nameof(apiVersion));
|
||||||
{
|
}
|
||||||
requestBuilder.Headers.ContentType = "multipart/form-data";
|
|
||||||
|
|
||||||
foreach (var arg in arguments)
|
if (httpVerb == HttpMethod.POST)
|
||||||
{
|
{
|
||||||
if (arg.Key == "file")
|
if (apiInfo.NeedsAuthentication)
|
||||||
{
|
|
||||||
Dictionary<string, object> file = (Dictionary<string, object>)arg.Value;
|
|
||||||
requestBuilder.AddFormUpload(arg.Key, file["name"].ToString(), (byte[])file["data"]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
requestBuilder.AddFormParameter(arg.Key, arg.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
requestBuilder.Headers.ContentType = "application/json";
|
requestBuilder.AddFormParameter("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestBuilder.AddFormParameter("api", apiInfo.Name);
|
||||||
|
requestBuilder.AddFormParameter("version", apiVersion);
|
||||||
|
requestBuilder.AddFormParameter("method", methodName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var arg in arguments)
|
if (apiInfo.NeedsAuthentication)
|
||||||
{
|
{
|
||||||
requestBuilder.AddQueryParam(arg.Key, arg.Value);
|
requestBuilder.AddQueryParam("_sid", _sessionCache.Get(GenerateSessionCacheKey(settings), () => AuthenticateClient(settings), TimeSpan.FromHours(6)));
|
||||||
|
}
|
||||||
|
|
||||||
|
requestBuilder.AddQueryParam("api", apiInfo.Name);
|
||||||
|
requestBuilder.AddQueryParam("version", apiVersion);
|
||||||
|
requestBuilder.AddQueryParam("method", methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateInfoCacheKey(DownloadStationSettings settings, DiskStationApi api)
|
||||||
|
{
|
||||||
|
return $"{settings.Host}:{settings.Port}->{api}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateApiInfo(DownloadStationSettings settings)
|
||||||
|
{
|
||||||
|
var apis = new Dictionary<string, DiskStationApi>()
|
||||||
|
{
|
||||||
|
{ "SYNO.API.Auth", DiskStationApi.Auth },
|
||||||
|
{ _apiName, _apiType }
|
||||||
|
};
|
||||||
|
|
||||||
|
var requestBuilder = BuildRequest(settings, _apiInfo, "query", _apiInfo.MinVersion);
|
||||||
|
requestBuilder.AddQueryParam("query", string.Join(",", apis.Keys));
|
||||||
|
|
||||||
|
var infoResponse = ProcessRequest<DiskStationApiInfoResponse>(requestBuilder, "get api info", _apiInfo.Type, settings);
|
||||||
|
|
||||||
|
foreach (var data in infoResponse.Data)
|
||||||
|
{
|
||||||
|
if (apis.ContainsKey(data.Key))
|
||||||
|
{
|
||||||
|
data.Value.Name = data.Key;
|
||||||
|
data.Value.Type = apis[data.Key];
|
||||||
|
data.Value.NeedsAuthentication = apis[data.Key] != DiskStationApi.Auth;
|
||||||
|
|
||||||
|
_infoCache.Set(GenerateInfoCacheKey(settings, apis[data.Key]), data.Value, TimeSpan.FromHours(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DiskStationApiInfo GetApiInfo(DiskStationApi api, DownloadStationSettings settings)
|
||||||
|
{
|
||||||
|
if (api == DiskStationApi.Info)
|
||||||
|
{
|
||||||
|
return _apiInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
var key = GenerateInfoCacheKey(settings, api);
|
||||||
|
var info = _infoCache.Find(key);
|
||||||
|
|
||||||
|
if (info == null)
|
||||||
|
{
|
||||||
|
UpdateApiInfo(settings);
|
||||||
|
info = _infoCache.Find(key);
|
||||||
|
|
||||||
|
if (info == null)
|
||||||
|
{
|
||||||
|
throw new DownloadClientException("Info of {0} not found on {1}:{2}", api, settings.Host, settings.Port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return requestBuilder.Build();
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<int> GetApiVersion(DownloadStationSettings settings, DiskStationApi api)
|
public DiskStationApiInfo GetApiInfo(DownloadStationSettings settings)
|
||||||
{
|
{
|
||||||
var arguments = new Dictionary<string, object>
|
return GetApiInfo(_apiType, settings);
|
||||||
{
|
|
||||||
{ "api", "SYNO.API.Info" },
|
|
||||||
{ "version", "1" },
|
|
||||||
{ "method", "query" },
|
|
||||||
{ "query", "SYNO.API.Auth, SYNO.DownloadStation.Info, SYNO.DownloadStation.Task, SYNO.FileStation.List, SYNO.DSM.Info" },
|
|
||||||
};
|
|
||||||
|
|
||||||
var infoResponse = ProcessRequest<DiskStationApiInfoResponse>(DiskStationApi.Info, arguments, settings, "Get api version");
|
|
||||||
|
|
||||||
//TODO: Refactor this into more elegant code
|
|
||||||
var infoResponeDSAuth = infoResponse.Data["SYNO.API.Auth"];
|
|
||||||
var infoResponeDSInfo = infoResponse.Data["SYNO.DownloadStation.Info"];
|
|
||||||
var infoResponeDSTask = infoResponse.Data["SYNO.DownloadStation.Task"];
|
|
||||||
var infoResponseFSList = infoResponse.Data["SYNO.FileStation.List"];
|
|
||||||
var infoResponseDSMInfo = infoResponse.Data["SYNO.DSM.Info"];
|
|
||||||
|
|
||||||
Resources[DiskStationApi.Auth] = infoResponeDSAuth.Path;
|
|
||||||
Resources[DiskStationApi.DownloadStationInfo] = infoResponeDSInfo.Path;
|
|
||||||
Resources[DiskStationApi.DownloadStationTask] = infoResponeDSTask.Path;
|
|
||||||
Resources[DiskStationApi.FileStationList] = infoResponseFSList.Path;
|
|
||||||
Resources[DiskStationApi.DSMInfo] = infoResponseDSMInfo.Path;
|
|
||||||
|
|
||||||
switch (api)
|
|
||||||
{
|
|
||||||
case DiskStationApi.Auth:
|
|
||||||
return Enumerable.Range(infoResponeDSAuth.MinVersion, infoResponeDSAuth.MaxVersion - infoResponeDSAuth.MinVersion + 1);
|
|
||||||
case DiskStationApi.DownloadStationInfo:
|
|
||||||
return Enumerable.Range(infoResponeDSInfo.MinVersion, infoResponeDSInfo.MaxVersion - infoResponeDSInfo.MinVersion + 1);
|
|
||||||
case DiskStationApi.DownloadStationTask:
|
|
||||||
return Enumerable.Range(infoResponeDSTask.MinVersion, infoResponeDSTask.MaxVersion - infoResponeDSTask.MinVersion + 1);
|
|
||||||
case DiskStationApi.FileStationList:
|
|
||||||
return Enumerable.Range(infoResponseFSList.MinVersion, infoResponseFSList.MaxVersion - infoResponseFSList.MinVersion + 1);
|
|
||||||
case DiskStationApi.DSMInfo:
|
|
||||||
return Enumerable.Range(infoResponseDSMInfo.MinVersion, infoResponseDSMInfo.MaxVersion - infoResponseDSMInfo.MinVersion + 1);
|
|
||||||
default:
|
|
||||||
throw new DownloadClientException("Api not implemented");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||||
|
{
|
||||||
|
public interface IDownloadStationInfoProxy : IDiskStationProxy
|
||||||
|
{
|
||||||
|
Dictionary<string, object> GetConfig(DownloadStationSettings settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DownloadStationInfoProxy : DiskStationProxyBase, IDownloadStationInfoProxy
|
||||||
|
{
|
||||||
|
public DownloadStationInfoProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger) :
|
||||||
|
base(DiskStationApi.DownloadStationInfo, "SYNO.DownloadStation.Info", httpClient, cacheManager, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, object> GetConfig(DownloadStationSettings settings)
|
||||||
|
{
|
||||||
|
var requestBuilder = BuildRequest(settings, "getConfig", 1);
|
||||||
|
|
||||||
|
var response = ProcessRequest<Dictionary<string, object>>(requestBuilder, "get config", settings);
|
||||||
|
|
||||||
|
return response.Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Common.Extensions;
|
|
||||||
using NzbDrone.Common.Http;
|
|
||||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
|
||||||
{
|
|
||||||
public interface IDownloadStationProxy
|
|
||||||
{
|
|
||||||
IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings);
|
|
||||||
Dictionary<string, object> GetConfig(DownloadStationSettings settings);
|
|
||||||
void RemoveTask(string downloadId, DownloadStationSettings settings);
|
|
||||||
void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings);
|
|
||||||
void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings);
|
|
||||||
IEnumerable<int> GetApiVersion(DownloadStationSettings settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DownloadStationProxy : DiskStationProxyBase, IDownloadStationProxy
|
|
||||||
{
|
|
||||||
public DownloadStationProxy(IHttpClient httpClient, Logger logger)
|
|
||||||
: base(httpClient, logger)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings)
|
|
||||||
{
|
|
||||||
var arguments = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "api", "SYNO.DownloadStation.Task" },
|
|
||||||
{ "version", "2" },
|
|
||||||
{ "method", "create" }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
arguments.Add("destination", downloadDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
arguments.Add("file", new Dictionary<string, object>() { { "name", filename }, { "data", data } });
|
|
||||||
|
|
||||||
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"add task from data {filename}", HttpMethod.POST);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings)
|
|
||||||
{
|
|
||||||
var arguments = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "api", "SYNO.DownloadStation.Task" },
|
|
||||||
{ "version", "3" },
|
|
||||||
{ "method", "create" },
|
|
||||||
{ "uri", url }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
arguments.Add("destination", downloadDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"add task from url {url}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings)
|
|
||||||
{
|
|
||||||
var arguments = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "api", "SYNO.DownloadStation.Task" },
|
|
||||||
{ "version", "1" },
|
|
||||||
{ "method", "list" },
|
|
||||||
{ "additional", "detail,transfer" }
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = ProcessRequest<DownloadStationTaskInfoResponse>(DiskStationApi.DownloadStationTask, arguments, settings, "get tasks");
|
|
||||||
|
|
||||||
return response.Data.Tasks;
|
|
||||||
}
|
|
||||||
catch (DownloadClientException e)
|
|
||||||
{
|
|
||||||
_logger.Error(e);
|
|
||||||
return new List<DownloadStationTask>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<string, object> GetConfig(DownloadStationSettings settings)
|
|
||||||
{
|
|
||||||
var arguments = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "api", "SYNO.DownloadStation.Info" },
|
|
||||||
{ "version", "1" },
|
|
||||||
{ "method", "getconfig" }
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = ProcessRequest<Dictionary<string, object>>(DiskStationApi.DownloadStationInfo, arguments, settings, "get config");
|
|
||||||
|
|
||||||
return response.Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveTask(string downloadId, DownloadStationSettings settings)
|
|
||||||
{
|
|
||||||
var arguments = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "api", "SYNO.DownloadStation.Task" },
|
|
||||||
{ "version", "1" },
|
|
||||||
{ "method", "delete" },
|
|
||||||
{ "id", downloadId },
|
|
||||||
{ "force_complete", false }
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = ProcessRequest(DiskStationApi.DownloadStationTask, arguments, settings, $"remove item {downloadId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<int> GetApiVersion(DownloadStationSettings settings)
|
|
||||||
{
|
|
||||||
return base.GetApiVersion(settings, DiskStationApi.DownloadStationInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||||
|
{
|
||||||
|
public interface IDownloadStationTaskProxy : IDiskStationProxy
|
||||||
|
{
|
||||||
|
IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings);
|
||||||
|
void RemoveTask(string downloadId, DownloadStationSettings settings);
|
||||||
|
void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings);
|
||||||
|
void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DownloadStationTaskProxy : DiskStationProxyBase, IDownloadStationTaskProxy
|
||||||
|
{
|
||||||
|
public DownloadStationTaskProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger)
|
||||||
|
: base(DiskStationApi.DownloadStationTask, "SYNO.DownloadStation.Task", httpClient, cacheManager, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTaskFromData(byte[] data, string filename, string downloadDirectory, DownloadStationSettings settings)
|
||||||
|
{
|
||||||
|
var requestBuilder = BuildRequest(settings, "create", 2, HttpMethod.POST);
|
||||||
|
|
||||||
|
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
requestBuilder.AddFormParameter("destination", downloadDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
requestBuilder.AddFormUpload("file", filename, data);
|
||||||
|
|
||||||
|
var response = ProcessRequest<object>(requestBuilder, $"add task from data {filename}", settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTaskFromUrl(string url, string downloadDirectory, DownloadStationSettings settings)
|
||||||
|
{
|
||||||
|
var requestBuilder = BuildRequest(settings, "create", 3);
|
||||||
|
requestBuilder.AddQueryParam("uri", url);
|
||||||
|
|
||||||
|
if (downloadDirectory.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
requestBuilder.AddQueryParam("destination", downloadDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = ProcessRequest<object>(requestBuilder, $"add task from url {url}", settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<DownloadStationTask> GetTasks(DownloadStationSettings settings)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var requestBuilder = BuildRequest(settings, "list", 1);
|
||||||
|
requestBuilder.AddQueryParam("additional", "detail,transfer");
|
||||||
|
|
||||||
|
var response = ProcessRequest<DownloadStationTaskInfoResponse>(requestBuilder, "get tasks", settings);
|
||||||
|
|
||||||
|
return response.Data.Tasks;
|
||||||
|
}
|
||||||
|
catch (DownloadClientException e)
|
||||||
|
{
|
||||||
|
_logger.Error(e);
|
||||||
|
return new List<DownloadStationTask>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveTask(string downloadId, DownloadStationSettings settings)
|
||||||
|
{
|
||||||
|
var requestBuilder = BuildRequest(settings, "delete", 1);
|
||||||
|
requestBuilder.AddQueryParam("id", downloadId);
|
||||||
|
requestBuilder.AddQueryParam("force_complete", false);
|
||||||
|
|
||||||
|
var response = ProcessRequest<object>(requestBuilder, $"remove item {downloadId}", settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,31 +2,27 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
using NzbDrone.Core.Download.Clients.DownloadStation.Responses;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
||||||
{
|
{
|
||||||
public interface IFileStationProxy
|
public interface IFileStationProxy : IDiskStationProxy
|
||||||
{
|
{
|
||||||
SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings);
|
SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings);
|
||||||
IEnumerable<int> GetApiVersion(DownloadStationSettings settings);
|
|
||||||
FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings);
|
FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FileStationProxy : DiskStationProxyBase, IFileStationProxy
|
public class FileStationProxy : DiskStationProxyBase, IFileStationProxy
|
||||||
{
|
{
|
||||||
public FileStationProxy(IHttpClient httpClient, Logger logger)
|
public FileStationProxy(IHttpClient httpClient, ICacheManager cacheManager, Logger logger)
|
||||||
: base(httpClient, logger)
|
: base(DiskStationApi.FileStationList, "SYNO.FileStation.List", httpClient, cacheManager, logger)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<int> GetApiVersion(DownloadStationSettings settings)
|
|
||||||
{
|
|
||||||
return base.GetApiVersion(settings, DiskStationApi.FileStationList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings)
|
public SharedFolderMapping GetSharedFolderMapping(string sharedFolder, DownloadStationSettings settings)
|
||||||
{
|
{
|
||||||
var info = GetInfoFileOrDirectory(sharedFolder, settings);
|
var info = GetInfoFileOrDirectory(sharedFolder, settings);
|
||||||
@@ -38,16 +34,11 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation.Proxies
|
|||||||
|
|
||||||
public FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings)
|
public FileStationListFileInfoResponse GetInfoFileOrDirectory(string path, DownloadStationSettings settings)
|
||||||
{
|
{
|
||||||
var arguments = new Dictionary<string, object>
|
var requestBuilder = BuildRequest(settings, "getinfo", 2);
|
||||||
{
|
requestBuilder.AddQueryParam("path", new[] { path }.ToJson());
|
||||||
{ "api", "SYNO.FileStation.List" },
|
requestBuilder.AddQueryParam("additional", "[\"real_path\"]");
|
||||||
{ "version", "2" },
|
|
||||||
{ "method", "getinfo" },
|
|
||||||
{ "path", new [] { path }.ToJson() },
|
|
||||||
{ "additional", $"[\"real_path\"]" }
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = ProcessRequest<FileStationListResponse>(DiskStationApi.FileStationList, arguments, settings, $"get info of {path}");
|
var response = ProcessRequest<FileStationListResponse>(requestBuilder, $"get info of {path}", settings);
|
||||||
|
|
||||||
return response.Data.Files.First();
|
return response.Data.Files.First();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ using System.Linq;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
@@ -20,7 +19,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
{
|
{
|
||||||
public class TorrentDownloadStation : TorrentClientBase<DownloadStationSettings>
|
public class TorrentDownloadStation : TorrentClientBase<DownloadStationSettings>
|
||||||
{
|
{
|
||||||
protected readonly IDownloadStationProxy _proxy;
|
protected readonly IDownloadStationInfoProxy _dsInfoProxy;
|
||||||
|
protected readonly IDownloadStationTaskProxy _dsTaskProxy;
|
||||||
protected readonly ISharedFolderResolver _sharedFolderResolver;
|
protected readonly ISharedFolderResolver _sharedFolderResolver;
|
||||||
protected readonly ISerialNumberProvider _serialNumberProvider;
|
protected readonly ISerialNumberProvider _serialNumberProvider;
|
||||||
protected readonly IFileStationProxy _fileStationProxy;
|
protected readonly IFileStationProxy _fileStationProxy;
|
||||||
@@ -28,7 +28,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
public TorrentDownloadStation(ISharedFolderResolver sharedFolderResolver,
|
public TorrentDownloadStation(ISharedFolderResolver sharedFolderResolver,
|
||||||
ISerialNumberProvider serialNumberProvider,
|
ISerialNumberProvider serialNumberProvider,
|
||||||
IFileStationProxy fileStationProxy,
|
IFileStationProxy fileStationProxy,
|
||||||
IDownloadStationProxy proxy,
|
IDownloadStationInfoProxy dsInfoProxy,
|
||||||
|
IDownloadStationTaskProxy dsTaskProxy,
|
||||||
ITorrentFileInfoReader torrentFileInfoReader,
|
ITorrentFileInfoReader torrentFileInfoReader,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
@@ -37,7 +38,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger)
|
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_dsInfoProxy = dsInfoProxy;
|
||||||
|
_dsTaskProxy = dsTaskProxy;
|
||||||
_fileStationProxy = fileStationProxy;
|
_fileStationProxy = fileStationProxy;
|
||||||
_sharedFolderResolver = sharedFolderResolver;
|
_sharedFolderResolver = sharedFolderResolver;
|
||||||
_serialNumberProvider = serialNumberProvider;
|
_serialNumberProvider = serialNumberProvider;
|
||||||
@@ -47,7 +49,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
|
|
||||||
protected IEnumerable<DownloadStationTask> GetTasks()
|
protected IEnumerable<DownloadStationTask> GetTasks()
|
||||||
{
|
{
|
||||||
return _proxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.BT.ToString().ToLower());
|
return _dsTaskProxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.BT.ToString().ToLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<DownloadClientItem> GetItems()
|
public override IEnumerable<DownloadClientItem> GetItems()
|
||||||
@@ -129,7 +131,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
DeleteItemData(downloadId);
|
DeleteItemData(downloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
_proxy.RemoveTask(ParseDownloadId(downloadId), Settings);
|
_dsTaskProxy.RemoveTask(ParseDownloadId(downloadId), Settings);
|
||||||
_logger.Debug("{0} removed correctly", downloadId);
|
_logger.Debug("{0} removed correctly", downloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +160,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
{
|
{
|
||||||
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
||||||
|
|
||||||
_proxy.AddTaskFromUrl(magnetLink, GetDownloadDirectory(), Settings);
|
_dsTaskProxy.AddTaskFromUrl(magnetLink, GetDownloadDirectory(), Settings);
|
||||||
|
|
||||||
var item = GetTasks().SingleOrDefault(t => t.Additional.Detail["uri"] == magnetLink);
|
var item = GetTasks().SingleOrDefault(t => t.Additional.Detail["uri"] == magnetLink);
|
||||||
|
|
||||||
@@ -177,7 +179,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
{
|
{
|
||||||
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
||||||
|
|
||||||
_proxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
|
_dsTaskProxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
|
||||||
|
|
||||||
var items = GetTasks().Where(t => t.Additional.Detail["uri"] == Path.GetFileNameWithoutExtension(filename));
|
var items = GetTasks().Where(t => t.Additional.Detail["uri"] == Path.GetFileNameWithoutExtension(filename));
|
||||||
|
|
||||||
@@ -368,13 +370,13 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
|
|
||||||
protected ValidationFailure ValidateVersion()
|
protected ValidationFailure ValidateVersion()
|
||||||
{
|
{
|
||||||
var versionRange = _proxy.GetApiVersion(Settings);
|
var info = _dsTaskProxy.GetApiInfo(Settings);
|
||||||
|
|
||||||
_logger.Debug("Download Station api version information: Min {0} - Max {1}", versionRange.Min(), versionRange.Max());
|
_logger.Debug("Download Station api version information: Min {0} - Max {1}", info.MinVersion, info.MaxVersion);
|
||||||
|
|
||||||
if (!versionRange.Contains(2))
|
if (info.MinVersion > 2 || info.MaxVersion < 2)
|
||||||
{
|
{
|
||||||
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {versionRange.Min()} to {versionRange.Max()}");
|
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {info.MinVersion} to {info.MaxVersion}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -405,7 +407,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
|
|
||||||
protected string GetDefaultDir()
|
protected string GetDefaultDir()
|
||||||
{
|
{
|
||||||
var config = _proxy.GetConfig(Settings);
|
var config = _dsInfoProxy.GetConfig(Settings);
|
||||||
|
|
||||||
var path = config["default_destination"] as string;
|
var path = config["default_destination"] as string;
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
{
|
{
|
||||||
public class UsenetDownloadStation : UsenetClientBase<DownloadStationSettings>
|
public class UsenetDownloadStation : UsenetClientBase<DownloadStationSettings>
|
||||||
{
|
{
|
||||||
protected readonly IDownloadStationProxy _proxy;
|
protected readonly IDownloadStationInfoProxy _dsInfoProxy;
|
||||||
|
protected readonly IDownloadStationTaskProxy _dsTaskProxy;
|
||||||
protected readonly ISharedFolderResolver _sharedFolderResolver;
|
protected readonly ISharedFolderResolver _sharedFolderResolver;
|
||||||
protected readonly ISerialNumberProvider _serialNumberProvider;
|
protected readonly ISerialNumberProvider _serialNumberProvider;
|
||||||
protected readonly IFileStationProxy _fileStationProxy;
|
protected readonly IFileStationProxy _fileStationProxy;
|
||||||
@@ -25,7 +26,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
public UsenetDownloadStation(ISharedFolderResolver sharedFolderResolver,
|
public UsenetDownloadStation(ISharedFolderResolver sharedFolderResolver,
|
||||||
ISerialNumberProvider serialNumberProvider,
|
ISerialNumberProvider serialNumberProvider,
|
||||||
IFileStationProxy fileStationProxy,
|
IFileStationProxy fileStationProxy,
|
||||||
IDownloadStationProxy proxy,
|
IDownloadStationInfoProxy dsInfoProxy,
|
||||||
|
IDownloadStationTaskProxy dsTaskProxy,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
@@ -34,7 +36,8 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
)
|
)
|
||||||
: base(httpClient, configService, diskProvider, remotePathMappingService, logger)
|
: base(httpClient, configService, diskProvider, remotePathMappingService, logger)
|
||||||
{
|
{
|
||||||
_proxy = proxy;
|
_dsInfoProxy = dsInfoProxy;
|
||||||
|
_dsTaskProxy = dsTaskProxy;
|
||||||
_fileStationProxy = fileStationProxy;
|
_fileStationProxy = fileStationProxy;
|
||||||
_sharedFolderResolver = sharedFolderResolver;
|
_sharedFolderResolver = sharedFolderResolver;
|
||||||
_serialNumberProvider = serialNumberProvider;
|
_serialNumberProvider = serialNumberProvider;
|
||||||
@@ -44,7 +47,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
|
|
||||||
protected IEnumerable<DownloadStationTask> GetTasks()
|
protected IEnumerable<DownloadStationTask> GetTasks()
|
||||||
{
|
{
|
||||||
return _proxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.NZB.ToString().ToLower());
|
return _dsTaskProxy.GetTasks(Settings).Where(v => v.Type.ToLower() == DownloadStationTaskType.NZB.ToString().ToLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<DownloadClientItem> GetItems()
|
public override IEnumerable<DownloadClientItem> GetItems()
|
||||||
@@ -153,7 +156,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
DeleteItemData(downloadId);
|
DeleteItemData(downloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
_proxy.RemoveTask(ParseDownloadId(downloadId), Settings);
|
_dsTaskProxy.RemoveTask(ParseDownloadId(downloadId), Settings);
|
||||||
_logger.Debug("{0} removed correctly", downloadId);
|
_logger.Debug("{0} removed correctly", downloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +169,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
{
|
{
|
||||||
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
var hashedSerialNumber = _serialNumberProvider.GetSerialNumber(Settings);
|
||||||
|
|
||||||
_proxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
|
_dsTaskProxy.AddTaskFromData(fileContent, filename, GetDownloadDirectory(), Settings);
|
||||||
|
|
||||||
var items = GetTasks().Where(t => t.Additional.Detail["uri"] == filename);
|
var items = GetTasks().Where(t => t.Additional.Detail["uri"] == filename);
|
||||||
|
|
||||||
@@ -281,13 +284,13 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
|
|
||||||
protected ValidationFailure ValidateVersion()
|
protected ValidationFailure ValidateVersion()
|
||||||
{
|
{
|
||||||
var versionRange = _proxy.GetApiVersion(Settings);
|
var info = _dsTaskProxy.GetApiInfo(Settings);
|
||||||
|
|
||||||
_logger.Debug("Download Station api version information: Min {0} - Max {1}", versionRange.Min(), versionRange.Max());
|
_logger.Debug("Download Station api version information: Min {0} - Max {1}", info.MinVersion, info.MaxVersion);
|
||||||
|
|
||||||
if (!versionRange.Contains(2))
|
if (info.MinVersion > 2 || info.MaxVersion < 2)
|
||||||
{
|
{
|
||||||
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {versionRange.Min()} to {versionRange.Max()}");
|
return new ValidationFailure(string.Empty, $"Download Station API version not supported, should be at least 2. It supports from {info.MinVersion} to {info.MaxVersion}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -399,7 +402,7 @@ namespace NzbDrone.Core.Download.Clients.DownloadStation
|
|||||||
|
|
||||||
protected string GetDefaultDir()
|
protected string GetDefaultDir()
|
||||||
{
|
{
|
||||||
var config = _proxy.GetConfig(Settings);
|
var config = _dsInfoProxy.GetConfig(Settings);
|
||||||
|
|
||||||
var path = config["default_destination"] as string;
|
var path = config["default_destination"] as string;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace NzbDrone.Core.Download.Clients.Sabnzbd.Responses
|
||||||
|
{
|
||||||
|
public class SabnzbdFullStatusResponse
|
||||||
|
{
|
||||||
|
public SabnzbdFullStatus Status { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -225,10 +225,18 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
|
|
||||||
if (!completeDir.IsRooted)
|
if (!completeDir.IsRooted)
|
||||||
{
|
{
|
||||||
var queue = _proxy.GetQueue(0, 1, Settings);
|
if (HasVersion(2, 0))
|
||||||
var defaultRootFolder = new OsPath(queue.DefaultRootFolder);
|
{
|
||||||
|
var status = _proxy.GetFullStatus(Settings);
|
||||||
|
completeDir = new OsPath(status.CompleteDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var queue = _proxy.GetQueue(0, 1, Settings);
|
||||||
|
var defaultRootFolder = new OsPath(queue.DefaultRootFolder);
|
||||||
|
|
||||||
completeDir = defaultRootFolder + completeDir;
|
completeDir = defaultRootFolder + completeDir;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var category in config.Categories)
|
foreach (var category in config.Categories)
|
||||||
@@ -448,50 +456,47 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (config.Misc.enable_tv_sorting && ContainsCategory(config.Misc.tv_categories, Settings.TvCategory))
|
||||||
if (config.Misc.enable_tv_sorting)
|
|
||||||
{
|
{
|
||||||
if (!config.Misc.tv_categories.Any<string>() ||
|
return new NzbDroneValidationFailure("TvCategory", "Disable TV Sorting")
|
||||||
config.Misc.tv_categories.Contains(Settings.TvCategory) ||
|
|
||||||
(Settings.TvCategory.IsNullOrWhiteSpace() && config.Misc.tv_categories.Contains("Default")))
|
|
||||||
{
|
{
|
||||||
return new NzbDroneValidationFailure("TvCategory", "Disable TV Sorting")
|
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||||
{
|
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
};
|
||||||
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (config.Misc.enable_movie_sorting && ContainsCategory(config.Misc.movie_categories, Settings.TvCategory))
|
||||||
if (config.Misc.enable_movie_sorting)
|
|
||||||
{
|
{
|
||||||
if (!config.Misc.movie_categories.Any<string>() ||
|
return new NzbDroneValidationFailure("TvCategory", "Disable Movie Sorting")
|
||||||
config.Misc.movie_categories.Contains(Settings.TvCategory) ||
|
|
||||||
(Settings.TvCategory.IsNullOrWhiteSpace() && config.Misc.movie_categories.Contains("Default")))
|
|
||||||
{
|
{
|
||||||
return new NzbDroneValidationFailure("TvCategory", "Disable Movie Sorting")
|
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||||
{
|
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
};
|
||||||
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (config.Misc.enable_date_sorting && ContainsCategory(config.Misc.date_categories, Settings.TvCategory))
|
||||||
if (config.Misc.enable_date_sorting)
|
|
||||||
{
|
{
|
||||||
if (!config.Misc.date_categories.Any<string>() ||
|
return new NzbDroneValidationFailure("TvCategory", "Disable Date Sorting")
|
||||||
config.Misc.date_categories.Contains(Settings.TvCategory) ||
|
|
||||||
(Settings.TvCategory.IsNullOrWhiteSpace() && config.Misc.date_categories.Contains("Default")))
|
|
||||||
{
|
{
|
||||||
return new NzbDroneValidationFailure("TvCategory", "Disable Date Sorting")
|
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||||
{
|
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
};
|
||||||
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ContainsCategory(IEnumerable<string> categories, string category)
|
||||||
|
{
|
||||||
|
if (categories == null || categories.Empty())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (category.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
category = "Default";
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories.Contains(category);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||||
|
{
|
||||||
|
public class SabnzbdFullStatus
|
||||||
|
{
|
||||||
|
// Added in Sabnzbd 2.0.0, my_home was previously in &mode=queue.
|
||||||
|
// This is the already resolved completedir path.
|
||||||
|
[JsonProperty(PropertyName = "completedir")]
|
||||||
|
public string CompleteDir { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
void RemoveFrom(string source, string id,bool deleteData, SabnzbdSettings settings);
|
void RemoveFrom(string source, string id,bool deleteData, SabnzbdSettings settings);
|
||||||
string GetVersion(SabnzbdSettings settings);
|
string GetVersion(SabnzbdSettings settings);
|
||||||
SabnzbdConfig GetConfig(SabnzbdSettings settings);
|
SabnzbdConfig GetConfig(SabnzbdSettings settings);
|
||||||
|
SabnzbdFullStatus GetFullStatus(SabnzbdSettings settings);
|
||||||
SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings);
|
SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings);
|
||||||
SabnzbdHistory GetHistory(int start, int limit, string category, SabnzbdSettings settings);
|
SabnzbdHistory GetHistory(int start, int limit, string category, SabnzbdSettings settings);
|
||||||
string RetryDownload(string id, SabnzbdSettings settings);
|
string RetryDownload(string id, SabnzbdSettings settings);
|
||||||
@@ -37,7 +38,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
|
|
||||||
request.AddQueryParam("cat", category);
|
request.AddQueryParam("cat", category);
|
||||||
request.AddQueryParam("priority", priority);
|
request.AddQueryParam("priority", priority);
|
||||||
|
|
||||||
request.AddFormUpload("name", filename, nzbData, "application/x-nzb");
|
request.AddFormUpload("name", filename, nzbData, "application/x-nzb");
|
||||||
|
|
||||||
SabnzbdAddResponse response;
|
SabnzbdAddResponse response;
|
||||||
@@ -84,6 +85,16 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
return response.Config;
|
return response.Config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SabnzbdFullStatus GetFullStatus(SabnzbdSettings settings)
|
||||||
|
{
|
||||||
|
var request = BuildRequest("fullstatus", settings);
|
||||||
|
request.AddQueryParam("skip_dashboard", "1");
|
||||||
|
|
||||||
|
var response = Json.Deserialize<SabnzbdFullStatusResponse>(ProcessRequest(request, settings));
|
||||||
|
|
||||||
|
return response.Status;
|
||||||
|
}
|
||||||
|
|
||||||
public SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings)
|
public SabnzbdQueue GetQueue(int start, int limit, SabnzbdSettings settings)
|
||||||
{
|
{
|
||||||
var request = BuildRequest("queue", settings);
|
var request = BuildRequest("queue", settings);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
{
|
{
|
||||||
public class SabnzbdQueue
|
public class SabnzbdQueue
|
||||||
{
|
{
|
||||||
|
// Removed in Sabnzbd 2.0.0, see mode=fullstatus instead.
|
||||||
[JsonProperty(PropertyName = "my_home")]
|
[JsonProperty(PropertyName = "my_home")]
|
||||||
public string DefaultRootFolder { get; set; }
|
public string DefaultRootFolder { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -86,8 +86,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
item.Status = DownloadItemStatus.Warning;
|
item.Status = DownloadItemStatus.Warning;
|
||||||
item.Message = torrent.ErrorString;
|
item.Message = torrent.ErrorString;
|
||||||
}
|
}
|
||||||
else if (torrent.Status == TransmissionTorrentStatus.Seeding ||
|
else if (torrent.LeftUntilDone == 0 && (torrent.Status == TransmissionTorrentStatus.Stopped ||
|
||||||
torrent.Status == TransmissionTorrentStatus.SeedingWait)
|
torrent.Status == TransmissionTorrentStatus.Seeding ||
|
||||||
|
torrent.Status == TransmissionTorrentStatus.SeedingWait))
|
||||||
{
|
{
|
||||||
item.Status = DownloadItemStatus.Completed;
|
item.Status = DownloadItemStatus.Completed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,19 @@ namespace NzbDrone.Core.Download.Clients.Vuze
|
|||||||
|
|
||||||
protected override OsPath GetOutputPath(OsPath outputPath, TransmissionTorrent torrent)
|
protected override OsPath GetOutputPath(OsPath outputPath, TransmissionTorrent torrent)
|
||||||
{
|
{
|
||||||
_logger.Debug("Vuze output directory: {0}", outputPath);
|
// Vuze has similar behavior as uTorrent:
|
||||||
|
// - A multi-file torrent is downloaded in a job folder and 'outputPath' points to that directory directly.
|
||||||
|
// - A single-file torrent is downloaded in the root folder and 'outputPath' poinst to that root folder.
|
||||||
|
// We have to make sure the return value points to the job folder OR file.
|
||||||
|
if (outputPath == null || outputPath.FileName == torrent.Name)
|
||||||
|
{
|
||||||
|
_logger.Trace("Vuze output directory: {0}", outputPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputPath = outputPath + torrent.Name;
|
||||||
|
_logger.Trace("Vuze output file: {0}", outputPath);
|
||||||
|
}
|
||||||
|
|
||||||
return outputPath;
|
return outputPath;
|
||||||
}
|
}
|
||||||
@@ -50,4 +62,4 @@ namespace NzbDrone.Core.Download.Clients.Vuze
|
|||||||
|
|
||||||
public override string Name => "Vuze";
|
public override string Name => "Vuze";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,52 +49,36 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
|
|
||||||
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
|
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
|
||||||
{
|
{
|
||||||
_proxy.AddTorrentFromUrl(magnetLink, Settings);
|
_proxy.AddTorrentFromUrl(magnetLink, Settings.MovieCategory, RTorrentPriority.Normal, Settings.MovieDirectory, Settings);
|
||||||
|
|
||||||
// Download the magnet to the appropriate directory.
|
|
||||||
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
|
|
||||||
SetDownloadDirectory(hash);
|
|
||||||
_proxy.StartTorrent(hash, Settings);
|
|
||||||
|
|
||||||
// Wait for the magnet to be resolved.
|
|
||||||
var tries = 10;
|
var tries = 10;
|
||||||
var retryDelay = 500;
|
var retryDelay = 500;
|
||||||
if (WaitForTorrent(hash, tries, retryDelay))
|
|
||||||
{
|
// Wait a bit for the magnet to be resolved.
|
||||||
_logger.Info("Resolved magnet for {0}", remoteMovie.Movie.CleanTitle);
|
if (!WaitForTorrent(hash, tries, retryDelay))
|
||||||
SetDownloadDirectory(hash);
|
|
||||||
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
|
|
||||||
_proxy.StartTorrent(hash, Settings);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
_logger.Warn("rTorrent could not resolve magnet within {0} seconds, download may remain stuck: {1}.", tries * retryDelay / 1000, magnetLink);
|
_logger.Warn("rTorrent could not resolve magnet within {0} seconds, download may remain stuck: {1}.", tries * retryDelay / 1000, magnetLink);
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
|
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
|
||||||
{
|
{
|
||||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
_proxy.AddTorrentFromFile(filename, fileContent, Settings.MovieCategory, RTorrentPriority.Normal, Settings.MovieDirectory, Settings);
|
||||||
|
|
||||||
var tries = 5;
|
var tries = 10;
|
||||||
var retryDelay = 200;
|
var retryDelay = 500;
|
||||||
if (WaitForTorrent(hash, tries, retryDelay))
|
if (!WaitForTorrent(hash, tries, retryDelay))
|
||||||
{
|
{
|
||||||
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
|
_logger.Debug("rTorrent didn't add the torrent within {0} seconds: {1}.", tries * retryDelay / 1000, filename);
|
||||||
SetDownloadDirectory(hash);
|
|
||||||
_proxy.StartTorrent(hash, Settings);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Debug("rTorrent could not add file");
|
|
||||||
|
|
||||||
RemoveItem(hash, true);
|
|
||||||
throw new ReleaseDownloadException(remoteMovie.Release, "Downloading torrent failed");
|
throw new ReleaseDownloadException(remoteMovie.Release, "Downloading torrent failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name => "rTorrent";
|
public override string Name => "rTorrent";
|
||||||
@@ -233,14 +217,6 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
return result.Errors.First();
|
return result.Errors.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetDownloadDirectory(string hash)
|
|
||||||
{
|
|
||||||
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
_proxy.SetTorrentDownloadDirectory(hash, Settings.MovieDirectory, Settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool WaitForTorrent(string hash, int tries, int retryDelay)
|
private bool WaitForTorrent(string hash, int tries, int retryDelay)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < tries; i++)
|
for (var i = 0; i < tries; i++)
|
||||||
|
|||||||
@@ -13,15 +13,10 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
string GetVersion(RTorrentSettings settings);
|
string GetVersion(RTorrentSettings settings);
|
||||||
List<RTorrentTorrent> GetTorrents(RTorrentSettings settings);
|
List<RTorrentTorrent> GetTorrents(RTorrentSettings settings);
|
||||||
|
|
||||||
void AddTorrentFromUrl(string torrentUrl, RTorrentSettings settings);
|
void AddTorrentFromUrl(string torrentUrl, string label, RTorrentPriority priority, string directory, RTorrentSettings settings);
|
||||||
void AddTorrentFromFile(string fileName, byte[] fileContent, RTorrentSettings settings);
|
void AddTorrentFromFile(string fileName, byte[] fileContent, string label, RTorrentPriority priority, string directory, RTorrentSettings settings);
|
||||||
void RemoveTorrent(string hash, RTorrentSettings settings);
|
void RemoveTorrent(string hash, RTorrentSettings settings);
|
||||||
void SetTorrentPriority(string hash, RTorrentPriority priority, RTorrentSettings settings);
|
|
||||||
void SetTorrentLabel(string hash, string label, RTorrentSettings settings);
|
|
||||||
void SetTorrentDownloadDirectory(string hash, string directory, RTorrentSettings settings);
|
|
||||||
bool HasHashTorrent(string hash, RTorrentSettings settings);
|
bool HasHashTorrent(string hash, RTorrentSettings settings);
|
||||||
void StartTorrent(string hash, RTorrentSettings settings);
|
|
||||||
void SetDeferredMagnetProperties(string hash, string category, string directory, RTorrentPriority priority, RTorrentSettings settings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IRTorrent : IXmlRpcProxy
|
public interface IRTorrent : IXmlRpcProxy
|
||||||
@@ -29,35 +24,20 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
[XmlRpcMethod("d.multicall2")]
|
[XmlRpcMethod("d.multicall2")]
|
||||||
object[] TorrentMulticall(params string[] parameters);
|
object[] TorrentMulticall(params string[] parameters);
|
||||||
|
|
||||||
[XmlRpcMethod("load.normal")]
|
[XmlRpcMethod("load.start")]
|
||||||
int LoadUrl(string target, string data);
|
int LoadStart(string target, string data, params string[] commands);
|
||||||
|
|
||||||
[XmlRpcMethod("load.raw")]
|
[XmlRpcMethod("load.raw_start")]
|
||||||
int LoadBinary(string target, byte[] data);
|
int LoadRawStart(string target, byte[] data, params string[] commands);
|
||||||
|
|
||||||
[XmlRpcMethod("d.erase")]
|
[XmlRpcMethod("d.erase")]
|
||||||
int Remove(string hash);
|
int Remove(string hash);
|
||||||
|
|
||||||
[XmlRpcMethod("d.custom1.set")]
|
|
||||||
string SetLabel(string hash, string label);
|
|
||||||
|
|
||||||
[XmlRpcMethod("d.priority.set")]
|
|
||||||
int SetPriority(string hash, long priority);
|
|
||||||
|
|
||||||
[XmlRpcMethod("d.directory.set")]
|
|
||||||
int SetDirectory(string hash, string directory);
|
|
||||||
|
|
||||||
[XmlRpcMethod("method.set_key")]
|
|
||||||
int SetKey(string target, string key, string cmd_key, string value);
|
|
||||||
|
|
||||||
[XmlRpcMethod("d.name")]
|
[XmlRpcMethod("d.name")]
|
||||||
string GetName(string hash);
|
string GetName(string hash);
|
||||||
|
|
||||||
[XmlRpcMethod("system.client_version")]
|
[XmlRpcMethod("system.client_version")]
|
||||||
string GetVersion();
|
string GetVersion();
|
||||||
|
|
||||||
[XmlRpcMethod("system.multicall")]
|
|
||||||
object[] SystemMulticall(object[] parameters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RTorrentProxy : IRTorrentProxy
|
public class RTorrentProxy : IRTorrentProxy
|
||||||
@@ -101,20 +81,20 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
var items = new List<RTorrentTorrent>();
|
var items = new List<RTorrentTorrent>();
|
||||||
foreach (object[] torrent in ret)
|
foreach (object[] torrent in ret)
|
||||||
{
|
{
|
||||||
var labelDecoded = System.Web.HttpUtility.UrlDecode((string) torrent[3]);
|
var labelDecoded = System.Web.HttpUtility.UrlDecode((string)torrent[3]);
|
||||||
|
|
||||||
var item = new RTorrentTorrent();
|
var item = new RTorrentTorrent();
|
||||||
item.Name = (string) torrent[0];
|
item.Name = (string)torrent[0];
|
||||||
item.Hash = (string) torrent[1];
|
item.Hash = (string)torrent[1];
|
||||||
item.Path = (string) torrent[2];
|
item.Path = (string)torrent[2];
|
||||||
item.Category = labelDecoded;
|
item.Category = labelDecoded;
|
||||||
item.TotalSize = (long) torrent[4];
|
item.TotalSize = (long)torrent[4];
|
||||||
item.RemainingSize = (long) torrent[5];
|
item.RemainingSize = (long)torrent[5];
|
||||||
item.DownRate = (long) torrent[6];
|
item.DownRate = (long)torrent[6];
|
||||||
item.Ratio = (long) torrent[7];
|
item.Ratio = (long)torrent[7];
|
||||||
item.IsOpen = Convert.ToBoolean((long) torrent[8]);
|
item.IsOpen = Convert.ToBoolean((long)torrent[8]);
|
||||||
item.IsActive = Convert.ToBoolean((long) torrent[9]);
|
item.IsActive = Convert.ToBoolean((long)torrent[9]);
|
||||||
item.IsFinished = Convert.ToBoolean((long) torrent[10]);
|
item.IsFinished = Convert.ToBoolean((long)torrent[10]);
|
||||||
|
|
||||||
items.Add(item);
|
items.Add(item);
|
||||||
}
|
}
|
||||||
@@ -122,26 +102,26 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddTorrentFromUrl(string torrentUrl, RTorrentSettings settings)
|
public void AddTorrentFromUrl(string torrentUrl, string label, RTorrentPriority priority, string directory, RTorrentSettings settings)
|
||||||
{
|
{
|
||||||
_logger.Debug("Executing remote method: load.normal");
|
_logger.Debug("Executing remote method: load.normal");
|
||||||
|
|
||||||
var client = BuildClient(settings);
|
var client = BuildClient(settings);
|
||||||
|
|
||||||
var response = client.LoadUrl("", torrentUrl);
|
var response = client.LoadStart("", torrentUrl, GetCommands(label, priority, directory));
|
||||||
if (response != 0)
|
if (response != 0)
|
||||||
{
|
{
|
||||||
throw new DownloadClientException("Could not add torrent: {0}.", torrentUrl);
|
throw new DownloadClientException("Could not add torrent: {0}.", torrentUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddTorrentFromFile(string fileName, byte[] fileContent, RTorrentSettings settings)
|
public void AddTorrentFromFile(string fileName, byte[] fileContent, string label, RTorrentPriority priority, string directory, RTorrentSettings settings)
|
||||||
{
|
{
|
||||||
_logger.Debug("Executing remote method: load.raw");
|
_logger.Debug("Executing remote method: load.raw");
|
||||||
|
|
||||||
var client = BuildClient(settings);
|
var client = BuildClient(settings);
|
||||||
|
|
||||||
var response = client.LoadBinary("", fileContent);
|
var response = client.LoadRawStart("", fileContent, GetCommands(label, priority, directory));
|
||||||
if (response != 0)
|
if (response != 0)
|
||||||
{
|
{
|
||||||
throw new DownloadClientException("Could not add torrent: {0}.", fileName);
|
throw new DownloadClientException("Could not add torrent: {0}.", fileName);
|
||||||
@@ -161,94 +141,26 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTorrentPriority(string hash, RTorrentPriority priority, RTorrentSettings settings)
|
private string[] GetCommands(string label, RTorrentPriority priority, string directory)
|
||||||
{
|
{
|
||||||
_logger.Debug("Executing remote method: d.priority.set");
|
var result = new List<string>();
|
||||||
|
|
||||||
var client = BuildClient(settings);
|
if (label.IsNotNullOrWhiteSpace())
|
||||||
|
|
||||||
var response = client.SetPriority(hash, (long) priority);
|
|
||||||
if (response != 0)
|
|
||||||
{
|
{
|
||||||
throw new DownloadClientException("Could not set priority on torrent: {0}.", hash);
|
result.Add("d.custom1.set=" + label);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetTorrentLabel(string hash, string label, RTorrentSettings settings)
|
|
||||||
{
|
|
||||||
_logger.Debug("Executing remote method: d.custom1.set");
|
|
||||||
|
|
||||||
var labelEncoded = System.Web.HttpUtility.UrlEncode(label);
|
|
||||||
|
|
||||||
var client = BuildClient(settings);
|
|
||||||
|
|
||||||
var setLabel = client.SetLabel(hash, labelEncoded);
|
|
||||||
if (setLabel != labelEncoded)
|
|
||||||
{
|
|
||||||
throw new DownloadClientException("Could set label on torrent: {0}.", hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetTorrentDownloadDirectory(string hash, string directory, RTorrentSettings settings)
|
|
||||||
{
|
|
||||||
_logger.Debug("Executing remote method: d.directory.set");
|
|
||||||
|
|
||||||
var client = BuildClient(settings);
|
|
||||||
|
|
||||||
var response = client.SetDirectory(hash, directory);
|
|
||||||
if (response != 0)
|
|
||||||
{
|
|
||||||
throw new DownloadClientException("Could not set directory for torrent: {0}.", hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetDeferredMagnetProperties(string hash, string category, string directory, RTorrentPriority priority, RTorrentSettings settings)
|
|
||||||
{
|
|
||||||
var commands = new List<string>();
|
|
||||||
|
|
||||||
if (category.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
commands.Add("d.custom1.set=" + category);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (directory.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
commands.Add("d.directory.set=" + directory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priority != RTorrentPriority.Normal)
|
if (priority != RTorrentPriority.Normal)
|
||||||
{
|
{
|
||||||
commands.Add("d.priority.set=" + (long)priority);
|
result.Add("d.priority.set=" + (int)priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure it gets started if the user doesn't have schedule=...,start_tied=
|
if (directory.IsNotNullOrWhiteSpace())
|
||||||
commands.Add("d.open=");
|
|
||||||
commands.Add("d.start=");
|
|
||||||
|
|
||||||
if (commands.Any())
|
|
||||||
{
|
{
|
||||||
var key = "event.download.inserted_new";
|
result.Add("d.directory.set=" + directory);
|
||||||
var cmd_key = "sonarr_deferred_" + hash;
|
|
||||||
|
|
||||||
commands.Add(string.Format("print=\"Applying deferred properties to {0}\"", hash));
|
|
||||||
|
|
||||||
// Remove event handler once triggered.
|
|
||||||
commands.Add(string.Format("\"method.set_key={0},{1}\"", key, cmd_key));
|
|
||||||
|
|
||||||
var setKeyValue = string.Format("branch=\"equal=d.hash=,cat={0}\",{{{1}}}", hash, string.Join(",", commands));
|
|
||||||
|
|
||||||
_logger.Debug("Executing remote method: method.set_key = {0},{1},{2}", key, cmd_key, setKeyValue);
|
|
||||||
|
|
||||||
var client = BuildClient(settings);
|
|
||||||
|
|
||||||
// Commands need a target, in this case the target is an empty string
|
|
||||||
// See: https://github.com/rakshasa/rtorrent/issues/227
|
|
||||||
var response = client.SetKey("", key, cmd_key, setKeyValue);
|
|
||||||
if (response != 0)
|
|
||||||
{
|
|
||||||
throw new DownloadClientException("Could set properties for torrent: {0}.", hash);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasHashTorrent(string hash, RTorrentSettings settings)
|
public bool HasHashTorrent(string hash, RTorrentSettings settings)
|
||||||
@@ -270,32 +182,6 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartTorrent(string hash, RTorrentSettings settings)
|
|
||||||
{
|
|
||||||
_logger.Debug("Executing remote methods: d.open and d.start");
|
|
||||||
|
|
||||||
var client = BuildClient(settings);
|
|
||||||
|
|
||||||
var multicallResponse = client.SystemMulticall(new[]
|
|
||||||
{
|
|
||||||
new
|
|
||||||
{
|
|
||||||
methodName = "d.open",
|
|
||||||
@params = new[] { hash }
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
methodName = "d.start",
|
|
||||||
@params = new[] { hash }
|
|
||||||
},
|
|
||||||
}).SelectMany(c => ((IEnumerable<int>)c));
|
|
||||||
|
|
||||||
if (multicallResponse.Any(r => r != 0))
|
|
||||||
{
|
|
||||||
throw new DownloadClientException("Could not start torrent: {0}.", hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IRTorrent BuildClient(RTorrentSettings settings)
|
private IRTorrent BuildClient(RTorrentSettings settings)
|
||||||
{
|
{
|
||||||
var client = XmlRpcProxyGen.Create<IRTorrent>();
|
var client = XmlRpcProxyGen.Create<IRTorrent>();
|
||||||
@@ -316,4 +202,4 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,14 @@ namespace NzbDrone.Core.Download
|
|||||||
{
|
{
|
||||||
var statusMessages = importResults
|
var statusMessages = importResults
|
||||||
.Where(v => v.Result != ImportResultType.Imported)
|
.Where(v => v.Result != ImportResultType.Imported)
|
||||||
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalMovie.Path), v.Errors))
|
.Select(v =>
|
||||||
|
{
|
||||||
|
if (v.ImportDecision.LocalMovie == null)
|
||||||
|
{
|
||||||
|
return new TrackedDownloadStatusMessage("", v.Errors);
|
||||||
|
}
|
||||||
|
return new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalMovie.Path), v.Errors);
|
||||||
|
})
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
trackedDownload.Warn(statusMessages);
|
trackedDownload.Warn(statusMessages);
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ namespace NzbDrone.Core.Download
|
|||||||
public ValidationResult Test()
|
public ValidationResult Test()
|
||||||
{
|
{
|
||||||
var failures = new List<ValidationFailure>();
|
var failures = new List<ValidationFailure>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Test(failures);
|
Test(failures);
|
||||||
|
|||||||
@@ -117,45 +117,43 @@ namespace NzbDrone.Core.Download.Pending
|
|||||||
|
|
||||||
foreach (var pendingRelease in GetPendingReleases())
|
foreach (var pendingRelease in GetPendingReleases())
|
||||||
{
|
{
|
||||||
//foreach (var episode in pendingRelease.RemoteEpisode.Episodes)
|
var ect = pendingRelease.Release.PublishDate.AddMinutes(GetDelay(pendingRelease.RemoteMovie));
|
||||||
//{
|
|
||||||
var ect = pendingRelease.Release.PublishDate.AddMinutes(GetDelay(pendingRelease.RemoteMovie));
|
|
||||||
|
|
||||||
if (ect < nextRssSync.Value)
|
if (ect < nextRssSync.Value)
|
||||||
{
|
{
|
||||||
ect = nextRssSync.Value;
|
ect = nextRssSync.Value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ect = ect.AddMinutes(_configService.RssSyncInterval);
|
ect = ect.AddMinutes(_configService.RssSyncInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
var queue = new Queue.Queue
|
var queue = new Queue.Queue
|
||||||
{
|
{
|
||||||
Id = GetQueueId(pendingRelease, pendingRelease.RemoteMovie.Movie),
|
Id = GetQueueId(pendingRelease, pendingRelease.RemoteMovie.Movie),
|
||||||
Series = null,
|
Series = null,
|
||||||
Episode = null,
|
Episode = null,
|
||||||
Movie = pendingRelease.RemoteMovie.Movie,
|
Movie = pendingRelease.RemoteMovie.Movie,
|
||||||
Quality = pendingRelease.RemoteMovie.ParsedMovieInfo.Quality,
|
Quality = pendingRelease.RemoteMovie.ParsedMovieInfo?.Quality ?? new QualityModel(),
|
||||||
Title = pendingRelease.Title,
|
Title = pendingRelease.Title,
|
||||||
Size = pendingRelease.RemoteMovie.Release.Size,
|
Size = pendingRelease.RemoteMovie.Release.Size,
|
||||||
Sizeleft = pendingRelease.RemoteMovie.Release.Size,
|
Sizeleft = pendingRelease.RemoteMovie.Release.Size,
|
||||||
RemoteMovie = pendingRelease.RemoteMovie,
|
RemoteMovie = pendingRelease.RemoteMovie,
|
||||||
Timeleft = ect.Subtract(DateTime.UtcNow),
|
Timeleft = ect.Subtract(DateTime.UtcNow),
|
||||||
EstimatedCompletionTime = ect,
|
EstimatedCompletionTime = ect,
|
||||||
Status = "Pending",
|
Status = "Pending",
|
||||||
Protocol = pendingRelease.RemoteMovie.Release.DownloadProtocol
|
Protocol = pendingRelease.RemoteMovie.Release.DownloadProtocol
|
||||||
};
|
};
|
||||||
queued.Add(queue);
|
|
||||||
//}
|
queued.Add(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Return best quality release for each episode
|
//Return best quality release for each episode
|
||||||
var deduped = queued.GroupBy(q => q.Episode.Id).Select(g =>
|
var deduped = queued.GroupBy(q => q.Movie.Id).Select(g =>
|
||||||
{
|
{
|
||||||
var series = g.First().Series;
|
var movies = g.First().Movie;
|
||||||
|
|
||||||
return g.OrderByDescending(e => e.Quality, new QualityModelComparer(series.Profile))
|
return g.OrderByDescending(e => e.Quality, new QualityModelComparer(movies.Profile))
|
||||||
.ThenBy(q => PrioritizeDownloadProtocol(q.Movie, q.Protocol))
|
.ThenBy(q => PrioritizeDownloadProtocol(q.Movie, q.Protocol))
|
||||||
.First();
|
.First();
|
||||||
});
|
});
|
||||||
@@ -220,14 +218,20 @@ namespace NzbDrone.Core.Download.Pending
|
|||||||
|
|
||||||
private void Insert(DownloadDecision decision)
|
private void Insert(DownloadDecision decision)
|
||||||
{
|
{
|
||||||
_repository.Insert(new PendingRelease
|
var release = new PendingRelease
|
||||||
{
|
{
|
||||||
MovieId = decision.RemoteMovie.Movie.Id,
|
MovieId = decision.RemoteMovie.Movie.Id,
|
||||||
ParsedMovieInfo = decision.RemoteMovie.ParsedMovieInfo,
|
ParsedMovieInfo = decision.RemoteMovie.ParsedMovieInfo,
|
||||||
Release = decision.RemoteMovie.Release,
|
Release = decision.RemoteMovie.Release,
|
||||||
Title = decision.RemoteMovie.Release.Title,
|
Title = decision.RemoteMovie.Release.Title,
|
||||||
Added = DateTime.UtcNow
|
Added = DateTime.UtcNow
|
||||||
});
|
};
|
||||||
|
if (release.ParsedMovieInfo == null)
|
||||||
|
{
|
||||||
|
_logger.Warn("Pending release {0} does not have ParsedMovieInfo, will cause issues.", release.Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
_repository.Insert(release);
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent());
|
_eventAggregator.PublishEvent(new PendingReleasesUpdatedEvent());
|
||||||
}
|
}
|
||||||
@@ -254,12 +258,12 @@ namespace NzbDrone.Core.Download.Pending
|
|||||||
return new[] { delay, minimumAge }.Max();
|
return new[] { delay, minimumAge }.Max();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveGrabbed(RemoteMovie remoteEpisode)
|
private void RemoveGrabbed(RemoteMovie remoteMovie)
|
||||||
{
|
{
|
||||||
var pendingReleases = GetPendingReleases();
|
var pendingReleases = GetPendingReleases();
|
||||||
|
|
||||||
|
|
||||||
var existingReports = pendingReleases.Where(r => r.RemoteMovie.Movie.Id == remoteEpisode.Movie.Id)
|
var existingReports = pendingReleases.Where(r => r.RemoteMovie.Movie.Id == remoteMovie.Movie.Id)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (existingReports.Empty())
|
if (existingReports.Empty())
|
||||||
@@ -267,11 +271,11 @@ namespace NzbDrone.Core.Download.Pending
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var profile = remoteEpisode.Movie.Profile.Value;
|
var profile = remoteMovie.Movie.Profile.Value;
|
||||||
|
|
||||||
foreach (var existingReport in existingReports)
|
foreach (var existingReport in existingReports)
|
||||||
{
|
{
|
||||||
var compare = new QualityModelComparer(profile).Compare(remoteEpisode.ParsedMovieInfo.Quality,
|
var compare = new QualityModelComparer(profile).Compare(remoteMovie.ParsedMovieInfo.Quality,
|
||||||
existingReport.RemoteMovie.ParsedMovieInfo.Quality);
|
existingReport.RemoteMovie.ParsedMovieInfo.Quality);
|
||||||
|
|
||||||
//Only remove lower/equal quality pending releases
|
//Only remove lower/equal quality pending releases
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
|||||||
{
|
{
|
||||||
var mapper = _database.GetDataMapper();
|
var mapper = _database.GetDataMapper();
|
||||||
|
|
||||||
mapper.ExecuteNonQuery(@"DELETE FROM EpisodeFiles
|
mapper.ExecuteNonQuery(@"DELETE FROM MovieFiles
|
||||||
WHERE Id IN (
|
WHERE Id IN (
|
||||||
SELECT EpisodeFiles.Id FROM EpisodeFiles
|
SELECT MovieFiles.Id FROM MovieFiles
|
||||||
LEFT OUTER JOIN Episodes
|
LEFT OUTER JOIN Movies
|
||||||
ON EpisodeFiles.Id = Episodes.EpisodeFileId
|
ON MovieFiles.Id = Movies.MovieFileId
|
||||||
WHERE Episodes.Id IS NULL)");
|
WHERE Movies.Id IS NULL)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
|||||||
{
|
{
|
||||||
var mapper = _database.GetDataMapper();
|
var mapper = _database.GetDataMapper();
|
||||||
|
|
||||||
var usedTags = new[] { "Series", "Notifications", "DelayProfiles", "Restrictions" }
|
var usedTags = new[] { "Movies", "Series", "Notifications", "DelayProfiles", "Restrictions" }
|
||||||
.SelectMany(v => GetUsedTags(v, mapper))
|
.SelectMany(v => GetUsedTags(v, mapper))
|
||||||
.Distinct()
|
.Distinct()
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|||||||
@@ -6,21 +6,21 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
|||||||
{
|
{
|
||||||
public class UpdateCleanTitleForSeries : IHousekeepingTask
|
public class UpdateCleanTitleForSeries : IHousekeepingTask
|
||||||
{
|
{
|
||||||
private readonly ISeriesRepository _seriesRepository;
|
private readonly IMovieRepository _movieRepository;
|
||||||
|
|
||||||
public UpdateCleanTitleForSeries(ISeriesRepository seriesRepository)
|
public UpdateCleanTitleForSeries(IMovieRepository movieRepository)
|
||||||
{
|
{
|
||||||
_seriesRepository = seriesRepository;
|
_movieRepository = movieRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clean()
|
public void Clean()
|
||||||
{
|
{
|
||||||
var series = _seriesRepository.All().ToList();
|
var movies = _movieRepository.All().ToList();
|
||||||
|
|
||||||
series.ForEach(s =>
|
movies.ForEach(m =>
|
||||||
{
|
{
|
||||||
s.CleanTitle = s.CleanTitle.CleanSeriesTitle();
|
m.CleanTitle = m.CleanTitle.CleanSeriesTitle();
|
||||||
_seriesRepository.Update(s);
|
_movieRepository.Update(m);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Indexers.Exceptions;
|
using NzbDrone.Core.Indexers.Exceptions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
@@ -64,12 +62,19 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
|
|||||||
Subtitles = x.Element("subtitles").Value,
|
Subtitles = x.Element("subtitles").Value,
|
||||||
EncodeStatus = x.Element("encodestatus").Value,
|
EncodeStatus = x.Element("encodestatus").Value,
|
||||||
Freeleech = x.Element("freeleech").Value,
|
Freeleech = x.Element("freeleech").Value,
|
||||||
|
ImdbId = x.Element("imdb").Value
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
foreach (var torrent in torrents)
|
foreach (var torrent in torrents)
|
||||||
{
|
{
|
||||||
var id = torrent.Id;
|
var id = torrent.Id;
|
||||||
var title = $"{torrent.Name}.{torrent.Year}.{torrent.Resolution}.{torrent.Media}.{torrent.Encoding}.{torrent.AudioFormat}-{torrent.ReleaseGroup}";
|
var title = $"{torrent.Name}.{torrent.Year}.{torrent.Resolution}.{torrent.Media}.{torrent.Encoding}.{torrent.AudioFormat}-{torrent.ReleaseGroup}";
|
||||||
|
IndexerFlags flags = 0;
|
||||||
|
|
||||||
|
if (torrent.Freeleech == "1.00")
|
||||||
|
{
|
||||||
|
flags |= IndexerFlags.G_Freeleech;
|
||||||
|
}
|
||||||
|
|
||||||
torrentInfos.Add(new TorrentInfo()
|
torrentInfos.Add(new TorrentInfo()
|
||||||
{
|
{
|
||||||
@@ -80,7 +85,9 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
|
|||||||
InfoUrl = GetInfoUrl(torrent.GroupId, id),
|
InfoUrl = GetInfoUrl(torrent.GroupId, id),
|
||||||
Seeders = int.Parse(torrent.Seeders),
|
Seeders = int.Parse(torrent.Seeders),
|
||||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||||
PublishDate = torrent.Time.ToUniversalTime()
|
PublishDate = torrent.Time.ToUniversalTime(),
|
||||||
|
ImdbId = int.Parse(torrent.ImdbId.Substring(2)),
|
||||||
|
IndexerFlags = flags,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ namespace NzbDrone.Core.Indexers.HDBits
|
|||||||
|
|
||||||
public class ImdbInfo
|
public class ImdbInfo
|
||||||
{
|
{
|
||||||
public int? Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string EnglishTitle { get; set; }
|
public string EnglishTitle { get; set; }
|
||||||
public string OriginalTitle { get; set; }
|
public string OriginalTitle { get; set; }
|
||||||
public int? Year { get; set; }
|
public int? Year { get; set; }
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.HDBits
|
namespace NzbDrone.Core.Indexers.HDBits
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,6 +53,18 @@ namespace NzbDrone.Core.Indexers.HDBits
|
|||||||
var id = result.Id;
|
var id = result.Id;
|
||||||
var internalRelease = (result.TypeOrigin == 1 ? true : false);
|
var internalRelease = (result.TypeOrigin == 1 ? true : false);
|
||||||
|
|
||||||
|
IndexerFlags flags = 0;
|
||||||
|
|
||||||
|
if (result.FreeLeech == "yes")
|
||||||
|
{
|
||||||
|
flags |= IndexerFlags.G_Freeleech;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (internalRelease)
|
||||||
|
{
|
||||||
|
flags |= IndexerFlags.HDB_Internal;
|
||||||
|
}
|
||||||
|
|
||||||
torrentInfos.Add(new HDBitsInfo()
|
torrentInfos.Add(new HDBitsInfo()
|
||||||
{
|
{
|
||||||
Guid = string.Format("HDBits-{0}", id),
|
Guid = string.Format("HDBits-{0}", id),
|
||||||
@@ -64,7 +76,9 @@ namespace NzbDrone.Core.Indexers.HDBits
|
|||||||
Seeders = result.Seeders,
|
Seeders = result.Seeders,
|
||||||
Peers = result.Leechers + result.Seeders,
|
Peers = result.Leechers + result.Seeders,
|
||||||
PublishDate = result.Added.ToUniversalTime(),
|
PublishDate = result.Added.ToUniversalTime(),
|
||||||
Internal = internalRelease
|
Internal = internalRelease,
|
||||||
|
ImdbId = result.ImdbInfo?.Id ?? 0,
|
||||||
|
IndexerFlags = flags
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Xml;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
@@ -49,15 +51,30 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
|
|
||||||
var request = new HttpRequest(url, HttpAccept.Rss);
|
var request = new HttpRequest(url, HttpAccept.Rss);
|
||||||
|
|
||||||
|
HttpResponse response;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = _httpClient.Get(request);
|
response = _httpClient.Get(request);
|
||||||
|
|
||||||
capabilities = ParseCapabilities(response);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Debug(ex, string.Format("Failed to get capabilities from {0}: {1}", indexerSettings.Url, ex.Message));
|
_logger.Debug(ex, "Failed to get newznab api capabilities from {0}", indexerSettings.Url);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
capabilities = ParseCapabilities(response);
|
||||||
|
}
|
||||||
|
catch (XmlException ex)
|
||||||
|
{
|
||||||
|
_logger.Debug(ex, "Failed to parse newznab api capabilities for {0}.", indexerSettings.Url);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, "Failed to determine newznab api capabilities for {0}, using the defaults instead till Sonarr restarts.", indexerSettings.Url);
|
||||||
}
|
}
|
||||||
|
|
||||||
return capabilities;
|
return capabilities;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
if (SupportsMovieSearch)
|
if (SupportsMovieSearch && searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "movie", $"&imdbid={searchCriteria.Movie.ImdbId.Substring(2)}"));
|
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "movie", $"&imdbid={searchCriteria.Movie.ImdbId.Substring(2)}"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
public string ReleaseName { get; set; }
|
public string ReleaseName { get; set; }
|
||||||
public bool Checked { get; set; }
|
public bool Checked { get; set; }
|
||||||
public bool GoldenPopcorn { get; set; }
|
public bool GoldenPopcorn { get; set; }
|
||||||
|
public string FreeleechType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Movie
|
public class Movie
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
@@ -41,8 +41,8 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
}
|
}
|
||||||
|
|
||||||
var jsonResponse = JsonConvert.DeserializeObject<PassThePopcornResponse>(indexerResponse.Content);
|
var jsonResponse = JsonConvert.DeserializeObject<PassThePopcornResponse>(indexerResponse.Content);
|
||||||
if (jsonResponse.TotalResults == "0" ||
|
if (jsonResponse.TotalResults == "0" ||
|
||||||
jsonResponse.TotalResults.IsNullOrWhiteSpace() ||
|
jsonResponse.TotalResults.IsNullOrWhiteSpace() ||
|
||||||
jsonResponse.Movies == null)
|
jsonResponse.Movies == null)
|
||||||
{
|
{
|
||||||
throw new IndexerException(indexerResponse, "No results were found");
|
throw new IndexerException(indexerResponse, "No results were found");
|
||||||
@@ -55,58 +55,69 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
{
|
{
|
||||||
var id = torrent.Id;
|
var id = torrent.Id;
|
||||||
var title = torrent.ReleaseName;
|
var title = torrent.ReleaseName;
|
||||||
|
IndexerFlags flags = 0;
|
||||||
|
|
||||||
if (torrent.GoldenPopcorn)
|
if (torrent.GoldenPopcorn)
|
||||||
{
|
{
|
||||||
title = $"{title} 🍿";
|
flags |= IndexerFlags.PTP_Golden;//title = $"{title} 🍿";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torrent.Checked)
|
if (torrent.Checked)
|
||||||
{
|
{
|
||||||
title = $"{title} ✔";
|
flags |= IndexerFlags.PTP_Approved;//title = $"{title} ✔";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (torrent.FreeleechType == "Freeleech")
|
||||||
|
{
|
||||||
|
flags |= IndexerFlags.G_Freeleech;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only add approved torrents
|
// Only add approved torrents
|
||||||
if (_settings.RequireApproved && torrent.Checked)
|
if (_settings.RequireApproved && torrent.Checked)
|
||||||
{
|
|
||||||
torrentInfos.Add(new PassThePopcornInfo()
|
|
||||||
{
|
{
|
||||||
Guid = string.Format("PassThePopcorn-{0}", id),
|
torrentInfos.Add(new PassThePopcornInfo()
|
||||||
Title = title,
|
{
|
||||||
Size = long.Parse(torrent.Size),
|
Guid = string.Format("PassThePopcorn-{0}", id),
|
||||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
Title = title,
|
||||||
InfoUrl = GetInfoUrl(result.GroupId, id),
|
Size = long.Parse(torrent.Size),
|
||||||
Seeders = int.Parse(torrent.Seeders),
|
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
||||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
InfoUrl = GetInfoUrl(result.GroupId, id),
|
||||||
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
Seeders = int.Parse(torrent.Seeders),
|
||||||
Golden = torrent.GoldenPopcorn,
|
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||||
Scene = torrent.Scene,
|
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
||||||
Approved = torrent.Checked
|
Golden = torrent.GoldenPopcorn,
|
||||||
});
|
Scene = torrent.Scene,
|
||||||
}
|
Approved = torrent.Checked,
|
||||||
// Add all torrents
|
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
|
||||||
else if (!_settings.RequireApproved)
|
IndexerFlags = flags
|
||||||
{
|
});
|
||||||
torrentInfos.Add(new PassThePopcornInfo()
|
}
|
||||||
|
|
||||||
|
// Add all torrents
|
||||||
|
else if (!_settings.RequireApproved)
|
||||||
{
|
{
|
||||||
Guid = string.Format("PassThePopcorn-{0}", id),
|
torrentInfos.Add(new PassThePopcornInfo()
|
||||||
Title = title,
|
{
|
||||||
Size = long.Parse(torrent.Size),
|
Guid = string.Format("PassThePopcorn-{0}", id),
|
||||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
Title = title,
|
||||||
InfoUrl = GetInfoUrl(result.GroupId, id),
|
Size = long.Parse(torrent.Size),
|
||||||
Seeders = int.Parse(torrent.Seeders),
|
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
||||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
InfoUrl = GetInfoUrl(result.GroupId, id),
|
||||||
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
Seeders = int.Parse(torrent.Seeders),
|
||||||
Golden = torrent.GoldenPopcorn,
|
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||||
Scene = torrent.Scene,
|
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
||||||
Approved = torrent.Checked
|
Golden = torrent.GoldenPopcorn,
|
||||||
});
|
Scene = torrent.Scene,
|
||||||
}
|
Approved = torrent.Checked,
|
||||||
// Don't add any torrents
|
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
|
||||||
else if (_settings.RequireApproved && !torrent.Checked)
|
IndexerFlags = flags
|
||||||
{
|
});
|
||||||
continue;
|
}
|
||||||
}
|
// Don't add any torrents
|
||||||
|
else if (_settings.RequireApproved && !torrent.Checked)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,10 +129,10 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
return
|
return
|
||||||
torrentInfos.OrderByDescending(o => o.PublishDate)
|
torrentInfos.OrderByDescending(o => o.PublishDate)
|
||||||
.ThenBy(o => ((dynamic)o).Golden ? 0 : 1)
|
.ThenBy(o => ((dynamic)o).Golden ? 0 : 1)
|
||||||
.ThenBy(o => ((dynamic) o).Scene ? 0 : 1)
|
.ThenBy(o => ((dynamic)o).Scene ? 0 : 1)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
torrentInfos.OrderByDescending(o => o.PublishDate)
|
torrentInfos.OrderByDescending(o => o.PublishDate)
|
||||||
.ThenBy(o => ((dynamic)o).Golden ? 0 : 1)
|
.ThenBy(o => ((dynamic)o).Golden ? 0 : 1)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@@ -130,14 +141,14 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
// prefer scene
|
// prefer scene
|
||||||
if (_settings.Scene)
|
if (_settings.Scene)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
torrentInfos.OrderByDescending(o => o.PublishDate)
|
torrentInfos.OrderByDescending(o => o.PublishDate)
|
||||||
.ThenBy(o => ((dynamic)o).Scene ? 0 : 1)
|
.ThenBy(o => ((dynamic)o).Scene ? 0 : 1)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
// order by date
|
// order by date
|
||||||
return
|
return
|
||||||
torrentInfos
|
torrentInfos
|
||||||
.OrderByDescending(o => o.PublishDate)
|
.OrderByDescending(o => o.PublishDate)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ namespace NzbDrone.Core.Indexers.Torznab
|
|||||||
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
|
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
torrentInfo.IndexerFlags = GetFlags(item);
|
||||||
|
|
||||||
return torrentInfo;
|
return torrentInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +154,32 @@ namespace NzbDrone.Core.Indexers.Torznab
|
|||||||
return base.GetPeers(item);
|
return base.GetPeers(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected IndexerFlags GetFlags(XElement item)
|
||||||
|
{
|
||||||
|
IndexerFlags flags = 0;
|
||||||
|
|
||||||
|
var downloadFactor = TryGetFloatTorznabAttribute(item, "downloadvolumefactor", 1);
|
||||||
|
|
||||||
|
var uploadFactor = TryGetFloatTorznabAttribute(item, "uploadvolumefactor", 1);
|
||||||
|
|
||||||
|
if (uploadFactor == 2)
|
||||||
|
{
|
||||||
|
flags |= IndexerFlags.G_DoubleUpload;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloadFactor == 0.5)
|
||||||
|
{
|
||||||
|
flags |= IndexerFlags.G_Halfleech;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloadFactor == 0.0)
|
||||||
|
{
|
||||||
|
flags |= IndexerFlags.G_Freeleech;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
protected string TryGetTorznabAttribute(XElement item, string key, string defaultValue = "")
|
protected string TryGetTorznabAttribute(XElement item, string key, string defaultValue = "")
|
||||||
{
|
{
|
||||||
var attr = item.Elements(ns + "attr").FirstOrDefault(e => e.Attribute("name").Value.Equals(key, StringComparison.CurrentCultureIgnoreCase));
|
var attr = item.Elements(ns + "attr").FirstOrDefault(e => e.Attribute("name").Value.Equals(key, StringComparison.CurrentCultureIgnoreCase));
|
||||||
@@ -160,6 +189,20 @@ namespace NzbDrone.Core.Indexers.Torznab
|
|||||||
return attr.Attribute("value").Value;
|
return attr.Attribute("value").Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float TryGetFloatTorznabAttribute(XElement item, string key, float defaultValue = 0)
|
||||||
|
{
|
||||||
|
var attr = TryGetTorznabAttribute(item, key, defaultValue.ToString());
|
||||||
|
|
||||||
|
float result = 0;
|
||||||
|
|
||||||
|
if (float.TryParse(attr, out result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles.Commands
|
||||||
|
{
|
||||||
|
public class RenameMovieFolderCommand : Command
|
||||||
|
{
|
||||||
|
public List<int> MovieIds { get; set; }
|
||||||
|
|
||||||
|
public override bool SendUpdatesToClient => true;
|
||||||
|
|
||||||
|
public RenameMovieFolderCommand(List<int> ids)
|
||||||
|
{
|
||||||
|
MovieIds = ids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,6 +44,8 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
private readonly IMediaFileTableCleanupService _mediaFileTableCleanupService;
|
private readonly IMediaFileTableCleanupService _mediaFileTableCleanupService;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IMovieService _movieService;
|
private readonly IMovieService _movieService;
|
||||||
|
private readonly IMovieFileRepository _movieFileRepository;
|
||||||
|
private readonly IRenameMovieFileService _renameMovieFiles;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public DiskScanService(IDiskProvider diskProvider,
|
public DiskScanService(IDiskProvider diskProvider,
|
||||||
@@ -55,6 +57,8 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
IMediaFileTableCleanupService mediaFileTableCleanupService,
|
IMediaFileTableCleanupService mediaFileTableCleanupService,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
IMovieService movieService,
|
IMovieService movieService,
|
||||||
|
IMovieFileRepository movieFileRepository,
|
||||||
|
IRenameMovieFileService renameMovieFiles,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
@@ -66,6 +70,8 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
_mediaFileTableCleanupService = mediaFileTableCleanupService;
|
_mediaFileTableCleanupService = mediaFileTableCleanupService;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_movieService = movieService;
|
_movieService = movieService;
|
||||||
|
_movieFileRepository = movieFileRepository;
|
||||||
|
_renameMovieFiles = renameMovieFiles;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,18 +138,21 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
|
|
||||||
public void Scan(Movie movie)
|
public void Scan(Movie movie)
|
||||||
{
|
{
|
||||||
|
//Try renaming the movie path in case anything changed such as year, title or something else.
|
||||||
|
_renameMovieFiles.RenameMoviePath(movie, true);
|
||||||
|
|
||||||
var rootFolder = _diskProvider.GetParentFolder(movie.Path);
|
var rootFolder = _diskProvider.GetParentFolder(movie.Path);
|
||||||
|
|
||||||
if (!_diskProvider.FolderExists(rootFolder))
|
if (!_diskProvider.FolderExists(rootFolder))
|
||||||
{
|
{
|
||||||
_logger.Warn("Series' root folder ({0}) doesn't exist.", rootFolder);
|
_logger.Warn("Movies' root folder ({0}) doesn't exist.", rootFolder);
|
||||||
_eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderDoesNotExist));
|
_eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderDoesNotExist));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_diskProvider.GetDirectories(rootFolder).Empty())
|
if (_diskProvider.GetDirectories(rootFolder).Empty())
|
||||||
{
|
{
|
||||||
_logger.Warn("Series' root folder ({0}) is empty.", rootFolder);
|
_logger.Warn("Movies' root folder ({0}) is empty.", rootFolder);
|
||||||
_eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderIsEmpty));
|
_eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderIsEmpty));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -155,13 +164,20 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
if (_configService.CreateEmptySeriesFolders &&
|
if (_configService.CreateEmptySeriesFolders &&
|
||||||
_diskProvider.FolderExists(rootFolder))
|
_diskProvider.FolderExists(rootFolder))
|
||||||
{
|
{
|
||||||
_logger.Debug("Creating missing series folder: {0}", movie.Path);
|
_logger.Debug("Creating missing movies folder: {0}", movie.Path);
|
||||||
_diskProvider.CreateFolder(movie.Path);
|
_diskProvider.CreateFolder(movie.Path);
|
||||||
SetPermissions(movie.Path);
|
SetPermissions(movie.Path);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Debug("Series folder doesn't exist: {0}", movie.Path);
|
// Delete Movie from MovieFiles
|
||||||
|
_movieFileRepository.Delete(movie.MovieFileId);
|
||||||
|
|
||||||
|
// Update Movie
|
||||||
|
movie.MovieFileId = 0;
|
||||||
|
_movieService.UpdateMovie(movie);
|
||||||
|
|
||||||
|
_logger.Debug("Movies folder doesn't exist: {0}", movie.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.MovieFolderDoesNotExist));
|
_eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.MovieFolderDoesNotExist));
|
||||||
|
|||||||
@@ -135,16 +135,16 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||||||
localMovie.Size = _diskProvider.GetFileSize(file);
|
localMovie.Size = _diskProvider.GetFileSize(file);
|
||||||
|
|
||||||
_logger.Debug("Size: {0}", localMovie.Size);
|
_logger.Debug("Size: {0}", localMovie.Size);
|
||||||
|
var current = localMovie.Quality;
|
||||||
//TODO: make it so media info doesn't ruin the import process of a new series
|
//TODO: make it so media info doesn't ruin the import process of a new series
|
||||||
if (sceneSource)
|
if (sceneSource && ShouldCheckQualityForParsedQuality(current.Quality))
|
||||||
{
|
{
|
||||||
localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
|
localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
|
||||||
if (shouldCheckQuality)
|
if (shouldCheckQuality)
|
||||||
{
|
{
|
||||||
_logger.Debug("Checking quality for this video file to make sure nothing mismatched.");
|
_logger.Debug("Checking quality for this video file to make sure nothing mismatched.");
|
||||||
var width = localMovie.MediaInfo.Width;
|
var width = localMovie.MediaInfo.Width;
|
||||||
var current = localMovie.Quality;
|
|
||||||
var qualityName = current.Quality.Name.ToLower();
|
var qualityName = current.Quality.Name.ToLower();
|
||||||
QualityModel updated = null;
|
QualityModel updated = null;
|
||||||
if (width > 2000)
|
if (width > 2000)
|
||||||
@@ -565,5 +565,20 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ShouldCheckQualityForParsedQuality(Quality quality)
|
||||||
|
{
|
||||||
|
List<Quality> shouldNotCheck = new List<Quality> { Quality.WORKPRINT, Quality.TELECINE, Quality.TELESYNC,
|
||||||
|
Quality.DVDSCR, Quality.DVD, Quality.CAM, Quality.DVDR, Quality.Remux1080p, Quality.Remux2160p, Quality.REGIONAL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (shouldNotCheck.Contains(quality))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using NzbDrone.Common.Messaging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles.Events
|
||||||
|
{
|
||||||
|
public class MovieFileUpdatedEvent : IEvent
|
||||||
|
{
|
||||||
|
public MovieFile MovieFile { get; private set; }
|
||||||
|
|
||||||
|
public MovieFileUpdatedEvent(MovieFile movieFile)
|
||||||
|
{
|
||||||
|
MovieFile = movieFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -189,6 +189,11 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
|||||||
|
|
||||||
public int Open(Stream stream)
|
public int Open(Stream stream)
|
||||||
{
|
{
|
||||||
|
if (stream.Length < 1024)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
var isValid = (int)MediaInfo_Open_Buffer_Init(_handle, stream.Length, 0);
|
var isValid = (int)MediaInfo_Open_Buffer_Init(_handle, stream.Length, 0);
|
||||||
if (isValid == 1)
|
if (isValid == 1)
|
||||||
{
|
{
|
||||||
@@ -203,7 +208,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
|||||||
totalRead += bufferRead;
|
totalRead += bufferRead;
|
||||||
|
|
||||||
var status = (BufferStatus)MediaInfo_Open_Buffer_Continue(_handle, buffer, (IntPtr)bufferRead);
|
var status = (BufferStatus)MediaInfo_Open_Buffer_Continue(_handle, buffer, (IntPtr)bufferRead);
|
||||||
|
|
||||||
if (status.HasFlag(BufferStatus.Finalized) || status <= 0 || bufferRead == 0)
|
if (status.HasFlag(BufferStatus.Finalized) || status <= 0 || bufferRead == 0)
|
||||||
{
|
{
|
||||||
Logger.Trace("Read file offset {0}-{1} ({2} bytes)", seekStart, stream.Position, stream.Position - seekStart);
|
Logger.Trace("Read file offset {0}-{1} ({2} bytes)", seekStart, stream.Position, stream.Position - seekStart);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
private readonly IDiskTransferService _diskTransferService;
|
private readonly IDiskTransferService _diskTransferService;
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly IMediaFileAttributeService _mediaFileAttributeService;
|
private readonly IMediaFileAttributeService _mediaFileAttributeService;
|
||||||
|
private readonly IRecycleBinProvider _recycleBinProvider;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
@@ -40,6 +41,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
IDiskTransferService diskTransferService,
|
IDiskTransferService diskTransferService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
IMediaFileAttributeService mediaFileAttributeService,
|
IMediaFileAttributeService mediaFileAttributeService,
|
||||||
|
IRecycleBinProvider recycleBinProvider,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
@@ -50,6 +52,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
_diskTransferService = diskTransferService;
|
_diskTransferService = diskTransferService;
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_mediaFileAttributeService = mediaFileAttributeService;
|
_mediaFileAttributeService = mediaFileAttributeService;
|
||||||
|
_recycleBinProvider = recycleBinProvider;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -116,6 +119,15 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
|
|
||||||
_diskTransferService.TransferFile(movieFilePath, destinationFilePath, mode);
|
_diskTransferService.TransferFile(movieFilePath, destinationFilePath, mode);
|
||||||
|
|
||||||
|
var oldMoviePath = movie.Path;
|
||||||
|
|
||||||
|
var newMoviePath = new OsPath(destinationFilePath).Directory.FullPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||||
|
movie.Path = newMoviePath;
|
||||||
|
if (oldMoviePath != newMoviePath)
|
||||||
|
{
|
||||||
|
_movieService.UpdateMovie(movie);
|
||||||
|
}
|
||||||
|
|
||||||
movieFile.RelativePath = movie.Path.GetRelativePath(destinationFilePath);
|
movieFile.RelativePath = movie.Path.GetRelativePath(destinationFilePath);
|
||||||
|
|
||||||
_updateMovieFileService.ChangeFileDateForFile(movieFile, movie);
|
_updateMovieFileService.ChangeFileDateForFile(movieFile, movie);
|
||||||
@@ -132,6 +144,14 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
|
|
||||||
_mediaFileAttributeService.SetFilePermissions(destinationFilePath);
|
_mediaFileAttributeService.SetFilePermissions(destinationFilePath);
|
||||||
|
|
||||||
|
if(oldMoviePath != newMoviePath)
|
||||||
|
{
|
||||||
|
if (_diskProvider.GetFiles(oldMoviePath, SearchOption.AllDirectories).Count() == 0)
|
||||||
|
{
|
||||||
|
_recycleBinProvider.DeleteFolder(oldMoviePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return movieFile;
|
return movieFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +163,9 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
private void EnsureMovieFolder(MovieFile movieFile, Movie movie, string filePath)
|
private void EnsureMovieFolder(MovieFile movieFile, Movie movie, string filePath)
|
||||||
{
|
{
|
||||||
var movieFolder = Path.GetDirectoryName(filePath);
|
var movieFolder = Path.GetDirectoryName(filePath);
|
||||||
|
movie.Path = movieFolder;
|
||||||
var rootFolder = new OsPath(movieFolder).Directory.FullPath;
|
var rootFolder = new OsPath(movieFolder).Directory.FullPath;
|
||||||
|
var fileName = Path.GetFileName(filePath);
|
||||||
|
|
||||||
if (!_diskProvider.FolderExists(rootFolder))
|
if (!_diskProvider.FolderExists(rootFolder))
|
||||||
{
|
{
|
||||||
@@ -156,7 +178,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
if (!_diskProvider.FolderExists(movieFolder))
|
if (!_diskProvider.FolderExists(movieFolder))
|
||||||
{
|
{
|
||||||
CreateFolder(movieFolder);
|
CreateFolder(movieFolder);
|
||||||
newEvent.SeriesFolder = movieFolder;
|
newEvent.MovieFolder = movieFolder;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,23 +13,29 @@ using NzbDrone.Common.Extensions;
|
|||||||
using NzbDrone.Common.Instrumentation.Extensions;
|
using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles
|
namespace NzbDrone.Core.MediaFiles
|
||||||
{
|
{
|
||||||
public interface IRenameMovieFileService
|
public interface IRenameMovieFileService
|
||||||
{
|
{
|
||||||
List<RenameMovieFilePreview> GetRenamePreviews(int movieId);
|
List<RenameMovieFilePreview> GetRenamePreviews(int movieId);
|
||||||
|
void RenameMoviePath(Movie movie, bool shouldRenameFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RenameMovieFileService : IRenameMovieFileService,
|
public class RenameMovieFileService : IRenameMovieFileService,
|
||||||
IExecute<RenameMovieFilesCommand>,
|
IExecute<RenameMovieFilesCommand>,
|
||||||
IExecute<RenameMovieCommand>
|
IExecute<RenameMovieCommand>,
|
||||||
|
IExecute<RenameMovieFolderCommand>
|
||||||
{
|
{
|
||||||
private readonly IMovieService _movieService;
|
private readonly IMovieService _movieService;
|
||||||
private readonly IMediaFileService _mediaFileService;
|
private readonly IMediaFileService _mediaFileService;
|
||||||
private readonly IMoveMovieFiles _movieFileMover;
|
private readonly IMoveMovieFiles _movieFileMover;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IBuildFileNames _filenameBuilder;
|
private readonly IBuildFileNames _filenameBuilder;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly IRecycleBinProvider _recycleBinProvider;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public RenameMovieFileService(IMovieService movieService,
|
public RenameMovieFileService(IMovieService movieService,
|
||||||
@@ -37,6 +43,9 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
IMoveMovieFiles movieFileMover,
|
IMoveMovieFiles movieFileMover,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
IBuildFileNames filenameBuilder,
|
IBuildFileNames filenameBuilder,
|
||||||
|
IConfigService configService,
|
||||||
|
IRecycleBinProvider recycleBinProvider,
|
||||||
|
IDiskProvider diskProvider,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_movieService = movieService;
|
_movieService = movieService;
|
||||||
@@ -44,6 +53,9 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
_movieFileMover = movieFileMover;
|
_movieFileMover = movieFileMover;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_filenameBuilder = filenameBuilder;
|
_filenameBuilder = filenameBuilder;
|
||||||
|
_configService = configService;
|
||||||
|
_recycleBinProvider = recycleBinProvider;
|
||||||
|
_diskProvider = diskProvider;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,8 +83,9 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
{
|
{
|
||||||
MovieId = movie.Id,
|
MovieId = movie.Id,
|
||||||
MovieFileId = file.Id,
|
MovieFileId = file.Id,
|
||||||
ExistingPath = file.RelativePath,
|
ExistingPath = movieFilePath,
|
||||||
NewPath = movie.Path.GetRelativePath(newPath)
|
//NewPath = movie.Path.GetRelativePath(newPath)
|
||||||
|
NewPath = newPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,13 +93,19 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenameFiles(List<MovieFile> movieFiles, Movie movie)
|
private void RenameFiles(List<MovieFile> movieFiles, Movie movie, string oldMoviePath = null)
|
||||||
{
|
{
|
||||||
var renamed = new List<MovieFile>();
|
var renamed = new List<MovieFile>();
|
||||||
|
|
||||||
foreach(var movieFile in movieFiles)
|
if (oldMoviePath == null)
|
||||||
{
|
{
|
||||||
var movieFilePath = Path.Combine(movie.Path, movieFile.RelativePath);
|
oldMoviePath = movie.Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var movieFile in movieFiles)
|
||||||
|
{
|
||||||
|
var oldMovieFilePath = Path.Combine(oldMoviePath, movieFile.RelativePath);
|
||||||
|
movieFile.Path = oldMovieFilePath;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -94,22 +113,64 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
_movieFileMover.MoveMovieFile(movieFile, movie);
|
_movieFileMover.MoveMovieFile(movieFile, movie);
|
||||||
|
|
||||||
_mediaFileService.Update(movieFile);
|
_mediaFileService.Update(movieFile);
|
||||||
|
_movieService.UpdateMovie(movie);
|
||||||
renamed.Add(movieFile);
|
renamed.Add(movieFile);
|
||||||
|
|
||||||
_logger.Debug("Renamed movie file: {0}", movieFile);
|
_logger.Debug("Renamed movie file: {0}", movieFile);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(SameFilenameException ex)
|
catch (SameFilenameException ex)
|
||||||
{
|
{
|
||||||
_logger.Debug("File not renamed, source and destination are the same: {0}", ex.Filename);
|
_logger.Debug("File not renamed, source and destination are the same: {0}", ex.Filename);
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error(ex, "Failed to rename file: " + movieFilePath);
|
_logger.Error(ex, "Failed to rename file: " + oldMovieFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RenameMoviePath(Movie movie, bool shouldRenameFiles = true)
|
||||||
|
{
|
||||||
|
var newFolder = _filenameBuilder.BuildMoviePath(movie);
|
||||||
|
if (newFolder != movie.Path && movie.PathState == MoviePathState.Dynamic)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!_configService.AutoRenameFolders)
|
||||||
|
{
|
||||||
|
_logger.Info("{0}'s movie should be {1} according to your naming config.", movie, newFolder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Info("{0}'s movie folder changed to: {1}", movie, newFolder);
|
||||||
|
var oldFolder = movie.Path;
|
||||||
|
movie.Path = newFolder;
|
||||||
|
|
||||||
|
if (shouldRenameFiles)
|
||||||
|
{
|
||||||
|
var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
|
||||||
|
_logger.ProgressInfo("Renaming movie files for {0}", movie.Title);
|
||||||
|
RenameFiles(movieFiles, movie, oldFolder);
|
||||||
|
_logger.ProgressInfo("All movie files renamed for {0}", movie.Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
_movieService.UpdateMovie(movie);
|
||||||
|
|
||||||
|
if (_diskProvider.GetFiles(oldFolder, SearchOption.AllDirectories).Count() == 0)
|
||||||
|
{
|
||||||
|
_recycleBinProvider.DeleteFolder(oldFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movie.PathState == MoviePathState.StaticOnce)
|
||||||
|
{
|
||||||
|
movie.PathState = MoviePathState.Dynamic;
|
||||||
|
_movieService.UpdateMovie(movie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Execute(RenameMovieFilesCommand message)
|
public void Execute(RenameMovieFilesCommand message)
|
||||||
{
|
{
|
||||||
var movie = _movieService.GetMovie(message.MovieId);
|
var movie = _movieService.GetMovie(message.MovieId);
|
||||||
@@ -134,5 +195,17 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Execute(RenameMovieFolderCommand message)
|
||||||
|
{
|
||||||
|
_logger.Debug("Renaming movie folder for selected movie if necessary");
|
||||||
|
var moviesToRename = _movieService.GetMovies(message.MovieIds);
|
||||||
|
foreach(var movie in moviesToRename)
|
||||||
|
{
|
||||||
|
var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
|
||||||
|
_logger.ProgressInfo("Renaming movie folder for {0}", movie.Title);
|
||||||
|
RenameMoviePath(movie);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
private readonly IMediaFileService _mediaFileService;
|
private readonly IMediaFileService _mediaFileService;
|
||||||
private readonly IMoveEpisodeFiles _episodeFileMover;
|
private readonly IMoveEpisodeFiles _episodeFileMover;
|
||||||
private readonly IMoveMovieFiles _movieFileMover;
|
private readonly IMoveMovieFiles _movieFileMover;
|
||||||
|
private readonly IRenameMovieFileService _movieFileRenamer;
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
IMoveEpisodeFiles episodeFileMover,
|
IMoveEpisodeFiles episodeFileMover,
|
||||||
IMoveMovieFiles movieFileMover,
|
IMoveMovieFiles movieFileMover,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
|
IRenameMovieFileService movieFileRenamer,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_recycleBinProvider = recycleBinProvider;
|
_recycleBinProvider = recycleBinProvider;
|
||||||
@@ -33,6 +35,7 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
_episodeFileMover = episodeFileMover;
|
_episodeFileMover = episodeFileMover;
|
||||||
_movieFileMover = movieFileMover;
|
_movieFileMover = movieFileMover;
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
|
_movieFileRenamer = movieFileRenamer;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +60,10 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
_mediaFileService.Delete(existingFile, DeleteMediaFileReason.Upgrade);
|
_mediaFileService.Delete(existingFile, DeleteMediaFileReason.Upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Temporary for correctly getting path
|
||||||
|
localMovie.Movie.MovieFileId = 1;
|
||||||
|
localMovie.Movie.MovieFile = movieFile;
|
||||||
|
|
||||||
if (copyOnly)
|
if (copyOnly)
|
||||||
{
|
{
|
||||||
moveFileResult.MovieFile = _movieFileMover.CopyMovieFile(movieFile, localMovie);
|
moveFileResult.MovieFile = _movieFileMover.CopyMovieFile(movieFile, localMovie);
|
||||||
@@ -66,6 +73,8 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
moveFileResult.MovieFile = _movieFileMover.MoveMovieFile(movieFile, localMovie);
|
moveFileResult.MovieFile = _movieFileMover.MoveMovieFile(movieFile, localMovie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//_movieFileRenamer.RenameMoviePath(localMovie.Movie, false);
|
||||||
|
|
||||||
return moveFileResult;
|
return moveFileResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MetadataSource
|
||||||
|
{
|
||||||
|
public interface IDiscoverNewMovies
|
||||||
|
{
|
||||||
|
List<Movie> DiscoverNewMovies(string action);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,6 +62,7 @@ namespace NzbDrone.Core.MetadataSource.PreDB
|
|||||||
|
|
||||||
private List<PreDBResult> GetResults(string category = "", string search = "")
|
private List<PreDBResult> GetResults(string category = "", string search = "")
|
||||||
{
|
{
|
||||||
|
return new List<PreDBResult>();
|
||||||
var builder = new HttpRequestBuilder("http://predb.me").AddQueryParam("rss", "1");
|
var builder = new HttpRequestBuilder("http://predb.me").AddQueryParam("rss", "1");
|
||||||
if (category.IsNotNullOrWhiteSpace())
|
if (category.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
@@ -171,10 +172,12 @@ namespace NzbDrone.Core.MetadataSource.PreDB
|
|||||||
|
|
||||||
public bool HasReleases(Movie movie)
|
public bool HasReleases(Movie movie)
|
||||||
{
|
{
|
||||||
var results = GetResults("movies", movie.Title);
|
try
|
||||||
|
{
|
||||||
|
var results = GetResults("movies", movie.Title);
|
||||||
|
|
||||||
foreach (PreDBResult result in results)
|
foreach (PreDBResult result in results)
|
||||||
{
|
{
|
||||||
var parsed = Parser.Parser.ParseMovieTitle(result.Title);
|
var parsed = Parser.Parser.ParseMovieTitle(result.Title);
|
||||||
if (parsed == null)
|
if (parsed == null)
|
||||||
{
|
{
|
||||||
@@ -182,13 +185,20 @@ namespace NzbDrone.Core.MetadataSource.PreDB
|
|||||||
}
|
}
|
||||||
var match = _parsingService.Map(parsed, "", new MovieSearchCriteria { Movie = movie });
|
var match = _parsingService.Map(parsed, "", new MovieSearchCriteria { Movie = movie });
|
||||||
|
|
||||||
if (match != null && match.Movie != null && match.Movie.Id == movie.Id)
|
if (match != null && match.Movie != null && match.Movie.Id == movie.Id)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warn(ex, "Error while looking on predb.me.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user