Compare commits
148 Commits
v0.2.0.134
...
v0.2.0.238
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
487c5e22ce | ||
|
|
6efd63a292 | ||
|
|
5ebd035b1c | ||
|
|
d50514f8bc | ||
|
|
a417ac2716 | ||
|
|
a89e662721 | ||
|
|
4b1e4eecfb | ||
|
|
8e452f8b6d | ||
|
|
7e6db89eff | ||
|
|
16214e666b | ||
|
|
2b25ce237f | ||
|
|
f0a9955447 | ||
|
|
d0439296fe | ||
|
|
bc3fdb0f80 | ||
|
|
186b2ada36 | ||
|
|
577125f345 | ||
|
|
687dd8a05f | ||
|
|
81861c6121 | ||
|
|
302462f48c | ||
|
|
d132f55830 | ||
|
|
6bbd64e59a | ||
|
|
290c4e1f2e | ||
|
|
1112616514 | ||
|
|
7fddbca4b7 | ||
|
|
692841478c | ||
|
|
23232b9830 | ||
|
|
b886566b25 | ||
|
|
2c56d60678 | ||
|
|
a0c8127ecf | ||
|
|
05f61df59e | ||
|
|
a0b80ad41a | ||
|
|
9e7cb708bf | ||
|
|
1ad4006819 | ||
|
|
5339f8efdc | ||
|
|
b273bfb10e | ||
|
|
b2317ada1f | ||
|
|
336aee7fda | ||
|
|
9e7468d723 | ||
|
|
f05ee13206 | ||
|
|
2b579eb0d3 | ||
|
|
791121fa06 | ||
|
|
f0bcb27beb | ||
|
|
ec6b389d75 | ||
|
|
f38430d632 | ||
|
|
266f28883a | ||
|
|
cc3c2533fa | ||
|
|
f8162b34f2 | ||
|
|
309877bf76 | ||
|
|
a50b20a397 | ||
|
|
de5489ae9a | ||
|
|
12e74aa38b | ||
|
|
80ec66b47c | ||
|
|
585fd87ad6 | ||
|
|
ec5161e848 | ||
|
|
0ec54daaff | ||
|
|
3ed1bebb7d | ||
|
|
29ae088a3d | ||
|
|
eb299ce847 | ||
|
|
a7e071318b | ||
|
|
3d67f6237e | ||
|
|
a691ffa7b7 | ||
|
|
aa9537c201 | ||
|
|
a3d9fb1c20 | ||
|
|
62a1e70c86 | ||
|
|
93d0d21846 | ||
|
|
b1c5a3ac14 | ||
|
|
55a525ba2f | ||
|
|
a53768463b | ||
|
|
24cbd6bcef | ||
|
|
3ab3e66853 | ||
|
|
40ca469339 | ||
|
|
2cbd2f719f | ||
|
|
53cbfa803b | ||
|
|
c0b0310bbd | ||
|
|
30e50062a8 | ||
|
|
85fd8f2c65 | ||
|
|
f72b042d5d | ||
|
|
2d3a3a0677 | ||
|
|
2bb21fedab | ||
|
|
91c820f98b | ||
|
|
7d3118aece | ||
|
|
4f4ad77ad1 | ||
|
|
42f205a731 | ||
|
|
cbb2b778a6 | ||
|
|
b3e03a648d | ||
|
|
acf45a79e8 | ||
|
|
b5d8ac852e | ||
|
|
4aec0e8fc6 | ||
|
|
ecea417fd8 | ||
|
|
6a41f6a435 | ||
|
|
da2d075aa8 | ||
|
|
10dc3993df | ||
|
|
7e5020db9a | ||
|
|
c48fe9de12 | ||
|
|
421e827a95 | ||
|
|
34d8045cf4 | ||
|
|
c6de163748 | ||
|
|
d9e2b22e74 | ||
|
|
65c0137964 | ||
|
|
ae19424ce7 | ||
|
|
7527ec52b7 | ||
|
|
640fcf3eaf | ||
|
|
3ce8232777 | ||
|
|
864b441d8e | ||
|
|
bc2ff149b4 | ||
|
|
dea305e921 | ||
|
|
e2eab31548 | ||
|
|
fe62e18f0d | ||
|
|
f1fa1553cf | ||
|
|
b576ae813d | ||
|
|
99123be936 | ||
|
|
dd0a033b0f | ||
|
|
c64597c9f1 | ||
|
|
6d2f81e3ed | ||
|
|
4263808360 | ||
|
|
c5ca2babf7 | ||
|
|
08db74d6e6 | ||
|
|
b309a9b01f | ||
|
|
2730745607 | ||
|
|
ae0df2aef0 | ||
|
|
6d665aeb21 | ||
|
|
967d3fd5c0 | ||
|
|
199d9c93ed | ||
|
|
30d2b41fbb | ||
|
|
75bb2533a3 | ||
|
|
9b3b4eb55b | ||
|
|
42f84b830c | ||
|
|
eb0f825cfc | ||
|
|
56a5b6ec89 | ||
|
|
af478d3799 | ||
|
|
c2d40051d4 | ||
|
|
281e516495 | ||
|
|
f63c3091f4 | ||
|
|
50f49863b7 | ||
|
|
941b3bd701 | ||
|
|
f60b8cefca | ||
|
|
7c5f2ca54e | ||
|
|
401a650273 | ||
|
|
105af5cf11 | ||
|
|
637c2e43eb | ||
|
|
53373e6f4a | ||
|
|
ad147ed425 | ||
|
|
ed35e2f194 | ||
|
|
674919dbf5 | ||
|
|
15b77e303f | ||
|
|
757ca1d72c | ||
|
|
8c8c7a99e3 | ||
|
|
b3dfb960b5 |
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,6 +1,8 @@
|
||||
|
||||
|
||||
|
||||
Please use the search bar and make sure you are not submitting an already submitted issue.
|
||||
|
||||
Provide a description of the feature request or bug, the more details the better.
|
||||
When possible include a log!
|
||||
|
||||
|
||||
26
.gitignore
vendored
@@ -101,16 +101,21 @@ App_Data/*.ldf
|
||||
_NCrunch_*
|
||||
_TeamCity*
|
||||
|
||||
# Sonarr
|
||||
config.xml
|
||||
nzbdrone.log*txt
|
||||
# Radarr
|
||||
Backups/
|
||||
logs/
|
||||
MediaCover/
|
||||
UpdateLogs/
|
||||
xdg/
|
||||
config.xml
|
||||
logs.db*
|
||||
nzbdrone.db*
|
||||
nzbdrone.pid
|
||||
*workspace.xml
|
||||
*.test-cache
|
||||
*.userprefs
|
||||
*/test-results/*
|
||||
src/UI/.idea/*
|
||||
*log.txt
|
||||
node_modules/
|
||||
_output*
|
||||
_rawPackage/
|
||||
@@ -122,23 +127,26 @@ setup/Output/
|
||||
|
||||
UI.Phantom/
|
||||
|
||||
#VS outout folders
|
||||
# VS outout folders
|
||||
bin
|
||||
obj
|
||||
output/*
|
||||
|
||||
#Packages
|
||||
# Packages
|
||||
Radarr_*/
|
||||
Radarr_*.zip
|
||||
Radarr_*.gz
|
||||
|
||||
#OS X metadata files
|
||||
# macOS metadata files
|
||||
._*
|
||||
.DS_Store
|
||||
|
||||
_start
|
||||
_temp_*/**/*
|
||||
|
||||
#AppVeyor
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
|
||||
# AppVeyor
|
||||
/tools-cake/
|
||||
/_artifacts/
|
||||
/_artifacts/
|
||||
|
||||
10
.travis.yml
@@ -1,12 +1,14 @@
|
||||
language: csharp
|
||||
solution: src/NzbDrone.sln
|
||||
script: # the following commands are just examples, use whatever your build process requires
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- nodejs
|
||||
- npm
|
||||
script:
|
||||
- ./build.sh
|
||||
- chmod +x test.sh
|
||||
# - ./test.sh Linux Unit Takes far too long, maybe even crashes travis :/
|
||||
install:
|
||||
- sudo apt-get install nodejs
|
||||
- sudo apt-get install npm
|
||||
after_success:
|
||||
- chmod +x package.sh
|
||||
- ./package.sh
|
||||
|
||||
BIN
Logo/1024.png
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 48 KiB |
BIN
Logo/128.png
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
Logo/16.png
|
Before Width: | Height: | Size: 811 B After Width: | Height: | Size: 701 B |
BIN
Logo/256.png
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 11 KiB |
BIN
Logo/32.png
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
Logo/400.png
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 17 KiB |
BIN
Logo/48.png
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.0 KiB |
BIN
Logo/512.png
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 22 KiB |
BIN
Logo/64.png
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
Logo/800.png
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 37 KiB |
597
Logo/Radarr.svg
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 31 KiB |
BIN
Logo/Thumbs.db
96
README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
## Status
|
||||
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
[](https://github.com/Radarr/Radarr/pulls)
|
||||
[](http://www.gnu.org/licenses/gpl.html)
|
||||
[](https://github.com/Radarr/Radarr)
|
||||
[](https://github.com/Radar/Radarr/releases/latest)
|
||||
[](https://hub.docker.com/r/linuxserver/radarr/)
|
||||
|
||||
| Service | Master | Develop |
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
|
||||
| Travis | [](https://travis-ci.org/Radarr/Radarr) | [](https://travis-ci.org/Radarr/Radarr) |
|
||||
|
||||
A fork of [Sonarr](https://github.com/Sonarr/Sonarr) to work with movies à la Couchpotato.
|
||||
|
||||
**This fork works independently of Sonarr and will not interfere with it.**
|
||||
|
||||
## Downloads
|
||||
|
||||
[](https://github.com/Radarr/Radarr/releases)
|
||||
|
||||
[](https://ci.appveyor.com/project/galli-leo/radarr-usby1/build/artifacts)
|
||||
|
||||
[](https://store.docker.com/community/images/linuxserver/radarr)
|
||||
[](https://store.docker.com/community/images/lsioarmhf/radarr)
|
||||
[](https://store.docker.com/community/images/lsioarmhf/radarr-aarch64)
|
||||
|
||||
To connect to the UI, fire up your browser and open <http://localhost:7878> or <http://your-ip:7878>.
|
||||
|
||||
## Support
|
||||
|
||||
[](https://discord.gg/AD3UP37)
|
||||
[](https://www.reddit.com/r/radarr)
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
|
||||
## Features
|
||||
|
||||
### Current Features
|
||||
|
||||
* Adding new movies with lots of information, such as trailers, ratings, etc.
|
||||
* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc.
|
||||
* Can watch for better quality of the movies you have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
|
||||
* Automatic failed download handling will try another release if one fails
|
||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically
|
||||
* Full integration with SABnzbd and NZBGet
|
||||
* Automatically searching for releases as well as RSS Sync
|
||||
* Automatically importing downloaded movies
|
||||
* Recognizing Special Editions, Director's Cut, etc.
|
||||
* Identifying releases with hardcoded subs
|
||||
* All indexers supported by Sonarr also supported
|
||||
* New PassThePopcorn Indexer
|
||||
* QBittorrent, Deluge, rTorrent, Transmission and uTorrent download client (Other clients are coming)
|
||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||
* And a beautiful UI
|
||||
|
||||
### Planned Features
|
||||
|
||||
* Scanning PreDB to know when a new release is available
|
||||
* Fixing the other Indexers and download clients
|
||||
* Importing movies from various online sources, such as IMDb Watchlists (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114))
|
||||
* Full integration with Kodi, Plex (notification, library update, metadata)
|
||||
|
||||
##Feature Requests
|
||||
[](http://feathub.com/Radarr/Radarr)
|
||||
|
||||
## Configuring Development Environment
|
||||
|
||||
### Requirements
|
||||
|
||||
* [Visual Studio Community](https://www.visualstudio.com/vs/community/) or [MonoDevelop](http://www.monodevelop.com)
|
||||
* [Git](https://git-scm.com/downloads)
|
||||
* [Node.js](https://nodejs.org/en/download/)
|
||||
|
||||
### Setup
|
||||
|
||||
* Make sure all the required software mentioned above are installed
|
||||
* Clone the repository into your development machine ([*info*](https://help.github.com/desktop/guides/contributing/working-with-your-remote-repository-on-github-or-github-enterprise))
|
||||
* Grab the submodules `git submodule init && git submodule update`
|
||||
* Install the required Node Packages `npm install`
|
||||
* Start gulp to monitor your dev environment for any changes that need post processing using `npm start` command.
|
||||
|
||||
> **Notice**
|
||||
> Gulp must be running at all times while you are working with Radarr client source files.
|
||||
|
||||
### Development
|
||||
|
||||
* Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed
|
||||
* Make sure `NzbDrone.Console` is set as the startup project
|
||||
|
||||
## Sponsors
|
||||
|
||||
[JetBrains](http://www.jetbrains.com) for providing us with free licenses to their great tools:
|
||||
* [ReSharper](http://www.jetbrains.com/resharper)
|
||||
* [WebStorm](http://www.jetbrains.com/webstorm)
|
||||
* [TeamCity](http://www.jetbrains.com/teamcity)
|
||||
83
readme.md
@@ -1,83 +0,0 @@
|
||||
# Radarr
|
||||
|
||||
| Service | Master | Develop |
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
|
||||
| Travis | [](https://travis-ci.org/galli-leo/Radarr) | [](https://travis-ci.org/galli-leo/Radarr) |
|
||||
|
||||
This fork of Sonarr aims to turn it into something like Couchpotato.
|
||||
|
||||
## Currently working:
|
||||
* Adding new movies
|
||||
* Manually searching for releases of movies.
|
||||
* Automatically searching for releases.
|
||||
* Automatically importing downloaded movies.
|
||||
* Recognizing Special Editions, Director's Cut, etc.
|
||||
* Identifying releases with hardcoded subs.
|
||||
* Rarbg.to, Torznab and Newznab Indexer.
|
||||
* QBittorrent and Deluge download client (Other clients are coming)
|
||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||
|
||||
## Planned Features:
|
||||
* Scanning PreDB to know when a new release is available.
|
||||
* Fixing the other Indexers and download clients.
|
||||
* Importing of Sonarr config.
|
||||
|
||||
## Download
|
||||
The latest precompiled binary versions can be found here: https://github.com/galli-leo/Radarr/releases.
|
||||
|
||||
To connect to the UI, fire up your browser and open localhost:7878 or your-ip:7878.
|
||||
|
||||
Docker containers from [linuxserver.io](https://linuxserver.io) can be found here.
|
||||
* [Radarr (x64)](https://hub.docker.com/r/linuxserver/radarr/)
|
||||
* [Radarr (armhf)](https://hub.docker.com/r/lsioarmhf/radarr/)
|
||||
* [Radarr (aarch64)](https://hub.docker.com/r/lsioarmhf/radarr-aarch64/)
|
||||
|
||||
For more up to date versions (but also sometimes broken), daily builds can be found here:
|
||||
* [OSX](https://leonardogalli.ch/radarr/builds/latest.php?os=osx)
|
||||
* [Windows](https://leonardogalli.ch/radarr/builds/latest.php?os=windows)
|
||||
* [Linux](https://leonardogalli.ch/radarr/builds/latest.php?os=mono)
|
||||
|
||||
## Major Features Include: ##
|
||||
|
||||
* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
|
||||
* Can watch for better quality of the movies you have and do an upgrade.
|
||||
* Automatic failed download handling will try another release if one fails
|
||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically.
|
||||
* Full integration with SABNzbd and NzbGet.
|
||||
* Full integration with XBMC, Plex (notification, library update, metadata).
|
||||
* And a beautiful UI
|
||||
|
||||
## Configuring Development Environment: ##
|
||||
|
||||
### Requirements ###
|
||||
- Visual Studio 2015 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) or Mono
|
||||
- [Git](http://git-scm.com/downloads)
|
||||
- [NodeJS](http://nodejs.org/download/)
|
||||
|
||||
### Setup ###
|
||||
|
||||
- Make sure all the required software mentioned above are installed.
|
||||
- Clone the repository into your development machine. [*info*](https://help.github.com/articles/working-with-repositories)
|
||||
- Grab the submodules `git submodule init && git submodule update`
|
||||
- install the required Node Packages `npm install`
|
||||
- start gulp to monitor your dev environment for any changes that need post processing using `npm start` command.
|
||||
|
||||
*Please note gulp must be running at all times while you are working with Sonarr client source files.*
|
||||
|
||||
|
||||
### Development ###
|
||||
- Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed.
|
||||
- Make sure `NzbDrone.Console` is set as the startup project
|
||||
|
||||
|
||||
### License ###
|
||||
* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
||||
Copyright 2010-2016
|
||||
|
||||
|
||||
### Sponsors ###
|
||||
- [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools
|
||||
- [ReSharper](http://www.jetbrains.com/resharper/)
|
||||
- [WebStorm](http://www.jetbrains.com/webstorm/)
|
||||
- [TeamCity](http://www.jetbrains.com/teamcity/)
|
||||
@@ -64,6 +64,8 @@ namespace NzbDrone.Api.Authentication
|
||||
new DefaultHmacProvider(new PassphraseKeyGenerator(_configService.HmacPassphrase, Encoding.ASCII.GetBytes(_configService.HmacSalt)))
|
||||
);
|
||||
|
||||
FormsAuthentication.FormsAuthenticationCookieName = "_ncfaradarr"; //For those people that both have sonarr and radarr.
|
||||
|
||||
FormsAuthentication.Enable(pipelines, new FormsAuthenticationConfiguration
|
||||
{
|
||||
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Api.Series;
|
||||
@@ -11,13 +12,14 @@ namespace NzbDrone.Api.Blacklist
|
||||
{
|
||||
public int SeriesId { get; set; }
|
||||
public List<int> EpisodeIds { get; set; }
|
||||
public int MovieId { get; set; }
|
||||
public string SourceTitle { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public MovieResource Movie { get; set; }
|
||||
public SeriesResource Series { get; set; }
|
||||
}
|
||||
|
||||
@@ -30,7 +32,7 @@ namespace NzbDrone.Api.Blacklist
|
||||
return new BlacklistResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
MovieId = model.MovieId,
|
||||
SeriesId = model.SeriesId,
|
||||
EpisodeIds = model.EpisodeIds,
|
||||
SourceTitle = model.SourceTitle,
|
||||
@@ -39,7 +41,7 @@ namespace NzbDrone.Api.Blacklist
|
||||
Protocol = model.Protocol,
|
||||
Indexer = model.Indexer,
|
||||
Message = model.Message,
|
||||
|
||||
Movie = model.Movie.ToResource(),
|
||||
Series = model.Series.ToResource()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Movies
|
||||
private readonly IRenameMovieFileService _renameMovieFileService;
|
||||
|
||||
public RenameMovieModule(IRenameMovieFileService renameMovieFileService)
|
||||
: base("rename")
|
||||
: base("renameMovie")
|
||||
{
|
||||
_renameMovieFileService = renameMovieFileService;
|
||||
|
||||
|
||||
@@ -260,6 +260,7 @@
|
||||
<Compile Include="Wanted\CutoffModule.cs" />
|
||||
<Compile Include="Wanted\LegacyMissingModule.cs" />
|
||||
<Compile Include="Wanted\MissingModule.cs" />
|
||||
<Compile Include="Wanted\MovieMissingModule.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
@@ -294,4 +295,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Api.Movie
|
||||
IHandle<MediaCoversUpdatedEvent>
|
||||
|
||||
{
|
||||
private readonly IMovieService _moviesService;
|
||||
protected readonly IMovieService _moviesService;
|
||||
private readonly IMovieStatisticsService _moviesStatisticsService;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
|
||||
@@ -78,13 +78,33 @@ namespace NzbDrone.Api.Movie
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
}
|
||||
|
||||
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMovieService moviesService,
|
||||
IMovieStatisticsService moviesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
string resource)
|
||||
: base(signalRBroadcaster, resource)
|
||||
{
|
||||
_moviesService = moviesService;
|
||||
_moviesStatisticsService = moviesStatisticsService;
|
||||
|
||||
_coverMapper = coverMapper;
|
||||
|
||||
GetResourceAll = AllMovie;
|
||||
GetResourceById = GetMovie;
|
||||
CreateResource = AddMovie;
|
||||
UpdateResource = UpdateMovie;
|
||||
DeleteResource = DeleteMovie;
|
||||
}
|
||||
|
||||
private MovieResource GetMovie(int id)
|
||||
{
|
||||
var movies = _moviesService.GetMovie(id);
|
||||
return MapToResource(movies);
|
||||
}
|
||||
|
||||
private MovieResource MapToResource(Core.Tv.Movie movies)
|
||||
protected MovieResource MapToResource(Core.Tv.Movie movies)
|
||||
{
|
||||
if (movies == null) return null;
|
||||
|
||||
@@ -181,6 +201,8 @@ namespace NzbDrone.Api.Movie
|
||||
//var mappings = null;//_sceneMappingService.FindByTvdbId(resource.TvdbId);
|
||||
|
||||
//if (mappings == null) return;
|
||||
|
||||
//Not necessary anymore
|
||||
|
||||
//resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
||||
}
|
||||
@@ -219,7 +241,7 @@ namespace NzbDrone.Api.Movie
|
||||
|
||||
public void Handle(MediaCoversUpdatedEvent message)
|
||||
{
|
||||
//BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace NzbDrone.Api.Movie
|
||||
public string RemotePoster { get; set; }
|
||||
public int Year { get; set; }
|
||||
public bool HasFile { get; set; }
|
||||
public string YouTubeTrailerId { get; set; }
|
||||
public string Studio { get; set; }
|
||||
|
||||
//View & Edit
|
||||
public string Path { get; set; }
|
||||
@@ -144,7 +146,9 @@ namespace NzbDrone.Api.Movie
|
||||
AddOptions = model.AddOptions,
|
||||
AlternativeTitles = model.AlternativeTitles,
|
||||
Ratings = model.Ratings,
|
||||
MovieFile = movieFile
|
||||
MovieFile = movieFile,
|
||||
YouTubeTrailerId = model.YouTubeTrailerId,
|
||||
Studio = model.Studio
|
||||
};
|
||||
}
|
||||
|
||||
@@ -191,7 +195,9 @@ namespace NzbDrone.Api.Movie
|
||||
Added = resource.Added,
|
||||
AddOptions = resource.AddOptions,
|
||||
AlternativeTitles = resource.AlternativeTitles,
|
||||
Ratings = resource.Ratings
|
||||
Ratings = resource.Ratings,
|
||||
YouTubeTrailerId = resource.YouTubeTrailerId,
|
||||
Studio = resource.Studio
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ namespace NzbDrone.Api.Series
|
||||
|
||||
public void Handle(MediaCoversUpdatedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Series.Id);
|
||||
//BroadcastResourceChange(ModelAction.Updated, message.Series.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace NzbDrone.Api.Validation
|
||||
public class RssSyncIntervalValidator : PropertyValidator
|
||||
{
|
||||
public RssSyncIntervalValidator()
|
||||
: base("Must be between 10 and 120 or 0 to disable")
|
||||
: base("Must be between 10 and 720 or 0 to disable")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Api.Validation
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value >= 10 && value <= 120)
|
||||
if (value >= 10 && value <= 720)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Wanted
|
||||
ISeriesService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing_episodes")
|
||||
{
|
||||
GetResourcePaged = GetMissingEpisodes;
|
||||
}
|
||||
|
||||
77
src/NzbDrone.Api/Wanted/MovieMissingModule.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Api.Movies;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.SignalR;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using System;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
|
||||
namespace NzbDrone.Api.Wanted
|
||||
{
|
||||
class MovieMissingModule : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>,
|
||||
IHandle<MovieGrabbedEvent>,
|
||||
IHandle<MovieDownloadedEvent>
|
||||
{
|
||||
protected readonly IMovieService _movieService;
|
||||
|
||||
public MovieMissingModule(IMovieService movieService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(signalRBroadcaster, "wanted/missing")
|
||||
{
|
||||
|
||||
_movieService = movieService;
|
||||
GetResourcePaged = GetMissingMovies;
|
||||
}
|
||||
|
||||
private PagingResource<MovieResource> GetMissingMovies(PagingResource<MovieResource> pagingResource)
|
||||
{
|
||||
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("physicalRelease", SortDirection.Descending);
|
||||
|
||||
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
|
||||
{
|
||||
pagingSpec.FilterExpression = v => v.Monitored == false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pagingSpec.FilterExpression = v => v.Monitored == true;
|
||||
}
|
||||
|
||||
var resource = ApplyToPage(_movieService.MoviesWithoutFiles, pagingSpec, v => MapToResource(v, false));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
private MovieResource GetMovie(int id)
|
||||
{
|
||||
var movie = _movieService.GetMovie(id);
|
||||
var resource = MapToResource(movie, true);
|
||||
return resource;
|
||||
}
|
||||
|
||||
private MovieResource MapToResource(Core.Tv.Movie movie, bool includeMovieFile)
|
||||
{
|
||||
var resource = movie.ToResource();
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void Handle(MovieGrabbedEvent message)
|
||||
{
|
||||
var resource = message.Movie.Movie.ToResource();
|
||||
|
||||
//add a grabbed field in MovieResource?
|
||||
//resource.Grabbed = true;
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
}
|
||||
|
||||
public void Handle(MovieDownloadedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Movie.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 81 KiB |
@@ -32,7 +32,7 @@ namespace NzbDrone.Core.Test.Configuration
|
||||
[Test]
|
||||
public void Get_value_should_return_default_when_no_value()
|
||||
{
|
||||
Subject.RssSyncInterval.Should().Be(15);
|
||||
Subject.RssSyncInterval.Should().Be(60);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -47,7 +47,7 @@ namespace NzbDrone.Core.Test.Configuration
|
||||
public void get_value_with_out_persist_should_not_store_default_value()
|
||||
{
|
||||
var interval = Subject.RssSyncInterval;
|
||||
interval.Should().Be(15);
|
||||
interval.Should().Be(60);
|
||||
Mocker.GetMock<IConfigRepository>().Verify(c => c.Insert(It.IsAny<Config>()), Times.Never());
|
||||
}
|
||||
|
||||
|
||||
@@ -92,14 +92,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
||||
protected void GivenFailedDownload()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<NzbgetSettings>()))
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns((string)null);
|
||||
}
|
||||
|
||||
protected void GivenSuccessfulDownload()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<NzbgetSettings>()))
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns(Guid.NewGuid().ToString().Replace("-", ""));
|
||||
}
|
||||
|
||||
|
||||
@@ -47,5 +47,17 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
{
|
||||
QualityParser.ParseQuality(title).Revision.Version.Should().Be(version);
|
||||
}
|
||||
|
||||
[TestCase("Deadpool 2016 2160p 4K UltraHD BluRay DTS-HD MA 7 1 x264-Whatevs", 19)]
|
||||
[TestCase("Deadpool 2016 2160p 4K UltraHD DTS-HD MA 7 1 x264-Whatevs", 16)]
|
||||
[TestCase("Deadpool 2016 4K 2160p UltraHD BluRay AAC2 0 HEVC x265", 19)]
|
||||
[TestCase("The Revenant 2015 2160p UHD BluRay DTS x264-Whatevs", 19)]
|
||||
[TestCase("The Revenant 2015 2160p UHD BluRay FLAC 7 1 x264-Whatevs", 19)]
|
||||
[TestCase("The Martian 2015 2160p Ultra HD BluRay DTS-HD MA 7 1 x264-Whatevs", 19)]
|
||||
[TestCase("Into the Inferno 2016 2160p Netflix WEBRip DD5 1 x264-Whatevs", 18)]
|
||||
public void should_parse_ultrahd_from_title(string title, int version)
|
||||
{
|
||||
QualityParser.ParseQuality(title).Quality.Id.Should().Be(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace NzbDrone.Core.Blacklisting
|
||||
{
|
||||
public int SeriesId { get; set; }
|
||||
public Series Series { get; set; }
|
||||
public int MovieId { get; set; }
|
||||
public Movie Movie { get; set; }
|
||||
public List<int> EpisodeIds { get; set; }
|
||||
public string SourceTitle { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace NzbDrone.Core.Blacklisting
|
||||
{
|
||||
List<Blacklist> BlacklistedByTitle(int seriesId, string sourceTitle);
|
||||
List<Blacklist> BlacklistedByTorrentInfoHash(int seriesId, string torrentInfoHash);
|
||||
List<Blacklist> BlacklistedBySeries(int seriesId);
|
||||
List<Blacklist> BlacklistedByMovie(int seriesId);
|
||||
}
|
||||
|
||||
public class BlacklistRepository : BasicRepository<Blacklist>, IBlacklistRepository
|
||||
@@ -20,15 +20,15 @@ namespace NzbDrone.Core.Blacklisting
|
||||
{
|
||||
}
|
||||
|
||||
public List<Blacklist> BlacklistedByTitle(int seriesId, string sourceTitle)
|
||||
public List<Blacklist> BlacklistedByTitle(int movieId, string sourceTitle)
|
||||
{
|
||||
return Query.Where(e => e.SeriesId == seriesId)
|
||||
return Query.Where(e => e.MovieId == movieId)
|
||||
.AndWhere(e => e.SourceTitle.Contains(sourceTitle));
|
||||
}
|
||||
|
||||
public List<Blacklist> BlacklistedByTorrentInfoHash(int seriesId, string torrentInfoHash)
|
||||
public List<Blacklist> BlacklistedByTorrentInfoHash(int movieId, string torrentInfoHash)
|
||||
{
|
||||
return Query.Where(e => e.SeriesId == seriesId)
|
||||
return Query.Where(e => e.MovieId == movieId)
|
||||
.AndWhere(e => e.TorrentInfoHash.Contains(torrentInfoHash));
|
||||
}
|
||||
|
||||
@@ -37,9 +37,14 @@ namespace NzbDrone.Core.Blacklisting
|
||||
return Query.Where(b => b.SeriesId == seriesId);
|
||||
}
|
||||
|
||||
public List<Blacklist> BlacklistedByMovie(int movieId)
|
||||
{
|
||||
return Query.Where(b => b.MovieId == movieId);
|
||||
}
|
||||
|
||||
protected override SortBuilder<Blacklist> GetPagedQuery(QueryBuilder<Blacklist> query, PagingSpec<Blacklist> pagingSpec)
|
||||
{
|
||||
var baseQuery = query.Join<Blacklist, Series>(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id);
|
||||
var baseQuery = query.Join<Blacklist, Movie>(JoinType.Inner, h => h.Movie, (h, s) => h.MovieId == s.Id);
|
||||
|
||||
return base.GetPagedQuery(baseQuery, pagingSpec);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.Blacklisting
|
||||
|
||||
IExecute<ClearBlacklistCommand>,
|
||||
IHandle<DownloadFailedEvent>,
|
||||
IHandleAsync<SeriesDeletedEvent>
|
||||
IHandleAsync<MovieDeletedEvent>
|
||||
{
|
||||
private readonly IBlacklistRepository _blacklistRepository;
|
||||
|
||||
@@ -128,8 +128,9 @@ namespace NzbDrone.Core.Blacklisting
|
||||
{
|
||||
var blacklist = new Blacklist
|
||||
{
|
||||
SeriesId = message.SeriesId,
|
||||
SeriesId = 0,
|
||||
EpisodeIds = message.EpisodeIds,
|
||||
MovieId = message.MovieId,
|
||||
SourceTitle = message.SourceTitle,
|
||||
Quality = message.Quality,
|
||||
Date = DateTime.UtcNow,
|
||||
@@ -144,9 +145,9 @@ namespace NzbDrone.Core.Blacklisting
|
||||
_blacklistRepository.Insert(blacklist);
|
||||
}
|
||||
|
||||
public void HandleAsync(SeriesDeletedEvent message)
|
||||
public void HandleAsync(MovieDeletedEvent message)
|
||||
{
|
||||
var blacklisted = _blacklistRepository.BlacklistedBySeries(message.Series.Id);
|
||||
var blacklisted = _blacklistRepository.BlacklistedByMovie(message.Movie.Id);
|
||||
|
||||
_blacklistRepository.DeleteMany(blacklisted);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace NzbDrone.Core.Configuration
|
||||
|
||||
public int RssSyncInterval
|
||||
{
|
||||
get { return GetValueInt("RssSyncInterval", 15); }
|
||||
get { return GetValueInt("RssSyncInterval", 60); }
|
||||
|
||||
set { SetValue("RssSyncInterval", 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using System.Data;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(122)]
|
||||
public class add_movieid_to_blacklist : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Blacklist").AddColumn("MovieId").AsInt32().Nullable().WithDefaultValue(0);
|
||||
Alter.Table("Blacklist").AlterColumn("SeriesId").AsInt32().Nullable();
|
||||
Alter.Table("Blacklist").AlterColumn("EpisodeIds").AsString().Nullable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,17 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
|
||||
{
|
||||
|
||||
|
||||
if (x.IsForMovie)
|
||||
{
|
||||
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
|
||||
{
|
||||
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Movie.Tags);
|
||||
var downloadProtocol = remoteEpisode.Release.DownloadProtocol;
|
||||
return downloadProtocol == delayProfile.PreferredProtocol;
|
||||
});
|
||||
}
|
||||
|
||||
var result = CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
|
||||
{
|
||||
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Series.Tags);
|
||||
@@ -75,15 +86,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
return downloadProtocol == delayProfile.PreferredProtocol;
|
||||
});
|
||||
|
||||
if (x.IsForMovie)
|
||||
{
|
||||
result = CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
|
||||
{
|
||||
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Movie.Tags);
|
||||
var downloadProtocol = remoteEpisode.Release.DownloadProtocol;
|
||||
return downloadProtocol == delayProfile.PreferredProtocol;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -125,8 +128,8 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
|
||||
private int CompareAgeIfUsenet(DownloadDecision x, DownloadDecision y)
|
||||
{
|
||||
if (x.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Usenet ||
|
||||
y.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Usenet)
|
||||
if (x.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Usenet ||
|
||||
y.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Usenet)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
|
||||
public List<DownloadDecision> GetRssDecision(List<ReleaseInfo> reports)
|
||||
{
|
||||
return GetDecisions(reports).ToList();
|
||||
return GetMovieDecisions(reports).ToList();
|
||||
}
|
||||
|
||||
public List<DownloadDecision> GetSearchDecision(List<ReleaseInfo> reports, SearchCriteriaBase searchCriteriaBase)
|
||||
@@ -83,7 +83,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
if (parsedEpisodeInfo.Quality.HardcodedSubs.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
remoteEpisode.DownloadAllowed = false;
|
||||
remoteEpisode.DownloadAllowed = true;
|
||||
decision = new DownloadDecision(remoteEpisode, new Rejection("Hardcoded subs found: " + parsedEpisodeInfo.Quality.HardcodedSubs));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -34,11 +34,11 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
public List<DownloadDecision> PrioritizeDecisionsForMovies(List<DownloadDecision> decisions)
|
||||
{
|
||||
return decisions.Where(c => c.RemoteMovie.Movie != null)
|
||||
/*.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) =>
|
||||
.GroupBy(c => c.RemoteMovie.Movie.Id, (movieId, downloadDecisions) =>
|
||||
{
|
||||
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
|
||||
})
|
||||
.SelectMany(c => c)*/
|
||||
.SelectMany(c => c)
|
||||
.Union(decisions.Where(c => c.RemoteMovie.Movie == null))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
@@ -33,7 +33,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
|
||||
throw new NotImplementedException();
|
||||
if (_blacklistService.Blacklisted(subject.Movie.Id, subject.Release))
|
||||
{
|
||||
_logger.Debug("{0} is blacklisted, rejecting.", subject.Release.Title);
|
||||
return Decision.Reject("Release is blacklisted");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,21 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (searchCriteria != null)
|
||||
{
|
||||
if (searchCriteria.UserInvokedSearch)
|
||||
{
|
||||
_logger.Debug("Skipping monitored check during search");
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
|
||||
if (!subject.Movie.Monitored)
|
||||
{
|
||||
return Decision.Reject("Movie is not monitored");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||
|
||||
@@ -32,9 +32,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContents)
|
||||
{
|
||||
var category = Settings.TvCategory;
|
||||
|
||||
var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
|
||||
|
||||
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
|
||||
var addpaused = Settings.AddPaused;
|
||||
|
||||
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, addpaused, Settings);
|
||||
|
||||
if (response == null)
|
||||
{
|
||||
@@ -47,9 +50,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents)
|
||||
{
|
||||
var category = Settings.TvCategory; // TODO: Update this to MovieCategory?
|
||||
|
||||
var priority = Settings.RecentTvPriority;
|
||||
|
||||
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
|
||||
var addpaused = Settings.AddPaused;
|
||||
|
||||
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, addpaused, Settings);
|
||||
|
||||
if(response == null)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public interface INzbgetProxy
|
||||
{
|
||||
string DownloadNzb(byte[] nzbData, string title, string category, int priority, NzbgetSettings settings);
|
||||
string DownloadNzb(byte[] nzbData, string title, string category, int priority, bool addpaused, NzbgetSettings settings);
|
||||
NzbgetGlobalStatus GetGlobalStatus(NzbgetSettings settings);
|
||||
List<NzbgetQueueItem> GetQueue(NzbgetSettings settings);
|
||||
List<NzbgetHistoryItem> GetHistory(NzbgetSettings settings);
|
||||
@@ -45,12 +45,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
return version >= minimumVersion;
|
||||
}
|
||||
|
||||
public string DownloadNzb(byte[] nzbData, string title, string category, int priority, NzbgetSettings settings)
|
||||
public string DownloadNzb(byte[] nzbData, string title, string category, int priority, bool addpaused, NzbgetSettings settings)
|
||||
{
|
||||
if (HasVersion(16, settings))
|
||||
{
|
||||
var droneId = Guid.NewGuid().ToString().Replace("-", "");
|
||||
var response = ProcessRequest<int>(settings, "append", title, nzbData, category, priority, false, false, string.Empty, 0, "all", new string[] { "drone", droneId });
|
||||
var response = ProcessRequest<int>(settings, "append", title, nzbData, category, priority, false, addpaused, string.Empty, 0, "all", new string[] { "drone", droneId });
|
||||
if (response <= 0)
|
||||
{
|
||||
return null;
|
||||
|
||||
@@ -57,6 +57,9 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
|
||||
public bool UseSsl { get; set; }
|
||||
|
||||
[FieldDefinition(8, Label = "Add Paused", Type = FieldType.Checkbox, HelpText = "This option requires at least NzbGet version 16.0")]
|
||||
public bool AddPaused { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
||||
@@ -5,6 +5,7 @@ using NzbDrone.Core.IndexerSearch;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
@@ -38,7 +39,7 @@ namespace NzbDrone.Core.Download
|
||||
{
|
||||
_logger.Debug("Failed download contains a movie, searching again.");
|
||||
|
||||
_commandQueueManager.Push(new MoviesSearchCommand { MovieId = message.MovieId });
|
||||
_commandQueueManager.Push(new MoviesSearchCommand { MovieIds = new List<int> { message.MovieId } });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -102,13 +102,13 @@ namespace NzbDrone.Core.Extras
|
||||
|
||||
public void Handle(MediaCoversUpdatedEvent message)
|
||||
{
|
||||
var series = message.Series;
|
||||
var episodeFiles = GetEpisodeFiles(series.Id);
|
||||
//var series = message.Series;
|
||||
//var episodeFiles = GetEpisodeFiles(series.Id);
|
||||
|
||||
foreach (var extraFileManager in _extraFileManagers)
|
||||
{
|
||||
extraFileManager.CreateAfterSeriesScan(series, episodeFiles);
|
||||
}
|
||||
//foreach (var extraFileManager in _extraFileManagers)
|
||||
//{
|
||||
// extraFileManager.CreateAfterSeriesScan(series, episodeFiles);
|
||||
//}
|
||||
}
|
||||
|
||||
//TODO: Implementing this will fix a lot of our warning exceptions
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class MissingMoviesSearchCommand : Command
|
||||
{
|
||||
public override bool SendUpdatesToClient => true;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class MoviesSearchCommand : Command
|
||||
{
|
||||
public int MovieId { get; set; }
|
||||
public List<int> MovieIds { get; set; }
|
||||
|
||||
public override bool SendUpdatesToClient => true;
|
||||
}
|
||||
|
||||
@@ -4,22 +4,23 @@ using NzbDrone.Common.Instrumentation.Extensions;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class MovieSearchService : IExecute<MoviesSearchCommand>
|
||||
public class MovieSearchService : IExecute<MoviesSearchCommand>, IExecute<MissingMoviesSearchCommand>
|
||||
{
|
||||
private readonly IMovieService _seriesService;
|
||||
private readonly IMovieService _movieService;
|
||||
private readonly ISearchForNzb _nzbSearchService;
|
||||
private readonly IProcessDownloadDecisions _processDownloadDecisions;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MovieSearchService(IMovieService seriesService,
|
||||
public MovieSearchService(IMovieService movieService,
|
||||
ISearchForNzb nzbSearchService,
|
||||
IProcessDownloadDecisions processDownloadDecisions,
|
||||
Logger logger)
|
||||
{
|
||||
_seriesService = seriesService;
|
||||
_movieService = movieService;
|
||||
_nzbSearchService = nzbSearchService;
|
||||
_processDownloadDecisions = processDownloadDecisions;
|
||||
_logger = logger;
|
||||
@@ -27,20 +28,35 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
|
||||
public void Execute(MoviesSearchCommand message)
|
||||
{
|
||||
var series = _seriesService.GetMovie(message.MovieId);
|
||||
|
||||
var downloadedCount = 0;
|
||||
|
||||
foreach (var movieId in message.MovieIds)
|
||||
{
|
||||
var series = _movieService.GetMovie(movieId);
|
||||
|
||||
if (!series.Monitored)
|
||||
{
|
||||
_logger.Debug("Movie {0} is not monitored, skipping search", series.Title);
|
||||
}
|
||||
|
||||
var decisions = _nzbSearchService.MovieSearch(message.MovieId, false);//_nzbSearchService.SeasonSearch(message.MovieId, season.SeasonNumber, false, message.Trigger == CommandTrigger.Manual);
|
||||
var decisions = _nzbSearchService.MovieSearch(movieId, false);//_nzbSearchService.SeasonSearch(message.MovieId, season.SeasonNumber, false, message.Trigger == CommandTrigger.Manual);
|
||||
downloadedCount += _processDownloadDecisions.ProcessDecisions(decisions).Grabbed.Count;
|
||||
|
||||
|
||||
}
|
||||
_logger.ProgressInfo("Movie search completed. {0} reports downloaded.", downloadedCount);
|
||||
}
|
||||
|
||||
public void Execute(MissingMoviesSearchCommand message)
|
||||
{
|
||||
var movies = _movieService.MoviesWithoutFiles(new PagingSpec<Movie>
|
||||
{
|
||||
Page = 1,
|
||||
PageSize = 100000,
|
||||
SortDirection = SortDirection.Ascending,
|
||||
SortKey = "Id",
|
||||
FilterExpression =
|
||||
v =>
|
||||
v.Monitored == true
|
||||
}).Records.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,13 +54,19 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
|
||||
|
||||
private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
|
||||
{
|
||||
var onlyInternal = "";
|
||||
if (Settings.Internal)
|
||||
{
|
||||
onlyInternal = "&internal=true";
|
||||
}
|
||||
|
||||
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);
|
||||
yield return new IndexerRequest($"{Settings.BaseUrl.Trim().TrimEnd('/')}/searchapi.php?action=imdbsearch&passkey={Settings.Passkey.Trim()}&imdb={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);
|
||||
yield return new IndexerRequest($"{Settings.BaseUrl.Trim().TrimEnd('/')}/searchapi.php?action=latestmovies&passkey={Settings.Passkey.Trim()}{onlyInternal}", HttpAccept.Rss);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace NzbDrone.Core.Indexers.AwesomeHD
|
||||
[FieldDefinition(1, Label = "Passkey")]
|
||||
public string Passkey { get; set; }
|
||||
|
||||
[FieldDefinition(2, Type = FieldType.Checkbox, Label = "Require Internal", HelpText = "Will only include internal releases for RSS Sync.")]
|
||||
public bool Internal { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,12 +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;
|
||||
torrentInfo.PublishDate = torrent.publishdate.ToUniversalTime();
|
||||
|
||||
|
||||
results.Add(torrentInfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
|
||||
public int size { get; set; }
|
||||
public int leechers { get; set; }
|
||||
public int seeders { get; set; }
|
||||
public DateTime publishdate { get; set; }
|
||||
public DateTime publish_date { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,13 @@ namespace NzbDrone.Core.Indexers.Torznab
|
||||
protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInfo)
|
||||
{
|
||||
var torrentInfo = base.ProcessItem(item, releaseInfo) as TorrentInfo;
|
||||
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
|
||||
if (GetImdbId(item) != null)
|
||||
{
|
||||
if (torrentInfo != null)
|
||||
{
|
||||
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
|
||||
}
|
||||
}
|
||||
return torrentInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,12 +30,14 @@ namespace NzbDrone.Core.Jobs
|
||||
{
|
||||
private readonly IScheduledTaskRepository _scheduledTaskRepository;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public TaskManager(IScheduledTaskRepository scheduledTaskRepository, IConfigService configService, Logger logger)
|
||||
public TaskManager(IScheduledTaskRepository scheduledTaskRepository, IConfigService configService, IConfigFileProvider configFileProvider, Logger logger)
|
||||
{
|
||||
_scheduledTaskRepository = scheduledTaskRepository;
|
||||
_configService = configService;
|
||||
_configFileProvider = configFileProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -59,14 +61,21 @@ namespace NzbDrone.Core.Jobs
|
||||
|
||||
public void Handle(ApplicationStartedEvent message)
|
||||
{
|
||||
float updateInterval = 6 * 60;
|
||||
|
||||
if (_configFileProvider.Branch == "nightly")
|
||||
{
|
||||
updateInterval = 30;
|
||||
}
|
||||
|
||||
var defaultTasks = new[]
|
||||
{
|
||||
new ScheduledTask{ Interval = 0.25f, TypeName = typeof(CheckForFinishedDownloadCommand).FullName},
|
||||
new ScheduledTask{ Interval = 5, TypeName = typeof(MessagingCleanupCommand).FullName},
|
||||
new ScheduledTask{ Interval = 6*60, TypeName = typeof(ApplicationUpdateCommand).FullName},
|
||||
new ScheduledTask{ Interval = 3*60, TypeName = typeof(UpdateSceneMappingCommand).FullName},
|
||||
new ScheduledTask{ Interval = updateInterval, 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},
|
||||
|
||||
@@ -80,6 +89,7 @@ namespace NzbDrone.Core.Jobs
|
||||
{
|
||||
Interval = _configService.DownloadedEpisodesScanInterval,
|
||||
TypeName = typeof(DownloadedEpisodesScanCommand).FullName
|
||||
//TypeName = typeof(DownloadedMovieScanCommand).FullName
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using NzbDrone.Common.Disk;
|
||||
using System;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Http;
|
||||
using System.Drawing;
|
||||
using NLog;
|
||||
|
||||
namespace NzbDrone.Core.MediaCover
|
||||
{
|
||||
@@ -12,11 +15,13 @@ namespace NzbDrone.Core.MediaCover
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IHttpClient _httpClient;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public CoverAlreadyExistsSpecification(IDiskProvider diskProvider, IHttpClient httpClient)
|
||||
public CoverAlreadyExistsSpecification(IDiskProvider diskProvider, IHttpClient httpClient, Logger logger)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool AlreadyExists(string url, string path)
|
||||
@@ -26,9 +31,38 @@ namespace NzbDrone.Core.MediaCover
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsValidGDIPlusImage(path))
|
||||
{
|
||||
_diskProvider.DeleteFile(path);
|
||||
return false;
|
||||
}
|
||||
|
||||
var headers = _httpClient.Head(new HttpRequest(url)).Headers;
|
||||
var fileSize = _diskProvider.GetFileSize(path);
|
||||
return fileSize == headers.ContentLength;
|
||||
}
|
||||
|
||||
private bool IsValidGDIPlusImage(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
GdiPlusInterop.CheckGdiPlus();
|
||||
|
||||
using (var bmp = new Bitmap(filename))
|
||||
{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (DllNotFoundException ex)
|
||||
{
|
||||
_logger.Error(ex, "Could not find libgdiplus. Cannot test if image is corrupt.");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Debug(ex, "Corrupted image found at: {0}. Redownloading...", filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ namespace NzbDrone.Core.MediaCover
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureCovers(Movie movie)
|
||||
private void EnsureCovers(Movie movie, int retried = 0)
|
||||
{
|
||||
foreach (var cover in movie.Images)
|
||||
{
|
||||
@@ -130,7 +130,25 @@ namespace NzbDrone.Core.MediaCover
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
_logger.Warn(string.Format("Couldn't download media cover for {0}. {1}", movie, e.Message));
|
||||
if (e.Status == WebExceptionStatus.ProtocolError)
|
||||
{
|
||||
_logger.Warn(e, "Server returned different code than 200. The poster is probably not available yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Warn(e, string.Format("Couldn't download media cover for {0}. {1}", movie, e.Message));
|
||||
if (retried < 3)
|
||||
{
|
||||
retried = +1;
|
||||
_logger.Warn("Retrying for the {0}. time in ten seconds.", retried);
|
||||
System.Threading.Thread.Sleep(10*1000);
|
||||
EnsureCovers(movie, retried);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn(e, "Couldn't download media cover even after retrying five times :(.");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -68,22 +68,22 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
{
|
||||
//check if already imported
|
||||
if (importResults.Select(r => r.ImportDecision.LocalMovie.Movie)
|
||||
.Select(e => e.Id).Contains(localMovie.Movie.Id))
|
||||
.Select(m => m.Id).Contains(localMovie.Movie.Id))
|
||||
{
|
||||
importResults.Add(new ImportResult(importDecision, "Movie has already been imported"));
|
||||
continue;
|
||||
}
|
||||
|
||||
var episodeFile = new MovieFile();
|
||||
episodeFile.DateAdded = DateTime.UtcNow;
|
||||
episodeFile.MovieId = localMovie.Movie.Id;
|
||||
episodeFile.Path = localMovie.Path.CleanFilePath();
|
||||
episodeFile.Size = _diskProvider.GetFileSize(localMovie.Path);
|
||||
episodeFile.Quality = localMovie.Quality;
|
||||
episodeFile.MediaInfo = localMovie.MediaInfo;
|
||||
episodeFile.Movie = localMovie.Movie;
|
||||
episodeFile.ReleaseGroup = localMovie.ParsedMovieInfo.ReleaseGroup;
|
||||
episodeFile.Edition = localMovie.ParsedMovieInfo.Edition;
|
||||
var movieFile = new MovieFile();
|
||||
movieFile.DateAdded = DateTime.UtcNow;
|
||||
movieFile.MovieId = localMovie.Movie.Id;
|
||||
movieFile.Path = localMovie.Path.CleanFilePath();
|
||||
movieFile.Size = _diskProvider.GetFileSize(localMovie.Path);
|
||||
movieFile.Quality = localMovie.Quality;
|
||||
movieFile.MediaInfo = localMovie.MediaInfo;
|
||||
movieFile.Movie = localMovie.Movie;
|
||||
movieFile.ReleaseGroup = localMovie.ParsedMovieInfo.ReleaseGroup;
|
||||
movieFile.Edition = localMovie.ParsedMovieInfo.Edition;
|
||||
|
||||
bool copyOnly;
|
||||
switch (importMode)
|
||||
@@ -102,17 +102,17 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
|
||||
if (newDownload)
|
||||
{
|
||||
episodeFile.SceneName = GetSceneName(downloadClientItem, localMovie);
|
||||
movieFile.SceneName = GetSceneName(downloadClientItem, localMovie);
|
||||
|
||||
var moveResult = _episodeFileUpgrader.UpgradeMovieFile(episodeFile, localMovie, copyOnly);
|
||||
var moveResult = _episodeFileUpgrader.UpgradeMovieFile(movieFile, localMovie, copyOnly); //TODO: Check if this works
|
||||
oldFiles = moveResult.OldFiles;
|
||||
}
|
||||
else
|
||||
{
|
||||
episodeFile.RelativePath = localMovie.Movie.Path.GetRelativePath(episodeFile.Path);
|
||||
movieFile.RelativePath = localMovie.Movie.Path.GetRelativePath(movieFile.Path);
|
||||
}
|
||||
|
||||
_mediaFileService.Add(episodeFile);
|
||||
_mediaFileService.Add(movieFile);
|
||||
importResults.Add(new ImportResult(importDecision));
|
||||
|
||||
if (newDownload)
|
||||
@@ -122,22 +122,22 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
|
||||
if (downloadClientItem != null)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, episodeFile, newDownload, downloadClientItem.DownloadClient, downloadClientItem.DownloadId, downloadClientItem.IsReadOnly));
|
||||
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, movieFile, newDownload, downloadClientItem.DownloadClient, downloadClientItem.DownloadId, downloadClientItem.IsReadOnly));
|
||||
}
|
||||
else
|
||||
{
|
||||
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, episodeFile, newDownload));
|
||||
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, movieFile, newDownload));
|
||||
}
|
||||
|
||||
if (newDownload)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new MovieDownloadedEvent(localMovie, episodeFile, oldFiles));
|
||||
_eventAggregator.PublishEvent(new MovieDownloadedEvent(localMovie, movieFile, oldFiles));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Warn(e, "Couldn't import episode " + localMovie);
|
||||
importResults.Add(new ImportResult(importDecision, "Failed to import episode"));
|
||||
_logger.Warn(e, "Couldn't import movie " + localMovie);
|
||||
importResults.Add(new ImportResult(importDecision, "Failed to import movie"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
public enum FileDateType
|
||||
{
|
||||
None = 0,
|
||||
LocalAirDate = 1,
|
||||
UtcAirDate = 2
|
||||
Cinemas = 1,
|
||||
Release = 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +111,11 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
public List<string> FilterExistingFiles(List<string> files, Movie movie)
|
||||
{
|
||||
var seriesFiles = GetFilesBySeries(movie.Id).Select(f => Path.Combine(movie.Path, f.RelativePath)).ToList();
|
||||
var movieFiles = GetFilesByMovie(movie.Id).Select(f => Path.Combine(movie.Path, f.RelativePath)).ToList();
|
||||
|
||||
if (!seriesFiles.Any()) return files;
|
||||
if (!movieFiles.Any()) return files;
|
||||
|
||||
return files.Except(seriesFiles, PathEqualityComparer.Instance).ToList();
|
||||
return files.Except(movieFiles, PathEqualityComparer.Instance).ToList();
|
||||
}
|
||||
|
||||
public EpisodeFile Get(int id)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
@@ -18,14 +18,17 @@ namespace NzbDrone.Core.MediaFiles
|
||||
public class MediaFileTableCleanupService : IMediaFileTableCleanupService
|
||||
{
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly IMovieService _movieService;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MediaFileTableCleanupService(IMediaFileService mediaFileService,
|
||||
IMovieService movieService,
|
||||
IEpisodeService episodeService,
|
||||
Logger logger)
|
||||
{
|
||||
_mediaFileService = mediaFileService;
|
||||
_movieService = movieService;
|
||||
_episodeService = episodeService;
|
||||
_logger = logger;
|
||||
}
|
||||
@@ -89,61 +92,39 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
public void Clean(Movie movie, List<string> filesOnDisk)
|
||||
{
|
||||
|
||||
//TODO: Update implementation for movies.
|
||||
var seriesFiles = _mediaFileService.GetFilesBySeries(movie.Id);
|
||||
var episodes = _episodeService.GetEpisodeBySeries(movie.Id);
|
||||
var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
|
||||
|
||||
var filesOnDiskKeys = new HashSet<string>(filesOnDisk, PathEqualityComparer.Instance);
|
||||
|
||||
foreach (var seriesFile in seriesFiles)
|
||||
foreach(var movieFile in movieFiles)
|
||||
{
|
||||
var episodeFile = seriesFile;
|
||||
var episodeFilePath = Path.Combine(movie.Path, episodeFile.RelativePath);
|
||||
var movieFilePath = Path.Combine(movie.Path, movieFile.RelativePath);
|
||||
|
||||
try
|
||||
{
|
||||
if (!filesOnDiskKeys.Contains(episodeFilePath))
|
||||
if (!filesOnDiskKeys.Contains(movieFilePath))
|
||||
{
|
||||
_logger.Debug("File [{0}] no longer exists on disk, removing from db", episodeFilePath);
|
||||
_mediaFileService.Delete(seriesFile, DeleteMediaFileReason.MissingFromDisk);
|
||||
_logger.Debug("File [{0}] no longer exists on disk, removing from db", movieFilePath);
|
||||
_mediaFileService.Delete(movieFile, DeleteMediaFileReason.MissingFromDisk);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (episodes.None(e => e.EpisodeFileId == episodeFile.Id))
|
||||
{
|
||||
_logger.Debug("File [{0}] is not assigned to any episodes, removing from db", episodeFilePath);
|
||||
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.NoLinkedEpisodes);
|
||||
continue;
|
||||
}
|
||||
//var localMovie = _parsingService.GetLocalMovie(movieFile.Path, movie);
|
||||
|
||||
// var localEpsiode = _parsingService.GetLocalEpisode(episodeFile.Path, series);
|
||||
//
|
||||
// if (localEpsiode == null || episodes.Count != localEpsiode.Episodes.Count)
|
||||
// {
|
||||
// _logger.Debug("File [{0}] parsed episodes has changed, removing from db", episodeFile.Path);
|
||||
// _mediaFileService.Delete(episodeFile);
|
||||
// continue;
|
||||
// }
|
||||
//if (localMovie == null)
|
||||
//{
|
||||
// _logger.Debug("File [{0}] parsed episodes has changed, removing from db", localMovie.Path);
|
||||
// _mediaFileService.Delete(localMovie);
|
||||
// continue;
|
||||
//}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorMessage = string.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id);
|
||||
var errorMessage = string.Format("Unable to cleanup MovieFile in DB: {0}", movieFile.Id);
|
||||
_logger.Error(ex, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var e in episodes)
|
||||
{
|
||||
var episode = e;
|
||||
|
||||
if (episode.EpisodeFileId > 0 && seriesFiles.None(f => f.Id == episode.EpisodeFileId))
|
||||
{
|
||||
episode.EpisodeFileId = 0;
|
||||
_episodeService.UpdateEpisode(episode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,12 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
return AudioChannelPositionsText.ContainsIgnoreCase("LFE") ? AudioChannels - 1 + 0.1m : AudioChannels;
|
||||
}
|
||||
|
||||
return AudioChannelPositions.Split('/').Sum(s => decimal.Parse(s, CultureInfo.InvariantCulture));
|
||||
return
|
||||
AudioChannelPositions.Replace("Object Based /", "").Replace(" / ", "$")
|
||||
.Split('$')
|
||||
.First()
|
||||
.Split('/')
|
||||
.Sum(s => decimal.Parse(s, CultureInfo.InvariantCulture));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
switch (_configService.FileDate)
|
||||
{
|
||||
case FileDateType.LocalAirDate:
|
||||
case FileDateType.Release:
|
||||
{
|
||||
var airDate = episodes.First().AirDate;
|
||||
var airTime = series.AirTime;
|
||||
@@ -62,7 +62,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
return ChangeFileDateToLocalAirDate(episodeFilePath, airDate, airTime);
|
||||
}
|
||||
|
||||
case FileDateType.UtcAirDate:
|
||||
case FileDateType.Cinemas:
|
||||
{
|
||||
var airDateUtc = episodes.First().AirDateUtc;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -20,7 +20,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
}
|
||||
|
||||
public class UpdateMovieFileService : IUpdateMovieFileService,
|
||||
IHandle<SeriesScannedEvent>
|
||||
IHandle<MovieScannedEvent>
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly IConfigService _configService;
|
||||
@@ -47,17 +47,67 @@ namespace NzbDrone.Core.MediaFiles
|
||||
{
|
||||
var movieFilePath = Path.Combine(movie.Path, movieFile.RelativePath);
|
||||
|
||||
switch (_configService.FileDate)
|
||||
{
|
||||
case FileDateType.Release:
|
||||
{
|
||||
var airDate = movie.PhysicalRelease;
|
||||
|
||||
if (airDate == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ChangeFileDate(movieFilePath, airDate.Value);
|
||||
}
|
||||
|
||||
case FileDateType.Cinemas:
|
||||
{
|
||||
var airDate = movie.InCinemas;
|
||||
|
||||
if (airDate == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ChangeFileDate(movieFilePath, airDate.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Handle(SeriesScannedEvent message)
|
||||
private bool ChangeFileDate(string filePath, DateTime date)
|
||||
{
|
||||
DateTime oldDateTime = _diskProvider.FileGetLastWrite(filePath);
|
||||
|
||||
if (!DateTime.Equals(date, oldDateTime))
|
||||
{
|
||||
try
|
||||
{
|
||||
_diskProvider.FileSetLastWriteTime(filePath, date);
|
||||
_logger.Debug("Date of file [{0}] changed from '{1}' to '{2}'", filePath, oldDateTime, date);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Unable to set date of file [" + filePath + "]");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Handle(MovieScannedEvent message)
|
||||
{
|
||||
if (_configService.FileDate == FileDateType.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* var movies = _movieService.MoviesWithFiles(message.Series.Id);
|
||||
var movies = _movieService.MoviesWithFiles(message.Movie.Id);
|
||||
|
||||
var movieFiles = new List<MovieFile>();
|
||||
var updated = new List<MovieFile>();
|
||||
@@ -69,7 +119,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
movieFiles.Add(movieFile);
|
||||
|
||||
if (ChangeFileDate(movieFile, message.Series, moviesInFile))
|
||||
if (ChangeFileDate(movieFile, message.Movie))
|
||||
{
|
||||
updated.Add(movieFile);
|
||||
}
|
||||
@@ -77,13 +127,13 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
if (updated.Any())
|
||||
{
|
||||
_logger.ProgressDebug("Changed file date for {0} files of {1} in {2}", updated.Count, movieFiles.Count, message.Series.Title);
|
||||
_logger.ProgressDebug("Changed file date for {0} files of {1} in {2}", updated.Count, movieFiles.Count, message.Movie.Title);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_logger.ProgressDebug("No file dates changed for {0}", message.Series.Title);
|
||||
}*/
|
||||
_logger.ProgressDebug("No file dates changed for {0}", message.Movie.Title);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ChangeFileDateToLocalAirDate(string filePath, string fileDate, string fileTime)
|
||||
|
||||
@@ -38,10 +38,13 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
public MovieFileMoveResult UpgradeMovieFile(MovieFile episodeFile, LocalMovie localEpisode, bool copyOnly = false)
|
||||
{
|
||||
_logger.Trace("Upgrading existing episode file.");
|
||||
var moveFileResult = new MovieFileMoveResult();
|
||||
localEpisode.Movie.MovieFile.LazyLoad();
|
||||
var existingFile = localEpisode.Movie.MovieFile;
|
||||
existingFile.LazyLoad();
|
||||
|
||||
if (existingFile.IsLoaded)
|
||||
if (existingFile.IsLoaded && existingFile.Value != null)
|
||||
{
|
||||
var file = existingFile.Value;
|
||||
var episodeFilePath = Path.Combine(localEpisode.Movie.Path, file.RelativePath);
|
||||
@@ -55,6 +58,10 @@ namespace NzbDrone.Core.MediaFiles
|
||||
moveFileResult.OldFiles.Add(file);
|
||||
_mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("The existing movie file was not lazy loaded.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource
|
||||
@@ -7,6 +8,6 @@ namespace NzbDrone.Core.MetadataSource
|
||||
public interface IProvideMovieInfo
|
||||
{
|
||||
Movie GetMovieInfo(string ImdbId);
|
||||
Movie GetMovieInfo(int TmdbId);
|
||||
Movie GetMovieInfo(int TmdbId, Profile profile);
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
public int vote_count { get; set; }
|
||||
public AlternativeTitles alternative_titles { get; set; }
|
||||
public ReleaseDatesResource release_dates { get; set; }
|
||||
public VideosResource videos { get; set; }
|
||||
}
|
||||
|
||||
public class ReleaseDatesResource
|
||||
@@ -130,4 +131,21 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
||||
public string iso_3166_1 { get; set; }
|
||||
public string title { get; set; }
|
||||
}
|
||||
|
||||
public class VideosResource
|
||||
{
|
||||
public List<Video> results { get; set; }
|
||||
}
|
||||
|
||||
public class Video
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string iso_639_1 { get; set; }
|
||||
public string iso_3166_1 { get; set; }
|
||||
public string key { get; set; }
|
||||
public string name { get; set; }
|
||||
public string site { get; set; }
|
||||
public string size { get; set; }
|
||||
public string type { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ using NzbDrone.Core.Tv;
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Profiles;
|
||||
|
||||
namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
{
|
||||
@@ -67,31 +69,45 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
return new Tuple<Series, List<Episode>>(series, episodes.ToList());
|
||||
}
|
||||
|
||||
public Movie GetMovieInfo(int TmdbId)
|
||||
public Movie GetMovieInfo(int TmdbId, Profile profile = null)
|
||||
{
|
||||
var langCode = profile != null ? IsoLanguages.Get(profile.Language).TwoLetterCode : "us";
|
||||
|
||||
var request = _movieBuilder.Create()
|
||||
.SetSegment("route", "movie")
|
||||
.SetSegment("id", TmdbId.ToString())
|
||||
.SetSegment("secondaryRoute", "")
|
||||
.AddQueryParam("append_to_response", "alternative_titles,release_dates")
|
||||
.AddQueryParam("country", "US")
|
||||
.AddQueryParam("append_to_response", "alternative_titles,release_dates,videos")
|
||||
.AddQueryParam("language", langCode.ToUpper())
|
||||
// .AddQueryParam("country", "US")
|
||||
.Build();
|
||||
|
||||
request.AllowAutoRedirect = true;
|
||||
request.SuppressHttpError = true;
|
||||
|
||||
var response = _httpClient.Get<MovieResourceRoot>(request);
|
||||
|
||||
var resource = response.Resource;
|
||||
|
||||
var movie = new Movie();
|
||||
|
||||
foreach (var alternativeTitle in resource.alternative_titles.titles)
|
||||
{
|
||||
if (alternativeTitle.iso_3166_1.ToLower() == langCode)
|
||||
{
|
||||
movie.AlternativeTitles.Add(alternativeTitle.title);
|
||||
}
|
||||
else if (alternativeTitle.iso_3166_1.ToLower() == "us")
|
||||
{
|
||||
movie.AlternativeTitles.Add(alternativeTitle.title);
|
||||
}
|
||||
}
|
||||
|
||||
movie.TmdbId = TmdbId;
|
||||
movie.ImdbId = resource.imdb_id;
|
||||
movie.Title = resource.title;
|
||||
movie.TitleSlug = ToUrlSlug(movie.Title);
|
||||
movie.CleanTitle = Parser.Parser.CleanSeriesTitle(movie.Title);
|
||||
movie.SortTitle = Parser.Parser.NormalizeTitle(movie.Title);
|
||||
movie.TitleSlug = ToUrlSlug(resource.title);
|
||||
movie.CleanTitle = Parser.Parser.CleanSeriesTitle(resource.title);
|
||||
movie.SortTitle = Parser.Parser.NormalizeTitle(resource.title);
|
||||
movie.Overview = resource.overview;
|
||||
movie.Website = resource.homepage;
|
||||
if (resource.release_date.IsNotNullOrWhiteSpace())
|
||||
@@ -106,10 +122,10 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
movie.Images.Add(_configService.GetCoverForURL(resource.backdrop_path, MediaCoverTypes.Banner));
|
||||
movie.Runtime = resource.runtime;
|
||||
|
||||
foreach(Title title in resource.alternative_titles.titles)
|
||||
{
|
||||
movie.AlternativeTitles.Add(title.title);
|
||||
}
|
||||
//foreach(Title title in resource.alternative_titles.titles)
|
||||
//{
|
||||
// movie.AlternativeTitles.Add(title.title);
|
||||
//}
|
||||
|
||||
foreach(ReleaseDates releaseDates in resource.release_dates.results)
|
||||
{
|
||||
@@ -150,6 +166,29 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
movie.Status = MovieStatusType.Announced;
|
||||
}
|
||||
|
||||
if (resource.videos != null)
|
||||
{
|
||||
foreach (Video video in resource.videos.results)
|
||||
{
|
||||
if (video.type == "Trailer" && video.site == "YouTube")
|
||||
{
|
||||
if (video.key != null)
|
||||
{
|
||||
movie.YouTubeTrailerId = video.key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource.production_companies != null)
|
||||
{
|
||||
if (resource.production_companies.Any())
|
||||
{
|
||||
movie.Studio = resource.production_companies[0].name;
|
||||
}
|
||||
}
|
||||
|
||||
return movie;
|
||||
}
|
||||
|
||||
@@ -186,6 +225,8 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
{
|
||||
var lowerTitle = title.ToLower();
|
||||
|
||||
lowerTitle = lowerTitle.Replace(".", "");
|
||||
|
||||
var parserResult = Parser.Parser.ParseMovieTitle(title, true);
|
||||
|
||||
var yearTerm = "";
|
||||
@@ -193,7 +234,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
if (parserResult != null && parserResult.MovieTitle != title)
|
||||
{
|
||||
//Parser found something interesting!
|
||||
lowerTitle = parserResult.MovieTitle.ToLower();
|
||||
lowerTitle = parserResult.MovieTitle.ToLower().Replace(".", " "); //TODO Update so not every period gets replaced (e.g. R.I.P.D.)
|
||||
if (parserResult.Year > 1800)
|
||||
{
|
||||
yearTerm = parserResult.Year.ToString();
|
||||
@@ -326,25 +367,19 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
||||
{
|
||||
imdbMovie.SortTitle = Parser.Parser.NormalizeTitle(result.title);
|
||||
imdbMovie.Title = result.title;
|
||||
string titleSlug = ToUrlSlug(result.title);
|
||||
imdbMovie.TitleSlug = titleSlug.ToLower().Replace(" ", "-");
|
||||
imdbMovie.TitleSlug = ToUrlSlug(result.title);
|
||||
|
||||
if (result.release_date.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
imdbMovie.Year = DateTime.Parse(result.release_date).Year;
|
||||
}
|
||||
//var slugResult = _movieService.FindByTitleSlug(imdbMovie.TitleSlug);
|
||||
//if (slugResult != null)
|
||||
//{
|
||||
// _logger.Debug("Movie with this title slug already exists. Adding year...");
|
||||
//}
|
||||
imdbMovie.TitleSlug += "-" + imdbMovie.Year.ToString();
|
||||
|
||||
imdbMovie.TitleSlug += "-" + imdbMovie.Year;
|
||||
|
||||
imdbMovie.Images = new List<MediaCover.MediaCover>();
|
||||
imdbMovie.Overview = result.overview;
|
||||
try
|
||||
{
|
||||
string url = result.poster_path;
|
||||
var imdbPoster = _configService.GetCoverForURL(result.poster_path, MediaCoverTypes.Poster);
|
||||
imdbMovie.Images.Add(imdbPoster);
|
||||
}
|
||||
|
||||
@@ -18,18 +18,22 @@ namespace NzbDrone.Core.Notifications.Boxcar
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
const string title = "Movie Grabbed";
|
||||
|
||||
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
const string title = "Movie Downloaded";
|
||||
|
||||
_proxy.SendNotification(title, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -24,75 +25,65 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string Link => "https://github.com/Sonarr/Sonarr/wiki/Custom-Post-Processing-Scripts";
|
||||
public override string Link => "https://github.com/Radarr/Radarr/wiki/Custom-Post-Processing-Scripts";
|
||||
|
||||
public override void OnGrab(GrabMessage message)
|
||||
{
|
||||
var series = message.Series;
|
||||
var remoteEpisode = message.Episode;
|
||||
var releaseGroup = remoteEpisode.ParsedEpisodeInfo.ReleaseGroup;
|
||||
var movie = message.Movie;
|
||||
var remoteMovie = message.RemoteMovie;
|
||||
var releaseGroup = remoteMovie.ParsedMovieInfo.ReleaseGroup;
|
||||
var environmentVariables = new StringDictionary();
|
||||
|
||||
environmentVariables.Add("Sonarr_EventType", "Grab");
|
||||
environmentVariables.Add("Sonarr_Series_Id", series.Id.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_Title", series.Title);
|
||||
environmentVariables.Add("Sonarr_Series_TvdbId", series.TvdbId.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_Type", series.SeriesType.ToString());
|
||||
environmentVariables.Add("Sonarr_Release_EpisodeCount", remoteEpisode.Episodes.Count.ToString());
|
||||
environmentVariables.Add("Sonarr_Release_SeasonNumber", remoteEpisode.ParsedEpisodeInfo.SeasonNumber.ToString());
|
||||
environmentVariables.Add("Sonarr_Release_EpisodeNumbers", string.Join(",", remoteEpisode.Episodes.Select(e => e.EpisodeNumber)));
|
||||
environmentVariables.Add("Sonarr_Release_Title", remoteEpisode.Release.Title);
|
||||
environmentVariables.Add("Sonarr_Release_Indexer", remoteEpisode.Release.Indexer);
|
||||
environmentVariables.Add("Sonarr_Release_Size", remoteEpisode.Release.Size.ToString());
|
||||
environmentVariables.Add("Sonarr_Release_ReleaseGroup", releaseGroup);
|
||||
environmentVariables.Add("Radarr_EventType", "Grab");
|
||||
environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString());
|
||||
environmentVariables.Add("Radarr_Movie_Title", movie.Title);
|
||||
environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId.ToString());
|
||||
environmentVariables.Add("Radarr_Release_Title", remoteMovie.Release.Title);
|
||||
environmentVariables.Add("Radarr_Release_Indexer", remoteMovie.Release.Indexer);
|
||||
environmentVariables.Add("Radarr_Release_Size", remoteMovie.Release.Size.ToString());
|
||||
environmentVariables.Add("Radarr_Release_ReleaseGroup", releaseGroup);
|
||||
|
||||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
var series = message.Series;
|
||||
var episodeFile = message.EpisodeFile;
|
||||
var movie = message.Movie;
|
||||
var movieFile = message.MovieFile;
|
||||
var sourcePath = message.SourcePath;
|
||||
var environmentVariables = new StringDictionary();
|
||||
|
||||
environmentVariables.Add("Sonarr_EventType", "Download");
|
||||
environmentVariables.Add("Sonarr_Series_Id", series.Id.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_Title", series.Title);
|
||||
environmentVariables.Add("Sonarr_Series_Path", series.Path);
|
||||
environmentVariables.Add("Sonarr_Series_TvdbId", series.TvdbId.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_Type", series.SeriesType.ToString());
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_Id", episodeFile.Id.ToString());
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeCount", episodeFile.Episodes.Value.Count.ToString());
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_RelativePath", episodeFile.RelativePath);
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_Path", Path.Combine(series.Path, episodeFile.RelativePath));
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_SeasonNumber", episodeFile.SeasonNumber.ToString());
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeNumbers", string.Join(",", episodeFile.Episodes.Value.Select(e => e.EpisodeNumber)));
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeAirDates", string.Join(",", episodeFile.Episodes.Value.Select(e => e.AirDate)));
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeAirDatesUtc", string.Join(",", episodeFile.Episodes.Value.Select(e => e.AirDateUtc)));
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_EpisodeTitles", string.Join("|", episodeFile.Episodes.Value.Select(e => e.Title)));
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_Quality", episodeFile.Quality.Quality.Name);
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_QualityVersion", episodeFile.Quality.Revision.Version.ToString());
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_ReleaseGroup", episodeFile.ReleaseGroup ?? string.Empty);
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_SceneName", episodeFile.SceneName ?? string.Empty);
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_SourcePath", sourcePath);
|
||||
environmentVariables.Add("Sonarr_EpisodeFile_SourceFolder", Path.GetDirectoryName(sourcePath));
|
||||
environmentVariables.Add("Radarr_EventType", "Download");
|
||||
environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString());
|
||||
environmentVariables.Add("Radarr_Movie_Title", movie.Title);
|
||||
environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId.ToString());
|
||||
environmentVariables.Add("Radarr_MovieFile_Id", movieFile.Id.ToString());
|
||||
environmentVariables.Add("Radarr_MovieFile_RelativePath", movieFile.RelativePath);
|
||||
environmentVariables.Add("Radarr_MovieFile_Path", Path.Combine(movie.Path, movieFile.RelativePath));
|
||||
environmentVariables.Add("Radarr_MovieFile_Quality", movieFile.Quality.Quality.Name);
|
||||
environmentVariables.Add("Radarr_MovieFile_QualityVersion", movieFile.Quality.Revision.Version.ToString());
|
||||
environmentVariables.Add("Radarr_MovieFile_ReleaseGroup", movieFile.ReleaseGroup ?? string.Empty);
|
||||
environmentVariables.Add("Radarr_MovieFile_SceneName", movieFile.SceneName ?? string.Empty);
|
||||
environmentVariables.Add("Radarr_MovieFile_SourcePath", sourcePath);
|
||||
environmentVariables.Add("Radarr_MovieFile_SourceFolder", Path.GetDirectoryName(sourcePath));
|
||||
|
||||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
var environmentVariables = new StringDictionary();
|
||||
|
||||
environmentVariables.Add("Radarr_EventType", "Rename");
|
||||
environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString());
|
||||
environmentVariables.Add("Radarr_Movie_Title", movie.Title);
|
||||
environmentVariables.Add("Radarr_Movie_Path", movie.Path);
|
||||
environmentVariables.Add("Radarr_Movie_TvdbId", movie.ImdbId.ToString());
|
||||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
var environmentVariables = new StringDictionary();
|
||||
|
||||
environmentVariables.Add("Sonarr_EventType", "Rename");
|
||||
environmentVariables.Add("Sonarr_Series_Id", series.Id.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_Title", series.Title);
|
||||
environmentVariables.Add("Sonarr_Series_Path", series.Path);
|
||||
environmentVariables.Add("Sonarr_Series_TvdbId", series.TvdbId.ToString());
|
||||
environmentVariables.Add("Sonarr_Series_Type", series.SeriesType.ToString());
|
||||
|
||||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
|
||||
public override string Name => "Custom Script";
|
||||
|
||||
@@ -8,8 +8,11 @@ namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public Series Series { get; set; }
|
||||
public Movie Movie { get; set; }
|
||||
public EpisodeFile EpisodeFile { get; set; }
|
||||
public List<EpisodeFile> OldFiles { get; set; }
|
||||
public MovieFile MovieFile { get; set; }
|
||||
public List<MovieFile> OldMovieFiles { get; set; }
|
||||
public string SourcePath { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.Notifications.Email
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string subject = "Radarr [TV] - Grabbed";
|
||||
const string subject = "Radarr [Movie] - Grabbed";
|
||||
var body = string.Format("{0} sent to queue.", grabMessage.Message);
|
||||
|
||||
_emailService.SendEmail(Settings, subject, body);
|
||||
@@ -26,12 +26,16 @@ namespace NzbDrone.Core.Notifications.Email
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string subject = "Radarr [TV] - Downloaded";
|
||||
const string subject = "Radarr [Movie] - Downloaded";
|
||||
var body = string.Format("{0} Downloaded and sorted.", message.Message);
|
||||
|
||||
_emailService.SendEmail(Settings, subject, body);
|
||||
}
|
||||
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public Series Series { get; set; }
|
||||
public Movie Movie { get; set; }
|
||||
public RemoteMovie RemoteMovie { get; set; }
|
||||
public RemoteEpisode Episode { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
|
||||
|
||||
@@ -18,18 +18,22 @@ namespace NzbDrone.Core.Notifications.Growl
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
const string title = "Movie Grabbed";
|
||||
|
||||
_growlService.SendNotification(title, grabMessage.Message, "GRAB", Settings.Host, Settings.Port, Settings.Password);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
const string title = "Movie Downloaded";
|
||||
|
||||
_growlService.SendNotification(title, message.Message, "DOWNLOAD", Settings.Host, Settings.Port, Settings.Password);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace NzbDrone.Core.Notifications
|
||||
void OnGrab(GrabMessage grabMessage);
|
||||
void OnDownload(DownloadMessage message);
|
||||
void OnRename(Series series);
|
||||
void OnMovieRename(Movie movie);
|
||||
bool SupportsOnGrab { get; }
|
||||
bool SupportsOnDownload { get; }
|
||||
bool SupportsOnUpgrade { get; }
|
||||
|
||||
@@ -18,18 +18,22 @@ namespace NzbDrone.Core.Notifications.Join
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Radarr - Episode Grabbed";
|
||||
const string title = "Radarr - Movie Grabbed";
|
||||
|
||||
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Radarr - Episode Downloaded";
|
||||
const string title = "Radarr - Movie Downloaded";
|
||||
|
||||
_proxy.SendNotification(title, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace NzbDrone.Core.Notifications.Join
|
||||
request.AddParameter("apikey", settings.ApiKey);
|
||||
request.AddParameter("title", title);
|
||||
request.AddParameter("text", message);
|
||||
request.AddParameter("icon", "https://cdn.rawgit.com/Sonarr/Sonarr/develop/Logo/256.png"); // Use the Sonarr logo.
|
||||
request.AddParameter("icon", "https://cdn.rawgit.com/Radarr/Radarr/develop/Logo/256.png"); // Use the Radarr logo.
|
||||
|
||||
var response = client.ExecuteAndValidate(request);
|
||||
var res = Json.Deserialize<JoinResponseModel>(response.Content);
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Radarr - Grabbed";
|
||||
const string title = "Radarr - Movie Grabbed";
|
||||
|
||||
if (Settings.Notify)
|
||||
{
|
||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Radarr - Downloaded";
|
||||
const string title = "Radarr - Movie Downloaded";
|
||||
|
||||
if (Settings.Notify)
|
||||
{
|
||||
@@ -41,6 +41,10 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
if (Settings.UpdateLibrary)
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace NzbDrone.Core.Notifications
|
||||
public abstract void OnGrab(GrabMessage grabMessage);
|
||||
public abstract void OnDownload(DownloadMessage message);
|
||||
public abstract void OnRename(Series series);
|
||||
public abstract void OnMovieRename(Movie movie);
|
||||
|
||||
public virtual bool SupportsOnGrab => true;
|
||||
public virtual bool SupportsOnDownload => true;
|
||||
|
||||
@@ -15,7 +15,11 @@ namespace NzbDrone.Core.Notifications
|
||||
public class NotificationService
|
||||
: IHandle<EpisodeGrabbedEvent>,
|
||||
IHandle<EpisodeDownloadedEvent>,
|
||||
IHandle<SeriesRenamedEvent>
|
||||
IHandle<SeriesRenamedEvent>,
|
||||
IHandle<MovieRenamedEvent>,
|
||||
IHandle<MovieGrabbedEvent>,
|
||||
IHandle<MovieDownloadedEvent>
|
||||
|
||||
{
|
||||
private readonly INotificationFactory _notificationFactory;
|
||||
private readonly Logger _logger;
|
||||
@@ -67,6 +71,41 @@ namespace NzbDrone.Core.Notifications
|
||||
qualityString);
|
||||
}
|
||||
|
||||
private string GetMessage(Movie movie, QualityModel quality)
|
||||
{
|
||||
var qualityString = quality.Quality.ToString();
|
||||
|
||||
if (quality.Revision.Version > 1)
|
||||
{
|
||||
qualityString += " Proper";
|
||||
}
|
||||
|
||||
return string.Format("{0} [{1}]",
|
||||
movie.Title,
|
||||
qualityString);
|
||||
}
|
||||
|
||||
private bool ShouldHandleMovie(ProviderDefinition definition, Movie movie)
|
||||
{
|
||||
var notificationDefinition = (NotificationDefinition)definition;
|
||||
|
||||
if (notificationDefinition.Tags.Empty())
|
||||
{
|
||||
_logger.Debug("No tags set for this notification.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (notificationDefinition.Tags.Intersect(movie.Tags).Any())
|
||||
{
|
||||
_logger.Debug("Notification and series have one or more matching tags.");
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO: this message could be more clear
|
||||
_logger.Debug("{0} does not have any tags that match {1}'s tags", notificationDefinition.Name, movie.Title);
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ShouldHandleSeries(ProviderDefinition definition, Series series)
|
||||
{
|
||||
var notificationDefinition = (NotificationDefinition) definition;
|
||||
@@ -112,6 +151,33 @@ namespace NzbDrone.Core.Notifications
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(MovieGrabbedEvent message)
|
||||
{
|
||||
var grabMessage = new GrabMessage
|
||||
{
|
||||
Message = GetMessage(message.Movie.Movie, message.Movie.ParsedMovieInfo.Quality),
|
||||
Series = null,
|
||||
Quality = message.Movie.ParsedMovieInfo.Quality,
|
||||
Episode = null,
|
||||
Movie = message.Movie.Movie,
|
||||
RemoteMovie = message.Movie
|
||||
};
|
||||
|
||||
foreach (var notification in _notificationFactory.OnGrabEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ShouldHandleMovie(notification.Definition, message.Movie.Movie)) continue;
|
||||
notification.OnGrab(grabMessage);
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send OnGrab notification to: " + notification.Definition.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(EpisodeDownloadedEvent message)
|
||||
{
|
||||
var downloadMessage = new DownloadMessage();
|
||||
@@ -141,6 +207,38 @@ namespace NzbDrone.Core.Notifications
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(MovieDownloadedEvent message)
|
||||
{
|
||||
var downloadMessage = new DownloadMessage();
|
||||
downloadMessage.Message = GetMessage(message.Movie.Movie, message.Movie.Quality);
|
||||
downloadMessage.Series = null;
|
||||
downloadMessage.EpisodeFile = null;
|
||||
downloadMessage.MovieFile = message.MovieFile;
|
||||
downloadMessage.Movie = message.Movie.Movie;
|
||||
downloadMessage.OldFiles = null;
|
||||
downloadMessage.OldMovieFiles = message.OldFiles;
|
||||
downloadMessage.SourcePath = message.Movie.Path;
|
||||
|
||||
foreach (var notification in _notificationFactory.OnDownloadEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ShouldHandleMovie(notification.Definition, message.Movie.Movie))
|
||||
{
|
||||
if (downloadMessage.OldMovieFiles.Empty() || ((NotificationDefinition)notification.Definition).OnUpgrade)
|
||||
{
|
||||
notification.OnDownload(downloadMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Unable to send OnDownload notification to: " + notification.Definition.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(SeriesRenamedEvent message)
|
||||
{
|
||||
foreach (var notification in _notificationFactory.OnRenameEnabled())
|
||||
@@ -159,5 +257,24 @@ namespace NzbDrone.Core.Notifications
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(MovieRenamedEvent message)
|
||||
{
|
||||
foreach (var notification in _notificationFactory.OnRenameEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ShouldHandleMovie(notification.Definition, message.Movie))
|
||||
{
|
||||
notification.OnMovieRename(message.Movie);
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Unable to send OnRename notification to: " + notification.Definition.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,18 +19,22 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
const string title = "Movie Grabbed";
|
||||
|
||||
_proxy.SendNotification(title, grabMessage.Message, Settings.ApiKey, (NotifyMyAndroidPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
const string title = "Movie Downloaded";
|
||||
|
||||
_proxy.SendNotification(title, message.Message, Settings.ApiKey, (NotifyMyAndroidPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
_plexClientService.Notify(Settings, header, message.Message);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
Notify(Settings, header, message.Message);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
|
||||
|
||||
@@ -22,19 +22,24 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
UpdateIfEnabled(message.Series);
|
||||
UpdateIfEnabled(message.Movie);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
UpdateIfEnabled(movie);
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
UpdateIfEnabled(series);
|
||||
//UpdateIfEnabled(movie);
|
||||
}
|
||||
|
||||
private void UpdateIfEnabled(Series series)
|
||||
private void UpdateIfEnabled(Movie movie)
|
||||
{
|
||||
if (Settings.UpdateLibrary)
|
||||
{
|
||||
_plexServerService.UpdateLibrary(series, Settings);
|
||||
_plexServerService.UpdateMovieSections(movie, Settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
public interface IPlexServerProxy
|
||||
{
|
||||
List<PlexSection> GetTvSections(PlexServerSettings settings);
|
||||
List<PlexSection> GetMovieSections(PlexServerSettings settings);
|
||||
void Update(int sectionId, PlexServerSettings settings);
|
||||
void UpdateSeries(int metadataId, PlexServerSettings settings);
|
||||
string Version(PlexServerSettings settings);
|
||||
@@ -66,6 +67,37 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<PlexSection> GetMovieSections(PlexServerSettings settings)
|
||||
{
|
||||
var request = GetPlexServerRequest("library/sections", Method.GET, settings);
|
||||
var client = GetPlexServerClient(settings);
|
||||
var response = client.Execute(request);
|
||||
|
||||
_logger.Trace("Sections response: {0}", response.Content);
|
||||
CheckForError(response, settings);
|
||||
|
||||
if (response.Content.Contains("_children"))
|
||||
{
|
||||
return Json.Deserialize<PlexMediaContainerLegacy>(response.Content)
|
||||
.Sections
|
||||
.Where(d => d.Type == "movie")
|
||||
.Select(s => new PlexSection
|
||||
{
|
||||
Id = s.Id,
|
||||
Language = s.Language,
|
||||
Locations = s.Locations,
|
||||
Type = s.Type
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return Json.Deserialize<PlexResponse<PlexSectionsContainer>>(response.Content)
|
||||
.MediaContainer
|
||||
.Sections
|
||||
.Where(d => d.Type == "movie")
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public void Update(int sectionId, PlexServerSettings settings)
|
||||
{
|
||||
var resource = string.Format("library/sections/{0}/refresh", sectionId);
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
public interface IPlexServerService
|
||||
{
|
||||
void UpdateLibrary(Series series, PlexServerSettings settings);
|
||||
void UpdateMovieSections(Movie movie, PlexServerSettings settings);
|
||||
ValidationFailure Test(PlexServerSettings settings);
|
||||
}
|
||||
|
||||
@@ -62,11 +63,43 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateMovieSections(Movie movie, PlexServerSettings settings)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Debug("Sending Update Request to Plex Server");
|
||||
|
||||
var version = _versionCache.Get(settings.Host, () => GetVersion(settings), TimeSpan.FromHours(2));
|
||||
ValidateVersion(version);
|
||||
|
||||
var sections = GetSections(settings);
|
||||
var partialUpdates = _partialUpdateCache.Get(settings.Host, () => PartialUpdatesAllowed(settings, version), TimeSpan.FromHours(2));
|
||||
|
||||
// TODO: Investiate partial updates later, for now just update all movie sections...
|
||||
|
||||
//if (partialUpdates)
|
||||
//{
|
||||
// UpdatePartialSection(series, sections, settings);
|
||||
//}
|
||||
|
||||
//else
|
||||
//{
|
||||
sections.ForEach(s => UpdateSection(s.Id, settings));
|
||||
//}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Failed to Update Plex host: " + settings.Host);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private List<PlexSection> GetSections(PlexServerSettings settings)
|
||||
{
|
||||
_logger.Debug("Getting sections from Plex host: {0}", settings.Host);
|
||||
|
||||
return _plexServerProxy.GetTvSections(settings).ToList();
|
||||
return _plexServerProxy.GetMovieSections(settings).ToList();
|
||||
}
|
||||
|
||||
private bool PartialUpdatesAllowed(PlexServerSettings settings, Version version)
|
||||
|
||||
@@ -19,18 +19,22 @@ namespace NzbDrone.Core.Notifications.Prowl
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
const string title = "Movie Grabbed";
|
||||
|
||||
_prowlService.SendNotification(title, grabMessage.Message, Settings.ApiKey, (NotificationPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
const string title = "Movie Downloaded";
|
||||
|
||||
_prowlService.SendNotification(title, message.Message, Settings.ApiKey, (NotificationPriority)Settings.Priority);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -18,18 +18,22 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Radarr - Episode Grabbed";
|
||||
const string title = "Radarr - Movie Grabbed";
|
||||
|
||||
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Radarr - Episode Downloaded";
|
||||
const string title = "Radarr - Movie Downloaded";
|
||||
|
||||
_proxy.SendNotification(title, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -18,18 +18,22 @@ namespace NzbDrone.Core.Notifications.Pushalot
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
const string title = "Movie Grabbed";
|
||||
|
||||
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
const string title = "Movie Downloaded";
|
||||
|
||||
_proxy.SendNotification(title, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -18,18 +18,22 @@ namespace NzbDrone.Core.Notifications.Pushover
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
const string title = "Movie Grabbed";
|
||||
|
||||
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
const string title = "Movie Downloaded";
|
||||
|
||||
_proxy.SendNotification(title, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
public enum PushoverPriority
|
||||
{
|
||||
Silent = -1,
|
||||
Silent = -2,
|
||||
Quiet = -1,
|
||||
Normal = 0,
|
||||
High = 1,
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Notifications.Slack
|
||||
new Attachment
|
||||
{
|
||||
Fallback = message.Message,
|
||||
Title = message.Series.Title,
|
||||
Title = message.Movie.Title,
|
||||
Text = message.Message,
|
||||
Color = "warning"
|
||||
}
|
||||
@@ -59,7 +59,7 @@ namespace NzbDrone.Core.Notifications.Slack
|
||||
new Attachment
|
||||
{
|
||||
Fallback = message.Message,
|
||||
Title = message.Series.Title,
|
||||
Title = message.Movie.Title,
|
||||
Text = message.Message,
|
||||
Color = "good"
|
||||
}
|
||||
@@ -69,6 +69,25 @@ namespace NzbDrone.Core.Notifications.Slack
|
||||
NotifySlack(payload);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
var payload = new SlackPayload
|
||||
{
|
||||
IconEmoji = Settings.Icon,
|
||||
Username = Settings.Username,
|
||||
Text = "Renamed",
|
||||
Attachments = new List<Attachment>
|
||||
{
|
||||
new Attachment
|
||||
{
|
||||
Title = movie.Title,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NotifySlack(payload);
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
var payload = new SlackPayload
|
||||
|
||||
@@ -42,6 +42,10 @@ namespace NzbDrone.Core.Notifications.Synology
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
if (Settings.UpdateLibrary)
|
||||
|
||||
@@ -18,18 +18,22 @@ namespace NzbDrone.Core.Notifications.Telegram
|
||||
|
||||
public override void OnGrab(GrabMessage grabMessage)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
const string title = "Movie Grabbed";
|
||||
|
||||
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnDownload(DownloadMessage message)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
const string title = "Movie Downloaded";
|
||||
|
||||
_proxy.SendNotification(title, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@ namespace NzbDrone.Core.Notifications.Twitter
|
||||
_twitterService.SendNotification($"Imported: {message.Message}", Settings);
|
||||
}
|
||||
|
||||
public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||