1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-15 15:54:47 -04:00

Compare commits

...

145 Commits

Author SHA1 Message Date
Leonardo Galli
3d67f6237e Should fix 4K releases not getting parsed. 2017-01-21 00:39:44 +01:00
Krystian Charubin
a691ffa7b7 adds 'Movie Title, The' filename option (#359)
* adds 'Movie Title, The' filename option
* updates the FileNameBuilder.MovieTitleRegex to include new format
2017-01-20 17:42:14 -05:00
Leonardo Galli
aa9537c201 Fix issue when movie file is null. 2017-01-20 20:30:36 +01:00
Leonardo Galli
a3d9fb1c20 Should fix upgrading of existing movie files. 2017-01-20 18:26:18 +01:00
Leonardo Galli
62a1e70c86 Add tests for 4K quality. 2017-01-20 18:21:31 +01:00
Leonardo Galli
93d0d21846 Hopefully a fix for corrupt media covers. 2017-01-20 18:06:58 +01:00
Leonardo Galli
b1c5a3ac14 Fixed blacklist being ignored by download decision maker. 2017-01-20 17:48:47 +01:00
vertigo235
55a525ba2f Add helptext to nzbget "add paused" settings. (#363)
Requires nzbget 16 or greater.
2017-01-20 09:14:15 -05:00
Devin Buhl
a53768463b Merge pull request #358 from Radarr/patch/add-year-to-search
add year to search
2017-01-19 20:07:33 -05:00
Tim Turner
24cbd6bcef Fix issue with reimporting on movie fresh (#357)
Fixes #314. Still have multiple movieFiles issue to clean up.
2017-01-19 19:58:57 -05:00
Devin Buhl
3ab3e66853 Add year to quick search results 2017-01-19 19:56:26 -05:00
Leonardo Galli
40ca469339 Update MovieModule 2017-01-20 00:00:12 +01:00
Tim Turner
2cbd2f719f Merge branch 'develop' of https://github.com/Radarr/Radarr into develop 2017-01-19 16:45:39 -05:00
Tim Turner
53cbfa803b Fix MediaCoversUpdatedEvent broadcast
Cleans exception when updating media covers expects a series Id.
2017-01-19 16:45:29 -05:00
Leonardo Galli
c0b0310bbd Update ISSUE_TEMPLATE.md 2017-01-19 22:10:59 +01:00
Devin Buhl
30e50062a8 Merge pull request #352 from baltoaca/develop
bug fix for 15 movie wanted tab limit
2017-01-19 13:17:40 -05:00
Vlad Ilies
85fd8f2c65 bug fix for 15 movie wanted tab (#348) 2017-01-19 20:08:15 +02:00
Leonardo Galli
f72b042d5d Blacklisting works now. 2017-01-19 17:43:23 +01:00
Leonardo Galli
2d3a3a0677 Update sizing information in settings tab. 2017-01-19 17:40:25 +01:00
Tim Turner
2bb21fedab Update height of posters to accomodate additional labels 2017-01-18 17:24:32 -05:00
vertigo235
91c820f98b Fix pushover priority values. 2017-01-18 23:16:57 +01:00
Leonardo Galli
7d3118aece Hopefully fix issue when importing
existing scene named movies
2017-01-18 23:02:05 +01:00
Tim Turner
4f4ad77ad1 Add download status to poster view
Fixes #319
2017-01-18 16:54:17 -05:00
Leonardo Galli
42f205a731 Update SkyHookProxy.cs 2017-01-18 22:50:12 +01:00
Devin Buhl
cbb2b778a6 Merge pull request #336 from Radarr/patch/add-imdb-to-naming
Add IMDb ID to file naming
2017-01-18 15:11:16 -05:00
Devin Buhl
b3e03a648d Add IMDb ID to file naming 2017-01-18 14:53:29 -05:00
Devin Buhl
acf45a79e8 Merge pull request #333 from baltoaca/develop
basic implementation of the wanted tab
2017-01-18 14:36:48 -05:00
Devin Buhl
b5d8ac852e Merge pull request #335 from Radarr/patch/task-updates
Turn off scene mapping task #329, update TaskManager to use 'DownloadedMovieScanCommand
2017-01-18 14:36:29 -05:00
Vlad Ilies
4aec0e8fc6 fixed build 2017-01-18 21:09:00 +02:00
Devin Buhl
ecea417fd8 Revert DownloadedMovieScanCommand to DownloadedEpisodesScanCommand
Not sure if it will break anything so putting it back.
2017-01-18 14:07:51 -05:00
Devin Buhl
6a41f6a435 Turn off scene mapping task #329, update TaskManager to use 'DownloadedMovieScanCommand' 2017-01-18 14:02:04 -05:00
Vlad Ilies
da2d075aa8 basic implementation of the wanted tab (#31)
* top buttons don't yet work

* new missing module for movies

*  find missing movies method to movie service

* new movie status cell with text

* adapted UI missing collection and layout
2017-01-18 20:53:17 +02:00
Devin Buhl
10dc3993df Merge pull request #332 from Radarr/revert-318-sonarr/sqlite-updates
Revert "Sonarr/sqlite updates"
2017-01-18 13:33:46 -05:00
Devin Buhl
7e5020db9a Merge pull request #331 from vertigo235/nzbgetaddpaused
Nzbgetaddpaused
2017-01-18 13:20:12 -05:00
Devin Buhl
c48fe9de12 Revert "Sonarr/sqlite updates" 2017-01-18 13:17:35 -05:00
vertigo235
421e827a95 Update Test Files for AddPaused to NZBGET 2017-01-18 13:08:59 -05:00
vertigo235
34d8045cf4 Add "Add Paused" option for NZBGET downloader
Adds option to pause nzbs uppon sending to NZBGET downloader.
2017-01-18 12:42:33 -05:00
Devin Buhl
c6de163748 Merge pull request #318 from Radarr/sonarr/sqlite-updates
Sonarr/sqlite updates
2017-01-17 18:59:11 -05:00
Keivan Beigi
d9e2b22e74 Upgraded System.Data.SQLite to 1.0.104.0 2017-01-17 18:45:23 -05:00
Keivan Beigi
65c0137964 Revert "Upgraded System.Data.SQLite to 1.0.104.0"
This reverts commit a6f3ac219d61964f1b923cfd89382f94c4c74243.
2017-01-17 18:44:37 -05:00
Keivan
ae19424ce7 New: Upgraded SQLite binares for macOS
Upgraded from 3.8.1 to 3.9.1
2017-01-17 18:41:11 -05:00
Keivan Beigi
7527ec52b7 New: Upgraded SQLite binaries for Windows (3.16.0) 2017-01-17 18:41:05 -05:00
Leonardo Galli
640fcf3eaf Remove series references 2017-01-17 23:57:04 +01:00
Leonardo Galli
3ce8232777 Hopefully fix download ordering. 2017-01-17 23:30:11 +01:00
Devin Buhl
864b441d8e Merge pull request #316 from Radarr/patch/skyhook-cleanup
Maybe this will solve the error Object reference not set to an instance of an object
2017-01-17 17:20:49 -05:00
Devin Buhl
bc2ff149b4 Maybe this will solve the error
Couldn't refresh info for [tt2032572][USS Indianapolis: Men of Courage]: Object reference not set to an instance of an object
2017-01-17 17:05:19 -05:00
Devin Buhl
dea305e921 Fix Issue when adding some movies. 2017-01-17 22:25:49 +01:00
Leonardo Galli
e2eab31548 Hopefully fix RSSSync 2017-01-17 21:22:51 +01:00
Devin Buhl
fe62e18f0d Merge pull request #308 from Radarr/patch/jackett
Fix publish date for jackett #239
2017-01-17 13:56:47 -05:00
Devin Buhl
f1fa1553cf Merge pull request #307 from aenima99x/aenima99x-issue91
Fix: Issue #91 - "Search All Missing" wording
2017-01-17 13:48:30 -05:00
Devin Buhl
b576ae813d Fix publish date #239 2017-01-17 13:47:11 -05:00
Aenima99x
99123be936 Fix: Issue #91 - "Search All Missing" wording 2017-01-17 09:00:56 -08:00
Leonardo Galli
dd0a033b0f Add Support for changing file date to either cinema or physical release.
Fixes #124
2017-01-17 15:02:48 +01:00
Leonardo Galli
c64597c9f1 Fix for movies with . in title when importing them. Fixes #268 2017-01-17 14:47:23 +01:00
Leonardo Galli
6d2f81e3ed Remove - as replacement for : 2017-01-17 14:28:30 +01:00
Leonardo Galli
4263808360 Fix only one movie showing. Fix more button not showing up. 2017-01-17 13:21:40 +01:00
Leonardo Galli
c5ca2babf7 Updated website and donation links 2017-01-17 13:07:02 +01:00
Leonardo Galli
08db74d6e6 Fix Audiochannels just being added together. 2017-01-17 13:03:20 +01:00
Leonardo Galli
b309a9b01f Change Scheduled Refresh Series to Refresh Movie. Fixes #301 2017-01-17 12:55:32 +01:00
Tim Turner
2730745607 Clean up rename preview & organize
Fixes #125, #129,

BE SURE TO RUN "Update Library" before renaming/organizing.
2017-01-16 18:43:32 -05:00
Tim Turner
ae0df2aef0 Disambiguate Movie from Episode Renaming
Fixes #84
2017-01-16 17:12:27 -05:00
Leonardo Galli
6d665aeb21 Fix for hardcoded subs regex. 2017-01-16 22:51:45 +01:00
Leonardo Galli
967d3fd5c0 Add Calendar Tab back. Fixes #32 2017-01-16 22:40:59 +01:00
Devin Buhl
199d9c93ed Merge pull request #287 from baltoaca/develop
Added movie studio to movie details page (#262)
2017-01-16 14:30:21 -05:00
Vlad Ilies
30d2b41fbb Added movie studio to movie details page (#262)
* modified Movie model

* db migration

* ui template modification
2017-01-16 20:57:43 +02:00
Devin Buhl
75bb2533a3 Merge pull request #286 from Radarr/onedr0p-patch-1
Removed duplicate PublishDate
2017-01-16 13:46:29 -05:00
Devin Buhl
9b3b4eb55b Removed duplicate PublishDate 2017-01-16 13:25:59 -05:00
Leonardo Galli
42f84b830c Update NewznabRequestGenerator.cs 2017-01-16 12:54:51 +01:00
Leonardo Galli
eb0f825cfc Update README.md 2017-01-16 00:10:30 +01:00
Vlad Ilies
56a5b6ec89 Added trailer link to movie links (#255) (#282)
* added YouTubeTrailerId to movie model
* db migration for new column

* added videos to append_to_response for tmdb
* increased height of .series-posters-item
* new handlebar helper to build the trailer url
2017-01-15 15:17:24 -05:00
hotio
af478d3799 Add support section to README (#281)
* Add support section to README

* Update README.md

* Change docker color badge
2017-01-15 18:23:49 +01:00
Tim Turner
c2d40051d4 First pass at hiding existing movies upon import
Fixes #183
2017-01-15 11:34:43 -05:00
Tim Turner
281e516495 Merge branch 'develop' of https://github.com/Radarr/Radarr into develop 2017-01-15 11:07:41 -05:00
hotio
f63c3091f4 Reworked README (#280) 2017-01-15 13:50:45 +01:00
Leonardo Galli
50f49863b7 Update README.md 2017-01-15 11:42:15 +01:00
Mitchell Cash
941b3bd701 Move Travis builds to container-based infrastructure (#273)
* Remove example warning as it does not apply

* Modify the way apt packages work in .travis.yml

By modifying the way apt packages work (remove the need to directly require sudo), the builds can now run on container-based infrastructure.
2017-01-15 11:39:00 +01:00
hotio
f60b8cefca Update .gitignore and remove Thumbs.db files (#276)
* Update .gitignore

* Delete Thumbs.db

* Delete Thumbs.db

* Delete Thumbs.db

* Update .gitignore
2017-01-15 11:38:54 +01:00
Tim Turner
7c5f2ca54e 95% done with hiding existing movies 2017-01-14 23:04:31 -05:00
Leonardo Galli
401a650273 Adding only original title is now allowed. Fixes #272 2017-01-15 01:36:05 +01:00
Leonardo Galli
105af5cf11 Fix for special characters when searching with title in Newznab. Fixes #97 2017-01-15 01:20:07 +01:00
hotio
637c2e43eb Update README.md (#271)
* Update README.md

* Update README.md
2017-01-15 00:56:52 +01:00
Leonardo Galli
53373e6f4a Add {Original Title} to FileNameBuilder. Fixes #103 2017-01-15 00:55:15 +01:00
Leonardo Galli
ad147ed425 Release Group should now be available for renamer to use. 2017-01-15 00:49:37 +01:00
Devin Buhl
ed35e2f194 Merge pull request #270 from hotio/patch-1
Update README.md
2017-01-14 18:10:58 -05:00
hotio
674919dbf5 Update README.md 2017-01-15 00:06:18 +01:00
Devin Buhl
15b77e303f Merge pull request #266 from hotio/patch-1
Update README.md
2017-01-14 17:53:01 -05:00
hotio
757ca1d72c Update README.md
Some small additional fixes to README
2017-01-14 23:48:04 +01:00
Devin Buhl
8c8c7a99e3 Merge pull request #265 from mitchellcash/readme
Cleanup README
2017-01-14 17:35:33 -05:00
Mitchell Cash
b3dfb960b5 Cleanup README 2017-01-15 08:23:35 +10:00
Devin Buhl
98856e6747 Merge pull request #263 from Radarr/patch/update-movie-list
Add in theaters to 1st coumn in movie list
2017-01-14 16:51:27 -05:00
Devin Buhl
8fb5049899 Add in theaters to 1st coumn in movie list 2017-01-14 16:43:51 -05:00
Devin Buhl
3f62911a4f Merge pull request #260 from Radarr/patch/fix-downloadservice
Simplify completed download service
2017-01-14 14:12:54 -05:00
Devin Buhl
170349c950 Update CompletedDownloadService.cs 2017-01-14 14:07:34 -05:00
Devin Buhl
6c413d83eb Simply completed download service 2017-01-14 14:02:45 -05:00
Leonardo Galli
3afd27cad3 Merge branch 'develop' of https://github.com/Radarr/Radarr into develop 2017-01-14 19:21:52 +01:00
Leonardo Galli
149faf467d Fixed exception when Quality meets cutoff. 2017-01-14 19:21:48 +01:00
Devin Buhl
ce52bb8f68 Merge pull request #258 from Radarr/patch/fix-title-slugs-again
Fixed TitleSlug For Realz!
2017-01-14 13:18:58 -05:00
Devin Buhl
4bb5857444 Fixed TitleSlug For Realz! 2017-01-14 13:14:42 -05:00
Devin Buhl
620f09ef8b Merge pull request #257 from Radarr/patch-torpotato-regression
Torpotato username regression
2017-01-14 12:31:16 -05:00
Devin Buhl
16c1a2ee50 Torpotato username regression 2017-01-14 12:27:16 -05:00
Leonardo Galli
4b559cf29c Fix history items getting deleted because they do not have a series id. 2017-01-14 14:23:48 +01:00
Leonardo Galli
ca03f21b03 If this does not fix stuff with no history, I have no clue anymore. 2017-01-14 13:56:42 +01:00
Leonardo Galli
f481fe9ea9 Added more checks when tracking downloads. It should work now, even if history was not present. 2017-01-14 13:36:14 +01:00
Leonardo Galli
3a0278d0a1 Use MediaInfo to correctly identify quality when scanning disk as some file names may not contain the real quality.
Fixes #170
2017-01-14 13:33:30 +01:00
Leonardo Galli
d18b15d504 Should help identify problem with queue trying to reimport stuff. 2017-01-14 13:00:10 +01:00
Leonardo Galli
dc7e75187c Should fix issue when history fails to capture a download item. 2017-01-14 12:47:45 +01:00
Mitchell Cash
68a0ef65df Use DOGnzb name as the default rather than the URL (#250) 2017-01-14 12:15:59 +01:00
Leonardo Galli
fe11928487 Disable migration 117, takes too long to complete 2017-01-14 11:56:08 +01:00
Leonardo Galli
41dda3af48 Update uTorrent to be able to use it as download client. 2017-01-14 11:50:18 +01:00
Leonardo Galli
8c3260c545 Remove file count, unecessary after the file info tab was added
Fixes #215.
2017-01-14 11:41:39 +01:00
Leonardo Galli
bd0ec5dfce Fix epic fail on migration 117 2017-01-14 10:13:31 +01:00
Devin Buhl
ad38437b70 Merge pull request #248 from mitchellcash/sabnzbd_develop
Fixed: Parsing of SABnzbd develop version
2017-01-14 00:57:04 -05:00
Mark McDowall
4447b7cd62 Fixed: Parsing of SABnzbd develop version 2017-01-14 15:16:19 +10:00
Devin Buhl
d33de0d158 Merge pull request #247 from Radarr/patch/awesomehd-rsssync
Add rss sync to awesome-hd
2017-01-13 22:00:00 -05:00
Devin Buhl
dd5049b483 Add rss sync to awesome-hd 2017-01-13 21:55:07 -05:00
Leonardo Galli
29586667cb Files tab is now present. (#245)
* Adding file info tab. Not finished yet.

* Adding more media info options.

* Deleting files now works. Fixes #127

* Fix button for modifying episode files.

* Get Media Info when running DiskScanService.
2017-01-13 19:03:37 -05:00
Devin Buhl
5daece0ed4 Merge pull request #244 from Radarr/revert-238-patch/fix-slugs
Revert "Fix movie title slugs"
2017-01-13 18:24:23 -05:00
Devin Buhl
5dc63e5607 Revert "Fix movie title slugs" 2017-01-13 18:20:22 -05:00
Devin Buhl
7df283e57f Merge pull request #238 from Radarr/patch/fix-slugs
Fix movie title slugs
2017-01-13 18:07:13 -05:00
Devin Buhl
e9b6c250f7 Revert TMDBResources 2017-01-13 17:56:34 -05:00
Devin Buhl
10515156d1 Merge pull request #243 from Radarr/patch/update-torznab
Update Torznab to work with movies
2017-01-13 17:51:35 -05:00
Devin Buhl
4260b58535 Update Torznab to work with movies 2017-01-13 17:34:27 -05:00
Devin Buhl
3a386f2e18 Merge pull request #241 from Radarr/patch/fix-torpotato-age
#236 #239 - Fixed user being needed & fixed age on torrentpotato
2017-01-13 16:33:01 -05:00
Devin Buhl
d3bd0c9b69 This conditional makes more sense. 2017-01-13 16:16:31 -05:00
Devin Buhl
3180e648b4 #236 #239 - Fixed user being needed, fixed age on torrentpotato 2017-01-13 16:12:49 -05:00
Devin Buhl
d0c93759c6 Fix Movie Title Slugs #233 2017-01-13 15:49:57 -05:00
William Comartin
f7471940c4 Add Missing Filter (#237) 2017-01-13 20:57:25 +01:00
Devin Buhl
3a6873cc4d Merge pull request #232 from Radarr/patch/awesomehd
awesomeHD indexer support - Clean up Deluge, Transmission, rTorrent, QBitTorrent - Fix Sorting Titles
2017-01-13 13:15:52 -05:00
Leonardo Galli
330ae38ec2 Merge branch 'develop' of https://github.com/Radarr/Radarr into develop 2017-01-13 19:03:03 +01:00
Leonardo Galli
a0ecb19e32 DownloadMonitoringService should now not care about deleted movies. Fixes #131. 2017-01-13 19:02:59 +01:00
Leonardo Galli
38c966c07b Queue Service should now work properly again.
Fixes issue with Activity Tab
2017-01-13 18:57:43 +01:00
Devin Buhl
ad824d4da5 Finally fix for sorting title (hopefully) 2017-01-13 12:16:12 -05:00
Leonardo Galli
e76c160afe Downloaded column should now use the correct quality name. Fixes #210. 2017-01-13 18:13:39 +01:00
Devin Buhl
6a62546a4d Clean up QBitTorrent 2017-01-13 11:25:59 -05:00
Devin Buhl
0efdc78f8d Clean up rTorrent 2017-01-13 11:21:34 -05:00
Devin Buhl
fdd06127fc Clean up Transmission 2017-01-13 11:13:41 -05:00
Devin Buhl
317f8917b9 Clean up Deluge Settings 2017-01-13 11:08:36 -05:00
vertigo235
4038ce18c3 update movie monitor tooltip (#223) 2017-01-13 16:08:24 +01:00
Mike
7f3ca85953 Stop incrementing version for pull requests. 2017-01-13 06:15:38 +01:00
Devin Buhl
b93a9719fe initial awesomeHD support 2017-01-12 23:06:26 -05:00
Devin Buhl
2ef18edf08 Merge pull request #217 from aaearon/indexer-fix/omgwtfnzbs
omgwtfnzbs: fixed parsing of GetInfoUrl and updated tests
2017-01-12 23:00:30 -05:00
Tim Schindler
d61b9ab207 omgwtfnzbs: fixed parsing of GetInfoUrl and updated tests 2017-01-12 21:02:27 -05:00
Devin Buhl
abf4b137f1 Merge pull request #208 from Radarr/patch/usenet-crawler
improved categories, added Nzb-Tortuga as a preset
2017-01-12 18:51:52 -05:00
Devin Buhl
774c85f06b improved categories, added Nzb-Tortuga as a preset 2017-01-12 18:44:05 -05:00
Leonardo Galli
a060335bbc Update readme.md 2017-01-13 00:15:27 +01:00
166 changed files with 14470 additions and 9504 deletions

View File

@@ -1,6 +1,8 @@
Please use the search bar and make sure you are not submitting an already submitted issue.
Provide a description of the feature request or bug, the more details the better.
When possible include a log!

26
.gitignore vendored
View File

@@ -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/

View File

@@ -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
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

Binary file not shown.

94
README.md Normal file
View File

@@ -0,0 +1,94 @@
## Status
[![GitHub issues](https://img.shields.io/github/issues/radarr/radarr.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/radarr/radarr.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/pulls)
[![GNU GPL v3](https://img.shields.io/badge/license-GNU%20GPL%20v3-blue.svg?maxAge=60&style=flat-square)](http://www.gnu.org/licenses/gpl.html)
[![Copyright 2010-2017](https://img.shields.io/badge/copyright-2017-blue.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr)
[![Github Releases](https://img.shields.io/github/downloads/Radarr/Radarr/total.svg?maxAge=60&style=flat-square)](https://github.com/Radar/Radarr/releases/latest)
[![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/radarr.svg?maxAge=60&style=flat-square)](https://hub.docker.com/r/linuxserver/radarr/)
| Service | Master | Develop |
|----------|:---------------------------:|:----------------------------:|
| AppVeyor | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr/master.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr) | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr-usby1/develop.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
| Travis | [![Travis](https://img.shields.io/travis/Radarr/Radarr/master.svg?maxAge=60&style=flat-square)](https://travis-ci.org/Radarr/Radarr) | [![Travis](https://img.shields.io/travis/Radarr/Radarr/develop.svg?maxAge=60&style=flat-square)](https://travis-ci.org/Radarr/Radarr) |
This fork of Sonarr aims to turn it into something like CouchPotato.
## Downloads
[![GitHub Releases](https://img.shields.io/badge/downloads-releases-brightgreen.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/releases)
[![AppVeyor Builds](https://img.shields.io/badge/downloads-continuous-green.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/radarr-usby1/build/artifacts)
[![Docker x64](https://img.shields.io/badge/docker-x64-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/linuxserver/radarr)
[![Docker armhf](https://img.shields.io/badge/docker-armhf-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/lsioarmhf/radarr)
[![Docker aarch64](https://img.shields.io/badge/docker-aarch64-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](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
[![Discord](https://img.shields.io/badge/discord-chat-7289DA.svg?maxAge=60&style=flat-square)](https://discord.gg/AD3UP37)
[![Reddit](https://img.shields.io/badge/reddit-discussion-FF4500.svg?maxAge=60&style=flat-square)](https://www.reddit.com/r/radarr)
[![GitHub](https://img.shields.io/badge/github-issues-181717.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/issues)
## Features
### 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
### Major Features
* 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
* Full integration with Kodi, Plex (notification, library update, metadata)
* And a beautiful UI
## 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)

View File

@@ -36,6 +36,9 @@ artifacts:
cache:
- '%USERPROFILE%\.nuget\packages'
- node_modules
pull_requests:
do_not_increment_build_number: true
only_commits:
files:

View File

@@ -1,81 +0,0 @@
# Radarr
| Service | Master | Develop |
|----------|:---------------------------:|:----------------------------:|
| AppVeyor | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr/master.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr) | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr-usby1/develop.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
| Travis | [![Travis](https://img.shields.io/travis/galli-leo/Radarr/master.svg?maxAge=60&style=flat-square)](https://travis-ci.org/galli-leo/Radarr) | [![Travis](https://img.shields.io/travis/galli-leo/Radarr/develop.svg?maxAge=60&style=flat-square)](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.
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/)

View File

@@ -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()
};
}

View File

@@ -2,24 +2,38 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.Movie;
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 +47,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();
}
}
}

View File

@@ -0,0 +1,89 @@
using System.Collections.Generic;
using System.IO;
using NLog;
using NzbDrone.Api.REST;
using NzbDrone.Api.Movie;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Tv;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.SignalR;
namespace NzbDrone.Api.EpisodeFiles
{
public class MovieFileModule : NzbDroneRestModuleWithSignalR<MovieFileResource, MovieFile>
//IHandle<EpisodeFileAddedEvent>
{
private readonly IMediaFileService _mediaFileService;
private readonly IRecycleBinProvider _recycleBinProvider;
private readonly IMovieService _seriesService;
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
private readonly Logger _logger;
public MovieFileModule(IBroadcastSignalRMessage signalRBroadcaster,
IMediaFileService mediaFileService,
IRecycleBinProvider recycleBinProvider,
IMovieService seriesService,
IQualityUpgradableSpecification qualityUpgradableSpecification,
Logger logger)
: base(signalRBroadcaster)
{
_mediaFileService = mediaFileService;
_recycleBinProvider = recycleBinProvider;
_seriesService = seriesService;
_qualityUpgradableSpecification = qualityUpgradableSpecification;
_logger = logger;
/*GetResourceById = GetEpisodeFile;
GetResourceAll = GetEpisodeFiles;
UpdateResource = SetQuality;*/
DeleteResource = DeleteEpisodeFile;
}
/*private EpisodeFileResource GetEpisodeFile(int id)
{
var episodeFile = _mediaFileService.Get(id);
var series = _seriesService.GetSeries(episodeFile.SeriesId);
return episodeFile.ToResource(series, _qualityUpgradableSpecification);
}
private List<EpisodeFileResource> GetEpisodeFiles()
{
if (!Request.Query.SeriesId.HasValue)
{
throw new BadRequestException("seriesId is missing");
}
var seriesId = (int)Request.Query.SeriesId;
var series = _seriesService.GetSeries(seriesId);
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _qualityUpgradableSpecification));
}
private void SetQuality(EpisodeFileResource episodeFileResource)
{
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
episodeFile.Quality = episodeFileResource.Quality;
_mediaFileService.Update(episodeFile);
}*/
private void DeleteEpisodeFile(int id)
{
var episodeFile = _mediaFileService.GetMovie(id);
var series = _seriesService.GetMovie(episodeFile.MovieId);
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
_logger.Info("Deleting episode file: {0}", fullPath);
_recycleBinProvider.DeleteFile(fullPath);
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
}
public void Handle(EpisodeFileAddedEvent message)
{
BroadcastResourceChange(ModelAction.Updated, message.EpisodeFile.Id);
}
}
}

View File

@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Movies
private readonly IRenameMovieFileService _renameMovieFileService;
public RenameMovieModule(IRenameMovieFileService renameMovieFileService)
: base("rename")
: base("renameMovie")
{
_renameMovieFileService = renameMovieFileService;

View File

@@ -116,6 +116,7 @@
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
<Compile Include="Indexers\ReleaseModuleBase.cs" />
<Compile Include="Indexers\ReleasePushModule.cs" />
<Compile Include="Movies\MovieFileModule.cs" />
<Compile Include="Movies\MovieModule.cs" />
<Compile Include="Movies\RenameMovieModule.cs" />
<Compile Include="Movies\RenameMovieResource.cs" />
@@ -259,6 +260,7 @@
<Compile Include="Wanted\CutoffModule.cs" />
<Compile Include="Wanted\LegacyMissingModule.cs" />
<Compile Include="Wanted\MissingModule.cs" />
<Compile Include="Wanted\MovieMissingModule.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
@@ -293,4 +295,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -30,8 +30,8 @@ namespace NzbDrone.Api.Movie
public string ReleaseGroup { get; set; }
public QualityModel Quality { get; set; }
public MovieResource Movie { get; set; }
public string Edition { get; set; }
public Core.MediaFiles.MediaInfo.MediaInfoModel MediaInfo { get; set; }
//TODO: Add series statistics as a property of the series (instead of individual properties)
}
@@ -63,7 +63,8 @@ namespace NzbDrone.Api.Movie
ReleaseGroup = model.ReleaseGroup,
Quality = model.Quality,
Movie = movie,
MediaInfo = model.MediaInfo,
Edition = model.Edition
};
}

View File

@@ -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);
}
}
}

View File

@@ -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
};
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,77 @@
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 : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>,
IHandle<MovieGrabbedEvent>,
IHandle<MovieDownloadedEvent>
{
protected readonly IMovieService _movieService;
public MovieMissingModule(IMovieService movieService,
IQualityUpgradableSpecification qualityUpgradableSpecification,
IBroadcastSignalRMessage signalRBroadcaster)
: base(signalRBroadcaster, "wanted/missing")
{
_movieService = movieService;
GetResourcePaged = GetMissingMovies;
}
private PagingResource<MovieResource> GetMissingMovies(PagingResource<MovieResource> pagingResource)
{
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("physicalRelease", 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, false));
return resource;
}
private MovieResource GetMovie(int id)
{
var movie = _movieService.GetMovie(id);
var resource = MapToResource(movie, true);
return resource;
}
private MovieResource MapToResource(Core.Tv.Movie movie, bool includeMovieFile)
{
var resource = movie.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)
{
BroadcastResourceChange(ModelAction.Updated, message.Movie.Movie.Id);
}
}
}

View File

@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
Subject.Definition = new DownloadClientDefinition();
Subject.Definition.Settings = new DelugeSettings()
{
TvCategory = null
MovieCategory = null
};
_queued = new DelugeTorrent

View File

@@ -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("-", ""));
}

View File

@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
Port = 2222,
Username = "admin",
Password = "pass",
TvCategory = "tv"
MovieCategory = "movies-radarr"
};
Mocker.GetMock<ITorrentFileInfoReader>()

View File

@@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
Subject.Definition = new DownloadClientDefinition();
Subject.Definition.Settings = new RTorrentSettings()
{
TvCategory = null
MovieCategory = null
};
_downloading = new RTorrentTorrent

View File

@@ -112,12 +112,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
protected void GivenTvCategory()
{
_settings.TvCategory = "sonarr";
_settings.MovieCategory = "radarr";
}
protected void GivenTvDirectory()
{
_settings.TvDirectory = @"C:/Downloads/Finished/sonarr";
_settings.MovieDirectory = @"C:/Downloads/Finished/radarr";
}
protected void GivenFailedDownload()

File diff suppressed because it is too large Load Diff

View File

@@ -42,14 +42,14 @@ namespace NzbDrone.Core.Test.IndexerTests.OmgwtfnzbsTests
var releaseInfo = releases.First();
releaseInfo.Title.Should().Be("Stephen.Fry.Gadget.Man.S01E05.HDTV.x264-C4TV");
releaseInfo.Title.Should().Be("Un.Petit.Boulot.2016.FRENCH.720p.BluRay.DTS.x264-LOST");
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
releaseInfo.DownloadUrl.Should().Be("http://api.omgwtfnzbs.org/sn.php?id=OAl4g&user=nzbdrone&api=nzbdrone");
releaseInfo.InfoUrl.Should().Be("http://omgwtfnzbs.org/details.php?id=OAl4g");
releaseInfo.DownloadUrl.Should().Be("https://api.omgwtfnzbs.me/nzb/?id=8a2Bw&user=nzbdrone&api=nzbdrone");
releaseInfo.InfoUrl.Should().Be("https://omgwtfnzbs.me/details.php?id=8a2Bw");
releaseInfo.CommentUrl.Should().BeNullOrEmpty();
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2012/12/17 23:30:13"));
releaseInfo.Size.Should().Be(236822906);
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2017/01/09 00:16:54"));
releaseInfo.Size.Should().Be(5354909355);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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; }

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -0,0 +1,44 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(116)]
public class update_movie_sorttitle_again : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Execute.WithConnection(SetSortTitles);
}
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
{
using (IDbCommand getSeriesCmd = conn.CreateCommand())
{
getSeriesCmd.Transaction = tran;
getSeriesCmd.CommandText = @"SELECT Id, Title FROM Movies";
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
{
while (seriesReader.Read())
{
var id = seriesReader.GetInt32(0);
var title = seriesReader.GetString(1);
var sortTitle = Parser.Parser.NormalizeTitle(title).ToLower();
using (IDbCommand updateCmd = conn.CreateCommand())
{
updateCmd.Transaction = tran;
updateCmd.CommandText = "UPDATE Movies SET SortTitle = ? WHERE Id = ?";
updateCmd.AddParameter(sortTitle);
updateCmd.AddParameter(id);
updateCmd.ExecuteNonQuery();
}
}
}
}
}
}
}

View File

@@ -0,0 +1,52 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(117)]
public class update_movie_file : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.Column("Edition").OnTable("MovieFiles").AsString().Nullable();
//Execute.WithConnection(SetSortTitles);
}
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
{
using (IDbCommand getSeriesCmd = conn.CreateCommand())
{
getSeriesCmd.Transaction = tran;
getSeriesCmd.CommandText = @"SELECT Id, RelativePath FROM MovieFiles";
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
{
while (seriesReader.Read())
{
var id = seriesReader.GetInt32(0);
var relativePath = seriesReader.GetString(1);
var result = Parser.Parser.ParseMovieTitle(relativePath);
var edition = "";
if (result != null)
{
edition = Parser.Parser.ParseMovieTitle(relativePath).Edition;
}
using (IDbCommand updateCmd = conn.CreateCommand())
{
updateCmd.Transaction = tran;
updateCmd.CommandText = "UPDATE MovieFiles SET Edition = ? WHERE Id = ?";
updateCmd.AddParameter(edition);
updateCmd.AddParameter(id);
updateCmd.ExecuteNonQuery();
}
}
}
}
}
}
}

View File

@@ -0,0 +1,71 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
using System.Text;
using System.Text.RegularExpressions;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(118)]
public class update_movie_slug : 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, Title, Year FROM Movies";
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
{
while (seriesReader.Read())
{
var id = seriesReader.GetInt32(0);
var title = seriesReader.GetString(1);
var year = seriesReader.GetInt32(2);
var titleSlug = ToUrlSlug(title + "-" + year);
using (IDbCommand updateCmd = conn.CreateCommand())
{
updateCmd.Transaction = tran;
updateCmd.CommandText = "UPDATE Movies SET TitleSlug = ? WHERE Id = ?";
updateCmd.AddParameter(titleSlug);
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;
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -68,6 +68,17 @@ namespace NzbDrone.Core.DecisionEngine
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
{
if (x.IsForMovie)
{
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
{
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Movie.Tags);
var downloadProtocol = remoteEpisode.Release.DownloadProtocol;
return downloadProtocol == delayProfile.PreferredProtocol;
});
}
var result = CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
{
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Series.Tags);
@@ -75,15 +86,7 @@ namespace NzbDrone.Core.DecisionEngine
return downloadProtocol == delayProfile.PreferredProtocol;
});
if (x.IsForMovie)
{
result = CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
{
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Movie.Tags);
var downloadProtocol = remoteEpisode.Release.DownloadProtocol;
return downloadProtocol == delayProfile.PreferredProtocol;
});
}
return result;
}
@@ -125,8 +128,8 @@ namespace NzbDrone.Core.DecisionEngine
private int CompareAgeIfUsenet(DownloadDecision x, DownloadDecision y)
{
if (x.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Usenet ||
y.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Usenet)
if (x.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Usenet ||
y.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Usenet)
{
return 0;
}

View File

@@ -32,7 +32,7 @@ namespace NzbDrone.Core.DecisionEngine
public List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports)
{
return GetDecisions(reports).ToList();
return GetMovieDecisions(reports).ToList();
}
public List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase)
@@ -83,7 +83,7 @@ namespace NzbDrone.Core.DecisionEngine
{
if (parsedEpisodeInfo.Quality.HardcodedSubs.IsNotNullOrWhiteSpace())
{
remoteEpisode.DownloadAllowed = false;
remoteEpisode.DownloadAllowed = true;
decision = new DownloadDecision(remoteEpisode, new Rejection("Hardcoded subs found: " + parsedEpisodeInfo.Quality.HardcodedSubs));
}
else

View File

@@ -34,11 +34,11 @@ namespace NzbDrone.Core.DecisionEngine
public List<DownloadDecision> PrioritizeDecisionsForMovies(List<DownloadDecision> decisions)
{
return decisions.Where(c => c.RemoteMovie.Movie != null)
/*.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) =>
.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) =>
{
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
})
.SelectMany(c => c)*/
.SelectMany(c => c)
.Union(decisions.Where(c => c.RemoteMovie.Movie == null))
.ToList();
}

View File

@@ -33,7 +33,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
{
throw new NotImplementedException();
if (_blacklistService.Blacklisted(subject.Movie.Id, subject.Release))
{
_logger.Debug("{0} is blacklisted, rejecting.", subject.Release.Title);
return Decision.Reject("Release is blacklisted");
}
return Decision.Accept();
}

View File

@@ -64,7 +64,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Movie.Profile, remoteEpisode.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
{
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedMovieInfo.Quality);
}
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0}", remoteEpisode.ParsedMovieInfo.Quality);

View File

@@ -31,25 +31,17 @@ namespace NzbDrone.Core.Download.Clients.Deluge
_proxy = proxy;
}
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
var actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
_proxy.SetLabel(actualHash, Settings.MovieCategory, Settings);
}
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
{
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
}*/
return actualHash.ToUpper();
}
@@ -57,66 +49,24 @@ namespace NzbDrone.Core.Download.Clients.Deluge
{
var actualHash = _proxy.AddTorrentFromFile(filename, fileContent, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
_proxy.SetLabel(actualHash, Settings.MovieCategory, Settings);
}
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
{
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
}*/
return actualHash.ToUpper();
}
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
var actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
}
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
{
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
}
return actualHash.ToUpper();
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
var actualHash = _proxy.AddTorrentFromFile(filename, fileContent, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
}
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
{
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
}
return actualHash.ToUpper();
throw new NotImplementedException("Episodes are not working with Radarr");
}
public override string Name => "Deluge";
@@ -127,9 +77,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge
try
{
if (!Settings.TvCategory.IsNullOrWhiteSpace())
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
{
torrents = _proxy.GetTorrentsByLabel(Settings.TvCategory, Settings);
torrents = _proxy.GetTorrentsByLabel(Settings.MovieCategory, Settings);
}
else
{
@@ -149,7 +99,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
var item = new DownloadClientItem();
item.DownloadId = torrent.Hash.ToUpper();
item.Title = torrent.Name;
item.Category = Settings.TvCategory;
item.Category = Settings.MovieCategory;
item.DownloadClient = Definition.Name;
@@ -280,7 +230,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
private ValidationFailure TestCategory()
{
if (Settings.TvCategory.IsNullOrWhiteSpace())
if (Settings.MovieCategory.IsNullOrWhiteSpace())
{
return null;
}
@@ -297,14 +247,14 @@ namespace NzbDrone.Core.Download.Clients.Deluge
var labels = _proxy.GetAvailableLabels(Settings);
if (!labels.Contains(Settings.TvCategory))
if (!labels.Contains(Settings.MovieCategory))
{
_proxy.AddLabel(Settings.TvCategory, Settings);
_proxy.AddLabel(Settings.MovieCategory, Settings);
labels = _proxy.GetAvailableLabels(Settings);
if (!labels.Contains(Settings.TvCategory))
if (!labels.Contains(Settings.MovieCategory))
{
return new NzbDroneValidationFailure("TvCategory", "Configuration of label failed")
return new NzbDroneValidationFailure("MovieCategory", "Configuration of label failed")
{
DetailedDescription = "Radarr as unable to add the label to Deluge."
};

View File

@@ -12,7 +12,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
RuleFor(c => c.Host).ValidHost();
RuleFor(c => c.Port).GreaterThan(0);
RuleFor(c => c.TvCategory).Matches("^[-a-z]*$").WithMessage("Allowed characters a-z and -");
RuleFor(c => c.MovieCategory).Matches("^[-a-z]*$").WithMessage("Allowed characters a-z and -");
}
}
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
Host = "localhost";
Port = 8112;
Password = "deluge";
TvCategory = "movie-radarr";
MovieCategory = "movie-radarr";
}
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
@@ -41,15 +41,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge
public string Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(DelugePriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(DelugePriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public int OlderTvPriority { get; set; }
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
[FieldDefinition(5, Label = "Use SSL", Type = FieldType.Checkbox)]
public bool UseSsl { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -32,9 +32,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContents)
{
var category = Settings.TvCategory;
var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
var addpaused = Settings.AddPaused;
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, addpaused, Settings);
if (response == null)
{
@@ -47,9 +50,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents)
{
var category = Settings.TvCategory; // TODO: Update this to MovieCategory?
var priority = Settings.RecentTvPriority;
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
var addpaused = Settings.AddPaused;
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, addpaused, Settings);
if(response == null)
{

View File

@@ -11,7 +11,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
public interface INzbgetProxy
{
string DownloadNzb(byte[] nzbData, string title, string category, int priority, NzbgetSettings settings);
string DownloadNzb(byte[] nzbData, string title, string category, int priority, bool addpaused, NzbgetSettings settings);
NzbgetGlobalStatus GetGlobalStatus(NzbgetSettings settings);
List<NzbgetQueueItem> GetQueue(NzbgetSettings settings);
List<NzbgetHistoryItem> GetHistory(NzbgetSettings settings);
@@ -45,12 +45,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
return version >= minimumVersion;
}
public string DownloadNzb(byte[] nzbData, string title, string category, int priority, NzbgetSettings settings)
public string DownloadNzb(byte[] nzbData, string title, string category, int priority, bool addpaused, NzbgetSettings settings)
{
if (HasVersion(16, settings))
{
var droneId = Guid.NewGuid().ToString().Replace("-", "");
var response = ProcessRequest<int>(settings, "append", title, nzbData, category, priority, false, false, string.Empty, 0, "all", new string[] { "drone", droneId });
var response = ProcessRequest<int>(settings, "append", title, nzbData, category, priority, false, addpaused, string.Empty, 0, "all", new string[] { "drone", droneId });
if (response <= 0)
{
return null;

View File

@@ -57,6 +57,9 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
public bool UseSsl { get; set; }
[FieldDefinition(8, Label = "Add Paused", Type = FieldType.Checkbox, HelpText = "This option requires at least NzbGet version 16.0")]
public bool AddPaused { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

View File

@@ -33,81 +33,35 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
}
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
}
return hash;
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, Byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
}
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
}
return hash;
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
_proxy.SetTorrentLabel(hash.ToLower(), Settings.MovieCategory, Settings);
}
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
}*/ //TODO: Maybe reimplement for movies
return hash;
}
protected override string AddFromTorrentFile(RemoteMovie remoteEpisode, string hash, string filename, Byte[] fileContent)
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, Byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
_proxy.SetTorrentLabel(hash.ToLower(), Settings.MovieCategory, Settings);
}
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
}*/
return hash;
}
@@ -236,7 +190,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
else if (version < 6)
{
// API version 6 introduced support for labels
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
return new NzbDroneValidationFailure("Category", "Category is not supported")
{
@@ -244,7 +198,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
};
}
}
else if (Settings.TvCategory.IsNullOrWhiteSpace())
else if (Settings.MovieCategory.IsNullOrWhiteSpace())
{
// warn if labels are supported, but category is not provided
return new NzbDroneValidationFailure("TvCategory", "Category is recommended")

View File

@@ -58,8 +58,8 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
public List<QBittorrentTorrent> GetTorrents(QBittorrentSettings settings)
{
var request = BuildRequest(settings).Resource("/query/torrents")
.AddQueryParam("label", settings.TvCategory)
.AddQueryParam("category", settings.TvCategory);
.AddQueryParam("label", settings.MovieCategory)
.AddQueryParam("category", settings.MovieCategory);
var response = ProcessRequest<List<QBittorrentTorrent>>(request, settings);

View File

@@ -22,7 +22,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
{
Host = "localhost";
Port = 9091;
TvCategory = "movie-radarr";
MovieCategory = "movie-radarr";
}
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
@@ -38,16 +38,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
public string Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
//Todo: update this shit.
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public int OlderTvPriority { get; set; }
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection. See Options -> Web UI -> 'Use HTTPS instead of HTTP' in qBittorrent.")]
[FieldDefinition(5, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection. See Options -> Web UI -> 'Use HTTPS instead of HTTP' in qBittorrent.")]
public bool UseSsl { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -30,13 +30,13 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
}
// patch can be a number (releases) or 'x' (git)
private static readonly Regex VersionRegex = new Regex(@"(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+|x)(?<candidate>.*)", RegexOptions.Compiled);
private static readonly Regex VersionRegex = new Regex(@"(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+|x)", RegexOptions.Compiled);
protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContents)
{
var category = Settings.TvCategory;
var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
if (response != null && response.Ids.Any())
@@ -284,110 +284,103 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
failures.AddIfNotNull(TestCategory());
}
private bool HasVersion(int major, int minor, int patch = 0, string candidate = null)
private bool HasVersion(int major, int minor, int patch = 0)
{
candidate = candidate ?? string.Empty;
var rawVersion = _proxy.GetVersion(Settings);
var version = ParseVersion(rawVersion);
var version = _proxy.GetVersion(Settings);
if (version == null)
{
return false;
}
if (version.Major > major)
{
return true;
}
else if (version.Major < major)
{
return false;
}
if (version.Minor > minor)
{
return true;
}
else if (version.Minor < minor)
{
return false;
}
if (version.Build > patch)
{
return true;
}
else if (version.Build < patch)
{
return false;
}
return true;
}
private Version ParseVersion(string version)
{
var parsed = VersionRegex.Match(version);
int actualMajor;
int actualMinor;
int actualPatch;
string actualCandidate;
int major;
int minor;
int patch;
if (!parsed.Success)
if (parsed.Success)
{
major = Convert.ToInt32(parsed.Groups["major"].Value);
minor = Convert.ToInt32(parsed.Groups["minor"].Value);
patch = Convert.ToInt32(parsed.Groups["patch"].Value.Replace("x", "0"));
}
else
{
if (!version.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
{
return false;
return null;
}
actualMajor = 1;
actualMinor = 1;
actualPatch = 0;
actualCandidate = null;
major = 1;
minor = 1;
patch = 0;
}
else
{
actualMajor = Convert.ToInt32(parsed.Groups["major"].Value);
actualMinor = Convert.ToInt32(parsed.Groups["minor"].Value);
actualPatch = Convert.ToInt32(parsed.Groups["patch"].Value.Replace("x", ""));
actualCandidate = parsed.Groups["candidate"].Value.ToUpper();
}
if (actualMajor > major)
{
return true;
}
else if (actualMajor < major)
{
return false;
}
if (actualMinor > minor)
{
return true;
}
else if (actualMinor < minor)
{
return false;
}
if (actualPatch > patch)
{
return true;
}
else if (actualPatch < patch)
{
return false;
}
if (actualCandidate.IsNullOrWhiteSpace())
{
return true;
}
else if (candidate.IsNullOrWhiteSpace())
{
return false;
}
else
{
return actualCandidate.CompareTo(candidate) > 0;
}
return new Version(major, minor, patch);
}
private ValidationFailure TestConnectionAndVersion()
{
try
{
var version = _proxy.GetVersion(Settings);
var parsed = VersionRegex.Match(version);
var rawVersion = _proxy.GetVersion(Settings);
var version = ParseVersion(rawVersion);
if (!parsed.Success)
if (version == null)
{
if (version.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
{
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
{
IsWarning = true,
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
};
}
return new ValidationFailure("Version", "Unknown Version: " + version);
}
var major = Convert.ToInt32(parsed.Groups["major"].Value);
var minor = Convert.ToInt32(parsed.Groups["minor"].Value);
if (rawVersion.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
{
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
{
IsWarning = true,
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
};
}
if (major >= 1)
if (version.Major >= 1)
{
return null;
}
if (minor >= 7)
if (version.Minor >= 7)
{
return null;
}

View File

@@ -54,21 +54,21 @@ namespace NzbDrone.Core.Download.Clients.Transmission
var outputPath = new OsPath(torrent.DownloadDir);
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
{
if (!new OsPath(Settings.TvDirectory).Contains(outputPath)) continue;
if (!new OsPath(Settings.MovieDirectory).Contains(outputPath)) continue;
}
else if (Settings.TvCategory.IsNotNullOrWhiteSpace())
else if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
var directories = outputPath.FullPath.Split('\\', '/');
if (!directories.Contains(Settings.TvCategory)) continue;
if (!directories.Contains(Settings.MovieCategory)) continue;
}
outputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, outputPath);
var item = new DownloadClientItem();
item.DownloadId = torrent.HashString.ToUpper();
item.Category = Settings.TvCategory;
item.Category = Settings.MovieCategory;
item.Title = torrent.Name;
item.DownloadClient = Definition.Name;
@@ -123,9 +123,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
var config = _proxy.GetConfig(Settings);
var destDir = config.GetValueOrDefault("download-dir") as string;
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
destDir = string.Format("{0}/.{1}", destDir, Settings.TvCategory);
destDir = string.Format("{0}/.{1}", destDir, Settings.MovieCategory);
}
return new DownloadClientStatus
@@ -137,56 +137,23 @@ namespace NzbDrone.Core.Download.Clients.Transmission
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)TransmissionPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}
return hash;
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)TransmissionPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}
return hash;
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
if (remoteMovie.Release.Age < 14 && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
remoteMovie.Release.Age > 14 && Settings.OlderTvPriority == (int)TransmissionPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}
return hash;
}
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
if (remoteMovie.Release.Age < 14 && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
remoteMovie.Release.Age > 14 && Settings.OlderTvPriority == (int)TransmissionPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}
return hash;
}
@@ -204,16 +171,16 @@ namespace NzbDrone.Core.Download.Clients.Transmission
protected string GetDownloadDirectory()
{
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
{
return Settings.TvDirectory;
return Settings.MovieDirectory;
}
else if (Settings.TvCategory.IsNotNullOrWhiteSpace())
else if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
var config = _proxy.GetConfig(Settings);
var destDir = (string)config.GetValueOrDefault("download-dir");
return string.Format("{0}/{1}", destDir.TrimEnd('/'), Settings.TvCategory);
return string.Format("{0}/{1}", destDir.TrimEnd('/'), Settings.MovieCategory);
}
else
{

View File

@@ -16,10 +16,10 @@ namespace NzbDrone.Core.Download.Clients.Transmission
RuleFor(c => c.UrlBase).ValidUrlBase();
RuleFor(c => c.TvCategory).Matches(@"^\.?[-a-z]*$", RegexOptions.IgnoreCase).WithMessage("Allowed characters a-z and -");
RuleFor(c => c.MovieCategory).Matches(@"^\.?[-a-z]*$", RegexOptions.IgnoreCase).WithMessage("Allowed characters a-z and -");
RuleFor(c => c.TvCategory).Empty()
.When(c => c.TvDirectory.IsNotNullOrWhiteSpace())
RuleFor(c => c.MovieCategory).Empty()
.When(c => c.MovieDirectory.IsNotNullOrWhiteSpace())
.WithMessage("Cannot use Category and Directory");
}
}
@@ -51,18 +51,12 @@ namespace NzbDrone.Core.Download.Clients.Transmission
public string Password { get; set; }
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional. Creates a [category] subdirectory in the output directory.")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(6, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default Transmission location")]
public string TvDirectory { get; set; }
public string MovieDirectory { get; set; }
[FieldDefinition(7, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing movies that we're released within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(8, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing movies that we're released over 14 days ago")]
public int OlderTvPriority { get; set; }
[FieldDefinition(9, Label = "Use SSL", Type = FieldType.Checkbox)]
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
public bool UseSsl { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -37,51 +37,23 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
_rTorrentDirectoryValidator = rTorrentDirectoryValidator;
}
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
// Download the magnet to the appropriate directory.
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
//SetPriority(remoteEpisode, hash);
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
SetDownloadDirectory(hash);
// Once the magnet meta download finishes, rTorrent replaces it with the actual torrent download with default settings.
// Schedule an event to apply the appropriate settings when that happens.
// var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
//_proxy.SetDeferredMagnetProperties(hash, Settings.TvCategory, Settings.TvDirectory, priority, Settings);
_proxy.StartTorrent(hash, Settings);
// Wait for the magnet to be resolved.
var tries = 10;
var retryDelay = 500;
if (WaitForTorrent(hash, tries, retryDelay))
{
return hash;
}
else
{
_logger.Warn("rTorrent could not resolve magnet within {0} seconds, download may remain stuck: {1}.", tries * retryDelay / 1000, magnetLink);
return hash;
}
}
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
// Download the magnet to the appropriate directory.
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
SetPriority(remoteEpisode, hash);
SetDownloadDirectory(hash);
// Once the magnet meta download finishes, rTorrent replaces it with the actual torrent download with default settings.
// Schedule an event to apply the appropriate settings when that happens.
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
_proxy.SetDeferredMagnetProperties(hash, Settings.TvCategory, Settings.TvDirectory, priority, Settings);
_proxy.StartTorrent(hash, Settings);
// Wait for the magnet to be resolved.
@@ -107,13 +79,9 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
var retryDelay = 100;
if (WaitForTorrent(hash, tries, retryDelay))
{
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
//SetPriority(remoteEpisode, hash);
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
SetDownloadDirectory(hash);
_proxy.StartTorrent(hash, Settings);
return hash;
}
else
@@ -125,32 +93,6 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
}
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
var tries = 2;
var retryDelay = 100;
if (WaitForTorrent(hash, tries, retryDelay))
{
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
SetPriority(remoteEpisode, hash);
SetDownloadDirectory(hash);
_proxy.StartTorrent(hash, Settings);
return hash;
}
else
{
_logger.Debug("rTorrent could not add file");
RemoveItem(hash, true);
throw new ReleaseDownloadException(remoteEpisode.Release, "Downloading torrent failed");
}
}
public override string Name => "rTorrent";
public override ProviderMessage Message => new ProviderMessage("Radarr is unable to remove torrents that have finished seeding when using rTorrent", ProviderMessageType.Warning);
@@ -167,7 +109,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
foreach (RTorrentTorrent torrent in torrents)
{
// Don't concern ourselves with categories other than specified
if (torrent.Category != Settings.TvCategory) continue;
if (torrent.Category != Settings.MovieCategory) continue;
if (torrent.Path.StartsWith("."))
{
@@ -287,17 +229,11 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
return result.Errors.First();
}
private void SetPriority(RemoteEpisode remoteEpisode, string hash)
{
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
_proxy.SetTorrentPriority(hash, priority, Settings);
}
private void SetDownloadDirectory(string hash)
{
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentDownloadDirectory(hash, Settings.TvDirectory, Settings);
_proxy.SetTorrentDownloadDirectory(hash, Settings.MovieDirectory, Settings);
}
}

View File

@@ -18,13 +18,13 @@ namespace NzbDrone.Core.Download.Clients.rTorrent
DroneFactoryValidator droneFactoryValidator,
MappedNetworkDriveValidator mappedNetworkDriveValidator)
{
RuleFor(c => c.TvDirectory).Cascade(CascadeMode.StopOnFirstFailure)
RuleFor(c => c.MovieDirectory).Cascade(CascadeMode.StopOnFirstFailure)
.IsValidPath()
.SetValidator(rootFolderValidator)
.SetValidator(droneFactoryValidator)
.SetValidator(mappedNetworkDriveValidator)
.SetValidator(pathExistsValidator)
.When(c => c.TvDirectory.IsNotNullOrWhiteSpace())
.When(c => c.MovieDirectory.IsNotNullOrWhiteSpace())
.When(c => c.Host == "localhost" || c.Host == "127.0.0.1");
}
}

View File

@@ -11,7 +11,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
{
RuleFor(c => c.Host).ValidHost();
RuleFor(c => c.Port).InclusiveBetween(0, 65535);
RuleFor(c => c.TvCategory).NotEmpty()
RuleFor(c => c.MovieCategory).NotEmpty()
.WithMessage("A category is recommended")
.AsWarning();
}
@@ -26,9 +26,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
Host = "localhost";
Port = 8080;
UrlBase = "RPC2";
TvCategory = "movies-radarr";
OlderTvPriority = (int)RTorrentPriority.Normal;
RecentTvPriority = (int)RTorrentPriority.Normal;
MovieCategory = "movies-radarr";
}
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
@@ -50,16 +48,10 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
public string Password { get; set; }
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional.")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(7, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default rTorrent location")]
public string TvDirectory { get; set; }
[FieldDefinition(8, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(9, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public int OlderTvPriority { get; set; }
public string MovieDirectory { get; set; }
public NzbDroneValidationResult Validate()
{

View File

@@ -68,6 +68,38 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
return hash;
}
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)UTorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)UTorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}*/
return hash;
}
protected override string AddFromTorrentFile(RemoteMovie remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)UTorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)UTorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}*/
return hash;
}
public override string Name => "uTorrent";
public override IEnumerable<DownloadClientItem> GetItems()

View File

@@ -94,34 +94,18 @@ namespace NzbDrone.Core.Download
return;
}
var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title);
if (series == null)
var movie = _parsingService.GetMovie(trackedDownload.DownloadItem.Title);
if (movie == null)
{
if (historyItem != null)
{
//series = _seriesService.GetSeries(historyItem.SeriesId);
movie = _movieService.GetMovie(historyItem.MovieId);
}
if (series == null)
if (movie == null)
{
var movie = _parsingService.GetMovie(trackedDownload.DownloadItem.Title);
if (movie == null)
{
if (historyItem != null)
{
movie = _movieService.GetMovie(historyItem.MovieId);
}
if (movie == null)
{
trackedDownload.Warn("Movie title mismatch, automatic import is not possible.");
}
}
//trackedDownload.Warn("Series title mismatch, automatic import is not possible.");
//return;
trackedDownload.Warn("Movie title mismatch, automatic import is not possible.");
return;
}
}
}
@@ -132,61 +116,30 @@ namespace NzbDrone.Core.Download
private void Import(TrackedDownload trackedDownload)
{
var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath;
if (trackedDownload.RemoteMovie.Movie != null)
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
if (importResults.Empty())
{
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
if (importResults.Empty())
{
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
return;
}
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= 1)
{
trackedDownload.State = TrackedDownloadStage.Imported;
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
return;
}
if (importResults.Any(c => c.Result != ImportResultType.Imported))
{
var statusMessages = importResults
.Where(v => v.Result != ImportResultType.Imported)
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors))
.ToArray();
trackedDownload.Warn(statusMessages);
}
}
else if (trackedDownload.RemoteEpisode.Series != null)
{
var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem);
if (importResults.Empty())
{
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
return;
}
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count))
{
trackedDownload.State = TrackedDownloadStage.Imported;
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
return;
}
if (importResults.Any(c => c.Result != ImportResultType.Imported))
{
var statusMessages = importResults
.Where(v => v.Result != ImportResultType.Imported)
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors))
.ToArray();
trackedDownload.Warn(statusMessages);
}
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
return;
}
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= 1)
{
trackedDownload.State = TrackedDownloadStage.Imported;
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
return;
}
if (importResults.Any(c => c.Result != ImportResultType.Imported))
{
var statusMessages = importResults
.Where(v => v.Result != ImportResultType.Imported)
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalMovie.Path), v.Errors))
.ToArray();
trackedDownload.Warn(statusMessages);
}
}
}
}

View File

@@ -13,8 +13,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
public void Clean()
{
CleanupOrphanedBySeries();
CleanupOrphanedByEpisode();
//CleanupOrphanedBySeries();
//CleanupOrphanedByEpisode();
CleanupOrphanedByMovie();
}
private void CleanupOrphanedBySeries()
@@ -29,6 +30,18 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
WHERE Series.Id IS NULL)");
}
private void CleanupOrphanedByMovie()
{
var mapper = _database.GetDataMapper();
mapper.ExecuteNonQuery(@"DELETE FROM History
WHERE Id IN (
SELECT History.Id FROM History
LEFT OUTER JOIN Movies
ON History.MovieId = Movies.Id
WHERE Movies.Id IS NULL)");
}
private void CleanupOrphanedByEpisode()
{
var mapper = _database.GetDataMapper();

View File

@@ -0,0 +1,30 @@
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHD : HttpIndexerBase<AwesomeHDSettings>
{
public override string Name => "AwesomeHD";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override bool SupportsRss => true;
public override bool SupportsSearch => true;
public override int PageSize => 50;
public AwesomeHD(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
: base(httpClient, indexerStatusService, configService, parsingService, logger)
{ }
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new AwesomeHDRequestGenerator() { Settings = Settings };
}
public override IParseIndexerResponse GetParser()
{
return new AwesomeHDRssParser(Settings);
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using Newtonsoft.Json;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class Torrent
{
[XmlElement(ElementName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "groupid")]
public string GroupId { get; set; }
[XmlElement(ElementName = "time")]
public DateTime Time { get; set; }
[XmlElement(ElementName = "userid")]
public string Userid { get; set; }
[XmlElement(ElementName = "size")]
public long Size { get; set; }
[XmlElement(ElementName = "snatched")]
public string Snatched { get; set; }
[XmlElement(ElementName = "seeders")]
public string Seeders { get; set; }
[XmlElement(ElementName = "leechers")]
public string Leechers { get; set; }
[XmlElement(ElementName = "releasegroup")]
public string Releasegroup { get; set; }
[XmlElement(ElementName = "resolution")]
public string Resolution { get; set; }
[XmlElement(ElementName = "media")]
public string Media { get; set; }
[XmlElement(ElementName = "format")]
public string Format { get; set; }
[XmlElement(ElementName = "encoding")]
public string Encoding { get; set; }
[XmlElement(ElementName = "audioformat")]
public string Audioformat { get; set; }
[XmlElement(ElementName = "audiobitrate")]
public string Audiobitrate { get; set; }
[XmlElement(ElementName = "audiochannels")]
public string Audiochannels { get; set; }
[XmlElement(ElementName = "subtitles")]
public string Subtitles { get; set; }
[XmlElement(ElementName = "encodestatus")]
public string Encodestatus { get; set; }
[XmlElement(ElementName = "freeleech")]
public string Freeleech { get; set; }
[XmlElement(ElementName = "cover")]
public string Cover { get; set; }
[XmlElement(ElementName = "smallcover")]
public string Smallcover { get; set; }
[XmlElement(ElementName = "year")]
public string Year { get; set; }
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "imdb")]
public string Imdb { get; set; }
[XmlElement(ElementName = "type")]
public string Type { get; set; }
[XmlElement(ElementName = "plotoutline")]
public string Plotoutline { get; set; }
}
public class SearchResults
{
[XmlElement(ElementName = "authkey")]
public string AuthKey { get; set; }
[XmlElement(ElementName = "torrent")]
public List<Torrent> Torrent { get; set; }
}
public class AwesomeHDSearchResponse
{
[XmlElement(ElementName = "?xml")]
public string Xml { get; set; }
[XmlElement(ElementName = "searchresults")]
public SearchResults SearchResults { get; set; }
}
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDRequestGenerator : IIndexerRequestGenerator
{
public AwesomeHDSettings Settings { get; set; }
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(null));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(searchCriteria.Movie.ImdbId));
return pageableRequests;
}
private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
{
if (searchParameters != null)
{
yield return new IndexerRequest(string.Format("{0}/searchapi.php?action=imdbsearch&passkey={1}&imdb={2}", Settings.BaseUrl.Trim().TrimEnd('/'), Settings.Passkey.Trim(), searchParameters), HttpAccept.Rss);
}
else
{
yield return new IndexerRequest(string.Format("{0}/searchapi.php?action=latestmovies&passkey={1}", Settings.BaseUrl.Trim().TrimEnd('/'), Settings.Passkey.Trim()), HttpAccept.Rss);
}
}
}
}

View File

@@ -0,0 +1,92 @@
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Parser.Model;
using System;
using System.Linq;
using System.Xml;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDRssParser : IParseIndexerResponse
{
private readonly AwesomeHDSettings _settings;
public AwesomeHDRssParser(AwesomeHDSettings settings)
{
_settings = settings;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse,
"Unexpected response status {0} code from API request",
indexerResponse.HttpResponse.StatusCode);
}
// Hacky ¯\_(ツ)_/¯
XmlDocument doc = new XmlDocument();
doc.LoadXml(indexerResponse.Content);
var json = JsonConvert.SerializeXmlNode(doc);
Console.WriteLine(json);
var jsonResponse = JsonConvert.DeserializeObject<AwesomeHDSearchResponse>(json);
if (jsonResponse == null)
{
throw new IndexerException(indexerResponse, "Unexpected response from request");
}
foreach (var torrent in jsonResponse.SearchResults.Torrent)
{
var id = torrent.Id;
var title = $"{torrent.Name}.{torrent.Year}.{torrent.Resolution}.{torrent.Media}.{torrent.Encoding}.{torrent.Audioformat}-{torrent.Releasegroup}";
torrentInfos.Add(new TorrentInfo()
{
Guid = string.Format("AwesomeHD-{0}", id),
Title = title,
Size = torrent.Size,
DownloadUrl = GetDownloadUrl(id, jsonResponse.SearchResults.AuthKey, _settings.Passkey),
InfoUrl = GetInfoUrl(torrent.GroupId, id),
Seeders = int.Parse(torrent.Seeders),
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
PublishDate = torrent.Time.ToUniversalTime()
});
}
return torrentInfos.OrderByDescending(o => ((dynamic)o).Seeders).ToArray();
}
private string GetDownloadUrl(string torrentId, string authKey, string passKey)
{
var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php")
.AddQueryParam("action", "download")
.AddQueryParam("id", torrentId)
.AddQueryParam("authkey", authKey)
.AddQueryParam("torrent_pass", passKey);
return url.FullUri;
}
private string GetInfoUrl(string groupId, string torrentId)
{
var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php")
.AddQueryParam("id", groupId)
.AddQueryParam("torrentid", torrentId);
return url.FullUri;
}
}
}

View File

@@ -0,0 +1,37 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDSettingsValidator : AbstractValidator<AwesomeHDSettings>
{
public AwesomeHDSettingsValidator()
{
RuleFor(c => c.BaseUrl).ValidRootUrl();
RuleFor(c => c.Passkey).NotEmpty();
}
}
public class AwesomeHDSettings : IProviderConfig
{
private static readonly AwesomeHDSettingsValidator Validator = new AwesomeHDSettingsValidator();
public AwesomeHDSettings()
{
BaseUrl = "https://awesome-hd.me";
}
[FieldDefinition(0, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since you Passkey will be sent to that host.")]
public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Passkey")]
public string Passkey { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -39,14 +39,15 @@ namespace NzbDrone.Core.Indexers.Newznab
{
get
{
yield return GetDefinition("Dognzb.cr", GetSettings("https://api.dognzb.cr"));
yield return GetDefinition("DOGnzb", GetSettings("https://api.dognzb.cr"));
yield return GetDefinition("DrunkenSlug", GetSettings("https://api.drunkenslug.com"));
yield return GetDefinition("Nzb-Tortuga", GetSettings("https://www.nzb-tortuga.com"));
yield return GetDefinition("Nzb.su", GetSettings("https://api.nzb.su"));
yield return GetDefinition("NZBCat", GetSettings("https://nzb.cat"));
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws", 5010, 5030, 5040, 5045));
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws"));
yield return GetDefinition("NZBgeek", GetSettings("https://api.nzbgeek.info"));
yield return GetDefinition("nzbplanet.net", GetSettings("https://api.nzbplanet.net"));
yield return GetDefinition("Nzbs.org", GetSettings("http://nzbs.org", 2000));
yield return GetDefinition("Nzbs.org", GetSettings("http://nzbs.org"));
yield return GetDefinition("OZnzb.com", GetSettings("https://api.oznzb.com"));
yield return GetDefinition("PFmonkey", GetSettings("https://www.pfmonkey.com"));
yield return GetDefinition("SimplyNZBs", GetSettings("https://simplynzbs.com"));

View File

@@ -133,7 +133,7 @@ namespace NzbDrone.Core.Indexers.Newznab
{
//Let's try anyways with q parameter, worst case nothing found.
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "search",
string.Format("&q={0}", searchCriteria.Movie.Title)));
string.Format("&q={0}", Parser.Parser.NormalizeTitle(searchCriteria.Movie.Title))));
}
return pageableRequests;

View File

@@ -60,7 +60,7 @@ namespace NzbDrone.Core.Indexers.Newznab
public NewznabSettings()
{
Categories = new[] { 2030, 2035, 2040, 2045, 2050 };
Categories = new[] { 2000, 2010, 2020, 2030, 2035, 2040, 2045, 2050, 2060 };
AnimeCategories = Enumerable.Empty<int>();
}

View File

@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
protected override string GetInfoUrl(XElement item)
{
//Todo: Me thinks I need to parse details to get this...
var match = Regex.Match(item.Description(), @"(?:\<b\>View NZB\:\<\/b\>\s\<a\shref\=\"")(?<URL>.+)(?:\""\starget)",
var match = Regex.Match(item.Description(), @"(?:\<b\>View NZB\:\<\/b\>\s\<a\shref\=\"")(?<URL>.+)(?:\"")",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
if (match.Success)

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
using NzbDrone.Common.Http;
@@ -36,11 +37,11 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
torrentInfo.Size = (long)torrent.size*1000*1000;
torrentInfo.DownloadUrl = torrent.download_url;
torrentInfo.InfoUrl = torrent.details_url;
torrentInfo.PublishDate = new System.DateTime();
torrentInfo.PublishDate = torrent.publish_date.ToUniversalTime();
torrentInfo.Seeders = torrent.seeders;
torrentInfo.Peers = torrent.leechers + torrent.seeders;
torrentInfo.Freeleech = torrent.freeleech;
results.Add(torrentInfo);
}

View File

@@ -78,9 +78,16 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
.Accept(HttpAccept.Json);
requestBuilder.AddQueryParam("passkey", Settings.Passkey);
requestBuilder.AddQueryParam("user", Settings.User);
// requestBuilder.AddQueryParam("imdbid", "tt0076759"); //For now just search for Star Wars.
requestBuilder.AddQueryParam("search", "the"); // there has to be movies with 'the' in the title on any indexer
if (!string.IsNullOrWhiteSpace(Settings.User))
{
requestBuilder.AddQueryParam("user", Settings.User);
}
else
{
requestBuilder.AddQueryParam("user", "");
}
requestBuilder.AddQueryParam("search", "the");
yield return new IndexerRequest(requestBuilder.Build());
}
@@ -91,7 +98,15 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
.Accept(HttpAccept.Json);
requestBuilder.AddQueryParam("passkey", Settings.Passkey);
requestBuilder.AddQueryParam("user", Settings.User);
if (!string.IsNullOrWhiteSpace(Settings.User))
{
requestBuilder.AddQueryParam("user", Settings.User);
}
else
{
requestBuilder.AddQueryParam("user", "");
}
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
{

View File

@@ -21,6 +21,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
public int size { get; set; }
public int leechers { get; set; }
public int seeders { get; set; }
public DateTime publish_date { get; set; }
}
}

View File

@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
public TorrentPotatoSettings()
{
BaseUrl = "";
BaseUrl = "http://127.0.0.1";
}
[FieldDefinition(0, Label = "API URL", HelpText = "URL to TorrentPotato api.")]

View File

@@ -97,8 +97,7 @@ namespace NzbDrone.Core.Indexers.Torznab
}
if (capabilities.SupportedTvSearchParameters != null &&
new[] { "q", "tvdbid", "rid" }.Any(v => capabilities.SupportedTvSearchParameters.Contains(v)) &&
new[] { "season", "ep" }.All(v => capabilities.SupportedTvSearchParameters.Contains(v)))
new[] { "q", "imdbid" }.Any(v => capabilities.SupportedTvSearchParameters.Contains(v)))
{
return null;
}

View File

@@ -39,10 +39,13 @@ namespace NzbDrone.Core.Indexers.Torznab
protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInfo)
{
var torrentInfo = base.ProcessItem(item, releaseInfo) as TorrentInfo;
torrentInfo.TvdbId = GetTvdbId(item);
torrentInfo.TvRageId = GetTvRageId(item);
if (GetImdbId(item) != null)
{
if (torrentInfo != null)
{
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
}
}
return torrentInfo;
}
@@ -100,31 +103,12 @@ namespace NzbDrone.Core.Indexers.Torznab
return url;
}
protected virtual int GetTvdbId(XElement item)
protected virtual string GetImdbId(XElement item)
{
var tvdbIdString = TryGetTorznabAttribute(item, "tvdbid");
int tvdbId;
if (!tvdbIdString.IsNullOrWhiteSpace() && int.TryParse(tvdbIdString, out tvdbId))
{
return tvdbId;
}
return 0;
var imdbIdString = TryGetTorznabAttribute(item, "imdbid");
return (!imdbIdString.IsNullOrWhiteSpace() ? imdbIdString.Substring(2) : null);
}
protected virtual int GetTvRageId(XElement item)
{
var tvRageIdString = TryGetTorznabAttribute(item, "rageid");
int tvRageId;
if (!tvRageIdString.IsNullOrWhiteSpace() && int.TryParse(tvRageIdString, out tvRageId))
{
return tvRageId;
}
return 0;
}
protected override string GetInfoHash(XElement item)
{
return TryGetTorznabAttribute(item, "infohash");

View File

@@ -64,9 +64,9 @@ namespace NzbDrone.Core.Jobs
new ScheduledTask{ Interval = 0.25f, TypeName = typeof(CheckForFinishedDownloadCommand).FullName},
new ScheduledTask{ Interval = 5, TypeName = typeof(MessagingCleanupCommand).FullName},
new ScheduledTask{ Interval = 6*60, TypeName = typeof(ApplicationUpdateCommand).FullName},
new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
// new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
new ScheduledTask{ Interval = 6*60, TypeName = typeof(CheckHealthCommand).FullName},
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName},
new ScheduledTask{ Interval = 24*60, TypeName = typeof(RefreshMovieCommand).FullName},
new ScheduledTask{ Interval = 24*60, TypeName = typeof(HousekeepingCommand).FullName},
new ScheduledTask{ Interval = 7*24*60, TypeName = typeof(BackupCommand).FullName},
@@ -80,6 +80,7 @@ namespace NzbDrone.Core.Jobs
{
Interval = _configService.DownloadedEpisodesScanInterval,
TypeName = typeof(DownloadedEpisodesScanCommand).FullName
//TypeName = typeof(DownloadedMovieScanCommand).FullName
},
};

View File

@@ -114,7 +114,7 @@ namespace NzbDrone.Core.MediaCover
}
}
private void EnsureCovers(Movie movie)
private void EnsureCovers(Movie movie, int retried = 0)
{
foreach (var cover in movie.Images)
{
@@ -130,7 +130,25 @@ namespace NzbDrone.Core.MediaCover
}
catch (WebException e)
{
_logger.Warn(string.Format("Couldn't download media cover for {0}. {1}", movie, e.Message));
if (e.Status == WebExceptionStatus.ProtocolError)
{
_logger.Warn(e, "Server returned different code than 200. The poster is probably not available yet.");
return;
}
_logger.Warn(e, string.Format("Couldn't download media cover for {0}. {1}", movie, e.Message));
if (retried < 3)
{
retried = +1;
_logger.Warn("Retrying for the {0}. time in ten seconds.", retried);
System.Threading.Thread.Sleep(10*1000);
EnsureCovers(movie, retried);
}
else
{
_logger.Warn(e, "Couldn't download media cover even after retrying five times :(.");
}
}
catch (Exception e)
{

View File

@@ -178,7 +178,7 @@ namespace NzbDrone.Core.MediaFiles
_mediaFileTableCleanupService.Clean(movie, mediaFileList);
var decisionsStopwatch = Stopwatch.StartNew();
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie);
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie, true);
decisionsStopwatch.Stop();
_logger.Trace("Import decisions complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed);

View File

@@ -183,7 +183,7 @@ namespace NzbDrone.Core.MediaFiles
}
}
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true);
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true, false);
var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
if ((downloadClientItem == null || !downloadClientItem.IsReadOnly) &&
@@ -237,7 +237,7 @@ namespace NzbDrone.Core.MediaFiles
}
}
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true);
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true, false);
return _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
}

View File

@@ -68,21 +68,22 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
{
//check if already imported
if (importResults.Select(r => r.ImportDecision.LocalMovie.Movie)
.Select(e => e.Id).Contains(localMovie.Movie.Id))
.Select(m => m.Id).Contains(localMovie.Movie.Id))
{
importResults.Add(new ImportResult(importDecision, "Movie has already been imported"));
continue;
}
var episodeFile = new MovieFile();
episodeFile.DateAdded = DateTime.UtcNow;
episodeFile.MovieId = localMovie.Movie.Id;
episodeFile.Path = localMovie.Path.CleanFilePath();
episodeFile.Size = _diskProvider.GetFileSize(localMovie.Path);
episodeFile.Quality = localMovie.Quality;
episodeFile.MediaInfo = localMovie.MediaInfo;
episodeFile.Movie = localMovie.Movie;
episodeFile.ReleaseGroup = localMovie.ParsedMovieInfo.ReleaseGroup;
var movieFile = new MovieFile();
movieFile.DateAdded = DateTime.UtcNow;
movieFile.MovieId = localMovie.Movie.Id;
movieFile.Path = localMovie.Path.CleanFilePath();
movieFile.Size = _diskProvider.GetFileSize(localMovie.Path);
movieFile.Quality = localMovie.Quality;
movieFile.MediaInfo = localMovie.MediaInfo;
movieFile.Movie = localMovie.Movie;
movieFile.ReleaseGroup = localMovie.ParsedMovieInfo.ReleaseGroup;
movieFile.Edition = localMovie.ParsedMovieInfo.Edition;
bool copyOnly;
switch (importMode)
@@ -101,17 +102,17 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
if (newDownload)
{
episodeFile.SceneName = GetSceneName(downloadClientItem, localMovie);
movieFile.SceneName = GetSceneName(downloadClientItem, localMovie);
var moveResult = _episodeFileUpgrader.UpgradeMovieFile(episodeFile, localMovie, copyOnly);
var moveResult = _episodeFileUpgrader.UpgradeMovieFile(movieFile, localMovie, copyOnly); //TODO: Check if this works
oldFiles = moveResult.OldFiles;
}
else
{
episodeFile.RelativePath = localMovie.Movie.Path.GetRelativePath(episodeFile.Path);
movieFile.RelativePath = localMovie.Movie.Path.GetRelativePath(movieFile.Path);
}
_mediaFileService.Add(episodeFile);
_mediaFileService.Add(movieFile);
importResults.Add(new ImportResult(importDecision));
if (newDownload)
@@ -121,22 +122,22 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
if (downloadClientItem != null)
{
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, episodeFile, newDownload, downloadClientItem.DownloadClient, downloadClientItem.DownloadId, downloadClientItem.IsReadOnly));
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, movieFile, newDownload, downloadClientItem.DownloadClient, downloadClientItem.DownloadId, downloadClientItem.IsReadOnly));
}
else
{
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, episodeFile, newDownload));
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, movieFile, newDownload));
}
if (newDownload)
{
_eventAggregator.PublishEvent(new MovieDownloadedEvent(localMovie, episodeFile, oldFiles));
_eventAggregator.PublishEvent(new MovieDownloadedEvent(localMovie, movieFile, oldFiles));
}
}
catch (Exception e)
{
_logger.Warn(e, "Couldn't import episode " + localMovie);
importResults.Add(new ImportResult(importDecision, "Failed to import episode"));
_logger.Warn(e, "Couldn't import movie " + localMovie);
importResults.Add(new ImportResult(importDecision, "Failed to import movie"));
}
}

View File

@@ -19,7 +19,8 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
{
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series);
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie);
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource); //TODO: Needs changing to ParsedMovieInfo!!
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, bool shouldCheckQuality);
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality); //TODO: Needs changing to ParsedMovieInfo!!
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource);
}
@@ -31,6 +32,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
private readonly IDiskProvider _diskProvider;
private readonly IVideoFileInfoReader _videoFileInfoReader;
private readonly IDetectSample _detectSample;
private readonly IQualityDefinitionService _qualitiesService;
private readonly Logger _logger;
public ImportDecisionMaker(IEnumerable<IImportDecisionEngineSpecification> specifications,
@@ -39,6 +41,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
IDiskProvider diskProvider,
IVideoFileInfoReader videoFileInfoReader,
IDetectSample detectSample,
IQualityDefinitionService qualitiesService,
Logger logger)
{
_specifications = specifications;
@@ -47,6 +50,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
_diskProvider = diskProvider;
_videoFileInfoReader = videoFileInfoReader;
_detectSample = detectSample;
_qualitiesService = qualitiesService;
_logger = logger;
}
@@ -57,7 +61,12 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie)
{
return GetImportDecisions(videoFiles, movie, null, false);
return GetImportDecisions(videoFiles, movie, null, true, false);
}
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, bool shouldCheckQuality = false)
{
return GetImportDecisions(videoFiles, movie, null, true, shouldCheckQuality);
}
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource)
@@ -77,7 +86,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
return decisions;
}
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource)
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality = false)
{
var newFiles = _mediaFileService.FilterExistingFiles(videoFiles.ToList(), movie);
@@ -88,13 +97,13 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
foreach (var file in newFiles)
{
decisions.AddIfNotNull(GetDecision(file, movie, folderInfo, sceneSource, shouldUseFolderName));
decisions.AddIfNotNull(GetDecision(file, movie, folderInfo, sceneSource, shouldUseFolderName, shouldCheckQuality));
}
return decisions;
}
private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName)
private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
{
ImportDecision decision = null;
@@ -113,6 +122,106 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
if (sceneSource)
{
localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
if (shouldCheckQuality)
{
var width = localMovie.MediaInfo.Width;
var current = localMovie.Quality;
var qualityName = current.Quality.Name.ToLower();
QualityModel updated = null;
if (width > 1400)
{
if (qualityName.Contains("bluray"))
{
updated = new QualityModel(Quality.Bluray1080p);
}
else if (qualityName.Contains("webdl"))
{
updated = new QualityModel(Quality.WEBDL1080p);
}
else if (qualityName.Contains("hdtv"))
{
updated = new QualityModel(Quality.HDTV1080p);
}
else
{
var def = _qualitiesService.Get(Quality.HDTV1080p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.HDTV1080p);
}
def = _qualitiesService.Get(Quality.WEBDL1080p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.WEBDL1080p);
}
def = _qualitiesService.Get(Quality.Bluray1080p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.Bluray1080p);
}
if (updated == null)
{
updated = new QualityModel(Quality.Bluray1080p);
}
}
}
else
if (width > 900)
{
if (qualityName.Contains("bluray"))
{
updated = new QualityModel(Quality.Bluray720p);
}
else if (qualityName.Contains("webdl"))
{
updated = new QualityModel(Quality.WEBDL720p);
}
else if (qualityName.Contains("hdtv"))
{
updated = new QualityModel(Quality.HDTV720p);
}
else
{
var def = _qualitiesService.Get(Quality.HDTV720p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.HDTV720p);
}
def = _qualitiesService.Get(Quality.WEBDL720p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.WEBDL720p);
}
def = _qualitiesService.Get(Quality.Bluray720p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.Bluray720p);
}
if (updated == null)
{
updated = new QualityModel(Quality.Bluray720p);
}
}
}
if (updated != null && updated != current)
{
updated.QualitySource = QualitySource.MediaInfo;
localMovie.Quality = updated;
}
}
decision = GetDecision(localMovie);
}
else

View File

@@ -161,7 +161,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
}
var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> { file },
movie, null, SceneSource(movie, folder));
movie, null, SceneSource(movie, folder), true);
return importDecisions.Any() ? MapItem(importDecisions.First(), folder, downloadId) : null;
}

View File

@@ -3,7 +3,7 @@
public enum FileDateType
{
None = 0,
LocalAirDate = 1,
UtcAirDate = 2
Cinemas = 1,
Release = 2
}
}

View File

@@ -26,6 +26,7 @@ namespace NzbDrone.Core.MediaFiles
List<string> FilterExistingFiles(List<string> files, Series series);
List<string> FilterExistingFiles(List<string> files, Movie movie);
EpisodeFile Get(int id);
MovieFile GetMovie(int id);
List<EpisodeFile> Get(IEnumerable<int> ids);
List<MovieFile> GetMovies(IEnumerable<int> ids);
@@ -110,11 +111,11 @@ namespace NzbDrone.Core.MediaFiles
public List<string> FilterExistingFiles(List<string> files, Movie movie)
{
var seriesFiles = GetFilesBySeries(movie.Id).Select(f => Path.Combine(movie.Path, f.RelativePath)).ToList();
var movieFiles = GetFilesByMovie(movie.Id).Select(f => Path.Combine(movie.Path, f.RelativePath)).ToList();
if (!seriesFiles.Any()) return files;
if (!movieFiles.Any()) return files;
return files.Except(seriesFiles, PathEqualityComparer.Instance).ToList();
return files.Except(movieFiles, PathEqualityComparer.Instance).ToList();
}
public EpisodeFile Get(int id)
@@ -150,5 +151,9 @@ namespace NzbDrone.Core.MediaFiles
_movieFileRepository.Update(episodeFile);
}
public MovieFile GetMovie(int id)
{
return _movieFileRepository.Get(id);
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using NLog;
@@ -18,14 +18,17 @@ namespace NzbDrone.Core.MediaFiles
public class MediaFileTableCleanupService : IMediaFileTableCleanupService
{
private readonly IMediaFileService _mediaFileService;
private readonly IMovieService _movieService;
private readonly IEpisodeService _episodeService;
private readonly Logger _logger;
public MediaFileTableCleanupService(IMediaFileService mediaFileService,
IMovieService movieService,
IEpisodeService episodeService,
Logger logger)
{
_mediaFileService = mediaFileService;
_movieService = movieService;
_episodeService = episodeService;
_logger = logger;
}
@@ -89,61 +92,39 @@ namespace NzbDrone.Core.MediaFiles
public void Clean(Movie movie, List<string> filesOnDisk)
{
//TODO: Update implementation for movies.
var seriesFiles = _mediaFileService.GetFilesBySeries(movie.Id);
var episodes = _episodeService.GetEpisodeBySeries(movie.Id);
var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
var filesOnDiskKeys = new HashSet<string>(filesOnDisk, PathEqualityComparer.Instance);
foreach (var seriesFile in seriesFiles)
foreach(var movieFile in movieFiles)
{
var episodeFile = seriesFile;
var episodeFilePath = Path.Combine(movie.Path, episodeFile.RelativePath);
var movieFilePath = Path.Combine(movie.Path, movieFile.RelativePath);
try
{
if (!filesOnDiskKeys.Contains(episodeFilePath))
if (!filesOnDiskKeys.Contains(movieFilePath))
{
_logger.Debug("File [{0}] no longer exists on disk, removing from db", episodeFilePath);
_mediaFileService.Delete(seriesFile, DeleteMediaFileReason.MissingFromDisk);
_logger.Debug("File [{0}] no longer exists on disk, removing from db", movieFilePath);
_mediaFileService.Delete(movieFile, DeleteMediaFileReason.MissingFromDisk);
continue;
}
if (episodes.None(e => e.EpisodeFileId == episodeFile.Id))
{
_logger.Debug("File [{0}] is not assigned to any episodes, removing from db", episodeFilePath);
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.NoLinkedEpisodes);
continue;
}
//var localMovie = _parsingService.GetLocalMovie(movieFile.Path, movie);
// var localEpsiode = _parsingService.GetLocalEpisode(episodeFile.Path, series);
//
// if (localEpsiode == null || episodes.Count != localEpsiode.Episodes.Count)
// {
// _logger.Debug("File [{0}] parsed episodes has changed, removing from db", episodeFile.Path);
// _mediaFileService.Delete(episodeFile);
// continue;
// }
//if (localMovie == null)
//{
// _logger.Debug("File [{0}] parsed episodes has changed, removing from db", localMovie.Path);
// _mediaFileService.Delete(localMovie);
// continue;
//}
}
catch (Exception ex)
{
var errorMessage = string.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id);
var errorMessage = string.Format("Unable to cleanup MovieFile in DB: {0}", movieFile.Id);
_logger.Error(ex, errorMessage);
}
}
foreach (var e in episodes)
{
var episode = e;
if (episode.EpisodeFileId > 0 && seriesFiles.None(f => f.Id == episode.EpisodeFileId))
{
episode.EpisodeFileId = 0;
_episodeService.UpdateEpisode(episode);
}
}
}
}
}

View File

@@ -48,7 +48,11 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return AudioChannelPositionsText.ContainsIgnoreCase("LFE") ? AudioChannels - 1 + 0.1m : AudioChannels;
}
return AudioChannelPositions.Split('/').Sum(s => decimal.Parse(s, CultureInfo.InvariantCulture));
decimal channels = 0;
decimal.TryParse(AudioChannelPositions.Split('/').First(), out channels);
return channels;
}
}
}

View File

@@ -19,6 +19,7 @@ namespace NzbDrone.Core.MediaFiles
public string ReleaseGroup { get; set; }
public QualityModel Quality { get; set; }
public MediaInfoModel MediaInfo { get; set; }
public string Edition { get; set; }
public LazyLoaded<Movie> Movie { get; set; }
public override string ToString()

View File

@@ -49,7 +49,7 @@ namespace NzbDrone.Core.MediaFiles
switch (_configService.FileDate)
{
case FileDateType.LocalAirDate:
case FileDateType.Release:
{
var airDate = episodes.First().AirDate;
var airTime = series.AirTime;
@@ -62,7 +62,7 @@ namespace NzbDrone.Core.MediaFiles
return ChangeFileDateToLocalAirDate(episodeFilePath, airDate, airTime);
}
case FileDateType.UtcAirDate:
case FileDateType.Cinemas:
{
var airDateUtc = episodes.First().AirDateUtc;

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -20,7 +20,7 @@ namespace NzbDrone.Core.MediaFiles
}
public class UpdateMovieFileService : IUpdateMovieFileService,
IHandle<SeriesScannedEvent>
IHandle<MovieScannedEvent>
{
private readonly IDiskProvider _diskProvider;
private readonly IConfigService _configService;
@@ -47,17 +47,67 @@ namespace NzbDrone.Core.MediaFiles
{
var movieFilePath = Path.Combine(movie.Path, movieFile.RelativePath);
switch (_configService.FileDate)
{
case FileDateType.Release:
{
var airDate = movie.PhysicalRelease;
if (airDate == null)
{
return false;
}
return ChangeFileDate(movieFilePath, airDate.Value);
}
case FileDateType.Cinemas:
{
var airDate = movie.InCinemas;
if (airDate == null)
{
return false;
}
return ChangeFileDate(movieFilePath, airDate.Value);
}
}
return false;
}
public void Handle(SeriesScannedEvent message)
private bool ChangeFileDate(string filePath, DateTime date)
{
DateTime oldDateTime = _diskProvider.FileGetLastWrite(filePath);
if (!DateTime.Equals(date, oldDateTime))
{
try
{
_diskProvider.FileSetLastWriteTime(filePath, date);
_logger.Debug("Date of file [{0}] changed from '{1}' to '{2}'", filePath, oldDateTime, date);
return true;
}
catch (Exception ex)
{
_logger.Warn(ex, "Unable to set date of file [" + filePath + "]");
}
}
return false;
}
public void Handle(MovieScannedEvent message)
{
if (_configService.FileDate == FileDateType.None)
{
return;
}
/* var movies = _movieService.MoviesWithFiles(message.Series.Id);
var movies = _movieService.MoviesWithFiles(message.Movie.Id);
var movieFiles = new List<MovieFile>();
var updated = new List<MovieFile>();
@@ -69,7 +119,7 @@ namespace NzbDrone.Core.MediaFiles
movieFiles.Add(movieFile);
if (ChangeFileDate(movieFile, message.Series, moviesInFile))
if (ChangeFileDate(movieFile, message.Movie))
{
updated.Add(movieFile);
}
@@ -77,13 +127,13 @@ namespace NzbDrone.Core.MediaFiles
if (updated.Any())
{
_logger.ProgressDebug("Changed file date for {0} files of {1} in {2}", updated.Count, movieFiles.Count, message.Series.Title);
_logger.ProgressDebug("Changed file date for {0} files of {1} in {2}", updated.Count, movieFiles.Count, message.Movie.Title);
}
else
{
_logger.ProgressDebug("No file dates changed for {0}", message.Series.Title);
}*/
_logger.ProgressDebug("No file dates changed for {0}", message.Movie.Title);
}
}
private bool ChangeFileDateToLocalAirDate(string filePath, string fileDate, string fileTime)

View File

@@ -38,10 +38,13 @@ namespace NzbDrone.Core.MediaFiles
public MovieFileMoveResult UpgradeMovieFile(MovieFile episodeFile, LocalMovie localEpisode, bool copyOnly = false)
{
_logger.Trace("Upgrading existing episode file.");
var moveFileResult = new MovieFileMoveResult();
localEpisode.Movie.MovieFile.LazyLoad();
var existingFile = localEpisode.Movie.MovieFile;
existingFile.LazyLoad();
if (existingFile.IsLoaded)
if (existingFile.IsLoaded && existingFile.Value != null)
{
var file = existingFile.Value;
var episodeFilePath = Path.Combine(localEpisode.Movie.Path, file.RelativePath);
@@ -55,6 +58,10 @@ namespace NzbDrone.Core.MediaFiles
moveFileResult.OldFiles.Add(file);
_mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
}
else
{
_logger.Warn("The existing movie file was not lazy loaded.");
}

View File

@@ -66,6 +66,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
public int vote_count { get; set; }
public AlternativeTitles alternative_titles { get; set; }
public ReleaseDatesResource release_dates { get; set; }
public VideosResource videos { get; set; }
}
public class ReleaseDatesResource
@@ -130,4 +131,21 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
public string iso_3166_1 { get; set; }
public string title { get; set; }
}
public class VideosResource
{
public List<Video> results { get; set; }
}
public class Video
{
public string id { get; set; }
public string iso_639_1 { get; set; }
public string iso_3166_1 { get; set; }
public string key { get; set; }
public string name { get; set; }
public string site { get; set; }
public string size { get; set; }
public string type { get; set; }
}
}

View File

@@ -13,6 +13,7 @@ using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Tv;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using System.Text;
namespace NzbDrone.Core.MetadataSource.SkyHook
{
@@ -72,7 +73,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
.SetSegment("route", "movie")
.SetSegment("id", TmdbId.ToString())
.SetSegment("secondaryRoute", "")
.AddQueryParam("append_to_response", "alternative_titles,release_dates")
.AddQueryParam("append_to_response", "alternative_titles,release_dates,videos")
.AddQueryParam("country", "US")
.Build();
@@ -88,8 +89,9 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
movie.TmdbId = TmdbId;
movie.ImdbId = resource.imdb_id;
movie.Title = resource.title;
movie.TitleSlug = movie.Title.ToLower().Replace(" ", "-");
movie.CleanTitle = Parser.Parser.CleanSeriesTitle(movie.Title);
movie.TitleSlug = ToUrlSlug(resource.title);
movie.CleanTitle = Parser.Parser.CleanSeriesTitle(resource.title);
movie.SortTitle = Parser.Parser.NormalizeTitle(resource.title);
movie.Overview = resource.overview;
movie.Website = resource.homepage;
if (resource.release_date.IsNotNullOrWhiteSpace())
@@ -98,11 +100,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
movie.Year = movie.InCinemas.Value.Year;
}
var slugResult = _movieService.FindByTitleSlug(movie.TitleSlug);
if (slugResult != null)
{
_logger.Debug("Movie with this title slug already exists. Adding year...");
}
movie.TitleSlug += "-" + movie.Year.ToString();
movie.Images.Add(_configService.GetCoverForURL(resource.poster_path, MediaCoverTypes.Poster));//TODO: Update to load image specs from tmdb page!
@@ -152,6 +149,29 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
{
movie.Status = MovieStatusType.Announced;
}
if (resource.videos != null)
{
foreach (Video video in resource.videos.results)
{
if (video.type == "Trailer" && video.site == "YouTube")
{
if (video.key != null)
{
movie.YouTubeTrailerId = video.key;
break;
}
}
}
}
if (resource.production_companies != null)
{
if (resource.production_companies.Any())
{
movie.Studio = resource.production_companies[0].name;
}
}
return movie;
}
@@ -189,6 +209,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
{
var lowerTitle = title.ToLower();
lowerTitle = lowerTitle.Replace(".", "");
var parserResult = Parser.Parser.ParseMovieTitle(title, true);
var yearTerm = "";
@@ -196,7 +218,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
if (parserResult != null && parserResult.MovieTitle != title)
{
//Parser found something interesting!
lowerTitle = parserResult.MovieTitle.ToLower();
lowerTitle = parserResult.MovieTitle.ToLower().Replace(".", " "); //TODO Update so not every period gets replaced (e.g. R.I.P.D.)
if (parserResult.Year > 1800)
{
yearTerm = parserResult.Year.ToString();
@@ -329,28 +351,19 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
{
imdbMovie.SortTitle = Parser.Parser.NormalizeTitle(result.title);
imdbMovie.Title = result.title;
string titleSlug = result.title;
imdbMovie.TitleSlug = titleSlug.ToLower().Replace(" ", "-");
imdbMovie.TitleSlug = ToUrlSlug(result.title);
if (result.release_date.IsNotNullOrWhiteSpace())
{
imdbMovie.Year = DateTime.Parse(result.release_date).Year;
}
var slugResult = _movieService.FindByTitleSlug(imdbMovie.TitleSlug);
if (slugResult != null)
{
_logger.Debug("Movie with this title slug already exists. Adding year...");
}
imdbMovie.TitleSlug += "-" + imdbMovie.Year.ToString();
imdbMovie.TitleSlug += "-" + imdbMovie.Year;
imdbMovie.Images = new List<MediaCover.MediaCover>();
imdbMovie.Overview = result.overview;
try
{
string url = result.poster_path;
var imdbPoster = _configService.GetCoverForURL(result.poster_path, MediaCoverTypes.Poster);
imdbMovie.Images.Add(imdbPoster);
}
@@ -524,5 +537,29 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return MediaCoverTypes.Unknown;
}
}
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;
}
}
}

View File

@@ -2,7 +2,7 @@
{
public enum PushoverPriority
{
Silent = -1,
Silent = -2,
Quiet = -1,
Normal = 0,
High = 1,

View File

@@ -183,6 +183,13 @@
<Compile Include="Datastore\Migration\002_remove_tvrage_imdb_unique_constraint.cs" />
<Compile Include="Datastore\Migration\003_remove_clean_title_from_scene_mapping.cs" />
<Compile Include="Datastore\Migration\004_updated_history.cs" />
<Compile Include="Datastore\Migration\122_add_movieid_to_blacklist.cs" />
<Compile Include="Datastore\Migration\121_update_filedate_config.cs" />
<Compile Include="Datastore\Migration\120_add_studio_to_table.cs" />
<Compile Include="Datastore\Migration\119_add_youtube_trailer_id_table .cs" />
<Compile Include="Datastore\Migration\118_update_movie_slug.cs" />
<Compile Include="Datastore\Migration\117_update_movie_file.cs" />
<Compile Include="Datastore\Migration\116_update_movie_sorttitle_again.cs" />
<Compile Include="Datastore\Migration\115_update_movie_sorttitle.cs" />
<Compile Include="Datastore\Migration\111_remove_bitmetv.cs" />
<Compile Include="Datastore\Migration\112_remove_torrentleech.cs" />
@@ -578,6 +585,7 @@
<Compile Include="IndexerSearch\Definitions\MovieSearchCriteria.cs" />
<Compile Include="IndexerSearch\MoviesSearchCommand.cs" />
<Compile Include="IndexerSearch\MoviesSearchService.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDRssParser.cs" />
<Compile Include="Indexers\DownloadProtocol.cs" />
<Compile Include="Indexers\Exceptions\ApiKeyException.cs" />
<Compile Include="Indexers\Exceptions\IndexerException.cs" />
@@ -585,6 +593,10 @@
<Compile Include="Indexers\Exceptions\UnsupportedFeedException.cs" />
<Compile Include="Indexers\EzrssTorrentRssParser.cs" />
<Compile Include="Indexers\FetchAndParseRssService.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHD.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDApi.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDRequestGenerator.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDSettings.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcorn.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcornApi.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcornInfo.cs" />

View File

@@ -58,7 +58,7 @@ namespace NzbDrone.Core.Organizer
public static readonly Regex SeriesTitleRegex = new Regex(@"(?<token>\{(?:Series)(?<separator>[- ._])(Clean)?Title\})",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static readonly Regex MovieTitleRegex = new Regex(@"(?<token>\{(?:Movie)(?<separator>[- ._])(Clean)?Title\})",
public static readonly Regex MovieTitleRegex = new Regex(@"(?<token>\{((?:(Movie|Original))(?<separator>[- ._])(Clean)?Title(The)?)\})",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled);
@@ -161,8 +161,10 @@ namespace NzbDrone.Core.Organizer
AddMovieTokens(tokenHandlers, movie);
AddReleaseDateTokens(tokenHandlers, movie.Year); //In case we want to separate the year
AddImdbIdTokens(tokenHandlers, movie.ImdbId);
AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile);
var fileName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
@@ -300,6 +302,7 @@ namespace NzbDrone.Core.Organizer
AddMovieTokens(tokenHandlers, movie);
AddReleaseDateTokens(tokenHandlers, movie.Year);
AddImdbIdTokens(tokenHandlers, movie.ImdbId);
return CleanFolderName(ReplaceTokens(namingConfig.MovieFolderFormat, tokenHandlers, namingConfig));
}
@@ -313,11 +316,27 @@ namespace NzbDrone.Core.Organizer
return title;
}
public static string TitleThe(string title)
{
string[] prefixes = { "The ", "An ", "A " };
foreach (string prefix in prefixes)
{
int prefix_length = prefix.Length;
if (prefix.ToLower() == title.Substring(0, prefix_length).ToLower())
{
title = title.Substring(prefix_length) + ", " + prefix.Trim();
break;
}
}
return title.Trim();
}
public static string CleanFileName(string name, bool replace = true)
{
string result = name;
string[] badCharacters = { "\\", "/", "<", ">", "?", "*", ":", "|", "\"" };
string[] goodCharacters = { "+", "+", "", "", "!", "-", "-", "", "" };
string[] goodCharacters = { "+", "+", "", "", "!", "-", "", "", "" };
for (int i = 0; i < badCharacters.Length; i++)
{
@@ -469,6 +488,7 @@ namespace NzbDrone.Core.Organizer
{
tokenHandlers["{Movie Title}"] = m => movie.Title;
tokenHandlers["{Movie CleanTitle}"] = m => CleanTitle(movie.Title);
tokenHandlers["{Movie Title The}"] = m => TitleThe(movie.Title);
}
private void AddReleaseDateTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, int releaseYear)
@@ -476,6 +496,11 @@ namespace NzbDrone.Core.Organizer
tokenHandlers["{Release Year}"] = m => string.Format("{0}", releaseYear.ToString()); //Do I need m.CustomFormat?
}
private void AddImdbIdTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, string imdbId)
{
tokenHandlers["{IMDb Id}"] = m => $"{imdbId}";
}
private void AddSeasonTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, int seasonNumber)
{
tokenHandlers["{Season}"] = m => seasonNumber.ToString(m.CustomFormat);
@@ -503,6 +528,14 @@ namespace NzbDrone.Core.Organizer
tokenHandlers["{Release Group}"] = m => episodeFile.ReleaseGroup ?? m.DefaultValue("Sonarr");
}
private void AddMovieFileTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, MovieFile episodeFile)
{
tokenHandlers["{Original Title}"] = m => GetOriginalTitle(episodeFile);
tokenHandlers["{Original Filename}"] = m => GetOriginalFileName(episodeFile);
//tokenHandlers["{IMDb Id}"] = m =>
tokenHandlers["{Release Group}"] = m => episodeFile.ReleaseGroup ?? m.DefaultValue("Sonarr");
}
private void AddQualityTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Series series, EpisodeFile episodeFile)
{
var qualityTitle = _qualityDefinitionService.Get(episodeFile.Quality.Quality).Title;

View File

@@ -46,8 +46,9 @@ namespace NzbDrone.Core.Organizer
_movie = new Movie
{
Title = "Movie Title",
Year = 2010
Title = "The Movie Title",
Year = 2010,
ImdbId = "tt0066921"
};
_standardSeries = new Series

View File

@@ -268,7 +268,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex ReportImdbId = new Regex(@"(?<imdbid>tt\d{9})", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex SimpleTitleRegex = new Regex(@"(?:480[ip]|576[ip]|720[ip]|1080[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*:|]|848x480|1280x720|1920x1080|(8|10)b(it)?)\s*",
private static readonly Regex SimpleTitleRegex = new Regex(@"(?:480[ip]|576[ip]|720[ip]|1080[ip]|2160[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*:|]|848x480|1280x720|1920x1080|(8|10)b(it)?)\s*",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex WebsitePrefixRegex = new Regex(@"^\[\s*[a-z]+(\.[a-z]+)+\s*\][- ]*",

View File

@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Parser
)\b",
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
private static readonly Regex HardcodedSubsRegex = new Regex(@"\b(?<hcsub>(\w+SUB))|(?<hc>(HC))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
private static readonly Regex HardcodedSubsRegex = new Regex(@"\b(?<hcsub>(\w+SUB)\b)|(?<hc>(HC))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
private static readonly Regex RawHDRegex = new Regex(@"\b(?<rawhd>RawHD|1080i[-_. ]HDTV|Raw[-_. ]HD|MPEG[-_. ]?2)\b",
RegexOptions.Compiled | RegexOptions.IgnoreCase);

View File

@@ -44,14 +44,14 @@ namespace NzbDrone.Core.Queue
private IEnumerable<Queue> MapQueue(TrackedDownload trackedDownload)
{
if (trackedDownload.RemoteEpisode.Episodes != null && trackedDownload.RemoteEpisode.Episodes.Any())
if (trackedDownload.RemoteEpisode != null && trackedDownload.RemoteEpisode.Episodes != null && trackedDownload.RemoteEpisode.Episodes.Any())
{
foreach (var episode in trackedDownload.RemoteEpisode.Episodes)
{
yield return MapEpisode(trackedDownload, episode);
}
}
else if (trackedDownload.RemoteMovie.Movie != null)
else if (trackedDownload.RemoteMovie != null && trackedDownload.RemoteMovie.Movie != null)
{
yield return MapMovie(trackedDownload, trackedDownload.RemoteMovie.Movie);
}

View File

@@ -48,6 +48,8 @@ namespace NzbDrone.Core.Tv
public LazyLoaded<MovieFile> MovieFile { get; set; }
public int MovieFileId { get; set; }
public List<string> AlternativeTitles { get; set; }
public string YouTubeTrailerId{ get; set; }
public string Studio { get; set; }
public bool HasFile => MovieFileId > 0;

View File

@@ -3,7 +3,9 @@ using System.Linq;
using System.Collections.Generic;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Datastore.Extensions;
using Marr.Data.QGen;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.Tv
{
@@ -14,6 +16,9 @@ namespace NzbDrone.Core.Tv
Movie FindByTitle(string cleanTitle, int year);
Movie FindByImdbId(string imdbid);
Movie FindByTitleSlug(string slug);
List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
List<Movie> MoviesWithFiles(int movieId);
PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec);
List<Movie> GetMoviesByFileId(int fileId);
void SetFileId(int fileId, int movieId);
}
@@ -119,5 +124,42 @@ namespace NzbDrone.Core.Tv
{
return Query.Where(m => m.TitleSlug == slug).FirstOrDefault();
}
public List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
{
var query = Query.Where(m => m.InCinemas >= start && m.InCinemas <= end).OrWhere(m => m.PhysicalRelease >= start && m.PhysicalRelease <= end);
if (!includeUnmonitored)
{
query.AndWhere(e => e.Monitored);
}
return query.ToList();
}
public List<Movie> MoviesWithFiles(int movieId)
{
return Query.Join<Movie, MovieFile>(JoinType.Inner, m => m.MovieFile, (m, mf) => m.MovieFileId == mf.Id)
.Where(m => m.Id == movieId);
}
public PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec)
{
pagingSpec.TotalRecords = GetMoviesWithoutFilesQuery(pagingSpec).GetRowCount();
pagingSpec.Records = GetMoviesWithoutFilesQuery(pagingSpec).ToList();
return pagingSpec;
}
public SortBuilder<Movie> GetMoviesWithoutFilesQuery(PagingSpec<Movie> pagingSpec)
{
return Query.Where(pagingSpec.FilterExpression)
.AndWhere(m => m.MovieFileId == 0)
.AndWhere(m => m.Status == MovieStatusType.Released)
.OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection())
.Skip(pagingSpec.PagingOffset())
.Take(pagingSpec.PageSize);
}
}
}

View File

@@ -12,6 +12,7 @@ using NzbDrone.Core.Parser;
using NzbDrone.Core.Tv.Events;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Tv
{
@@ -26,12 +27,15 @@ namespace NzbDrone.Core.Tv
Movie FindByTitleInexact(string title);
Movie FindByTitleSlug(string slug);
Movie GetMovieByFileId(int fileId);
List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec);
void DeleteMovie(int movieId, bool deleteFiles);
List<Movie> GetAllMovies();
Movie UpdateMovie(Movie movie);
List<Movie> UpdateMovie(List<Movie> movie);
bool MoviePathExists(string folder);
void RemoveAddOptions(Movie movie);
List<Movie> MoviesWithFiles(int movieId);
}
public class MovieService : IMovieService, IHandle<MovieFileAddedEvent>,
@@ -224,5 +228,24 @@ namespace NzbDrone.Core.Tv
{
return _movieRepository.FindByTitleSlug(slug);
}
public List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
{
var episodes = _movieRepository.MoviesBetweenDates(start.ToUniversalTime(), end.ToUniversalTime(), includeUnmonitored);
return episodes;
}
public List<Movie> MoviesWithFiles(int movieId)
{
return _movieRepository.MoviesWithFiles(movieId);
}
public PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec)
{
var movieResult = _movieRepository.MoviesWithoutFiles(pagingSpec);
return movieResult;
}
}
}

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