mirror of
https://github.com/Radarr/Radarr.git
synced 2026-03-14 15:46:43 -04:00
Compare commits
172 Commits
v0.2.0.32
...
v0.2.0.166
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dea305e921 | ||
|
|
e2eab31548 | ||
|
|
fe62e18f0d | ||
|
|
f1fa1553cf | ||
|
|
b576ae813d | ||
|
|
99123be936 | ||
|
|
dd0a033b0f | ||
|
|
c64597c9f1 | ||
|
|
6d2f81e3ed | ||
|
|
4263808360 | ||
|
|
c5ca2babf7 | ||
|
|
08db74d6e6 | ||
|
|
b309a9b01f | ||
|
|
2730745607 | ||
|
|
ae0df2aef0 | ||
|
|
6d665aeb21 | ||
|
|
967d3fd5c0 | ||
|
|
199d9c93ed | ||
|
|
30d2b41fbb | ||
|
|
75bb2533a3 | ||
|
|
9b3b4eb55b | ||
|
|
42f84b830c | ||
|
|
eb0f825cfc | ||
|
|
56a5b6ec89 | ||
|
|
af478d3799 | ||
|
|
c2d40051d4 | ||
|
|
281e516495 | ||
|
|
f63c3091f4 | ||
|
|
50f49863b7 | ||
|
|
941b3bd701 | ||
|
|
f60b8cefca | ||
|
|
7c5f2ca54e | ||
|
|
401a650273 | ||
|
|
105af5cf11 | ||
|
|
637c2e43eb | ||
|
|
53373e6f4a | ||
|
|
ad147ed425 | ||
|
|
ed35e2f194 | ||
|
|
674919dbf5 | ||
|
|
15b77e303f | ||
|
|
757ca1d72c | ||
|
|
8c8c7a99e3 | ||
|
|
b3dfb960b5 | ||
|
|
98856e6747 | ||
|
|
8fb5049899 | ||
|
|
3f62911a4f | ||
|
|
170349c950 | ||
|
|
6c413d83eb | ||
|
|
3afd27cad3 | ||
|
|
149faf467d | ||
|
|
ce52bb8f68 | ||
|
|
4bb5857444 | ||
|
|
620f09ef8b | ||
|
|
16c1a2ee50 | ||
|
|
4b559cf29c | ||
|
|
ca03f21b03 | ||
|
|
f481fe9ea9 | ||
|
|
3a0278d0a1 | ||
|
|
d18b15d504 | ||
|
|
dc7e75187c | ||
|
|
68a0ef65df | ||
|
|
fe11928487 | ||
|
|
41dda3af48 | ||
|
|
8c3260c545 | ||
|
|
bd0ec5dfce | ||
|
|
ad38437b70 | ||
|
|
4447b7cd62 | ||
|
|
d33de0d158 | ||
|
|
dd5049b483 | ||
|
|
29586667cb | ||
|
|
5daece0ed4 | ||
|
|
5dc63e5607 | ||
|
|
7df283e57f | ||
|
|
e9b6c250f7 | ||
|
|
10515156d1 | ||
|
|
4260b58535 | ||
|
|
3a386f2e18 | ||
|
|
d3bd0c9b69 | ||
|
|
3180e648b4 | ||
|
|
d0c93759c6 | ||
|
|
f7471940c4 | ||
|
|
3a6873cc4d | ||
|
|
330ae38ec2 | ||
|
|
a0ecb19e32 | ||
|
|
38c966c07b | ||
|
|
ad824d4da5 | ||
|
|
e76c160afe | ||
|
|
6a62546a4d | ||
|
|
0efdc78f8d | ||
|
|
fdd06127fc | ||
|
|
317f8917b9 | ||
|
|
4038ce18c3 | ||
|
|
7f3ca85953 | ||
|
|
b93a9719fe | ||
|
|
2ef18edf08 | ||
|
|
d61b9ab207 | ||
|
|
abf4b137f1 | ||
|
|
774c85f06b | ||
|
|
a060335bbc | ||
|
|
5a8d944397 | ||
|
|
0b70a5c315 | ||
|
|
91cded3b71 | ||
|
|
84112dc85b | ||
|
|
b1b947ae7f | ||
|
|
1b035f8657 | ||
|
|
9d50f4d651 | ||
|
|
c06a6dc988 | ||
|
|
f198ca2b77 | ||
|
|
9cfc766889 | ||
|
|
5ef1e40403 | ||
|
|
c9e6835d7b | ||
|
|
604cea00f6 | ||
|
|
b4782da1d1 | ||
|
|
d5504043c5 | ||
|
|
81ebbcad70 | ||
|
|
92e9dc6ee1 | ||
|
|
5e8b617625 | ||
|
|
2cbe17151d | ||
|
|
95bd615718 | ||
|
|
8e8c4ff497 | ||
|
|
5eddcc1660 | ||
|
|
d42165a93a | ||
|
|
99012d8a40 | ||
|
|
8bc42c76e4 | ||
|
|
b7f72c6259 | ||
|
|
64ef8db037 | ||
|
|
3b5887bf09 | ||
|
|
40a75949ba | ||
|
|
6747267d19 | ||
|
|
13db03f97c | ||
|
|
cd68eea790 | ||
|
|
cfe55d00ae | ||
|
|
1d88313424 | ||
|
|
9513068467 | ||
|
|
9206258370 | ||
|
|
0fa1509ca6 | ||
|
|
c5eb772f7a | ||
|
|
04fec6d4d8 | ||
|
|
d0b5e380d7 | ||
|
|
df69c58d2b | ||
|
|
27114c9399 | ||
|
|
cfca07996b | ||
|
|
e97b80f630 | ||
|
|
792679fd81 | ||
|
|
ecf47d4b17 | ||
|
|
3b1d49a78f | ||
|
|
753f3eb863 | ||
|
|
9fc2d22d19 | ||
|
|
3cb42f06c2 | ||
|
|
a6c396a595 | ||
|
|
bac9076b1e | ||
|
|
b228273be0 | ||
|
|
e7fa4cba19 | ||
|
|
0506cc4185 | ||
|
|
cde8b4dd97 | ||
|
|
0a0a44162c | ||
|
|
125f46fbec | ||
|
|
f3222ca7c7 | ||
|
|
d252a8b232 | ||
|
|
48559cf964 | ||
|
|
c734e8bc7e | ||
|
|
3c7d7756e6 | ||
|
|
683bda49d8 | ||
|
|
52fb29ee18 | ||
|
|
236e16c9a5 | ||
|
|
0584038273 | ||
|
|
6685aea144 | ||
|
|
e4f7aa52df | ||
|
|
f61c4feb00 | ||
|
|
04e8c635e0 | ||
|
|
93ea5cfdee | ||
|
|
1b7288e7cb |
26
.gitignore
vendored
26
.gitignore
vendored
@@ -101,16 +101,21 @@ App_Data/*.ldf
|
||||
_NCrunch_*
|
||||
_TeamCity*
|
||||
|
||||
# Sonarr
|
||||
config.xml
|
||||
nzbdrone.log*txt
|
||||
# Radarr
|
||||
Backups/
|
||||
logs/
|
||||
MediaCover/
|
||||
UpdateLogs/
|
||||
xdg/
|
||||
config.xml
|
||||
logs.db*
|
||||
nzbdrone.db*
|
||||
nzbdrone.pid
|
||||
*workspace.xml
|
||||
*.test-cache
|
||||
*.userprefs
|
||||
*/test-results/*
|
||||
src/UI/.idea/*
|
||||
*log.txt
|
||||
node_modules/
|
||||
_output*
|
||||
_rawPackage/
|
||||
@@ -122,23 +127,26 @@ setup/Output/
|
||||
|
||||
UI.Phantom/
|
||||
|
||||
#VS outout folders
|
||||
# VS outout folders
|
||||
bin
|
||||
obj
|
||||
output/*
|
||||
|
||||
#Packages
|
||||
# Packages
|
||||
Radarr_*/
|
||||
Radarr_*.zip
|
||||
Radarr_*.gz
|
||||
|
||||
#OS X metadata files
|
||||
# macOS metadata files
|
||||
._*
|
||||
.DS_Store
|
||||
|
||||
_start
|
||||
_temp_*/**/*
|
||||
|
||||
#AppVeyor
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
|
||||
# AppVeyor
|
||||
/tools-cake/
|
||||
/_artifacts/
|
||||
/_artifacts/
|
||||
|
||||
10
.travis.yml
10
.travis.yml
@@ -1,12 +1,14 @@
|
||||
language: csharp
|
||||
solution: src/NzbDrone.sln
|
||||
script: # the following commands are just examples, use whatever your build process requires
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- nodejs
|
||||
- npm
|
||||
script:
|
||||
- ./build.sh
|
||||
- chmod +x test.sh
|
||||
# - ./test.sh Linux Unit Takes far too long, maybe even crashes travis :/
|
||||
install:
|
||||
- sudo apt-get install nodejs
|
||||
- sudo apt-get install npm
|
||||
after_success:
|
||||
- chmod +x package.sh
|
||||
- ./package.sh
|
||||
|
||||
4
CLA.md
4
CLA.md
@@ -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 ##
|
||||
|
||||
@@ -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
BIN
Logo/Thumbs.db
Binary file not shown.
94
README.md
Normal file
94
README.md
Normal file
@@ -0,0 +1,94 @@
|
||||
## Status
|
||||
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
[](https://github.com/Radarr/Radarr/pulls)
|
||||
[](http://www.gnu.org/licenses/gpl.html)
|
||||
[](https://github.com/Radarr/Radarr)
|
||||
[](https://github.com/Radar/Radarr/releases/latest)
|
||||
[](https://hub.docker.com/r/linuxserver/radarr/)
|
||||
|
||||
| Service | Master | Develop |
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
|
||||
| Travis | [](https://travis-ci.org/Radarr/Radarr) | [](https://travis-ci.org/Radarr/Radarr) |
|
||||
|
||||
This fork of Sonarr aims to turn it into something like CouchPotato.
|
||||
|
||||
## Downloads
|
||||
|
||||
[](https://github.com/Radarr/Radarr/releases)
|
||||
|
||||
[](https://ci.appveyor.com/project/galli-leo/radarr-usby1/build/artifacts)
|
||||
|
||||
[](https://store.docker.com/community/images/linuxserver/radarr)
|
||||
[](https://store.docker.com/community/images/lsioarmhf/radarr)
|
||||
[](https://store.docker.com/community/images/lsioarmhf/radarr-aarch64)
|
||||
|
||||
To connect to the UI, fire up your browser and open <http://localhost:7878> or <http://your-ip:7878>.
|
||||
|
||||
## Support
|
||||
|
||||
[](https://discord.gg/AD3UP37)
|
||||
[](https://www.reddit.com/r/radarr)
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
|
||||
## Features
|
||||
|
||||
### Currently Working
|
||||
|
||||
* Adding new movies
|
||||
* Manually searching for releases of movies
|
||||
* Automatically searching for releases
|
||||
* Automatically importing downloaded movies
|
||||
* Recognizing Special Editions, Director's Cut, etc.
|
||||
* Identifying releases with hardcoded subs
|
||||
* Rarbg.to, Torznab and Newznab Indexer
|
||||
* QBittorrent and Deluge download client (Other clients are coming)
|
||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||
|
||||
### Planned Features
|
||||
|
||||
* Scanning PreDB to know when a new release is available
|
||||
* Fixing the other Indexers and download clients
|
||||
* Importing of Sonarr config
|
||||
|
||||
### Major Features
|
||||
|
||||
* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc.
|
||||
* Can watch for better quality of the movies you have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
|
||||
* Automatic failed download handling will try another release if one fails
|
||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically
|
||||
* Full integration with SABnzbd and NZBGet
|
||||
* Full integration with Kodi, Plex (notification, library update, metadata)
|
||||
* And a beautiful UI
|
||||
|
||||
## Configuring Development Environment
|
||||
|
||||
### Requirements
|
||||
|
||||
* [Visual Studio Community](https://www.visualstudio.com/vs/community/) or [MonoDevelop](http://www.monodevelop.com)
|
||||
* [Git](https://git-scm.com/downloads)
|
||||
* [Node.js](https://nodejs.org/en/download/)
|
||||
|
||||
### Setup
|
||||
|
||||
* Make sure all the required software mentioned above are installed
|
||||
* Clone the repository into your development machine ([*info*](https://help.github.com/desktop/guides/contributing/working-with-your-remote-repository-on-github-or-github-enterprise))
|
||||
* Grab the submodules `git submodule init && git submodule update`
|
||||
* Install the required Node Packages `npm install`
|
||||
* Start gulp to monitor your dev environment for any changes that need post processing using `npm start` command.
|
||||
|
||||
> **Notice**
|
||||
> Gulp must be running at all times while you are working with Radarr client source files.
|
||||
|
||||
### Development
|
||||
|
||||
* Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed
|
||||
* Make sure `NzbDrone.Console` is set as the startup project
|
||||
|
||||
## Sponsors
|
||||
|
||||
[JetBrains](http://www.jetbrains.com) for providing us with free licenses to their great tools:
|
||||
* [ReSharper](http://www.jetbrains.com/resharper)
|
||||
* [WebStorm](http://www.jetbrains.com/webstorm)
|
||||
* [TeamCity](http://www.jetbrains.com/teamcity)
|
||||
12
appveyor.yml
12
appveyor.yml
@@ -35,4 +35,14 @@ artifacts:
|
||||
|
||||
cache:
|
||||
- '%USERPROFILE%\.nuget\packages'
|
||||
- node_modules
|
||||
- node_modules
|
||||
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
|
||||
only_commits:
|
||||
files:
|
||||
- src/
|
||||
- osx/
|
||||
- gulp/
|
||||
- logo/
|
||||
|
||||
76
readme.md
76
readme.md
@@ -1,76 +0,0 @@
|
||||
# Radarr
|
||||
|
||||
| Service | Master | Develop |
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr) |
|
||||
| Travis | [](https://travis-ci.org/galli-leo/Radarr) | [](https://travis-ci.org/galli-leo/Radarr) |
|
||||
|
||||
This fork of Sonarr aims to turn it into something like Couchpotato.
|
||||
|
||||
## Currently working:
|
||||
* Adding new movies
|
||||
* Manually searching for releases of movies.
|
||||
* Automatically searching for releases.
|
||||
* Automatically importing downloaded movies.
|
||||
* Recognizing Special Editions, Director's Cut, etc.
|
||||
* Identifying releases with hardcoded subs.
|
||||
* Rarbg.to, Torznab and Newznab Indexer.
|
||||
* QBittorrent and Deluge download client (Other clients are coming)
|
||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||
|
||||
## Planned Features:
|
||||
* Scanning PreDB to know when a new release is available.
|
||||
* Fixing the other Indexers and download clients.
|
||||
* Importing of Sonarr config.
|
||||
|
||||
## Download
|
||||
The latest precompiled binary versions can be found here: https://github.com/galli-leo/Radarr/releases.
|
||||
|
||||
For more up to date versions (but also sometimes broken), daily builds can be found here:
|
||||
* [OSX](https://leonardogalli.ch/radarr/builds/latest.php?os=osx)
|
||||
* [Windows](https://leonardogalli.ch/radarr/builds/latest.php?os=windows)
|
||||
* [Linux](https://leonardogalli.ch/radarr/builds/latest.php?os=mono)
|
||||
|
||||
## Major Features Include: ##
|
||||
|
||||
* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
|
||||
* Can watch for better quality of the movies you have and do an upgrade.
|
||||
* Automatic failed download handling will try another release if one fails
|
||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically.
|
||||
* Full integration with SABNzbd and NzbGet.
|
||||
* Full integration with XBMC, Plex (notification, library update, metadata).
|
||||
* And a beautiful UI
|
||||
|
||||
## Configuring Development Environment: ##
|
||||
|
||||
### Requirements ###
|
||||
- Visual Studio 2015 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) or Mono
|
||||
- [Git](http://git-scm.com/downloads)
|
||||
- [NodeJS](http://nodejs.org/download/)
|
||||
|
||||
### Setup ###
|
||||
|
||||
- Make sure all the required software mentioned above are installed.
|
||||
- Clone the repository into your development machine. [*info*](https://help.github.com/articles/working-with-repositories)
|
||||
- Grab the submodules `git submodule init && git submodule update`
|
||||
- install the required Node Packages `npm install`
|
||||
- start gulp to monitor your dev environment for any changes that need post processing using `npm start` command.
|
||||
|
||||
*Please note gulp must be running at all times while you are working with Sonarr client source files.*
|
||||
|
||||
|
||||
### Development ###
|
||||
- Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed.
|
||||
- Make sure `NzbDrone.Console` is set as the startup project
|
||||
|
||||
|
||||
### License ###
|
||||
* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
||||
Copyright 2010-2016
|
||||
|
||||
|
||||
### Sponsors ###
|
||||
- [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools
|
||||
- [ReSharper](http://www.jetbrains.com/resharper/)
|
||||
- [WebStorm](http://www.jetbrains.com/webstorm/)
|
||||
- [TeamCity](http://www.jetbrains.com/teamcity/)
|
||||
@@ -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()
|
||||
|
||||
@@ -2,24 +2,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.MovieStats;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.Calendar
|
||||
{
|
||||
public class CalendarModule : EpisodeModuleWithSignalR
|
||||
public class CalendarModule : MovieModule
|
||||
{
|
||||
public CalendarModule(IEpisodeService episodeService,
|
||||
ISeriesService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "calendar")
|
||||
public CalendarModule(IBroadcastSignalRMessage signalR,
|
||||
IMovieService moviesService,
|
||||
IMovieStatisticsService moviesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper)
|
||||
: base(signalR, moviesService, moviesStatisticsService, sceneMappingService, coverMapper, "calendar")
|
||||
{
|
||||
|
||||
GetResourceAll = GetCalendar;
|
||||
}
|
||||
|
||||
private List<EpisodeResource> GetCalendar()
|
||||
private List<MovieResource> GetCalendar()
|
||||
{
|
||||
var start = DateTime.Today;
|
||||
var end = DateTime.Today.AddDays(2);
|
||||
@@ -33,9 +47,9 @@ namespace NzbDrone.Api.Calendar
|
||||
if (queryEnd.HasValue) end = DateTime.Parse(queryEnd.Value);
|
||||
if (queryIncludeUnmonitored.HasValue) includeUnmonitored = Convert.ToBoolean(queryIncludeUnmonitored.Value);
|
||||
|
||||
var resources = MapToResource(_episodeService.EpisodesBetweenDates(start, end, includeUnmonitored), true, true);
|
||||
var resources = _moviesService.GetMoviesBetweenDates(start, end, includeUnmonitored).Select(MapToResource);
|
||||
|
||||
return resources.OrderBy(e => e.AirDateUtc).ToList();
|
||||
return resources.OrderBy(e => e.InCinemas).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,11 @@ 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();
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
31
src/NzbDrone.Api/Movies/MovieEditorModule.cs
Normal file
31
src/NzbDrone.Api/Movies/MovieEditorModule.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
src/NzbDrone.Api/Movies/MovieFileModule.cs
Normal file
89
src/NzbDrone.Api/Movies/MovieFileModule.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.EpisodeFiles
|
||||
{
|
||||
public class MovieFileModule : NzbDroneRestModuleWithSignalR<MovieFileResource, MovieFile>
|
||||
//IHandle<EpisodeFileAddedEvent>
|
||||
{
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly IRecycleBinProvider _recycleBinProvider;
|
||||
private readonly IMovieService _seriesService;
|
||||
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MovieFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMediaFileService mediaFileService,
|
||||
IRecycleBinProvider recycleBinProvider,
|
||||
IMovieService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
Logger logger)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_mediaFileService = mediaFileService;
|
||||
_recycleBinProvider = recycleBinProvider;
|
||||
_seriesService = seriesService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
_logger = logger;
|
||||
/*GetResourceById = GetEpisodeFile;
|
||||
GetResourceAll = GetEpisodeFiles;
|
||||
UpdateResource = SetQuality;*/
|
||||
DeleteResource = DeleteEpisodeFile;
|
||||
}
|
||||
|
||||
/*private EpisodeFileResource GetEpisodeFile(int id)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(id);
|
||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||
|
||||
return episodeFile.ToResource(series, _qualityUpgradableSpecification);
|
||||
}
|
||||
|
||||
private List<EpisodeFileResource> GetEpisodeFiles()
|
||||
{
|
||||
if (!Request.Query.SeriesId.HasValue)
|
||||
{
|
||||
throw new BadRequestException("seriesId is missing");
|
||||
}
|
||||
|
||||
var seriesId = (int)Request.Query.SeriesId;
|
||||
|
||||
var series = _seriesService.GetSeries(seriesId);
|
||||
|
||||
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _qualityUpgradableSpecification));
|
||||
}
|
||||
|
||||
private void SetQuality(EpisodeFileResource episodeFileResource)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
|
||||
episodeFile.Quality = episodeFileResource.Quality;
|
||||
_mediaFileService.Update(episodeFile);
|
||||
}*/
|
||||
|
||||
private void DeleteEpisodeFile(int id)
|
||||
{
|
||||
var episodeFile = _mediaFileService.GetMovie(id);
|
||||
var series = _seriesService.GetMovie(episodeFile.MovieId);
|
||||
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
|
||||
|
||||
_logger.Info("Deleting episode file: {0}", fullPath);
|
||||
_recycleBinProvider.DeleteFile(fullPath);
|
||||
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
|
||||
}
|
||||
|
||||
public void Handle(EpisodeFileAddedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.EpisodeFile.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Movies
|
||||
private readonly IRenameMovieFileService _renameMovieFileService;
|
||||
|
||||
public RenameMovieModule(IRenameMovieFileService renameMovieFileService)
|
||||
: base("rename")
|
||||
: base("renameMovie")
|
||||
{
|
||||
_renameMovieFileService = renameMovieFileService;
|
||||
|
||||
|
||||
@@ -116,9 +116,11 @@
|
||||
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
|
||||
<Compile Include="Indexers\ReleaseModuleBase.cs" />
|
||||
<Compile Include="Indexers\ReleasePushModule.cs" />
|
||||
<Compile Include="Movies\MovieFileModule.cs" />
|
||||
<Compile Include="Movies\MovieModule.cs" />
|
||||
<Compile Include="Movies\RenameMovieModule.cs" />
|
||||
<Compile Include="Movies\RenameMovieResource.cs" />
|
||||
<Compile Include="Movies\MovieEditorModule.cs" />
|
||||
<Compile Include="Parse\ParseModule.cs" />
|
||||
<Compile Include="Parse\ParseResource.cs" />
|
||||
<Compile Include="ManualImport\ManualImportModule.cs" />
|
||||
@@ -231,6 +233,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" />
|
||||
|
||||
86
src/NzbDrone.Api/Series/MovieFileResource.cs
Normal file
86
src/NzbDrone.Api/Series/MovieFileResource.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
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; }
|
||||
public string Edition { get; set; }
|
||||
public Core.MediaFiles.MediaInfo.MediaInfoModel MediaInfo { get; set; }
|
||||
|
||||
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
||||
}
|
||||
|
||||
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,
|
||||
MediaInfo = model.MediaInfo,
|
||||
Edition = model.Edition
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Api.Movie
|
||||
IHandle<MediaCoversUpdatedEvent>
|
||||
|
||||
{
|
||||
private readonly IMovieService _moviesService;
|
||||
protected readonly IMovieService _moviesService;
|
||||
private readonly IMovieStatisticsService _moviesStatisticsService;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
|
||||
@@ -78,13 +78,33 @@ namespace NzbDrone.Api.Movie
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
}
|
||||
|
||||
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMovieService moviesService,
|
||||
IMovieStatisticsService moviesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
string resource)
|
||||
: base(signalRBroadcaster, resource)
|
||||
{
|
||||
_moviesService = moviesService;
|
||||
_moviesStatisticsService = moviesStatisticsService;
|
||||
|
||||
_coverMapper = coverMapper;
|
||||
|
||||
GetResourceAll = AllMovie;
|
||||
GetResourceById = GetMovie;
|
||||
CreateResource = AddMovie;
|
||||
UpdateResource = UpdateMovie;
|
||||
DeleteResource = DeleteMovie;
|
||||
}
|
||||
|
||||
private MovieResource GetMovie(int id)
|
||||
{
|
||||
var movies = _moviesService.GetMovie(id);
|
||||
return MapToResource(movies);
|
||||
}
|
||||
|
||||
private MovieResource MapToResource(Core.Tv.Movie movies)
|
||||
protected MovieResource MapToResource(Core.Tv.Movie movies)
|
||||
{
|
||||
if (movies == null) return null;
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace NzbDrone.Api.Movie
|
||||
public string RemotePoster { get; set; }
|
||||
public int Year { get; set; }
|
||||
public bool HasFile { get; set; }
|
||||
public string YouTubeTrailerId { get; set; }
|
||||
public string Studio { get; set; }
|
||||
|
||||
//View & Edit
|
||||
public string Path { get; set; }
|
||||
@@ -55,6 +57,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)
|
||||
|
||||
@@ -84,6 +87,7 @@ namespace NzbDrone.Api.Movie
|
||||
|
||||
long size = 0;
|
||||
bool downloaded = false;
|
||||
MovieFileResource movieFile = null;
|
||||
|
||||
|
||||
if(model.MovieFile != null)
|
||||
@@ -95,6 +99,7 @@ namespace NzbDrone.Api.Movie
|
||||
{
|
||||
size = model.MovieFile.Value.Size;
|
||||
downloaded = true;
|
||||
movieFile = model.MovieFile.Value.ToResource();
|
||||
}
|
||||
|
||||
return new MovieResource
|
||||
@@ -140,7 +145,10 @@ namespace NzbDrone.Api.Movie
|
||||
Added = model.Added,
|
||||
AddOptions = model.AddOptions,
|
||||
AlternativeTitles = model.AlternativeTitles,
|
||||
Ratings = model.Ratings
|
||||
Ratings = model.Ratings,
|
||||
MovieFile = movieFile,
|
||||
YouTubeTrailerId = model.YouTubeTrailerId,
|
||||
Studio = model.Studio
|
||||
};
|
||||
}
|
||||
|
||||
@@ -187,7 +195,9 @@ namespace NzbDrone.Api.Movie
|
||||
Added = resource.Added,
|
||||
AddOptions = resource.AddOptions,
|
||||
AlternativeTitles = resource.AlternativeTitles,
|
||||
Ratings = resource.Ratings
|
||||
Ratings = resource.Ratings,
|
||||
YouTubeTrailerId = resource.YouTubeTrailerId,
|
||||
Studio = resource.Studio
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new DelugeSettings()
|
||||
{
|
||||
TvCategory = null
|
||||
MovieCategory = null
|
||||
};
|
||||
|
||||
_queued = new DelugeTorrent
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
Port = 2222,
|
||||
Username = "admin",
|
||||
Password = "pass",
|
||||
TvCategory = "tv"
|
||||
MovieCategory = "movies-radarr"
|
||||
};
|
||||
|
||||
Mocker.GetMock<ITorrentFileInfoReader>()
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new RTorrentSettings()
|
||||
{
|
||||
TvCategory = null
|
||||
MovieCategory = null
|
||||
};
|
||||
|
||||
_downloading = new RTorrentTorrent
|
||||
|
||||
@@ -112,12 +112,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
||||
|
||||
protected void GivenTvCategory()
|
||||
{
|
||||
_settings.TvCategory = "sonarr";
|
||||
_settings.MovieCategory = "radarr";
|
||||
}
|
||||
|
||||
protected void GivenTvDirectory()
|
||||
{
|
||||
_settings.TvDirectory = @"C:/Downloads/Finished/sonarr";
|
||||
_settings.MovieDirectory = @"C:/Downloads/Finished/radarr";
|
||||
}
|
||||
|
||||
protected void GivenFailedDownload()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,14 +42,14 @@ namespace NzbDrone.Core.Test.IndexerTests.OmgwtfnzbsTests
|
||||
|
||||
var releaseInfo = releases.First();
|
||||
|
||||
releaseInfo.Title.Should().Be("Stephen.Fry.Gadget.Man.S01E05.HDTV.x264-C4TV");
|
||||
releaseInfo.Title.Should().Be("Un.Petit.Boulot.2016.FRENCH.720p.BluRay.DTS.x264-LOST");
|
||||
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
|
||||
releaseInfo.DownloadUrl.Should().Be("http://api.omgwtfnzbs.org/sn.php?id=OAl4g&user=nzbdrone&api=nzbdrone");
|
||||
releaseInfo.InfoUrl.Should().Be("http://omgwtfnzbs.org/details.php?id=OAl4g");
|
||||
releaseInfo.DownloadUrl.Should().Be("https://api.omgwtfnzbs.me/nzb/?id=8a2Bw&user=nzbdrone&api=nzbdrone");
|
||||
releaseInfo.InfoUrl.Should().Be("https://omgwtfnzbs.me/details.php?id=8a2Bw");
|
||||
releaseInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2012/12/17 23:30:13"));
|
||||
releaseInfo.Size.Should().Be(236822906);
|
||||
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2017/01/09 00:16:54"));
|
||||
releaseInfo.Size.Should().Be(5354909355);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,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" />
|
||||
|
||||
@@ -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();
|
||||
|
||||
14
src/NzbDrone.Core/Datastore/Migration/114_remove_fanzub.cs
Normal file
14
src/NzbDrone.Core/Datastore/Migration/114_remove_fanzub.cs
Normal 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" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(116)]
|
||||
public class update_movie_sorttitle_again : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(SetSortTitles);
|
||||
}
|
||||
|
||||
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||
{
|
||||
getSeriesCmd.Transaction = tran;
|
||||
getSeriesCmd.CommandText = @"SELECT Id, Title FROM Movies";
|
||||
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||
{
|
||||
while (seriesReader.Read())
|
||||
{
|
||||
var id = seriesReader.GetInt32(0);
|
||||
var title = seriesReader.GetString(1);
|
||||
|
||||
var sortTitle = Parser.Parser.NormalizeTitle(title).ToLower();
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "UPDATE Movies SET SortTitle = ? WHERE Id = ?";
|
||||
updateCmd.AddParameter(sortTitle);
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(117)]
|
||||
public class update_movie_file : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Create.Column("Edition").OnTable("MovieFiles").AsString().Nullable();
|
||||
//Execute.WithConnection(SetSortTitles);
|
||||
}
|
||||
|
||||
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||
{
|
||||
getSeriesCmd.Transaction = tran;
|
||||
getSeriesCmd.CommandText = @"SELECT Id, RelativePath FROM MovieFiles";
|
||||
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||
{
|
||||
while (seriesReader.Read())
|
||||
{
|
||||
var id = seriesReader.GetInt32(0);
|
||||
var relativePath = seriesReader.GetString(1);
|
||||
|
||||
var result = Parser.Parser.ParseMovieTitle(relativePath);
|
||||
|
||||
var edition = "";
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
edition = Parser.Parser.ParseMovieTitle(relativePath).Edition;
|
||||
}
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "UPDATE MovieFiles SET Edition = ? WHERE Id = ?";
|
||||
updateCmd.AddParameter(edition);
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(118)]
|
||||
public class update_movie_slug : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(SetTitleSlug);
|
||||
}
|
||||
|
||||
private void SetTitleSlug(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||
{
|
||||
getSeriesCmd.Transaction = tran;
|
||||
getSeriesCmd.CommandText = @"SELECT Id, Title, Year FROM Movies";
|
||||
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||
{
|
||||
while (seriesReader.Read())
|
||||
{
|
||||
var id = seriesReader.GetInt32(0);
|
||||
var title = seriesReader.GetString(1);
|
||||
var year = seriesReader.GetInt32(2);
|
||||
|
||||
var titleSlug = ToUrlSlug(title + "-" + year);
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "UPDATE Movies SET TitleSlug = ? WHERE Id = ?";
|
||||
updateCmd.AddParameter(titleSlug);
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToUrlSlug(string value)
|
||||
{
|
||||
//First to lower case
|
||||
value = value.ToLowerInvariant();
|
||||
|
||||
//Remove all accents
|
||||
var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(value);
|
||||
value = Encoding.ASCII.GetString(bytes);
|
||||
|
||||
//Replace spaces
|
||||
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
|
||||
|
||||
//Remove invalid chars
|
||||
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
|
||||
|
||||
//Trim dashes from end
|
||||
value = value.Trim('-', '_');
|
||||
|
||||
//Replace double occurences of - or _
|
||||
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(119)]
|
||||
public class add_youtube_trailer_id : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Movies").AddColumn("YouTubeTrailerId").AsString().Nullable();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(120)]
|
||||
public class add_studio : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Movies").AddColumn("Studio").AsString().Nullable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(121)]
|
||||
public class update_filedate_config : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Execute.WithConnection(SetTitleSlug);
|
||||
}
|
||||
|
||||
private void SetTitleSlug(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||
{
|
||||
getSeriesCmd.Transaction = tran;
|
||||
getSeriesCmd.CommandText = @"SELECT Id, Value FROM Config WHERE Key = 'filedate'";
|
||||
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||
{
|
||||
while (seriesReader.Read())
|
||||
{
|
||||
var id = seriesReader.GetInt32(0);
|
||||
var value = seriesReader.GetString(1);
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "UPDATE Config SET Value = 'Release' WHERE Id = ?";
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToUrlSlug(string value)
|
||||
{
|
||||
//First to lower case
|
||||
value = value.ToLowerInvariant();
|
||||
|
||||
//Remove all accents
|
||||
var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(value);
|
||||
value = Encoding.ASCII.GetString(bytes);
|
||||
|
||||
//Replace spaces
|
||||
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
|
||||
|
||||
//Remove invalid chars
|
||||
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
|
||||
|
||||
//Trim dashes from end
|
||||
value = value.Trim('-', '_');
|
||||
|
||||
//Replace double occurences of - or _
|
||||
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
|
||||
public List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports)
|
||||
{
|
||||
return GetDecisions(reports).ToList();
|
||||
return GetMovieDecisions(reports).ToList();
|
||||
}
|
||||
|
||||
public List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase)
|
||||
@@ -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;
|
||||
|
||||
@@ -60,11 +60,11 @@ 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))
|
||||
{
|
||||
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
|
||||
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedMovieInfo.Quality);
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0}", remoteEpisode.ParsedMovieInfo.Quality);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -31,25 +31,17 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
_proxy = proxy;
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
|
||||
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
|
||||
{
|
||||
var actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);
|
||||
|
||||
if (!Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
|
||||
_proxy.SetLabel(actualHash, Settings.MovieCategory, Settings);
|
||||
}
|
||||
|
||||
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
|
||||
|
||||
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
|
||||
}*/
|
||||
|
||||
return actualHash.ToUpper();
|
||||
}
|
||||
|
||||
@@ -57,66 +49,24 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
{
|
||||
var actualHash = _proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||
|
||||
if (!Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
|
||||
_proxy.SetLabel(actualHash, Settings.MovieCategory, Settings);
|
||||
}
|
||||
|
||||
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
|
||||
|
||||
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
|
||||
}*/
|
||||
|
||||
return actualHash.ToUpper();
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
||||
{
|
||||
var actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);
|
||||
|
||||
if (!Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
|
||||
}
|
||||
|
||||
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
|
||||
|
||||
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
|
||||
}
|
||||
|
||||
return actualHash.ToUpper();
|
||||
throw new NotImplementedException("Episodes are not working with Radarr");
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
var actualHash = _proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||
|
||||
if (!Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
|
||||
}
|
||||
|
||||
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
|
||||
|
||||
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
|
||||
}
|
||||
|
||||
return actualHash.ToUpper();
|
||||
throw new NotImplementedException("Episodes are not working with Radarr");
|
||||
}
|
||||
|
||||
public override string Name => "Deluge";
|
||||
@@ -127,9 +77,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
|
||||
try
|
||||
{
|
||||
if (!Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
torrents = _proxy.GetTorrentsByLabel(Settings.TvCategory, Settings);
|
||||
torrents = _proxy.GetTorrentsByLabel(Settings.MovieCategory, Settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -149,7 +99,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
var item = new DownloadClientItem();
|
||||
item.DownloadId = torrent.Hash.ToUpper();
|
||||
item.Title = torrent.Name;
|
||||
item.Category = Settings.TvCategory;
|
||||
item.Category = Settings.MovieCategory;
|
||||
|
||||
item.DownloadClient = Definition.Name;
|
||||
|
||||
@@ -280,7 +230,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
|
||||
private ValidationFailure TestCategory()
|
||||
{
|
||||
if (Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
if (Settings.MovieCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -297,16 +247,16 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
|
||||
var labels = _proxy.GetAvailableLabels(Settings);
|
||||
|
||||
if (!labels.Contains(Settings.TvCategory))
|
||||
if (!labels.Contains(Settings.MovieCategory))
|
||||
{
|
||||
_proxy.AddLabel(Settings.TvCategory, Settings);
|
||||
_proxy.AddLabel(Settings.MovieCategory, Settings);
|
||||
labels = _proxy.GetAvailableLabels(Settings);
|
||||
|
||||
if (!labels.Contains(Settings.TvCategory))
|
||||
if (!labels.Contains(Settings.MovieCategory))
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "Configuration of label failed")
|
||||
return new NzbDroneValidationFailure("MovieCategory", "Configuration of label failed")
|
||||
{
|
||||
DetailedDescription = "Sonarr as unable to add the label to Deluge."
|
||||
DetailedDescription = "Radarr as unable to add the label to Deluge."
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
RuleFor(c => c.Host).ValidHost();
|
||||
RuleFor(c => c.Port).GreaterThan(0);
|
||||
|
||||
RuleFor(c => c.TvCategory).Matches("^[-a-z]*$").WithMessage("Allowed characters a-z and -");
|
||||
RuleFor(c => c.MovieCategory).Matches("^[-a-z]*$").WithMessage("Allowed characters a-z and -");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
Host = "localhost";
|
||||
Port = 8112;
|
||||
Password = "deluge";
|
||||
TvCategory = "movie-radarr";
|
||||
MovieCategory = "movie-radarr";
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
|
||||
@@ -41,15 +41,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
||||
public string Password { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||
public string TvCategory { get; set; }
|
||||
public string MovieCategory { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(DelugePriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
||||
public int RecentTvPriority { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(DelugePriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
|
||||
public int OlderTvPriority { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
|
||||
[FieldDefinition(5, Label = "Use SSL", Type = FieldType.Checkbox)]
|
||||
public bool UseSsl { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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."
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -33,81 +33,35 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, Settings);
|
||||
|
||||
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
|
||||
}
|
||||
|
||||
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
|
||||
}
|
||||
|
||||
return hash;
|
||||
throw new NotImplementedException("Episodes are not working with Radarr");
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, Byte[] fileContent)
|
||||
{
|
||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||
|
||||
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
|
||||
}
|
||||
|
||||
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
|
||||
}
|
||||
|
||||
return hash;
|
||||
throw new NotImplementedException("Episodes are not working with Radarr");
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
|
||||
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, Settings);
|
||||
|
||||
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
|
||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.MovieCategory, Settings);
|
||||
}
|
||||
|
||||
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
|
||||
}*/ //TODO: Maybe reimplement for movies
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteMovie remoteEpisode, string hash, string filename, Byte[] fileContent)
|
||||
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, Byte[] fileContent)
|
||||
{
|
||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||
|
||||
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
|
||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.MovieCategory, Settings);
|
||||
}
|
||||
|
||||
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
|
||||
}*/
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -236,7 +190,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
else if (version < 6)
|
||||
{
|
||||
// API version 6 introduced support for labels
|
||||
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return new NzbDroneValidationFailure("Category", "Category is not supported")
|
||||
{
|
||||
@@ -244,7 +198,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
else if (Settings.MovieCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
// warn if labels are supported, but category is not provided
|
||||
return new NzbDroneValidationFailure("TvCategory", "Category is recommended")
|
||||
|
||||
@@ -58,8 +58,8 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
public List<QBittorrentTorrent> GetTorrents(QBittorrentSettings settings)
|
||||
{
|
||||
var request = BuildRequest(settings).Resource("/query/torrents")
|
||||
.AddQueryParam("label", settings.TvCategory)
|
||||
.AddQueryParam("category", settings.TvCategory);
|
||||
.AddQueryParam("label", settings.MovieCategory)
|
||||
.AddQueryParam("category", settings.MovieCategory);
|
||||
|
||||
var response = ProcessRequest<List<QBittorrentTorrent>>(request, settings);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
{
|
||||
Host = "localhost";
|
||||
Port = 9091;
|
||||
TvCategory = "movie-radarr";
|
||||
MovieCategory = "movie-radarr";
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
|
||||
@@ -38,16 +38,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
public string Password { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||
public string TvCategory { get; set; }
|
||||
public string MovieCategory { get; set; }
|
||||
|
||||
//Todo: update this shit.
|
||||
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
||||
public int RecentTvPriority { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
|
||||
public int OlderTvPriority { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection. See Options -> Web UI -> 'Use HTTPS instead of HTTP' in qBittorrent.")]
|
||||
[FieldDefinition(5, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection. See Options -> Web UI -> 'Use HTTPS instead of HTTP' in qBittorrent.")]
|
||||
public bool UseSsl { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
|
||||
@@ -30,13 +30,13 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
}
|
||||
|
||||
// patch can be a number (releases) or 'x' (git)
|
||||
private static readonly Regex VersionRegex = new Regex(@"(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+|x)(?<candidate>.*)", RegexOptions.Compiled);
|
||||
private static readonly Regex VersionRegex = new Regex(@"(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+|x)", RegexOptions.Compiled);
|
||||
|
||||
protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContents)
|
||||
{
|
||||
var category = Settings.TvCategory;
|
||||
var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
|
||||
|
||||
|
||||
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
|
||||
|
||||
if (response != null && response.Ids.Any())
|
||||
@@ -284,110 +284,103 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
failures.AddIfNotNull(TestCategory());
|
||||
}
|
||||
|
||||
private bool HasVersion(int major, int minor, int patch = 0, string candidate = null)
|
||||
private bool HasVersion(int major, int minor, int patch = 0)
|
||||
{
|
||||
candidate = candidate ?? string.Empty;
|
||||
var rawVersion = _proxy.GetVersion(Settings);
|
||||
var version = ParseVersion(rawVersion);
|
||||
|
||||
var version = _proxy.GetVersion(Settings);
|
||||
if (version == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version.Major > major)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (version.Major < major)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version.Minor > minor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (version.Minor < minor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version.Build > patch)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (version.Build < patch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Version ParseVersion(string version)
|
||||
{
|
||||
var parsed = VersionRegex.Match(version);
|
||||
|
||||
int actualMajor;
|
||||
int actualMinor;
|
||||
int actualPatch;
|
||||
string actualCandidate;
|
||||
int major;
|
||||
int minor;
|
||||
int patch;
|
||||
|
||||
if (!parsed.Success)
|
||||
if (parsed.Success)
|
||||
{
|
||||
major = Convert.ToInt32(parsed.Groups["major"].Value);
|
||||
minor = Convert.ToInt32(parsed.Groups["minor"].Value);
|
||||
patch = Convert.ToInt32(parsed.Groups["patch"].Value.Replace("x", "0"));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (!version.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
actualMajor = 1;
|
||||
actualMinor = 1;
|
||||
actualPatch = 0;
|
||||
actualCandidate = null;
|
||||
major = 1;
|
||||
minor = 1;
|
||||
patch = 0;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
actualMajor = Convert.ToInt32(parsed.Groups["major"].Value);
|
||||
actualMinor = Convert.ToInt32(parsed.Groups["minor"].Value);
|
||||
actualPatch = Convert.ToInt32(parsed.Groups["patch"].Value.Replace("x", ""));
|
||||
actualCandidate = parsed.Groups["candidate"].Value.ToUpper();
|
||||
}
|
||||
|
||||
if (actualMajor > major)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (actualMajor < major)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actualMinor > minor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (actualMinor < minor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actualPatch > patch)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (actualPatch < patch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actualCandidate.IsNullOrWhiteSpace())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (candidate.IsNullOrWhiteSpace())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return actualCandidate.CompareTo(candidate) > 0;
|
||||
}
|
||||
return new Version(major, minor, patch);
|
||||
}
|
||||
|
||||
private ValidationFailure TestConnectionAndVersion()
|
||||
{
|
||||
try
|
||||
{
|
||||
var version = _proxy.GetVersion(Settings);
|
||||
var parsed = VersionRegex.Match(version);
|
||||
var rawVersion = _proxy.GetVersion(Settings);
|
||||
var version = ParseVersion(rawVersion);
|
||||
|
||||
if (!parsed.Success)
|
||||
if (version == null)
|
||||
{
|
||||
if (version.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
|
||||
{
|
||||
IsWarning = true,
|
||||
DetailedDescription = "Sonarr may not be able to support new features added to SABnzbd when running develop versions."
|
||||
};
|
||||
}
|
||||
|
||||
return new ValidationFailure("Version", "Unknown Version: " + version);
|
||||
}
|
||||
|
||||
var major = Convert.ToInt32(parsed.Groups["major"].Value);
|
||||
var minor = Convert.ToInt32(parsed.Groups["minor"].Value);
|
||||
if (rawVersion.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
|
||||
{
|
||||
IsWarning = true,
|
||||
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
|
||||
};
|
||||
}
|
||||
|
||||
if (major >= 1)
|
||||
if (version.Major >= 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (minor >= 7)
|
||||
if (version.Minor >= 7)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -431,7 +424,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 +443,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 +468,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 +482,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 +496,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."
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -54,21 +54,21 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
|
||||
var outputPath = new OsPath(torrent.DownloadDir);
|
||||
|
||||
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
|
||||
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
if (!new OsPath(Settings.TvDirectory).Contains(outputPath)) continue;
|
||||
if (!new OsPath(Settings.MovieDirectory).Contains(outputPath)) continue;
|
||||
}
|
||||
else if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
else if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var directories = outputPath.FullPath.Split('\\', '/');
|
||||
if (!directories.Contains(Settings.TvCategory)) continue;
|
||||
if (!directories.Contains(Settings.MovieCategory)) continue;
|
||||
}
|
||||
|
||||
outputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, outputPath);
|
||||
|
||||
var item = new DownloadClientItem();
|
||||
item.DownloadId = torrent.HashString.ToUpper();
|
||||
item.Category = Settings.TvCategory;
|
||||
item.Category = Settings.MovieCategory;
|
||||
item.Title = torrent.Name;
|
||||
|
||||
item.DownloadClient = Definition.Name;
|
||||
@@ -123,9 +123,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
var destDir = config.GetValueOrDefault("download-dir") as string;
|
||||
|
||||
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
destDir = string.Format("{0}/.{1}", destDir, Settings.TvCategory);
|
||||
destDir = string.Format("{0}/.{1}", destDir, Settings.MovieCategory);
|
||||
}
|
||||
|
||||
return new DownloadClientStatus
|
||||
@@ -137,31 +137,23 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
|
||||
|
||||
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)TransmissionPriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(hash, Settings);
|
||||
}
|
||||
|
||||
return hash;
|
||||
throw new NotImplementedException("Episodes are not working with Radarr");
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
throw new NotImplementedException("Episodes are not working with Radarr");
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
|
||||
|
||||
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)TransmissionPriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(hash, Settings);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -179,16 +171,16 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
|
||||
protected string GetDownloadDirectory()
|
||||
{
|
||||
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
|
||||
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return Settings.TvDirectory;
|
||||
return Settings.MovieDirectory;
|
||||
}
|
||||
else if (Settings.TvCategory.IsNotNullOrWhiteSpace())
|
||||
else if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
var destDir = (string)config.GetValueOrDefault("download-dir");
|
||||
|
||||
return string.Format("{0}/{1}", destDir.TrimEnd('/'), Settings.TvCategory);
|
||||
return string.Format("{0}/{1}", destDir.TrimEnd('/'), Settings.MovieCategory);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -207,7 +199,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)
|
||||
|
||||
@@ -16,10 +16,10 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
|
||||
RuleFor(c => c.UrlBase).ValidUrlBase();
|
||||
|
||||
RuleFor(c => c.TvCategory).Matches(@"^\.?[-a-z]*$", RegexOptions.IgnoreCase).WithMessage("Allowed characters a-z and -");
|
||||
RuleFor(c => c.MovieCategory).Matches(@"^\.?[-a-z]*$", RegexOptions.IgnoreCase).WithMessage("Allowed characters a-z and -");
|
||||
|
||||
RuleFor(c => c.TvCategory).Empty()
|
||||
.When(c => c.TvDirectory.IsNotNullOrWhiteSpace())
|
||||
RuleFor(c => c.MovieCategory).Empty()
|
||||
.When(c => c.MovieDirectory.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Cannot use Category and Directory");
|
||||
}
|
||||
}
|
||||
@@ -50,19 +50,13 @@ 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.")]
|
||||
public string TvCategory { get; set; }
|
||||
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional. Creates a [category] subdirectory in the output directory.")]
|
||||
public string MovieCategory { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default Transmission location")]
|
||||
public string TvDirectory { get; set; }
|
||||
public string MovieDirectory { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing episodes that aired 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")]
|
||||
public int OlderTvPriority { get; set; }
|
||||
|
||||
[FieldDefinition(9, Label = "Use SSL", Type = FieldType.Checkbox)]
|
||||
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
|
||||
public bool UseSsl { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
|
||||
@@ -37,51 +37,23 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
_rTorrentDirectoryValidator = rTorrentDirectoryValidator;
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
||||
{
|
||||
throw new NotImplementedException("Episodes are not working with Radarr");
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
throw new NotImplementedException("Episodes are not working with Radarr");
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, Settings);
|
||||
|
||||
// Download the magnet to the appropriate directory.
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
//SetPriority(remoteEpisode, hash);
|
||||
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
|
||||
SetDownloadDirectory(hash);
|
||||
|
||||
// Once the magnet meta download finishes, rTorrent replaces it with the actual torrent download with default settings.
|
||||
// Schedule an event to apply the appropriate settings when that happens.
|
||||
// var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
|
||||
//_proxy.SetDeferredMagnetProperties(hash, Settings.TvCategory, Settings.TvDirectory, priority, Settings);
|
||||
|
||||
_proxy.StartTorrent(hash, Settings);
|
||||
|
||||
// Wait for the magnet to be resolved.
|
||||
var tries = 10;
|
||||
var retryDelay = 500;
|
||||
if (WaitForTorrent(hash, tries, retryDelay))
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("rTorrent could not resolve magnet within {0} seconds, download may remain stuck: {1}.", tries * retryDelay / 1000, magnetLink);
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, Settings);
|
||||
|
||||
// Download the magnet to the appropriate directory.
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
SetPriority(remoteEpisode, hash);
|
||||
SetDownloadDirectory(hash);
|
||||
|
||||
// Once the magnet meta download finishes, rTorrent replaces it with the actual torrent download with default settings.
|
||||
// Schedule an event to apply the appropriate settings when that happens.
|
||||
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
|
||||
_proxy.SetDeferredMagnetProperties(hash, Settings.TvCategory, Settings.TvDirectory, priority, Settings);
|
||||
|
||||
_proxy.StartTorrent(hash, Settings);
|
||||
|
||||
// Wait for the magnet to be resolved.
|
||||
@@ -107,13 +79,9 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
var retryDelay = 100;
|
||||
if (WaitForTorrent(hash, tries, retryDelay))
|
||||
{
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
|
||||
//SetPriority(remoteEpisode, hash);
|
||||
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
|
||||
SetDownloadDirectory(hash);
|
||||
|
||||
_proxy.StartTorrent(hash, Settings);
|
||||
|
||||
return hash;
|
||||
}
|
||||
else
|
||||
@@ -125,32 +93,6 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
}
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||
|
||||
var tries = 2;
|
||||
var retryDelay = 100;
|
||||
if (WaitForTorrent(hash, tries, retryDelay))
|
||||
{
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
|
||||
SetPriority(remoteEpisode, hash);
|
||||
SetDownloadDirectory(hash);
|
||||
|
||||
_proxy.StartTorrent(hash, Settings);
|
||||
|
||||
return hash;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Debug("rTorrent could not add file");
|
||||
|
||||
RemoveItem(hash, true);
|
||||
throw new ReleaseDownloadException(remoteEpisode.Release, "Downloading torrent failed");
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name => "rTorrent";
|
||||
|
||||
public override ProviderMessage Message => new ProviderMessage("Radarr is unable to remove torrents that have finished seeding when using rTorrent", ProviderMessageType.Warning);
|
||||
@@ -167,7 +109,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
foreach (RTorrentTorrent torrent in torrents)
|
||||
{
|
||||
// Don't concern ourselves with categories other than specified
|
||||
if (torrent.Category != Settings.TvCategory) continue;
|
||||
if (torrent.Category != Settings.MovieCategory) continue;
|
||||
|
||||
if (torrent.Path.StartsWith("."))
|
||||
{
|
||||
@@ -287,17 +229,11 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
return result.Errors.First();
|
||||
}
|
||||
|
||||
private void SetPriority(RemoteEpisode remoteEpisode, string hash)
|
||||
{
|
||||
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
|
||||
_proxy.SetTorrentPriority(hash, priority, Settings);
|
||||
}
|
||||
|
||||
private void SetDownloadDirectory(string hash)
|
||||
{
|
||||
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
|
||||
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
_proxy.SetTorrentDownloadDirectory(hash, Settings.TvDirectory, Settings);
|
||||
_proxy.SetTorrentDownloadDirectory(hash, Settings.MovieDirectory, Settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@ namespace NzbDrone.Core.Download.Clients.rTorrent
|
||||
DroneFactoryValidator droneFactoryValidator,
|
||||
MappedNetworkDriveValidator mappedNetworkDriveValidator)
|
||||
{
|
||||
RuleFor(c => c.TvDirectory).Cascade(CascadeMode.StopOnFirstFailure)
|
||||
RuleFor(c => c.MovieDirectory).Cascade(CascadeMode.StopOnFirstFailure)
|
||||
.IsValidPath()
|
||||
.SetValidator(rootFolderValidator)
|
||||
.SetValidator(droneFactoryValidator)
|
||||
.SetValidator(mappedNetworkDriveValidator)
|
||||
.SetValidator(pathExistsValidator)
|
||||
.When(c => c.TvDirectory.IsNotNullOrWhiteSpace())
|
||||
.When(c => c.MovieDirectory.IsNotNullOrWhiteSpace())
|
||||
.When(c => c.Host == "localhost" || c.Host == "127.0.0.1");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
{
|
||||
RuleFor(c => c.Host).ValidHost();
|
||||
RuleFor(c => c.Port).InclusiveBetween(0, 65535);
|
||||
RuleFor(c => c.TvCategory).NotEmpty()
|
||||
RuleFor(c => c.MovieCategory).NotEmpty()
|
||||
.WithMessage("A category is recommended")
|
||||
.AsWarning();
|
||||
}
|
||||
@@ -26,9 +26,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
||||
Host = "localhost";
|
||||
Port = 8080;
|
||||
UrlBase = "RPC2";
|
||||
TvCategory = "movies-radarr";
|
||||
OlderTvPriority = (int)RTorrentPriority.Normal;
|
||||
RecentTvPriority = (int)RTorrentPriority.Normal;
|
||||
MovieCategory = "movies-radarr";
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
|
||||
@@ -49,17 +47,11 @@ 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.")]
|
||||
public string TvCategory { get; set; }
|
||||
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional.")]
|
||||
public string MovieCategory { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default rTorrent location")]
|
||||
public string TvDirectory { get; set; }
|
||||
|
||||
[FieldDefinition(8, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
||||
public int RecentTvPriority { get; set; }
|
||||
|
||||
[FieldDefinition(9, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
|
||||
public int OlderTvPriority { get; set; }
|
||||
public string MovieDirectory { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
||||
@@ -68,6 +68,38 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, Settings);
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
|
||||
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)UTorrentPriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)UTorrentPriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(hash, Settings);
|
||||
}*/
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteMovie remoteEpisode, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
|
||||
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
if (isRecentEpisode && Settings.RecentTvPriority == (int)UTorrentPriority.First ||
|
||||
!isRecentEpisode && Settings.OlderTvPriority == (int)UTorrentPriority.First)
|
||||
{
|
||||
_proxy.MoveTorrentToTopInQueue(hash, Settings);
|
||||
}*/
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override string Name => "uTorrent";
|
||||
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -94,31 +94,18 @@ namespace NzbDrone.Core.Download
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title);
|
||||
|
||||
if (series == null)
|
||||
var movie = _parsingService.GetMovie(trackedDownload.DownloadItem.Title);
|
||||
if (movie == null)
|
||||
{
|
||||
if (historyItem != null)
|
||||
{
|
||||
//series = _seriesService.GetSeries(historyItem.SeriesId);
|
||||
movie = _movieService.GetMovie(historyItem.MovieId);
|
||||
}
|
||||
|
||||
if (series == null)
|
||||
if (movie == null)
|
||||
{
|
||||
var movie = _parsingService.GetMovie(trackedDownload.DownloadItem.Title);
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
movie = _movieService.GetMovie(historyItem.MovieId);
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
trackedDownload.Warn("Movie title mismatch, automatic import is not possible.");
|
||||
}
|
||||
}
|
||||
//trackedDownload.Warn("Series title mismatch, automatic import is not possible.");
|
||||
//return;
|
||||
trackedDownload.Warn("Movie title mismatch, automatic import is not possible.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,61 +116,30 @@ namespace NzbDrone.Core.Download
|
||||
private void Import(TrackedDownload trackedDownload)
|
||||
{
|
||||
var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath;
|
||||
if (trackedDownload.RemoteMovie.Movie != null)
|
||||
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
|
||||
|
||||
if (importResults.Empty())
|
||||
{
|
||||
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
|
||||
|
||||
if (importResults.Empty())
|
||||
{
|
||||
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= 1)
|
||||
{
|
||||
trackedDownload.State = TrackedDownloadStage.Imported;
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
|
||||
return;
|
||||
}
|
||||
|
||||
if (importResults.Any(c => c.Result != ImportResultType.Imported))
|
||||
{
|
||||
var statusMessages = importResults
|
||||
.Where(v => v.Result != ImportResultType.Imported)
|
||||
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors))
|
||||
.ToArray();
|
||||
|
||||
trackedDownload.Warn(statusMessages);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem);
|
||||
|
||||
if (importResults.Empty())
|
||||
{
|
||||
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count))
|
||||
{
|
||||
trackedDownload.State = TrackedDownloadStage.Imported;
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
|
||||
return;
|
||||
}
|
||||
|
||||
if (importResults.Any(c => c.Result != ImportResultType.Imported))
|
||||
{
|
||||
var statusMessages = importResults
|
||||
.Where(v => v.Result != ImportResultType.Imported)
|
||||
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors))
|
||||
.ToArray();
|
||||
|
||||
trackedDownload.Warn(statusMessages);
|
||||
}
|
||||
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= 1)
|
||||
{
|
||||
trackedDownload.State = TrackedDownloadStage.Imported;
|
||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
|
||||
return;
|
||||
}
|
||||
|
||||
if (importResults.Any(c => c.Result != ImportResultType.Imported))
|
||||
{
|
||||
var statusMessages = importResults
|
||||
.Where(v => v.Result != ImportResultType.Imported)
|
||||
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalMovie.Path), v.Errors))
|
||||
.ToArray();
|
||||
|
||||
trackedDownload.Warn(statusMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -13,8 +13,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
CleanupOrphanedBySeries();
|
||||
CleanupOrphanedByEpisode();
|
||||
//CleanupOrphanedBySeries();
|
||||
//CleanupOrphanedByEpisode();
|
||||
CleanupOrphanedByMovie();
|
||||
}
|
||||
|
||||
private void CleanupOrphanedBySeries()
|
||||
@@ -29,6 +30,18 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
WHERE Series.Id IS NULL)");
|
||||
}
|
||||
|
||||
private void CleanupOrphanedByMovie()
|
||||
{
|
||||
var mapper = _database.GetDataMapper();
|
||||
|
||||
mapper.ExecuteNonQuery(@"DELETE FROM History
|
||||
WHERE Id IN (
|
||||
SELECT History.Id FROM History
|
||||
LEFT OUTER JOIN Movies
|
||||
ON History.MovieId = Movies.Id
|
||||
WHERE Movies.Id IS NULL)");
|
||||
}
|
||||
|
||||
private void CleanupOrphanedByEpisode()
|
||||
{
|
||||
var mapper = _database.GetDataMapper();
|
||||
|
||||
30
src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHD.cs
Normal file
30
src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHD.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.AwesomeHD
|
||||
{
|
||||
public class AwesomeHD : HttpIndexerBase<AwesomeHDSettings>
|
||||
{
|
||||
public override string Name => "AwesomeHD";
|
||||
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
|
||||
public override bool SupportsRss => true;
|
||||
public override bool SupportsSearch => true;
|
||||
public override int PageSize => 50;
|
||||
|
||||
public AwesomeHD(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
||||
: base(httpClient, indexerStatusService, configService, parsingService, logger)
|
||||
{ }
|
||||
|
||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new AwesomeHDRequestGenerator() { Settings = Settings };
|
||||
}
|
||||
|
||||
public override IParseIndexerResponse GetParser()
|
||||
{
|
||||
return new AwesomeHDRssParser(Settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
80
src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDApi.cs
Normal file
80
src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDApi.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using System.Xml.Serialization;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.AwesomeHD
|
||||
{
|
||||
public class Torrent
|
||||
{
|
||||
[XmlElement(ElementName = "id")]
|
||||
public string Id { get; set; }
|
||||
[XmlElement(ElementName = "groupid")]
|
||||
public string GroupId { get; set; }
|
||||
[XmlElement(ElementName = "time")]
|
||||
public DateTime Time { get; set; }
|
||||
[XmlElement(ElementName = "userid")]
|
||||
public string Userid { get; set; }
|
||||
[XmlElement(ElementName = "size")]
|
||||
public long Size { get; set; }
|
||||
[XmlElement(ElementName = "snatched")]
|
||||
public string Snatched { get; set; }
|
||||
[XmlElement(ElementName = "seeders")]
|
||||
public string Seeders { get; set; }
|
||||
[XmlElement(ElementName = "leechers")]
|
||||
public string Leechers { get; set; }
|
||||
[XmlElement(ElementName = "releasegroup")]
|
||||
public string Releasegroup { get; set; }
|
||||
[XmlElement(ElementName = "resolution")]
|
||||
public string Resolution { get; set; }
|
||||
[XmlElement(ElementName = "media")]
|
||||
public string Media { get; set; }
|
||||
[XmlElement(ElementName = "format")]
|
||||
public string Format { get; set; }
|
||||
[XmlElement(ElementName = "encoding")]
|
||||
public string Encoding { get; set; }
|
||||
[XmlElement(ElementName = "audioformat")]
|
||||
public string Audioformat { get; set; }
|
||||
[XmlElement(ElementName = "audiobitrate")]
|
||||
public string Audiobitrate { get; set; }
|
||||
[XmlElement(ElementName = "audiochannels")]
|
||||
public string Audiochannels { get; set; }
|
||||
[XmlElement(ElementName = "subtitles")]
|
||||
public string Subtitles { get; set; }
|
||||
[XmlElement(ElementName = "encodestatus")]
|
||||
public string Encodestatus { get; set; }
|
||||
[XmlElement(ElementName = "freeleech")]
|
||||
public string Freeleech { get; set; }
|
||||
[XmlElement(ElementName = "cover")]
|
||||
public string Cover { get; set; }
|
||||
[XmlElement(ElementName = "smallcover")]
|
||||
public string Smallcover { get; set; }
|
||||
[XmlElement(ElementName = "year")]
|
||||
public string Year { get; set; }
|
||||
[XmlElement(ElementName = "name")]
|
||||
public string Name { get; set; }
|
||||
[XmlElement(ElementName = "imdb")]
|
||||
public string Imdb { get; set; }
|
||||
[XmlElement(ElementName = "type")]
|
||||
public string Type { get; set; }
|
||||
[XmlElement(ElementName = "plotoutline")]
|
||||
public string Plotoutline { get; set; }
|
||||
}
|
||||
|
||||
public class SearchResults
|
||||
{
|
||||
[XmlElement(ElementName = "authkey")]
|
||||
public string AuthKey { get; set; }
|
||||
[XmlElement(ElementName = "torrent")]
|
||||
public List<Torrent> Torrent { get; set; }
|
||||
}
|
||||
|
||||
public class AwesomeHDSearchResponse
|
||||
{
|
||||
[XmlElement(ElementName = "?xml")]
|
||||
public string Xml { get; set; }
|
||||
[XmlElement(ElementName = "searchresults")]
|
||||
public SearchResults SearchResults { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.AwesomeHD
|
||||
{
|
||||
public class AwesomeHDRequestGenerator : IIndexerRequestGenerator
|
||||
{
|
||||
public AwesomeHDSettings Settings { get; set; }
|
||||
|
||||
public virtual IndexerPageableRequestChain GetRecentRequests()
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetRequest(null));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
return new IndexerPageableRequestChain();
|
||||
}
|
||||
|
||||
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
return new IndexerPageableRequestChain();
|
||||
}
|
||||
|
||||
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
return new IndexerPageableRequestChain();
|
||||
}
|
||||
|
||||
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
|
||||
{
|
||||
return new IndexerPageableRequestChain();
|
||||
}
|
||||
|
||||
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
|
||||
{
|
||||
return new IndexerPageableRequestChain();
|
||||
}
|
||||
|
||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||
{
|
||||
var pageableRequests = new IndexerPageableRequestChain();
|
||||
pageableRequests.Add(GetRequest(searchCriteria.Movie.ImdbId));
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
|
||||
{
|
||||
if (searchParameters != null)
|
||||
{
|
||||
yield return new IndexerRequest(string.Format("{0}/searchapi.php?action=imdbsearch&passkey={1}&imdb={2}", Settings.BaseUrl.Trim().TrimEnd('/'), Settings.Passkey.Trim(), searchParameters), HttpAccept.Rss);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new IndexerRequest(string.Format("{0}/searchapi.php?action=latestmovies&passkey={1}", Settings.BaseUrl.Trim().TrimEnd('/'), Settings.Passkey.Trim()), HttpAccept.Rss);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
92
src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDRssParser.cs
Normal file
92
src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDRssParser.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers.Exceptions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.AwesomeHD
|
||||
{
|
||||
public class AwesomeHDRssParser : IParseIndexerResponse
|
||||
{
|
||||
private readonly AwesomeHDSettings _settings;
|
||||
|
||||
public AwesomeHDRssParser(AwesomeHDSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
{
|
||||
var torrentInfos = new List<ReleaseInfo>();
|
||||
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new IndexerException(indexerResponse,
|
||||
"Unexpected response status {0} code from API request",
|
||||
indexerResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
// Hacky ¯\_(ツ)_/¯
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(indexerResponse.Content);
|
||||
|
||||
var json = JsonConvert.SerializeXmlNode(doc);
|
||||
|
||||
Console.WriteLine(json);
|
||||
|
||||
var jsonResponse = JsonConvert.DeserializeObject<AwesomeHDSearchResponse>(json);
|
||||
|
||||
if (jsonResponse == null)
|
||||
{
|
||||
throw new IndexerException(indexerResponse, "Unexpected response from request");
|
||||
}
|
||||
|
||||
foreach (var torrent in jsonResponse.SearchResults.Torrent)
|
||||
{
|
||||
var id = torrent.Id;
|
||||
var title = $"{torrent.Name}.{torrent.Year}.{torrent.Resolution}.{torrent.Media}.{torrent.Encoding}.{torrent.Audioformat}-{torrent.Releasegroup}";
|
||||
|
||||
torrentInfos.Add(new TorrentInfo()
|
||||
{
|
||||
Guid = string.Format("AwesomeHD-{0}", id),
|
||||
Title = title,
|
||||
Size = torrent.Size,
|
||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.SearchResults.AuthKey, _settings.Passkey),
|
||||
InfoUrl = GetInfoUrl(torrent.GroupId, id),
|
||||
Seeders = int.Parse(torrent.Seeders),
|
||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||
PublishDate = torrent.Time.ToUniversalTime()
|
||||
});
|
||||
}
|
||||
|
||||
return torrentInfos.OrderByDescending(o => ((dynamic)o).Seeders).ToArray();
|
||||
}
|
||||
|
||||
private string GetDownloadUrl(string torrentId, string authKey, string passKey)
|
||||
{
|
||||
var url = new HttpUri(_settings.BaseUrl)
|
||||
.CombinePath("/torrents.php")
|
||||
.AddQueryParam("action", "download")
|
||||
.AddQueryParam("id", torrentId)
|
||||
.AddQueryParam("authkey", authKey)
|
||||
.AddQueryParam("torrent_pass", passKey);
|
||||
|
||||
return url.FullUri;
|
||||
}
|
||||
|
||||
private string GetInfoUrl(string groupId, string torrentId)
|
||||
{
|
||||
var url = new HttpUri(_settings.BaseUrl)
|
||||
.CombinePath("/torrents.php")
|
||||
.AddQueryParam("id", groupId)
|
||||
.AddQueryParam("torrentid", torrentId);
|
||||
|
||||
return url.FullUri;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDSettings.cs
Normal file
37
src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHDSettings.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.AwesomeHD
|
||||
{
|
||||
public class AwesomeHDSettingsValidator : AbstractValidator<AwesomeHDSettings>
|
||||
{
|
||||
public AwesomeHDSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.BaseUrl).ValidRootUrl();
|
||||
RuleFor(c => c.Passkey).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class AwesomeHDSettings : IProviderConfig
|
||||
{
|
||||
private static readonly AwesomeHDSettingsValidator Validator = new AwesomeHDSettingsValidator();
|
||||
|
||||
public AwesomeHDSettings()
|
||||
{
|
||||
BaseUrl = "https://awesome-hd.me";
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since you Passkey will be sent to that host.")]
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "Passkey")]
|
||||
public string Passkey { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,14 +39,15 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return GetDefinition("Dognzb.cr", GetSettings("https://api.dognzb.cr"));
|
||||
yield return GetDefinition("DOGnzb", GetSettings("https://api.dognzb.cr"));
|
||||
yield return GetDefinition("DrunkenSlug", GetSettings("https://api.drunkenslug.com"));
|
||||
yield return GetDefinition("Nzb-Tortuga", GetSettings("https://www.nzb-tortuga.com"));
|
||||
yield return GetDefinition("Nzb.su", GetSettings("https://api.nzb.su"));
|
||||
yield return GetDefinition("NZBCat", GetSettings("https://nzb.cat"));
|
||||
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws", 5010, 5030, 5040, 5045));
|
||||
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws"));
|
||||
yield return GetDefinition("NZBgeek", GetSettings("https://api.nzbgeek.info"));
|
||||
yield return GetDefinition("nzbplanet.net", GetSettings("https://api.nzbplanet.net"));
|
||||
yield return GetDefinition("Nzbs.org", GetSettings("http://nzbs.org", 2000));
|
||||
yield return GetDefinition("Nzbs.org", GetSettings("http://nzbs.org"));
|
||||
yield return GetDefinition("OZnzb.com", GetSettings("https://api.oznzb.com"));
|
||||
yield return GetDefinition("PFmonkey", GetSettings("https://www.pfmonkey.com"));
|
||||
yield return GetDefinition("SimplyNZBs", GetSettings("https://simplynzbs.com"));
|
||||
@@ -106,8 +107,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;
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,7 +112,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
|
||||
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||
|
||||
if (capabilities.SupportedMovieSearchParamters != null)
|
||||
if (capabilities.SupportedMovieSearchParameters != null)
|
||||
{
|
||||
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories.Concat(Settings.AnimeCategories), "movie", ""));
|
||||
}
|
||||
@@ -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
|
||||
@@ -133,7 +133,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
{
|
||||
//Let's try anyways with q parameter, worst case nothing found.
|
||||
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "search",
|
||||
string.Format("&q={0}", searchCriteria.Movie.Title)));
|
||||
string.Format("&q={0}", Parser.Parser.NormalizeTitle(searchCriteria.Movie.Title))));
|
||||
}
|
||||
|
||||
return pageableRequests;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
|
||||
public NewznabSettings()
|
||||
{
|
||||
Categories = new[] { 2030, 2040, 2050 };
|
||||
Categories = new[] { 2000, 2010, 2020, 2030, 2035, 2040, 2045, 2050, 2060 };
|
||||
AnimeCategories = Enumerable.Empty<int>();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
|
||||
protected override string GetInfoUrl(XElement item)
|
||||
{
|
||||
//Todo: Me thinks I need to parse details to get this...
|
||||
var match = Regex.Match(item.Description(), @"(?:\<b\>View NZB\:\<\/b\>\s\<a\shref\=\"")(?<URL>.+)(?:\""\starget)",
|
||||
var match = Regex.Match(item.Description(), @"(?:\<b\>View NZB\:\<\/b\>\s\<a\shref\=\"")(?<URL>.+)(?:\"")",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
if (match.Success)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Common.Http;
|
||||
@@ -36,11 +37,11 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
|
||||
torrentInfo.Size = (long)torrent.size*1000*1000;
|
||||
torrentInfo.DownloadUrl = torrent.download_url;
|
||||
torrentInfo.InfoUrl = torrent.details_url;
|
||||
torrentInfo.PublishDate = new System.DateTime();
|
||||
torrentInfo.PublishDate = torrent.publish_date.ToUniversalTime();
|
||||
torrentInfo.Seeders = torrent.seeders;
|
||||
torrentInfo.Peers = torrent.leechers + torrent.seeders;
|
||||
torrentInfo.Freeleech = torrent.freeleech;
|
||||
|
||||
|
||||
results.Add(torrentInfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,9 +78,16 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
|
||||
.Accept(HttpAccept.Json);
|
||||
|
||||
requestBuilder.AddQueryParam("passkey", Settings.Passkey);
|
||||
requestBuilder.AddQueryParam("user", Settings.User);
|
||||
// requestBuilder.AddQueryParam("imdbid", "tt0076759"); //For now just search for Star Wars.
|
||||
requestBuilder.AddQueryParam("search", "the"); // there has to be movies with 'the' in the title on any indexer
|
||||
if (!string.IsNullOrWhiteSpace(Settings.User))
|
||||
{
|
||||
requestBuilder.AddQueryParam("user", Settings.User);
|
||||
}
|
||||
else
|
||||
{
|
||||
requestBuilder.AddQueryParam("user", "");
|
||||
}
|
||||
|
||||
requestBuilder.AddQueryParam("search", "the");
|
||||
|
||||
yield return new IndexerRequest(requestBuilder.Build());
|
||||
}
|
||||
@@ -91,7 +98,15 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
|
||||
.Accept(HttpAccept.Json);
|
||||
|
||||
requestBuilder.AddQueryParam("passkey", Settings.Passkey);
|
||||
requestBuilder.AddQueryParam("user", Settings.User);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Settings.User))
|
||||
{
|
||||
requestBuilder.AddQueryParam("user", Settings.User);
|
||||
}
|
||||
else
|
||||
{
|
||||
requestBuilder.AddQueryParam("user", "");
|
||||
}
|
||||
|
||||
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
|
||||
public int size { get; set; }
|
||||
public int leechers { get; set; }
|
||||
public int seeders { get; set; }
|
||||
public DateTime publish_date { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
|
||||
|
||||
public TorrentPotatoSettings()
|
||||
{
|
||||
BaseUrl = "";
|
||||
BaseUrl = "http://127.0.0.1";
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "API URL", HelpText = "URL to TorrentPotato api.")]
|
||||
|
||||
@@ -97,8 +97,7 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
}
|
||||
|
||||
if (capabilities.SupportedTvSearchParameters != null &&
|
||||
new[] { "q", "tvdbid", "rid" }.Any(v => capabilities.SupportedTvSearchParameters.Contains(v)) &&
|
||||
new[] { "season", "ep" }.All(v => capabilities.SupportedTvSearchParameters.Contains(v)))
|
||||
new[] { "q", "imdbid" }.Any(v => capabilities.SupportedTvSearchParameters.Contains(v)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -39,10 +39,13 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInfo)
|
||||
{
|
||||
var torrentInfo = base.ProcessItem(item, releaseInfo) as TorrentInfo;
|
||||
|
||||
torrentInfo.TvdbId = GetTvdbId(item);
|
||||
torrentInfo.TvRageId = GetTvRageId(item);
|
||||
|
||||
if (GetImdbId(item) != null)
|
||||
{
|
||||
if (torrentInfo != null)
|
||||
{
|
||||
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
|
||||
}
|
||||
}
|
||||
return torrentInfo;
|
||||
}
|
||||
|
||||
@@ -100,31 +103,12 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
return url;
|
||||
}
|
||||
|
||||
protected virtual int GetTvdbId(XElement item)
|
||||
protected virtual string GetImdbId(XElement item)
|
||||
{
|
||||
var tvdbIdString = TryGetTorznabAttribute(item, "tvdbid");
|
||||
int tvdbId;
|
||||
|
||||
if (!tvdbIdString.IsNullOrWhiteSpace() && int.TryParse(tvdbIdString, out tvdbId))
|
||||
{
|
||||
return tvdbId;
|
||||
}
|
||||
|
||||
return 0;
|
||||
var imdbIdString = TryGetTorznabAttribute(item, "imdbid");
|
||||
return (!imdbIdString.IsNullOrWhiteSpace() ? imdbIdString.Substring(2) : null);
|
||||
}
|
||||
|
||||
protected virtual int GetTvRageId(XElement item)
|
||||
{
|
||||
var tvRageIdString = TryGetTorznabAttribute(item, "rageid");
|
||||
int tvRageId;
|
||||
|
||||
if (!tvRageIdString.IsNullOrWhiteSpace() && int.TryParse(tvRageIdString, out tvRageId))
|
||||
{
|
||||
return tvRageId;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
protected override string GetInfoHash(XElement item)
|
||||
{
|
||||
return TryGetTorznabAttribute(item, "infohash");
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Indexers.Wombles
|
||||
|
||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new RssIndexerRequestGenerator("http://newshost.co.za/rss/?sec=TV&fr=false");
|
||||
return new RssIndexerRequestGenerator("http://newshost.co.za/rss/?sec=Movies&fr=false");
|
||||
}
|
||||
|
||||
public Wombles(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace NzbDrone.Core.Jobs
|
||||
new ScheduledTask{ Interval = 6*60, TypeName = typeof(ApplicationUpdateCommand).FullName},
|
||||
new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
|
||||
new ScheduledTask{ Interval = 6*60, TypeName = typeof(CheckHealthCommand).FullName},
|
||||
new ScheduledTask{ Interval = 12*60, TypeName = typeof(RefreshSeriesCommand).FullName},
|
||||
new ScheduledTask{ Interval = 24*60, TypeName = typeof(RefreshMovieCommand).FullName},
|
||||
new ScheduledTask{ Interval = 24*60, TypeName = typeof(HousekeepingCommand).FullName},
|
||||
new ScheduledTask{ Interval = 7*24*60, TypeName = typeof(BackupCommand).FullName},
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Commands
|
||||
{
|
||||
public class DownloadedMovieScanCommand : Command
|
||||
{
|
||||
public override bool SendUpdatesToClient => SendUpdates;
|
||||
|
||||
public bool SendUpdates { get; set; }
|
||||
|
||||
// Properties used by third-party apps, do not modify.
|
||||
public string Path { get; set; }
|
||||
public string DownloadClientId { get; set; }
|
||||
public ImportMode ImportMode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -178,7 +178,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
_mediaFileTableCleanupService.Clean(movie, mediaFileList);
|
||||
|
||||
var decisionsStopwatch = Stopwatch.StartNew();
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie);
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie, true);
|
||||
decisionsStopwatch.Stop();
|
||||
_logger.Trace("Import decisions complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed);
|
||||
|
||||
|
||||
@@ -1,265 +1,107 @@
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.MediaFiles.Commands;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface IDownloadedMovieImportService
|
||||
{
|
||||
List<ImportResult> ProcessRootFolder(DirectoryInfo directoryInfo);
|
||||
List<ImportResult> ProcessPath(string path, ImportMode importMode = ImportMode.Auto, Movie movie = null, DownloadClientItem downloadClientItem = null);
|
||||
bool ShouldDeleteFolder(DirectoryInfo directoryInfo, Movie movie);
|
||||
}
|
||||
|
||||
public class DownloadedMovieImportService : IDownloadedMovieImportService
|
||||
public class DownloadedMovieCommandService : IExecute<DownloadedMovieScanCommand>
|
||||
{
|
||||
private readonly IDownloadedMovieImportService _downloadedMovieImportService;
|
||||
private readonly ITrackedDownloadService _trackedDownloadService;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
private readonly IMovieService _movieService;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly IMakeImportDecision _importDecisionMaker;
|
||||
private readonly IImportApprovedMovie _importApprovedMovie;
|
||||
private readonly IDetectSample _detectSample;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public DownloadedMovieImportService(IDiskProvider diskProvider,
|
||||
IDiskScanService diskScanService,
|
||||
IMovieService movieService,
|
||||
IParsingService parsingService,
|
||||
IMakeImportDecision importDecisionMaker,
|
||||
IImportApprovedMovie importApprovedMovie,
|
||||
IDetectSample detectSample,
|
||||
Logger logger)
|
||||
public DownloadedMovieCommandService(IDownloadedMovieImportService downloadedMovieImportService,
|
||||
ITrackedDownloadService trackedDownloadService,
|
||||
IDiskProvider diskProvider,
|
||||
IConfigService configService,
|
||||
Logger logger)
|
||||
{
|
||||
_downloadedMovieImportService = downloadedMovieImportService;
|
||||
_trackedDownloadService = trackedDownloadService;
|
||||
_diskProvider = diskProvider;
|
||||
_diskScanService = diskScanService;
|
||||
_movieService = movieService;
|
||||
_parsingService = parsingService;
|
||||
_importDecisionMaker = importDecisionMaker;
|
||||
_importApprovedMovie = importApprovedMovie;
|
||||
_detectSample = detectSample;
|
||||
_configService = configService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<ImportResult> ProcessRootFolder(DirectoryInfo directoryInfo)
|
||||
private List<ImportResult> ProcessDroneFactoryFolder()
|
||||
{
|
||||
var results = new List<ImportResult>();
|
||||
var downloadedEpisodesFolder = _configService.DownloadedEpisodesFolder;
|
||||
|
||||
foreach (var subFolder in _diskProvider.GetDirectories(directoryInfo.FullName))
|
||||
if (string.IsNullOrEmpty(downloadedEpisodesFolder))
|
||||
{
|
||||
var folderResults = ProcessFolder(new DirectoryInfo(subFolder), ImportMode.Auto, null);
|
||||
results.AddRange(folderResults);
|
||||
}
|
||||
|
||||
foreach (var videoFile in _diskScanService.GetVideoFiles(directoryInfo.FullName, false))
|
||||
{
|
||||
var fileResults = ProcessFile(new FileInfo(videoFile), ImportMode.Auto, null);
|
||||
results.AddRange(fileResults);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<ImportResult> ProcessPath(string path, ImportMode importMode = ImportMode.Auto, Movie movie = null, DownloadClientItem downloadClientItem = null)
|
||||
{
|
||||
if (_diskProvider.FolderExists(path))
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(path);
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
return ProcessFolder(directoryInfo, importMode, downloadClientItem);
|
||||
}
|
||||
|
||||
return ProcessFolder(directoryInfo, importMode, movie, downloadClientItem);
|
||||
}
|
||||
|
||||
if (_diskProvider.FileExists(path))
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
return ProcessFile(fileInfo, importMode, downloadClientItem);
|
||||
}
|
||||
|
||||
return ProcessFile(fileInfo, importMode, movie, downloadClientItem);
|
||||
}
|
||||
|
||||
_logger.Error("Import failed, path does not exist or is not accessible by Sonarr: {0}", path);
|
||||
return new List<ImportResult>();
|
||||
}
|
||||
|
||||
public bool ShouldDeleteFolder(DirectoryInfo directoryInfo, Movie movie)
|
||||
{
|
||||
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
||||
var rarFiles = _diskProvider.GetFiles(directoryInfo.FullName, SearchOption.AllDirectories).Where(f => Path.GetExtension(f) == ".rar");
|
||||
|
||||
foreach (var videoFile in videoFiles)
|
||||
{
|
||||
var episodeParseResult = Parser.Parser.ParseTitle(Path.GetFileName(videoFile));
|
||||
|
||||
if (episodeParseResult == null)
|
||||
{
|
||||
_logger.Warn("Unable to parse file on import: [{0}]", videoFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
var size = _diskProvider.GetFileSize(videoFile);
|
||||
var quality = QualityParser.ParseQuality(videoFile);
|
||||
|
||||
if (!_detectSample.IsSample(movie, quality, videoFile, size, episodeParseResult.IsPossibleSpecialEpisode))
|
||||
{
|
||||
_logger.Warn("Non-sample file detected: [{0}]", videoFile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (rarFiles.Any(f => _diskProvider.GetFileSize(f) > 10.Megabytes()))
|
||||
{
|
||||
_logger.Warn("RAR file detected, will require manual cleanup");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode importMode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
||||
var movie = _parsingService.GetMovie(cleanedUpName);
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
_logger.Debug("Unknown Movie {0}", cleanedUpName);
|
||||
|
||||
return new List<ImportResult>
|
||||
{
|
||||
UnknownMovieResult("Unknown Movie")
|
||||
};
|
||||
}
|
||||
|
||||
return ProcessFolder(directoryInfo, importMode, movie, downloadClientItem);
|
||||
}
|
||||
|
||||
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode importMode, Movie movie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (_movieService.MoviePathExists(directoryInfo.FullName))
|
||||
{
|
||||
_logger.Warn("Unable to process folder that is mapped to an existing show");
|
||||
_logger.Trace("Drone Factory folder is not configured");
|
||||
return new List<ImportResult>();
|
||||
}
|
||||
|
||||
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
||||
var folderInfo = Parser.Parser.ParseMovieTitle(directoryInfo.Name);
|
||||
|
||||
if (folderInfo != null)
|
||||
if (!_diskProvider.FolderExists(downloadedEpisodesFolder))
|
||||
{
|
||||
_logger.Debug("{0} folder quality: {1}", cleanedUpName, folderInfo.Quality);
|
||||
_logger.Warn("Drone Factory folder [{0}] doesn't exist.", downloadedEpisodesFolder);
|
||||
return new List<ImportResult>();
|
||||
}
|
||||
|
||||
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
||||
return _downloadedMovieImportService.ProcessRootFolder(new DirectoryInfo(downloadedEpisodesFolder));
|
||||
}
|
||||
|
||||
if (downloadClientItem == null)
|
||||
private List<ImportResult> ProcessPath(DownloadedMovieScanCommand message)
|
||||
{
|
||||
if (!_diskProvider.FolderExists(message.Path) && !_diskProvider.FileExists(message.Path))
|
||||
{
|
||||
foreach (var videoFile in videoFiles)
|
||||
_logger.Warn("Folder/File specified for import scan [{0}] doesn't exist.", message.Path);
|
||||
return new List<ImportResult>();
|
||||
}
|
||||
|
||||
if (message.DownloadClientId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var trackedDownload = _trackedDownloadService.Find(message.DownloadClientId);
|
||||
|
||||
if (trackedDownload != null)
|
||||
{
|
||||
if (_diskProvider.IsFileLocked(videoFile))
|
||||
{
|
||||
return new List<ImportResult>
|
||||
{
|
||||
FileIsLockedResult(videoFile)
|
||||
};
|
||||
}
|
||||
_logger.Debug("External directory scan request for known download {0}. [{1}]", message.DownloadClientId, message.Path);
|
||||
|
||||
return _downloadedMovieImportService.ProcessPath(message.Path, message.ImportMode, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("External directory scan request for unknown download {0}, attempting normal import. [{1}]", message.DownloadClientId, message.Path);
|
||||
|
||||
return _downloadedMovieImportService.ProcessPath(message.Path, message.ImportMode);
|
||||
}
|
||||
}
|
||||
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true);
|
||||
var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
||||
return _downloadedMovieImportService.ProcessPath(message.Path, message.ImportMode);
|
||||
}
|
||||
|
||||
if ((downloadClientItem == null || !downloadClientItem.IsReadOnly) &&
|
||||
importResults.Any(i => i.Result == ImportResultType.Imported) &&
|
||||
ShouldDeleteFolder(directoryInfo, movie))
|
||||
public void Execute(DownloadedMovieScanCommand message)
|
||||
{
|
||||
List<ImportResult> importResults;
|
||||
|
||||
if (message.Path.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
_logger.Debug("Deleting folder after importing valid files");
|
||||
_diskProvider.DeleteFolder(directoryInfo.FullName, true);
|
||||
importResults = ProcessPath(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
importResults = ProcessDroneFactoryFolder();
|
||||
}
|
||||
|
||||
return importResults;
|
||||
}
|
||||
|
||||
private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
var movie = _parsingService.GetMovie(Path.GetFileNameWithoutExtension(fileInfo.Name));
|
||||
|
||||
if (movie == null)
|
||||
if (importResults == null || importResults.All(v => v.Result != ImportResultType.Imported))
|
||||
{
|
||||
_logger.Debug("Unknown Movie for file: {0}", fileInfo.Name);
|
||||
|
||||
return new List<ImportResult>
|
||||
{
|
||||
UnknownMovieResult(string.Format("Unknown Movie for file: {0}", fileInfo.Name), fileInfo.FullName)
|
||||
};
|
||||
// Atm we don't report it as a command failure, coz that would cause the download to be failed.
|
||||
// Changing the message won't do a thing either, coz it will get set to 'Completed' a msec later.
|
||||
//message.SetMessage("Failed to import");
|
||||
}
|
||||
|
||||
return ProcessFile(fileInfo, importMode, movie, downloadClientItem);
|
||||
}
|
||||
|
||||
private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode, Movie movie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (Path.GetFileNameWithoutExtension(fileInfo.Name).StartsWith("._"))
|
||||
{
|
||||
_logger.Debug("[{0}] starts with '._', skipping", fileInfo.FullName);
|
||||
|
||||
return new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalEpisode { Path = fileInfo.FullName }, new Rejection("Invalid video file, filename starts with '._'")), "Invalid video file, filename starts with '._'")
|
||||
};
|
||||
}
|
||||
|
||||
if (downloadClientItem == null)
|
||||
{
|
||||
if (_diskProvider.IsFileLocked(fileInfo.FullName))
|
||||
{
|
||||
return new List<ImportResult>
|
||||
{
|
||||
FileIsLockedResult(fileInfo.FullName)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true);
|
||||
|
||||
return _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
||||
}
|
||||
|
||||
private string GetCleanedUpFolderName(string folder)
|
||||
{
|
||||
folder = folder.Replace("_UNPACK_", "")
|
||||
.Replace("_FAILED_", "");
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
private ImportResult FileIsLockedResult(string videoFile)
|
||||
{
|
||||
_logger.Debug("[{0}] is currently locked by another process, skipping", videoFile);
|
||||
return new ImportResult(new ImportDecision(new LocalEpisode { Path = videoFile }, new Rejection("Locked file, try again later")), "Locked file, try again later");
|
||||
}
|
||||
|
||||
private ImportResult UnknownMovieResult(string message, string videoFile = null)
|
||||
{
|
||||
var localEpisode = videoFile == null ? null : new LocalEpisode { Path = videoFile };
|
||||
|
||||
return new ImportResult(new ImportDecision(localEpisode, new Rejection("Unknown Movie")), message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
266
src/NzbDrone.Core/MediaFiles/DownloadedMovieImportService.cs
Normal file
266
src/NzbDrone.Core/MediaFiles/DownloadedMovieImportService.cs
Normal file
@@ -0,0 +1,266 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.MediaFiles.Commands;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
public interface IDownloadedMovieImportService
|
||||
{
|
||||
List<ImportResult> ProcessRootFolder(DirectoryInfo directoryInfo);
|
||||
List<ImportResult> ProcessPath(string path, ImportMode importMode = ImportMode.Auto, Movie movie = null, DownloadClientItem downloadClientItem = null);
|
||||
bool ShouldDeleteFolder(DirectoryInfo directoryInfo, Movie movie);
|
||||
}
|
||||
|
||||
public class DownloadedMovieImportService : IDownloadedMovieImportService
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IDiskScanService _diskScanService;
|
||||
private readonly IMovieService _movieService;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly IMakeImportDecision _importDecisionMaker;
|
||||
private readonly IImportApprovedMovie _importApprovedMovie;
|
||||
private readonly IDetectSample _detectSample;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public DownloadedMovieImportService(IDiskProvider diskProvider,
|
||||
IDiskScanService diskScanService,
|
||||
IMovieService movieService,
|
||||
IParsingService parsingService,
|
||||
IMakeImportDecision importDecisionMaker,
|
||||
IImportApprovedMovie importApprovedMovie,
|
||||
IDetectSample detectSample,
|
||||
Logger logger)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_diskScanService = diskScanService;
|
||||
_movieService = movieService;
|
||||
_parsingService = parsingService;
|
||||
_importDecisionMaker = importDecisionMaker;
|
||||
_importApprovedMovie = importApprovedMovie;
|
||||
_detectSample = detectSample;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public List<ImportResult> ProcessRootFolder(DirectoryInfo directoryInfo)
|
||||
{
|
||||
var results = new List<ImportResult>();
|
||||
|
||||
foreach (var subFolder in _diskProvider.GetDirectories(directoryInfo.FullName))
|
||||
{
|
||||
var folderResults = ProcessFolder(new DirectoryInfo(subFolder), ImportMode.Auto, null);
|
||||
results.AddRange(folderResults);
|
||||
}
|
||||
|
||||
foreach (var videoFile in _diskScanService.GetVideoFiles(directoryInfo.FullName, false))
|
||||
{
|
||||
var fileResults = ProcessFile(new FileInfo(videoFile), ImportMode.Auto, null);
|
||||
results.AddRange(fileResults);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<ImportResult> ProcessPath(string path, ImportMode importMode = ImportMode.Auto, Movie movie = null, DownloadClientItem downloadClientItem = null)
|
||||
{
|
||||
if (_diskProvider.FolderExists(path))
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(path);
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
return ProcessFolder(directoryInfo, importMode, downloadClientItem);
|
||||
}
|
||||
|
||||
return ProcessFolder(directoryInfo, importMode, movie, downloadClientItem);
|
||||
}
|
||||
|
||||
if (_diskProvider.FileExists(path))
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
return ProcessFile(fileInfo, importMode, downloadClientItem);
|
||||
}
|
||||
|
||||
return ProcessFile(fileInfo, importMode, movie, downloadClientItem);
|
||||
}
|
||||
|
||||
_logger.Error("Import failed, path does not exist or is not accessible by Radarr: {0}", path);
|
||||
return new List<ImportResult>();
|
||||
}
|
||||
|
||||
public bool ShouldDeleteFolder(DirectoryInfo directoryInfo, Movie movie)
|
||||
{
|
||||
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
||||
var rarFiles = _diskProvider.GetFiles(directoryInfo.FullName, SearchOption.AllDirectories).Where(f => Path.GetExtension(f) == ".rar");
|
||||
|
||||
foreach (var videoFile in videoFiles)
|
||||
{
|
||||
var episodeParseResult = Parser.Parser.ParseTitle(Path.GetFileName(videoFile));
|
||||
|
||||
if (episodeParseResult == null)
|
||||
{
|
||||
_logger.Warn("Unable to parse file on import: [{0}]", videoFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
var size = _diskProvider.GetFileSize(videoFile);
|
||||
var quality = QualityParser.ParseQuality(videoFile);
|
||||
|
||||
if (!_detectSample.IsSample(movie, quality, videoFile, size, episodeParseResult.IsPossibleSpecialEpisode))
|
||||
{
|
||||
_logger.Warn("Non-sample file detected: [{0}]", videoFile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (rarFiles.Any(f => _diskProvider.GetFileSize(f) > 10.Megabytes()))
|
||||
{
|
||||
_logger.Warn("RAR file detected, will require manual cleanup");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode importMode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
||||
var movie = _parsingService.GetMovie(cleanedUpName);
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
_logger.Debug("Unknown Movie {0}", cleanedUpName);
|
||||
|
||||
return new List<ImportResult>
|
||||
{
|
||||
UnknownMovieResult("Unknown Movie")
|
||||
};
|
||||
}
|
||||
|
||||
return ProcessFolder(directoryInfo, importMode, movie, downloadClientItem);
|
||||
}
|
||||
|
||||
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode importMode, Movie movie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (_movieService.MoviePathExists(directoryInfo.FullName))
|
||||
{
|
||||
_logger.Warn("Unable to process folder that is mapped to an existing show");
|
||||
return new List<ImportResult>();
|
||||
}
|
||||
|
||||
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
||||
var folderInfo = Parser.Parser.ParseMovieTitle(directoryInfo.Name);
|
||||
|
||||
if (folderInfo != null)
|
||||
{
|
||||
_logger.Debug("{0} folder quality: {1}", cleanedUpName, folderInfo.Quality);
|
||||
}
|
||||
|
||||
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
||||
|
||||
if (downloadClientItem == null)
|
||||
{
|
||||
foreach (var videoFile in videoFiles)
|
||||
{
|
||||
if (_diskProvider.IsFileLocked(videoFile))
|
||||
{
|
||||
return new List<ImportResult>
|
||||
{
|
||||
FileIsLockedResult(videoFile)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true, false);
|
||||
var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
||||
|
||||
if ((downloadClientItem == null || !downloadClientItem.IsReadOnly) &&
|
||||
importResults.Any(i => i.Result == ImportResultType.Imported) &&
|
||||
ShouldDeleteFolder(directoryInfo, movie))
|
||||
{
|
||||
_logger.Debug("Deleting folder after importing valid files");
|
||||
_diskProvider.DeleteFolder(directoryInfo.FullName, true);
|
||||
}
|
||||
|
||||
return importResults;
|
||||
}
|
||||
|
||||
private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
var movie = _parsingService.GetMovie(Path.GetFileNameWithoutExtension(fileInfo.Name));
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
_logger.Debug("Unknown Movie for file: {0}", fileInfo.Name);
|
||||
|
||||
return new List<ImportResult>
|
||||
{
|
||||
UnknownMovieResult(string.Format("Unknown Movie for file: {0}", fileInfo.Name), fileInfo.FullName)
|
||||
};
|
||||
}
|
||||
|
||||
return ProcessFile(fileInfo, importMode, movie, downloadClientItem);
|
||||
}
|
||||
|
||||
private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode, Movie movie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (Path.GetFileNameWithoutExtension(fileInfo.Name).StartsWith("._"))
|
||||
{
|
||||
_logger.Debug("[{0}] starts with '._', skipping", fileInfo.FullName);
|
||||
|
||||
return new List<ImportResult>
|
||||
{
|
||||
new ImportResult(new ImportDecision(new LocalEpisode { Path = fileInfo.FullName }, new Rejection("Invalid video file, filename starts with '._'")), "Invalid video file, filename starts with '._'")
|
||||
};
|
||||
}
|
||||
|
||||
if (downloadClientItem == null)
|
||||
{
|
||||
if (_diskProvider.IsFileLocked(fileInfo.FullName))
|
||||
{
|
||||
return new List<ImportResult>
|
||||
{
|
||||
FileIsLockedResult(fileInfo.FullName)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true, false);
|
||||
|
||||
return _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
||||
}
|
||||
|
||||
private string GetCleanedUpFolderName(string folder)
|
||||
{
|
||||
folder = folder.Replace("_UNPACK_", "")
|
||||
.Replace("_FAILED_", "");
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
private ImportResult FileIsLockedResult(string videoFile)
|
||||
{
|
||||
_logger.Debug("[{0}] is currently locked by another process, skipping", videoFile);
|
||||
return new ImportResult(new ImportDecision(new LocalEpisode { Path = videoFile }, new Rejection("Locked file, try again later")), "Locked file, try again later");
|
||||
}
|
||||
|
||||
private ImportResult UnknownMovieResult(string message, string videoFile = null)
|
||||
{
|
||||
var localEpisode = videoFile == null ? null : new LocalEpisode { Path = videoFile };
|
||||
|
||||
return new ImportResult(new ImportDecision(localEpisode, new Rejection("Unknown Movie")), message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
|
||||
private int GetMinimumAllowedRuntime(Movie movie)
|
||||
{
|
||||
return 120; //2 minutes
|
||||
return 360; //6 minutes
|
||||
}
|
||||
|
||||
private int GetMinimumAllowedRuntime(Series series)
|
||||
|
||||
@@ -83,6 +83,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
episodeFile.MediaInfo = localMovie.MediaInfo;
|
||||
episodeFile.Movie = localMovie.Movie;
|
||||
episodeFile.ReleaseGroup = localMovie.ParsedMovieInfo.ReleaseGroup;
|
||||
episodeFile.Edition = localMovie.ParsedMovieInfo.Edition;
|
||||
|
||||
bool copyOnly;
|
||||
switch (importMode)
|
||||
|
||||
@@ -19,7 +19,8 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
{
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource); //TODO: Needs changing to ParsedMovieInfo!!
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, bool shouldCheckQuality);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality); //TODO: Needs changing to ParsedMovieInfo!!
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource);
|
||||
}
|
||||
|
||||
@@ -31,6 +32,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IVideoFileInfoReader _videoFileInfoReader;
|
||||
private readonly IDetectSample _detectSample;
|
||||
private readonly IQualityDefinitionService _qualitiesService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public ImportDecisionMaker(IEnumerable<IImportDecisionEngineSpecification> specifications,
|
||||
@@ -39,6 +41,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
IDiskProvider diskProvider,
|
||||
IVideoFileInfoReader videoFileInfoReader,
|
||||
IDetectSample detectSample,
|
||||
IQualityDefinitionService qualitiesService,
|
||||
Logger logger)
|
||||
{
|
||||
_specifications = specifications;
|
||||
@@ -47,6 +50,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
_diskProvider = diskProvider;
|
||||
_videoFileInfoReader = videoFileInfoReader;
|
||||
_detectSample = detectSample;
|
||||
_qualitiesService = qualitiesService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -57,7 +61,12 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie)
|
||||
{
|
||||
return GetImportDecisions(videoFiles, movie, null, false);
|
||||
return GetImportDecisions(videoFiles, movie, null, true, false);
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, bool shouldCheckQuality = false)
|
||||
{
|
||||
return GetImportDecisions(videoFiles, movie, null, true, shouldCheckQuality);
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource)
|
||||
@@ -77,7 +86,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
return decisions;
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource)
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality = false)
|
||||
{
|
||||
var newFiles = _mediaFileService.FilterExistingFiles(videoFiles.ToList(), movie);
|
||||
|
||||
@@ -88,13 +97,13 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
|
||||
foreach (var file in newFiles)
|
||||
{
|
||||
decisions.AddIfNotNull(GetDecision(file, movie, folderInfo, sceneSource, shouldUseFolderName));
|
||||
decisions.AddIfNotNull(GetDecision(file, movie, folderInfo, sceneSource, shouldUseFolderName, shouldCheckQuality));
|
||||
}
|
||||
|
||||
return decisions;
|
||||
}
|
||||
|
||||
private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName)
|
||||
private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
|
||||
{
|
||||
ImportDecision decision = null;
|
||||
|
||||
@@ -113,6 +122,106 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
if (sceneSource)
|
||||
{
|
||||
localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
|
||||
if (shouldCheckQuality)
|
||||
{
|
||||
var width = localMovie.MediaInfo.Width;
|
||||
var current = localMovie.Quality;
|
||||
var qualityName = current.Quality.Name.ToLower();
|
||||
QualityModel updated = null;
|
||||
if (width > 1400)
|
||||
{
|
||||
if (qualityName.Contains("bluray"))
|
||||
{
|
||||
updated = new QualityModel(Quality.Bluray1080p);
|
||||
}
|
||||
|
||||
else if (qualityName.Contains("webdl"))
|
||||
{
|
||||
updated = new QualityModel(Quality.WEBDL1080p);
|
||||
}
|
||||
|
||||
else if (qualityName.Contains("hdtv"))
|
||||
{
|
||||
updated = new QualityModel(Quality.HDTV1080p);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
var def = _qualitiesService.Get(Quality.HDTV1080p);
|
||||
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
|
||||
{
|
||||
updated = new QualityModel(Quality.HDTV1080p);
|
||||
}
|
||||
def = _qualitiesService.Get(Quality.WEBDL1080p);
|
||||
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
|
||||
{
|
||||
updated = new QualityModel(Quality.WEBDL1080p);
|
||||
}
|
||||
def = _qualitiesService.Get(Quality.Bluray1080p);
|
||||
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
|
||||
{
|
||||
updated = new QualityModel(Quality.Bluray1080p);
|
||||
}
|
||||
if (updated == null)
|
||||
{
|
||||
updated = new QualityModel(Quality.Bluray1080p);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if (width > 900)
|
||||
{
|
||||
if (qualityName.Contains("bluray"))
|
||||
{
|
||||
updated = new QualityModel(Quality.Bluray720p);
|
||||
}
|
||||
|
||||
else if (qualityName.Contains("webdl"))
|
||||
{
|
||||
updated = new QualityModel(Quality.WEBDL720p);
|
||||
}
|
||||
|
||||
else if (qualityName.Contains("hdtv"))
|
||||
{
|
||||
updated = new QualityModel(Quality.HDTV720p);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
var def = _qualitiesService.Get(Quality.HDTV720p);
|
||||
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
|
||||
{
|
||||
updated = new QualityModel(Quality.HDTV720p);
|
||||
}
|
||||
def = _qualitiesService.Get(Quality.WEBDL720p);
|
||||
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
|
||||
{
|
||||
updated = new QualityModel(Quality.WEBDL720p);
|
||||
}
|
||||
def = _qualitiesService.Get(Quality.Bluray720p);
|
||||
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
|
||||
{
|
||||
updated = new QualityModel(Quality.Bluray720p);
|
||||
}
|
||||
if (updated == null)
|
||||
{
|
||||
updated = new QualityModel(Quality.Bluray720p);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (updated != null && updated != current)
|
||||
{
|
||||
updated.QualitySource = QualitySource.MediaInfo;
|
||||
localMovie.Quality = updated;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
decision = GetDecision(localMovie);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -10,5 +10,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
public List<int> EpisodeIds { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
public int MovieId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,5 +17,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||
public QualityModel Quality { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
public IEnumerable<Rejection> Rejections { get; set; }
|
||||
public Movie Movie { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user