1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-12 20:36:55 -04:00

Compare commits

...

154 Commits

Author SHA1 Message Date
Leonardo Galli
5a8d944397 Fixed sorting in movie list view. Also added new downloaded quality column.
Fixes #128
2017-01-12 23:07:09 +01:00
Leonardo Galli
0b70a5c315 Should fix ordering of releases. Fixes #147 (hopefully) 2017-01-12 22:12:32 +01:00
Leonardo Galli
91cded3b71 Merge pull request #202 from Radarr/onedr0p-patch-1
Update UserAgentBuilder.cs
2017-01-12 21:48:16 +01:00
Leonardo Galli
84112dc85b Should fix queueService failed while processing
(#178)
2017-01-12 21:48:02 +01:00
Devin Buhl
b1b947ae7f Update UserAgentBuilder.cs
Make user-agent Radarr
2017-01-12 15:41:56 -05:00
Leonardo Galli
1b035f8657 Update Parser to support large array of Extended, Director, Collectors, ... Cut, Edition, etc.
Fixes #192
2017-01-12 19:21:09 +01:00
Devin Buhl
9d50f4d651 Merge pull request #199 from Radarr/patch/add-uhd-todefault-indexers
Add UHD to default movie categories for newsnab providers
2017-01-12 12:58:23 -05:00
Devin Buhl
c06a6dc988 Add UHD to default movie categories for newsnab providers 2017-01-12 12:53:09 -05:00
Devin Buhl
f198ca2b77 Merge pull request #177 from Radarr/patch/sort-title
Movies in list don't sort correctly #174
2017-01-12 01:08:32 -05:00
Devin Buhl
9cfc766889 Merge pull request #180 from wcomartin/Issue115
Changed Sonarr Branding to Radarr
2017-01-11 23:27:31 -05:00
William Comartin
5ef1e40403 Change Sonarr to Radarr in CLA.md and CONTRIBUTING.md 2017-01-11 22:02:54 -05:00
William Comartin
c9e6835d7b Change Sonarr to Radarr in Help Text, and in Notification Text
Change sonarr log files to radarr log files
2017-01-11 21:59:13 -05:00
William Comartin
604cea00f6 Replace Sonarr With Radarr in UI Directory 2017-01-11 21:42:47 -05:00
Tim Turner
b4782da1d1 Update sortValue when selecting movie for manual import 2017-01-11 19:29:22 -05:00
Devin Buhl
d5504043c5 Movies in list don't sort correctly #174 2017-01-11 19:06:08 -05:00
Leonardo Galli
81ebbcad70 Now hidden files are ignored :). Fixes #166. 2017-01-11 23:05:11 +01:00
Leonardo Galli
92e9dc6ee1 Fix sorting of unkown release date. 2017-01-11 22:39:07 +01:00
Leonardo Galli
5e8b617625 Sorting now working according to quality in release collection. Fixes #85. 2017-01-11 22:27:37 +01:00
Leonardo Galli
2cbe17151d Correctly check if inCinemas date is present. Creates issue with sorting, but eh. Fixes 140. 2017-01-11 22:02:24 +01:00
Devin Buhl
95bd615718 Merge pull request #169 from Radarr/patch/big-movie-revenues
Problem with Avatar (2009) #168
2017-01-11 15:53:16 -05:00
Leonardo Galli
8e8c4ff497 Update parser to recognize [] and year at the beginning. Fixes #155, fixes #137 and fixes #136. 2017-01-11 21:49:59 +01:00
Devin Buhl
5eddcc1660 Problem with Avatar (2009) #168 2017-01-11 15:48:19 -05:00
Tim Turner
d42165a93a Clean up basic movie naming
Fixes #132
2017-01-11 15:03:55 -05:00
Devin Buhl
99012d8a40 Merge pull request #163 from Radarr/patch/fix-plex-notifs
update plex movie libraries instead of series
2017-01-11 12:35:01 -05:00
Devin Buhl
8bc42c76e4 update plex movie libraries instead of series 2017-01-11 12:25:27 -05:00
Leonardo Galli
b7f72c6259 Merge pull request #160 from Radarr/patch/fix-newznab
fix some spelling mistakes and update the newznab api 'imdbid'
2017-01-11 16:59:09 +01:00
Devin Buhl
64ef8db037 fix some spelling mistakes and update the newznab api 'imdbid' 2017-01-11 10:51:06 -05:00
Leonardo Galli
3b5887bf09 Merge pull request #133 from Radarr/fix-manual-import
Fix Manual Import & Drone Factory
2017-01-11 16:39:09 +01:00
Leonardo Galli
40a75949ba Merge pull request #156 from CHBMB/develop
aarch64 docker container added to readme.
2017-01-11 16:33:36 +01:00
Neil
6747267d19 aarch64 docker container added to readme. 2017-01-11 15:12:26 +00:00
Devin Buhl
13db03f97c Merge pull request #154 from Radarr/patch/remove-fanzub
removed indexer Fanzub - site shutdown
2017-01-11 10:12:03 -05:00
Devin Buhl
cd68eea790 removed indexer Fanzub - site shutdown 2017-01-11 09:40:42 -05:00
Devin Buhl
cfe55d00ae Merge pull request #148 from Radarr/patch/newznab-imdb
search imdbid for usenet indexers that support it
2017-01-11 08:53:28 -05:00
Devin Buhl
1d88313424 #146 search imdbid for usenet indexers that support it 2017-01-11 08:42:29 -05:00
Mike
9513068467 Get rid of unnecessary AppVeyor builds. 2017-01-11 08:57:15 +01:00
Tim Turner
9206258370 Fixes Manual Import and DroneFactory
Automatic Import still doesn't work - waiting for answer from Sonarr
team.
2017-01-10 21:12:47 -05:00
Tim Turner
0fa1509ca6 Manual Import works
Automatically importing still broken
2017-01-10 19:37:17 -05:00
Devin Buhl
c5eb772f7a Merge pull request #130 from Radarr/newznab-patch
Add category 2035 to Newznab providers for WEB-DL search support. #123
2017-01-10 19:14:21 -05:00
Devin Buhl
04fec6d4d8 Add category 2035 to Newznab providers for WEB-DL search support. #123 2017-01-10 19:09:12 -05:00
Devin Buhl
d0b5e380d7 Merge pull request #122 from Radarr/transmission-patch
Fix transmission
2017-01-10 17:43:16 -05:00
Devin Buhl
df69c58d2b Fix transmission 2017-01-10 17:37:23 -05:00
Leonardo Galli
27114c9399 Merge pull request #119 from CHBMB/develop
Update readme.md
2017-01-10 23:25:05 +01:00
Neil
cfca07996b Update readme.md 2017-01-10 22:19:12 +00:00
Leonardo Galli
e97b80f630 Update readme.md 2017-01-10 23:19:00 +01:00
Devin Buhl
792679fd81 Merge pull request #118 from lxh87/patch-1
Update SystemLayout.js
2017-01-10 16:50:15 -05:00
lxh87
ecf47d4b17 Update SystemLayout.js
Change restart/shutdown message from"Sonarr" to "Radarr"
2017-01-10 22:42:44 +01:00
Leonardo Galli
3b1d49a78f Update readme.md 2017-01-10 22:30:36 +01:00
Devin Buhl
753f3eb863 Merge pull request #117 from Radarr/wombles-patch
Fix Wombles for movies
2017-01-10 16:29:02 -05:00
Devin Buhl
9fc2d22d19 Fix Wombles for movies 2017-01-10 16:28:16 -05:00
Tim Turner
3cb42f06c2 Clean up Feature Requests 2017-01-10 16:05:56 -05:00
Devin Buhl
a6c396a595 Merge pull request #111 from Radarr/addmovie-patch
fix #108 - Links to IMDB not working when searching for movies
2017-01-10 15:45:39 -05:00
Devin Buhl
bac9076b1e fix #108 - Links to IMDB not working when searching for movies 2017-01-10 15:39:25 -05:00
Tim Turner
b228273be0 Update Info page.
Updates #73
2017-01-10 15:34:43 -05:00
Leonardo Galli
e7fa4cba19 Fix download rejections being ignored. 2017-01-10 21:25:36 +01:00
Leonardo Galli
0506cc4185 Merge branch 'develop' of https://github.com/galli-leo/Radarr into develop 2017-01-10 20:07:01 +01:00
Leonardo Galli
cde8b4dd97 Added MovieFileResource. This allows the UI to interact with movie files better. Downloaded Quality is now shown in the table. 2017-01-10 20:06:53 +01:00
Leonardo Galli
0a0a44162c Merge pull request #105 from galli-leo/linux-tmp-path-patch
Fixes #104 - Backup/update fail Access to the path "/tmp/nzbdrone_backup/config.xml" is denied
2017-01-10 19:31:12 +01:00
Devin Buhl
125f46fbec Fixes #104 - Backup/update fail Access to the path "/tmp/nzbdrone_backup/config.xml" is denied 2017-01-10 13:21:54 -05:00
Leonardo Galli
f3222ca7c7 Merge pull request #102 from galli-leo/addmovies-patch
When adding a movie, monitored toggle doesn't apply and always defaults to being monitored
2017-01-10 19:21:24 +01:00
Devin Buhl
d252a8b232 Fixes #100 - When adding a movie, monitored toggle doesn't apply and always defaults to being monitored 2017-01-10 12:39:28 -05:00
Leonardo Galli
48559cf964 Updated legend with number of movies 2017-01-10 17:36:04 +01:00
Leonardo Galli
c734e8bc7e Update legend for missing status colors. 2017-01-10 17:07:32 +01:00
Leonardo Galli
3c7d7756e6 Fix issues with media managment config not getting saved. 2017-01-10 17:05:37 +01:00
Leonardo Galli
683bda49d8 Movie Editor works now. Fixes #99. 2017-01-10 16:51:56 +01:00
Leonardo Galli
52fb29ee18 Fixes a few things with importing: Sample check is done even when file is already in movie folder. Fixed importing of movies with "DC". 2017-01-10 16:23:07 +01:00
Leonardo Galli
236e16c9a5 Update sample detection runtime minutes. Some trailers can be long. 2017-01-10 15:43:35 +01:00
Leonardo Galli
0584038273 Fix queue specification. 2017-01-10 15:33:39 +01:00
Leonardo Galli
6685aea144 Movie search should now work, even when titles returned from the TMDB do not have a release date set. Fixes #27. 2017-01-10 15:29:20 +01:00
Leonardo Galli
e4f7aa52df History now correctly shows movie title. Fixes #92 2017-01-10 15:15:15 +01:00
Leonardo Galli
f61c4feb00 Redownloading failed downloads works again. Fixes #89. 2017-01-10 14:15:27 +01:00
Leonardo Galli
04e8c635e0 Use correct Modal for editing movies in table view. Fixes #90 2017-01-10 14:05:01 +01:00
Leonardo Galli
93ea5cfdee Merge pull request #88 from schumi2004/develop
Replace Sonarr with Radarr in Test notification messages
2017-01-10 11:31:39 +01:00
schumi2004
1b7288e7cb Replace Sonarr with Radarr in Test notification messages 2017-01-10 11:21:09 +01:00
Tim Turner
f1914082b8 Merge pull request #74 from fedoranimus/develop
Taking a pass at Library import and rename/organize
2017-01-09 17:31:25 -05:00
Tim Turner
6016948329 Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-09 17:26:25 -05:00
Tim Turner
708db1a75c Organize & Rename work 2017-01-09 17:26:13 -05:00
Leonardo Galli
994e881ba6 Fixes an issue with movies not being added with same title slug as existing movies. 2017-01-09 23:16:54 +01:00
Leonardo Galli
893e20c27b Fix some links under status. Needs further changing further down the line. 2017-01-09 22:17:17 +01:00
Tim Turner
23aace6149 Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop
# Conflicts:
#	src/NzbDrone.Api/Series/MovieResource.cs
2017-01-09 15:59:25 -05:00
Leonardo Galli
e774e6a038 Fix for importing movie folders with the at the end. 2017-01-09 21:37:37 +01:00
Leonardo Galli
f19a1a5960 Update Parser to support 576p movies, fixes #67 2017-01-09 18:43:41 +01:00
Devin Buhl
03156d62f6 Remove some indexers and fixed HDBits (#79)
* Update HDBitsRequestGenerator.cs

* Removed torrentleech, btn and bitmetv
2017-01-09 18:28:08 +01:00
Leonardo Galli
04d01dc781 Fixes Parser to match ImdbId as well as (year).
Also fixes searching by imdbid. Fixes importing existing movies as well.
2017-01-09 17:52:55 +01:00
Leonardo Galli
cfae8807aa Fixes movies not being able to be searched for.
(Very stupid mistake on my part.) Fixes #80
2017-01-09 16:47:51 +01:00
Tim Turner
f90e77987e Merge pull request #70 from aaearon/indexer-fix/omgwtfnzbs
update rss sync and fix search for omgwtfnzbs indexer
2017-01-09 08:39:23 -05:00
Devin Buhl
2ed0738b30 Added PassThePopcorn indexer (#64)
* Added PassThePopcorn indexe

* Added checkboxes for Gold and Checked torrents thanks @evulhotdog

* Sorted movie releases by golden -> checked -> upload date

* Refactored logic.

* Added flags at the end of torrent name for golden / approved

* Updated PTP GOlden to be the popcorn emoji

* Revert "Updated PTP GOlden to be the popcorn emoji"

This reverts commit c6cf0f5fc5.

* Opps, hopefully build will pass now.

* Move PTP props to new subclass.
2017-01-09 14:30:15 +01:00
Tim Turner
74c5664a7f Taking another pass at organization/renaming
Works once in a while
2017-01-08 22:16:14 -05:00
Tim Turner
4c9abe3d84 Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-08 19:48:14 -05:00
Tim Turner
7a45394820 Unable to properly parse many movie titles 2017-01-08 19:48:04 -05:00
Tim Schindler
588a48e65d update rss sync and fix search for omgwtfnzbs indexer 2017-01-08 18:49:27 -05:00
Leonardo Galli
83453e2464 Update SkyHookProxy.cs 2017-01-09 00:40:36 +01:00
Leonardo Galli
e6809585c9 Update SonarrCloudRequestBuilder.cs
Fix https error on older mono versions
2017-01-08 23:58:49 +01:00
Tim Turner
14bf63e21d Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-08 17:01:47 -05:00
Tim Turner
b5d932866a Second Pass at rename/organize 2017-01-08 17:01:37 -05:00
Leonardo Galli
0b8a84a57c Merge branch 'develop' of https://github.com/galli-leo/Radarr into develop 2017-01-08 20:45:22 +01:00
Leonardo Galli
3555b4ce20 Change name from updated message. 2017-01-08 20:45:19 +01:00
Mike
8cad976e7f Update readme.md 2017-01-08 20:23:24 +01:00
Leonardo Galli
ad7b6a8ec2 Remove hacky way to change branch 2017-01-08 20:09:44 +01:00
Leonardo Galli
906ecfb6a1 Fixed multiple things in the Update procedure 2017-01-08 20:06:39 +01:00
Mike
03cc3a1ad2 Change default branch in config. (#63)
* Change Sonarr / NzbDrone auto-updater stuff to Radarr.

This is required in order for the auto-updater to work.

* Change default branch to develop instead of forcing it.
2017-01-08 19:42:46 +01:00
Mike
d62dbd48ae Change Sonarr / NzbDrone auto-updater stuff to Radarr. (#61)
This is required in order for the auto-updater to work.
2017-01-08 18:47:48 +01:00
Leonardo Galli
cb12945270 Merge branch 'develop' of https://github.com/galli-leo/Radarr into develop 2017-01-08 18:16:10 +01:00
Leonardo Galli
af74854b8e Fix Service install, when Sonarr is also present. Fixes #55. 2017-01-08 18:16:07 +01:00
Leonardo Galli
f35fae109b Merge pull request #59 from galli-leo/feature/release-dates
Physical release dates now are retreived and stored.
2017-01-08 17:57:22 +01:00
Leonardo Galli
804b2130a8 Merge branch 'develop' into feature/release-dates 2017-01-08 17:49:06 +01:00
Leonardo Galli
49537a2efe Update UI to display download status. 2017-01-08 17:47:19 +01:00
Leonardo Galli
1dfb4ddcd8 Fixes sorting of movies. Fixes #53. 2017-01-08 17:10:56 +01:00
Leonardo Galli
fb7969e046 Available date is now displayed. 2017-01-08 16:36:51 +01:00
Tim Turner
cd4863b974 Display UI for MovieEditor, remove reference to SeasonPass 2017-01-08 09:16:24 -05:00
Leonardo Galli
55f4a81dee Adding first implementation of release_dates for movies. 2017-01-08 12:58:39 +01:00
Tim Turner
d006df8d7c Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-08 06:51:47 -05:00
Leonardo Galli
97095733dd Sets Branch to develop. We need to change this later. 2017-01-08 11:28:23 +01:00
Mike
d08b0ce47a Integrate AppVeyor and change assembly versioning (#50)
* Change tvsearch to movie.

* Start working on AppVeyor.

* Add builds.

* MSBuild clean

* Fix.

* Added submodules.

* Add NuGet and Build.

* Restore properly.

* Proper build.

* Disable appveyor tests.

* Ignore cakebuild tools and updated build task.

* Package mono finished.

* Added osx package task.

* Less output, added osx package.

* Shut up npm.

* Actually shut up.

* Added PackageTests task.

* Added task CleanupWindowsPackage.

* Add artifacts.

* AssemblyVersion patching.

* Fix appveyor path.

* Is this a valid pattern?

* Cache node modules.

* Put in subdirectory.

* Start from v0.2.0.x to have a clean start with versions.

* Add tests.

* Tests work but disabled for now.

* Disable for real.
2017-01-08 11:03:04 +01:00
Leonardo Galli
caa5a7e6b7 Merge branch 'develop' of https://github.com/galli-leo/Radarr into develop 2017-01-08 10:58:54 +01:00
Leonardo Galli
9376c02158 Movies can now be edited, even from the detail view. Fixes #42 2017-01-08 10:58:51 +01:00
Tim Turner
1ebd639e36 Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-07 21:05:30 -05:00
Tim Turner
eff34725af Merge pull request #47 from mitchellcash/remove_DS_Store
Remove all .DS_Store files
2017-01-07 20:57:10 -05:00
Tim Turner
00d4bfd712 Merge pull request #48 from fedoranimus/develop
Harden parsing of imported movie titles
2017-01-07 20:56:33 -05:00
Tim Turner
5f9e285c70 Fix issues with ", the" not trimming properly 2017-01-07 20:55:14 -05:00
Tim Turner
902824cdbd Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-07 20:54:52 -05:00
Mitchell Cash
d3cbf9a8ff Remove all .DS_Store files
It is now part of .gitignore so hopefully we shouldn't see these again.
2017-01-08 11:20:50 +10:00
Mike
c63704ba0d Change tvsearch to movie. (#46) 2017-01-07 20:48:45 +01:00
Tim Turner
da404d6435 Merge pull request #45 from fedoranimus/develop
Enables the Import UI & parses movie titles which contain year
2017-01-07 14:31:24 -05:00
Tim Turner
d9a6c4f211 Update import UI & parse titles which contain years 2017-01-07 14:29:23 -05:00
Tim Turner
7436997f9b Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-07 12:38:58 -05:00
Tim Turner
4c2be68549 Merge pull request #38 from fedoranimus/develop
First pass at Media Management
2017-01-07 12:31:28 -05:00
Tim Turner
6d1766d81a Update default formats 2017-01-07 12:19:26 -05:00
Tim Turner
3e676d2073 Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-07 11:58:47 -05:00
Leonardo Galli
6da73d73a5 Merge pull request #40 from AeonLucid/develop
Update services url to fix auto-updater.
2017-01-07 17:40:33 +01:00
Tim Turner
b9c98205e0 Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-07 11:12:26 -05:00
Leonardo Galli
07d2f5b6a0 Update package.sh to support OSX AutoUpdater 2017-01-07 12:49:10 +01:00
Leonardo Galli
bfa479507c Update package.sh and PathExtensions in preparation for AutoUpdater 2017-01-07 12:40:19 +01:00
Leonardo Galli
4182728901 Updated all AssemblyInfos so version info only needs to be changed once 2017-01-07 12:03:56 +01:00
Leonardo Galli
5be5709043 Update package.sh, fixes #35 2017-01-07 11:24:53 +01:00
Leonardo Galli
ee5a2ec289 Merge branch 'develop' of https://github.com/galli-leo/Radarr into develop 2017-01-07 11:03:59 +01:00
Leonardo Galli
cdfb95f425 Hopefully icon is now finally fixed. 2017-01-07 11:02:56 +01:00
Leonardo Galli
451060cb65 Merge pull request #37 from aaearon/rtorrent
dirty fix for rtorrent
2017-01-07 10:47:10 +01:00
Leonardo Galli
4d795e13cd Fix for movie naming config. Still kinda hacky, but works ok now. 2017-01-07 10:42:21 +01:00
Leonardo Galli
ff6bf235aa Merge branch 'develop' of https://github.com/galli-leo/Radarr into develop 2017-01-07 09:47:14 +01:00
Leonardo Galli
a272127a00 Should finally fix exe icon and resulting build error. 2017-01-07 09:47:08 +01:00
AeonLucid
e3bc6de734 Update services url to fix auto-updater. 2017-01-07 05:48:24 +01:00
Tim Turner
23249de728 Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-06 22:51:47 -05:00
Tim Turner
05e4af9ae7 1st pass at Movie Naming
Parser is failing on the sample
2017-01-06 22:51:15 -05:00
Tim Turner
1864a79f99 Merge pull request #36 from aaearon/nzbs.org
changed nzbs.org category for movies
2017-01-06 22:24:35 -05:00
Tim Schindler
5843a881e6 changed nzbs.org category for movies 2017-01-06 21:58:46 -05:00
Tim Schindler
d898fbb4b0 dirty fix for rtorrent 2017-01-06 21:54:24 -05:00
Tim Turner
721767331b Update naming management
Still need to write BuildFileName() and BuildFilePath()
2017-01-06 19:32:19 -05:00
Leonardo Galli
abd4c1a1ad Merge branch 'develop' of https://github.com/galli-leo/Radarr into develop 2017-01-06 23:16:39 +01:00
Leonardo Galli
df971b1289 Fix exe icon. 2017-01-06 23:16:35 +01:00
Leonardo Galli
e5c81eefd2 Merge pull request #34 from onedr0p/develop
Instead of searching for imdbid (which jackett may or may not have depending on the tracker) search for a word instead.
2017-01-06 21:56:02 +01:00
Tim Turner
49c7c033d9 Merge remote-tracking branch 'refs/remotes/galli-leo/develop' into develop 2017-01-06 15:31:19 -05:00
Devin Buhl
f7fb238fb4 Merge pull request #1 from onedr0p/onedr0p-patch-1
Update TorrentPotatoRequestGenerator.cs
2017-01-06 15:27:33 -05:00
Devin Buhl
52dbd8d708 Update TorrentPotatoRequestGenerator.cs
Instead of searching for imdbid (which jackett may or may not have depending on the tracker) search for a word instead.
2017-01-06 15:26:16 -05:00
Leonardo Galli
427babf34e Update readme.md 2017-01-06 19:24:40 +01:00
278 changed files with 4315 additions and 2313 deletions

BIN
.DS_Store vendored

Binary file not shown.

5
.gitignore vendored
View File

@@ -130,6 +130,7 @@ output/*
#Packages
Radarr_*/
Radarr_*.zip
Radarr_*.gz
#OS X metadata files
._*
@@ -137,3 +138,7 @@ Radarr_*.zip
_start
_temp_*/**/*
#AppVeyor
/tools-cake/
/_artifacts/

BIN
7za.dll Normal file

Binary file not shown.

BIN
7za.exe Normal file

Binary file not shown.

BIN
7zxa.dll Normal file

Binary file not shown.

4
CLA.md
View File

@@ -1,6 +1,6 @@
# Sonarr Individual Contributor License Agreement #
# Radarr Individual Contributor License Agreement #
Thank you for your interest in contributing to Sonarr ("We" or "Us").
Thank you for your interest in contributing to Radarr ("We" or "Us").
This contributor agreement ("Agreement") documents the rights granted by contributors to Us. To make this document effective, please complete the form below. This is a legally binding document, so please read it carefully before agreeing to it. The Agreement may cover more than one software project managed by Us.
## 1. Definitions ##

View File

@@ -1,6 +1,6 @@
# How to Contribute #
We're always looking for people to help make Sonarr even better, there are a number of ways to contribute.
We're always looking for people to help make Radarr even better, there are a number of ways to contribute.
## Documentation ##
Setup guides, FAQ, the more information we have on the wiki the better.
@@ -15,7 +15,7 @@ Setup guides, FAQ, the more information we have on the wiki the better.
### Getting started ###
1. Fork Sonarr
1. Fork Radarr
2. Clone (develop branch) *you may need pull in submodules separately if you client doesn't clone them automatically (CurlSharp)*
3. Run `npm install`
4. Run `npm start` - Used to compile the UI components and copy them.
@@ -24,8 +24,8 @@ Setup guides, FAQ, the more information we have on the wiki the better.
5. Compile in Visual Studio
### Contributing Code ###
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Sonarr/Sonarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
- Rebase from Sonarr's develop branch, don't merge
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Radarr/Radarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
- Rebase from Radarr's develop branch, don't merge
- Make meaningful commits, or squash them
- Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements
- Reach out to us on the forums or on IRC if you have any questions

BIN
Logo/Thumbs.db Normal file

Binary file not shown.

45
appveyor.yml Normal file
View File

@@ -0,0 +1,45 @@
version: '0.2.0.{build}'
branches:
only:
- develop
assembly_info:
patch: true
file: 'src\NzbDrone.Common\Properties\SharedAssemblyInfo.cs'
assembly_version: '{version}'
assembly_file_version: '{version}'
assembly_informational_version: '{version}-rc1'
environment:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
install:
- git submodule update --init --recursive
build_script:
- ps: ./build-appveyor.ps1
test: off
# test:
# assemblies:
# - '_tests\*Test.dll'
# categories:
# except:
# - IntegrationTest
# - AutomationTest
artifacts:
- path: '_artifacts\*.zip'
- path: '_artifacts\*.tar.gz'
cache:
- '%USERPROFILE%\.nuget\packages'
- node_modules
only_commits:
files:
- src/
- osx/
- gulp/
- logo/

303
build-appveyor.cake Normal file
View File

@@ -0,0 +1,303 @@
#addin "Cake.Npm"
#addin "SharpZipLib"
#addin "Cake.Compression"
// Build variables
var outputFolder = "./_output";
var outputFolderMono = outputFolder + "_mono";
var outputFolderOsx = outputFolder + "_osx";
var outputFolderOsxApp = outputFolderOsx + "_app";
var testPackageFolder = "./_tests";
var testSearchPattern = "*.Test/bin/x86/Release";
var sourceFolder = "./src";
var solutionFile = sourceFolder + "/NzbDrone.sln";
var updateFolder = outputFolder + "/NzbDrone.Update";
var updateFolderMono = outputFolderMono + "/NzbDrone.Update";
// Artifact variables
var artifactsFolder = "./_artifacts";
var artifactsFolderWindows = artifactsFolder + "/windows";
var artifactsFolderLinux = artifactsFolder + "/linux";
var artifactsFolderOsx = artifactsFolder + "/osx";
var artifactsFolderOsxApp = artifactsFolder + "/osx-app";
// Utility methods
public void RemoveEmptyFolders(string startLocation) {
foreach (var directory in System.IO.Directory.GetDirectories(startLocation))
{
RemoveEmptyFolders(directory);
if (System.IO.Directory.GetFiles(directory).Length == 0 &&
System.IO.Directory.GetDirectories(directory).Length == 0)
{
DeleteDirectory(directory, false);
}
}
}
public void CleanFolder(string path, bool keepConfigFiles) {
DeleteFiles(path + "/**/*.transform");
if (!keepConfigFiles) {
DeleteFiles(path + "/**/*.dll.config");
}
DeleteFiles(path + "/**/FluentValidation.resources.dll");
DeleteFiles(path + "/**/App.config");
DeleteFiles(path + "/**/*.less");
DeleteFiles(path + "/**/*.vshost.exe");
DeleteFiles(path + "/**/*.dylib");
RemoveEmptyFolders(path);
}
public void CreateMdbs(string path) {
foreach (var file in System.IO.Directory.EnumerateFiles(path, "*.pdb", System.IO.SearchOption.AllDirectories)) {
var actualFile = file.Substring(0, file.Length - 4);
if (FileExists(actualFile + ".exe")) {
StartProcess("./tools/pdb2mdb/pdb2mdb.exe", new ProcessSettings()
.WithArguments(args => args.Append(actualFile + ".exe")));
}
if (FileExists(actualFile + ".dll")) {
StartProcess("./tools/pdb2mdb/pdb2mdb.exe", new ProcessSettings()
.WithArguments(args => args.Append(actualFile + ".dll")));
}
}
}
// Build Tasks
Task("Compile").Does(() => {
// Build
if (DirectoryExists(outputFolder)) {
DeleteDirectory(outputFolder, true);
}
MSBuild(solutionFile, config =>
config.UseToolVersion(MSBuildToolVersion.VS2015)
.WithTarget("Clean")
.SetVerbosity(Verbosity.Minimal));
NuGetRestore(solutionFile);
MSBuild(solutionFile, config =>
config.UseToolVersion(MSBuildToolVersion.VS2015)
.SetPlatformTarget(PlatformTarget.x86)
.SetConfiguration("Release")
.WithProperty("AllowedReferenceRelatedFileExtensions", new string[] { ".pdb" })
.WithTarget("Build")
.SetVerbosity(Verbosity.Minimal));
CleanFolder(outputFolder, false);
// Add JsonNet
DeleteFiles(outputFolder + "/Newtonsoft.Json.*");
CopyFiles(sourceFolder + "/packages/Newtonsoft.Json.*/lib/net35/*.dll", outputFolder);
CopyFiles(sourceFolder + "/packages/Newtonsoft.Json.*/lib/net35/*.dll", updateFolder);
// Remove Mono stuff
DeleteFile(outputFolder + "/Mono.Posix.dll");
});
Task("Gulp").Does(() => {
Npm
.WithLogLevel(NpmLogLevel.Silent)
.FromPath(".")
.Install()
.RunScript("build");
});
Task("PackageMono").Does(() => {
// Start mono package
if (DirectoryExists(outputFolderMono)) {
DeleteDirectory(outputFolderMono, true);
}
CopyDirectory(outputFolder, outputFolderMono);
// Create MDBs
CreateMdbs(outputFolderMono);
// Remove PDBs
DeleteFiles(outputFolderMono + "/**/*.pdb");
// Remove service helpers
DeleteFiles(outputFolderMono + "/ServiceUninstall.*");
DeleteFiles(outputFolderMono + "/ServiceInstall.*");
// Remove native windows binaries
DeleteFiles(outputFolderMono + "/sqlite3.*");
DeleteFiles(outputFolderMono + "/MediaInfo.*");
// Adding NzbDrone.Core.dll.config (for dllmap)
CopyFile(sourceFolder + "/NzbDrone.Core/NzbDrone.Core.dll.config", outputFolderMono + "/NzbDrone.Core.dll.config");
// Adding CurlSharp.dll.config (for dllmap)
CopyFile(sourceFolder + "/NzbDrone.Common/CurlSharp.dll.config", outputFolderMono + "/CurlSharp.dll.config");
// Renaming Radarr.Console.exe to Radarr.exe
DeleteFiles(outputFolderMono + "/Radarr.exe*");
MoveFile(outputFolderMono + "/Radarr.Console.exe", outputFolderMono + "/Radarr.exe");
MoveFile(outputFolderMono + "/Radarr.Console.exe.config", outputFolderMono + "/Radarr.exe.config");
MoveFile(outputFolderMono + "/Radarr.Console.exe.mdb", outputFolderMono + "/Radarr.exe.mdb");
// Remove NzbDrone.Windows.*
DeleteFiles(outputFolderMono + "/NzbDrone.Windows.*");
// Adding NzbDrone.Mono to updatePackage
CopyFiles(outputFolderMono + "/NzbDrone.Mono.*", updateFolderMono);
});
Task("PackageOsx").Does(() => {
// Start osx package
if (DirectoryExists(outputFolderOsx)) {
DeleteDirectory(outputFolderOsx, true);
}
CopyDirectory(outputFolderMono, outputFolderOsx);
// Adding sqlite dylibs
CopyFiles(sourceFolder + "/Libraries/Sqlite/*.dylib", outputFolderOsx);
// Adding MediaInfo dylib
CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx);
// Adding Startup script
CopyFile("./osx/Sonarr", outputFolderOsx + "/Sonarr");
});
Task("PackageOsxApp").Does(() => {
// Start osx app package
if (DirectoryExists(outputFolderOsxApp)) {
DeleteDirectory(outputFolderOsxApp, true);
}
CreateDirectory(outputFolderOsxApp);
// Copy osx package files
CopyDirectory("./osx/Radarr.app", outputFolderOsxApp + "/Radarr.app");
CopyDirectory(outputFolderOsx, outputFolderOsxApp + "/Radarr.app/Contents/MacOS");
});
Task("PackageTests").Does(() => {
// Start tests package
if (DirectoryExists(testPackageFolder)) {
DeleteDirectory(testPackageFolder, true);
}
CreateDirectory(testPackageFolder);
// Copy tests
CopyFiles(sourceFolder + "/" + testSearchPattern + "/*", testPackageFolder);
foreach (var directory in System.IO.Directory.GetDirectories(sourceFolder, "*.Test")) {
var releaseDirectory = directory + "/bin/x86/Release";
if (DirectoryExists(releaseDirectory)) {
foreach (var releaseSubDirectory in System.IO.Directory.GetDirectories(releaseDirectory)) {
Information(System.IO.Path.GetDirectoryName(releaseSubDirectory));
CopyDirectory(releaseSubDirectory, testPackageFolder + "/" + System.IO.Path.GetFileName(releaseSubDirectory));
}
}
}
// Install NUnit.ConsoleRunner
NuGetInstall("NUnit.ConsoleRunner", new NuGetInstallSettings {
Version = "3.2.0",
OutputDirectory = testPackageFolder
});
// Copy dlls
CopyFiles(outputFolder + "/*.dll", testPackageFolder);
// Copy scripts
CopyFiles("./*.sh", testPackageFolder);
// Create MDBs for tests
CreateMdbs(testPackageFolder);
// Remove config
DeleteFiles(testPackageFolder + "/*.log.config");
// Clean
CleanFolder(testPackageFolder, true);
// Adding NzbDrone.Core.dll.config (for dllmap)
CopyFile(sourceFolder + "/NzbDrone.Core/NzbDrone.Core.dll.config", testPackageFolder + "/NzbDrone.Core.dll.config");
// Adding CurlSharp.dll.config (for dllmap)
CopyFile(sourceFolder + "/NzbDrone.Common/CurlSharp.dll.config", testPackageFolder + "/CurlSharp.dll.config");
// Adding CurlSharp libraries
CopyFiles(sourceFolder + "/ExternalModules/CurlSharp/libs/i386/*", testPackageFolder);
});
Task("CleanupWindowsPackage").Does(() => {
// Remove mono
DeleteFiles(outputFolder + "/NzbDrone.Mono.*");
// Adding NzbDrone.Windows to updatePackage
CopyFiles(outputFolder + "/NzbDrone.Windows.*", updateFolder);
});
Task("Build")
.IsDependentOn("Compile")
.IsDependentOn("Gulp")
.IsDependentOn("PackageMono")
.IsDependentOn("PackageOsx")
.IsDependentOn("PackageOsxApp")
.IsDependentOn("PackageTests")
.IsDependentOn("CleanupWindowsPackage");
// Build Artifacts
Task("CleanArtifacts").Does(() => {
if (DirectoryExists(artifactsFolder)) {
DeleteDirectory(artifactsFolder, true);
}
CreateDirectory(artifactsFolder);
});
Task("ArtifactsWindows").Does(() => {
CopyDirectory(outputFolder, artifactsFolderWindows + "/Radarr");
});
Task("ArtifactsLinux").Does(() => {
CopyDirectory(outputFolderMono, artifactsFolderLinux + "/Radarr");
});
Task("ArtifactsOsx").Does(() => {
CopyDirectory(outputFolderOsx, artifactsFolderOsx + "/Radarr");
});
Task("ArtifactsOsxApp").Does(() => {
CopyDirectory(outputFolderOsxApp, artifactsFolderOsxApp);
});
Task("CompressArtifacts").Does(() => {
var prefix = "";
if (AppVeyor.IsRunningOnAppVeyor) {
prefix += AppVeyor.Environment.Repository.Branch + ".";
prefix += AppVeyor.Environment.Build.Version + ".";
}
Zip(artifactsFolderWindows, artifactsFolder + "/Radarr." + prefix + "windows.zip");
GZipCompress(artifactsFolderLinux, artifactsFolder + "/Radarr." + prefix + "linux.tar.gz");
GZipCompress(artifactsFolderOsx, artifactsFolder + "/Radarr." + prefix + "osx.tar.gz");
Zip(artifactsFolderOsxApp, artifactsFolder + "/Radarr." + prefix + "osx-app.zip");
});
Task("Artifacts")
.IsDependentOn("CleanArtifacts")
.IsDependentOn("ArtifactsWindows")
.IsDependentOn("ArtifactsLinux")
.IsDependentOn("ArtifactsOsx")
.IsDependentOn("ArtifactsOsxApp")
.IsDependentOn("CompressArtifacts");
// Run
RunTarget("Build");
RunTarget("Artifacts");

184
build-appveyor.ps1 Normal file
View File

@@ -0,0 +1,184 @@
##########################################################################
# This is the Cake bootstrapper script for PowerShell.
# This file was downloaded from https://github.com/cake-build/resources
# Feel free to change this file to fit your needs.
##########################################################################
<#
.SYNOPSIS
This is a Powershell script to bootstrap a Cake build.
.DESCRIPTION
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
and execute your Cake build script with the parameters you provide.
.PARAMETER Script
The build script to execute.
.PARAMETER Target
The build script target to run.
.PARAMETER Configuration
The build configuration to use.
.PARAMETER Verbosity
Specifies the amount of information to be displayed.
.PARAMETER Experimental
Tells Cake to use the latest Roslyn release.
.PARAMETER WhatIf
Performs a dry run of the build script.
No tasks will be executed.
.PARAMETER Mono
Tells Cake to use the Mono scripting engine.
.PARAMETER SkipToolPackageRestore
Skips restoring of packages.
.PARAMETER ScriptArgs
Remaining arguments are added here.
.LINK
http://cakebuild.net
#>
[CmdletBinding()]
Param(
[string]$Script = "build-appveyor.cake",
[string]$Target = "Default",
[ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
[string]$Verbosity = "Verbose",
[switch]$Experimental,
[Alias("DryRun","Noop")]
[switch]$WhatIf,
[switch]$Mono,
[switch]$SkipToolPackageRestore,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$ScriptArgs
)
[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
function MD5HashFile([string] $filePath)
{
if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
{
return $null
}
[System.IO.Stream] $file = $null;
[System.Security.Cryptography.MD5] $md5 = $null;
try
{
$md5 = [System.Security.Cryptography.MD5]::Create()
$file = [System.IO.File]::OpenRead($filePath)
return [System.BitConverter]::ToString($md5.ComputeHash($file))
}
finally
{
if ($file -ne $null)
{
$file.Dispose()
}
}
}
Write-Host "Preparing to run build script..."
if(!$PSScriptRoot){
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
}
$TOOLS_DIR = Join-Path $PSScriptRoot "tools-cake"
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
# Should we use mono?
$UseMono = "";
if($Mono.IsPresent) {
Write-Verbose -Message "Using the Mono based scripting engine."
$UseMono = "-mono"
}
# Should we use the new Roslyn?
$UseExperimental = "";
if($Experimental.IsPresent -and !($Mono.IsPresent)) {
Write-Verbose -Message "Using experimental version of Roslyn."
$UseExperimental = "-experimental"
}
# Is this a dry run?
$UseDryRun = "";
if($WhatIf.IsPresent) {
$UseDryRun = "-dryrun"
}
# Make sure tools folder exists
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
Write-Verbose -Message "Creating tools directory..."
New-Item -Path $TOOLS_DIR -Type directory | out-null
}
# Make sure that packages.config exist.
if (!(Test-Path $PACKAGES_CONFIG)) {
Write-Verbose -Message "Downloading packages.config..."
try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
Throw "Could not download packages.config."
}
}
# Try find NuGet.exe in path if not exists
if (!(Test-Path $NUGET_EXE)) {
Write-Verbose -Message "Trying to find nuget.exe in PATH..."
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
$NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
}
}
# Try download NuGet.exe if not exists
if (!(Test-Path $NUGET_EXE)) {
Write-Verbose -Message "Downloading NuGet.exe..."
try {
(New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
} catch {
Throw "Could not download NuGet.exe."
}
}
# Save nuget.exe path to environment to be available to child processed
$ENV:NUGET_EXE = $NUGET_EXE
# Restore tools from NuGet?
if(-Not $SkipToolPackageRestore.IsPresent) {
Push-Location
Set-Location $TOOLS_DIR
# Check for changes in packages.config and remove installed tools if true.
[string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
Write-Verbose -Message "Missing or changed package.config hash..."
Remove-Item * -Recurse -Exclude packages.config,nuget.exe
}
Write-Verbose -Message "Restoring tools from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occured while restoring NuGet tools."
}
else
{
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Make sure that Cake has been installed.
if (!(Test-Path $CAKE_EXE)) {
Throw "Could not find Cake.exe at $CAKE_EXE"
}
# Start Cake
Write-Host "Running build script..."
Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
exit $LASTEXITCODE

View File

@@ -4,6 +4,18 @@ if [ $# -eq 0 ]; then
fi
fi
# Use mono or .net depending on OS
case "$(uname -s)" in
CYGWIN*|MINGW32*|MINGW64*|MSYS*)
# on windows, use dotnet
runtime="dotnet"
;;
*)
# otherwise use mono
runtime="mono"
;;
esac
if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
VERSION="`date +%H:%M:%S`"
YEAR="`date +%Y`"
@@ -26,10 +38,16 @@ cp -r $outputFolder/ Radarr_Windows_$VERSION
cp -r $outputFolderMono/ Radarr_Mono_$VERSION
cp -r $outputFolderOsxApp/ Radarr_OSX_$VERSION
zip -r Radarr_Windows_$VERSION.zip Radarr_Windows_$VERSION >& /dev/null
zip -r Radarr_Mono_$VERSION.zip Radarr_Mono_$VERSION >& /dev/null
zip -r Radarr_OSX_$VERSION.zip Radarr_OSX_$VERSION >& /dev/null
if [ $runtime = "dotnet" ] ; then
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
./7za.exe a -ttar -so Radarr_Mono_$VERSION.tar ./Radarr_Mono_$VERSION/* | ./7za.exe a -si Radarr_Mono_$VERSION.tar.gz
./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz
./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz
else
zip -r Radarr_Windows_$VERSION.zip Radarr_Windows_$VERSION/* >& /dev/null
zip -r Radarr_Mono_$VERSION.zip Radarr_Mono_$VERSION/* >& /dev/null #TODO update for tar.gz
zip -r Radarr_OSX_$VERSION_App.zip Radarr_OSX_$VERSION/* >& /dev/null
fi
ftp -n ftp.leonardogalli.ch << END_SCRIPT
passive
quote USER $FTP_USER

View File

@@ -1,4 +1,9 @@
# Radarr [![Build Status](https://travis-ci.org/galli-leo/Radarr.svg?branch=develop)](https://travis-ci.org/galli-leo/Radarr)#
# 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.
@@ -6,20 +11,26 @@ This fork of Sonarr aims to turn it into something like Couchpotato.
* Adding new movies
* Manually searching for releases of movies.
* Automatically searching for releases.
* Rarbg.to indexer (Other indexers are coming, I just need to find the right categories)
* QBittorrent download client (Other clients are coming)
* 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.
* Fixing how movies are parsed.
* Fixing movie import.
* Importing of Sonarr config.
* New TorrentPotato Indexer.
## 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)
@@ -28,15 +39,11 @@ For more up to date versions (but also sometimes broken), daily builds can be fo
## Major Features Include: ##
* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
* Automatically detects new episodes
* Can scan your existing library and download any missing episodes
* Can watch for better quality of the episodes you already have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
* 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
* Fully configurable episode renaming
* Full integration with SABNzbd and NzbGet
* Full integration with XBMC, Plex (notification, library update, metadata)
* Full support for specials and multi-episode releases
* 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: ##

BIN
src/.DS_Store vendored

Binary file not shown.

View File

@@ -21,4 +21,3 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("260b2ff9-d3b7-4d8a-b720-a12c93d045e5")]
[assembly: AssemblyVersion("0.1.0.*")]

View File

@@ -27,6 +27,7 @@ namespace NzbDrone.Api.Calendar
Get["/NzbDrone.ics"] = options => GetCalendarFeed();
Get["/Sonarr.ics"] = options => GetCalendarFeed();
Get["/Radarr.ics"] = options => GetCalendarFeed();
}
private Response GetCalendarFeed()

View File

@@ -34,11 +34,13 @@ namespace NzbDrone.Api.Config
Get["/samples"] = x => GetExamples(this.Bind<NamingConfigResource>());
SharedValidator.RuleFor(c => c.MultiEpisodeStyle).InclusiveBetween(0, 5);
SharedValidator.RuleFor(c => c.StandardEpisodeFormat).ValidEpisodeFormat();
/*SharedValidator.RuleFor(c => c.StandardEpisodeFormat).ValidEpisodeFormat();
SharedValidator.RuleFor(c => c.DailyEpisodeFormat).ValidDailyEpisodeFormat();
SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat();
SharedValidator.RuleFor(c => c.SeriesFolderFormat).ValidSeriesFolderFormat();
SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat();
SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat();*/
SharedValidator.RuleFor(c => c.StandardMovieFormat).ValidMovieFormat();
SharedValidator.RuleFor(c => c.MovieFolderFormat).ValidMovieFolderFormat();
}
private void UpdateNamingConfig(NamingConfigResource resource)
@@ -54,7 +56,13 @@ namespace NzbDrone.Api.Config
var nameSpec = _namingConfigService.GetConfig();
var resource = nameSpec.ToResource();
if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace())
//if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace())
//{
// var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
// basicConfig.AddToResource(resource);
//}
if (resource.StandardMovieFormat.IsNotNullOrWhiteSpace())
{
var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
basicConfig.AddToResource(resource);
@@ -73,39 +81,50 @@ namespace NzbDrone.Api.Config
var nameSpec = config.ToModel();
var sampleResource = new NamingSampleResource();
var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec);
var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec);
var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec);
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
//var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec);
//var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec);
//var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec);
//var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
//var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
? "Invalid format"
: singleEpisodeSampleResult.FileName;
var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
sampleResource.MultiEpisodeExample = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult) != null
? "Invalid format"
: multiEpisodeSampleResult.FileName;
//sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
// ? "Invalid format"
// : singleEpisodeSampleResult.FileName;
sampleResource.DailyEpisodeExample = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult) != null
? "Invalid format"
: dailyEpisodeSampleResult.FileName;
//sampleResource.MultiEpisodeExample = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult) != null
// ? "Invalid format"
// : multiEpisodeSampleResult.FileName;
sampleResource.AnimeEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult) != null
? "Invalid format"
: animeEpisodeSampleResult.FileName;
//sampleResource.DailyEpisodeExample = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult) != null
// ? "Invalid format"
// : dailyEpisodeSampleResult.FileName;
sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
? "Invalid format"
: animeMultiEpisodeSampleResult.FileName;
//sampleResource.AnimeEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult) != null
// ? "Invalid format"
// : animeEpisodeSampleResult.FileName;
sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
//sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
// ? "Invalid format"
// : animeMultiEpisodeSampleResult.FileName;
sampleResource.MovieExample = nameSpec.StandardMovieFormat.IsNullOrWhiteSpace()
? "Invalid Format"
: movieSampleResult.FileName;
//sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
// ? "Invalid format"
// : _filenameSampleService.GetSeriesFolderSample(nameSpec);
//sampleResource.SeasonFolderExample = nameSpec.SeasonFolderFormat.IsNullOrWhiteSpace()
// ? "Invalid format"
// : _filenameSampleService.GetSeasonFolderSample(nameSpec);
sampleResource.MovieFolderExample = nameSpec.MovieFolderFormat.IsNullOrWhiteSpace()
? "Invalid format"
: _filenameSampleService.GetSeriesFolderSample(nameSpec);
sampleResource.SeasonFolderExample = nameSpec.SeasonFolderFormat.IsNullOrWhiteSpace()
? "Invalid format"
: _filenameSampleService.GetSeasonFolderSample(nameSpec);
: _filenameSampleService.GetMovieFolderSample(nameSpec);
return sampleResource.AsResponse();
}
@@ -118,19 +137,25 @@ namespace NzbDrone.Api.Config
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult);
var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult);
var dailyEpisodeValidationResult = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult);
var animeEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult);
var animeMultiEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult);
//var standardMovieValidationResult = _filenameValidationService.ValidateMovieFilename(movieSampleResult); For now, let's hope the user is not stupid enough :/
var validationFailures = new List<ValidationFailure>();
validationFailures.AddIfNotNull(singleEpisodeValidationResult);
validationFailures.AddIfNotNull(multiEpisodeValidationResult);
validationFailures.AddIfNotNull(dailyEpisodeValidationResult);
validationFailures.AddIfNotNull(animeEpisodeValidationResult);
validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
//validationFailures.AddIfNotNull(singleEpisodeValidationResult);
//validationFailures.AddIfNotNull(multiEpisodeValidationResult);
//validationFailures.AddIfNotNull(dailyEpisodeValidationResult);
//validationFailures.AddIfNotNull(animeEpisodeValidationResult);
//validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
//validationFailures.AddIfNotNull(standardMovieValidationResult);
if (validationFailures.Any())
{

View File

@@ -7,6 +7,8 @@ namespace NzbDrone.Api.Config
{
public bool RenameEpisodes { get; set; }
public bool ReplaceIllegalCharacters { get; set; }
public string StandardMovieFormat { get; set; }
public string MovieFolderFormat { get; set; }
public int MultiEpisodeStyle { get; set; }
public string StandardEpisodeFormat { get; set; }
public string DailyEpisodeFormat { get; set; }
@@ -36,7 +38,9 @@ namespace NzbDrone.Api.Config
DailyEpisodeFormat = model.DailyEpisodeFormat,
AnimeEpisodeFormat = model.AnimeEpisodeFormat,
SeriesFolderFormat = model.SeriesFolderFormat,
SeasonFolderFormat = model.SeasonFolderFormat
SeasonFolderFormat = model.SeasonFolderFormat,
StandardMovieFormat = model.StandardMovieFormat,
MovieFolderFormat = model.MovieFolderFormat
//IncludeSeriesTitle
//IncludeEpisodeTitle
//IncludeQuality
@@ -64,12 +68,14 @@ namespace NzbDrone.Api.Config
RenameEpisodes = resource.RenameEpisodes,
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
MultiEpisodeStyle = resource.MultiEpisodeStyle,
StandardEpisodeFormat = resource.StandardEpisodeFormat,
DailyEpisodeFormat = resource.DailyEpisodeFormat,
AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
SeriesFolderFormat = resource.SeriesFolderFormat,
SeasonFolderFormat = resource.SeasonFolderFormat
//MultiEpisodeStyle = resource.MultiEpisodeStyle,
//StandardEpisodeFormat = resource.StandardEpisodeFormat,
//DailyEpisodeFormat = resource.DailyEpisodeFormat,
//AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
//SeriesFolderFormat = resource.SeriesFolderFormat,
//SeasonFolderFormat = resource.SeasonFolderFormat,
StandardMovieFormat = resource.StandardMovieFormat,
MovieFolderFormat = resource.MovieFolderFormat
};
}
}

View File

@@ -9,5 +9,8 @@
public string AnimeMultiEpisodeExample { get; set; }
public string SeriesFolderExample { get; set; }
public string SeasonFolderExample { get; set; }
public string MovieExample { get; set; }
public string MovieFolderExample { get; set; }
}
}

View File

@@ -25,7 +25,7 @@ namespace NzbDrone.Api.Frontend.Mappers
public override bool CanHandle(string resourceUrl)
{
return resourceUrl.StartsWith("/backup/") && resourceUrl.ContainsIgnoreCase("nzbdrone_backup_") && resourceUrl.EndsWith(".zip");
return resourceUrl.StartsWith("/backup/") && resourceUrl.ContainsIgnoreCase("radarr_backup_") && resourceUrl.EndsWith(".zip");
}
}
}

View File

@@ -97,7 +97,7 @@ namespace NzbDrone.Api.Indexers
{
Guid = releaseInfo.Guid,
Quality = parsedMovieInfo.Quality,
//QualityWeight
QualityWeight = parsedMovieInfo.Quality.Quality.Id, //Id kinda hacky for wheight, but what you gonna do? TODO: Fix this shit!
Age = releaseInfo.Age,
AgeHours = releaseInfo.AgeHours,
AgeMinutes = releaseInfo.AgeMinutes,
@@ -107,8 +107,8 @@ namespace NzbDrone.Api.Indexers
ReleaseGroup = parsedMovieInfo.ReleaseGroup,
ReleaseHash = parsedMovieInfo.ReleaseHash,
Title = releaseInfo.Title,
FullSeason = parsedMovieInfo.FullSeason,
SeasonNumber = parsedMovieInfo.SeasonNumber,
//FullSeason = parsedMovieInfo.FullSeason,
//SeasonNumber = parsedMovieInfo.SeasonNumber,
Language = parsedMovieInfo.Language,
AirDate = "",
SeriesTitle = parsedMovieInfo.MovieTitle,
@@ -138,7 +138,7 @@ namespace NzbDrone.Api.Indexers
IsDaily = false,
IsAbsoluteNumbering = false,
IsPossibleSpecialEpisode = false,
Special = parsedMovieInfo.Special,
//Special = parsedMovieInfo.Special,
};
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Linq;
using Nancy;
using NzbDrone.Api.Extensions;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Movie
{
public class MovieEditorModule : NzbDroneApiModule
{
private readonly IMovieService _movieService;
public MovieEditorModule(IMovieService movieService)
: base("/movie/editor")
{
_movieService = movieService;
Put["/"] = Movie => SaveAll();
}
private Response SaveAll()
{
var resources = Request.Body.FromJson<List<MovieResource>>();
var Movie = resources.Select(MovieResource => MovieResource.ToModel(_movieService.GetMovie(MovieResource.Id))).ToList();
return _movieService.UpdateMovie(Movie)
.ToResource()
.AsResponse(HttpStatusCode.Accepted);
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Api.Movies
{
class MovieModule
{
}
}

View File

@@ -0,0 +1,35 @@
using NzbDrone.Api.REST;
using NzbDrone.Core.MediaFiles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Api.Movies
{
public class RenameMovieModule : NzbDroneRestModule<RenameMovieResource>
{
private readonly IRenameMovieFileService _renameMovieFileService;
public RenameMovieModule(IRenameMovieFileService renameMovieFileService)
: base("rename")
{
_renameMovieFileService = renameMovieFileService;
GetResourceAll = GetMovies; //TODO: GetResourceSingle?
}
private List<RenameMovieResource> GetMovies()
{
if(!Request.Query.MovieId.HasValue)
{
throw new BadRequestException("movieId is missing");
}
var movieId = (int)Request.Query.MovieId;
return _renameMovieFileService.GetRenamePreviews(movieId).ToResource();
}
}
}

View File

@@ -0,0 +1,35 @@
using NzbDrone.Api.REST;
using System.Collections.Generic;
using System.Linq;
namespace NzbDrone.Api.Movies
{
public class RenameMovieResource : RestResource
{
public int MovieId { get; set; }
public int MovieFileId { get; set; }
public string ExistingPath { get; set; }
public string NewPath { get; set; }
}
public static class RenameMovieResourceMapper
{
public static RenameMovieResource ToResource(this Core.MediaFiles.RenameMovieFilePreview model)
{
if (model == null) return null;
return new RenameMovieResource
{
MovieId = model.MovieId,
MovieFileId = model.MovieFileId,
ExistingPath = model.ExistingPath,
NewPath = model.NewPath
};
}
public static List<RenameMovieResource> ToResource(this IEnumerable<Core.MediaFiles.RenameMovieFilePreview> models)
{
return models.Select(ToResource).ToList();
}
}
}

View File

@@ -116,6 +116,10 @@
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
<Compile Include="Indexers\ReleaseModuleBase.cs" />
<Compile Include="Indexers\ReleasePushModule.cs" />
<Compile Include="Movies\MovieModule.cs" />
<Compile Include="Movies\RenameMovieModule.cs" />
<Compile Include="Movies\RenameMovieResource.cs" />
<Compile Include="Movies\MovieEditorModule.cs" />
<Compile Include="Parse\ParseModule.cs" />
<Compile Include="Parse\ParseResource.cs" />
<Compile Include="ManualImport\ManualImportModule.cs" />
@@ -228,6 +232,7 @@
<Compile Include="RootFolders\RootFolderResource.cs" />
<Compile Include="SeasonPass\SeasonPassResource.cs" />
<Compile Include="Series\AlternateTitleResource.cs" />
<Compile Include="Series\MovieFileResource.cs" />
<Compile Include="Series\SeasonResource.cs" />
<Compile Include="SeasonPass\SeasonPassModule.cs" />
<Compile Include="Series\SeriesEditorModule.cs" />

View File

@@ -6,6 +6,5 @@ using System.Runtime.InteropServices;
[assembly: Guid("4c0922d7-979e-4ff7-b44b-b8ac2100eeb5")]
[assembly: AssemblyVersion("0.1.0.*")]
[assembly: InternalsVisibleTo("NzbDrone.Core")]

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Api.REST;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Qualities;
using NzbDrone.Api.Series;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Api.Movie
{
public class MovieFileResource : RestResource
{
public MovieFileResource()
{
}
//Todo: Sorters should be done completely on the client
//Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing?
//Todo: We should get the entire Profile instead of ID and Name separately
public int MovieId { get; set; }
public string RelativePath { get; set; }
public string Path { get; set; }
public long Size { get; set; }
public DateTime DateAdded { get; set; }
public string SceneName { get; set; }
public string ReleaseGroup { get; set; }
public QualityModel Quality { get; set; }
public MovieResource Movie { get; set; }
//TODO: Add series statistics as a property of the series (instead of individual properties)
}
public static class MovieFileResourceMapper
{
public static MovieFileResource ToResource(this MovieFile model)
{
if (model == null) return null;
MovieResource movie = null;
if (model.Movie != null)
{
model.Movie.LazyLoad();
if (model.Movie.Value != null)
{
//movie = model.Movie.Value.ToResource();
}
}
return new MovieFileResource
{
Id = model.Id,
RelativePath = model.RelativePath,
Path = model.Path,
Size = model.Size,
DateAdded = model.DateAdded,
ReleaseGroup = model.ReleaseGroup,
Quality = model.Quality,
Movie = movie,
};
}
public static MovieFile ToModel(this MovieFileResource resource)
{
if (resource == null) return null;
return new MovieFile
{
};
}
public static List<MovieFileResource> ToResource(this IEnumerable<MovieFile> movies)
{
return movies.Select(ToResource).ToList();
}
}
}

View File

@@ -18,7 +18,7 @@ namespace NzbDrone.Api.Movie
//Todo: Sorters should be done completely on the client
//Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing?
//Todo: We should get the entire Profile instead of ID and Name separately
//View Only
public string Title { get; set; }
public List<AlternateTitleResource> AlternateTitles { get; set; }
@@ -27,11 +27,13 @@ namespace NzbDrone.Api.Movie
public MovieStatusType Status { get; set; }
public string Overview { get; set; }
public DateTime? InCinemas { get; set; }
public DateTime? PhysicalRelease { get; set; }
public List<MediaCover> Images { get; set; }
public string Website { get; set; }
public bool Downloaded { get; set; }
public string RemotePoster { get; set; }
public int Year { get; set; }
public bool HasFile { get; set; }
//View & Edit
public string Path { get; set; }
@@ -53,6 +55,7 @@ namespace NzbDrone.Api.Movie
public AddMovieOptions AddOptions { get; set; }
public Ratings Ratings { get; set; }
public List<string> AlternativeTitles { get; set; }
public MovieFileResource MovieFile { get; set; }
//TODO: Add series statistics as a property of the series (instead of individual properties)
@@ -79,6 +82,24 @@ namespace NzbDrone.Api.Movie
{
if (model == null) return null;
long size = 0;
bool downloaded = false;
MovieFileResource movieFile = null;
if(model.MovieFile != null)
{
model.MovieFile.LazyLoad();
}
if (model.MovieFile != null && model.MovieFile.IsLoaded && model.MovieFile.Value != null)
{
size = model.MovieFile.Value.Size;
downloaded = true;
movieFile = model.MovieFile.Value.ToResource();
}
return new MovieResource
{
Id = model.Id,
@@ -87,6 +108,9 @@ namespace NzbDrone.Api.Movie
//AlternateTitles
SortTitle = model.SortTitle,
InCinemas = model.InCinemas,
PhysicalRelease = model.PhysicalRelease,
HasFile = model.HasFile,
Downloaded = downloaded,
//TotalEpisodeCount
//EpisodeCount
//EpisodeFileCount
@@ -104,6 +128,8 @@ namespace NzbDrone.Api.Movie
Monitored = model.Monitored,
SizeOnDisk = size,
Runtime = model.Runtime,
LastInfoSync = model.LastInfoSync,
CleanTitle = model.CleanTitle,
@@ -117,7 +143,8 @@ namespace NzbDrone.Api.Movie
Added = model.Added,
AddOptions = model.AddOptions,
AlternativeTitles = model.AlternativeTitles,
Ratings = model.Ratings
Ratings = model.Ratings,
MovieFile = movieFile
};
}
@@ -134,6 +161,7 @@ namespace NzbDrone.Api.Movie
//AlternateTitles
SortTitle = resource.SortTitle,
InCinemas = resource.InCinemas,
PhysicalRelease = resource.PhysicalRelease,
//TotalEpisodeCount
//EpisodeCount
//EpisodeFileCount

View File

@@ -21,4 +21,3 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b47d34ef-05e8-4826-8a57-9dd05106c964")]
[assembly: AssemblyVersion("0.1.0.*")]

View File

@@ -20,5 +20,3 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6b8945f5-f5b5-4729-865d-f958fbd673d9")]
[assembly: AssemblyVersion("0.1.0.*")]

View File

@@ -14,7 +14,7 @@ namespace NzbDrone.Common.Cloud
{
public SonarrCloudRequestBuilder()
{
Services = new HttpRequestBuilder("http://services.sonarr.tv/v1/")
Services = new HttpRequestBuilder("http://radarr.aeonlucid.com/v1/")
.CreateFactory();
SkyHookTvdb = new HttpRequestBuilder("http://skyhook.sonarr.tv/v1/tvdb/{route}/{language}/")
@@ -26,12 +26,11 @@ namespace NzbDrone.Common.Cloud
.CreateFactory();
TMDBSingle = new HttpRequestBuilder("https://api.themoviedb.org/3/{route}")
.AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
.CreateFactory();
.AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
.CreateFactory();
}
public IHttpRequestBuilderFactory Services { get; private set; }
public IHttpRequestBuilderFactory SkyHookTvdb { get; private set; }
public IHttpRequestBuilderFactory TMDB { get; private set; }
public IHttpRequestBuilderFactory TMDBSingle { get; private set; }

View File

@@ -23,7 +23,7 @@ namespace NzbDrone.Common
Console.WriteLine(" Commands:");
Console.WriteLine(" /{0} Install the application as a Windows Service ({1}).", StartupContext.INSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
Console.WriteLine(" /{0} Uninstall already installed Windows Service ({1}).", StartupContext.UNINSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
Console.WriteLine(" /{0} Don't open Sonarr in a browser", StartupContext.NO_BROWSER);
Console.WriteLine(" /{0} Don't open Radarr in a browser", StartupContext.NO_BROWSER);
Console.WriteLine(" <No Arguments> Run application in console mode.");
}

View File

@@ -16,10 +16,10 @@ namespace NzbDrone.Common.Extensions
private const string UPDATE_CLIENT_EXE = "Radarr.Update.exe";
private const string BACKUP_FOLDER = "Backups";
private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "nzbdrone_update" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "NzbDrone" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_BACKUP_FOLDER_NAME = "nzbdrone_backup" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_BACKUP_APPDATA_FOLDER_NAME = "nzbdrone_appdata_backup" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "radarr_update" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "Radarr" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_BACKUP_FOLDER_NAME = "radarr_backup" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_BACKUP_APPDATA_FOLDER_NAME = "radarr_appdata_backup" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_CLIENT_FOLDER_NAME = "NzbDrone.Update" + Path.DirectorySeparatorChar;
private static readonly string UPDATE_LOG_FOLDER_NAME = "UpdateLogs" + Path.DirectorySeparatorChar;

View File

@@ -9,12 +9,12 @@ namespace NzbDrone.Common.Http
static UserAgentBuilder()
{
UserAgent = string.Format("Sonarr/{0} ({1} {2})",
UserAgent = string.Format("Radarr/{0} ({1} {2})",
BuildInfo.Version,
OsInfo.Os, OsInfo.Version.ToString(2));
UserAgentSimplified = string.Format("Sonarr/{0}",
UserAgentSimplified = string.Format("Radarr/{0}",
BuildInfo.Version.ToString(2));
}
}
}
}

View File

@@ -103,9 +103,9 @@ namespace NzbDrone.Common.Instrumentation
private static void RegisterAppFile(IAppFolderInfo appFolderInfo)
{
RegisterAppFile(appFolderInfo, "appFileInfo", "sonarr.txt", 5, LogLevel.Info);
RegisterAppFile(appFolderInfo, "appFileDebug", "sonarr.debug.txt", 50, LogLevel.Off);
RegisterAppFile(appFolderInfo, "appFileTrace", "sonarr.trace.txt", 50, LogLevel.Off);
RegisterAppFile(appFolderInfo, "appFileInfo", "radarr.txt", 5, LogLevel.Info);
RegisterAppFile(appFolderInfo, "appFileDebug", "radarr.debug.txt", 50, LogLevel.Off);
RegisterAppFile(appFolderInfo, "appFileTrace", "radarr.trace.txt", 50, LogLevel.Off);
}
private static LoggingRule RegisterAppFile(IAppFolderInfo appFolderInfo, string name, string fileName, int maxArchiveFiles, LogLevel minLogLevel)

View File

@@ -9,4 +9,3 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b6eaa144-e13b-42e5-a738-c60d89c0f728")]
[assembly: AssemblyVersion("0.1.0.*")]

View File

@@ -2,8 +2,9 @@
using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sonarr.tv")]
[assembly: AssemblyCompany("radarr.tv")]
[assembly: AssemblyProduct("NzbDrone")]
[assembly: AssemblyVersion("0.1.0.*")]
[assembly: AssemblyCopyright("GNU General Public v3")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@@ -25,7 +25,7 @@ namespace NzbDrone.Common
public class ServiceProvider : IServiceProvider
{
public const string NZBDRONE_SERVICE_NAME = "NzbDrone";
public const string NZBDRONE_SERVICE_NAME = "Radarr";
private readonly IProcessProvider _processProvider;
private readonly Logger _logger;
@@ -78,7 +78,7 @@ namespace NzbDrone.Common
serviceInstaller.Context = context;
serviceInstaller.DisplayName = serviceName;
serviceInstaller.ServiceName = serviceName;
serviceInstaller.Description = "NzbDrone Application Server";
serviceInstaller.Description = "Radarr Application Server";
serviceInstaller.StartType = ServiceStartMode.Automatic;
serviceInstaller.ServicesDependedOn = new[] { "EventLog", "Tcpip", "http" };

View File

@@ -54,7 +54,7 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>..\NzbDrone.Host\NzbDrone.ico</ApplicationIcon>
<ApplicationIcon>Radarr.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<StartupObject>NzbDrone.Console.ConsoleApp</StartupObject>
@@ -139,6 +139,9 @@
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Radarr.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>

View File

@@ -7,5 +7,3 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("NzbDrone.Host")]
[assembly: Guid("67AADCD9-89AA-4D95-8281-3193740E70E5")]
[assembly: AssemblyVersion("0.1.0.*")]

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -1,57 +0,0 @@
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.BitMeTv;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using System;
using System.Linq;
using FluentAssertions;
namespace NzbDrone.Core.Test.IndexerTests.BitMeTvTests
{
[TestFixture]
public class BitMeTvFixture : CoreTest<BitMeTv>
{
[SetUp]
public void Setup()
{
Subject.Definition = new IndexerDefinition()
{
Name = "BitMeTV",
Settings = new BitMeTvSettings() { Cookie = "uid=123" }
};
}
[Test]
public void should_parse_recent_feed_from_BitMeTv()
{
var recentFeed = ReadAllText(@"Files/Indexers/BitMeTv/BitMeTv.xml");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(5);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Title.Should().Be("Total.Divas.S02E08.HDTV.x264-CRiMSON");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("http://www.bitmetv.org/download.php/12/Total.Divas.S02E08.HDTV.x264-CRiMSON.torrent");
torrentInfo.InfoUrl.Should().BeNullOrEmpty();
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/05/13 17:04:29"));
torrentInfo.Size.Should().Be(395009065);
torrentInfo.InfoHash.Should().Be(null);
torrentInfo.MagnetUrl.Should().Be(null);
torrentInfo.Peers.Should().Be(null);
torrentInfo.Seeders.Should().Be(null);
}
}
}

View File

@@ -1,161 +0,0 @@
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.BroadcastheNet;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
using System;
using System.Linq;
using FluentAssertions;
namespace NzbDrone.Core.Test.IndexerTests.BroadcastheNetTests
{
[TestFixture]
public class BroadcastheNetFixture : CoreTest<BroadcastheNet>
{
[SetUp]
public void Setup()
{
Subject.Definition = new IndexerDefinition()
{
Name = "BroadcastheNet",
Settings = new BroadcastheNetSettings() { ApiKey = "abc", BaseUrl = "https://api.btnapps.net/" }
};
}
[Test]
public void should_parse_recent_feed_from_BroadcastheNet()
{
var recentFeed = ReadAllText(@"Files/Indexers/BroadcastheNet/RecentFeed.json");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(2);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Guid.Should().Be("BTN-123");
torrentInfo.Title.Should().Be("Jimmy.Kimmel.2014.09.15.Jane.Fonda.HDTV.x264-aAF");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("https://broadcasthe.net/torrents.php?action=download&id=123&authkey=123&torrent_pass=123");
torrentInfo.InfoUrl.Should().Be("https://broadcasthe.net/torrents.php?id=237457&torrentid=123");
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/09/16 21:15:33"));
torrentInfo.Size.Should().Be(505099926);
torrentInfo.InfoHash.Should().Be("123");
torrentInfo.TvdbId.Should().Be(71998);
torrentInfo.TvRageId.Should().Be(4055);
torrentInfo.MagnetUrl.Should().BeNullOrEmpty();
torrentInfo.Peers.Should().Be(40+9);
torrentInfo.Seeders.Should().Be(40);
torrentInfo.Origin.Should().Be("Scene");
torrentInfo.Source.Should().Be("HDTV");
torrentInfo.Container.Should().Be("MP4");
torrentInfo.Codec.Should().Be("x264");
torrentInfo.Resolution.Should().Be("SD");
}
private void VerifyBackOff()
{
Mocker.GetMock<IIndexerStatusService>()
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Once());
}
[Test]
public void should_back_off_on_bad_request()
{
Mocker.GetMock<IHttpClient>()
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.BadRequest));
var results = Subject.FetchRecent();
results.Should().BeEmpty();
VerifyBackOff();
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_back_off_and_report_api_key_invalid()
{
Mocker.GetMock<IHttpClient>()
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.Unauthorized));
var results = Subject.FetchRecent();
results.Should().BeEmpty();
VerifyBackOff();
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_back_off_on_unknown_method()
{
Mocker.GetMock<IHttpClient>()
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.NotFound));
var results = Subject.FetchRecent();
results.Should().BeEmpty();
VerifyBackOff();
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_back_off_api_limit_reached()
{
Mocker.GetMock<IHttpClient>()
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.ServiceUnavailable));
var results = Subject.FetchRecent();
results.Should().BeEmpty();
VerifyBackOff();
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_replace_https_http_as_needed()
{
var recentFeed = ReadAllText(@"Files/Indexers/BroadcastheNet/RecentFeed.json");
(Subject.Definition.Settings as BroadcastheNetSettings).BaseUrl = "http://api.btnapps.net/";
recentFeed = recentFeed.Replace("http:", "https:");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(2);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.DownloadUrl.Should().Be("http://broadcasthe.net/torrents.php?action=download&id=123&authkey=123&torrent_pass=123");
torrentInfo.InfoUrl.Should().Be("http://broadcasthe.net/torrents.php?id=237457&torrentid=123");
}
}
}

View File

@@ -1,51 +0,0 @@
using System;
using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Fanzub;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.IndexerTests.FanzubTests
{
[TestFixture]
public class FanzubFixture : CoreTest<Fanzub>
{
[SetUp]
public void Setup()
{
Subject.Definition = new IndexerDefinition()
{
Name = "Fanzub",
Settings = new FanzubSettings()
};
}
[Test]
public void should_parse_recent_feed_from_fanzub()
{
var recentFeed = ReadAllText(@"Files/Indexers/Fanzub/fanzub.xml");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(3);
var releaseInfo = releases.First();
releaseInfo.Title.Should().Be("[Vivid] Hanayamata - 10 [A33D6606]");
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
releaseInfo.DownloadUrl.Should().Be("http://fanzub.com/nzb/296464/Vivid%20Hanayamata%20-%2010.nzb");
releaseInfo.InfoUrl.Should().BeNullOrEmpty();
releaseInfo.CommentUrl.Should().BeNullOrEmpty();
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2014/09/13 12:56:53"));
releaseInfo.Size.Should().Be(556246858);
}
}
}

View File

@@ -1,57 +0,0 @@
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Torrentleech;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using System;
using System.Linq;
using FluentAssertions;
namespace NzbDrone.Core.Test.IndexerTests.TorrentleechTests
{
[TestFixture]
public class TorrentleechFixture : CoreTest<Torrentleech>
{
[SetUp]
public void Setup()
{
Subject.Definition = new IndexerDefinition()
{
Name = "Torrentleech",
Settings = new TorrentleechSettings()
};
}
[Test]
public void should_parse_recent_feed_from_Torrentleech()
{
var recentFeed = ReadAllText(@"Files/Indexers/Torrentleech/Torrentleech.xml");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(5);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Title.Should().Be("Classic Car Rescue S02E04 720p HDTV x264-C4TV");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("http://www.torrentleech.org/rss/download/513575/1234/Classic.Car.Rescue.S02E04.720p.HDTV.x264-C4TV.torrent");
torrentInfo.InfoUrl.Should().Be("http://www.torrentleech.org/torrent/513575");
torrentInfo.CommentUrl.Should().Be("http://www.torrentleech.org/torrent/513575#comments");
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/05/12 19:15:28"));
torrentInfo.Size.Should().Be(0);
torrentInfo.InfoHash.Should().Be(null);
torrentInfo.MagnetUrl.Should().Be(null);
torrentInfo.Peers.Should().Be(7+1);
torrentInfo.Seeders.Should().Be(1);
}
}
}

View File

@@ -237,8 +237,6 @@
<Compile Include="IndexerSearchTests\NzbSearchServiceFixture.cs" />
<Compile Include="IndexerSearchTests\SearchDefinitionFixture.cs" />
<Compile Include="IndexerTests\BasicRssParserFixture.cs" />
<Compile Include="IndexerTests\BitMeTvTests\BitMeTvFixture.cs" />
<Compile Include="IndexerTests\BroadcastheNetTests\BroadcastheNetFixture.cs" />
<Compile Include="IndexerTests\HDBitsTests\HDBitsFixture.cs" />
<Compile Include="IndexerTests\IndexerServiceFixture.cs" />
<Compile Include="IndexerTests\IndexerStatusServiceFixture.cs" />
@@ -251,7 +249,6 @@
<Compile Include="IndexerTests\NewznabTests\NewznabFixture.cs" />
<Compile Include="IndexerTests\NewznabTests\NewznabRequestGeneratorFixture.cs" />
<Compile Include="IndexerTests\NewznabTests\NewznabSettingFixture.cs" />
<Compile Include="IndexerTests\FanzubTests\FanzubFixture.cs" />
<Compile Include="IndexerTests\OmgwtfnzbsTests\OmgwtfnzbsFixture.cs" />
<Compile Include="IndexerTests\SeasonSearchFixture.cs" />
<Compile Include="IndexerTests\TestIndexer.cs" />
@@ -259,7 +256,6 @@
<Compile Include="IndexerTests\IPTorrentsTests\IPTorrentsFixture.cs" />
<Compile Include="IndexerTests\KickassTorrentsTests\KickassTorrentsFixture.cs" />
<Compile Include="IndexerTests\NyaaTests\NyaaFixture.cs" />
<Compile Include="IndexerTests\TorrentleechTests\TorrentleechFixture.cs" />
<Compile Include="IndexerTests\TorrentRssIndexerTests\TorrentRssIndexerFixture.cs" />
<Compile Include="IndexerTests\TorrentRssIndexerTests\TestTorrentRssIndexer.cs" />
<Compile Include="IndexerTests\WomblesTests\WomblesFixture.cs" />

View File

@@ -25,6 +25,4 @@ using System.Runtime.InteropServices;
[assembly: Guid("699aed1b-015e-4f0d-9c81-d5557b05d260")]
[assembly: AssemblyVersion("0.1.0.*")]
[assembly: InternalsVisibleTo("NzbDrone.Core")]

View File

@@ -33,7 +33,7 @@ namespace NzbDrone.Core.Backup
private string _backupTempFolder;
private static readonly Regex BackupFileRegex = new Regex(@"nzbdrone_backup_[._0-9]+\.zip", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex BackupFileRegex = new Regex(@"radarr_backup_[._0-9]+\.zip", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public BackupService(IMainDatabase maindDb,
IDiskTransferService diskTransferService,
@@ -49,7 +49,7 @@ namespace NzbDrone.Core.Backup
_archiveService = archiveService;
_logger = logger;
_backupTempFolder = Path.Combine(_appFolderInfo.TempFolder, "nzbdrone_backup");
_backupTempFolder = Path.Combine(_appFolderInfo.TempFolder, "radarr_backup");
}
public void Backup(BackupType backupType)
@@ -59,7 +59,7 @@ namespace NzbDrone.Core.Backup
_diskProvider.EnsureFolder(_backupTempFolder);
_diskProvider.EnsureFolder(GetBackupFolder(backupType));
var backupFilename = string.Format("nzbdrone_backup_{0:yyyy.MM.dd_HH.mm.ss}.zip", DateTime.Now);
var backupFilename = string.Format("radarr_backup_{0:yyyy.MM.dd_HH.mm.ss}.zip", DateTime.Now);
var backupPath = Path.Combine(GetBackupFolder(backupType), backupFilename);
Cleanup();

View File

@@ -161,7 +161,8 @@ namespace NzbDrone.Core.Configuration
public bool AnalyticsEnabled => GetValueBoolean("AnalyticsEnabled", true, persist: false);
public string Branch => GetValue("Branch", "master").ToLowerInvariant();
// TODO: Change back to "master" for the first stable release.
public string Branch => GetValue("Branch", "develop").ToLowerInvariant();
public string LogLevel => GetValue("LogLevel", "Info");

View File

@@ -0,0 +1,65 @@
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(109)]
public class add_movie_formats_to_naming_config : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("NamingConfig").AddColumn("StandardMovieFormat").AsString().Nullable();
Alter.Table("NamingConfig").AddColumn("MovieFolderFormat").AsString().Nullable();
Execute.WithConnection(ConvertConfig);
}
private void ConvertConfig(IDbConnection conn, IDbTransaction tran)
{
using (IDbCommand namingConfigCmd = conn.CreateCommand())
{
namingConfigCmd.Transaction = tran;
namingConfigCmd.CommandText = @"SELECT * FROM NamingConfig LIMIT 1";
using (IDataReader namingConfigReader = namingConfigCmd.ExecuteReader())
{
while (namingConfigReader.Read())
{
// Output Settings
var movieTitlePattern = "";
var movieYearPattern = "({Release Year})";
var qualityFormat = "[{Quality Title}]";
movieTitlePattern = "{Movie Title}";
var standardMovieFormat = string.Format("{0} {1} {2}", movieTitlePattern,
movieYearPattern,
qualityFormat);
var movieFolderFormat = string.Format("{0} {1}", movieTitlePattern, movieYearPattern);
using (IDbCommand updateCmd = conn.CreateCommand())
{
var text = string.Format("UPDATE NamingConfig " +
"SET StandardMovieFormat = '{0}', " +
"MovieFolderFormat = '{1}'",
standardMovieFormat,
movieFolderFormat);
updateCmd.Transaction = tran;
updateCmd.CommandText = text;
updateCmd.ExecuteNonQuery();
}
}
}
}
}
}
}

View File

@@ -0,0 +1,23 @@
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(110)]
public class add_phyiscal_release : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Movies").AddColumn("PhysicalRelease").AsDateTime().Nullable();
}
}
}

View File

@@ -0,0 +1,14 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(111)]
public class remove_bitmetv : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Delete.FromTable("Indexers").Row(new { Implementation = "BitMeTv" });
}
}
}

View File

@@ -0,0 +1,14 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(112)]
public class remove_torrentleech : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Delete.FromTable("Indexers").Row(new { Implementation = "Torrentleech" });
}
}
}

View File

@@ -0,0 +1,14 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(113)]
public class remove_broadcasthenet : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Delete.FromTable("Indexers").Row(new { Implementation = "BroadcastheNet" });
}
}
}

View File

@@ -0,0 +1,14 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(114)]
public class remove_fanzub : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Delete.FromTable("Indexers").Row(new { Implementation = "Fanzub" });
}
}
}

View File

@@ -0,0 +1,45 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(115)]
public class update_movie_sorttitle : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
// Create.Column("SortTitle").OnTable("Series").AsString().Nullable();
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

@@ -24,8 +24,6 @@ namespace NzbDrone.Core.DecisionEngine
{
CompareQuality,
CompareProtocol,
CompareEpisodeCount,
CompareEpisodeNumber,
ComparePeersIfTorrent,
CompareAgeIfUsenet,
CompareSize
@@ -56,6 +54,12 @@ namespace NzbDrone.Core.DecisionEngine
private int CompareQuality(DownloadDecision x, DownloadDecision y)
{
if (x.IsForMovie && y.IsForMovie)
{
return CompareAll(CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.Movie.Profile.Value.Items.FindIndex(v => v.Quality == remoteEpisode.ParsedMovieInfo.Quality.Quality)),
CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.ParsedMovieInfo.Quality.Revision.Real),
CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.ParsedMovieInfo.Quality.Revision.Version));
}
return CompareAll(CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Series.Profile.Value.Items.FindIndex(v => v.Quality == remoteEpisode.ParsedEpisodeInfo.Quality.Quality)),
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Real),
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version));
@@ -63,6 +67,7 @@ namespace NzbDrone.Core.DecisionEngine
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
{
var result = CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
{
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Series.Tags);
@@ -70,13 +75,22 @@ 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;
}
private int CompareEpisodeCount(DownloadDecision x, DownloadDecision y)
{
return CompareAll(CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.FullSeason),
CompareByReverse(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Episodes.Count));
return 0;
}
private int CompareEpisodeNumber(DownloadDecision x, DownloadDecision y)
@@ -88,20 +102,20 @@ namespace NzbDrone.Core.DecisionEngine
{
// Different protocols should get caught when checking the preferred protocol,
// since we're dealing with the same series in our comparisions
if (x.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Torrent ||
y.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Torrent)
if (x.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Torrent ||
y.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Torrent)
{
return 0;
}
return CompareAll(
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
{
var seeders = TorrentInfo.GetSeeders(remoteEpisode.Release);
return seeders.HasValue && seeders.Value > 0 ? Math.Round(Math.Log10(seeders.Value)) : 0;
}),
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
{
var peers = TorrentInfo.GetPeers(remoteEpisode.Release);
@@ -117,7 +131,7 @@ namespace NzbDrone.Core.DecisionEngine
return 0;
}
return CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
{
var ageHours = remoteEpisode.Release.AgeHours;
var age = remoteEpisode.Release.Age;
@@ -145,7 +159,7 @@ namespace NzbDrone.Core.DecisionEngine
{
// TODO: Is smaller better? Smaller for usenet could mean no par2 files.
return CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes()));
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes()));
}
}
}

View File

@@ -83,7 +83,7 @@ namespace NzbDrone.Core.DecisionEngine
{
if (parsedEpisodeInfo.Quality.HardcodedSubs.IsNotNullOrWhiteSpace())
{
remoteEpisode.DownloadAllowed = true;
remoteEpisode.DownloadAllowed = false;
decision = new DownloadDecision(remoteEpisode, new Rejection("Hardcoded subs found: " + parsedEpisodeInfo.Quality.HardcodedSubs));
}
else
@@ -257,7 +257,7 @@ namespace NzbDrone.Core.DecisionEngine
}
catch (NotImplementedException e)
{
_logger.Info("Spec " + spec.GetType().Name + " does not care about movies.");
_logger.Trace("Spec " + spec.GetType().Name + " does not care about movies.");
}
catch (Exception e)
{
@@ -265,7 +265,6 @@ namespace NzbDrone.Core.DecisionEngine
e.Data.Add("parsed", remoteEpisode.ParsedEpisodeInfo.ToJson());
_logger.Error(e, "Couldn't evaluate decision on " + remoteEpisode.Release.Title + ", with spec: " + spec.GetType().Name);
return new Rejection(string.Format("{0}: {1}", spec.GetType().Name, e.Message));//TODO UPDATE SPECS!
return null;
}
return null;

View File

@@ -60,7 +60,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
foreach (var remoteEpisode in matchingSeries)
{
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteEpisode.ParsedMovieInfo.Quality);
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Movie.Profile, remoteEpisode.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
{

View File

@@ -26,10 +26,10 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
private static readonly TorrentBlackholeSettingsValidator Validator = new TorrentBlackholeSettingsValidator();
[FieldDefinition(0, Label = "Torrent Folder", Type = FieldType.Path, HelpText = "Folder in which Sonarr will store the .torrent file")]
[FieldDefinition(0, Label = "Torrent Folder", Type = FieldType.Path, HelpText = "Folder in which Radarr will store the .torrent file")]
public string TorrentFolder { get; set; }
[FieldDefinition(1, Label = "Watch Folder", Type = FieldType.Path, HelpText = "Folder from which Sonarr should import completed downloads")]
[FieldDefinition(1, Label = "Watch Folder", Type = FieldType.Path, HelpText = "Folder from which Radarr should import completed downloads")]
public string WatchFolder { get; set; }
[DefaultValue(false)]
@@ -39,7 +39,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
[DefaultValue(false)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[FieldDefinition(3, Label = "Read Only", Type = FieldType.Checkbox, HelpText = "Instead of moving files this will instruct Sonarr to Copy or Hardlink (depending on settings/system configuration)")]
[FieldDefinition(3, Label = "Read Only", Type = FieldType.Checkbox, HelpText = "Instead of moving files this will instruct Radarr to Copy or Hardlink (depending on settings/system configuration)")]
public bool ReadOnly { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -19,10 +19,10 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
{
private static readonly UsenetBlackholeSettingsValidator Validator = new UsenetBlackholeSettingsValidator();
[FieldDefinition(0, Label = "Nzb Folder", Type = FieldType.Path, HelpText = "Folder in which Sonarr will store the .nzb file")]
[FieldDefinition(0, Label = "Nzb Folder", Type = FieldType.Path, HelpText = "Folder in which Radarr will store the .nzb file")]
public string NzbFolder { get; set; }
[FieldDefinition(1, Label = "Watch Folder", Type = FieldType.Path, HelpText = "Folder from which Sonarr should import completed downloads")]
[FieldDefinition(1, Label = "Watch Folder", Type = FieldType.Path, HelpText = "Folder from which Radarr should import completed downloads")]
public string WatchFolder { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -306,7 +306,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
{
return new NzbDroneValidationFailure("TvCategory", "Configuration of label failed")
{
DetailedDescription = "Sonarr as unable to add the label to Deluge."
DetailedDescription = "Radarr as unable to add the label to Deluge."
};
}
}

View File

@@ -43,7 +43,7 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
[FieldDefinition(2, Label = "API Key", Type = FieldType.Textbox)]
public string ApiKey { get; set; }
[FieldDefinition(3, Label = "Group", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional")]
[FieldDefinition(3, Label = "Group", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
public string TvCategory { get; set; }
[FieldDefinition(4, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbVortexPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]

View File

@@ -337,7 +337,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
return new NzbDroneValidationFailure(string.Empty, "NzbGet setting KeepHistory should be greater than 0")
{
InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port),
DetailedDescription = "NzbGet setting KeepHistory is set to 0. Which prevents Sonarr from seeing completed downloads."
DetailedDescription = "NzbGet setting KeepHistory is set to 0. Which prevents Radarr from seeing completed downloads."
};
}

View File

@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
[FieldDefinition(3, Label = "Password", Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional")]
[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; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]

View File

@@ -372,7 +372,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
{
IsWarning = true,
DetailedDescription = "Sonarr may not be able to support new features added to SABnzbd when running develop versions."
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
};
}
@@ -431,7 +431,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
return new NzbDroneValidationFailure("", "Disable 'Check before download' option in Sabnbzd")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/switches/", Settings.Host, Settings.Port),
DetailedDescription = "Using Check before download affects Sonarr ability to track new downloads. Also Sabnzbd recommends 'Abort jobs that cannot be completed' instead since it's more effective."
DetailedDescription = "Using Check before download affects Radarr ability to track new downloads. Also Sabnzbd recommends 'Abort jobs that cannot be completed' instead since it's more effective."
};
}
@@ -450,7 +450,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
return new NzbDroneValidationFailure("TvCategory", "Enable Job folders")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port),
DetailedDescription = "Sonarr prefers each download to have a separate folder. With * appended to the Folder/Path Sabnzbd will not create these job folders. Go to Sabnzbd to fix it."
DetailedDescription = "Radarr prefers each download to have a separate folder. With * appended to the Folder/Path Sabnzbd will not create these job folders. Go to Sabnzbd to fix it."
};
}
}
@@ -475,7 +475,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
return new NzbDroneValidationFailure("TvCategory", "Disable TV Sorting")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
};
}
}
@@ -489,7 +489,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
return new NzbDroneValidationFailure("TvCategory", "Disable Movie Sorting")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
};
}
}
@@ -503,7 +503,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
return new NzbDroneValidationFailure("TvCategory", "Disable Date Sorting")
{
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
};
}
}

View File

@@ -58,7 +58,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
[FieldDefinition(4, Label = "Password", Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional")]
[FieldDefinition(5, 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; }
[FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]

View File

@@ -165,6 +165,31 @@ namespace NzbDrone.Core.Download.Clients.Transmission
return hash;
}
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;
}
protected override void Test(List<ValidationFailure> failures)
{
failures.AddIfNotNull(TestConnection());
@@ -207,7 +232,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
_logger.Error(ex, ex.Message);
return new NzbDroneValidationFailure("Username", "Authentication failure")
{
DetailedDescription = string.Format("Please verify your username and password. Also verify if the host running Sonarr isn't blocked from accessing {0} by WhiteList limitations in the {0} configuration.", Name)
DetailedDescription = string.Format("Please verify your username and password. Also verify if the host running Radarr isn't blocked from accessing {0} by WhiteList limitations in the {0} configuration.", Name)
};
}
catch (WebException ex)

View File

@@ -50,16 +50,16 @@ namespace NzbDrone.Core.Download.Clients.Transmission
[FieldDefinition(4, Label = "Password", Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional. Creates a [category] subdirectory in the output directory.")]
[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; }
[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; }
[FieldDefinition(7, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
[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 episodes that aired over 14 days ago")]
[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)]

View File

@@ -37,6 +37,37 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
_rTorrentDirectoryValidator = rTorrentDirectoryValidator;
}
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);
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);
@@ -68,6 +99,32 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
}
}
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, 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(remoteMovie.Release, "Downloading torrent failed");
}
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
@@ -96,7 +153,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
public override string Name => "rTorrent";
public override ProviderMessage Message => new ProviderMessage("Sonarr is unable to remove torrents that have finished seeding when using rTorrent", ProviderMessageType.Warning);
public override ProviderMessage Message => new ProviderMessage("Radarr is unable to remove torrents that have finished seeding when using rTorrent", ProviderMessageType.Warning);
public override IEnumerable<DownloadClientItem> GetItems()
{

View File

@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
Host = "localhost";
Port = 8080;
UrlBase = "RPC2";
TvCategory = "tv-sonarr";
TvCategory = "movies-radarr";
OlderTvPriority = (int)RTorrentPriority.Normal;
RecentTvPriority = (int)RTorrentPriority.Normal;
}
@@ -49,7 +49,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
[FieldDefinition(5, Label = "Password", Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional.")]
[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; }
[FieldDefinition(7, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default rTorrent location")]

View File

@@ -38,7 +38,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
[FieldDefinition(3, Label = "Password", Type = FieldType.Password)]
public string Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional")]
[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; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(UTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]

View File

@@ -94,7 +94,6 @@ namespace NzbDrone.Core.Download
return;
}
var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title);
if (series == null)
@@ -110,7 +109,11 @@ namespace NzbDrone.Core.Download
if (movie == null)
{
movie = _movieService.GetMovie(historyItem.MovieId);
if (historyItem != null)
{
movie = _movieService.GetMovie(historyItem.MovieId);
}
if (movie == null)
{
@@ -156,7 +159,7 @@ namespace NzbDrone.Core.Download
trackedDownload.Warn(statusMessages);
}
}
else
else if (trackedDownload.RemoteEpisode.Series != null)
{
var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem);

View File

@@ -13,6 +13,7 @@ namespace NzbDrone.Core.Download
}
public int SeriesId { get; set; }
public int MovieId { get; set; }
public List<int> EpisodeIds { get; set; }
public QualityModel Quality { get; set; }
public string SourceTitle { get; set; }

View File

@@ -72,7 +72,7 @@ namespace NzbDrone.Core.Download
if (grabbedItems.Empty())
{
trackedDownload.Warn("Download wasn't grabbed by sonarr, skipping");
trackedDownload.Warn("Download wasn't grabbed by Radarr, skipping");
return;
}
@@ -88,6 +88,7 @@ namespace NzbDrone.Core.Download
var downloadFailedEvent = new DownloadFailedEvent
{
SeriesId = historyItem.SeriesId,
MovieId = historyItem.MovieId,
EpisodeIds = historyItems.Select(h => h.EpisodeId).ToList(),
Quality = historyItem.Quality,
SourceTitle = historyItem.SourceTitle,

View File

@@ -51,6 +51,12 @@ namespace NzbDrone.Core.Download
continue;
}
if (report.Rejections.Any())
{
_logger.Debug("Rejecting release {0} because {1}", report.ToString(), report.Rejections.First().Reason);
continue;
}
if (remoteMovie == null || remoteMovie.Movie == null)
{
continue;

View File

@@ -34,6 +34,15 @@ namespace NzbDrone.Core.Download
return;
}
if (message.MovieId != 0)
{
_logger.Debug("Failed download contains a movie, searching again.");
_commandQueueManager.Push(new MoviesSearchCommand { MovieId = message.MovieId });
return;
}
if (message.EpisodeIds.Count == 1)
{
_logger.Debug("Failed download only contains one episode, searching again");

View File

@@ -111,6 +111,18 @@ namespace NzbDrone.Core.Extras
}
}
//TODO: Implementing this will fix a lot of our warning exceptions
//public void Handle(MediaCoversUpdatedEvent message)
//{
// var movie = message.Movie;
// var movieFiles = GetMovieFiles(movie.Id);
// foreach (var extraFileManager in _extraFileManagers)
// {
// extraFileManager.CreateAfterMovieScan(movie, movieFiles);
// }
//}
public void Handle(EpisodeFolderCreatedEvent message)
{
var series = message.Series;

View File

@@ -1,32 +0,0 @@
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NLog;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.BitMeTv
{
public class BitMeTv : HttpIndexerBase<BitMeTvSettings>
{
public override string Name => "BitMeTV";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override bool SupportsSearch => false;
public override int PageSize => 0;
public BitMeTv(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
: base(httpClient, indexerStatusService, configService, parsingService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new BitMeTvRequestGenerator() { Settings = Settings };
}
public override IParseIndexerResponse GetParser()
{
return new TorrentRssParser() { ParseSizeInDescription = true };
}
}
}

View File

@@ -1,52 +0,0 @@
using System.Text.RegularExpressions;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.BitMeTv
{
public class BitMeTvSettingsValidator : AbstractValidator<BitMeTvSettings>
{
public BitMeTvSettingsValidator()
{
RuleFor(c => c.BaseUrl).ValidRootUrl();
RuleFor(c => c.UserId).NotEmpty();
RuleFor(c => c.RssPasskey).NotEmpty();
RuleFor(c => c.Cookie).NotEmpty();
RuleFor(c => c.Cookie)
.Matches(@"pass=[0-9a-f]{32}", RegexOptions.IgnoreCase)
.WithMessage("Wrong pattern")
.AsWarning();
}
}
public class BitMeTvSettings : IProviderConfig
{
private static readonly BitMeTvSettingsValidator Validator = new BitMeTvSettingsValidator();
public BitMeTvSettings()
{
BaseUrl = "https://www.bitmetv.org";
}
[FieldDefinition(0, Label = "Website URL")]
public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "UserId")]
public string UserId { get; set; }
[FieldDefinition(2, Label = "RSS Passkey")]
public string RssPasskey { get; set; }
[FieldDefinition(3, Label = "Cookie", HelpText = "BitMeTv uses a login cookie needed to access the rss, you'll have to retrieve it via a browser.")]
public string Cookie { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,45 +0,0 @@
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.BroadcastheNet
{
public class BroadcastheNet : HttpIndexerBase<BroadcastheNetSettings>
{
public override string Name => "BroadcastheNet";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override bool SupportsRss => true;
public override bool SupportsSearch => true;
public override int PageSize => 100;
public BroadcastheNet(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
: base(httpClient, indexerStatusService, configService, parsingService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
var requestGenerator = new BroadcastheNetRequestGenerator() { Settings = Settings, PageSize = PageSize };
var releaseInfo = _indexerStatusService.GetLastRssSyncReleaseInfo(Definition.Id);
if (releaseInfo != null)
{
int torrentID;
if (int.TryParse(releaseInfo.Guid.Replace("BTN-", string.Empty), out torrentID))
{
requestGenerator.LastRecentTorrentID = torrentID;
}
}
return requestGenerator;
}
public override IParseIndexerResponse GetParser()
{
return new BroadcastheNetParser();
}
}
}

View File

@@ -1,91 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Indexers.BroadcastheNet
{
public class BroadcastheNetParser : IParseIndexerResponse
{
private static readonly Regex RegexProtocol = new Regex("^https?:", RegexOptions.Compiled);
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var results = new List<ReleaseInfo>();
switch (indexerResponse.HttpResponse.StatusCode)
{
case HttpStatusCode.Unauthorized:
throw new ApiKeyException("API Key invalid or not authorized");
case HttpStatusCode.NotFound:
throw new IndexerException(indexerResponse, "Indexer API call returned NotFound, the Indexer API may have changed.");
case HttpStatusCode.ServiceUnavailable:
throw new RequestLimitReachedException("Cannot do more than 150 API requests per hour.");
default:
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse, "Indexer API call returned an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
}
break;
}
if (indexerResponse.Content == "Query execution was interrupted")
{
throw new IndexerException(indexerResponse, "Indexer API returned an internal server error");
}
JsonRpcResponse<BroadcastheNetTorrents> jsonResponse = new HttpResponse<JsonRpcResponse<BroadcastheNetTorrents>>(indexerResponse.HttpResponse).Resource;
if (jsonResponse.Error != null || jsonResponse.Result == null)
{
throw new IndexerException(indexerResponse, "Indexer API call returned an error [{0}]", jsonResponse.Error);
}
if (jsonResponse.Result.Results == 0)
{
return results;
}
var protocol = indexerResponse.HttpRequest.Url.Scheme + ":";
foreach (var torrent in jsonResponse.Result.Torrents.Values)
{
var torrentInfo = new TorrentInfo();
torrentInfo.Guid = string.Format("BTN-{0}", torrent.TorrentID);
torrentInfo.Title = torrent.ReleaseName;
torrentInfo.Size = torrent.Size;
torrentInfo.DownloadUrl = RegexProtocol.Replace(torrent.DownloadURL, protocol);
torrentInfo.InfoUrl = string.Format("{0}//broadcasthe.net/torrents.php?id={1}&torrentid={2}", protocol, torrent.GroupID, torrent.TorrentID);
//torrentInfo.CommentUrl =
if (torrent.TvdbID.HasValue)
{
torrentInfo.TvdbId = torrent.TvdbID.Value;
}
if (torrent.TvrageID.HasValue)
{
torrentInfo.TvRageId = torrent.TvrageID.Value;
}
torrentInfo.PublishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToUniversalTime().AddSeconds(torrent.Time);
//torrentInfo.MagnetUrl =
torrentInfo.InfoHash = torrent.InfoHash;
torrentInfo.Seeders = torrent.Seeders;
torrentInfo.Peers = torrent.Leechers + torrent.Seeders;
torrentInfo.Origin = torrent.Origin;
torrentInfo.Source = torrent.Source;
torrentInfo.Container = torrent.Container;
torrentInfo.Codec = torrent.Codec;
torrentInfo.Resolution = torrent.Resolution;
results.Add(torrentInfo);
}
return results;
}
}
}

View File

@@ -1,199 +0,0 @@
using System.Linq;
using System.Collections.Generic;
using NzbDrone.Common.Http;
using NzbDrone.Core.IndexerSearch.Definitions;
using System;
namespace NzbDrone.Core.Indexers.BroadcastheNet
{
public class BroadcastheNetRequestGenerator : IIndexerRequestGenerator
{
public int MaxPages { get; set; }
public int PageSize { get; set; }
public BroadcastheNetSettings Settings { get; set; }
public int? LastRecentTorrentID { get; set; }
public BroadcastheNetRequestGenerator()
{
MaxPages = 10;
PageSize = 100;
}
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
if (LastRecentTorrentID.HasValue)
{
pageableRequests.Add(GetPagedRequests(MaxPages, new BroadcastheNetTorrentQuery()
{
Id = ">=" + (LastRecentTorrentID.Value - 100)
}));
}
pageableRequests.AddTier(GetPagedRequests(MaxPages, new BroadcastheNetTorrentQuery()
{
Age = "<=86400"
}));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new BroadcastheNetTorrentQuery();
if (AddSeriesSearchParameters(parameters, searchCriteria))
{
foreach (var episode in searchCriteria.Episodes)
{
parameters = parameters.Clone();
parameters.Category = "Episode";
parameters.Name = string.Format("S{0:00}%E{1:00}%", episode.SeasonNumber, episode.EpisodeNumber);
pageableRequests.Add(GetPagedRequests(MaxPages, parameters));
}
foreach (var seasonNumber in searchCriteria.Episodes.Select(v => v.SeasonNumber).Distinct())
{
parameters = parameters.Clone();
parameters.Category = "Season";
parameters.Name = string.Format("Season {0}", seasonNumber);
pageableRequests.Add(GetPagedRequests(MaxPages, parameters));
}
}
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new BroadcastheNetTorrentQuery();
if (AddSeriesSearchParameters(parameters, searchCriteria))
{
foreach (var seasonNumber in searchCriteria.Episodes.Select(v => v.SeasonNumber).Distinct())
{
parameters.Category = "Season";
parameters.Name = string.Format("Season {0}", seasonNumber);
pageableRequests.Add(GetPagedRequests(MaxPages, parameters));
parameters = parameters.Clone();
parameters.Category = "Episode";
parameters.Name = string.Format("S{0:00}E%", seasonNumber);
pageableRequests.Add(GetPagedRequests(MaxPages, parameters));
}
}
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new BroadcastheNetTorrentQuery();
if (AddSeriesSearchParameters(parameters, searchCriteria))
{
parameters.Category = "Episode";
parameters.Name = string.Format("{0:yyyy}.{0:MM}.{0:dd}", searchCriteria.AirDate);
pageableRequests.Add(GetPagedRequests(MaxPages, parameters));
pageableRequests.AddTier();
foreach (var episode in searchCriteria.Episodes)
{
parameters = parameters.Clone();
parameters.Category = "Episode";
parameters.Name = string.Format("S{0:00}E{1:00}", episode.SeasonNumber, episode.EpisodeNumber);
pageableRequests.Add(GetPagedRequests(MaxPages, parameters));
}
}
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var parameters = new BroadcastheNetTorrentQuery();
if (AddSeriesSearchParameters(parameters, searchCriteria))
{
foreach (var episode in searchCriteria.Episodes)
{
parameters = parameters.Clone();
parameters.Category = "Episode";
parameters.Name = string.Format("S{0:00}E{1:00}", episode.SeasonNumber, episode.EpisodeNumber);
pageableRequests.Add(GetPagedRequests(MaxPages, parameters));
}
foreach (var seasonNumber in searchCriteria.Episodes.Select(v => v.SeasonNumber).Distinct())
{
parameters = parameters.Clone();
parameters.Category = "Season";
parameters.Name = string.Format("Season {0}", seasonNumber);
pageableRequests.Add(GetPagedRequests(MaxPages, parameters));
}
}
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
private bool AddSeriesSearchParameters(BroadcastheNetTorrentQuery parameters, SearchCriteriaBase searchCriteria)
{
if (searchCriteria.Series.TvdbId != 0)
{
parameters.Tvdb = string.Format("{0}", searchCriteria.Series.TvdbId);
return true;
}
if (searchCriteria.Series.TvRageId != 0)
{
parameters.Tvrage = string.Format("{0}", searchCriteria.Series.TvRageId);
return true;
}
// BTN is very neatly managed, so it's unlikely they map tvrage/tvdb wrongly.
return false;
}
private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, BroadcastheNetTorrentQuery parameters)
{
var builder = new JsonRpcRequestBuilder(Settings.BaseUrl)
.Call("getTorrents", Settings.ApiKey, parameters, PageSize, 0);
builder.SuppressHttpError = true;
for (var page = 0; page < maxPages; page++)
{
builder.JsonParameters[3] = page * PageSize;
yield return new IndexerRequest(builder.Build());
}
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
}
}

View File

@@ -1,37 +0,0 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.BroadcastheNet
{
public class BroadcastheNetSettingsValidator : AbstractValidator<BroadcastheNetSettings>
{
public BroadcastheNetSettingsValidator()
{
RuleFor(c => c.BaseUrl).ValidRootUrl();
RuleFor(c => c.ApiKey).NotEmpty();
}
}
public class BroadcastheNetSettings : IProviderConfig
{
private static readonly BroadcastheNetSettingsValidator Validator = new BroadcastheNetSettingsValidator();
public BroadcastheNetSettings()
{
BaseUrl = "http://api.btnapps.net/";
}
[FieldDefinition(0, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since your API key will be sent to that host.")]
public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "API Key")]
public string ApiKey { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,31 +0,0 @@
namespace NzbDrone.Core.Indexers.BroadcastheNet
{
public class BroadcastheNetTorrent
{
public string GroupName { get; set; }
public int GroupID { get; set; }
public int TorrentID { get; set; }
public int SeriesID { get; set; }
public string Series { get; set; }
public string SeriesBanner { get; set; }
public string SeriesPoster { get; set; }
public string YoutubeTrailer { get; set; }
public string Category { get; set; }
public int? Snatched { get; set; }
public int? Seeders { get; set; }
public int? Leechers { get; set; }
public string Source { get; set; }
public string Container { get; set; }
public string Codec { get; set; }
public string Resolution { get; set; }
public string Origin { get; set; }
public string ReleaseName { get; set; }
public long Size { get; set; }
public long Time { get; set; }
public int? TvdbID { get; set; }
public int? TvrageID { get; set; }
public string ImdbID { get; set; }
public string InfoHash { get; set; }
public string DownloadURL { get; set; }
}
}

View File

@@ -1,39 +0,0 @@
using Newtonsoft.Json;
namespace NzbDrone.Core.Indexers.BroadcastheNet
{
public class BroadcastheNetTorrentQuery
{
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Id { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Category { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Search { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Codec { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Container { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Source { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Resolution { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Origin { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Hash { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Tvdb { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Tvrage { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Age { get; set; }
public BroadcastheNetTorrentQuery Clone()
{
return MemberwiseClone() as BroadcastheNetTorrentQuery;
}
}
}

View File

@@ -1,10 +0,0 @@
using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.BroadcastheNet
{
public class BroadcastheNetTorrents
{
public Dictionary<int, BroadcastheNetTorrent> Torrents { get; set; }
public int Results { get; set; }
}
}

View File

@@ -1,30 +0,0 @@
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.Fanzub
{
public class Fanzub : HttpIndexerBase<FanzubSettings>
{
public override string Name => "Fanzub";
public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
public Fanzub(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
: base(httpClient, indexerStatusService, configService, parsingService, logger)
{
}
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new FanzubRequestGenerator() { Settings = Settings };
}
public override IParseIndexerResponse GetParser()
{
return new RssParser() { UseEnclosureUrl = true, UseEnclosureLength = true };
}
}
}

View File

@@ -1,94 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.Indexers.Fanzub
{
public class FanzubRequestGenerator : IIndexerRequestGenerator
{
private static readonly Regex RemoveCharactersRegex = new Regex(@"[!?`]", RegexOptions.Compiled);
public FanzubSettings Settings { get; set; }
public int PageSize { get; set; }
public FanzubRequestGenerator()
{
PageSize = 100;
}
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(null));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var searchTitles = searchCriteria.QueryTitles.SelectMany(v => GetTitleSearchStrings(v, searchCriteria.AbsoluteEpisodeNumber)).ToList();
pageableRequests.Add(GetPagedRequests(string.Join("|", searchTitles)));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
private IEnumerable<IndexerRequest> GetPagedRequests(string query)
{
var url = new StringBuilder();
url.AppendFormat("{0}?cat=anime&max={1}", Settings.BaseUrl, PageSize);
if (query.IsNotNullOrWhiteSpace())
{
url.AppendFormat("&q={0}", query);
}
yield return new IndexerRequest(url.ToString(), HttpAccept.Rss);
}
private IEnumerable<string> GetTitleSearchStrings(string title, int absoluteEpisodeNumber)
{
var formats = new[] { "{0}%20{1:00}", "{0}%20-%20{1:00}" };
return formats.Select(s => "\"" + string.Format(s, CleanTitle(title), absoluteEpisodeNumber) + "\"");
}
private string CleanTitle(string title)
{
return RemoveCharactersRegex.Replace(title, "");
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
}
}

View File

@@ -1,33 +0,0 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Fanzub
{
public class FanzubSettingsValidator : AbstractValidator<FanzubSettings>
{
public FanzubSettingsValidator()
{
RuleFor(c => c.BaseUrl).ValidRootUrl();
}
}
public class FanzubSettings : IProviderConfig
{
private static readonly FanzubSettingsValidator Validator = new FanzubSettingsValidator();
public FanzubSettings()
{
BaseUrl = "http://fanzub.com/rss/";
}
[FieldDefinition(0, Label = "Rss URL", HelpText = "Enter to URL to an Fanzub compatible RSS feed")]
public string BaseUrl { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Http;
@@ -22,21 +22,7 @@ namespace NzbDrone.Core.Indexers.HDBits
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var queryBase = new TorrentQuery();
if (TryAddSearchParameters(queryBase, searchCriteria))
{
foreach (var episode in searchCriteria.Episodes)
{
var query = queryBase.Clone();
query.TvdbInfo.Season = episode.SeasonNumber;
query.TvdbInfo.Episode = episode.EpisodeNumber;
}
}
return pageableRequests;
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
@@ -46,69 +32,28 @@ namespace NzbDrone.Core.Indexers.HDBits
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var query = new TorrentQuery();
if (TryAddSearchParameters(query, searchCriteria))
{
query.Search = string.Format("{0:yyyy}-{0:MM}-{0:dd}", searchCriteria.AirDate);
pageableRequests.Add(GetRequest(query));
}
return pageableRequests;
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var queryBase = new TorrentQuery();
if (TryAddSearchParameters(queryBase, searchCriteria))
{
foreach (var seasonNumber in searchCriteria.Episodes.Select(e => e.SeasonNumber).Distinct())
{
var query = queryBase.Clone();
query.TvdbInfo.Season = seasonNumber;
pageableRequests.Add(GetRequest(query));
}
}
return pageableRequests;
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
var queryBase = new TorrentQuery();
if (TryAddSearchParameters(queryBase, searchCriteria))
{
foreach (var episode in searchCriteria.Episodes)
{
var query = queryBase.Clone();
query.TvdbInfo.Season = episode.SeasonNumber;
query.TvdbInfo.Episode = episode.EpisodeNumber;
pageableRequests.Add(GetRequest(query));
}
}
return pageableRequests;
return new IndexerPageableRequestChain();
}
private bool TryAddSearchParameters(TorrentQuery query, SearchCriteriaBase searchCriteria)
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
if (searchCriteria.Series.TvdbId != 0)
{
query.TvdbInfo = query.TvdbInfo ?? new TvdbInfo();
query.TvdbInfo.Id = searchCriteria.Series.TvdbId;
return true;
}
return false;
var pageableRequests = new IndexerPageableRequestChain();
var queryBase = new TorrentQuery();
var query = queryBase.Clone();
query.ImdbInfo.Id = int.Parse(searchCriteria.Movie.ImdbId.Substring(2));
pageableRequests.Add(GetRequest(query));
return pageableRequests;
}
private IEnumerable<IndexerRequest> GetRequest(TorrentQuery query)
@@ -129,10 +74,5 @@ namespace NzbDrone.Core.Indexers.HDBits
yield return new IndexerRequest(request);
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
}
}

View File

@@ -46,7 +46,7 @@ namespace NzbDrone.Core.Indexers.Newznab
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws", 5010, 5030, 5040, 5045));
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", 5000));
yield return GetDefinition("Nzbs.org", GetSettings("http://nzbs.org", 2000));
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"));
@@ -106,8 +106,8 @@ namespace NzbDrone.Core.Indexers.Newznab
}
if (capabilities.SupportedTvSearchParameters != null &&
new[] { "q", "imdb" }.Any(v => capabilities.SupportedMovieSearchParamters.Contains(v)) &&
new[] { "imdbtitle", "imdbyear" }.All(v => capabilities.SupportedMovieSearchParamters.Contains(v)))
new[] { "q", "imdbid" }.Any(v => capabilities.SupportedMovieSearchParameters.Contains(v)) &&
new[] { "imdbtitle", "imdbyear" }.All(v => capabilities.SupportedMovieSearchParameters.Contains(v)))
{
return null;
}

View File

@@ -8,7 +8,7 @@ namespace NzbDrone.Core.Indexers.Newznab
public int MaxPageSize { get; set; }
public string[] SupportedSearchParameters { get; set; }
public string[] SupportedTvSearchParameters { get; set; }
public string[] SupportedMovieSearchParamters { get; set; }
public string[] SupportedMovieSearchParameters { get; set; }
public bool SupportsAggregateIdSearch { get; set; }
public List<NewznabCategory> Categories { get; set; }
@@ -17,7 +17,7 @@ namespace NzbDrone.Core.Indexers.Newznab
DefaultPageSize = 100;
MaxPageSize = 100;
SupportedSearchParameters = new[] { "q" };
SupportedMovieSearchParamters = new[] { "q", "imdb", "imdbtitle", "imdbyear" };
SupportedMovieSearchParameters = new[] { "q", "imdbid", "imdbtitle", "imdbyear" };
SupportedTvSearchParameters = new[] { "q", "rid", "season", "ep" }; // This should remain 'rid' for older newznab installs.
SupportsAggregateIdSearch = false;
Categories = new List<NewznabCategory>();

View File

@@ -102,11 +102,11 @@ namespace NzbDrone.Core.Indexers.Newznab
var xmlMovieSearch = xmlSearching.Element("movie-search");
if (xmlMovieSearch == null || xmlMovieSearch.Attribute("available").Value != "yes")
{
capabilities.SupportedMovieSearchParamters = null;
capabilities.SupportedMovieSearchParameters = null;
}
else if (xmlMovieSearch.Attribute("supportedParams") != null)
{
capabilities.SupportedMovieSearchParamters = xmlMovieSearch.Attribute("supportedParams").Value.Split(',');
capabilities.SupportedMovieSearchParameters = xmlMovieSearch.Attribute("supportedParams").Value.Split(',');
capabilities.SupportsAggregateIdSearch = true;
}
}

View File

@@ -91,8 +91,8 @@ namespace NzbDrone.Core.Indexers.Newznab
{
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
return capabilities.SupportedMovieSearchParamters != null &&
capabilities.SupportedMovieSearchParamters.Contains("imdb");
return capabilities.SupportedMovieSearchParameters != null &&
capabilities.SupportedMovieSearchParameters.Contains("imdbid");
}
}
@@ -112,9 +112,9 @@ namespace NzbDrone.Core.Indexers.Newznab
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
if (capabilities.SupportedTvSearchParameters != null)
if (capabilities.SupportedMovieSearchParameters != null)
{
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories.Concat(Settings.AnimeCategories), "tvsearch", ""));
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories.Concat(Settings.AnimeCategories), "movie", ""));
}
return pageableRequests;
@@ -124,7 +124,7 @@ namespace NzbDrone.Core.Indexers.Newznab
{
var pageableRequests = new IndexerPageableRequestChain();
if(SupportsMovieSearch)
if (SupportsMovieSearch)
{
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "movie",
string.Format("&imdbid={0}", searchCriteria.Movie.ImdbId.Substring(2)))); //strip off the "tt" - VERY HACKY

View File

@@ -48,9 +48,7 @@ namespace NzbDrone.Core.Indexers.Newznab
protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInfo)
{
releaseInfo = base.ProcessItem(item, releaseInfo);
releaseInfo.TvdbId = GetTvdbId(item);
releaseInfo.TvRageId = GetTvRageId(item);
releaseInfo.ImdbId = GetImdbId(item);
return releaseInfo;
}
@@ -114,27 +112,14 @@ namespace NzbDrone.Core.Indexers.Newznab
return url;
}
protected virtual int GetTvdbId(XElement item)
protected virtual int GetImdbId(XElement item)
{
var tvdbIdString = TryGetNewznabAttribute(item, "tvdbid");
int tvdbId;
var imdbIdString = TryGetNewznabAttribute(item, "imdb");
int imdbId;
if (!tvdbIdString.IsNullOrWhiteSpace() && int.TryParse(tvdbIdString, out tvdbId))
if (!imdbIdString.IsNullOrWhiteSpace() && int.TryParse(imdbIdString, out imdbId))
{
return tvdbId;
}
return 0;
}
protected virtual int GetTvRageId(XElement item)
{
var tvRageIdString = TryGetNewznabAttribute(item, "rageid");
int tvRageId;
if (!tvRageIdString.IsNullOrWhiteSpace() && int.TryParse(tvRageIdString, out tvRageId))
{
return tvRageId;
return imdbId;
}
return 0;

View File

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

View File

@@ -92,7 +92,7 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
private IEnumerable<IndexerRequest> GetPagedRequests(string query)
{
var url = new StringBuilder();
url.AppendFormat("{0}?catid=19,20&user={1}&api={2}&eng=1&delay={3}", BaseUrl, Settings.Username, Settings.ApiKey, Settings.Delay);
url.AppendFormat("{0}?catid=15,16,17&user={1}&api={2}&eng=1&delay={3}", BaseUrl, Settings.Username, Settings.ApiKey, Settings.Delay);
if (query.IsNotNullOrWhiteSpace())
{
@@ -105,7 +105,12 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetPagedRequests(string.Format("{0}",
searchCriteria.Movie.Title)));
return pageableRequests;
}
}
}

View File

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

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