Compare commits
364 Commits
v0.2.0.134
...
v0.2.0.375
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89e5001bad | ||
|
|
056fb154a8 | ||
|
|
3edc2b80cf | ||
|
|
a1745cd02e | ||
|
|
1c0f9b64ca | ||
|
|
7d6a518f30 | ||
|
|
9f2fcebc24 | ||
|
|
91295f50b0 | ||
|
|
68bf97f52c | ||
|
|
363048e68e | ||
|
|
9c20c0b889 | ||
|
|
50891e5dd7 | ||
|
|
f393a95501 | ||
|
|
a68dd6d2f7 | ||
|
|
dadf6708ab | ||
|
|
7a86c78896 | ||
|
|
81688399c0 | ||
|
|
1e28a2e5d4 | ||
|
|
c5bb259555 | ||
|
|
0d5d75d6ea | ||
|
|
5bae9bbbcc | ||
|
|
a3e681078f | ||
|
|
758228e159 | ||
|
|
1b900a006f | ||
|
|
9b5c5169ef | ||
|
|
e78a55ac6e | ||
|
|
e82cf70399 | ||
|
|
e7d65ee4ae | ||
|
|
1db3669afa | ||
|
|
93e55b7575 | ||
|
|
f850c65b56 | ||
|
|
297348fffe | ||
|
|
07ff6558d1 | ||
|
|
85843efcb0 | ||
|
|
3d4b1c3be5 | ||
|
|
a3f389af5e | ||
|
|
1aeb3c6fd6 | ||
|
|
6ab6c016c0 | ||
|
|
a1961603d7 | ||
|
|
50ac95dec5 | ||
|
|
a16e46cf38 | ||
|
|
ea33b75764 | ||
|
|
31e657d052 | ||
|
|
fe0dfef83c | ||
|
|
bc1a47ff5a | ||
|
|
4e8089dd42 | ||
|
|
6dc9f90a8b | ||
|
|
1aae3ae2b5 | ||
|
|
75436bcce4 | ||
|
|
61df3ef40e | ||
|
|
f45aab27d1 | ||
|
|
f477c46406 | ||
|
|
2af07d7e0d | ||
|
|
df691488a9 | ||
|
|
800e7ae508 | ||
|
|
fcf156293e | ||
|
|
94f44a0eb7 | ||
|
|
1e2c28f67a | ||
|
|
62b45f7ea7 | ||
|
|
f577590ad6 | ||
|
|
0941247f63 | ||
|
|
3170060f37 | ||
|
|
35b384439f | ||
|
|
0d1150d4d2 | ||
|
|
1f68b46575 | ||
|
|
32c5c4d741 | ||
|
|
0cb15121e5 | ||
|
|
808033a01c | ||
|
|
736e0d2e70 | ||
|
|
96741570c5 | ||
|
|
8feb3fee98 | ||
|
|
07e3e44a68 | ||
|
|
d67d405024 | ||
|
|
520836f475 | ||
|
|
6d6bf1044b | ||
|
|
195866f3aa | ||
|
|
10f0be0708 | ||
|
|
721773ef68 | ||
|
|
0d647ffb9a | ||
|
|
b6235e99c8 | ||
|
|
1d0a6af7d7 | ||
|
|
efd7af165c | ||
|
|
3f4ee6d841 | ||
|
|
55c437d980 | ||
|
|
ecfe103c50 | ||
|
|
a282ad7809 | ||
|
|
64176b8d26 | ||
|
|
278fb298b6 | ||
|
|
1d1b88cf05 | ||
|
|
0c50aa7872 | ||
|
|
0bfa01f072 | ||
|
|
3e9594f069 | ||
|
|
a07138680b | ||
|
|
5f6f2f2859 | ||
|
|
e185ba0191 | ||
|
|
3ab0b17379 | ||
|
|
942d97931e | ||
|
|
40809f1d91 | ||
|
|
f6a37186aa | ||
|
|
9522bf3095 | ||
|
|
c3c7387390 | ||
|
|
09fb58c3e9 | ||
|
|
3d33e630ec | ||
|
|
b51916fb2b | ||
|
|
c9ee92cc30 | ||
|
|
0e81416c2f | ||
|
|
6cd7d46208 | ||
|
|
6af6da16b4 | ||
|
|
4c5900373d | ||
|
|
2fd167c446 | ||
|
|
31149aeed9 | ||
|
|
977b87cbf3 | ||
|
|
42ed4ff48a | ||
|
|
060c71f439 | ||
|
|
63527858e7 | ||
|
|
2f4ea9cac7 | ||
|
|
a1f2369306 | ||
|
|
a35c5f79c1 | ||
|
|
d382e15749 | ||
|
|
5b7d513986 | ||
|
|
be083cfd53 | ||
|
|
f9844c284a | ||
|
|
e8065d07b3 | ||
|
|
8a0820ad1e | ||
|
|
8274cc016f | ||
|
|
b88281b458 | ||
|
|
a1cb5eb420 | ||
|
|
d458c4ecc8 | ||
|
|
b6e4f53597 | ||
|
|
4abbf55ee4 | ||
|
|
1fd909cff6 | ||
|
|
7ca53d1073 | ||
|
|
2bda0f700c | ||
|
|
16b2cc49d4 | ||
|
|
e3e67d1098 | ||
|
|
3276e3ec52 | ||
|
|
5e9a79afe8 | ||
|
|
c6912a193c | ||
|
|
47083e6be1 | ||
|
|
ca78cc5c3c | ||
|
|
76db305ffa | ||
|
|
5d2ef4786b | ||
|
|
9953a5ed06 | ||
|
|
dd194d41be | ||
|
|
8168cf82c5 | ||
|
|
e2d6e39168 | ||
|
|
a340bc4da3 | ||
|
|
4bcb0e17f8 | ||
|
|
25a51df894 | ||
|
|
f9c6ffcdaa | ||
|
|
b76c54ceac | ||
|
|
4be7772d53 | ||
|
|
cbc70a8ff3 | ||
|
|
dd8af0ad8c | ||
|
|
00541e6cc1 | ||
|
|
a8eec60c9d | ||
|
|
7bb319b6d6 | ||
|
|
50a5a2de9b | ||
|
|
dbe5946d10 | ||
|
|
d5caac5d3b | ||
|
|
487c5e22ce | ||
|
|
6efd63a292 | ||
|
|
f31dc3c054 | ||
|
|
c60be3a467 | ||
|
|
44b4e71c05 | ||
|
|
5ebd035b1c | ||
|
|
d50514f8bc | ||
|
|
7da2183080 | ||
|
|
a417ac2716 | ||
|
|
a89e662721 | ||
|
|
72aac6e551 | ||
|
|
4b1e4eecfb | ||
|
|
8e452f8b6d | ||
|
|
7e6db89eff | ||
|
|
16214e666b | ||
|
|
2b25ce237f | ||
|
|
f0a9955447 | ||
|
|
d0439296fe | ||
|
|
e2c2bdb65b | ||
|
|
bc3fdb0f80 | ||
|
|
186b2ada36 | ||
|
|
577125f345 | ||
|
|
687dd8a05f | ||
|
|
81861c6121 | ||
|
|
302462f48c | ||
|
|
d132f55830 | ||
|
|
6bbd64e59a | ||
|
|
290c4e1f2e | ||
|
|
1112616514 | ||
|
|
7fddbca4b7 | ||
|
|
692841478c | ||
|
|
23232b9830 | ||
|
|
b886566b25 | ||
|
|
2c56d60678 | ||
|
|
a0c8127ecf | ||
|
|
05f61df59e | ||
|
|
a0b80ad41a | ||
|
|
9e7cb708bf | ||
|
|
95d97c59d7 | ||
|
|
a75f3e1f8e | ||
|
|
d09d30544f | ||
|
|
1ad4006819 | ||
|
|
43d904d20b | ||
|
|
5339f8efdc | ||
|
|
b273bfb10e | ||
|
|
244e82722d | ||
|
|
e182d8b964 | ||
|
|
02e610a5f2 | ||
|
|
032bc2d5c4 | ||
|
|
e59db74cad | ||
|
|
fbe9ad6582 | ||
|
|
87da542758 | ||
|
|
b2317ada1f | ||
|
|
336aee7fda | ||
|
|
9e7468d723 | ||
|
|
f05ee13206 | ||
|
|
8b3b46b724 | ||
|
|
80e53f209d | ||
|
|
82f29cdc70 | ||
|
|
93d6505f85 | ||
|
|
2b7afd3272 | ||
|
|
6d4e1f6c2e | ||
|
|
2b579eb0d3 | ||
|
|
c0f323b05a | ||
|
|
791121fa06 | ||
|
|
f25d4463f5 | ||
|
|
f0bcb27beb | ||
|
|
00099a5e40 | ||
|
|
7c251157ed | ||
|
|
ec6b389d75 | ||
|
|
f38430d632 | ||
|
|
266f28883a | ||
|
|
cc3c2533fa | ||
|
|
f8162b34f2 | ||
|
|
3ff5b36d29 | ||
|
|
1fa736c6d8 | ||
|
|
309877bf76 | ||
|
|
a50b20a397 | ||
|
|
de5489ae9a | ||
|
|
12e74aa38b | ||
|
|
94eccc6c14 | ||
|
|
80ec66b47c | ||
|
|
9fffcfaea3 | ||
|
|
f481676c81 | ||
|
|
76a42b28f3 | ||
|
|
ad26e48408 | ||
|
|
0bab97e02f | ||
|
|
2413457323 | ||
|
|
585fd87ad6 | ||
|
|
ec5161e848 | ||
|
|
0ec54daaff | ||
|
|
bfcd05206f | ||
|
|
ddf10ed137 | ||
|
|
3ed1bebb7d | ||
|
|
b4d1c0e053 | ||
|
|
68f58fb37d | ||
|
|
f9923f4592 | ||
|
|
29ae088a3d | ||
|
|
dd553b9439 | ||
|
|
451f2d30e4 | ||
|
|
463d85e479 | ||
|
|
2c52795822 | ||
|
|
4f37a36619 | ||
|
|
5aaba98c57 | ||
|
|
a98b69859c | ||
|
|
734a36de06 | ||
|
|
eb299ce847 | ||
|
|
a7e071318b | ||
|
|
3d67f6237e | ||
|
|
a691ffa7b7 | ||
|
|
aa9537c201 | ||
|
|
a3d9fb1c20 | ||
|
|
62a1e70c86 | ||
|
|
93d0d21846 | ||
|
|
b1c5a3ac14 | ||
|
|
55a525ba2f | ||
|
|
a53768463b | ||
|
|
24cbd6bcef | ||
|
|
3ab3e66853 | ||
|
|
40ca469339 | ||
|
|
2cbd2f719f | ||
|
|
53cbfa803b | ||
|
|
c0b0310bbd | ||
|
|
30e50062a8 | ||
|
|
85fd8f2c65 | ||
|
|
f72b042d5d | ||
|
|
2d3a3a0677 | ||
|
|
2bb21fedab | ||
|
|
91c820f98b | ||
|
|
7d3118aece | ||
|
|
4f4ad77ad1 | ||
|
|
42f205a731 | ||
|
|
cbb2b778a6 | ||
|
|
b3e03a648d | ||
|
|
acf45a79e8 | ||
|
|
b5d8ac852e | ||
|
|
4aec0e8fc6 | ||
|
|
ecea417fd8 | ||
|
|
6a41f6a435 | ||
|
|
da2d075aa8 | ||
|
|
10dc3993df | ||
|
|
7e5020db9a | ||
|
|
c48fe9de12 | ||
|
|
421e827a95 | ||
|
|
34d8045cf4 | ||
|
|
b02944a3b2 | ||
|
|
c6de163748 | ||
|
|
d9e2b22e74 | ||
|
|
65c0137964 | ||
|
|
ae19424ce7 | ||
|
|
7527ec52b7 | ||
|
|
640fcf3eaf | ||
|
|
3ce8232777 | ||
|
|
864b441d8e | ||
|
|
bc2ff149b4 | ||
|
|
dea305e921 | ||
|
|
e2eab31548 | ||
|
|
fe62e18f0d | ||
|
|
f1fa1553cf | ||
|
|
b576ae813d | ||
|
|
99123be936 | ||
|
|
dd0a033b0f | ||
|
|
c64597c9f1 | ||
|
|
6d2f81e3ed | ||
|
|
4263808360 | ||
|
|
c5ca2babf7 | ||
|
|
08db74d6e6 | ||
|
|
b309a9b01f | ||
|
|
2730745607 | ||
|
|
ae0df2aef0 | ||
|
|
6d665aeb21 | ||
|
|
967d3fd5c0 | ||
|
|
199d9c93ed | ||
|
|
30d2b41fbb | ||
|
|
75bb2533a3 | ||
|
|
9b3b4eb55b | ||
|
|
42f84b830c | ||
|
|
eb0f825cfc | ||
|
|
6878abe2a2 | ||
|
|
ec1c81e3ed | ||
|
|
56a5b6ec89 | ||
|
|
af478d3799 | ||
|
|
c2d40051d4 | ||
|
|
47824426c6 | ||
|
|
281e516495 | ||
|
|
f63c3091f4 | ||
|
|
50f49863b7 | ||
|
|
941b3bd701 | ||
|
|
f60b8cefca | ||
|
|
7c5f2ca54e | ||
|
|
401a650273 | ||
|
|
105af5cf11 | ||
|
|
637c2e43eb | ||
|
|
53373e6f4a | ||
|
|
ad147ed425 | ||
|
|
ed35e2f194 | ||
|
|
674919dbf5 | ||
|
|
15b77e303f | ||
|
|
757ca1d72c | ||
|
|
8c8c7a99e3 | ||
|
|
b3dfb960b5 | ||
|
|
4ded288c5d | ||
|
|
d123ca6063 | ||
|
|
0ee8b75b54 |
15
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,7 +1,12 @@
|
||||
**Description:**
|
||||
|
||||
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
|
||||
|
||||
**Radarr Version:**
|
||||
|
||||
**Logs:**
|
||||
|
||||
|
||||
|
||||
Provide a description of the feature request or bug, the more details the better.
|
||||
When possible include a log!
|
||||
|
||||
Please use our [Discord server](https://discord.gg/NWYch8M) for support or longer discussions.
|
||||
Please use the search bar and make sure you are not submitting an already submitted issue.
|
||||
Visit our [Discord server](https://discord.gg/NWYch8M) for support or longer discussions.
|
||||
|
||||
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -2,13 +2,11 @@
|
||||
YES | NO
|
||||
|
||||
#### Description
|
||||
A few sentences describing the overall goals of the pull request's commits.
|
||||
|
||||
|
||||
#### Todos
|
||||
- [ ] Tests
|
||||
- [ ] Documentation
|
||||
|
||||
|
||||
#### Issues Fixed or Closed by this PR
|
||||
|
||||
*
|
||||
* #
|
||||
|
||||
26
.gitignore
vendored
@@ -101,16 +101,21 @@ App_Data/*.ldf
|
||||
_NCrunch_*
|
||||
_TeamCity*
|
||||
|
||||
# Sonarr
|
||||
config.xml
|
||||
nzbdrone.log*txt
|
||||
# Radarr
|
||||
Backups/
|
||||
logs/
|
||||
MediaCover/
|
||||
UpdateLogs/
|
||||
xdg/
|
||||
config.xml
|
||||
logs.db*
|
||||
nzbdrone.db*
|
||||
nzbdrone.pid
|
||||
*workspace.xml
|
||||
*.test-cache
|
||||
*.userprefs
|
||||
*/test-results/*
|
||||
src/UI/.idea/*
|
||||
*log.txt
|
||||
node_modules/
|
||||
_output*
|
||||
_rawPackage/
|
||||
@@ -122,23 +127,26 @@ setup/Output/
|
||||
|
||||
UI.Phantom/
|
||||
|
||||
#VS outout folders
|
||||
# VS outout folders
|
||||
bin
|
||||
obj
|
||||
output/*
|
||||
|
||||
#Packages
|
||||
# Packages
|
||||
Radarr_*/
|
||||
Radarr_*.zip
|
||||
Radarr_*.gz
|
||||
|
||||
#OS X metadata files
|
||||
# macOS metadata files
|
||||
._*
|
||||
.DS_Store
|
||||
|
||||
_start
|
||||
_temp_*/**/*
|
||||
|
||||
#AppVeyor
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
|
||||
# AppVeyor
|
||||
/tools-cake/
|
||||
/_artifacts/
|
||||
/_artifacts/
|
||||
|
||||
10
.travis.yml
@@ -1,12 +1,14 @@
|
||||
language: csharp
|
||||
solution: src/NzbDrone.sln
|
||||
script: # the following commands are just examples, use whatever your build process requires
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- nodejs
|
||||
# - npm apparently not needed anymore.
|
||||
script:
|
||||
- ./build.sh
|
||||
- chmod +x test.sh
|
||||
# - ./test.sh Linux Unit Takes far too long, maybe even crashes travis :/
|
||||
install:
|
||||
- sudo apt-get install nodejs
|
||||
- sudo apt-get install npm
|
||||
after_success:
|
||||
- chmod +x package.sh
|
||||
- ./package.sh
|
||||
|
||||
BIN
Logo/1024.png
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 48 KiB |
BIN
Logo/128.png
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
Logo/16.png
|
Before Width: | Height: | Size: 811 B After Width: | Height: | Size: 701 B |
BIN
Logo/256.png
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 11 KiB |
BIN
Logo/32.png
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
Logo/400.png
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 17 KiB |
BIN
Logo/48.png
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.0 KiB |
BIN
Logo/512.png
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 22 KiB |
BIN
Logo/64.png
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
Logo/800.png
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 37 KiB |
597
Logo/Radarr.svg
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 31 KiB |
BIN
Logo/Thumbs.db
96
README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
## Status
|
||||
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
[](https://github.com/Radarr/Radarr/pulls)
|
||||
[](http://www.gnu.org/licenses/gpl.html)
|
||||
[](https://github.com/Radarr/Radarr)
|
||||
[](https://github.com/Radar/Radarr/releases/latest)
|
||||
[](https://hub.docker.com/r/linuxserver/radarr/)
|
||||
|
||||
| Service | Master | Develop |
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
|
||||
| Travis | [](https://travis-ci.org/Radarr/Radarr) | [](https://travis-ci.org/Radarr/Radarr) |
|
||||
|
||||
A fork of [Sonarr](https://github.com/Sonarr/Sonarr) to work with movies à la Couchpotato.
|
||||
|
||||
**This fork works independently of Sonarr and will not interfere with it.**
|
||||
|
||||
## Downloads
|
||||
|
||||
[](https://github.com/Radarr/Radarr/releases)
|
||||
|
||||
[](https://ci.appveyor.com/project/galli-leo/radarr-usby1/build/artifacts)
|
||||
|
||||
[](https://store.docker.com/community/images/linuxserver/radarr)
|
||||
[](https://store.docker.com/community/images/lsioarmhf/radarr)
|
||||
[](https://store.docker.com/community/images/lsioarmhf/radarr-aarch64)
|
||||
|
||||
To connect to the UI, fire up your browser and open <http://localhost:7878> or <http://your-ip:7878>.
|
||||
|
||||
## Support
|
||||
|
||||
[](https://discord.gg/AD3UP37)
|
||||
[](https://www.reddit.com/r/radarr)
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
|
||||
## Features
|
||||
|
||||
### Current Features
|
||||
|
||||
* Adding new movies with lots of information, such as trailers, ratings, etc.
|
||||
* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc.
|
||||
* Can watch for better quality of the movies you have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
|
||||
* Automatic failed download handling will try another release if one fails
|
||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically
|
||||
* Full integration with SABnzbd and NZBGet
|
||||
* Automatically searching for releases as well as RSS Sync
|
||||
* Automatically importing downloaded movies
|
||||
* Recognizing Special Editions, Director's Cut, etc.
|
||||
* Identifying releases with hardcoded subs
|
||||
* All indexers supported by Sonarr also supported
|
||||
* New PassThePopcorn Indexer
|
||||
* QBittorrent, Deluge, rTorrent, Transmission and uTorrent download client (Other clients are coming)
|
||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||
* And a beautiful UI
|
||||
|
||||
### Planned Features
|
||||
|
||||
* Scanning PreDB to know when a new release is available
|
||||
* Fixing the other Indexers and download clients
|
||||
* 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, metadata)
|
||||
|
||||
##Feature Requests
|
||||
[](http://feathub.com/Radarr/Radarr)
|
||||
|
||||
## Configuring Development Environment
|
||||
|
||||
### Requirements
|
||||
|
||||
* [Visual Studio Community](https://www.visualstudio.com/vs/community/) or [MonoDevelop](http://www.monodevelop.com)
|
||||
* [Git](https://git-scm.com/downloads)
|
||||
* [Node.js](https://nodejs.org/en/download/)
|
||||
|
||||
### Setup
|
||||
|
||||
* Make sure all the required software mentioned above are installed
|
||||
* Clone the repository into your development machine ([*info*](https://help.github.com/desktop/guides/contributing/working-with-your-remote-repository-on-github-or-github-enterprise))
|
||||
* Grab the submodules `git submodule init && git submodule update`
|
||||
* Install the required Node Packages `npm install`
|
||||
* Start gulp to monitor your dev environment for any changes that need post processing using `npm start` command.
|
||||
|
||||
> **Notice**
|
||||
> Gulp must be running at all times while you are working with Radarr client source files.
|
||||
|
||||
### Development
|
||||
|
||||
* Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed
|
||||
* Make sure `NzbDrone.Console` is set as the startup project
|
||||
|
||||
## Sponsors
|
||||
|
||||
[JetBrains](http://www.jetbrains.com) for providing us with free licenses to their great tools:
|
||||
* [ReSharper](http://www.jetbrains.com/resharper)
|
||||
* [WebStorm](http://www.jetbrains.com/webstorm)
|
||||
* [TeamCity](http://www.jetbrains.com/teamcity)
|
||||
83
readme.md
@@ -1,83 +0,0 @@
|
||||
# Radarr
|
||||
|
||||
| Service | Master | Develop |
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
|
||||
| Travis | [](https://travis-ci.org/galli-leo/Radarr) | [](https://travis-ci.org/galli-leo/Radarr) |
|
||||
|
||||
This fork of Sonarr aims to turn it into something like Couchpotato.
|
||||
|
||||
## Currently working:
|
||||
* Adding new movies
|
||||
* Manually searching for releases of movies.
|
||||
* Automatically searching for releases.
|
||||
* Automatically importing downloaded movies.
|
||||
* Recognizing Special Editions, Director's Cut, etc.
|
||||
* Identifying releases with hardcoded subs.
|
||||
* Rarbg.to, Torznab and Newznab Indexer.
|
||||
* QBittorrent and Deluge download client (Other clients are coming)
|
||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||
|
||||
## Planned Features:
|
||||
* Scanning PreDB to know when a new release is available.
|
||||
* Fixing the other Indexers and download clients.
|
||||
* Importing of Sonarr config.
|
||||
|
||||
## Download
|
||||
The latest precompiled binary versions can be found here: https://github.com/galli-leo/Radarr/releases.
|
||||
|
||||
To connect to the UI, fire up your browser and open localhost:7878 or your-ip:7878.
|
||||
|
||||
Docker containers from [linuxserver.io](https://linuxserver.io) can be found here.
|
||||
* [Radarr (x64)](https://hub.docker.com/r/linuxserver/radarr/)
|
||||
* [Radarr (armhf)](https://hub.docker.com/r/lsioarmhf/radarr/)
|
||||
* [Radarr (aarch64)](https://hub.docker.com/r/lsioarmhf/radarr-aarch64/)
|
||||
|
||||
For more up to date versions (but also sometimes broken), daily builds can be found here:
|
||||
* [OSX](https://leonardogalli.ch/radarr/builds/latest.php?os=osx)
|
||||
* [Windows](https://leonardogalli.ch/radarr/builds/latest.php?os=windows)
|
||||
* [Linux](https://leonardogalli.ch/radarr/builds/latest.php?os=mono)
|
||||
|
||||
## Major Features Include: ##
|
||||
|
||||
* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
|
||||
* Can watch for better quality of the movies you have and do an upgrade.
|
||||
* Automatic failed download handling will try another release if one fails
|
||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically.
|
||||
* Full integration with SABNzbd and NzbGet.
|
||||
* Full integration with XBMC, Plex (notification, library update, metadata).
|
||||
* And a beautiful UI
|
||||
|
||||
## Configuring Development Environment: ##
|
||||
|
||||
### Requirements ###
|
||||
- Visual Studio 2015 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) or Mono
|
||||
- [Git](http://git-scm.com/downloads)
|
||||
- [NodeJS](http://nodejs.org/download/)
|
||||
|
||||
### Setup ###
|
||||
|
||||
- Make sure all the required software mentioned above are installed.
|
||||
- Clone the repository into your development machine. [*info*](https://help.github.com/articles/working-with-repositories)
|
||||
- Grab the submodules `git submodule init && git submodule update`
|
||||
- install the required Node Packages `npm install`
|
||||
- start gulp to monitor your dev environment for any changes that need post processing using `npm start` command.
|
||||
|
||||
*Please note gulp must be running at all times while you are working with Sonarr client source files.*
|
||||
|
||||
|
||||
### Development ###
|
||||
- Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed.
|
||||
- Make sure `NzbDrone.Console` is set as the startup project
|
||||
|
||||
|
||||
### License ###
|
||||
* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
||||
Copyright 2010-2016
|
||||
|
||||
|
||||
### Sponsors ###
|
||||
- [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools
|
||||
- [ReSharper](http://www.jetbrains.com/resharper/)
|
||||
- [WebStorm](http://www.jetbrains.com/webstorm/)
|
||||
- [TeamCity](http://www.jetbrains.com/teamcity/)
|
||||
@@ -64,6 +64,8 @@ namespace NzbDrone.Api.Authentication
|
||||
new DefaultHmacProvider(new PassphraseKeyGenerator(_configService.HmacPassphrase, Encoding.ASCII.GetBytes(_configService.HmacSalt)))
|
||||
);
|
||||
|
||||
FormsAuthentication.FormsAuthenticationCookieName = "_ncfaradarr"; //For those people that both have sonarr and radarr.
|
||||
|
||||
FormsAuthentication.Enable(pipelines, new FormsAuthenticationConfiguration
|
||||
{
|
||||
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Api.Series;
|
||||
@@ -11,13 +12,14 @@ namespace NzbDrone.Api.Blacklist
|
||||
{
|
||||
public int SeriesId { get; set; }
|
||||
public List<int> EpisodeIds { get; set; }
|
||||
public int MovieId { get; set; }
|
||||
public string SourceTitle { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public MovieResource Movie { get; set; }
|
||||
public SeriesResource Series { get; set; }
|
||||
}
|
||||
|
||||
@@ -30,7 +32,7 @@ namespace NzbDrone.Api.Blacklist
|
||||
return new BlacklistResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
MovieId = model.MovieId,
|
||||
SeriesId = model.SeriesId,
|
||||
EpisodeIds = model.EpisodeIds,
|
||||
SourceTitle = model.SourceTitle,
|
||||
@@ -39,7 +41,7 @@ namespace NzbDrone.Api.Blacklist
|
||||
Protocol = model.Protocol,
|
||||
Indexer = model.Indexer,
|
||||
Message = model.Message,
|
||||
|
||||
Movie = model.Movie.ToResource(),
|
||||
Series = model.Series.ToResource()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,25 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.MovieStats;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.Calendar
|
||||
{
|
||||
public class CalendarModule : EpisodeModuleWithSignalR
|
||||
public class CalendarModule : MovieModule
|
||||
{
|
||||
public CalendarModule(IEpisodeService episodeService,
|
||||
ISeriesService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "calendar")
|
||||
public CalendarModule(IBroadcastSignalRMessage signalR,
|
||||
IMovieService moviesService,
|
||||
IMovieStatisticsService moviesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper)
|
||||
: base(signalR, moviesService, moviesStatisticsService, sceneMappingService, coverMapper, "calendar")
|
||||
{
|
||||
|
||||
GetResourceAll = GetCalendar;
|
||||
}
|
||||
|
||||
private List<EpisodeResource> GetCalendar()
|
||||
private List<MovieResource> GetCalendar()
|
||||
{
|
||||
var start = DateTime.Today;
|
||||
var end = DateTime.Today.AddDays(2);
|
||||
@@ -33,9 +49,9 @@ namespace NzbDrone.Api.Calendar
|
||||
if (queryEnd.HasValue) end = DateTime.Parse(queryEnd.Value);
|
||||
if (queryIncludeUnmonitored.HasValue) includeUnmonitored = Convert.ToBoolean(queryIncludeUnmonitored.Value);
|
||||
|
||||
var resources = MapToResource(_episodeService.EpisodesBetweenDates(start, end, includeUnmonitored), true, true);
|
||||
var resources = _moviesService.GetMoviesBetweenDates(start, end, includeUnmonitored).Select(MapToResource);
|
||||
|
||||
return resources.OrderBy(e => e.AirDateUtc).ToList();
|
||||
return resources.OrderBy(e => e.InCinemas).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Profiles;
|
||||
|
||||
namespace NzbDrone.Api.ClientSchema
|
||||
{
|
||||
@@ -73,14 +76,14 @@ namespace NzbDrone.Api.ClientSchema
|
||||
|
||||
if (propertyInfo.PropertyType == typeof(int))
|
||||
{
|
||||
var value = Convert.ToInt32(field.Value);
|
||||
propertyInfo.SetValue(target, value, null);
|
||||
var value = field.Value.ToString().ParseInt32();
|
||||
propertyInfo.SetValue(target, value ?? 0, null);
|
||||
}
|
||||
|
||||
else if (propertyInfo.PropertyType == typeof(long))
|
||||
{
|
||||
var value = Convert.ToInt64(field.Value);
|
||||
propertyInfo.SetValue(target, value, null);
|
||||
var value = field.Value.ToString().ParseInt64();
|
||||
propertyInfo.SetValue(target, value ?? 0, null);
|
||||
}
|
||||
|
||||
else if (propertyInfo.PropertyType == typeof(int?))
|
||||
@@ -147,6 +150,18 @@ namespace NzbDrone.Api.ClientSchema
|
||||
|
||||
private static List<SelectOption> GetSelectOptions(Type selectOptions)
|
||||
{
|
||||
if (selectOptions == typeof(Profile))
|
||||
{
|
||||
return new List<SelectOption>();
|
||||
}
|
||||
|
||||
if (selectOptions == typeof(Quality))
|
||||
{
|
||||
var qOptions = from Quality q in selectOptions.GetProperties(BindingFlags.Static | BindingFlags.Public)
|
||||
select new SelectOption {Name = q.Name, Value = q.Id};
|
||||
return qOptions.OrderBy(o => o.Value).ToList();
|
||||
}
|
||||
|
||||
var options = from Enum e in Enum.GetValues(selectOptions)
|
||||
select new SelectOption { Value = Convert.ToInt32(e), Name = e.ToString() };
|
||||
|
||||
|
||||
22
src/NzbDrone.Api/Config/NetImportConfigModule.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Api.Validation;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
public class NetImportConfigModule : NzbDroneConfigModule<NetImportConfigResource>
|
||||
{
|
||||
|
||||
public NetImportConfigModule(IConfigService configService)
|
||||
: base(configService)
|
||||
{
|
||||
SharedValidator.RuleFor(c => c.NetImportSyncInterval)
|
||||
.IsValidNetImportSyncInterval();
|
||||
}
|
||||
|
||||
protected override NetImportConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return NetImportConfigResourceMapper.ToResource(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/NzbDrone.Api/Config/NetImportConfigResource.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
public class NetImportConfigResource : RestResource
|
||||
{
|
||||
public int NetImportSyncInterval { get; set; }
|
||||
}
|
||||
|
||||
public static class NetImportConfigResourceMapper
|
||||
{
|
||||
public static NetImportConfigResource ToResource(IConfigService model)
|
||||
{
|
||||
return new NetImportConfigResource
|
||||
{
|
||||
NetImportSyncInterval = model.NetImportSyncInterval
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||
|
||||
private void DeleteEpisodeFile(int id)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(id);
|
||||
var episodeFile = _mediaFileService.Get(id);
|
||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
|
||||
|
||||
|
||||
@@ -66,13 +66,9 @@ namespace NzbDrone.Api.Extensions.Pipelines
|
||||
private Response LogError(NancyContext context, Exception exception)
|
||||
{
|
||||
var response = _errorPipeline.HandleException(context, exception);
|
||||
|
||||
context.Response = response;
|
||||
|
||||
LogEnd(context);
|
||||
|
||||
context.Response = null;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -80,12 +76,9 @@ namespace NzbDrone.Api.Extensions.Pipelines
|
||||
{
|
||||
if (request.Url.Query.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return string.Concat(request.Url.Path, "?", request.Url.Query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return request.Url.Path;
|
||||
return string.Concat(request.Url.Path, request.Url.Query);
|
||||
}
|
||||
return request.Url.Path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,9 @@ namespace NzbDrone.Api.Indexers
|
||||
|
||||
release.ReleaseWeight = initialWeight;
|
||||
|
||||
if (decision.RemoteEpisode.Series != null)
|
||||
if (decision.RemoteMovie.Movie != null)
|
||||
{
|
||||
release.QualityWeight = decision.RemoteEpisode.Series
|
||||
release.QualityWeight = decision.RemoteMovie.Movie
|
||||
.Profile.Value
|
||||
.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 100;
|
||||
}
|
||||
|
||||
175
src/NzbDrone.Api/Movies/MovieBulkImportModule.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Parser;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using Marr.Data;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.Movie
|
||||
{
|
||||
|
||||
public class UnmappedComparer : IComparer<UnmappedFolder>
|
||||
{
|
||||
public int Compare(UnmappedFolder a, UnmappedFolder b)
|
||||
{
|
||||
return a.Name.CompareTo(b.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public class MovieBulkImportModule : NzbDroneRestModule<MovieResource>
|
||||
{
|
||||
private readonly ISearchForNewMovie _searchProxy;
|
||||
private readonly IRootFolderService _rootFolderService;
|
||||
private readonly IMakeImportDecision _importDecisionMaker;
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
private readonly ICached<Core.Tv.Movie> _mappedMovies;
|
||||
private readonly IMovieService _movieService;
|
||||
|
||||
public MovieBulkImportModule(ISearchForNewMovie searchProxy, IRootFolderService rootFolderService, IMakeImportDecision importDecisionMaker,
|
||||
IDiskScanService diskScanService, ICacheManager cacheManager, IMovieService movieService)
|
||||
: base("/movies/bulkimport")
|
||||
{
|
||||
_searchProxy = searchProxy;
|
||||
_rootFolderService = rootFolderService;
|
||||
_importDecisionMaker = importDecisionMaker;
|
||||
_diskScanService = diskScanService;
|
||||
_mappedMovies = cacheManager.GetCache<Core.Tv.Movie>(GetType(), "mappedMoviesCache");
|
||||
_movieService = movieService;
|
||||
Get["/"] = x => Search();
|
||||
}
|
||||
|
||||
|
||||
private Response Search()
|
||||
{
|
||||
if (Request.Query.Id == 0)
|
||||
{
|
||||
//Todo error handling
|
||||
}
|
||||
|
||||
RootFolder rootFolder = _rootFolderService.Get(Request.Query.Id);
|
||||
|
||||
int page = Request.Query.page;
|
||||
int per_page = Request.Query.per_page;
|
||||
|
||||
int min = (page - 1) * per_page;
|
||||
|
||||
int max = page * per_page;
|
||||
|
||||
var unmapped = rootFolder.UnmappedFolders.OrderBy(f => f.Name).ToList();
|
||||
|
||||
int total_count = unmapped.Count;
|
||||
|
||||
if (Request.Query.total_entries.HasValue)
|
||||
{
|
||||
total_count = Request.Query.total_entries;
|
||||
}
|
||||
|
||||
max = total_count >= max ? max : total_count;
|
||||
|
||||
var paged = unmapped.GetRange(min, max-min);
|
||||
|
||||
var mapped = paged.Select(f =>
|
||||
{
|
||||
Core.Tv.Movie m = null;
|
||||
|
||||
var mappedMovie = _mappedMovies.Find(f.Name);
|
||||
|
||||
if (mappedMovie != null)
|
||||
{
|
||||
return mappedMovie;
|
||||
}
|
||||
|
||||
var parsedTitle = Parser.ParseMoviePath(f.Name);
|
||||
if (parsedTitle == null)
|
||||
{
|
||||
m = new Core.Tv.Movie
|
||||
{
|
||||
Title = f.Name.Replace(".", " ").Replace("-", " "),
|
||||
Path = f.Path,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
m = new Core.Tv.Movie
|
||||
{
|
||||
Title = parsedTitle.MovieTitle,
|
||||
Year = parsedTitle.Year,
|
||||
ImdbId = parsedTitle.ImdbId,
|
||||
Path = f.Path
|
||||
};
|
||||
}
|
||||
|
||||
var files = _diskScanService.GetVideoFiles(f.Path);
|
||||
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(files.ToList(), m);
|
||||
|
||||
var decision = decisions.Where(d => d.Approved && !d.Rejections.Any()).FirstOrDefault();
|
||||
|
||||
if (decision != null)
|
||||
{
|
||||
var local = decision.LocalMovie;
|
||||
|
||||
m.MovieFile = new LazyLoaded<MovieFile>(new MovieFile
|
||||
{
|
||||
Path = local.Path,
|
||||
Edition = local.ParsedMovieInfo.Edition,
|
||||
Quality = local.Quality,
|
||||
MediaInfo = local.MediaInfo,
|
||||
ReleaseGroup = local.ParsedMovieInfo.ReleaseGroup,
|
||||
RelativePath = f.Path.GetRelativePath(local.Path)
|
||||
});
|
||||
}
|
||||
|
||||
mappedMovie = _searchProxy.MapMovieToTmdbMovie(m);
|
||||
|
||||
if (mappedMovie != null)
|
||||
{
|
||||
mappedMovie.Monitored = true;
|
||||
|
||||
_mappedMovies.Set(f.Name, mappedMovie, TimeSpan.FromDays(2));
|
||||
|
||||
return mappedMovie;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return new PagingResource<MovieResource>
|
||||
{
|
||||
Page = page,
|
||||
PageSize = per_page,
|
||||
SortDirection = SortDirection.Ascending,
|
||||
SortKey = Request.Query.sort_by,
|
||||
TotalRecords = total_count - mapped.Where(m => m == null).Count(),
|
||||
Records = MapToResource(mapped.Where(m => m != null)).ToList()
|
||||
}.AsResponse();
|
||||
}
|
||||
|
||||
|
||||
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
||||
{
|
||||
foreach (var currentMovie in movies)
|
||||
{
|
||||
var resource = currentMovie.ToResource();
|
||||
var poster = currentMovie.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||
if (poster != null)
|
||||
{
|
||||
resource.RemotePoster = poster.Url;
|
||||
}
|
||||
|
||||
yield return resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,21 +35,21 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||
_seriesService = seriesService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
_logger = logger;
|
||||
/*GetResourceById = GetEpisodeFile;
|
||||
GetResourceAll = GetEpisodeFiles;
|
||||
GetResourceById = GetMovieFile;
|
||||
/*GetResourceAll = GetEpisodeFiles;
|
||||
UpdateResource = SetQuality;*/
|
||||
UpdateResource = SetQuality;
|
||||
DeleteResource = DeleteEpisodeFile;
|
||||
}
|
||||
|
||||
/*private EpisodeFileResource GetEpisodeFile(int id)
|
||||
private MovieFileResource GetMovieFile(int id)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(id);
|
||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||
var episodeFile = _mediaFileService.GetMovie(id);
|
||||
|
||||
return episodeFile.ToResource(series, _qualityUpgradableSpecification);
|
||||
return episodeFile.ToResource();
|
||||
}
|
||||
|
||||
private List<EpisodeFileResource> GetEpisodeFiles()
|
||||
/*private List<EpisodeFileResource> GetEpisodeFiles()
|
||||
{
|
||||
if (!Request.Query.SeriesId.HasValue)
|
||||
{
|
||||
@@ -62,13 +62,13 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||
|
||||
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _qualityUpgradableSpecification));
|
||||
}
|
||||
|
||||
private void SetQuality(EpisodeFileResource episodeFileResource)
|
||||
*/
|
||||
private void SetQuality(MovieFileResource episodeFileResource)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
|
||||
var episodeFile = _mediaFileService.GetMovie(episodeFileResource.Id);
|
||||
episodeFile.Quality = episodeFileResource.Quality;
|
||||
_mediaFileService.Update(episodeFile);
|
||||
}*/
|
||||
}
|
||||
|
||||
private void DeleteEpisodeFile(int id)
|
||||
{
|
||||
|
||||
78
src/NzbDrone.Api/Movies/MovieModuleWithSignalR.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.Movies
|
||||
{
|
||||
public abstract class MovieModuleWithSignalR : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>,
|
||||
IHandle<MovieGrabbedEvent>,
|
||||
IHandle<MovieDownloadedEvent>
|
||||
{
|
||||
protected readonly IMovieService _episodeService;
|
||||
protected readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
|
||||
protected MovieModuleWithSignalR(IMovieService episodeService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_episodeService = episodeService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
|
||||
GetResourceById = GetMovie;
|
||||
}
|
||||
|
||||
protected MovieModuleWithSignalR(IMovieService episodeService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster,
|
||||
string resource)
|
||||
: base(signalRBroadcaster, resource)
|
||||
{
|
||||
_episodeService = episodeService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
|
||||
GetResourceById = GetMovie;
|
||||
}
|
||||
|
||||
protected MovieResource GetMovie(int id)
|
||||
{
|
||||
var episode = _episodeService.GetMovie(id);
|
||||
var resource = MapToResource(episode, true);
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected MovieResource MapToResource(Core.Tv.Movie episode, bool includeSeries)
|
||||
{
|
||||
var resource = episode.ToResource();
|
||||
|
||||
if (includeSeries)
|
||||
{
|
||||
var series = episode ?? _episodeService.GetMovie(episode.Id);
|
||||
resource = series.ToResource();
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void Handle(MovieGrabbedEvent message)
|
||||
{
|
||||
var resource = message.Movie.Movie.ToResource();
|
||||
|
||||
//add a grabbed field in MovieResource?
|
||||
//resource.Grabbed = true;
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
}
|
||||
|
||||
public void Handle(MovieDownloadedEvent message)
|
||||
{
|
||||
var resource = message.Movie.Movie.ToResource();
|
||||
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Movies
|
||||
private readonly IRenameMovieFileService _renameMovieFileService;
|
||||
|
||||
public RenameMovieModule(IRenameMovieFileService renameMovieFileService)
|
||||
: base("rename")
|
||||
: base("renameMovie")
|
||||
{
|
||||
_renameMovieFileService = renameMovieFileService;
|
||||
|
||||
|
||||
34
src/NzbDrone.Api/NetImport/ListImportModule.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using Nancy.Extensions;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.NetImport
|
||||
{
|
||||
public class ListImportModule : NzbDroneApiModule
|
||||
{
|
||||
private readonly IMovieService _movieService;
|
||||
private readonly ISearchForNewMovie _movieSearch;
|
||||
|
||||
public ListImportModule(IMovieService movieService, ISearchForNewMovie movieSearch)
|
||||
: base("/movie/import")
|
||||
{
|
||||
_movieService = movieService;
|
||||
_movieSearch = movieSearch;
|
||||
Put["/"] = Movie => SaveAll();
|
||||
}
|
||||
|
||||
private Response SaveAll()
|
||||
{
|
||||
var resources = Request.Body.FromJson<List<MovieResource>>();
|
||||
|
||||
var Movies = resources.Select(MovieResource => _movieSearch.MapMovieToTmdbMovie(MovieResource.ToModel())).Where(m => m != null).DistinctBy(m => m.TmdbId).ToList();
|
||||
|
||||
return _movieService.AddMovies(Movies).ToResource().AsResponse(HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/NzbDrone.Api/NetImport/NetImportModule.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using NzbDrone.Api.ClientSchema;
|
||||
using NzbDrone.Core.NetImport;
|
||||
using NzbDrone.Core.Profiles;
|
||||
|
||||
namespace NzbDrone.Api.NetImport
|
||||
{
|
||||
public class NetImportModule : ProviderModuleBase<NetImportResource, INetImport, NetImportDefinition>
|
||||
{
|
||||
private readonly IProfileService _profileService;
|
||||
public NetImportModule(NetImportFactory indexerFactory, IProfileService profileService)
|
||||
: base(indexerFactory, "netimport")
|
||||
{
|
||||
_profileService = profileService;
|
||||
}
|
||||
|
||||
protected override void MapToResource(NetImportResource resource, NetImportDefinition definition)
|
||||
{
|
||||
base.MapToResource(resource, definition);
|
||||
|
||||
resource.Enabled = definition.Enabled;
|
||||
resource.EnableAuto = definition.EnableAuto;
|
||||
resource.ProfileId = definition.ProfileId;
|
||||
resource.RootFolderPath = definition.RootFolderPath;
|
||||
resource.ShouldMonitor = definition.ShouldMonitor;
|
||||
}
|
||||
|
||||
protected override void MapToModel(NetImportDefinition definition, NetImportResource resource)
|
||||
{
|
||||
base.MapToModel(definition, resource);
|
||||
|
||||
definition.Enabled = resource.Enabled;
|
||||
definition.EnableAuto = resource.EnableAuto;
|
||||
definition.ProfileId = resource.ProfileId;
|
||||
definition.RootFolderPath = resource.RootFolderPath;
|
||||
definition.ShouldMonitor = resource.ShouldMonitor;
|
||||
}
|
||||
|
||||
protected override void Validate(NetImportDefinition definition, bool includeWarnings)
|
||||
{
|
||||
if (!definition.Enable) return;
|
||||
base.Validate(definition, includeWarnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/NzbDrone.Api/NetImport/NetImportResource.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using NzbDrone.Core.NetImport;
|
||||
|
||||
namespace NzbDrone.Api.NetImport
|
||||
{
|
||||
public class NetImportResource : ProviderResource
|
||||
{
|
||||
public bool Enabled { get; set; }
|
||||
public bool EnableAuto { get; set; }
|
||||
public bool ShouldMonitor { get; set; }
|
||||
public string RootFolderPath { get; set; }
|
||||
public int ProfileId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -109,6 +109,8 @@
|
||||
<Compile Include="ClientSchema\SelectOption.cs" />
|
||||
<Compile Include="Commands\CommandModule.cs" />
|
||||
<Compile Include="Commands\CommandResource.cs" />
|
||||
<Compile Include="Config\NetImportConfigModule.cs" />
|
||||
<Compile Include="Config\NetImportConfigResource.cs" />
|
||||
<Compile Include="Extensions\AccessControlHeaders.cs" />
|
||||
<Compile Include="Extensions\Pipelines\CorsPipeline.cs" />
|
||||
<Compile Include="Extensions\Pipelines\RequestLoggingPipeline.cs" />
|
||||
@@ -116,11 +118,16 @@
|
||||
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
|
||||
<Compile Include="Indexers\ReleaseModuleBase.cs" />
|
||||
<Compile Include="Indexers\ReleasePushModule.cs" />
|
||||
<Compile Include="Movies\MovieModuleWithSignalR.cs" />
|
||||
<Compile Include="Movies\MovieBulkImportModule.cs" />
|
||||
<Compile Include="Movies\MovieFileModule.cs" />
|
||||
<Compile Include="Movies\MovieModule.cs" />
|
||||
<Compile Include="Series\MovieModule.cs" />
|
||||
<Compile Include="Movies\RenameMovieModule.cs" />
|
||||
<Compile Include="Movies\RenameMovieResource.cs" />
|
||||
<Compile Include="Movies\MovieEditorModule.cs" />
|
||||
<Compile Include="NetImport\ListImportModule.cs" />
|
||||
<Compile Include="NetImport\NetImportModule.cs" />
|
||||
<Compile Include="NetImport\NetImportResource.cs" />
|
||||
<Compile Include="Parse\ParseModule.cs" />
|
||||
<Compile Include="Parse\ParseResource.cs" />
|
||||
<Compile Include="ManualImport\ManualImportModule.cs" />
|
||||
@@ -234,12 +241,12 @@
|
||||
<Compile Include="SeasonPass\SeasonPassResource.cs" />
|
||||
<Compile Include="Series\AlternateTitleResource.cs" />
|
||||
<Compile Include="Series\MovieFileResource.cs" />
|
||||
<Compile Include="Series\FetchMovieListModule.cs" />
|
||||
<Compile Include="Series\SeasonResource.cs" />
|
||||
<Compile Include="SeasonPass\SeasonPassModule.cs" />
|
||||
<Compile Include="Series\SeriesEditorModule.cs" />
|
||||
<Compile Include="Series\MovieLookupModule.cs" />
|
||||
<Compile Include="Series\SeriesLookupModule.cs" />
|
||||
<Compile Include="Series\MovieModule.cs" />
|
||||
<Compile Include="Series\SeriesModule.cs" />
|
||||
<Compile Include="Series\MovieResource.cs" />
|
||||
<Compile Include="Series\SeriesResource.cs" />
|
||||
@@ -254,12 +261,15 @@
|
||||
<Compile Include="TinyIoCNancyBootstrapper.cs" />
|
||||
<Compile Include="Update\UpdateModule.cs" />
|
||||
<Compile Include="Update\UpdateResource.cs" />
|
||||
<Compile Include="Validation\NetImportSyncIntervalValidator.cs" />
|
||||
<Compile Include="Validation\RssSyncIntervalValidator.cs" />
|
||||
<Compile Include="Validation\EmptyCollectionValidator.cs" />
|
||||
<Compile Include="Validation\RuleBuilderExtensions.cs" />
|
||||
<Compile Include="Wanted\CutoffModule.cs" />
|
||||
<Compile Include="Wanted\LegacyMissingModule.cs" />
|
||||
<Compile Include="Wanted\MissingModule.cs" />
|
||||
<Compile Include="Wanted\MovieCutoffModule.cs" />
|
||||
<Compile Include="Wanted\MovieMissingModule.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
@@ -287,11 +297,11 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -11,6 +11,7 @@ namespace NzbDrone.Api.Profiles
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Quality Cutoff { get; set; }
|
||||
public string PreferredTags { get; set; }
|
||||
public List<ProfileQualityItemResource> Items { get; set; }
|
||||
public Language Language { get; set; }
|
||||
}
|
||||
@@ -33,6 +34,7 @@ namespace NzbDrone.Api.Profiles
|
||||
|
||||
Name = model.Name,
|
||||
Cutoff = model.Cutoff,
|
||||
PreferredTags = model.PreferredTags != null ? string.Join(",", model.PreferredTags) : "",
|
||||
Items = model.Items.ConvertAll(ToResource),
|
||||
Language = model.Language
|
||||
};
|
||||
@@ -59,6 +61,7 @@ namespace NzbDrone.Api.Profiles
|
||||
|
||||
Name = resource.Name,
|
||||
Cutoff = (Quality)resource.Cutoff.Id,
|
||||
PreferredTags = resource.PreferredTags.Split(',').ToList(),
|
||||
Items = resource.Items.ConvertAll(ToModel),
|
||||
Language = resource.Language
|
||||
};
|
||||
|
||||
@@ -38,8 +38,8 @@ namespace NzbDrone.Api.RootFolders
|
||||
Id = resource.Id,
|
||||
|
||||
Path = resource.Path,
|
||||
//FreeSpace
|
||||
//UnmappedFolders
|
||||
FreeSpace = resource.FreeSpace,
|
||||
UnmappedFolders = resource.UnmappedFolders
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
60
src/NzbDrone.Api/Series/FetchMovieListModule.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.Collections.Generic;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.NetImport;
|
||||
|
||||
namespace NzbDrone.Api.Movie
|
||||
{
|
||||
public class FetchMovieListModule : NzbDroneRestModule<MovieResource>
|
||||
{
|
||||
private readonly IFetchNetImport _fetchNetImport;
|
||||
private readonly ISearchForNewMovie _movieSearch;
|
||||
|
||||
public FetchMovieListModule(IFetchNetImport netImport, ISearchForNewMovie movieSearch)
|
||||
: base("/netimport/movies")
|
||||
{
|
||||
_fetchNetImport = netImport;
|
||||
_movieSearch = movieSearch;
|
||||
Get["/"] = x => Search();
|
||||
}
|
||||
|
||||
|
||||
private Response Search()
|
||||
{
|
||||
var results = _fetchNetImport.FetchAndFilter((int) Request.Query.listId, false);
|
||||
|
||||
List<Core.Tv.Movie> realResults = new List<Core.Tv.Movie>();
|
||||
|
||||
/*foreach (var movie in results)
|
||||
{
|
||||
var mapped = _movieSearch.MapMovieToTmdbMovie(movie);
|
||||
|
||||
if (mapped != null)
|
||||
{
|
||||
realResults.Add(mapped);
|
||||
}
|
||||
}*/
|
||||
|
||||
return MapToResource(results).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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,35 @@ 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 MovieLookupModule : NzbDroneRestModule<MovieResource>
|
||||
{
|
||||
private readonly ISearchForNewMovie _searchProxy;
|
||||
private readonly IProvideMovieInfo _movieInfo;
|
||||
|
||||
public MovieLookupModule(ISearchForNewMovie searchProxy)
|
||||
public MovieLookupModule(ISearchForNewMovie searchProxy, IProvideMovieInfo movieInfo)
|
||||
: base("/movies/lookup")
|
||||
{
|
||||
_movieInfo = movieInfo;
|
||||
_searchProxy = searchProxy;
|
||||
Get["/"] = x => Search();
|
||||
Get["/tmdb"] = x => SearchByTmdbId();
|
||||
}
|
||||
|
||||
private Response SearchByTmdbId()
|
||||
{
|
||||
int tmdbId = -1;
|
||||
if(Int32.TryParse(Request.Query.tmdbId, out tmdbId))
|
||||
{
|
||||
var result = _movieInfo.GetMovieInfo(tmdbId, null);
|
||||
return result.ToResource().AsResponse();
|
||||
}
|
||||
|
||||
throw new BadRequestException("Tmdb Id was not valid");
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +42,6 @@ namespace NzbDrone.Api.Movie
|
||||
return MapToResource(imdbResults).AsResponse();
|
||||
}
|
||||
|
||||
|
||||
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
||||
{
|
||||
foreach (var currentSeries in movies)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Api.Movie
|
||||
IHandle<MediaCoversUpdatedEvent>
|
||||
|
||||
{
|
||||
private readonly IMovieService _moviesService;
|
||||
protected readonly IMovieService _moviesService;
|
||||
private readonly IMovieStatisticsService _moviesStatisticsService;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
|
||||
@@ -78,13 +78,33 @@ namespace NzbDrone.Api.Movie
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
}
|
||||
|
||||
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMovieService moviesService,
|
||||
IMovieStatisticsService moviesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
string resource)
|
||||
: base(signalRBroadcaster, resource)
|
||||
{
|
||||
_moviesService = moviesService;
|
||||
_moviesStatisticsService = moviesStatisticsService;
|
||||
|
||||
_coverMapper = coverMapper;
|
||||
|
||||
GetResourceAll = AllMovie;
|
||||
GetResourceById = GetMovie;
|
||||
CreateResource = AddMovie;
|
||||
UpdateResource = UpdateMovie;
|
||||
DeleteResource = DeleteMovie;
|
||||
}
|
||||
|
||||
private MovieResource GetMovie(int id)
|
||||
{
|
||||
var movies = _moviesService.GetMovie(id);
|
||||
return MapToResource(movies);
|
||||
}
|
||||
|
||||
private MovieResource MapToResource(Core.Tv.Movie movies)
|
||||
protected MovieResource MapToResource(Core.Tv.Movie movies)
|
||||
{
|
||||
if (movies == null) return null;
|
||||
|
||||
@@ -181,6 +201,8 @@ namespace NzbDrone.Api.Movie
|
||||
//var mappings = null;//_sceneMappingService.FindByTvdbId(resource.TvdbId);
|
||||
|
||||
//if (mappings == null) return;
|
||||
|
||||
//Not necessary anymore
|
||||
|
||||
//resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
||||
}
|
||||
@@ -219,7 +241,7 @@ namespace NzbDrone.Api.Movie
|
||||
|
||||
public void Handle(MediaCoversUpdatedEvent message)
|
||||
{
|
||||
//BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace NzbDrone.Api.Movie
|
||||
public string RemotePoster { get; set; }
|
||||
public int Year { get; set; }
|
||||
public bool HasFile { get; set; }
|
||||
public string YouTubeTrailerId { get; set; }
|
||||
public string Studio { get; set; }
|
||||
|
||||
//View & Edit
|
||||
public string Path { get; set; }
|
||||
@@ -144,7 +146,9 @@ namespace NzbDrone.Api.Movie
|
||||
AddOptions = model.AddOptions,
|
||||
AlternativeTitles = model.AlternativeTitles,
|
||||
Ratings = model.Ratings,
|
||||
MovieFile = movieFile
|
||||
MovieFile = movieFile,
|
||||
YouTubeTrailerId = model.YouTubeTrailerId,
|
||||
Studio = model.Studio
|
||||
};
|
||||
}
|
||||
|
||||
@@ -191,7 +195,9 @@ namespace NzbDrone.Api.Movie
|
||||
Added = resource.Added,
|
||||
AddOptions = resource.AddOptions,
|
||||
AlternativeTitles = resource.AlternativeTitles,
|
||||
Ratings = resource.Ratings
|
||||
Ratings = resource.Ratings,
|
||||
YouTubeTrailerId = resource.YouTubeTrailerId,
|
||||
Studio = resource.Studio
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ namespace NzbDrone.Api.Series
|
||||
|
||||
public void Handle(MediaCoversUpdatedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Series.Id);
|
||||
//BroadcastResourceChange(ModelAction.Updated, message.Series.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using FluentValidation.Validators;
|
||||
|
||||
namespace NzbDrone.Api.Validation
|
||||
{
|
||||
public class NetImportSyncIntervalValidator : PropertyValidator
|
||||
{
|
||||
public NetImportSyncIntervalValidator()
|
||||
: base("Must be between 10 and 1440 or 0 to disable")
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool IsValid(PropertyValidatorContext context)
|
||||
{
|
||||
if (context.PropertyValue == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var value = (int)context.PropertyValue;
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value >= 10 && value <= 1440)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace NzbDrone.Api.Validation
|
||||
public class RssSyncIntervalValidator : PropertyValidator
|
||||
{
|
||||
public RssSyncIntervalValidator()
|
||||
: base("Must be between 10 and 120 or 0 to disable")
|
||||
: base("Must be between 10 and 720 or 0 to disable")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Api.Validation
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value >= 10 && value <= 120)
|
||||
if (value >= 10 && value <= 720)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,5 +36,10 @@ namespace NzbDrone.Api.Validation
|
||||
{
|
||||
return ruleBuilder.SetValidator(new RssSyncIntervalValidator());
|
||||
}
|
||||
|
||||
public static IRuleBuilderOptions<T, int> IsValidNetImportSyncInterval<T>(this IRuleBuilder<T, int> ruleBuilder)
|
||||
{
|
||||
return ruleBuilder.SetValidator(new NetImportSyncIntervalValidator());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace NzbDrone.Api.Wanted
|
||||
ISeriesService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/cutoff-old")
|
||||
{
|
||||
_episodeCutoffService = episodeCutoffService;
|
||||
GetResourcePaged = GetCutoffUnmetEpisodes;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Wanted
|
||||
ISeriesService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing_episodes")
|
||||
{
|
||||
GetResourcePaged = GetMissingEpisodes;
|
||||
}
|
||||
|
||||
42
src/NzbDrone.Api/Wanted/MovieCutoffModule.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Api.Movies;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.Wanted
|
||||
{
|
||||
public class MovieCutoffModule : MovieModuleWithSignalR
|
||||
{
|
||||
private readonly IMovieCutoffService _movieCutoffService;
|
||||
|
||||
public MovieCutoffModule(IMovieCutoffService movieCutoffService,
|
||||
IMovieService movieService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(movieService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
||||
{
|
||||
_movieCutoffService = movieCutoffService;
|
||||
GetResourcePaged = GetCutoffUnmetMovies;
|
||||
}
|
||||
|
||||
private PagingResource<MovieResource> GetCutoffUnmetMovies(PagingResource<MovieResource> pagingResource)
|
||||
{
|
||||
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("title", SortDirection.Ascending);
|
||||
|
||||
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
|
||||
{
|
||||
pagingSpec.FilterExpression = v => v.Monitored == false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pagingSpec.FilterExpression = v => v.Monitored == true;
|
||||
}
|
||||
|
||||
var resource = ApplyToPage(_movieCutoffService.MoviesWhereCutoffUnmet, pagingSpec, v => MapToResource(v, true));
|
||||
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/NzbDrone.Api/Wanted/MovieMissingModule.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Api.Movies;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.SignalR;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using System;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
|
||||
namespace NzbDrone.Api.Wanted
|
||||
{
|
||||
class MovieMissingModule : MovieModuleWithSignalR
|
||||
{
|
||||
protected readonly IMovieService _movieService;
|
||||
|
||||
public MovieMissingModule(IMovieService movieService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(movieService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||
{
|
||||
|
||||
_movieService = movieService;
|
||||
GetResourcePaged = GetMissingMovies;
|
||||
}
|
||||
|
||||
private PagingResource<MovieResource> GetMissingMovies(PagingResource<MovieResource> pagingResource)
|
||||
{
|
||||
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("title", SortDirection.Descending);
|
||||
|
||||
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
|
||||
{
|
||||
pagingSpec.FilterExpression = v => v.Monitored == false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pagingSpec.FilterExpression = v => v.Monitored == true;
|
||||
}
|
||||
|
||||
var resource = ApplyToPage(_movieService.MoviesWithoutFiles, pagingSpec, v => MapToResource(v, true));
|
||||
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 81 KiB |
75
src/NzbDrone.Core.Test/BulkImport/AddMultiMoviesFixture.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Moq;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.BulkImport
|
||||
{
|
||||
[TestFixture]
|
||||
public class AddMultiMoviesFixture : CoreTest<MovieService>
|
||||
{
|
||||
private List<Movie> fakeMovies;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
fakeMovies = Builder<Movie>.CreateListOfSize(3).BuildList();
|
||||
fakeMovies.ForEach(m =>
|
||||
{
|
||||
m.Path = null;
|
||||
m.RootFolderPath = @"C:\Test\TV";
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void movies_added_event_should_have_proper_path()
|
||||
{
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
.Setup(s => s.GetMovieFolder(It.IsAny<Movie>(), null))
|
||||
.Returns((Movie m, NamingConfig n) => m.Title);
|
||||
|
||||
var movies = Subject.AddMovies(fakeMovies);
|
||||
|
||||
foreach (Movie movie in movies)
|
||||
{
|
||||
movie.Path.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
//Subject.GetAllMovies().Should().HaveCount(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void movies_added_should_ignore_already_added()
|
||||
{
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
.Setup(s => s.GetMovieFolder(It.IsAny<Movie>(), null))
|
||||
.Returns((Movie m, NamingConfig n) => m.Title);
|
||||
|
||||
Mocker.GetMock<IMovieRepository>().Setup(s => s.All()).Returns(new List<Movie> { fakeMovies[0] });
|
||||
|
||||
var movies = Subject.AddMovies(fakeMovies);
|
||||
|
||||
Mocker.GetMock<IMovieRepository>().Verify(v => v.InsertMany(It.Is<List<Movie>>(l => l.Count == 2)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void movies_added_should_ignore_duplicates()
|
||||
{
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
.Setup(s => s.GetMovieFolder(It.IsAny<Movie>(), null))
|
||||
.Returns((Movie m, NamingConfig n) => m.Title);
|
||||
|
||||
fakeMovies[2].TmdbId = fakeMovies[0].TmdbId;
|
||||
|
||||
var movies = Subject.AddMovies(fakeMovies);
|
||||
|
||||
Mocker.GetMock<IMovieRepository>().Verify(v => v.InsertMany(It.Is<List<Movie>>(l => l.Count == 2)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace NzbDrone.Core.Test.Configuration
|
||||
[Test]
|
||||
public void Get_value_should_return_default_when_no_value()
|
||||
{
|
||||
Subject.RssSyncInterval.Should().Be(15);
|
||||
Subject.RssSyncInterval.Should().Be(60);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -47,7 +47,7 @@ namespace NzbDrone.Core.Test.Configuration
|
||||
public void get_value_with_out_persist_should_not_store_default_value()
|
||||
{
|
||||
var interval = Subject.RssSyncInterval;
|
||||
interval.Should().Be(15);
|
||||
interval.Should().Be(60);
|
||||
Mocker.GetMock<IConfigRepository>().Verify(c => c.Insert(It.IsAny<Config>()), Times.Never());
|
||||
}
|
||||
|
||||
|
||||
@@ -196,18 +196,18 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_if_RAWHD()
|
||||
{
|
||||
parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.RAWHD);
|
||||
//[Test]
|
||||
//public void should_return_true_if_RAWHD()
|
||||
//{
|
||||
// parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.RAWHD);
|
||||
|
||||
series.Runtime = 45;
|
||||
parseResultSingle.Series = series;
|
||||
parseResultSingle.Series.SeriesType = SeriesTypes.Daily;
|
||||
parseResultSingle.Release.Size = 8000.Megabytes();
|
||||
// series.Runtime = 45;
|
||||
// parseResultSingle.Series = series;
|
||||
// parseResultSingle.Series.SeriesType = SeriesTypes.Daily;
|
||||
// parseResultSingle.Release.Size = 8000.Megabytes();
|
||||
|
||||
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
// Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
|
||||
//}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_special()
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||
{
|
||||
private Profile _profile;
|
||||
private DelayProfile _delayProfile;
|
||||
private RemoteEpisode _remoteEpisode;
|
||||
private RemoteMovie _remoteEpisode;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
@@ -38,12 +38,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||
.With(d => d.PreferredProtocol = DownloadProtocol.Usenet)
|
||||
.Build();
|
||||
|
||||
var series = Builder<Series>.CreateNew()
|
||||
var series = Builder<Movie>.CreateNew()
|
||||
.With(s => s.Profile = _profile)
|
||||
.Build();
|
||||
|
||||
_remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
||||
.With(r => r.Series = series)
|
||||
_remoteEpisode = Builder<RemoteMovie>.CreateNew()
|
||||
.With(r => r.Movie = series)
|
||||
.Build();
|
||||
|
||||
_profile.Items = new List<ProfileQualityItem>();
|
||||
@@ -53,30 +53,30 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||
|
||||
_profile.Cutoff = Quality.WEBDL720p;
|
||||
|
||||
_remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
|
||||
_remoteEpisode.ParsedMovieInfo = new ParsedMovieInfo();
|
||||
_remoteEpisode.Release = new ReleaseInfo();
|
||||
_remoteEpisode.Release.DownloadProtocol = DownloadProtocol.Usenet;
|
||||
|
||||
_remoteEpisode.Episodes = Builder<Episode>.CreateListOfSize(1).Build().ToList();
|
||||
_remoteEpisode.Episodes.First().EpisodeFileId = 0;
|
||||
//_remoteEpisode.Episodes = Builder<Episode>.CreateListOfSize(1).Build().ToList();
|
||||
//_remoteEpisode.Episodes.First().EpisodeFileId = 0;
|
||||
|
||||
Mocker.GetMock<IDelayProfileService>()
|
||||
.Setup(s => s.BestForTags(It.IsAny<HashSet<int>>()))
|
||||
.Returns(_delayProfile);
|
||||
//Mocker.GetMock<IDelayProfileService>()
|
||||
// .Setup(s => s.BestForTags(It.IsAny<HashSet<int>>()))
|
||||
// .Returns(_delayProfile);
|
||||
|
||||
Mocker.GetMock<IPendingReleaseService>()
|
||||
.Setup(s => s.GetPendingRemoteEpisodes(It.IsAny<int>()))
|
||||
.Returns(new List<RemoteEpisode>());
|
||||
//Mocker.GetMock<IPendingReleaseService>()
|
||||
// .Setup(s => s.GetPendingRemoteEpisodes(It.IsAny<int>()))
|
||||
// .Returns(new List<RemoteEpisode>());
|
||||
}
|
||||
|
||||
private void GivenExistingFile(QualityModel quality)
|
||||
{
|
||||
_remoteEpisode.Episodes.First().EpisodeFileId = 1;
|
||||
//_remoteEpisode.Episodes.First().EpisodeFileId = 1;
|
||||
|
||||
_remoteEpisode.Episodes.First().EpisodeFile = new LazyLoaded<EpisodeFile>(new EpisodeFile
|
||||
{
|
||||
Quality = quality
|
||||
});
|
||||
//_remoteEpisode.Episodes.First().EpisodeFile = new LazyLoaded<EpisodeFile>(new EpisodeFile
|
||||
// {
|
||||
// Quality = quality
|
||||
// });
|
||||
}
|
||||
|
||||
private void GivenUpgradeForExistingFile()
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Download.Clients;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation.Proxies;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class SerialNumberProviderFixture : CoreTest<SerialNumberProvider>
|
||||
{
|
||||
protected DownloadStationSettings _settings;
|
||||
|
||||
[SetUp]
|
||||
protected void Setup()
|
||||
{
|
||||
_settings = new DownloadStationSettings();
|
||||
}
|
||||
|
||||
private void GivenValidResponse()
|
||||
{
|
||||
Mocker.GetMock<IDSMInfoProxy>()
|
||||
.Setup(d => d.GetSerialNumber(It.IsAny<DownloadStationSettings>()))
|
||||
.Returns("serial");
|
||||
}
|
||||
|
||||
private void GivenInvalidResponse()
|
||||
{
|
||||
Mocker.GetMock<IDSMInfoProxy>()
|
||||
.Setup(d => d.GetSerialNumber(It.IsAny<DownloadStationSettings>()))
|
||||
.Throws(new DownloadClientException("Serial response invalid"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_hashedserialnumber()
|
||||
{
|
||||
GivenValidResponse();
|
||||
|
||||
var serial = Subject.GetSerialNumber(_settings);
|
||||
|
||||
// This hash should remain the same for 'serial', so don't update the test if you change HashConverter, fix the code instead.
|
||||
serial.Should().Be("50DE66B735D30738618568294742FCF1DFA52A47");
|
||||
|
||||
Mocker.GetMock<IDSMInfoProxy>()
|
||||
.Verify(d => d.GetSerialNumber(It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_cache_serialnumber()
|
||||
{
|
||||
GivenValidResponse();
|
||||
|
||||
var serial1 = Subject.GetSerialNumber(_settings);
|
||||
var serial2 = Subject.GetSerialNumber(_settings);
|
||||
|
||||
serial2.Should().Be(serial1);
|
||||
|
||||
Mocker.GetMock<IDSMInfoProxy>()
|
||||
.Verify(d => d.GetSerialNumber(It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_if_serial_number_unavailable()
|
||||
{
|
||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.GetSerialNumber(_settings));
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Download.Clients;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation.Proxies;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class SharedFolderResolverFixture : CoreTest<SharedFolderResolver>
|
||||
{
|
||||
protected string _serialNumber = "SERIALNUMBER";
|
||||
protected OsPath _sharedFolder;
|
||||
protected OsPath _physicalPath;
|
||||
protected DownloadStationSettings _settings;
|
||||
|
||||
[SetUp]
|
||||
protected void Setup()
|
||||
{
|
||||
_sharedFolder = new OsPath("/myFolder");
|
||||
_physicalPath = new OsPath("/mnt/sda1/folder");
|
||||
_settings = new DownloadStationSettings();
|
||||
|
||||
Mocker.GetMock<IFileStationProxy>()
|
||||
.Setup(f => f.GetSharedFolderMapping(It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||
.Throws(new DownloadClientException("There is no shared folder"));
|
||||
|
||||
Mocker.GetMock<IFileStationProxy>()
|
||||
.Setup(f => f.GetSharedFolderMapping(_sharedFolder.FullPath, It.IsAny<DownloadStationSettings>()))
|
||||
.Returns(new SharedFolderMapping(_sharedFolder.FullPath, _physicalPath.FullPath));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_throw_when_cannot_resolve_shared_folder()
|
||||
{
|
||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.RemapToFullPath(new OsPath("/unknownFolder"), _settings, _serialNumber));
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_valid_sharedfolder()
|
||||
{
|
||||
var mapping = Subject.RemapToFullPath(_sharedFolder, _settings, "abc");
|
||||
|
||||
mapping.Should().Be(_physicalPath);
|
||||
|
||||
Mocker.GetMock<IFileStationProxy>()
|
||||
.Verify(f => f.GetSharedFolderMapping(It.IsAny<string>(), It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_cache_mapping()
|
||||
{
|
||||
Subject.RemapToFullPath(_sharedFolder, _settings, "abc");
|
||||
Subject.RemapToFullPath(_sharedFolder, _settings, "abc");
|
||||
|
||||
Mocker.GetMock<IFileStationProxy>()
|
||||
.Verify(f => f.GetSharedFolderMapping(It.IsAny<string>(), It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_remap_subfolder()
|
||||
{
|
||||
var mapping = Subject.RemapToFullPath(_sharedFolder + "sub", _settings, "abc");
|
||||
|
||||
mapping.Should().Be(_physicalPath + "sub");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,600 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation;
|
||||
using NzbDrone.Core.Download.Clients.DownloadStation.Proxies;
|
||||
using NzbDrone.Core.MediaFiles.TorrentInfo;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TorrentDownloadStationFixture : DownloadClientFixtureBase<TorrentDownloadStation>
|
||||
{
|
||||
protected DownloadStationSettings _settings;
|
||||
|
||||
protected DownloadStationTorrent _queued;
|
||||
protected DownloadStationTorrent _downloading;
|
||||
protected DownloadStationTorrent _failed;
|
||||
protected DownloadStationTorrent _completed;
|
||||
protected DownloadStationTorrent _seeding;
|
||||
protected DownloadStationTorrent _magnet;
|
||||
protected DownloadStationTorrent _singleFile;
|
||||
protected DownloadStationTorrent _multipleFiles;
|
||||
protected DownloadStationTorrent _singleFileCompleted;
|
||||
protected DownloadStationTorrent _multipleFilesCompleted;
|
||||
|
||||
protected string _serialNumber = "SERIALNUMBER";
|
||||
protected string _category = "sonarr";
|
||||
protected string _tvDirectory = @"video/Series";
|
||||
protected string _defaultDestination = "somepath";
|
||||
protected OsPath _physicalPath = new OsPath("/mnt/sdb1/mydata");
|
||||
|
||||
protected Dictionary<string, object> _downloadStationConfigItems;
|
||||
|
||||
protected string DownloadURL => "magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcad53426&dn=download";
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_settings = new DownloadStationSettings()
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
Port = 5000,
|
||||
Username = "admin",
|
||||
Password = "pass"
|
||||
};
|
||||
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = _settings;
|
||||
|
||||
_queued = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id1",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Waiting,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "title",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "0"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_completed = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id2",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Finished,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "title",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "speed_download", "0" }
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
_seeding = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id2",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Seeding,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "title",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_downloading = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id3",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Downloading,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "title",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "100"},
|
||||
{ "speed_download", "50" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_failed = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id4",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Error,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "title",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "10"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_singleFile = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id5",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Seeding,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "a.mkv",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_multipleFiles = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id6",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Seeding,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "title",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_singleFileCompleted = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id6",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Finished,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "a.mkv",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_multipleFilesCompleted = new DownloadStationTorrent()
|
||||
{
|
||||
Id = "id6",
|
||||
Size = 1000,
|
||||
Status = DownloadStationTaskStatus.Finished,
|
||||
Type = DownloadStationTaskType.BT,
|
||||
Username = "admin",
|
||||
Title = "title",
|
||||
Additional = new DownloadStationTorrentAdditional
|
||||
{
|
||||
Detail = new Dictionary<string, string>
|
||||
{
|
||||
{ "destination","shared/folder" },
|
||||
{ "uri", DownloadURL }
|
||||
},
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Mocker.GetMock<ITorrentFileInfoReader>()
|
||||
.Setup(s => s.GetHashFromTorrentFile(It.IsAny<byte[]>()))
|
||||
.Returns("CBC2F069FE8BB2F544EAE707D75BCD3DE9DCF951");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(s => s.Get(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0]));
|
||||
|
||||
_downloadStationConfigItems = new Dictionary<string, object>
|
||||
{
|
||||
{ "default_destination", _defaultDestination },
|
||||
};
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Setup(v => v.GetConfig(It.IsAny<DownloadStationSettings>()))
|
||||
.Returns(_downloadStationConfigItems);
|
||||
}
|
||||
|
||||
protected void GivenSharedFolder()
|
||||
{
|
||||
Mocker.GetMock<ISharedFolderResolver>()
|
||||
.Setup(s => s.RemapToFullPath(It.IsAny<OsPath>(), It.IsAny<DownloadStationSettings>(), It.IsAny<string>()))
|
||||
.Returns<OsPath, DownloadStationSettings, string>((path, setttings, serial) => _physicalPath);
|
||||
}
|
||||
|
||||
protected void GivenSerialNumber()
|
||||
{
|
||||
Mocker.GetMock<ISerialNumberProvider>()
|
||||
.Setup(s => s.GetSerialNumber(It.IsAny<DownloadStationSettings>()))
|
||||
.Returns(_serialNumber);
|
||||
}
|
||||
|
||||
protected void GivenTvCategory()
|
||||
{
|
||||
_settings.TvCategory = _category;
|
||||
}
|
||||
|
||||
protected void GivenTvDirectory()
|
||||
{
|
||||
_settings.TvDirectory = _tvDirectory;
|
||||
}
|
||||
|
||||
protected virtual void GivenTorrents(List<DownloadStationTorrent> torrents)
|
||||
{
|
||||
if (torrents == null)
|
||||
{
|
||||
torrents = new List<DownloadStationTorrent>();
|
||||
}
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Setup(s => s.GetTorrents(It.IsAny<DownloadStationSettings>()))
|
||||
.Returns(torrents);
|
||||
}
|
||||
|
||||
protected void PrepareClientToReturnQueuedItem()
|
||||
{
|
||||
GivenTorrents(new List<DownloadStationTorrent>
|
||||
{
|
||||
_queued
|
||||
});
|
||||
}
|
||||
|
||||
protected void GivenSuccessfulDownload()
|
||||
{
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(s => s.Get(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[1000]));
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Setup(s => s.AddTorrentFromUrl(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||
.Callback(PrepareClientToReturnQueuedItem);
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Setup(s => s.AddTorrentFromData(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DownloadStationSettings>()))
|
||||
.Callback(PrepareClientToReturnQueuedItem);
|
||||
}
|
||||
|
||||
protected override RemoteEpisode CreateRemoteEpisode()
|
||||
{
|
||||
var episode = base.CreateRemoteEpisode();
|
||||
|
||||
episode.Release.DownloadUrl = DownloadURL;
|
||||
|
||||
return episode;
|
||||
}
|
||||
|
||||
protected int GivenAllKindOfTasks()
|
||||
{
|
||||
var tasks = new List<DownloadStationTorrent>() { _queued, _completed, _failed, _downloading, _seeding };
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Setup(d => d.GetTorrents(_settings))
|
||||
.Returns(tasks);
|
||||
|
||||
return tasks.Count;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_with_TvDirectory_should_force_directory()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenTvDirectory();
|
||||
GivenSuccessfulDownload();
|
||||
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
|
||||
var id = Subject.Download(remoteEpisode);
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Verify(v => v.AddTorrentFromUrl(It.IsAny<string>(), _tvDirectory, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_with_category_should_force_directory()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenTvCategory();
|
||||
GivenSuccessfulDownload();
|
||||
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
|
||||
var id = Subject.Download(remoteEpisode);
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Verify(v => v.AddTorrentFromUrl(It.IsAny<string>(), $"{_defaultDestination}/{_category}", It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_without_TvDirectory_and_Category_should_use_default()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSuccessfulDownload();
|
||||
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
|
||||
var id = Subject.Download(remoteEpisode);
|
||||
|
||||
id.Should().NotBeNullOrEmpty();
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Verify(v => v.AddTorrentFromUrl(It.IsAny<string>(), null, It.IsAny<DownloadStationSettings>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_ignore_downloads_in_wrong_folder()
|
||||
{
|
||||
_settings.TvDirectory = @"/shared/folder/sub";
|
||||
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
GivenTorrents(new List<DownloadStationTorrent> { _completed });
|
||||
|
||||
Subject.GetItems().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_throw_if_shared_folder_resolve_fails()
|
||||
{
|
||||
Mocker.GetMock<ISharedFolderResolver>()
|
||||
.Setup(s => s.RemapToFullPath(It.IsAny<OsPath>(), It.IsAny<DownloadStationSettings>(), It.IsAny<string>()))
|
||||
.Throws(new ApplicationException("Some unknown exception, HttpException or DownloadClientException"));
|
||||
|
||||
GivenSerialNumber();
|
||||
GivenAllKindOfTasks();
|
||||
|
||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.GetItems());
|
||||
ExceptionVerification.ExpectedErrors(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_throw_if_serial_number_unavailable()
|
||||
{
|
||||
Mocker.GetMock<ISerialNumberProvider>()
|
||||
.Setup(s => s.GetSerialNumber(_settings))
|
||||
.Throws(new ApplicationException("Some unknown exception, HttpException or DownloadClientException"));
|
||||
|
||||
GivenSharedFolder();
|
||||
GivenAllKindOfTasks();
|
||||
|
||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.GetItems());
|
||||
ExceptionVerification.ExpectedErrors(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Download_should_throw_and_not_add_torrent_if_cannot_get_serial_number()
|
||||
{
|
||||
var remoteEpisode = CreateRemoteEpisode();
|
||||
|
||||
Mocker.GetMock<ISerialNumberProvider>()
|
||||
.Setup(s => s.GetSerialNumber(_settings))
|
||||
.Throws(new ApplicationException("Some unknown exception, HttpException or DownloadClientException"));
|
||||
|
||||
Assert.Throws(Is.InstanceOf<Exception>(), () => Subject.Download(remoteEpisode));
|
||||
|
||||
Mocker.GetMock<IDownloadStationProxy>()
|
||||
.Verify(v => v.AddTorrentFromUrl(It.IsAny<string>(), null, _settings), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_set_outputPath_to_base_folder_when_single_file_non_finished_torrent()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
|
||||
GivenTorrents(new List<DownloadStationTorrent>() { _singleFile });
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().OutputPath.Should().Be(_physicalPath + _singleFile.Title);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_set_outputPath_to_torrent_folder_when_multiple_files_non_finished_torrent()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
|
||||
GivenTorrents(new List<DownloadStationTorrent>() { _multipleFiles });
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().OutputPath.Should().Be(_physicalPath + _multipleFiles.Title);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_set_outputPath_to_base_folder_when_single_file_finished_torrent()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
|
||||
GivenTorrents(new List<DownloadStationTorrent>() { _singleFileCompleted });
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().OutputPath.Should().Be(_physicalPath + _singleFileCompleted.Title);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_set_outputPath_to_torrent_folder_when_multiple_files_finished_torrent()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
|
||||
GivenTorrents(new List<DownloadStationTorrent>() { _multipleFilesCompleted });
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().OutputPath.Should().Be($"{_physicalPath}/{_multipleFiles.Title}");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_not_map_outputpath_for_queued_or_downloading_torrents()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
|
||||
GivenTorrents(new List<DownloadStationTorrent>
|
||||
{
|
||||
_queued, _downloading
|
||||
});
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().HaveCount(2);
|
||||
items.Should().OnlyContain(v => v.OutputPath.IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetItems_should_map_outputpath_for_completed_or_failed_torrents()
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
|
||||
GivenTorrents(new List<DownloadStationTorrent>
|
||||
{
|
||||
_completed, _failed, _seeding
|
||||
});
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().HaveCount(3);
|
||||
items.Should().OnlyContain(v => !v.OutputPath.IsEmpty);
|
||||
}
|
||||
|
||||
[TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading, true)]
|
||||
[TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed, false)]
|
||||
[TestCase(DownloadStationTaskStatus.Seeding, DownloadItemStatus.Completed, true)]
|
||||
[TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued, true)]
|
||||
public void GetItems_should_return_readonly_expected(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus, bool readOnlyExpected)
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
|
||||
_queued.Status = apiStatus;
|
||||
|
||||
GivenTorrents(new List<DownloadStationTorrent>() { _queued });
|
||||
|
||||
var items = Subject.GetItems();
|
||||
|
||||
items.Should().HaveCount(1);
|
||||
items.First().IsReadOnly.Should().Be(readOnlyExpected);
|
||||
}
|
||||
|
||||
[TestCase(DownloadStationTaskStatus.Downloading, DownloadItemStatus.Downloading)]
|
||||
[TestCase(DownloadStationTaskStatus.Error, DownloadItemStatus.Failed)]
|
||||
[TestCase(DownloadStationTaskStatus.Extracting, DownloadItemStatus.Downloading)]
|
||||
[TestCase(DownloadStationTaskStatus.Finished, DownloadItemStatus.Completed)]
|
||||
[TestCase(DownloadStationTaskStatus.Finishing, DownloadItemStatus.Downloading)]
|
||||
[TestCase(DownloadStationTaskStatus.HashChecking, DownloadItemStatus.Downloading)]
|
||||
[TestCase(DownloadStationTaskStatus.Paused, DownloadItemStatus.Paused)]
|
||||
[TestCase(DownloadStationTaskStatus.Seeding, DownloadItemStatus.Completed)]
|
||||
[TestCase(DownloadStationTaskStatus.Waiting, DownloadItemStatus.Queued)]
|
||||
public void GetItems_should_return_item_as_downloadItemStatus(DownloadStationTaskStatus apiStatus, DownloadItemStatus expectedItemStatus)
|
||||
{
|
||||
GivenSerialNumber();
|
||||
GivenSharedFolder();
|
||||
|
||||
_queued.Status = apiStatus;
|
||||
|
||||
GivenTorrents(new List<DownloadStationTorrent>() { _queued });
|
||||
|
||||
var items = Subject.GetItems();
|
||||
items.Should().HaveCount(1);
|
||||
|
||||
items.First().Status.Should().Be(expectedItemStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,14 +92,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
||||
protected void GivenFailedDownload()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<NzbgetSettings>()))
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns((string)null);
|
||||
}
|
||||
|
||||
protected void GivenSuccessfulDownload()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<NzbgetSettings>()))
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns(Guid.NewGuid().ToString().Replace("-", ""));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,22 +20,19 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
public class RemoveGrabbedFixture : CoreTest<PendingReleaseService>
|
||||
{
|
||||
private DownloadDecision _temporarilyRejected;
|
||||
private Series _series;
|
||||
private Movie _series;
|
||||
private Episode _episode;
|
||||
private Profile _profile;
|
||||
private ReleaseInfo _release;
|
||||
private ParsedEpisodeInfo _parsedEpisodeInfo;
|
||||
private RemoteEpisode _remoteEpisode;
|
||||
private ParsedMovieInfo _parsedEpisodeInfo;
|
||||
private RemoteMovie _remoteEpisode;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_series = Builder<Series>.CreateNew()
|
||||
_series = Builder<Movie>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_episode = Builder<Episode>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_profile = new Profile
|
||||
{
|
||||
Name = "Test",
|
||||
@@ -52,13 +49,13 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
|
||||
_release = Builder<ReleaseInfo>.CreateNew().Build();
|
||||
|
||||
_parsedEpisodeInfo = Builder<ParsedEpisodeInfo>.CreateNew().Build();
|
||||
_parsedEpisodeInfo = Builder<ParsedMovieInfo>.CreateNew().Build();
|
||||
_parsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p);
|
||||
|
||||
_remoteEpisode = new RemoteEpisode();
|
||||
_remoteEpisode.Episodes = new List<Episode>{ _episode };
|
||||
_remoteEpisode.Series = _series;
|
||||
_remoteEpisode.ParsedEpisodeInfo = _parsedEpisodeInfo;
|
||||
_remoteEpisode = new RemoteMovie();
|
||||
//_remoteEpisode.Episodes = new List<Episode>{ _episode };
|
||||
_remoteEpisode.Movie = _series;
|
||||
_remoteEpisode.ParsedMovieInfo = _parsedEpisodeInfo;
|
||||
_remoteEpisode.Release = _release;
|
||||
|
||||
_temporarilyRejected = new DownloadDecision(_remoteEpisode, new Rejection("Temp Rejected", RejectionType.Temporary));
|
||||
@@ -67,13 +64,13 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
.Setup(s => s.All())
|
||||
.Returns(new List<PendingRelease>());
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Setup(s => s.GetSeries(It.IsAny<int>()))
|
||||
Mocker.GetMock<IMovieService>()
|
||||
.Setup(s => s.GetMovie(It.IsAny<int>()))
|
||||
.Returns(_series);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.GetEpisodes(It.IsAny<ParsedEpisodeInfo>(), _series, true, null))
|
||||
.Returns(new List<Episode> {_episode});
|
||||
//Mocker.GetMock<IParsingService>()
|
||||
// .Setup(s => s.GetMovie(It.IsAny<ParsedMovieInfo>(), _series.Title))
|
||||
// .Returns(_episode);
|
||||
|
||||
Mocker.GetMock<IPrioritizeDownloadDecision>()
|
||||
.Setup(s => s.PrioritizeDecisions(It.IsAny<List<DownloadDecision>>()))
|
||||
@@ -89,7 +86,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
.All()
|
||||
.With(h => h.SeriesId = _series.Id)
|
||||
.With(h => h.Release = _release.JsonClone())
|
||||
.With(h => h.ParsedEpisodeInfo = parsedEpisodeInfo)
|
||||
.With(h => h.ParsedMovieInfo = _parsedEpisodeInfo)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<IPendingReleaseRepository>()
|
||||
@@ -102,7 +99,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
{
|
||||
GivenHeldRelease(_parsedEpisodeInfo.Quality);
|
||||
|
||||
Subject.Handle(new EpisodeGrabbedEvent(_remoteEpisode));
|
||||
Subject.Handle(new MovieGrabbedEvent(_remoteEpisode));
|
||||
|
||||
VerifyDelete();
|
||||
}
|
||||
@@ -112,7 +109,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
{
|
||||
GivenHeldRelease(new QualityModel(Quality.SDTV));
|
||||
|
||||
Subject.Handle(new EpisodeGrabbedEvent(_remoteEpisode));
|
||||
Subject.Handle(new MovieGrabbedEvent(_remoteEpisode));
|
||||
|
||||
VerifyDelete();
|
||||
}
|
||||
@@ -122,7 +119,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
{
|
||||
GivenHeldRelease(new QualityModel(Quality.Bluray720p));
|
||||
|
||||
Subject.Handle(new EpisodeGrabbedEvent(_remoteEpisode));
|
||||
Subject.Handle(new MovieGrabbedEvent(_remoteEpisode));
|
||||
|
||||
VerifyNoDelete();
|
||||
}
|
||||
|
||||
449
src/NzbDrone.Core.Test/Files/couchpotato_movie_list.json
Normal file
@@ -0,0 +1,449 @@
|
||||
{
|
||||
"movies": [
|
||||
{
|
||||
"status": "active",
|
||||
"info": {
|
||||
"rating": { "imdb": [ 8.1, 228515 ] },
|
||||
"genres": [ "Action", "Adventure", "Fantasy", "Science Fiction", "Thriller", "War", "Sci-Fi" ],
|
||||
"tmdb_id": 330459,
|
||||
"plot": "A rogue band of resistance fighters unite for a mission to steal the Death Star plans and bring a new hope to the galaxy.",
|
||||
"tagline": "A Rebellion Built on Hope",
|
||||
"release_date": {
|
||||
"dvd": 1461016800,
|
||||
"expires": 1486410729,
|
||||
"theater": 1453417200,
|
||||
"bluray": true
|
||||
},
|
||||
"year": 2016,
|
||||
"original_title": "Rogue One: A Star Wars Story",
|
||||
"actor_roles": {
|
||||
"Warwick Davis": "Bistan",
|
||||
"Michael Giacchino": "Stormtrooper",
|
||||
"Lex Lang": "Stormtrooper",
|
||||
"Samuel Witwer": "Stormtrooper",
|
||||
"Steen Young": "Vault Officer",
|
||||
"Russell Balogh": "X-Wing Pilot",
|
||||
"Alan Tudyk": "K-2SO",
|
||||
"Angus Cook": "Mechanic",
|
||||
"David Boat": "Stormtrooper",
|
||||
"Kevin Hickman": "Stormtrooper",
|
||||
"Aidan Cook": "Edrio Two Tubes",
|
||||
"Valene Kane": "Lyra Erso",
|
||||
"Simon Farnaby": "Blue Squadron",
|
||||
"Donnie Yen": "Chirrut Imwe",
|
||||
"Forest Whitaker": "Saw Gerrera",
|
||||
"Jordan Stephens": "Corporal Tonc",
|
||||
"Verona Blue": "Stormtrooper",
|
||||
"David Sobolov": "Stormtrooper",
|
||||
"Attila G. Kerekes": "Rebel Marine on Yavin",
|
||||
"Ian McElhinney": "General Dodonna",
|
||||
"John Gilroy": "Stormtrooper",
|
||||
"Matthew Wood": "Stormtrooper",
|
||||
"Jiang Wen": "Baze Malbus",
|
||||
"Sharon Duncan-Brewster": "Senator Pamlo",
|
||||
"Christopher Scarabosio": "Stormtrooper",
|
||||
"Stephen Stanton": "Admiral Raddus (voice)",
|
||||
"Andrew Zographos": "X-Wing Pilot",
|
||||
"Ben Daniels": "General Merrick",
|
||||
"James Arnold Taylor": "Stormtrooper",
|
||||
"Robin Atkin Downes": "Stormtrooper",
|
||||
"Guy Henry": "Grand Moff Tarkin",
|
||||
"Mac Pietowski": "Commi Tech / Marine Soldier",
|
||||
"James Earl Jones": "Darth Vader (voice)",
|
||||
"Daniel Naprous": "Darth Vader",
|
||||
"Geraldine James": "Blue Squadron",
|
||||
"Eugene Byrd": "Stormtrooper",
|
||||
"Michael Donovan": "Stormtrooper",
|
||||
"Paul Kasey": "Admiral Raddus",
|
||||
"Fred Tatasciore": "Stormtrooper",
|
||||
"Vanessa Lengies": "Stormtrooper",
|
||||
"Duncan Pow": "Sergeant Melshi",
|
||||
"Dolly Gadsdon": "Younger Jyn (as Dolly Gadson)",
|
||||
"David Acord": "Stormtrooper",
|
||||
"Nick Kellington": "Bistan",
|
||||
"Julian Stone": "Stormtrooper",
|
||||
"Christian Simpson": "Stormtrooper",
|
||||
"Alistair Petrie": "General Draven",
|
||||
"Ariyon Bakare": "Blue Squadron",
|
||||
"Drewe Henley": "Red Leader Garven Dreis",
|
||||
"Ram Bergman": "Death Star technician",
|
||||
"Anthony Daniels": "C-3PO",
|
||||
"Derek Arnold": "Pao",
|
||||
"Karen Huie": "Stormtrooper",
|
||||
"Steve Bardrack": "Stormtrooper",
|
||||
"Jonathan Aris": "Senator Jebel",
|
||||
"Alexi Melvin": "Stormtroooper",
|
||||
"Emeson Nwolie": "Personnel",
|
||||
"Tyrone Love": "Rebel Marine Commander",
|
||||
"John S. Schwartz": "Stormtrooper",
|
||||
"Orly Schuchmacher": "Stormtrooper",
|
||||
"Dave Filoni": "Stormtrooper",
|
||||
"Yuri Lowenthal": "Stormtrooper",
|
||||
"Mads Mikkelsen": "Galen Erso",
|
||||
"Fares Fares": "Senator Vaspar",
|
||||
"Ian Whyte": "Moroff",
|
||||
"Genevieve O'Reilly": "Mon Mothma",
|
||||
"Jorge Leon Martinez": "X-Wing Pilot",
|
||||
"Beau Gadsdon": "Young Jyn",
|
||||
"Katie Sheridan": "Stormtrooper",
|
||||
"Michael Smiley": "Dr. Evazan",
|
||||
"Babou Ceesay": "Lieutenant Sefla",
|
||||
"Tom Harrison-Read": "Stormtrooper",
|
||||
"Spencer Wilding": "Darth Vader",
|
||||
"Tom Kane": "Stormtrooper",
|
||||
"Riz Ahmed": "Bodhi Rook",
|
||||
"Ingvild Deila": "Princess Leia",
|
||||
"Tony Gilroy": "Stormtrooper",
|
||||
"Felicity Jones": "Jyn Erso",
|
||||
"Jonathan Dixon": "Stormtrooper",
|
||||
"Angus MacInnes": "Gold Leader Dutch Vander",
|
||||
"William M. Patrick": "Stormtroooper",
|
||||
"Diego Luna": "Captain Cassian Andor",
|
||||
"Sam Hanover": "Imperial Officer",
|
||||
"Jimmy Smits": "Bail Organa",
|
||||
"Ned Dennehy": "Prisoner",
|
||||
"Rian Johnson": "Death Star Technician",
|
||||
"Jimmy Vee": "R2-D2",
|
||||
"David Cowgill": "Stormtrooper",
|
||||
"Vanessa Marshall": "Stormtrooper",
|
||||
"Terri Douglas": "Stormtrooper",
|
||||
"David Ankrum": "Wedge Antilles",
|
||||
"Flora Miller": "Stormtroooper",
|
||||
"Steve Blum": "Stormtrooper",
|
||||
"Ben Mendelsohn": "Director Orson Krennic"
|
||||
},
|
||||
"via_imdb": true,
|
||||
"images": {
|
||||
"disc_art": [],
|
||||
"poster": [ "https://images-na.ssl-images-amazon.com/images/M/MV5BMjEwMzMxODIzOV5BMl5BanBnXkFtZTgwNzg3OTAzMDI@._V1_SX300.jpg" ],
|
||||
"backdrop": [ "https://image.tmdb.org/t/p/w1280/tZjVVIYXACV4IIIhXeIM59ytqwS.jpg" ],
|
||||
"extra_thumbs": [],
|
||||
"poster_original": [ "https://image.tmdb.org/t/p/original/qjiskwlV1qQzRCjpV0cL9pEMF9a.jpg" ],
|
||||
"actors": {
|
||||
"Warwick Davis": "https://image.tmdb.org/t/p/w185/5xBunTQJexQOuCmtlh8MNJerbaM.jpg",
|
||||
"Michael Giacchino": "https://image.tmdb.org/t/p/w185/2YW8sSVvRhCwiQmsFCgtFsGkbv8.jpg",
|
||||
"Michael Smiley": "https://image.tmdb.org/t/p/w185/muzJQpsKJ4srfVpyRa7qkrRYWSq.jpg",
|
||||
"Babou Ceesay": "https://image.tmdb.org/t/p/w185/7HtIvbNxACa03ofJpN4EFQTNtRU.jpg",
|
||||
"Julian Stone": "https://image.tmdb.org/t/p/w185/sNKqRYXFYHCz8lXExXl0DAl3iGD.jpg",
|
||||
"Jordan Stephens": "https://image.tmdb.org/t/p/w185/oCQl5rkRExrDhGXNPeSxsmC5wvk.jpg",
|
||||
"Alistair Petrie": "https://image.tmdb.org/t/p/w185/tC5CHVPnxAMqF0W0csTqcDAawwj.jpg",
|
||||
"Samuel Witwer": "https://image.tmdb.org/t/p/w185/e4FRojd6SmiyRLo2nQQGUXwi16v.jpg",
|
||||
"Ben Daniels": "https://image.tmdb.org/t/p/w185/x6MI4Fdz1XbERbNbXYoxTK6NAgv.jpg",
|
||||
"Ariyon Bakare": "https://image.tmdb.org/t/p/w185/xjJlH9hU58Ocy6GxKfBlEvTif1p.jpg",
|
||||
"James Arnold Taylor": "https://image.tmdb.org/t/p/w185/rAtyfY0diWt078qQIg0IX9xxG9F.jpg",
|
||||
"Robin Atkin Downes": "https://image.tmdb.org/t/p/w185/pCnIQMMgrFc4hBOE4LJDdebqRZ4.jpg",
|
||||
"Drewe Henley": "https://image.tmdb.org/t/p/w185/C28FmnpDyhI9BwD6YjagAe1U53.jpg",
|
||||
"Spencer Wilding": "https://image.tmdb.org/t/p/w185/g3FJIpQZri7gG515rLehuo81T6W.jpg",
|
||||
"Alan Tudyk": "https://image.tmdb.org/t/p/w185/6QuMtbD8kmhpwWhFKfNzEvHRLOu.jpg",
|
||||
"Guy Henry": "https://image.tmdb.org/t/p/w185/zNjPC6BTZj7DZK4KFL0nMC1El2S.jpg",
|
||||
"Angus Cook": "https://image.tmdb.org/t/p/w185/jPc794vF0h8bmslQ3sO8O3vUVIa.jpg",
|
||||
"David Boat": "https://image.tmdb.org/t/p/w185/4ewxttZW0bhlta27oc5Tjrxel3p.jpg",
|
||||
"Tom Kane": "https://image.tmdb.org/t/p/w185/hAyEHNuhD6PqbPdCNR7iUyM271I.jpg",
|
||||
"Anthony Daniels": "https://image.tmdb.org/t/p/w185/cljvryjb3VwTsNR7fjQKjNPMaBB.jpg",
|
||||
"Duncan Pow": "https://image.tmdb.org/t/p/w185/vJOzoMzxszyZGnySfql3KY9zR78.jpg",
|
||||
"Fares Fares": "https://image.tmdb.org/t/p/w185/1BE5IG3hcFXfMjBuJJyKs2JpPjI.jpg",
|
||||
"Tony Gilroy": "https://image.tmdb.org/t/p/w185/9HOtDgcO6F4Fa4BaIjt0t3Vbxrj.jpg",
|
||||
"Felicity Jones": "https://image.tmdb.org/t/p/w185/9YekpRl6ndS7zpY0wwZAWcAXkl8.jpg",
|
||||
"Eugene Byrd": "https://image.tmdb.org/t/p/w185/ab4zEcqdBSjpaz4CPQ2Z6q4rLmO.jpg",
|
||||
"Jonathan Aris": "https://image.tmdb.org/t/p/w185/6RMuwGYfLLGq01LNGBydj9jpTWn.jpg",
|
||||
"Valene Kane": "https://image.tmdb.org/t/p/w185/7TcV6HqGXjf28yjuSU42Z5XZRYb.jpg",
|
||||
"Angus MacInnes": "https://image.tmdb.org/t/p/w185/qftkol8hj7yBBP3KCxRWYkhRyLC.jpg",
|
||||
"James Earl Jones": "https://image.tmdb.org/t/p/w185/2ZuBf3ip2RXhkiQqGUjbUzAf4Nx.jpg",
|
||||
"Emeson Nwolie": "https://image.tmdb.org/t/p/w185/dWCOK3qCOm1Vve567FXKhBp5x8B.jpg",
|
||||
"Terri Douglas": "https://image.tmdb.org/t/p/w185/lECiABogAKm5Zl8Je6niNAoqz5N.jpg",
|
||||
"Simon Farnaby": "https://image.tmdb.org/t/p/w185/3u1ObLUvaTyEMmpWQnkRg5Trlng.jpg",
|
||||
"Donnie Yen": "https://image.tmdb.org/t/p/w185/vlKBbOc0htUsDGvcxeULcFXDMRo.jpg",
|
||||
"Forest Whitaker": "https://image.tmdb.org/t/p/w185/4pMQkelS5lK661m9Kz3oIxLYiyS.jpg",
|
||||
"Diego Luna": "https://image.tmdb.org/t/p/w185/9f1y0pLqohP8U3eEVCa4di1tESb.jpg",
|
||||
"Dave Filoni": "https://image.tmdb.org/t/p/w185/1m7ijGgs29Emn3Sj08c1GwGTUm0.jpg",
|
||||
"Jimmy Smits": "https://image.tmdb.org/t/p/w185/tZfr6EaIxzlT9MhY5T4C6cL3UjF.jpg",
|
||||
"Yuri Lowenthal": "https://image.tmdb.org/t/p/w185/d5vbYEkrPYAiVdTee8e4xCm7Fg1.jpg",
|
||||
"Verona Blue": "https://image.tmdb.org/t/p/w185/9UJiyVd65nGCVLsTuFjtF3ejCqa.jpg",
|
||||
"David Sobolov": "https://image.tmdb.org/t/p/w185/lUXbnlyQPsfAGg0oinCtj6KlOkt.jpg",
|
||||
"Ned Dennehy": "https://image.tmdb.org/t/p/w185/k4kgPvUND2eTrgmotrVWVJM0JUG.jpg",
|
||||
"Ian McElhinney": "https://image.tmdb.org/t/p/w185/33RGircMDTbdvD6LUp8sLmQKWvA.jpg",
|
||||
"Fred Tatasciore": "https://image.tmdb.org/t/p/w185/lNe4zn9fJ302GehQVaFk5BNcGGM.jpg",
|
||||
"Mads Mikkelsen": "https://image.tmdb.org/t/p/w185/nJjN0bS6ssbOrXcnPJrNEIsbX9s.jpg",
|
||||
"Paul Kasey": "https://image.tmdb.org/t/p/w185/56f0ouOg2ASKKKZlaywor8E5V3J.jpg",
|
||||
"David Cowgill": "https://image.tmdb.org/t/p/w185/kcGjj4EuHfMp0VILRVoacoPqNFL.jpg",
|
||||
"Ian Whyte": "https://image.tmdb.org/t/p/w185/6mRY7hTtHfDTGuTLmZmODOu9buF.jpg",
|
||||
"Genevieve O'Reilly": "https://image.tmdb.org/t/p/w185/8NrrFxrGng88GU7lxwOyK3PZv05.jpg",
|
||||
"Jorge Leon Martinez": "https://image.tmdb.org/t/p/w185/nWYveATaySCXosWAjcSS8VNPRe7.jpg",
|
||||
"Katie Sheridan": "https://image.tmdb.org/t/p/w185/awNPsff9HU7NgAhG1qQ4Kh7pMmj.jpg",
|
||||
"Vanessa Marshall": "https://image.tmdb.org/t/p/w185/wOXilt4TVOd0LuTw6RbWhe5DUy4.jpg",
|
||||
"Vanessa Lengies": "https://image.tmdb.org/t/p/w185/vU4syqfb0PYE9efbBq9YZQu24cY.jpg",
|
||||
"David Ankrum": "https://image.tmdb.org/t/p/w185/vo6JMA38exMSSbyQ3K0YCBwBrWT.jpg",
|
||||
"Riz Ahmed": "https://image.tmdb.org/t/p/w185/yWjuIP634unLBCB4XjSgmJs5QGC.jpg",
|
||||
"Steve Blum": "https://image.tmdb.org/t/p/w185/asCL6bWSZ7Xl2kSoRqrPB0CUUUU.jpg",
|
||||
"Rian Johnson": "https://image.tmdb.org/t/p/w185/qWWRFkeMjTjQKoyEXhsV0QQp4qd.jpg",
|
||||
"Matthew Wood": "https://image.tmdb.org/t/p/w185/oB9wVbEIg8fjY3ulDKjKsGn2A55.jpg",
|
||||
"Jiang Wen": "https://image.tmdb.org/t/p/w185/sLLXxXg11VFdVYFthF9RB8wIQKv.jpg",
|
||||
"Ben Mendelsohn": "https://image.tmdb.org/t/p/w185/nAeZkSUXh9CUAUq1cFAg77rZLIS.jpg",
|
||||
"Geraldine James": "https://image.tmdb.org/t/p/w185/iHKFccX2qpSzMbhIBdfvr835MVg.jpg",
|
||||
"Russell Balogh": "https://image.tmdb.org/t/p/w185/yCfE3Pf1npGB15Rw8GHt4nvgK6p.jpg"
|
||||
},
|
||||
"backdrop_original": [ "https://image.tmdb.org/t/p/original/tZjVVIYXACV4IIIhXeIM59ytqwS.jpg" ],
|
||||
"clear_art": [],
|
||||
"logo": [],
|
||||
"banner": [],
|
||||
"landscape": [],
|
||||
"extra_fanart": []
|
||||
},
|
||||
"directors": [ "Gareth Edwards" ],
|
||||
"titles": [ "Rogue One: A Star Wars Story", "Rogue One", "Star Wars: Rogue One", "Star Wars Anthology: Rogue One", "Rogue One: Uma História Star Wars", "星際大戰外傳:俠盜一號", "Rogue One - A Star Wars Story", "星球大战外传:侠盗一号", "Rogue One: История от Междузвездни войни", "Star Wars - Rouge One" ],
|
||||
"imdb": "tt3748528",
|
||||
"mpaa": "PG-13",
|
||||
"via_tmdb": true,
|
||||
"actors": [ "Felicity Jones", "Diego Luna", "Alan Tudyk", "Donnie Yen" ],
|
||||
"writers": [ "Chris Weitz (screenplay)", "Tony Gilroy (screenplay)", "John Knoll (story by)", "Gary Whitta (story by)", "George Lucas (based on characters created by)" ],
|
||||
"runtime": 133,
|
||||
"type": "movie",
|
||||
"released": "16 Dec 2016"
|
||||
},
|
||||
"_t": "media",
|
||||
"releases": [],
|
||||
"title": "Rogue One: A Star Wars Story",
|
||||
"_rev": "00030f77",
|
||||
"profile_id": "38699ec285c447bab0bc6267ffb2f3ad",
|
||||
"_id": "d9d4e0ff9b0842518b9d5f5184a60f31",
|
||||
"category_id": null,
|
||||
"type": "movie",
|
||||
"files": { "image_poster": [ "C:\\Users\\devin\\AppData\\Roaming\\CouchPotato\\cache\\2100049b45a923e858dd161ae28b1f4d.jpg" ] },
|
||||
"identifiers": { "imdb": "tt3748528" }
|
||||
},
|
||||
{
|
||||
"status": "active",
|
||||
"info": {
|
||||
"rating": { "imdb": [ 7.3, 16900 ] },
|
||||
"genres": [ "Animation", "Comedy", "Family", "Music", "Drama" ],
|
||||
"tmdb_id": 335797,
|
||||
"plot": "In a city of humanoid animals, a hustling theater impresario's attempt to save his theater with a singing competition becomes grander than he anticipates even as its finalists' find that their lives will never be the same.",
|
||||
"tagline": "Auditions begin 2016.",
|
||||
"release_date": {
|
||||
"dvd": 1490997600,
|
||||
"expires": 1485114888,
|
||||
"theater": 1482274800,
|
||||
"bluray": true
|
||||
},
|
||||
"year": 2016,
|
||||
"original_title": "Sing",
|
||||
"actor_roles": {
|
||||
"Taron Egerton": "Johnny (voice)",
|
||||
"Catherine Cavadini": "Additional Voices (voice)",
|
||||
"Beck Bennett": "Lance (voice)",
|
||||
"Rhea Perlman": "Judith (voice)",
|
||||
"Jon Robert Hall": "Frog (voice)",
|
||||
"Abby Craden": "Additional Voices (voice)",
|
||||
"Jim Cummings": "Additional Voices (voice)",
|
||||
"Peter Serafinowicz": "Big Daddy (voice)",
|
||||
"Bill Farmer": "News Reporter Dog (voice)",
|
||||
"Jessica Rau": "Additional Voices (voice)",
|
||||
"Townsend Coleman": "Additional Voices (voice)",
|
||||
"Jen Faith Brown": "Singer (voice)",
|
||||
"Brad Morris": "Baboon (voice)",
|
||||
"Doug Burch": "Additional Voices (voice)",
|
||||
"Jennifer Hudson": "Young Nana (voice)",
|
||||
"Laura Dickinson": "Spider (voice)",
|
||||
"Jeremy Maxwell": "Additional Voices (voice)",
|
||||
"Asher Blinkoff": "Piglet (voice)",
|
||||
"Reese Witherspoon": "Rosita (voice)",
|
||||
"Scarlett Johansson": "Ash (voice)",
|
||||
"Carlos Alazraqui": "Additional Voices (voice)",
|
||||
"Edgar Wright": "Additional Voices (voice)",
|
||||
"Asa Jennings": "Piglet (voice)",
|
||||
"Nick Offerman": "Norman (voice)",
|
||||
"Mickael Carreira": "Voice 3",
|
||||
"Sara Mann": "Additional Voices (voice)",
|
||||
"Jay Pharoah": "Meena's Grandfather (voice)",
|
||||
"Adam Buxton": "Stan (voice)",
|
||||
"Garth Jennings": "Miss Crawly / Additional Voices (voice)",
|
||||
"Deolinda Kinzimba": "Voice 4",
|
||||
"Jess Harnell": "Additional Voices (voice)",
|
||||
"Bob Bergen": "Additional Voices (voice)",
|
||||
"Leslie Jones": "Meena's Mother (voice)",
|
||||
"Chris Renaud": "Additional Voices (voice)",
|
||||
"Nick Kroll": "Gunter (voice)",
|
||||
"Seth MacFarlane": "Mike (voice)",
|
||||
"Marisa Liz": "Voice 2",
|
||||
"Áurea": "Voice 1",
|
||||
"Leo Jennings": "Piglet (voice)",
|
||||
"Oscar Jennings": "Piglet (voice)",
|
||||
"Tara Strong": "Additional Voices (voice)",
|
||||
"John C. Reilly": "Eddie (voice)",
|
||||
"Matthew McConaughey": "Buster Moon (voice)",
|
||||
"Caspar Jennings": "Piglet (voice)",
|
||||
"Daamen J. Krall": "Additional Voices (voice)",
|
||||
"Tori Kelly": "Meena (voice)",
|
||||
"Laraine Newman": "Meena's Grandmother / Additional Voices (voice)",
|
||||
"Willow Geer": "Additional Voices (voice)",
|
||||
"Wes Anderson": "Additional Voices (voice)",
|
||||
"Jason Pace": "Additional Voices (voice)",
|
||||
"Jennifer Saunders": "Nana (voice)",
|
||||
"John DeMita": "Additional Voices (voice)"
|
||||
},
|
||||
"via_imdb": true,
|
||||
"images": {
|
||||
"disc_art": [],
|
||||
"poster": [ "https://images-na.ssl-images-amazon.com/images/M/MV5BMTYzODYzODU2Ml5BMl5BanBnXkFtZTgwNTc1MTA2NzE@._V1_SX300.jpg" ],
|
||||
"backdrop": [ "https://image.tmdb.org/t/p/w1280/fxDXp8un4qNY9b1dLd7SH6CKzC.jpg" ],
|
||||
"extra_thumbs": [],
|
||||
"poster_original": [ "https://image.tmdb.org/t/p/original/5XFchtGifv8mz4qlyT8PZ7ZsjfG.jpg" ],
|
||||
"actors": {
|
||||
"Taron Egerton": "https://image.tmdb.org/t/p/w185/bVsLVoO3BGoHRLjWoM4Gjav2hNb.jpg",
|
||||
"Catherine Cavadini": "https://image.tmdb.org/t/p/w185/o2wULQltvbzCTCJitNeT72AjklR.jpg",
|
||||
"Beck Bennett": "https://image.tmdb.org/t/p/w185/oblaqelpyBvtB5GaSgQpDrfka9M.jpg",
|
||||
"Daamen J. Krall": "https://image.tmdb.org/t/p/w185/u0CORJ8e2vvw1dFARU4estHYS2I.jpg",
|
||||
"Rhea Perlman": "https://image.tmdb.org/t/p/w185/cq7Cf4z3BHD9o58ki7MgCioty8q.jpg",
|
||||
"Abby Craden": "https://image.tmdb.org/t/p/w185/biX1xErOEwsuRvidr8Pw6edEyK4.jpg",
|
||||
"Jim Cummings": "https://image.tmdb.org/t/p/w185/i9frXvIJsGtoFikBEFVqE7uN8Bq.jpg",
|
||||
"Peter Serafinowicz": "https://image.tmdb.org/t/p/w185/nfXHDKeetwO16agC0S7tDmLt1il.jpg",
|
||||
"Bill Farmer": "https://image.tmdb.org/t/p/w185/4aDBlkt8nEkr1RkEhiKIbDWhpZB.jpg",
|
||||
"Jessica Rau": "https://image.tmdb.org/t/p/w185/jBbIYc3UQf7JU8ggQVkfezpmgVZ.jpg",
|
||||
"Townsend Coleman": "https://image.tmdb.org/t/p/w185/j7PvxQ7XuOQc1ggSRHWRP6CB8CU.jpg",
|
||||
"Brad Morris": "https://image.tmdb.org/t/p/w185/qX6oVdAt7Vzzcnw28bdXFp05BBH.jpg",
|
||||
"Doug Burch": "https://image.tmdb.org/t/p/w185/zwfqhPuIFrUL70bWPESdJZWXc7F.jpg",
|
||||
"Jennifer Hudson": "https://image.tmdb.org/t/p/w185/zqTu7AANIUsVMAYz5rK1YPnvbWR.jpg",
|
||||
"Asher Blinkoff": "https://image.tmdb.org/t/p/w185/780sIDWQoAIVVaUbAQex50Vam0V.jpg",
|
||||
"Reese Witherspoon": "https://image.tmdb.org/t/p/w185/a3o8T1P6yy4KWL7wZG6HuDeuh5n.jpg",
|
||||
"Scarlett Johansson": "https://image.tmdb.org/t/p/w185/f3c1rwcOoeU0v6Ak5loUvMyifR0.jpg",
|
||||
"Carlos Alazraqui": "https://image.tmdb.org/t/p/w185/o62NevO1Vt9n1MdYsWOsDyhUt3A.jpg",
|
||||
"Nick Offerman": "https://image.tmdb.org/t/p/w185/8rJOtmxL5GIfNdOfksVPzepQOy2.jpg",
|
||||
"Sara Mann": "https://image.tmdb.org/t/p/w185/1TiV16ODOJtTZQrWmHRwOyQnMb0.jpg",
|
||||
"Jay Pharoah": "https://image.tmdb.org/t/p/w185/yRD2vypRF0niEdoCCI0pNZENzvm.jpg",
|
||||
"Tara Strong": "https://image.tmdb.org/t/p/w185/rFUZnJ4BaSaQVKW734xnUHSN9pm.jpg",
|
||||
"Garth Jennings": "https://image.tmdb.org/t/p/w185/ahQh5uW5CXLe1LotxN4Y20aj5Gx.jpg",
|
||||
"Jess Harnell": "https://image.tmdb.org/t/p/w185/k0BOzEyMkZ1CcoCaohjqTyQJjP1.jpg",
|
||||
"Leslie Jones": "https://image.tmdb.org/t/p/w185/2cXrwJoX0QHGBtNMsMLqeF6bR3s.jpg",
|
||||
"Chris Renaud": "https://image.tmdb.org/t/p/w185/yK3RxNsIEBljUe9jPG0iz53Iz6t.jpg",
|
||||
"Nick Kroll": "https://image.tmdb.org/t/p/w185/puZov7sMmuVkvdqJvmlxtWcS1fU.jpg",
|
||||
"Seth MacFarlane": "https://image.tmdb.org/t/p/w185/v4c6JhGYpjMRBwf95gtPxBnElNu.jpg",
|
||||
"Bob Bergen": "https://image.tmdb.org/t/p/w185/kuWDjNTw6OVnc3q1ugMGBYpMMMa.jpg",
|
||||
"Edgar Wright": "https://image.tmdb.org/t/p/w185/ypyH2s4egy5BkviuGDfeltpb19N.jpg",
|
||||
"Matthew McConaughey": "https://image.tmdb.org/t/p/w185/jdRmHrG0TWXGhs4tO6TJNSoL25T.jpg",
|
||||
"John C. Reilly": "https://image.tmdb.org/t/p/w185/kUo2TPQp4kOWWvijvkjLl0v9PQB.jpg",
|
||||
"Adam Buxton": "https://image.tmdb.org/t/p/w185/zL31NlBBKL1NTjR48h610by5Rld.jpg",
|
||||
"Tori Kelly": "https://image.tmdb.org/t/p/w185/dMyLOIOYqTMQtMEiK9DSxxHTz6F.jpg",
|
||||
"Laraine Newman": "https://image.tmdb.org/t/p/w185/ApYftBOqDMBnVColOQwXIodOt5s.jpg",
|
||||
"Willow Geer": "https://image.tmdb.org/t/p/w185/q2TjAxrQSpPPUiTUwFBXcLJ7qxc.jpg",
|
||||
"Wes Anderson": "https://image.tmdb.org/t/p/w185/r6mr3gvbuocMznHXSlXVKDj7mEI.jpg",
|
||||
"Jason Pace": "https://image.tmdb.org/t/p/w185/2q6KfNytYUiHuf8Rx9HyBGoD1T7.jpg",
|
||||
"Jennifer Saunders": "https://image.tmdb.org/t/p/w185/nlxiFy0LUYGlICaFY3rF2DRovcc.jpg",
|
||||
"John DeMita": "https://image.tmdb.org/t/p/w185/lzwHtcKVd5oenYtoFtJYeNddpwT.jpg"
|
||||
},
|
||||
"backdrop_original": [ "https://image.tmdb.org/t/p/original/fxDXp8un4qNY9b1dLd7SH6CKzC.jpg" ],
|
||||
"clear_art": [],
|
||||
"logo": [],
|
||||
"banner": [],
|
||||
"landscape": [],
|
||||
"extra_fanart": []
|
||||
},
|
||||
"directors": [ "Christophe Lourdelet", "Garth Jennings" ],
|
||||
"titles": [ "Sing", "Welcome to the Auditions" ],
|
||||
"imdb": "tt3470600",
|
||||
"mpaa": "PG",
|
||||
"via_tmdb": true,
|
||||
"actors": [ "Matthew McConaughey", "Reese Witherspoon", "Seth MacFarlane", "Scarlett Johansson" ],
|
||||
"writers": [ "Garth Jennings" ],
|
||||
"runtime": 110,
|
||||
"type": "movie",
|
||||
"released": "21 Dec 2016"
|
||||
},
|
||||
"_t": "media",
|
||||
"releases": [],
|
||||
"title": "Sing",
|
||||
"_rev": "00031b86",
|
||||
"profile_id": "38699ec285c447bab0bc6267ffb2f3ad",
|
||||
"_id": "f12dc6bbff294daa85db0d839646442a",
|
||||
"category_id": null,
|
||||
"type": "movie",
|
||||
"files": { "image_poster": [ "C:\\Users\\devin\\AppData\\Roaming\\CouchPotato\\cache\\2ad327d73e8ef4deab7a4b564d3b9cb4.jpg" ] },
|
||||
"identifiers": { "imdb": "tt3470600" }
|
||||
},
|
||||
{
|
||||
"status": "active",
|
||||
"info": {
|
||||
"rating": { "imdb": [ 6.4, 10027 ] },
|
||||
"genres": [ "Action", "Horror" ],
|
||||
"tmdb_id": 346672,
|
||||
"plot": "Vampire death dealer Selene fends off brutal attacks from both the Lycan clan and the Vampire faction that betrayed her. With her only allies, David and his father Thomas, she must stop the eternal war between Lycans and Vampires, even if it means she has to make the ultimate sacrifice.",
|
||||
"tagline": "Protect the Bloodline",
|
||||
"release_date": {
|
||||
"dvd": 1493589600,
|
||||
"expires": 1485114954,
|
||||
"theater": 1483657200,
|
||||
"bluray": true
|
||||
},
|
||||
"year": 2016,
|
||||
"original_title": "Underworld: Blood Wars",
|
||||
"actor_roles": {
|
||||
"India Eisley": "Eve",
|
||||
"Kate Beckinsale": "Selene",
|
||||
"Oliver Stark": "Gregor",
|
||||
"Brian Caspe": "Hajna",
|
||||
"Charles Dance": "Thomas",
|
||||
"Alicia Vela-Bailey": "Safehouse Lycan",
|
||||
"Bradley James": "Varga",
|
||||
"David Bowles": "Grey Lycan",
|
||||
"Theo James": "David",
|
||||
"Lara Pulver": "Semira",
|
||||
"Eva Larvoire": "Tech Lycan",
|
||||
"Tobias Menzies": "Marius",
|
||||
"Daisy Head": "Alexia",
|
||||
"Trent Garrett": "Hybrid Michael"
|
||||
},
|
||||
"via_imdb": true,
|
||||
"images": {
|
||||
"disc_art": [],
|
||||
"poster": [ "https://images-na.ssl-images-amazon.com/images/M/MV5BMjI5Njk0NTIyNV5BMl5BanBnXkFtZTgwNjU4MjY5MDI@._V1_SX300.jpg" ],
|
||||
"backdrop": [ "https://image.tmdb.org/t/p/w1280/PIXSMakrO3s2dqA7mCvAAoVR0E.jpg" ],
|
||||
"extra_thumbs": [],
|
||||
"poster_original": [ "https://image.tmdb.org/t/p/original/nHXiMnWUAUba2LZ0dFkNDVdvJ1o.jpg" ],
|
||||
"actors": {
|
||||
"India Eisley": "https://image.tmdb.org/t/p/w185/njL744BT8mz9jf2TxcZDnSOEZFb.jpg",
|
||||
"Kate Beckinsale": "https://image.tmdb.org/t/p/w185/pTRtcZn9gWQZRiet36qWKh94urn.jpg",
|
||||
"Oliver Stark": "https://image.tmdb.org/t/p/w185/5yULYfaUMymZdSLhk2W96hZIQBP.jpg",
|
||||
"Brian Caspe": "https://image.tmdb.org/t/p/w185/1fDVsCwZOwp97Pdl7q743seHCMP.jpg",
|
||||
"Charles Dance": "https://image.tmdb.org/t/p/w185/bLT03rnI29YmbYWjA1JJCl4xVXw.jpg",
|
||||
"Alicia Vela-Bailey": "https://image.tmdb.org/t/p/w185/kVuyn6sS7ZSBlXVjjxq0LSE3k4I.jpg",
|
||||
"Bradley James": "https://image.tmdb.org/t/p/w185/4XAtJsz67pmpIsCQ9SBKfqayk2d.jpg",
|
||||
"Trent Garrett": "https://image.tmdb.org/t/p/w185/w9J2snV7QI71B5F7rCxfPqeS7GU.jpg",
|
||||
"Theo James": "https://image.tmdb.org/t/p/w185/hLNSoQ3gc52X5VVb172yO3CuUEq.jpg",
|
||||
"Eva Larvoire": "https://image.tmdb.org/t/p/w185/Aq96CWP3Pub2CdWSNbL5eaTwRt0.jpg",
|
||||
"Tobias Menzies": "https://image.tmdb.org/t/p/w185/bXUpxFsIowySRyyqchaE1XprptI.jpg",
|
||||
"Daisy Head": "https://image.tmdb.org/t/p/w185/33JAZTxDWj646mxdW1HksqHOsiY.jpg",
|
||||
"Lara Pulver": "https://image.tmdb.org/t/p/w185/ve68vtNYVXmKjzn81zKhI7TWEvy.jpg"
|
||||
},
|
||||
"backdrop_original": [ "https://image.tmdb.org/t/p/original/PIXSMakrO3s2dqA7mCvAAoVR0E.jpg" ],
|
||||
"clear_art": [],
|
||||
"logo": [],
|
||||
"banner": [],
|
||||
"landscape": [],
|
||||
"extra_fanart": []
|
||||
},
|
||||
"directors": [ "Anna Foerster" ],
|
||||
"titles": [ "Underworld: Blood Wars", "Inframundo: Guerras de Sangre", "Anjos da Noite: Guerras de Sangue", "Underworld Reboot", "Underworld: Next Generation", "決戰異世界:弒血之戰", "Інший світ 5: Кровна помста", "Інший світ 5", "Underworld 5 - Blood Wars" ],
|
||||
"imdb": "tt3717252",
|
||||
"mpaa": "R",
|
||||
"via_tmdb": true,
|
||||
"actors": [ "Kate Beckinsale", "Theo James", "Tobias Menzies", "Lara Pulver" ],
|
||||
"writers": [ "Cory Goodman (screenplay)", "Kyle Ward (story by)", "Cory Goodman (story by)", "Kevin Grevioux (based on characters created by)", "Len Wiseman (based on characters created by)", "Danny McBride (based on characters created by)" ],
|
||||
"runtime": 91,
|
||||
"type": "movie",
|
||||
"released": "06 Jan 2017"
|
||||
},
|
||||
"_t": "media",
|
||||
"releases": [],
|
||||
"title": "Underworld: Blood Wars",
|
||||
"_rev": "00037887",
|
||||
"profile_id": "38699ec285c447bab0bc6267ffb2f3ad",
|
||||
"_id": "4040237fdbd349629a51e29e8ff634f2",
|
||||
"category_id": null,
|
||||
"type": "movie",
|
||||
"files": { "image_poster": [ "C:\\Users\\devin\\AppData\\Roaming\\CouchPotato\\cache\\e41f29a177dd6756dce94f24148c81fe.jpg" ] },
|
||||
"identifiers": { "imdb": "tt3717252" }
|
||||
}
|
||||
],
|
||||
"total": 3,
|
||||
"empty": false,
|
||||
"success": true
|
||||
}
|
||||
1760
src/NzbDrone.Core.Test/Files/imdb_watchlist.xml
Normal file
@@ -45,6 +45,7 @@ namespace NzbDrone.Core.Test.IndexerTests
|
||||
return new IndexerResponse(new IndexerRequest(httpRequest), httpResponse);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_handle_relative_url()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using NUnit.Framework;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.Newznab;
|
||||
using NzbDrone.Core.Indexers.Omgwtfnzbs;
|
||||
using NzbDrone.Core.Indexers.Wombles;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
@@ -22,7 +21,6 @@ namespace NzbDrone.Core.Test.IndexerTests
|
||||
|
||||
_indexers.Add(Mocker.Resolve<Newznab>());
|
||||
_indexers.Add(Mocker.Resolve<Omgwtfnzbs>());
|
||||
_indexers.Add(Mocker.Resolve<Wombles>());
|
||||
|
||||
Mocker.SetConstant<IEnumerable<IIndexer>>(_indexers);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.KickassTorrents;
|
||||
using NzbDrone.Core.Indexers.Nyaa;
|
||||
using NzbDrone.Core.Indexers.Wombles;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
@@ -40,58 +38,6 @@ namespace NzbDrone.Core.Test.IndexerTests.IntegrationTests
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void wombles_fetch_recent()
|
||||
{
|
||||
var indexer = Mocker.Resolve<Wombles>();
|
||||
|
||||
indexer.Definition = new IndexerDefinition
|
||||
{
|
||||
Name = "MyIndexer",
|
||||
Settings = NullConfig.Instance
|
||||
};
|
||||
|
||||
var result = indexer.FetchRecent();
|
||||
|
||||
ValidateResult(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ManualTest]
|
||||
[Explicit]
|
||||
public void kickass_fetch_recent()
|
||||
{
|
||||
var indexer = Mocker.Resolve<KickassTorrents>();
|
||||
|
||||
indexer.Definition = new IndexerDefinition
|
||||
{
|
||||
Name = "MyIndexer",
|
||||
Settings = new KickassTorrentsSettings()
|
||||
};
|
||||
|
||||
var result = indexer.FetchRecent();
|
||||
|
||||
ValidateTorrentResult(result, hasSize: true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ManualTest]
|
||||
[Explicit]
|
||||
public void kickass_search_single()
|
||||
{
|
||||
var indexer = Mocker.Resolve<KickassTorrents>();
|
||||
|
||||
indexer.Definition = new IndexerDefinition
|
||||
{
|
||||
Name = "MyIndexer",
|
||||
Settings = new KickassTorrentsSettings()
|
||||
};
|
||||
|
||||
var result = indexer.Fetch(_singleSearchCriteria);
|
||||
|
||||
ValidateTorrentResult(result, hasSize: true, hasMagnet: true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void nyaa_fetch_recent()
|
||||
{
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.KickassTorrents;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.KickassTorrentsTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class KickassTorrentsFixture : CoreTest<KickassTorrents>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Subject.Definition = new IndexerDefinition()
|
||||
{
|
||||
Name = "Kickass Torrents",
|
||||
Settings = new KickassTorrentsSettings() { VerifiedOnly = false }
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_recent_feed_from_KickassTorrents()
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/KickassTorrents/KickassTorrents.xml");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(5);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = (TorrentInfo) releases.First();
|
||||
|
||||
torrentInfo.Title.Should().Be("Doctor Stranger.E03.140512.HDTV.H264.720p-iPOP.avi [CTRG]");
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("http://torcache.net/torrent/208C4F7866612CC88BFEBC7C496FA72C2368D1C0.torrent?title=%5Bkickass.to%5Ddoctor.stranger.e03.140512.hdtv.h264.720p.ipop.avi.ctrg");
|
||||
torrentInfo.InfoUrl.Should().Be("http://kickass.to/doctor-stranger-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100648.html");
|
||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/05/12 16:16:49"));
|
||||
torrentInfo.Size.Should().Be(1205364736);
|
||||
torrentInfo.InfoHash.Should().Be("208C4F7866612CC88BFEBC7C496FA72C2368D1C0");
|
||||
torrentInfo.MagnetUrl.Should().Be("magnet:?xt=urn:btih:208C4F7866612CC88BFEBC7C496FA72C2368D1C0&dn=doctor+stranger+e03+140512+hdtv+h264+720p+ipop+avi+ctrg&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_empty_list_on_404()
|
||||
{
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.NotFound));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(0);
|
||||
|
||||
ExceptionVerification.IgnoreWarns();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_return_unverified_releases_if_not_configured()
|
||||
{
|
||||
((KickassTorrentsSettings) Subject.Definition.Settings).VerifiedOnly = true;
|
||||
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/KickassTorrents/KickassTorrents.xml");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(4);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_set_seeders_to_null()
|
||||
{
|
||||
// Atm, Kickass supplies 0 as seeders and leechers on the rss feed (but not the site), so set it to null if there aren't any peers.
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/KickassTorrents/KickassTorrents.xml");
|
||||
|
||||
recentFeed = recentFeed.Replace("<pubDate>Mon, 12 May 2014 16:16:49 +0000</pubDate>", string.Format("<pubDate>{0:R}</pubDate>", DateTime.UtcNow));
|
||||
recentFeed = Regex.Replace(recentFeed, @"(seeds|peers)\>\d*", "$1>0");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(5);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = (TorrentInfo)releases.First();
|
||||
|
||||
torrentInfo.Peers.Should().NotHaveValue();
|
||||
torrentInfo.Seeders.Should().NotHaveValue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_set_seeders_to_null_if_has_peers()
|
||||
{
|
||||
// Atm, Kickass supplies 0 as seeders and leechers on the rss feed (but not the site), so set it to null if there aren't any peers.
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/KickassTorrents/KickassTorrents.xml");
|
||||
|
||||
recentFeed = recentFeed.Replace("<pubDate>Mon, 12 May 2014 16:16:49 +0000</pubDate>", string.Format("<pubDate>{0:R}</pubDate>", DateTime.UtcNow));
|
||||
recentFeed = Regex.Replace(recentFeed, @"(seeds)\>\d*", "$1>0");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(5);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = (TorrentInfo)releases.First();
|
||||
|
||||
torrentInfo.Peers.Should().Be(311);
|
||||
torrentInfo.Seeders.Should().Be(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_set_seeders_to_null_if_older_than_12_hours()
|
||||
{
|
||||
// Atm, Kickass supplies 0 as seeders and leechers on the rss feed (but not the site), so set it to null if there aren't any peers.
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/KickassTorrents/KickassTorrents.xml");
|
||||
|
||||
recentFeed = Regex.Replace(recentFeed, @"(seeds|peers)\>\d*", "$1>0");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(5);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = (TorrentInfo)releases.First();
|
||||
|
||||
torrentInfo.Peers.Should().Be(0);
|
||||
torrentInfo.Seeders.Should().Be(0);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_handle_xml_with_html_accents()
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/KickassTorrents/KickassTorrents_accents.xml");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.Wombles;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.WomblesTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class TorrentRssIndexerFixture : CoreTest<Wombles>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
|
||||
Subject.Definition = new IndexerDefinition()
|
||||
{
|
||||
Name = "Wombles",
|
||||
Settings = new NullConfig(),
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenRecentFeedResponse(string rssXmlFile)
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/" + rssXmlFile);
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_recent_feed_from_wombles()
|
||||
{
|
||||
GivenRecentFeedResponse("Wombles/wombles.xml");
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(5);
|
||||
|
||||
var releaseInfo = releases.First();
|
||||
|
||||
releaseInfo.Title.Should().Be("One.Child.S01E01.720p.HDTV.x264-TLA");
|
||||
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
|
||||
releaseInfo.DownloadUrl.Should().Be("http://indexer.local/nzb/bb4/One.Child.S01E01.720p.HDTV.x264-TLA.nzb");
|
||||
releaseInfo.InfoUrl.Should().BeNullOrEmpty();
|
||||
releaseInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2016-02-17 23:03:52 +0000").ToUniversalTime());
|
||||
releaseInfo.Size.Should().Be(956*1024*1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.NetImport;
|
||||
using NzbDrone.Core.NetImport.CouchPotato;
|
||||
using NzbDrone.Core.NetImport.RSSImport;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.NetImport.CouchPotato
|
||||
{
|
||||
public class CouchPotatoTest : CoreTest<CouchPotatoParser>
|
||||
{
|
||||
private NetImportResponse CreateResponse(string url, string content)
|
||||
{
|
||||
var httpRequest = new HttpRequest(url);
|
||||
var httpResponse = new HttpResponse(httpRequest, new HttpHeader(), Encoding.UTF8.GetBytes(content));
|
||||
|
||||
return new NetImportResponse(new NetImportRequest(httpRequest), httpResponse);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_parse_json_of_couchpotato()
|
||||
{
|
||||
var json = ReadAllText("Files/couchpotato_movie_list.json");
|
||||
|
||||
var result = Subject.ParseResponse(CreateResponse("http://my.indexer.com/api?q=My+Favourite+Show", json));
|
||||
|
||||
result.First().Title.Should().Be("Rogue One: A Star Wars Story");
|
||||
result.First().ImdbId.Should().Be("tt3748528");
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/NzbDrone.Core.Test/NetImport/RSSImportFixture.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.NetImport;
|
||||
using NzbDrone.Core.NetImport.RSSImport;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.NetImport
|
||||
{
|
||||
[TestFixture]
|
||||
public class RSSImportFixture : CoreTest<RSSImport>
|
||||
{
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Subject.Definition = Subject.DefaultDefinitions.First();
|
||||
}
|
||||
private void GivenRecentFeedResponse(string rssXmlFile)
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/" + rssXmlFile);
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fetch_imdb_list()
|
||||
{
|
||||
GivenRecentFeedResponse("imdb_watchlist.xml");
|
||||
|
||||
var result = Subject.Fetch();
|
||||
|
||||
result.First().Title.Should().Be("Think Like a Man Too");
|
||||
result.First().ImdbId.Should().Be("tt2239832");
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/NzbDrone.Core.Test/NetImport/RSSImportParserFixture.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.NetImport;
|
||||
using NzbDrone.Core.NetImport.RSSImport;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.NetImport
|
||||
{
|
||||
public class RSSImportTest : CoreTest<RSSImportParser>
|
||||
{
|
||||
private NetImportResponse CreateResponse(string url, string content)
|
||||
{
|
||||
var httpRequest = new HttpRequest(url);
|
||||
var httpResponse = new HttpResponse(httpRequest, new HttpHeader(), Encoding.UTF8.GetBytes(content));
|
||||
|
||||
return new NetImportResponse(new NetImportRequest(httpRequest), httpResponse);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_parse_xml_of_imdb()
|
||||
{
|
||||
var xml = ReadAllText("Files/imdb_watchlist.xml");
|
||||
|
||||
var result = Subject.ParseResponse(CreateResponse("http://my.indexer.com/api?q=My+Favourite+Show", xml));
|
||||
|
||||
result.First().Title.Should().Be("Think Like a Man Too");
|
||||
result.First().ImdbId.Should().Be("tt2239832");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,6 +183,9 @@
|
||||
<Compile Include="Download\DownloadClientTests\TransmissionTests\TransmissionFixtureBase.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\UTorrentTests\UTorrentFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\VuzeTests\VuzeFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\DownloadStationTests\TorrentDownloadStationFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\DownloadStationTests\SerialNumberProviderFixture.cs" />
|
||||
<Compile Include="Download\DownloadClientTests\DownloadStationTests\SharedFolderResolverFixture.cs" />
|
||||
<Compile Include="Download\DownloadServiceFixture.cs" />
|
||||
<Compile Include="Download\FailedDownloadServiceFixture.cs" />
|
||||
<Compile Include="Download\Pending\PendingReleaseServiceTests\PendingReleaseServiceFixture.cs" />
|
||||
@@ -190,6 +193,9 @@
|
||||
<Compile Include="Download\Pending\PendingReleaseServiceTests\RemoveRejectedFixture.cs" />
|
||||
<Compile Include="Download\Pending\PendingReleaseServiceTests\RemoveGrabbedFixture.cs" />
|
||||
<Compile Include="Download\Pending\PendingReleaseServiceTests\AddFixture.cs" />
|
||||
<None Include="Files\couchpotato_movie_list.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Files\Indexers\Rarbg\RecentFeed_v1.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
@@ -254,11 +260,9 @@
|
||||
<Compile Include="IndexerTests\TestIndexer.cs" />
|
||||
<Compile Include="IndexerTests\TestIndexerSettings.cs" />
|
||||
<Compile Include="IndexerTests\IPTorrentsTests\IPTorrentsFixture.cs" />
|
||||
<Compile Include="IndexerTests\KickassTorrentsTests\KickassTorrentsFixture.cs" />
|
||||
<Compile Include="IndexerTests\NyaaTests\NyaaFixture.cs" />
|
||||
<Compile Include="IndexerTests\TorrentRssIndexerTests\TorrentRssIndexerFixture.cs" />
|
||||
<Compile Include="IndexerTests\TorrentRssIndexerTests\TestTorrentRssIndexer.cs" />
|
||||
<Compile Include="IndexerTests\WomblesTests\WomblesFixture.cs" />
|
||||
<Compile Include="IndexerTests\XElementExtensionsFixture.cs" />
|
||||
<Compile Include="InstrumentationTests\DatabaseTargetFixture.cs" />
|
||||
<Compile Include="JobTests\JobRepositoryFixture.cs" />
|
||||
@@ -284,6 +288,9 @@
|
||||
<Compile Include="MetadataSource\SkyHook\SkyHookProxySearchFixture.cs" />
|
||||
<Compile Include="MetadataSource\SearchSeriesComparerFixture.cs" />
|
||||
<Compile Include="MetadataSource\SkyHook\SkyHookProxyFixture.cs" />
|
||||
<Compile Include="NetImport\CouchPotato\CouchPotatoParserFixture.cs" />
|
||||
<Compile Include="NetImport\RSSImportFixture.cs" />
|
||||
<Compile Include="NetImport\RSSImportParserFixture.cs" />
|
||||
<Compile Include="NotificationTests\SynologyIndexerFixture.cs" />
|
||||
<Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" />
|
||||
<Compile Include="OrganizerTests\FileNameBuilderTests\EpisodeTitleCollapseFixture.cs" />
|
||||
@@ -377,6 +384,7 @@
|
||||
<Compile Include="UpdateTests\UpdatePackageProviderFixture.cs" />
|
||||
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
|
||||
<Compile Include="XbmcVersionTests.cs" />
|
||||
<Compile Include="BulkImport\AddMultiMoviesFixture.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
|
||||
@@ -409,6 +417,9 @@
|
||||
<Link>sqlite3.dll</Link>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Files\imdb_watchlist.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="License.txt" />
|
||||
<None Include="Files\Indexers\BroadcastheNet\RecentFeed.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
@@ -565,6 +576,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="ProviderTests\UpdateProviderTests\" />
|
||||
<Folder Include="BulkImport\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
[Ignore("Series")]
|
||||
public class AbsoluteEpisodeNumberParserFixture : CoreTest
|
||||
{
|
||||
[TestCase("[SubDESU]_High_School_DxD_07_(1280x720_x264-AAC)_[6B7FD717]", "High School DxD", 7, 0, 0)]
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
[Ignore("Series")]
|
||||
public class DailyEpisodeParserFixture : CoreTest
|
||||
{
|
||||
[TestCase("Conan 2011 04 18 Emma Roberts HDTV XviD BFF", "Conan", 2011, 04, 18)]
|
||||
|
||||
@@ -47,5 +47,17 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
QualityParser.ParseQuality(title).Revision.Version.Should().Be(version);
|
||||
}
|
||||
|
||||
[TestCase("Deadpool 2016 2160p 4K UltraHD BluRay DTS-HD MA 7 1 x264-Whatevs", 19)]
|
||||
[TestCase("Deadpool 2016 2160p 4K UltraHD DTS-HD MA 7 1 x264-Whatevs", 16)]
|
||||
[TestCase("Deadpool 2016 4K 2160p UltraHD BluRay AAC2 0 HEVC x265", 19)]
|
||||
[TestCase("The Revenant 2015 2160p UHD BluRay DTS x264-Whatevs", 19)]
|
||||
[TestCase("The Revenant 2015 2160p UHD BluRay FLAC 7 1 x264-Whatevs", 19)]
|
||||
[TestCase("The Martian 2015 2160p Ultra HD BluRay DTS-HD MA 7 1 x264-Whatevs", 19)]
|
||||
[TestCase("Into the Inferno 2016 2160p Netflix WEBRip DD5 1 x264-Whatevs", 18)]
|
||||
public void should_parse_ultrahd_from_title(string title, int version)
|
||||
{
|
||||
QualityParser.ParseQuality(title).Quality.Id.Should().Be(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
[Ignore("Series")]
|
||||
public class MiniSeriesEpisodeParserFixture : CoreTest
|
||||
{
|
||||
[TestCase("The.Kennedys.Part.2.DSR.XviD-SYS", "The Kennedys", 2)]
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
[Ignore("Series")]
|
||||
public class MultiEpisodeParserFixture : CoreTest
|
||||
{
|
||||
[TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", "WEEDS", 3, new[] { 1, 2, 3, 4, 5, 6 })]
|
||||
|
||||
@@ -62,5 +62,24 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
Parser.Parser.ParseTitle(postTitle).SeriesTitle.Should().Be(title);
|
||||
}
|
||||
|
||||
[TestCase("The.Man.from.U.N.C.L.E.2015.1080p.BluRay.x264-SPARKS", "The Man from U.N.C.L.E.")]
|
||||
[TestCase("1941.1979.EXTENDED.720p.BluRay.X264-AMIABLE", "1941")]
|
||||
[TestCase("MY MOVIE (2016) [R][Action, Horror][720p.WEB-DL.AVC.8Bit.6ch.AC3].mkv", "MY MOVIE")]
|
||||
[TestCase("R.I.P.D.2013.720p.BluRay.x264-SPARKS", "R.I.P.D.")]
|
||||
[TestCase("V.H.S.2.2013.LIMITED.720p.BluRay.x264-GECKOS", "V.H.S. 2")]
|
||||
[TestCase("This Is A Movie (1999) [IMDB #] <Genre, Genre, Genre> {ACTORS} !DIRECTOR +MORE_SILLY_STUFF_NO_ONE_NEEDS ?", "This Is A Movie")]
|
||||
[TestCase("We Are the Best!.2013.720p.H264.mkv", "We Are the Best!")]
|
||||
[TestCase("(500).Days.Of.Summer.(2009).DTS.1080p.BluRay.x264.NLsubs", "(500) Days Of Summer")]
|
||||
public void should_parse_movie_title(string postTitle, string title)
|
||||
{
|
||||
Parser.Parser.ParseMovieTitle(postTitle).MovieTitle.Should().Be(title);
|
||||
}
|
||||
|
||||
[TestCase("1941.1979.EXTENDED.720p.BluRay.X264-AMIABLE", 1979)]
|
||||
public void should_parse_movie_year(string postTitle, int year)
|
||||
{
|
||||
Parser.Parser.ParseMovieTitle(postTitle).Year.Should().Be(year);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ using NzbDrone.Test.Common;
|
||||
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Series")]
|
||||
public class GetEpisodesFixture : TestBase<ParsingService>
|
||||
{
|
||||
private Series _series;
|
||||
|
||||
@@ -18,6 +18,12 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||
public class MapFixture : TestBase<ParsingService>
|
||||
{
|
||||
private Series _series;
|
||||
private Movie _movie;
|
||||
private ParsedMovieInfo _parsedMovieInfo;
|
||||
private ParsedMovieInfo _wrongYearInfo;
|
||||
private ParsedMovieInfo _romanTitleInfo;
|
||||
private ParsedMovieInfo _alternativeTitleInfo;
|
||||
private MovieSearchCriteria _movieSearchCriteria;
|
||||
private List<Episode> _episodes;
|
||||
private ParsedEpisodeInfo _parsedEpisodeInfo;
|
||||
private SingleEpisodeSearchCriteria _singleEpisodeSearchCriteria;
|
||||
@@ -30,6 +36,13 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||
.With(s => s.CleanTitle = "rock")
|
||||
.Build();
|
||||
|
||||
_movie = Builder<Movie>.CreateNew()
|
||||
.With(m => m.Title = "Mission Impossible 3")
|
||||
.With(m => m.CleanTitle = "missionimpossible3")
|
||||
.With(m => m.Year = 2006)
|
||||
.With(m => m.AlternativeTitles = new List<string> { "Mission Impossible 3: Same same" })
|
||||
.Build();
|
||||
|
||||
_episodes = Builder<Episode>.CreateListOfSize(1)
|
||||
.All()
|
||||
.With(e => e.AirDate = DateTime.Today.ToString(Episode.AIR_DATE_FORMAT))
|
||||
@@ -43,6 +56,31 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||
EpisodeNumbers = new[] { 1 }
|
||||
};
|
||||
|
||||
_parsedMovieInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.Title,
|
||||
Year = _movie.Year,
|
||||
|
||||
};
|
||||
|
||||
_wrongYearInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.Title,
|
||||
Year = 1900,
|
||||
};
|
||||
|
||||
_alternativeTitleInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = _movie.AlternativeTitles.First(),
|
||||
Year = _movie.Year,
|
||||
};
|
||||
|
||||
_romanTitleInfo = new ParsedMovieInfo
|
||||
{
|
||||
MovieTitle = "Mission Impossible III",
|
||||
Year = _movie.Year,
|
||||
};
|
||||
|
||||
_singleEpisodeSearchCriteria = new SingleEpisodeSearchCriteria
|
||||
{
|
||||
Series = _series,
|
||||
@@ -50,27 +88,18 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||
SeasonNumber = _episodes.First().SeasonNumber,
|
||||
Episodes = _episodes
|
||||
};
|
||||
|
||||
_movieSearchCriteria = new MovieSearchCriteria
|
||||
{
|
||||
Movie = _movie
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenMatchBySeriesTitle()
|
||||
private void GivenMatchByMovieTitle()
|
||||
{
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
Mocker.GetMock<IMovieService>()
|
||||
.Setup(s => s.FindByTitle(It.IsAny<string>()))
|
||||
.Returns(_series);
|
||||
}
|
||||
|
||||
private void GivenMatchByTvdbId()
|
||||
{
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Setup(s => s.FindByTvdbId(It.IsAny<Int32>()))
|
||||
.Returns(_series);
|
||||
}
|
||||
|
||||
private void GivenMatchByTvRageId()
|
||||
{
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Setup(s => s.FindByTvRageId(It.IsAny<int>()))
|
||||
.Returns(_series);
|
||||
.Returns(_movie);
|
||||
}
|
||||
|
||||
private void GivenParseResultSeriesDoesntMatchSearchCriteria()
|
||||
@@ -79,121 +108,45 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_lookup_series_by_name()
|
||||
public void should_lookup_Movie_by_name()
|
||||
{
|
||||
GivenMatchBySeriesTitle();
|
||||
GivenMatchByMovieTitle();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
Subject.Map(_parsedMovieInfo, "", null);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
Mocker.GetMock<IMovieService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_tvdbid_when_series_title_lookup_fails()
|
||||
public void should_use_search_criteria_movie_title()
|
||||
{
|
||||
GivenMatchByTvdbId();
|
||||
GivenMatchByMovieTitle();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvdbId(It.IsAny<Int32>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_tvrageid_when_series_title_lookup_fails()
|
||||
{
|
||||
GivenMatchByTvRageId();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 0, _series.TvRageId);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvRageId(It.IsAny<int>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_use_tvrageid_when_scene_naming_exception_exists()
|
||||
{
|
||||
GivenMatchByTvRageId();
|
||||
|
||||
Mocker.GetMock<ISceneMappingService>()
|
||||
.Setup(v => v.FindTvdbId(It.IsAny<string>()))
|
||||
.Returns(10);
|
||||
|
||||
var result = Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvRageId(It.IsAny<int>()), Times.Never());
|
||||
|
||||
result.Series.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_search_criteria_series_title()
|
||||
{
|
||||
GivenMatchBySeriesTitle();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
Subject.Map(_parsedMovieInfo, "", _movieSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_FindByTitle_when_search_criteria_matching_fails()
|
||||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Once());
|
||||
public void should_not_match_with_wrong_year()
|
||||
{
|
||||
GivenMatchByMovieTitle();
|
||||
Subject.Map(_wrongYearInfo, "", _movieSearchCriteria).Movie.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_FindByTvdbId_when_search_criteria_and_FindByTitle_matching_fails()
|
||||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
[Test]
|
||||
public void should_match_alternative_title()
|
||||
{
|
||||
Subject.Map(_alternativeTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
|
||||
}
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, _singleEpisodeSearchCriteria);
|
||||
[Test]
|
||||
public void should_match_roman_title()
|
||||
{
|
||||
Subject.Map(_romanTitleInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
|
||||
}
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvdbId(It.IsAny<Int32>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_FindByTvRageId_when_search_criteria_and_FindByTitle_matching_fails()
|
||||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, 10, 10, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTvRageId(It.IsAny<int>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_tvdbid_matching_when_alias_is_found()
|
||||
{
|
||||
Mocker.GetMock<ISceneMappingService>()
|
||||
.Setup(s => s.FindTvdbId(It.IsAny<string>()))
|
||||
.Returns(_series.TvdbId);
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_use_tvrageid_match_from_search_criteria_when_title_match_fails()
|
||||
{
|
||||
GivenParseResultSeriesDoesntMatchSearchCriteria();
|
||||
|
||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||
|
||||
Mocker.GetMock<ISeriesService>()
|
||||
.Verify(v => v.FindByTitle(It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
[Ignore("Series")]//Is this really necessary with movies? I dont think so
|
||||
public class PathParserFixture : CoreTest
|
||||
{
|
||||
[TestCase(@"z:\tv shows\battlestar galactica (2003)\Season 3\S03E05 - Collaborators.mkv", 3, 5)]
|
||||
|
||||
@@ -79,7 +79,6 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
[TestCase("the.shield.1x13.circles.ws.xvidvd-tns", false)]
|
||||
[TestCase("the_x-files.9x18.sunshine_days.ac3.ws_dvdrip_xvid-fov.avi", false)]
|
||||
[TestCase("[FroZen] Miyuki - 23 [DVD][7F6170E6]", false)]
|
||||
[TestCase("Hannibal.S01E05.576p.BluRay.DD5.1.x264-HiSD", false)]
|
||||
[TestCase("Hannibal.S01E05.480p.BluRay.DD5.1.x264-HiSD", false)]
|
||||
[TestCase("Heidi Girl of the Alps (BD)(640x480(RAW) (BATCH 1) (1-13)", false)]
|
||||
[TestCase("[Doki] Clannad - 02 (848x480 XviD BD MP3) [95360783]", false)]
|
||||
@@ -215,19 +214,26 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
ParseAndVerifyQuality(title, Quality.Bluray1080p, proper);
|
||||
}
|
||||
|
||||
[TestCase("POI S02E11 1080i HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
[TestCase("How I Met Your Mother S01E18 Nothing Good Happens After 2 A.M. 720p HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
[TestCase("The Voice S01E11 The Finals 1080i HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
[TestCase("Californication.S07E11.1080i.HDTV.DD5.1.MPEG2-NTb.ts", false)]
|
||||
[TestCase("Game of Thrones S04E10 1080i HDTV MPEG2 DD5.1-CtrlHD.ts", false)]
|
||||
[TestCase("VICE.S02E05.1080i.HDTV.DD2.0.MPEG2-NTb.ts", false)]
|
||||
[TestCase("Show - S03E01 - Episode Title Raw-HD.ts", false)]
|
||||
[TestCase("Saturday.Night.Live.Vintage.S10E09.Eddie.Murphy.The.Honeydrippers.1080i.UPSCALE.HDTV.DD5.1.MPEG2-zebra", false)]
|
||||
[TestCase("The.Colbert.Report.2011-08-04.1080i.HDTV.MPEG-2-CtrlHD", false)]
|
||||
public void should_parse_raw_quality(string title, bool proper)
|
||||
{
|
||||
ParseAndVerifyQuality(title, Quality.RAWHD, proper);
|
||||
}
|
||||
[TestCase("Movie.Name.2004.576p.BDRip.x264-HANDJOB")]
|
||||
[TestCase("Hannibal.S01E05.576p.BluRay.DD5.1.x264-HiSD")]
|
||||
public void should_parse_bluray576p_quality(string title)
|
||||
{
|
||||
ParseAndVerifyQuality(title, Quality.Bluray576p, false);
|
||||
}
|
||||
|
||||
//[TestCase("POI S02E11 1080i HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
//[TestCase("How I Met Your Mother S01E18 Nothing Good Happens After 2 A.M. 720p HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
//[TestCase("The Voice S01E11 The Finals 1080i HDTV DD5.1 MPEG2-TrollHD", false)]
|
||||
//[TestCase("Californication.S07E11.1080i.HDTV.DD5.1.MPEG2-NTb.ts", false)]
|
||||
//[TestCase("Game of Thrones S04E10 1080i HDTV MPEG2 DD5.1-CtrlHD.ts", false)]
|
||||
//[TestCase("VICE.S02E05.1080i.HDTV.DD2.0.MPEG2-NTb.ts", false)]
|
||||
//[TestCase("Show - S03E01 - Episode Title Raw-HD.ts", false)]
|
||||
//[TestCase("Saturday.Night.Live.Vintage.S10E09.Eddie.Murphy.The.Honeydrippers.1080i.UPSCALE.HDTV.DD5.1.MPEG2-zebra", false)]
|
||||
//[TestCase("The.Colbert.Report.2011-08-04.1080i.HDTV.MPEG-2-CtrlHD", false)]
|
||||
//public void should_parse_raw_quality(string title, bool proper)
|
||||
//{
|
||||
// ParseAndVerifyQuality(title, Quality.RAWHD, proper);
|
||||
//}
|
||||
|
||||
[TestCase("Sonny.With.a.Chance.S02E15", false)]
|
||||
[TestCase("Law & Order: Special Victims Unit - 11x11 - Quickie", false)]
|
||||
@@ -275,6 +281,15 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
QualityParser.ParseQuality(title).QualitySource.Should().Be(QualitySource.Extension);
|
||||
}
|
||||
|
||||
[TestCase("Movie.Title.2016.1080p.KORSUB.WEBRip.x264.AAC2.0-RADARR", "korsub")]
|
||||
[TestCase("Movie.Title.2016.1080p.KORSUBS.WEBRip.x264.AAC2.0-RADARR", "korsubs")]
|
||||
[TestCase("Movie.Title.2016.1080p.DKSUB.WEBRip.x264.AAC2.0-RADARR", "dksub")]
|
||||
[TestCase("Movie.Title.2016.1080p.DKSUBS.WEBRip.x264.AAC2.0-RADARR", "dksubs")]
|
||||
public void should_parse_hardcoded_subs(string postTitle, string sub)
|
||||
{
|
||||
QualityParser.ParseQuality(postTitle).HardcodedSubs.Should().Be(sub);
|
||||
}
|
||||
|
||||
private void ParseAndVerifyQuality(string title, Quality quality, bool proper)
|
||||
{
|
||||
var result = QualityParser.ParseQuality(title);
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
[Ignore("Series")]
|
||||
public class SeasonParserFixture : CoreTest
|
||||
{
|
||||
[TestCase("30.Rock.Season.04.HDTV.XviD-DIMENSION", "30 Rock", 4)]
|
||||
|
||||
@@ -5,6 +5,7 @@ using NzbDrone.Core.Test.Framework;
|
||||
namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("Series")]
|
||||
public class SeriesTitleInfoFixture : CoreTest
|
||||
{
|
||||
[Test]
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
[Ignore("Series")]
|
||||
public class SingleEpisodeParserFixture : CoreTest
|
||||
{
|
||||
[TestCase("Sonny.With.a.Chance.S02E15", "Sonny With a Chance", 2, 15)]
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Core.Test.Qualities
|
||||
new object[] {7, Quality.Bluray1080p},
|
||||
new object[] {8, Quality.WEBDL480p},
|
||||
new object[] {9, Quality.HDTV1080p},
|
||||
new object[] {10, Quality.RAWHD},
|
||||
//new object[] {10, Quality.RAWHD},
|
||||
new object[] {16, Quality.HDTV2160p},
|
||||
new object[] {18, Quality.WEBDL2160p},
|
||||
new object[] {19, Quality.Bluray2160p},
|
||||
@@ -41,7 +41,7 @@ namespace NzbDrone.Core.Test.Qualities
|
||||
new object[] {Quality.Bluray1080p, 7},
|
||||
new object[] {Quality.WEBDL480p, 8},
|
||||
new object[] {Quality.HDTV1080p, 9},
|
||||
new object[] {Quality.RAWHD, 10},
|
||||
//new object[] {Quality.RAWHD, 10},
|
||||
new object[] {Quality.HDTV2160p, 16},
|
||||
new object[] {Quality.WEBDL2160p, 18},
|
||||
new object[] {Quality.Bluray2160p, 19},
|
||||
@@ -65,20 +65,27 @@ namespace NzbDrone.Core.Test.Qualities
|
||||
{
|
||||
var qualities = new List<Quality>
|
||||
{
|
||||
Quality.Unknown,
|
||||
Quality.CAM,
|
||||
Quality.TELECINE,
|
||||
Quality.DVDSCR,
|
||||
Quality.REGIONAL,
|
||||
Quality.SDTV,
|
||||
Quality.WEBDL480p,
|
||||
Quality.DVD,
|
||||
Quality.DVDR,
|
||||
Quality.HDTV720p,
|
||||
Quality.HDTV1080p,
|
||||
Quality.HDTV2160p,
|
||||
Quality.RAWHD,
|
||||
Quality.WEBDL480p,
|
||||
Quality.WEBDL720p,
|
||||
Quality.WEBDL1080p,
|
||||
Quality.WEBDL2160p,
|
||||
Quality.Bluray480p,
|
||||
Quality.Bluray576p,
|
||||
Quality.Bluray720p,
|
||||
Quality.Bluray1080p,
|
||||
Quality.Bluray2160p,
|
||||
Quality.BRDISK,
|
||||
Quality.RAWHD
|
||||
};
|
||||
|
||||
if (allowed.Length == 0)
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||
{
|
||||
new ProfileQualityItem { Allowed = true, Quality = Quality.SDTV },
|
||||
new ProfileQualityItem { Allowed = true, Quality = Quality.WEBDL480p },
|
||||
new ProfileQualityItem { Allowed = true, Quality = Quality.RAWHD }
|
||||
//new ProfileQualityItem { Allowed = true, Quality = Quality.RAWHD }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,13 +71,13 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||
|
||||
var qualityMet = new EpisodeFile { RelativePath = "a", Quality = new QualityModel { Quality = Quality.WEBDL480p } };
|
||||
var qualityUnmet = new EpisodeFile { RelativePath = "b", Quality = new QualityModel { Quality = Quality.SDTV } };
|
||||
var qualityRawHD = new EpisodeFile { RelativePath = "c", Quality = new QualityModel { Quality = Quality.RAWHD } };
|
||||
//var qualityRawHD = new EpisodeFile { RelativePath = "c", Quality = new QualityModel { Quality = Quality.RAWHD } };
|
||||
|
||||
MediaFileRepository fileRepository = Mocker.Resolve<MediaFileRepository>();
|
||||
|
||||
qualityMet = fileRepository.Insert(qualityMet);
|
||||
qualityUnmet = fileRepository.Insert(qualityUnmet);
|
||||
qualityRawHD = fileRepository.Insert(qualityRawHD);
|
||||
//qualityRawHD = fileRepository.Insert(qualityRawHD);
|
||||
|
||||
var monitoredSeriesEpisodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
@@ -90,8 +90,8 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||
.With(e => e.Monitored = false)
|
||||
.With(e => e.EpisodeFileId = qualityMet.Id)
|
||||
.TheNext(1)
|
||||
.With(e => e.EpisodeFileId = qualityRawHD.Id)
|
||||
.TheLast(1)
|
||||
//.With(e => e.EpisodeFileId = qualityRawHD.Id)
|
||||
//.TheLast(1)
|
||||
.With(e => e.SeasonNumber = 0)
|
||||
.Build();
|
||||
|
||||
|
||||
@@ -1,40 +1,39 @@
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AddSeriesFixture : CoreTest<SeriesService>
|
||||
{
|
||||
private Series fakeSeries;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
fakeSeries = Builder<Series>.CreateNew().Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void series_added_event_should_have_proper_path()
|
||||
{
|
||||
fakeSeries.Path = null;
|
||||
fakeSeries.RootFolderPath = @"C:\Test\TV";
|
||||
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
.Setup(s => s.GetSeriesFolder(fakeSeries, null))
|
||||
.Returns(fakeSeries.Title);
|
||||
|
||||
var series = Subject.AddSeries(fakeSeries);
|
||||
|
||||
series.Path.Should().NotBeNull();
|
||||
|
||||
VerifyEventPublished<SeriesAddedEvent>();
|
||||
}
|
||||
|
||||
}
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
namespace NzbDrone.Core.Test.TvTests.SeriesServiceTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AddSeriesFixture : CoreTest<SeriesService>
|
||||
{
|
||||
private Series fakeSeries;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
fakeSeries = Builder<Series>.CreateNew().Build();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void series_added_event_should_have_proper_path()
|
||||
{
|
||||
fakeSeries.Path = null;
|
||||
fakeSeries.RootFolderPath = @"C:\Test\TV";
|
||||
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
.Setup(s => s.GetSeriesFolder(fakeSeries, null))
|
||||
.Returns(fakeSeries.Title);
|
||||
|
||||
var series = Subject.AddSeries(fakeSeries);
|
||||
|
||||
series.Path.Should().NotBeNull();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ namespace NzbDrone.Core.Blacklisting
|
||||
{
|
||||
public int SeriesId { get; set; }
|
||||
public Series Series { get; set; }
|
||||
public int MovieId { get; set; }
|
||||
public Movie Movie { get; set; }
|
||||
public List<int> EpisodeIds { get; set; }
|
||||
public string SourceTitle { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace NzbDrone.Core.Blacklisting
|
||||
{
|
||||
List<Blacklist> BlacklistedByTitle(int seriesId, string sourceTitle);
|
||||
List<Blacklist> BlacklistedByTorrentInfoHash(int seriesId, string torrentInfoHash);
|
||||
List<Blacklist> BlacklistedBySeries(int seriesId);
|
||||
List<Blacklist> BlacklistedByMovie(int seriesId);
|
||||
}
|
||||
|
||||
public class BlacklistRepository : BasicRepository<Blacklist>, IBlacklistRepository
|
||||
@@ -20,15 +20,15 @@ namespace NzbDrone.Core.Blacklisting
|
||||
{
|
||||
}
|
||||
|
||||
public List<Blacklist> BlacklistedByTitle(int seriesId, string sourceTitle)
|
||||
public List<Blacklist> BlacklistedByTitle(int movieId, string sourceTitle)
|
||||
{
|
||||
return Query.Where(e => e.SeriesId == seriesId)
|
||||
return Query.Where(e => e.MovieId == movieId)
|
||||
.AndWhere(e => e.SourceTitle.Contains(sourceTitle));
|
||||
}
|
||||
|
||||
public List<Blacklist> BlacklistedByTorrentInfoHash(int seriesId, string torrentInfoHash)
|
||||
public List<Blacklist> BlacklistedByTorrentInfoHash(int movieId, string torrentInfoHash)
|
||||
{
|
||||
return Query.Where(e => e.SeriesId == seriesId)
|
||||
return Query.Where(e => e.MovieId == movieId)
|
||||
.AndWhere(e => e.TorrentInfoHash.Contains(torrentInfoHash));
|
||||
}
|
||||
|
||||
@@ -37,9 +37,14 @@ namespace NzbDrone.Core.Blacklisting
|
||||
return Query.Where(b => b.SeriesId == seriesId);
|
||||
}
|
||||
|
||||
public List<Blacklist> BlacklistedByMovie(int movieId)
|
||||
{
|
||||
return Query.Where(b => b.MovieId == movieId);
|
||||
}
|
||||
|
||||
protected override SortBuilder<Blacklist> GetPagedQuery(QueryBuilder<Blacklist> query, PagingSpec<Blacklist> pagingSpec)
|
||||
{
|
||||
var baseQuery = query.Join<Blacklist, Series>(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id);
|
||||
var baseQuery = query.Join<Blacklist, Movie>(JoinType.Inner, h => h.Movie, (h, s) => h.MovieId == s.Id);
|
||||
|
||||
return base.GetPagedQuery(baseQuery, pagingSpec);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.Blacklisting
|
||||
|
||||
IExecute<ClearBlacklistCommand>,
|
||||
IHandle<DownloadFailedEvent>,
|
||||
IHandleAsync<SeriesDeletedEvent>
|
||||
IHandleAsync<MovieDeletedEvent>
|
||||
{
|
||||
private readonly IBlacklistRepository _blacklistRepository;
|
||||
|
||||
@@ -128,8 +128,9 @@ namespace NzbDrone.Core.Blacklisting
|
||||
{
|
||||
var blacklist = new Blacklist
|
||||
{
|
||||
SeriesId = message.SeriesId,
|
||||
SeriesId = 0,
|
||||
EpisodeIds = message.EpisodeIds,
|
||||
MovieId = message.MovieId,
|
||||
SourceTitle = message.SourceTitle,
|
||||
Quality = message.Quality,
|
||||
Date = DateTime.UtcNow,
|
||||
@@ -144,9 +145,9 @@ namespace NzbDrone.Core.Blacklisting
|
||||
_blacklistRepository.Insert(blacklist);
|
||||
}
|
||||
|
||||
public void HandleAsync(SeriesDeletedEvent message)
|
||||
public void HandleAsync(MovieDeletedEvent message)
|
||||
{
|
||||
var blacklisted = _blacklistRepository.BlacklistedBySeries(message.Series.Id);
|
||||
var blacklisted = _blacklistRepository.BlacklistedByMovie(message.Movie.Id);
|
||||
|
||||
_blacklistRepository.DeleteMany(blacklisted);
|
||||
}
|
||||
|
||||
@@ -100,11 +100,18 @@ namespace NzbDrone.Core.Configuration
|
||||
|
||||
public int RssSyncInterval
|
||||
{
|
||||
get { return GetValueInt("RssSyncInterval", 15); }
|
||||
get { return GetValueInt("RssSyncInterval", 60); }
|
||||
|
||||
set { SetValue("RssSyncInterval", value); }
|
||||
}
|
||||
|
||||
public int NetImportSyncInterval
|
||||
{
|
||||
get { return GetValueInt("NetImportSyncInterval", 60); }
|
||||
|
||||
set { SetValue("NetImportSyncInterval", value); }
|
||||
}
|
||||
|
||||
public int MinimumAge
|
||||
{
|
||||
get { return GetValueInt("MinimumAge", 0); }
|
||||
@@ -169,7 +176,7 @@ namespace NzbDrone.Core.Configuration
|
||||
|
||||
public int DownloadedEpisodesScanInterval
|
||||
{
|
||||
get { return GetValueInt("DownloadedEpisodesScanInterval", 1); }
|
||||
get { return GetValueInt("DownloadedEpisodesScanInterval", 0); }
|
||||
|
||||
set { SetValue("DownloadedEpisodesScanInterval", value); }
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace NzbDrone.Core.Configuration
|
||||
int RssSyncInterval { get; set; }
|
||||
int MinimumAge { get; set; }
|
||||
|
||||
int NetImportSyncInterval { get; set; }
|
||||
|
||||
//UI
|
||||
int FirstDayOfWeek { get; set; }
|
||||
string CalendarWeekColumnHeader { get; set; }
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(119)]
|
||||
public class add_youtube_trailer_id : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Movies").AddColumn("YouTubeTrailerId").AsString().Nullable();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(120)]
|
||||
public class add_studio : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Movies").AddColumn("Studio").AsString().Nullable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(121)]
|
||||
public class update_filedate_config : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(SetTitleSlug);
|
||||
}
|
||||
|
||||
private void SetTitleSlug(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||
{
|
||||
getSeriesCmd.Transaction = tran;
|
||||
getSeriesCmd.CommandText = @"SELECT Id, Value FROM Config WHERE Key = 'filedate'";
|
||||
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||
{
|
||||
while (seriesReader.Read())
|
||||
{
|
||||
var id = seriesReader.GetInt32(0);
|
||||
var value = seriesReader.GetString(1);
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "UPDATE Config SET Value = 'Release' WHERE Id = ?";
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToUrlSlug(string value)
|
||||
{
|
||||
//First to lower case
|
||||
value = value.ToLowerInvariant();
|
||||
|
||||
//Remove all accents
|
||||
var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(value);
|
||||
value = Encoding.ASCII.GetString(bytes);
|
||||
|
||||
//Replace spaces
|
||||
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
|
||||
|
||||
//Remove invalid chars
|
||||
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
|
||||
|
||||
//Trim dashes from end
|
||||
value = value.Trim('-', '_');
|
||||
|
||||
//Replace double occurences of - or _
|
||||
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(122)]
|
||||
public class add_movieid_to_blacklist : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Blacklist").AddColumn("MovieId").AsInt32().Nullable().WithDefaultValue(0);
|
||||
Alter.Table("Blacklist").AlterColumn("SeriesId").AsInt32().Nullable();
|
||||
Alter.Table("Blacklist").AlterColumn("EpisodeIds").AsString().Nullable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using FluentMigrator;
|
||||
using FluentMigrator.Expressions;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(123)]
|
||||
public class create_netimport_table : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
if (!this.Schema.Schema("dbo").Table("NetImport").Exists())
|
||||
{
|
||||
Create.TableForModel("NetImport")
|
||||
.WithColumn("Enabled").AsBoolean()
|
||||
.WithColumn("Name").AsString().Unique()
|
||||
.WithColumn("Implementation").AsString()
|
||||
.WithColumn("ConfigContract").AsString().Nullable()
|
||||
.WithColumn("Settings").AsString().Nullable()
|
||||
.WithColumn("EnableAuto").AsInt32()
|
||||
.WithColumn("RootFolderPath").AsString()
|
||||
.WithColumn("ShouldMonitor").AsInt32()
|
||||
.WithColumn("ProfileId").AsInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(124)]
|
||||
public class add_preferred_tags_to_profile : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Profiles").AddColumn("PreferredTags").AsString().Nullable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
31
src/NzbDrone.Core/Datastore/Migration/125_fix_imdb_unique.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(125)]
|
||||
public class fix_imdb_unique : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(DeleteUniqueIndex);
|
||||
}
|
||||
|
||||
private void DeleteUniqueIndex(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||
{
|
||||
getSeriesCmd.Transaction = tran;
|
||||
getSeriesCmd.CommandText = @"DROP INDEX 'IX_Movies_ImdbId'";
|
||||
|
||||
getSeriesCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||