mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-18 21:35:51 -04:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a8d944397 | ||
|
|
0b70a5c315 | ||
|
|
91cded3b71 | ||
|
|
84112dc85b | ||
|
|
b1b947ae7f | ||
|
|
1b035f8657 | ||
|
|
9d50f4d651 | ||
|
|
c06a6dc988 | ||
|
|
f198ca2b77 | ||
|
|
9cfc766889 | ||
|
|
5ef1e40403 | ||
|
|
c9e6835d7b | ||
|
|
604cea00f6 | ||
|
|
b4782da1d1 | ||
|
|
d5504043c5 | ||
|
|
81ebbcad70 | ||
|
|
92e9dc6ee1 | ||
|
|
5e8b617625 | ||
|
|
2cbe17151d | ||
|
|
95bd615718 | ||
|
|
8e8c4ff497 | ||
|
|
5eddcc1660 | ||
|
|
d42165a93a | ||
|
|
99012d8a40 | ||
|
|
8bc42c76e4 | ||
|
|
b7f72c6259 | ||
|
|
64ef8db037 | ||
|
|
3b5887bf09 | ||
|
|
40a75949ba | ||
|
|
6747267d19 | ||
|
|
13db03f97c | ||
|
|
cd68eea790 | ||
|
|
cfe55d00ae | ||
|
|
1d88313424 | ||
|
|
9513068467 | ||
|
|
9206258370 | ||
|
|
0fa1509ca6 | ||
|
|
c5eb772f7a | ||
|
|
04fec6d4d8 | ||
|
|
d0b5e380d7 | ||
|
|
df69c58d2b | ||
|
|
27114c9399 | ||
|
|
cfca07996b | ||
|
|
e97b80f630 | ||
|
|
792679fd81 | ||
|
|
ecf47d4b17 | ||
|
|
3b1d49a78f | ||
|
|
753f3eb863 | ||
|
|
9fc2d22d19 | ||
|
|
3cb42f06c2 | ||
|
|
a6c396a595 | ||
|
|
bac9076b1e | ||
|
|
b228273be0 | ||
|
|
e7fa4cba19 | ||
|
|
0506cc4185 | ||
|
|
cde8b4dd97 | ||
|
|
0a0a44162c | ||
|
|
125f46fbec | ||
|
|
f3222ca7c7 | ||
|
|
d252a8b232 | ||
|
|
48559cf964 | ||
|
|
c734e8bc7e | ||
|
|
3c7d7756e6 | ||
|
|
683bda49d8 | ||
|
|
52fb29ee18 | ||
|
|
236e16c9a5 | ||
|
|
0584038273 | ||
|
|
6685aea144 | ||
|
|
e4f7aa52df | ||
|
|
f61c4feb00 | ||
|
|
04e8c635e0 | ||
|
|
93ea5cfdee | ||
|
|
1b7288e7cb |
4
CLA.md
4
CLA.md
@@ -1,6 +1,6 @@
|
|||||||
# Sonarr Individual Contributor License Agreement #
|
# Radarr Individual Contributor License Agreement #
|
||||||
|
|
||||||
Thank you for your interest in contributing to Sonarr ("We" or "Us").
|
Thank you for your interest in contributing to Radarr ("We" or "Us").
|
||||||
This contributor agreement ("Agreement") documents the rights granted by contributors to Us. To make this document effective, please complete the form below. This is a legally binding document, so please read it carefully before agreeing to it. The Agreement may cover more than one software project managed by Us.
|
This contributor agreement ("Agreement") documents the rights granted by contributors to Us. To make this document effective, please complete the form below. This is a legally binding document, so please read it carefully before agreeing to it. The Agreement may cover more than one software project managed by Us.
|
||||||
|
|
||||||
## 1. Definitions ##
|
## 1. Definitions ##
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# How to Contribute #
|
# How to Contribute #
|
||||||
|
|
||||||
We're always looking for people to help make Sonarr even better, there are a number of ways to contribute.
|
We're always looking for people to help make Radarr even better, there are a number of ways to contribute.
|
||||||
|
|
||||||
## Documentation ##
|
## Documentation ##
|
||||||
Setup guides, FAQ, the more information we have on the wiki the better.
|
Setup guides, FAQ, the more information we have on the wiki the better.
|
||||||
@@ -15,7 +15,7 @@ Setup guides, FAQ, the more information we have on the wiki the better.
|
|||||||
|
|
||||||
### Getting started ###
|
### Getting started ###
|
||||||
|
|
||||||
1. Fork Sonarr
|
1. Fork Radarr
|
||||||
2. Clone (develop branch) *you may need pull in submodules separately if you client doesn't clone them automatically (CurlSharp)*
|
2. Clone (develop branch) *you may need pull in submodules separately if you client doesn't clone them automatically (CurlSharp)*
|
||||||
3. Run `npm install`
|
3. Run `npm install`
|
||||||
4. Run `npm start` - Used to compile the UI components and copy them.
|
4. Run `npm start` - Used to compile the UI components and copy them.
|
||||||
@@ -24,8 +24,8 @@ Setup guides, FAQ, the more information we have on the wiki the better.
|
|||||||
5. Compile in Visual Studio
|
5. Compile in Visual Studio
|
||||||
|
|
||||||
### Contributing Code ###
|
### Contributing Code ###
|
||||||
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Sonarr/Sonarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
|
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Radarr/Radarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
|
||||||
- Rebase from Sonarr's develop branch, don't merge
|
- Rebase from Radarr's develop branch, don't merge
|
||||||
- Make meaningful commits, or squash them
|
- Make meaningful commits, or squash them
|
||||||
- Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements
|
- Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements
|
||||||
- Reach out to us on the forums or on IRC if you have any questions
|
- Reach out to us on the forums or on IRC if you have any questions
|
||||||
|
|||||||
@@ -35,4 +35,11 @@ artifacts:
|
|||||||
|
|
||||||
cache:
|
cache:
|
||||||
- '%USERPROFILE%\.nuget\packages'
|
- '%USERPROFILE%\.nuget\packages'
|
||||||
- node_modules
|
- node_modules
|
||||||
|
|
||||||
|
only_commits:
|
||||||
|
files:
|
||||||
|
- src/
|
||||||
|
- osx/
|
||||||
|
- gulp/
|
||||||
|
- logo/
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
| Service | Master | Develop |
|
| Service | Master | Develop |
|
||||||
|----------|:---------------------------:|:----------------------------:|
|
|----------|:---------------------------:|:----------------------------:|
|
||||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr) |
|
| 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) |
|
| 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.
|
This fork of Sonarr aims to turn it into something like Couchpotato.
|
||||||
@@ -26,6 +26,11 @@ This fork of Sonarr aims to turn it into something like Couchpotato.
|
|||||||
## Download
|
## Download
|
||||||
The latest precompiled binary versions can be found here: https://github.com/galli-leo/Radarr/releases.
|
The latest precompiled binary versions can be found here: https://github.com/galli-leo/Radarr/releases.
|
||||||
|
|
||||||
|
Docker containers from [linuxserver.io](https://linuxserver.io) can be found here.
|
||||||
|
* [Radarr (x64)](https://hub.docker.com/r/linuxserver/radarr/)
|
||||||
|
* [Radarr (armhf)](https://hub.docker.com/r/lsioarmhf/radarr/)
|
||||||
|
* [Radarr (aarch64)](https://hub.docker.com/r/lsioarmhf/radarr-aarch64/)
|
||||||
|
|
||||||
For more up to date versions (but also sometimes broken), daily builds can be found here:
|
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)
|
* [OSX](https://leonardogalli.ch/radarr/builds/latest.php?os=osx)
|
||||||
* [Windows](https://leonardogalli.ch/radarr/builds/latest.php?os=windows)
|
* [Windows](https://leonardogalli.ch/radarr/builds/latest.php?os=windows)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace NzbDrone.Api.Calendar
|
|||||||
|
|
||||||
Get["/NzbDrone.ics"] = options => GetCalendarFeed();
|
Get["/NzbDrone.ics"] = options => GetCalendarFeed();
|
||||||
Get["/Sonarr.ics"] = options => GetCalendarFeed();
|
Get["/Sonarr.ics"] = options => GetCalendarFeed();
|
||||||
|
Get["/Radarr.ics"] = options => GetCalendarFeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response GetCalendarFeed()
|
private Response GetCalendarFeed()
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ namespace NzbDrone.Api.Config
|
|||||||
Get["/samples"] = x => GetExamples(this.Bind<NamingConfigResource>());
|
Get["/samples"] = x => GetExamples(this.Bind<NamingConfigResource>());
|
||||||
|
|
||||||
SharedValidator.RuleFor(c => c.MultiEpisodeStyle).InclusiveBetween(0, 5);
|
SharedValidator.RuleFor(c => c.MultiEpisodeStyle).InclusiveBetween(0, 5);
|
||||||
SharedValidator.RuleFor(c => c.StandardEpisodeFormat).ValidEpisodeFormat();
|
/*SharedValidator.RuleFor(c => c.StandardEpisodeFormat).ValidEpisodeFormat();
|
||||||
SharedValidator.RuleFor(c => c.DailyEpisodeFormat).ValidDailyEpisodeFormat();
|
SharedValidator.RuleFor(c => c.DailyEpisodeFormat).ValidDailyEpisodeFormat();
|
||||||
SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat();
|
SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat();
|
||||||
SharedValidator.RuleFor(c => c.SeriesFolderFormat).ValidSeriesFolderFormat();
|
SharedValidator.RuleFor(c => c.SeriesFolderFormat).ValidSeriesFolderFormat();
|
||||||
SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat();
|
SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat();*/
|
||||||
SharedValidator.RuleFor(c => c.StandardMovieFormat).ValidMovieFormat();
|
SharedValidator.RuleFor(c => c.StandardMovieFormat).ValidMovieFormat();
|
||||||
SharedValidator.RuleFor(c => c.MovieFolderFormat).ValidMovieFolderFormat();
|
SharedValidator.RuleFor(c => c.MovieFolderFormat).ValidMovieFolderFormat();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Api.Frontend.Mappers
|
|||||||
|
|
||||||
public override bool CanHandle(string resourceUrl)
|
public override bool CanHandle(string resourceUrl)
|
||||||
{
|
{
|
||||||
return resourceUrl.StartsWith("/backup/") && resourceUrl.ContainsIgnoreCase("nzbdrone_backup_") && resourceUrl.EndsWith(".zip");
|
return resourceUrl.StartsWith("/backup/") && resourceUrl.ContainsIgnoreCase("radarr_backup_") && resourceUrl.EndsWith(".zip");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ namespace NzbDrone.Api.Indexers
|
|||||||
{
|
{
|
||||||
Guid = releaseInfo.Guid,
|
Guid = releaseInfo.Guid,
|
||||||
Quality = parsedMovieInfo.Quality,
|
Quality = parsedMovieInfo.Quality,
|
||||||
//QualityWeight
|
QualityWeight = parsedMovieInfo.Quality.Quality.Id, //Id kinda hacky for wheight, but what you gonna do? TODO: Fix this shit!
|
||||||
Age = releaseInfo.Age,
|
Age = releaseInfo.Age,
|
||||||
AgeHours = releaseInfo.AgeHours,
|
AgeHours = releaseInfo.AgeHours,
|
||||||
AgeMinutes = releaseInfo.AgeMinutes,
|
AgeMinutes = releaseInfo.AgeMinutes,
|
||||||
|
|||||||
31
src/NzbDrone.Api/Movies/MovieEditorModule.cs
Normal file
31
src/NzbDrone.Api/Movies/MovieEditorModule.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Nancy;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
public class MovieEditorModule : NzbDroneApiModule
|
||||||
|
{
|
||||||
|
private readonly IMovieService _movieService;
|
||||||
|
|
||||||
|
public MovieEditorModule(IMovieService movieService)
|
||||||
|
: base("/movie/editor")
|
||||||
|
{
|
||||||
|
_movieService = movieService;
|
||||||
|
Put["/"] = Movie => SaveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response SaveAll()
|
||||||
|
{
|
||||||
|
var resources = Request.Body.FromJson<List<MovieResource>>();
|
||||||
|
|
||||||
|
var Movie = resources.Select(MovieResource => MovieResource.ToModel(_movieService.GetMovie(MovieResource.Id))).ToList();
|
||||||
|
|
||||||
|
return _movieService.UpdateMovie(Movie)
|
||||||
|
.ToResource()
|
||||||
|
.AsResponse(HttpStatusCode.Accepted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,6 +119,7 @@
|
|||||||
<Compile Include="Movies\MovieModule.cs" />
|
<Compile Include="Movies\MovieModule.cs" />
|
||||||
<Compile Include="Movies\RenameMovieModule.cs" />
|
<Compile Include="Movies\RenameMovieModule.cs" />
|
||||||
<Compile Include="Movies\RenameMovieResource.cs" />
|
<Compile Include="Movies\RenameMovieResource.cs" />
|
||||||
|
<Compile Include="Movies\MovieEditorModule.cs" />
|
||||||
<Compile Include="Parse\ParseModule.cs" />
|
<Compile Include="Parse\ParseModule.cs" />
|
||||||
<Compile Include="Parse\ParseResource.cs" />
|
<Compile Include="Parse\ParseResource.cs" />
|
||||||
<Compile Include="ManualImport\ManualImportModule.cs" />
|
<Compile Include="ManualImport\ManualImportModule.cs" />
|
||||||
@@ -231,6 +232,7 @@
|
|||||||
<Compile Include="RootFolders\RootFolderResource.cs" />
|
<Compile Include="RootFolders\RootFolderResource.cs" />
|
||||||
<Compile Include="SeasonPass\SeasonPassResource.cs" />
|
<Compile Include="SeasonPass\SeasonPassResource.cs" />
|
||||||
<Compile Include="Series\AlternateTitleResource.cs" />
|
<Compile Include="Series\AlternateTitleResource.cs" />
|
||||||
|
<Compile Include="Series\MovieFileResource.cs" />
|
||||||
<Compile Include="Series\SeasonResource.cs" />
|
<Compile Include="Series\SeasonResource.cs" />
|
||||||
<Compile Include="SeasonPass\SeasonPassModule.cs" />
|
<Compile Include="SeasonPass\SeasonPassModule.cs" />
|
||||||
<Compile Include="Series\SeriesEditorModule.cs" />
|
<Compile Include="Series\SeriesEditorModule.cs" />
|
||||||
|
|||||||
85
src/NzbDrone.Api/Series/MovieFileResource.cs
Normal file
85
src/NzbDrone.Api/Series/MovieFileResource.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.MediaCover;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Api.Series;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
public class MovieFileResource : RestResource
|
||||||
|
{
|
||||||
|
public MovieFileResource()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Todo: Sorters should be done completely on the client
|
||||||
|
//Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing?
|
||||||
|
//Todo: We should get the entire Profile instead of ID and Name separately
|
||||||
|
|
||||||
|
public int MovieId { get; set; }
|
||||||
|
public string RelativePath { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
public long Size { get; set; }
|
||||||
|
public DateTime DateAdded { get; set; }
|
||||||
|
public string SceneName { get; set; }
|
||||||
|
public string ReleaseGroup { get; set; }
|
||||||
|
public QualityModel Quality { get; set; }
|
||||||
|
public MovieResource Movie { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MovieFileResourceMapper
|
||||||
|
{
|
||||||
|
public static MovieFileResource ToResource(this MovieFile model)
|
||||||
|
{
|
||||||
|
if (model == null) return null;
|
||||||
|
|
||||||
|
MovieResource movie = null;
|
||||||
|
|
||||||
|
if (model.Movie != null)
|
||||||
|
{
|
||||||
|
model.Movie.LazyLoad();
|
||||||
|
if (model.Movie.Value != null)
|
||||||
|
{
|
||||||
|
//movie = model.Movie.Value.ToResource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MovieFileResource
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
RelativePath = model.RelativePath,
|
||||||
|
Path = model.Path,
|
||||||
|
Size = model.Size,
|
||||||
|
DateAdded = model.DateAdded,
|
||||||
|
ReleaseGroup = model.ReleaseGroup,
|
||||||
|
Quality = model.Quality,
|
||||||
|
Movie = movie,
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MovieFile ToModel(this MovieFileResource resource)
|
||||||
|
{
|
||||||
|
if (resource == null) return null;
|
||||||
|
|
||||||
|
return new MovieFile
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MovieFileResource> ToResource(this IEnumerable<MovieFile> movies)
|
||||||
|
{
|
||||||
|
return movies.Select(ToResource).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,6 +55,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
public AddMovieOptions AddOptions { get; set; }
|
public AddMovieOptions AddOptions { get; set; }
|
||||||
public Ratings Ratings { get; set; }
|
public Ratings Ratings { get; set; }
|
||||||
public List<string> AlternativeTitles { get; set; }
|
public List<string> AlternativeTitles { get; set; }
|
||||||
|
public MovieFileResource MovieFile { get; set; }
|
||||||
|
|
||||||
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
||||||
|
|
||||||
@@ -84,6 +85,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
long size = 0;
|
long size = 0;
|
||||||
bool downloaded = false;
|
bool downloaded = false;
|
||||||
|
MovieFileResource movieFile = null;
|
||||||
|
|
||||||
|
|
||||||
if(model.MovieFile != null)
|
if(model.MovieFile != null)
|
||||||
@@ -95,6 +97,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
{
|
{
|
||||||
size = model.MovieFile.Value.Size;
|
size = model.MovieFile.Value.Size;
|
||||||
downloaded = true;
|
downloaded = true;
|
||||||
|
movieFile = model.MovieFile.Value.ToResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MovieResource
|
return new MovieResource
|
||||||
@@ -140,7 +143,8 @@ namespace NzbDrone.Api.Movie
|
|||||||
Added = model.Added,
|
Added = model.Added,
|
||||||
AddOptions = model.AddOptions,
|
AddOptions = model.AddOptions,
|
||||||
AlternativeTitles = model.AlternativeTitles,
|
AlternativeTitles = model.AlternativeTitles,
|
||||||
Ratings = model.Ratings
|
Ratings = model.Ratings,
|
||||||
|
MovieFile = movieFile
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Common
|
|||||||
Console.WriteLine(" Commands:");
|
Console.WriteLine(" Commands:");
|
||||||
Console.WriteLine(" /{0} Install the application as a Windows Service ({1}).", StartupContext.INSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
|
Console.WriteLine(" /{0} Install the application as a Windows Service ({1}).", StartupContext.INSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
|
||||||
Console.WriteLine(" /{0} Uninstall already installed Windows Service ({1}).", StartupContext.UNINSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
|
Console.WriteLine(" /{0} Uninstall already installed Windows Service ({1}).", StartupContext.UNINSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
|
||||||
Console.WriteLine(" /{0} Don't open Sonarr in a browser", StartupContext.NO_BROWSER);
|
Console.WriteLine(" /{0} Don't open Radarr in a browser", StartupContext.NO_BROWSER);
|
||||||
Console.WriteLine(" <No Arguments> Run application in console mode.");
|
Console.WriteLine(" <No Arguments> Run application in console mode.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
static UserAgentBuilder()
|
static UserAgentBuilder()
|
||||||
{
|
{
|
||||||
UserAgent = string.Format("Sonarr/{0} ({1} {2})",
|
UserAgent = string.Format("Radarr/{0} ({1} {2})",
|
||||||
BuildInfo.Version,
|
BuildInfo.Version,
|
||||||
OsInfo.Os, OsInfo.Version.ToString(2));
|
OsInfo.Os, OsInfo.Version.ToString(2));
|
||||||
|
|
||||||
UserAgentSimplified = string.Format("Sonarr/{0}",
|
UserAgentSimplified = string.Format("Radarr/{0}",
|
||||||
BuildInfo.Version.ToString(2));
|
BuildInfo.Version.ToString(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,9 +103,9 @@ namespace NzbDrone.Common.Instrumentation
|
|||||||
|
|
||||||
private static void RegisterAppFile(IAppFolderInfo appFolderInfo)
|
private static void RegisterAppFile(IAppFolderInfo appFolderInfo)
|
||||||
{
|
{
|
||||||
RegisterAppFile(appFolderInfo, "appFileInfo", "sonarr.txt", 5, LogLevel.Info);
|
RegisterAppFile(appFolderInfo, "appFileInfo", "radarr.txt", 5, LogLevel.Info);
|
||||||
RegisterAppFile(appFolderInfo, "appFileDebug", "sonarr.debug.txt", 50, LogLevel.Off);
|
RegisterAppFile(appFolderInfo, "appFileDebug", "radarr.debug.txt", 50, LogLevel.Off);
|
||||||
RegisterAppFile(appFolderInfo, "appFileTrace", "sonarr.trace.txt", 50, LogLevel.Off);
|
RegisterAppFile(appFolderInfo, "appFileTrace", "radarr.trace.txt", 50, LogLevel.Off);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LoggingRule RegisterAppFile(IAppFolderInfo appFolderInfo, string name, string fileName, int maxArchiveFiles, LogLevel minLogLevel)
|
private static LoggingRule RegisterAppFile(IAppFolderInfo appFolderInfo, string name, string fileName, int maxArchiveFiles, LogLevel minLogLevel)
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using FluentAssertions;
|
|
||||||
using Moq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Common.Http;
|
|
||||||
using NzbDrone.Core.Indexers;
|
|
||||||
using NzbDrone.Core.Indexers.Fanzub;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.IndexerTests.FanzubTests
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class FanzubFixture : CoreTest<Fanzub>
|
|
||||||
{
|
|
||||||
[SetUp]
|
|
||||||
public void Setup()
|
|
||||||
{
|
|
||||||
Subject.Definition = new IndexerDefinition()
|
|
||||||
{
|
|
||||||
Name = "Fanzub",
|
|
||||||
Settings = new FanzubSettings()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_parse_recent_feed_from_fanzub()
|
|
||||||
{
|
|
||||||
var recentFeed = ReadAllText(@"Files/Indexers/Fanzub/fanzub.xml");
|
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
|
||||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
|
||||||
|
|
||||||
var releases = Subject.FetchRecent();
|
|
||||||
|
|
||||||
releases.Should().HaveCount(3);
|
|
||||||
|
|
||||||
var releaseInfo = releases.First();
|
|
||||||
|
|
||||||
releaseInfo.Title.Should().Be("[Vivid] Hanayamata - 10 [A33D6606]");
|
|
||||||
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
|
|
||||||
releaseInfo.DownloadUrl.Should().Be("http://fanzub.com/nzb/296464/Vivid%20Hanayamata%20-%2010.nzb");
|
|
||||||
releaseInfo.InfoUrl.Should().BeNullOrEmpty();
|
|
||||||
releaseInfo.CommentUrl.Should().BeNullOrEmpty();
|
|
||||||
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
|
|
||||||
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2014/09/13 12:56:53"));
|
|
||||||
releaseInfo.Size.Should().Be(556246858);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -249,7 +249,6 @@
|
|||||||
<Compile Include="IndexerTests\NewznabTests\NewznabFixture.cs" />
|
<Compile Include="IndexerTests\NewznabTests\NewznabFixture.cs" />
|
||||||
<Compile Include="IndexerTests\NewznabTests\NewznabRequestGeneratorFixture.cs" />
|
<Compile Include="IndexerTests\NewznabTests\NewznabRequestGeneratorFixture.cs" />
|
||||||
<Compile Include="IndexerTests\NewznabTests\NewznabSettingFixture.cs" />
|
<Compile Include="IndexerTests\NewznabTests\NewznabSettingFixture.cs" />
|
||||||
<Compile Include="IndexerTests\FanzubTests\FanzubFixture.cs" />
|
|
||||||
<Compile Include="IndexerTests\OmgwtfnzbsTests\OmgwtfnzbsFixture.cs" />
|
<Compile Include="IndexerTests\OmgwtfnzbsTests\OmgwtfnzbsFixture.cs" />
|
||||||
<Compile Include="IndexerTests\SeasonSearchFixture.cs" />
|
<Compile Include="IndexerTests\SeasonSearchFixture.cs" />
|
||||||
<Compile Include="IndexerTests\TestIndexer.cs" />
|
<Compile Include="IndexerTests\TestIndexer.cs" />
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace NzbDrone.Core.Backup
|
|||||||
|
|
||||||
private string _backupTempFolder;
|
private string _backupTempFolder;
|
||||||
|
|
||||||
private static readonly Regex BackupFileRegex = new Regex(@"nzbdrone_backup_[._0-9]+\.zip", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private static readonly Regex BackupFileRegex = new Regex(@"radarr_backup_[._0-9]+\.zip", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
public BackupService(IMainDatabase maindDb,
|
public BackupService(IMainDatabase maindDb,
|
||||||
IDiskTransferService diskTransferService,
|
IDiskTransferService diskTransferService,
|
||||||
@@ -49,7 +49,7 @@ namespace NzbDrone.Core.Backup
|
|||||||
_archiveService = archiveService;
|
_archiveService = archiveService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
_backupTempFolder = Path.Combine(_appFolderInfo.TempFolder, "nzbdrone_backup");
|
_backupTempFolder = Path.Combine(_appFolderInfo.TempFolder, "radarr_backup");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Backup(BackupType backupType)
|
public void Backup(BackupType backupType)
|
||||||
@@ -59,7 +59,7 @@ namespace NzbDrone.Core.Backup
|
|||||||
_diskProvider.EnsureFolder(_backupTempFolder);
|
_diskProvider.EnsureFolder(_backupTempFolder);
|
||||||
_diskProvider.EnsureFolder(GetBackupFolder(backupType));
|
_diskProvider.EnsureFolder(GetBackupFolder(backupType));
|
||||||
|
|
||||||
var backupFilename = string.Format("nzbdrone_backup_{0:yyyy.MM.dd_HH.mm.ss}.zip", DateTime.Now);
|
var backupFilename = string.Format("radarr_backup_{0:yyyy.MM.dd_HH.mm.ss}.zip", DateTime.Now);
|
||||||
var backupPath = Path.Combine(GetBackupFolder(backupType), backupFilename);
|
var backupPath = Path.Combine(GetBackupFolder(backupType), backupFilename);
|
||||||
|
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
|||||||
14
src/NzbDrone.Core/Datastore/Migration/114_remove_fanzub.cs
Normal file
14
src/NzbDrone.Core/Datastore/Migration/114_remove_fanzub.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(114)]
|
||||||
|
public class remove_fanzub : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Delete.FromTable("Indexers").Row(new { Implementation = "Fanzub" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Data;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(115)]
|
||||||
|
public class update_movie_sorttitle : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
// Create.Column("SortTitle").OnTable("Series").AsString().Nullable();
|
||||||
|
Execute.WithConnection(SetSortTitles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
getSeriesCmd.Transaction = tran;
|
||||||
|
getSeriesCmd.CommandText = @"SELECT Id, Title FROM Movies";
|
||||||
|
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (seriesReader.Read())
|
||||||
|
{
|
||||||
|
var id = seriesReader.GetInt32(0);
|
||||||
|
var title = seriesReader.GetString(1);
|
||||||
|
|
||||||
|
var sortTitle = Parser.Parser.NormalizeTitle(title).ToLower();
|
||||||
|
|
||||||
|
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateCmd.Transaction = tran;
|
||||||
|
updateCmd.CommandText = "UPDATE Movies SET SortTitle = ? WHERE Id = ?";
|
||||||
|
updateCmd.AddParameter(sortTitle);
|
||||||
|
updateCmd.AddParameter(id);
|
||||||
|
|
||||||
|
updateCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,8 +24,6 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
{
|
{
|
||||||
CompareQuality,
|
CompareQuality,
|
||||||
CompareProtocol,
|
CompareProtocol,
|
||||||
CompareEpisodeCount,
|
|
||||||
CompareEpisodeNumber,
|
|
||||||
ComparePeersIfTorrent,
|
ComparePeersIfTorrent,
|
||||||
CompareAgeIfUsenet,
|
CompareAgeIfUsenet,
|
||||||
CompareSize
|
CompareSize
|
||||||
@@ -56,6 +54,12 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
|
|
||||||
private int CompareQuality(DownloadDecision x, DownloadDecision y)
|
private int CompareQuality(DownloadDecision x, DownloadDecision y)
|
||||||
{
|
{
|
||||||
|
if (x.IsForMovie && y.IsForMovie)
|
||||||
|
{
|
||||||
|
return CompareAll(CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.Movie.Profile.Value.Items.FindIndex(v => v.Quality == remoteEpisode.ParsedMovieInfo.Quality.Quality)),
|
||||||
|
CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.ParsedMovieInfo.Quality.Revision.Real),
|
||||||
|
CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.ParsedMovieInfo.Quality.Revision.Version));
|
||||||
|
}
|
||||||
return CompareAll(CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Series.Profile.Value.Items.FindIndex(v => v.Quality == remoteEpisode.ParsedEpisodeInfo.Quality.Quality)),
|
return CompareAll(CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Series.Profile.Value.Items.FindIndex(v => v.Quality == remoteEpisode.ParsedEpisodeInfo.Quality.Quality)),
|
||||||
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Real),
|
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Real),
|
||||||
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version));
|
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version));
|
||||||
@@ -63,6 +67,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
|
|
||||||
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
|
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
|
||||||
{
|
{
|
||||||
|
|
||||||
var result = CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
|
var result = CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
|
||||||
{
|
{
|
||||||
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Series.Tags);
|
var delayProfile = _delayProfileService.BestForTags(remoteEpisode.Series.Tags);
|
||||||
@@ -70,13 +75,22 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
return downloadProtocol == delayProfile.PreferredProtocol;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int CompareEpisodeCount(DownloadDecision x, DownloadDecision y)
|
private int CompareEpisodeCount(DownloadDecision x, DownloadDecision y)
|
||||||
{
|
{
|
||||||
return CompareAll(CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.FullSeason),
|
return 0;
|
||||||
CompareByReverse(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Episodes.Count));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int CompareEpisodeNumber(DownloadDecision x, DownloadDecision y)
|
private int CompareEpisodeNumber(DownloadDecision x, DownloadDecision y)
|
||||||
@@ -88,20 +102,20 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
{
|
{
|
||||||
// Different protocols should get caught when checking the preferred protocol,
|
// Different protocols should get caught when checking the preferred protocol,
|
||||||
// since we're dealing with the same series in our comparisions
|
// since we're dealing with the same series in our comparisions
|
||||||
if (x.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Torrent ||
|
if (x.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Torrent ||
|
||||||
y.RemoteEpisode.Release.DownloadProtocol != DownloadProtocol.Torrent)
|
y.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Torrent)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CompareAll(
|
return CompareAll(
|
||||||
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
|
CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
|
||||||
{
|
{
|
||||||
var seeders = TorrentInfo.GetSeeders(remoteEpisode.Release);
|
var seeders = TorrentInfo.GetSeeders(remoteEpisode.Release);
|
||||||
|
|
||||||
return seeders.HasValue && seeders.Value > 0 ? Math.Round(Math.Log10(seeders.Value)) : 0;
|
return seeders.HasValue && seeders.Value > 0 ? Math.Round(Math.Log10(seeders.Value)) : 0;
|
||||||
}),
|
}),
|
||||||
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
|
CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
|
||||||
{
|
{
|
||||||
var peers = TorrentInfo.GetPeers(remoteEpisode.Release);
|
var peers = TorrentInfo.GetPeers(remoteEpisode.Release);
|
||||||
|
|
||||||
@@ -117,7 +131,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
|
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode =>
|
||||||
{
|
{
|
||||||
var ageHours = remoteEpisode.Release.AgeHours;
|
var ageHours = remoteEpisode.Release.AgeHours;
|
||||||
var age = remoteEpisode.Release.Age;
|
var age = remoteEpisode.Release.Age;
|
||||||
@@ -145,7 +159,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
{
|
{
|
||||||
// TODO: Is smaller better? Smaller for usenet could mean no par2 files.
|
// TODO: Is smaller better? Smaller for usenet could mean no par2 files.
|
||||||
|
|
||||||
return CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes()));
|
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteEpisode => remoteEpisode.Release.Size.Round(200.Megabytes()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
{
|
{
|
||||||
if (parsedEpisodeInfo.Quality.HardcodedSubs.IsNotNullOrWhiteSpace())
|
if (parsedEpisodeInfo.Quality.HardcodedSubs.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
remoteEpisode.DownloadAllowed = true;
|
remoteEpisode.DownloadAllowed = false;
|
||||||
decision = new DownloadDecision(remoteEpisode, new Rejection("Hardcoded subs found: " + parsedEpisodeInfo.Quality.HardcodedSubs));
|
decision = new DownloadDecision(remoteEpisode, new Rejection("Hardcoded subs found: " + parsedEpisodeInfo.Quality.HardcodedSubs));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -257,7 +257,7 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
}
|
}
|
||||||
catch (NotImplementedException e)
|
catch (NotImplementedException e)
|
||||||
{
|
{
|
||||||
_logger.Info("Spec " + spec.GetType().Name + " does not care about movies.");
|
_logger.Trace("Spec " + spec.GetType().Name + " does not care about movies.");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -265,7 +265,6 @@ namespace NzbDrone.Core.DecisionEngine
|
|||||||
e.Data.Add("parsed", remoteEpisode.ParsedEpisodeInfo.ToJson());
|
e.Data.Add("parsed", remoteEpisode.ParsedEpisodeInfo.ToJson());
|
||||||
_logger.Error(e, "Couldn't evaluate decision on " + remoteEpisode.Release.Title + ", with spec: " + spec.GetType().Name);
|
_logger.Error(e, "Couldn't evaluate decision on " + remoteEpisode.Release.Title + ", with spec: " + spec.GetType().Name);
|
||||||
return new Rejection(string.Format("{0}: {1}", spec.GetType().Name, e.Message));//TODO UPDATE SPECS!
|
return new Rejection(string.Format("{0}: {1}", spec.GetType().Name, e.Message));//TODO UPDATE SPECS!
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
|
|
||||||
foreach (var remoteEpisode in matchingSeries)
|
foreach (var remoteEpisode in matchingSeries)
|
||||||
{
|
{
|
||||||
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
|
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteEpisode.ParsedMovieInfo.Quality);
|
||||||
|
|
||||||
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Movie.Profile, remoteEpisode.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
|
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Movie.Profile, remoteEpisode.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
|||||||
|
|
||||||
private static readonly TorrentBlackholeSettingsValidator Validator = new TorrentBlackholeSettingsValidator();
|
private static readonly TorrentBlackholeSettingsValidator Validator = new TorrentBlackholeSettingsValidator();
|
||||||
|
|
||||||
[FieldDefinition(0, Label = "Torrent Folder", Type = FieldType.Path, HelpText = "Folder in which Sonarr will store the .torrent file")]
|
[FieldDefinition(0, Label = "Torrent Folder", Type = FieldType.Path, HelpText = "Folder in which Radarr will store the .torrent file")]
|
||||||
public string TorrentFolder { get; set; }
|
public string TorrentFolder { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(1, Label = "Watch Folder", Type = FieldType.Path, HelpText = "Folder from which Sonarr should import completed downloads")]
|
[FieldDefinition(1, Label = "Watch Folder", Type = FieldType.Path, HelpText = "Folder from which Radarr should import completed downloads")]
|
||||||
public string WatchFolder { get; set; }
|
public string WatchFolder { get; set; }
|
||||||
|
|
||||||
[DefaultValue(false)]
|
[DefaultValue(false)]
|
||||||
@@ -39,7 +39,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
|||||||
|
|
||||||
[DefaultValue(false)]
|
[DefaultValue(false)]
|
||||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
||||||
[FieldDefinition(3, Label = "Read Only", Type = FieldType.Checkbox, HelpText = "Instead of moving files this will instruct Sonarr to Copy or Hardlink (depending on settings/system configuration)")]
|
[FieldDefinition(3, Label = "Read Only", Type = FieldType.Checkbox, HelpText = "Instead of moving files this will instruct Radarr to Copy or Hardlink (depending on settings/system configuration)")]
|
||||||
public bool ReadOnly { get; set; }
|
public bool ReadOnly { get; set; }
|
||||||
|
|
||||||
public NzbDroneValidationResult Validate()
|
public NzbDroneValidationResult Validate()
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
|
|||||||
{
|
{
|
||||||
private static readonly UsenetBlackholeSettingsValidator Validator = new UsenetBlackholeSettingsValidator();
|
private static readonly UsenetBlackholeSettingsValidator Validator = new UsenetBlackholeSettingsValidator();
|
||||||
|
|
||||||
[FieldDefinition(0, Label = "Nzb Folder", Type = FieldType.Path, HelpText = "Folder in which Sonarr will store the .nzb file")]
|
[FieldDefinition(0, Label = "Nzb Folder", Type = FieldType.Path, HelpText = "Folder in which Radarr will store the .nzb file")]
|
||||||
public string NzbFolder { get; set; }
|
public string NzbFolder { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(1, Label = "Watch Folder", Type = FieldType.Path, HelpText = "Folder from which Sonarr should import completed downloads")]
|
[FieldDefinition(1, Label = "Watch Folder", Type = FieldType.Path, HelpText = "Folder from which Radarr should import completed downloads")]
|
||||||
public string WatchFolder { get; set; }
|
public string WatchFolder { get; set; }
|
||||||
|
|
||||||
public NzbDroneValidationResult Validate()
|
public NzbDroneValidationResult Validate()
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
|
|||||||
{
|
{
|
||||||
return new NzbDroneValidationFailure("TvCategory", "Configuration of label failed")
|
return new NzbDroneValidationFailure("TvCategory", "Configuration of label failed")
|
||||||
{
|
{
|
||||||
DetailedDescription = "Sonarr as unable to add the label to Deluge."
|
DetailedDescription = "Radarr as unable to add the label to Deluge."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
|
|||||||
[FieldDefinition(2, Label = "API Key", Type = FieldType.Textbox)]
|
[FieldDefinition(2, Label = "API Key", Type = FieldType.Textbox)]
|
||||||
public string ApiKey { get; set; }
|
public string ApiKey { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(3, Label = "Group", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional")]
|
[FieldDefinition(3, Label = "Group", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||||
public string TvCategory { get; set; }
|
public string TvCategory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(4, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbVortexPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
[FieldDefinition(4, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbVortexPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||||||
return new NzbDroneValidationFailure(string.Empty, "NzbGet setting KeepHistory should be greater than 0")
|
return new NzbDroneValidationFailure(string.Empty, "NzbGet setting KeepHistory should be greater than 0")
|
||||||
{
|
{
|
||||||
InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port),
|
InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port),
|
||||||
DetailedDescription = "NzbGet setting KeepHistory is set to 0. Which prevents Sonarr from seeing completed downloads."
|
DetailedDescription = "NzbGet setting KeepHistory is set to 0. Which prevents Radarr from seeing completed downloads."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
|
|||||||
[FieldDefinition(3, Label = "Password", Type = FieldType.Password)]
|
[FieldDefinition(3, Label = "Password", Type = FieldType.Password)]
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional")]
|
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||||
public string TvCategory { get; set; }
|
public string TvCategory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
|
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
|
||||||
{
|
{
|
||||||
IsWarning = true,
|
IsWarning = true,
|
||||||
DetailedDescription = "Sonarr may not be able to support new features added to SABnzbd when running develop versions."
|
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,7 +431,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
return new NzbDroneValidationFailure("", "Disable 'Check before download' option in Sabnbzd")
|
return new NzbDroneValidationFailure("", "Disable 'Check before download' option in Sabnbzd")
|
||||||
{
|
{
|
||||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/switches/", Settings.Host, Settings.Port),
|
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/switches/", Settings.Host, Settings.Port),
|
||||||
DetailedDescription = "Using Check before download affects Sonarr ability to track new downloads. Also Sabnzbd recommends 'Abort jobs that cannot be completed' instead since it's more effective."
|
DetailedDescription = "Using Check before download affects Radarr ability to track new downloads. Also Sabnzbd recommends 'Abort jobs that cannot be completed' instead since it's more effective."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,7 +450,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
return new NzbDroneValidationFailure("TvCategory", "Enable Job folders")
|
return new NzbDroneValidationFailure("TvCategory", "Enable Job folders")
|
||||||
{
|
{
|
||||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port),
|
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port),
|
||||||
DetailedDescription = "Sonarr prefers each download to have a separate folder. With * appended to the Folder/Path Sabnzbd will not create these job folders. Go to Sabnzbd to fix it."
|
DetailedDescription = "Radarr prefers each download to have a separate folder. With * appended to the Folder/Path Sabnzbd will not create these job folders. Go to Sabnzbd to fix it."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -475,7 +475,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
return new NzbDroneValidationFailure("TvCategory", "Disable TV Sorting")
|
return new NzbDroneValidationFailure("TvCategory", "Disable TV Sorting")
|
||||||
{
|
{
|
||||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||||
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -489,7 +489,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
return new NzbDroneValidationFailure("TvCategory", "Disable Movie Sorting")
|
return new NzbDroneValidationFailure("TvCategory", "Disable Movie Sorting")
|
||||||
{
|
{
|
||||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||||
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -503,7 +503,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
return new NzbDroneValidationFailure("TvCategory", "Disable Date Sorting")
|
return new NzbDroneValidationFailure("TvCategory", "Disable Date Sorting")
|
||||||
{
|
{
|
||||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||||
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Sonarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Radarr uses to prevent import issues. Go to Sabnzbd to fix it."
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
|||||||
[FieldDefinition(4, Label = "Password", Type = FieldType.Password)]
|
[FieldDefinition(4, Label = "Password", Type = FieldType.Password)]
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional")]
|
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||||
public string TvCategory { get; set; }
|
public string TvCategory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
[FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
||||||
|
|||||||
@@ -165,6 +165,31 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
|
||||||
|
{
|
||||||
|
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
|
||||||
|
if (remoteMovie.Release.Age < 14 && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
|
||||||
|
remoteMovie.Release.Age > 14 && Settings.OlderTvPriority == (int)TransmissionPriority.First)
|
||||||
|
{
|
||||||
|
_proxy.MoveTorrentToTopInQueue(hash, Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
|
||||||
|
{
|
||||||
|
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
|
||||||
|
|
||||||
|
if (remoteMovie.Release.Age < 14 && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
|
||||||
|
remoteMovie.Release.Age > 14 && Settings.OlderTvPriority == (int)TransmissionPriority.First)
|
||||||
|
{
|
||||||
|
_proxy.MoveTorrentToTopInQueue(hash, Settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Test(List<ValidationFailure> failures)
|
protected override void Test(List<ValidationFailure> failures)
|
||||||
{
|
{
|
||||||
failures.AddIfNotNull(TestConnection());
|
failures.AddIfNotNull(TestConnection());
|
||||||
@@ -207,7 +232,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
_logger.Error(ex, ex.Message);
|
_logger.Error(ex, ex.Message);
|
||||||
return new NzbDroneValidationFailure("Username", "Authentication failure")
|
return new NzbDroneValidationFailure("Username", "Authentication failure")
|
||||||
{
|
{
|
||||||
DetailedDescription = string.Format("Please verify your username and password. Also verify if the host running Sonarr isn't blocked from accessing {0} by WhiteList limitations in the {0} configuration.", Name)
|
DetailedDescription = string.Format("Please verify your username and password. Also verify if the host running Radarr isn't blocked from accessing {0} by WhiteList limitations in the {0} configuration.", Name)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (WebException ex)
|
catch (WebException ex)
|
||||||
|
|||||||
@@ -50,16 +50,16 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
[FieldDefinition(4, Label = "Password", Type = FieldType.Password)]
|
[FieldDefinition(4, Label = "Password", Type = FieldType.Password)]
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional. Creates a [category] subdirectory in the output directory.")]
|
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional. Creates a [category] subdirectory in the output directory.")]
|
||||||
public string TvCategory { get; set; }
|
public string TvCategory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(6, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default Transmission location")]
|
[FieldDefinition(6, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default Transmission location")]
|
||||||
public string TvDirectory { get; set; }
|
public string TvDirectory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(7, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
[FieldDefinition(7, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing movies that we're released within the last 14 days")]
|
||||||
public int RecentTvPriority { get; set; }
|
public int RecentTvPriority { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(8, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
|
[FieldDefinition(8, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing movies that we're released over 14 days ago")]
|
||||||
public int OlderTvPriority { get; set; }
|
public int OlderTvPriority { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(9, Label = "Use SSL", Type = FieldType.Checkbox)]
|
[FieldDefinition(9, Label = "Use SSL", Type = FieldType.Checkbox)]
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
|
|||||||
[FieldDefinition(5, Label = "Password", Type = FieldType.Password)]
|
[FieldDefinition(5, Label = "Password", Type = FieldType.Password)]
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional.")]
|
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional.")]
|
||||||
public string TvCategory { get; set; }
|
public string TvCategory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(7, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default rTorrent location")]
|
[FieldDefinition(7, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default rTorrent location")]
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
|
|||||||
[FieldDefinition(3, Label = "Password", Type = FieldType.Password)]
|
[FieldDefinition(3, Label = "Password", Type = FieldType.Password)]
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Sonarr avoids conflicts with unrelated downloads, but it's optional")]
|
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||||
public string TvCategory { get; set; }
|
public string TvCategory { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(UTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(UTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ namespace NzbDrone.Core.Download
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title);
|
var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title);
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
@@ -110,7 +109,11 @@ namespace NzbDrone.Core.Download
|
|||||||
|
|
||||||
if (movie == null)
|
if (movie == null)
|
||||||
{
|
{
|
||||||
movie = _movieService.GetMovie(historyItem.MovieId);
|
if (historyItem != null)
|
||||||
|
{
|
||||||
|
movie = _movieService.GetMovie(historyItem.MovieId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (movie == null)
|
if (movie == null)
|
||||||
{
|
{
|
||||||
@@ -156,7 +159,7 @@ namespace NzbDrone.Core.Download
|
|||||||
trackedDownload.Warn(statusMessages);
|
trackedDownload.Warn(statusMessages);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (trackedDownload.RemoteEpisode.Series != null)
|
||||||
{
|
{
|
||||||
var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem);
|
var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace NzbDrone.Core.Download
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
|
public int MovieId { get; set; }
|
||||||
public List<int> EpisodeIds { get; set; }
|
public List<int> EpisodeIds { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public string SourceTitle { get; set; }
|
public string SourceTitle { get; set; }
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace NzbDrone.Core.Download
|
|||||||
|
|
||||||
if (grabbedItems.Empty())
|
if (grabbedItems.Empty())
|
||||||
{
|
{
|
||||||
trackedDownload.Warn("Download wasn't grabbed by sonarr, skipping");
|
trackedDownload.Warn("Download wasn't grabbed by Radarr, skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +88,7 @@ namespace NzbDrone.Core.Download
|
|||||||
var downloadFailedEvent = new DownloadFailedEvent
|
var downloadFailedEvent = new DownloadFailedEvent
|
||||||
{
|
{
|
||||||
SeriesId = historyItem.SeriesId,
|
SeriesId = historyItem.SeriesId,
|
||||||
|
MovieId = historyItem.MovieId,
|
||||||
EpisodeIds = historyItems.Select(h => h.EpisodeId).ToList(),
|
EpisodeIds = historyItems.Select(h => h.EpisodeId).ToList(),
|
||||||
Quality = historyItem.Quality,
|
Quality = historyItem.Quality,
|
||||||
SourceTitle = historyItem.SourceTitle,
|
SourceTitle = historyItem.SourceTitle,
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ namespace NzbDrone.Core.Download
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (report.Rejections.Any())
|
||||||
|
{
|
||||||
|
_logger.Debug("Rejecting release {0} because {1}", report.ToString(), report.Rejections.First().Reason);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (remoteMovie == null || remoteMovie.Movie == null)
|
if (remoteMovie == null || remoteMovie.Movie == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -34,6 +34,15 @@ namespace NzbDrone.Core.Download
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (message.MovieId != 0)
|
||||||
|
{
|
||||||
|
_logger.Debug("Failed download contains a movie, searching again.");
|
||||||
|
|
||||||
|
_commandQueueManager.Push(new MoviesSearchCommand { MovieId = message.MovieId });
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (message.EpisodeIds.Count == 1)
|
if (message.EpisodeIds.Count == 1)
|
||||||
{
|
{
|
||||||
_logger.Debug("Failed download only contains one episode, searching again");
|
_logger.Debug("Failed download only contains one episode, searching again");
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
using NLog;
|
|
||||||
using NzbDrone.Common.Http;
|
|
||||||
using NzbDrone.Core.Configuration;
|
|
||||||
using NzbDrone.Core.Parser;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Fanzub
|
|
||||||
{
|
|
||||||
public class Fanzub : HttpIndexerBase<FanzubSettings>
|
|
||||||
{
|
|
||||||
public override string Name => "Fanzub";
|
|
||||||
|
|
||||||
public override DownloadProtocol Protocol => DownloadProtocol.Usenet;
|
|
||||||
|
|
||||||
public Fanzub(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
|
||||||
: base(httpClient, indexerStatusService, configService, parsingService, logger)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
|
||||||
{
|
|
||||||
return new FanzubRequestGenerator() { Settings = Settings };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IParseIndexerResponse GetParser()
|
|
||||||
{
|
|
||||||
return new RssParser() { UseEnclosureUrl = true, UseEnclosureLength = true };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using NzbDrone.Common.Extensions;
|
|
||||||
using NzbDrone.Common.Http;
|
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Fanzub
|
|
||||||
{
|
|
||||||
public class FanzubRequestGenerator : IIndexerRequestGenerator
|
|
||||||
{
|
|
||||||
private static readonly Regex RemoveCharactersRegex = new Regex(@"[!?`]", RegexOptions.Compiled);
|
|
||||||
|
|
||||||
public FanzubSettings Settings { get; set; }
|
|
||||||
public int PageSize { get; set; }
|
|
||||||
|
|
||||||
public FanzubRequestGenerator()
|
|
||||||
{
|
|
||||||
PageSize = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IndexerPageableRequestChain GetRecentRequests()
|
|
||||||
{
|
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
|
||||||
|
|
||||||
pageableRequests.Add(GetPagedRequests(null));
|
|
||||||
|
|
||||||
return pageableRequests;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
|
|
||||||
{
|
|
||||||
return new IndexerPageableRequestChain();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
|
|
||||||
{
|
|
||||||
return new IndexerPageableRequestChain();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
|
|
||||||
{
|
|
||||||
return new IndexerPageableRequestChain();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
|
|
||||||
{
|
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
|
||||||
|
|
||||||
var searchTitles = searchCriteria.QueryTitles.SelectMany(v => GetTitleSearchStrings(v, searchCriteria.AbsoluteEpisodeNumber)).ToList();
|
|
||||||
|
|
||||||
pageableRequests.Add(GetPagedRequests(string.Join("|", searchTitles)));
|
|
||||||
|
|
||||||
return pageableRequests;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
|
|
||||||
{
|
|
||||||
return new IndexerPageableRequestChain();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<IndexerRequest> GetPagedRequests(string query)
|
|
||||||
{
|
|
||||||
var url = new StringBuilder();
|
|
||||||
url.AppendFormat("{0}?cat=anime&max={1}", Settings.BaseUrl, PageSize);
|
|
||||||
|
|
||||||
if (query.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
url.AppendFormat("&q={0}", query);
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return new IndexerRequest(url.ToString(), HttpAccept.Rss);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<string> GetTitleSearchStrings(string title, int absoluteEpisodeNumber)
|
|
||||||
{
|
|
||||||
var formats = new[] { "{0}%20{1:00}", "{0}%20-%20{1:00}" };
|
|
||||||
|
|
||||||
return formats.Select(s => "\"" + string.Format(s, CleanTitle(title), absoluteEpisodeNumber) + "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
private string CleanTitle(string title)
|
|
||||||
{
|
|
||||||
return RemoveCharactersRegex.Replace(title, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
|
||||||
{
|
|
||||||
return new IndexerPageableRequestChain();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using FluentValidation;
|
|
||||||
using NzbDrone.Core.Annotations;
|
|
||||||
using NzbDrone.Core.ThingiProvider;
|
|
||||||
using NzbDrone.Core.Validation;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Fanzub
|
|
||||||
{
|
|
||||||
public class FanzubSettingsValidator : AbstractValidator<FanzubSettings>
|
|
||||||
{
|
|
||||||
public FanzubSettingsValidator()
|
|
||||||
{
|
|
||||||
RuleFor(c => c.BaseUrl).ValidRootUrl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FanzubSettings : IProviderConfig
|
|
||||||
{
|
|
||||||
private static readonly FanzubSettingsValidator Validator = new FanzubSettingsValidator();
|
|
||||||
|
|
||||||
public FanzubSettings()
|
|
||||||
{
|
|
||||||
BaseUrl = "http://fanzub.com/rss/";
|
|
||||||
}
|
|
||||||
|
|
||||||
[FieldDefinition(0, Label = "Rss URL", HelpText = "Enter to URL to an Fanzub compatible RSS feed")]
|
|
||||||
public string BaseUrl { get; set; }
|
|
||||||
|
|
||||||
public NzbDroneValidationResult Validate()
|
|
||||||
{
|
|
||||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -106,8 +106,8 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (capabilities.SupportedTvSearchParameters != null &&
|
if (capabilities.SupportedTvSearchParameters != null &&
|
||||||
new[] { "q", "imdb" }.Any(v => capabilities.SupportedMovieSearchParamters.Contains(v)) &&
|
new[] { "q", "imdbid" }.Any(v => capabilities.SupportedMovieSearchParameters.Contains(v)) &&
|
||||||
new[] { "imdbtitle", "imdbyear" }.All(v => capabilities.SupportedMovieSearchParamters.Contains(v)))
|
new[] { "imdbtitle", "imdbyear" }.All(v => capabilities.SupportedMovieSearchParameters.Contains(v)))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
public int MaxPageSize { get; set; }
|
public int MaxPageSize { get; set; }
|
||||||
public string[] SupportedSearchParameters { get; set; }
|
public string[] SupportedSearchParameters { get; set; }
|
||||||
public string[] SupportedTvSearchParameters { get; set; }
|
public string[] SupportedTvSearchParameters { get; set; }
|
||||||
public string[] SupportedMovieSearchParamters { get; set; }
|
public string[] SupportedMovieSearchParameters { get; set; }
|
||||||
public bool SupportsAggregateIdSearch { get; set; }
|
public bool SupportsAggregateIdSearch { get; set; }
|
||||||
public List<NewznabCategory> Categories { get; set; }
|
public List<NewznabCategory> Categories { get; set; }
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
DefaultPageSize = 100;
|
DefaultPageSize = 100;
|
||||||
MaxPageSize = 100;
|
MaxPageSize = 100;
|
||||||
SupportedSearchParameters = new[] { "q" };
|
SupportedSearchParameters = new[] { "q" };
|
||||||
SupportedMovieSearchParamters = new[] { "q", "imdb", "imdbtitle", "imdbyear" };
|
SupportedMovieSearchParameters = new[] { "q", "imdbid", "imdbtitle", "imdbyear" };
|
||||||
SupportedTvSearchParameters = new[] { "q", "rid", "season", "ep" }; // This should remain 'rid' for older newznab installs.
|
SupportedTvSearchParameters = new[] { "q", "rid", "season", "ep" }; // This should remain 'rid' for older newznab installs.
|
||||||
SupportsAggregateIdSearch = false;
|
SupportsAggregateIdSearch = false;
|
||||||
Categories = new List<NewznabCategory>();
|
Categories = new List<NewznabCategory>();
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
var xmlMovieSearch = xmlSearching.Element("movie-search");
|
var xmlMovieSearch = xmlSearching.Element("movie-search");
|
||||||
if (xmlMovieSearch == null || xmlMovieSearch.Attribute("available").Value != "yes")
|
if (xmlMovieSearch == null || xmlMovieSearch.Attribute("available").Value != "yes")
|
||||||
{
|
{
|
||||||
capabilities.SupportedMovieSearchParamters = null;
|
capabilities.SupportedMovieSearchParameters = null;
|
||||||
}
|
}
|
||||||
else if (xmlMovieSearch.Attribute("supportedParams") != null)
|
else if (xmlMovieSearch.Attribute("supportedParams") != null)
|
||||||
{
|
{
|
||||||
capabilities.SupportedMovieSearchParamters = xmlMovieSearch.Attribute("supportedParams").Value.Split(',');
|
capabilities.SupportedMovieSearchParameters = xmlMovieSearch.Attribute("supportedParams").Value.Split(',');
|
||||||
capabilities.SupportsAggregateIdSearch = true;
|
capabilities.SupportsAggregateIdSearch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
{
|
{
|
||||||
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||||
|
|
||||||
return capabilities.SupportedMovieSearchParamters != null &&
|
return capabilities.SupportedMovieSearchParameters != null &&
|
||||||
capabilities.SupportedMovieSearchParamters.Contains("imdb");
|
capabilities.SupportedMovieSearchParameters.Contains("imdbid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
|
|
||||||
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||||
|
|
||||||
if (capabilities.SupportedMovieSearchParamters != null)
|
if (capabilities.SupportedMovieSearchParameters != null)
|
||||||
{
|
{
|
||||||
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories.Concat(Settings.AnimeCategories), "movie", ""));
|
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories.Concat(Settings.AnimeCategories), "movie", ""));
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
if(SupportsMovieSearch)
|
if (SupportsMovieSearch)
|
||||||
{
|
{
|
||||||
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "movie",
|
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "movie",
|
||||||
string.Format("&imdbid={0}", searchCriteria.Movie.ImdbId.Substring(2)))); //strip off the "tt" - VERY HACKY
|
string.Format("&imdbid={0}", searchCriteria.Movie.ImdbId.Substring(2)))); //strip off the "tt" - VERY HACKY
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInfo)
|
protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInfo)
|
||||||
{
|
{
|
||||||
releaseInfo = base.ProcessItem(item, releaseInfo);
|
releaseInfo = base.ProcessItem(item, releaseInfo);
|
||||||
|
releaseInfo.ImdbId = GetImdbId(item);
|
||||||
releaseInfo.TvdbId = GetTvdbId(item);
|
|
||||||
releaseInfo.TvRageId = GetTvRageId(item);
|
|
||||||
|
|
||||||
return releaseInfo;
|
return releaseInfo;
|
||||||
}
|
}
|
||||||
@@ -114,27 +112,14 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual int GetTvdbId(XElement item)
|
protected virtual int GetImdbId(XElement item)
|
||||||
{
|
{
|
||||||
var tvdbIdString = TryGetNewznabAttribute(item, "tvdbid");
|
var imdbIdString = TryGetNewznabAttribute(item, "imdb");
|
||||||
int tvdbId;
|
int imdbId;
|
||||||
|
|
||||||
if (!tvdbIdString.IsNullOrWhiteSpace() && int.TryParse(tvdbIdString, out tvdbId))
|
if (!imdbIdString.IsNullOrWhiteSpace() && int.TryParse(imdbIdString, out imdbId))
|
||||||
{
|
{
|
||||||
return tvdbId;
|
return imdbId;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual int GetTvRageId(XElement item)
|
|
||||||
{
|
|
||||||
var tvRageIdString = TryGetNewznabAttribute(item, "rageid");
|
|
||||||
int tvRageId;
|
|
||||||
|
|
||||||
if (!tvRageIdString.IsNullOrWhiteSpace() && int.TryParse(tvRageIdString, out tvRageId))
|
|
||||||
{
|
|
||||||
return tvRageId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace NzbDrone.Core.Indexers.Newznab
|
|||||||
|
|
||||||
public NewznabSettings()
|
public NewznabSettings()
|
||||||
{
|
{
|
||||||
Categories = new[] { 2030, 2040, 2050 };
|
Categories = new[] { 2030, 2035, 2040, 2045, 2050 };
|
||||||
AnimeCategories = Enumerable.Empty<int>();
|
AnimeCategories = Enumerable.Empty<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Indexers.Wombles
|
|||||||
|
|
||||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||||
{
|
{
|
||||||
return new RssIndexerRequestGenerator("http://newshost.co.za/rss/?sec=TV&fr=false");
|
return new RssIndexerRequestGenerator("http://newshost.co.za/rss/?sec=Movies&fr=false");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Wombles(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
public Wombles(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles.Commands
|
||||||
|
{
|
||||||
|
public class DownloadedMovieScanCommand : Command
|
||||||
|
{
|
||||||
|
public override bool SendUpdatesToClient => SendUpdates;
|
||||||
|
|
||||||
|
public bool SendUpdates { get; set; }
|
||||||
|
|
||||||
|
// Properties used by third-party apps, do not modify.
|
||||||
|
public string Path { get; set; }
|
||||||
|
public string DownloadClientId { get; set; }
|
||||||
|
public ImportMode ImportMode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,265 +1,107 @@
|
|||||||
using System.Collections.Generic;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Download.TrackedDownloads;
|
||||||
|
using NzbDrone.Core.MediaFiles.Commands;
|
||||||
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using System.Text;
|
||||||
using NzbDrone.Common.Disk;
|
|
||||||
using NzbDrone.Core.DecisionEngine;
|
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
|
||||||
using NzbDrone.Core.Parser;
|
|
||||||
using NzbDrone.Core.Tv;
|
|
||||||
using NzbDrone.Core.Download;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles
|
namespace NzbDrone.Core.MediaFiles
|
||||||
{
|
{
|
||||||
public interface IDownloadedMovieImportService
|
public class DownloadedMovieCommandService : IExecute<DownloadedMovieScanCommand>
|
||||||
{
|
|
||||||
List<ImportResult> ProcessRootFolder(DirectoryInfo directoryInfo);
|
|
||||||
List<ImportResult> ProcessPath(string path, ImportMode importMode = ImportMode.Auto, Movie movie = null, DownloadClientItem downloadClientItem = null);
|
|
||||||
bool ShouldDeleteFolder(DirectoryInfo directoryInfo, Movie movie);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DownloadedMovieImportService : IDownloadedMovieImportService
|
|
||||||
{
|
{
|
||||||
|
private readonly IDownloadedMovieImportService _downloadedMovieImportService;
|
||||||
|
private readonly ITrackedDownloadService _trackedDownloadService;
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly IDiskScanService _diskScanService;
|
private readonly IConfigService _configService;
|
||||||
private readonly IMovieService _movieService;
|
|
||||||
private readonly IParsingService _parsingService;
|
|
||||||
private readonly IMakeImportDecision _importDecisionMaker;
|
|
||||||
private readonly IImportApprovedMovie _importApprovedMovie;
|
|
||||||
private readonly IDetectSample _detectSample;
|
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public DownloadedMovieImportService(IDiskProvider diskProvider,
|
public DownloadedMovieCommandService(IDownloadedMovieImportService downloadedMovieImportService,
|
||||||
IDiskScanService diskScanService,
|
ITrackedDownloadService trackedDownloadService,
|
||||||
IMovieService movieService,
|
IDiskProvider diskProvider,
|
||||||
IParsingService parsingService,
|
IConfigService configService,
|
||||||
IMakeImportDecision importDecisionMaker,
|
Logger logger)
|
||||||
IImportApprovedMovie importApprovedMovie,
|
|
||||||
IDetectSample detectSample,
|
|
||||||
Logger logger)
|
|
||||||
{
|
{
|
||||||
|
_downloadedMovieImportService = downloadedMovieImportService;
|
||||||
|
_trackedDownloadService = trackedDownloadService;
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_diskScanService = diskScanService;
|
_configService = configService;
|
||||||
_movieService = movieService;
|
|
||||||
_parsingService = parsingService;
|
|
||||||
_importDecisionMaker = importDecisionMaker;
|
|
||||||
_importApprovedMovie = importApprovedMovie;
|
|
||||||
_detectSample = detectSample;
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ImportResult> ProcessRootFolder(DirectoryInfo directoryInfo)
|
private List<ImportResult> ProcessDroneFactoryFolder()
|
||||||
{
|
{
|
||||||
var results = new List<ImportResult>();
|
var downloadedEpisodesFolder = _configService.DownloadedEpisodesFolder;
|
||||||
|
|
||||||
foreach (var subFolder in _diskProvider.GetDirectories(directoryInfo.FullName))
|
if (string.IsNullOrEmpty(downloadedEpisodesFolder))
|
||||||
{
|
{
|
||||||
var folderResults = ProcessFolder(new DirectoryInfo(subFolder), ImportMode.Auto, null);
|
_logger.Trace("Drone Factory folder is not configured");
|
||||||
results.AddRange(folderResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var videoFile in _diskScanService.GetVideoFiles(directoryInfo.FullName, false))
|
|
||||||
{
|
|
||||||
var fileResults = ProcessFile(new FileInfo(videoFile), ImportMode.Auto, null);
|
|
||||||
results.AddRange(fileResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ImportResult> ProcessPath(string path, ImportMode importMode = ImportMode.Auto, Movie movie = null, DownloadClientItem downloadClientItem = null)
|
|
||||||
{
|
|
||||||
if (_diskProvider.FolderExists(path))
|
|
||||||
{
|
|
||||||
var directoryInfo = new DirectoryInfo(path);
|
|
||||||
|
|
||||||
if (movie == null)
|
|
||||||
{
|
|
||||||
return ProcessFolder(directoryInfo, importMode, downloadClientItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ProcessFolder(directoryInfo, importMode, movie, downloadClientItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_diskProvider.FileExists(path))
|
|
||||||
{
|
|
||||||
var fileInfo = new FileInfo(path);
|
|
||||||
|
|
||||||
if (movie == null)
|
|
||||||
{
|
|
||||||
return ProcessFile(fileInfo, importMode, downloadClientItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ProcessFile(fileInfo, importMode, movie, downloadClientItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Error("Import failed, path does not exist or is not accessible by Sonarr: {0}", path);
|
|
||||||
return new List<ImportResult>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ShouldDeleteFolder(DirectoryInfo directoryInfo, Movie movie)
|
|
||||||
{
|
|
||||||
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
|
||||||
var rarFiles = _diskProvider.GetFiles(directoryInfo.FullName, SearchOption.AllDirectories).Where(f => Path.GetExtension(f) == ".rar");
|
|
||||||
|
|
||||||
foreach (var videoFile in videoFiles)
|
|
||||||
{
|
|
||||||
var episodeParseResult = Parser.Parser.ParseTitle(Path.GetFileName(videoFile));
|
|
||||||
|
|
||||||
if (episodeParseResult == null)
|
|
||||||
{
|
|
||||||
_logger.Warn("Unable to parse file on import: [{0}]", videoFile);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var size = _diskProvider.GetFileSize(videoFile);
|
|
||||||
var quality = QualityParser.ParseQuality(videoFile);
|
|
||||||
|
|
||||||
if (!_detectSample.IsSample(movie, quality, videoFile, size, episodeParseResult.IsPossibleSpecialEpisode))
|
|
||||||
{
|
|
||||||
_logger.Warn("Non-sample file detected: [{0}]", videoFile);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rarFiles.Any(f => _diskProvider.GetFileSize(f) > 10.Megabytes()))
|
|
||||||
{
|
|
||||||
_logger.Warn("RAR file detected, will require manual cleanup");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode importMode, DownloadClientItem downloadClientItem)
|
|
||||||
{
|
|
||||||
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
|
||||||
var movie = _parsingService.GetMovie(cleanedUpName);
|
|
||||||
|
|
||||||
if (movie == null)
|
|
||||||
{
|
|
||||||
_logger.Debug("Unknown Movie {0}", cleanedUpName);
|
|
||||||
|
|
||||||
return new List<ImportResult>
|
|
||||||
{
|
|
||||||
UnknownMovieResult("Unknown Movie")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return ProcessFolder(directoryInfo, importMode, movie, downloadClientItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode importMode, Movie movie, DownloadClientItem downloadClientItem)
|
|
||||||
{
|
|
||||||
if (_movieService.MoviePathExists(directoryInfo.FullName))
|
|
||||||
{
|
|
||||||
_logger.Warn("Unable to process folder that is mapped to an existing show");
|
|
||||||
return new List<ImportResult>();
|
return new List<ImportResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
if (!_diskProvider.FolderExists(downloadedEpisodesFolder))
|
||||||
var folderInfo = Parser.Parser.ParseMovieTitle(directoryInfo.Name);
|
|
||||||
|
|
||||||
if (folderInfo != null)
|
|
||||||
{
|
{
|
||||||
_logger.Debug("{0} folder quality: {1}", cleanedUpName, folderInfo.Quality);
|
_logger.Warn("Drone Factory folder [{0}] doesn't exist.", downloadedEpisodesFolder);
|
||||||
|
return new List<ImportResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
return _downloadedMovieImportService.ProcessRootFolder(new DirectoryInfo(downloadedEpisodesFolder));
|
||||||
|
}
|
||||||
|
|
||||||
if (downloadClientItem == null)
|
private List<ImportResult> ProcessPath(DownloadedMovieScanCommand message)
|
||||||
|
{
|
||||||
|
if (!_diskProvider.FolderExists(message.Path) && !_diskProvider.FileExists(message.Path))
|
||||||
{
|
{
|
||||||
foreach (var videoFile in videoFiles)
|
_logger.Warn("Folder/File specified for import scan [{0}] doesn't exist.", message.Path);
|
||||||
|
return new List<ImportResult>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.DownloadClientId.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
var trackedDownload = _trackedDownloadService.Find(message.DownloadClientId);
|
||||||
|
|
||||||
|
if (trackedDownload != null)
|
||||||
{
|
{
|
||||||
if (_diskProvider.IsFileLocked(videoFile))
|
_logger.Debug("External directory scan request for known download {0}. [{1}]", message.DownloadClientId, message.Path);
|
||||||
{
|
|
||||||
return new List<ImportResult>
|
return _downloadedMovieImportService.ProcessPath(message.Path, message.ImportMode, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
|
||||||
{
|
}
|
||||||
FileIsLockedResult(videoFile)
|
else
|
||||||
};
|
{
|
||||||
}
|
_logger.Warn("External directory scan request for unknown download {0}, attempting normal import. [{1}]", message.DownloadClientId, message.Path);
|
||||||
|
|
||||||
|
return _downloadedMovieImportService.ProcessPath(message.Path, message.ImportMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true);
|
return _downloadedMovieImportService.ProcessPath(message.Path, message.ImportMode);
|
||||||
var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
}
|
||||||
|
|
||||||
if ((downloadClientItem == null || !downloadClientItem.IsReadOnly) &&
|
public void Execute(DownloadedMovieScanCommand message)
|
||||||
importResults.Any(i => i.Result == ImportResultType.Imported) &&
|
{
|
||||||
ShouldDeleteFolder(directoryInfo, movie))
|
List<ImportResult> importResults;
|
||||||
|
|
||||||
|
if (message.Path.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
_logger.Debug("Deleting folder after importing valid files");
|
importResults = ProcessPath(message);
|
||||||
_diskProvider.DeleteFolder(directoryInfo.FullName, true);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
importResults = ProcessDroneFactoryFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
return importResults;
|
if (importResults == null || importResults.All(v => v.Result != ImportResultType.Imported))
|
||||||
}
|
|
||||||
|
|
||||||
private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode, DownloadClientItem downloadClientItem)
|
|
||||||
{
|
|
||||||
var movie = _parsingService.GetMovie(Path.GetFileNameWithoutExtension(fileInfo.Name));
|
|
||||||
|
|
||||||
if (movie == null)
|
|
||||||
{
|
{
|
||||||
_logger.Debug("Unknown Movie for file: {0}", fileInfo.Name);
|
// Atm we don't report it as a command failure, coz that would cause the download to be failed.
|
||||||
|
// Changing the message won't do a thing either, coz it will get set to 'Completed' a msec later.
|
||||||
return new List<ImportResult>
|
//message.SetMessage("Failed to import");
|
||||||
{
|
|
||||||
UnknownMovieResult(string.Format("Unknown Movie for file: {0}", fileInfo.Name), fileInfo.FullName)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ProcessFile(fileInfo, importMode, movie, downloadClientItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode, Movie movie, DownloadClientItem downloadClientItem)
|
|
||||||
{
|
|
||||||
if (Path.GetFileNameWithoutExtension(fileInfo.Name).StartsWith("._"))
|
|
||||||
{
|
|
||||||
_logger.Debug("[{0}] starts with '._', skipping", fileInfo.FullName);
|
|
||||||
|
|
||||||
return new List<ImportResult>
|
|
||||||
{
|
|
||||||
new ImportResult(new ImportDecision(new LocalEpisode { Path = fileInfo.FullName }, new Rejection("Invalid video file, filename starts with '._'")), "Invalid video file, filename starts with '._'")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (downloadClientItem == null)
|
|
||||||
{
|
|
||||||
if (_diskProvider.IsFileLocked(fileInfo.FullName))
|
|
||||||
{
|
|
||||||
return new List<ImportResult>
|
|
||||||
{
|
|
||||||
FileIsLockedResult(fileInfo.FullName)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true);
|
|
||||||
|
|
||||||
return _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetCleanedUpFolderName(string folder)
|
|
||||||
{
|
|
||||||
folder = folder.Replace("_UNPACK_", "")
|
|
||||||
.Replace("_FAILED_", "");
|
|
||||||
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ImportResult FileIsLockedResult(string videoFile)
|
|
||||||
{
|
|
||||||
_logger.Debug("[{0}] is currently locked by another process, skipping", videoFile);
|
|
||||||
return new ImportResult(new ImportDecision(new LocalEpisode { Path = videoFile }, new Rejection("Locked file, try again later")), "Locked file, try again later");
|
|
||||||
}
|
|
||||||
|
|
||||||
private ImportResult UnknownMovieResult(string message, string videoFile = null)
|
|
||||||
{
|
|
||||||
var localEpisode = videoFile == null ? null : new LocalEpisode { Path = videoFile };
|
|
||||||
|
|
||||||
return new ImportResult(new ImportDecision(localEpisode, new Rejection("Unknown Movie")), message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
266
src/NzbDrone.Core/MediaFiles/DownloadedMovieImportService.cs
Normal file
266
src/NzbDrone.Core/MediaFiles/DownloadedMovieImportService.cs
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.MediaFiles.Commands;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles
|
||||||
|
{
|
||||||
|
public interface IDownloadedMovieImportService
|
||||||
|
{
|
||||||
|
List<ImportResult> ProcessRootFolder(DirectoryInfo directoryInfo);
|
||||||
|
List<ImportResult> ProcessPath(string path, ImportMode importMode = ImportMode.Auto, Movie movie = null, DownloadClientItem downloadClientItem = null);
|
||||||
|
bool ShouldDeleteFolder(DirectoryInfo directoryInfo, Movie movie);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DownloadedMovieImportService : IDownloadedMovieImportService
|
||||||
|
{
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly IDiskScanService _diskScanService;
|
||||||
|
private readonly IMovieService _movieService;
|
||||||
|
private readonly IParsingService _parsingService;
|
||||||
|
private readonly IMakeImportDecision _importDecisionMaker;
|
||||||
|
private readonly IImportApprovedMovie _importApprovedMovie;
|
||||||
|
private readonly IDetectSample _detectSample;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public DownloadedMovieImportService(IDiskProvider diskProvider,
|
||||||
|
IDiskScanService diskScanService,
|
||||||
|
IMovieService movieService,
|
||||||
|
IParsingService parsingService,
|
||||||
|
IMakeImportDecision importDecisionMaker,
|
||||||
|
IImportApprovedMovie importApprovedMovie,
|
||||||
|
IDetectSample detectSample,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
_diskScanService = diskScanService;
|
||||||
|
_movieService = movieService;
|
||||||
|
_parsingService = parsingService;
|
||||||
|
_importDecisionMaker = importDecisionMaker;
|
||||||
|
_importApprovedMovie = importApprovedMovie;
|
||||||
|
_detectSample = detectSample;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ImportResult> ProcessRootFolder(DirectoryInfo directoryInfo)
|
||||||
|
{
|
||||||
|
var results = new List<ImportResult>();
|
||||||
|
|
||||||
|
foreach (var subFolder in _diskProvider.GetDirectories(directoryInfo.FullName))
|
||||||
|
{
|
||||||
|
var folderResults = ProcessFolder(new DirectoryInfo(subFolder), ImportMode.Auto, null);
|
||||||
|
results.AddRange(folderResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var videoFile in _diskScanService.GetVideoFiles(directoryInfo.FullName, false))
|
||||||
|
{
|
||||||
|
var fileResults = ProcessFile(new FileInfo(videoFile), ImportMode.Auto, null);
|
||||||
|
results.AddRange(fileResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ImportResult> ProcessPath(string path, ImportMode importMode = ImportMode.Auto, Movie movie = null, DownloadClientItem downloadClientItem = null)
|
||||||
|
{
|
||||||
|
if (_diskProvider.FolderExists(path))
|
||||||
|
{
|
||||||
|
var directoryInfo = new DirectoryInfo(path);
|
||||||
|
|
||||||
|
if (movie == null)
|
||||||
|
{
|
||||||
|
return ProcessFolder(directoryInfo, importMode, downloadClientItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessFolder(directoryInfo, importMode, movie, downloadClientItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_diskProvider.FileExists(path))
|
||||||
|
{
|
||||||
|
var fileInfo = new FileInfo(path);
|
||||||
|
|
||||||
|
if (movie == null)
|
||||||
|
{
|
||||||
|
return ProcessFile(fileInfo, importMode, downloadClientItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessFile(fileInfo, importMode, movie, downloadClientItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Error("Import failed, path does not exist or is not accessible by Radarr: {0}", path);
|
||||||
|
return new List<ImportResult>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShouldDeleteFolder(DirectoryInfo directoryInfo, Movie movie)
|
||||||
|
{
|
||||||
|
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
||||||
|
var rarFiles = _diskProvider.GetFiles(directoryInfo.FullName, SearchOption.AllDirectories).Where(f => Path.GetExtension(f) == ".rar");
|
||||||
|
|
||||||
|
foreach (var videoFile in videoFiles)
|
||||||
|
{
|
||||||
|
var episodeParseResult = Parser.Parser.ParseTitle(Path.GetFileName(videoFile));
|
||||||
|
|
||||||
|
if (episodeParseResult == null)
|
||||||
|
{
|
||||||
|
_logger.Warn("Unable to parse file on import: [{0}]", videoFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var size = _diskProvider.GetFileSize(videoFile);
|
||||||
|
var quality = QualityParser.ParseQuality(videoFile);
|
||||||
|
|
||||||
|
if (!_detectSample.IsSample(movie, quality, videoFile, size, episodeParseResult.IsPossibleSpecialEpisode))
|
||||||
|
{
|
||||||
|
_logger.Warn("Non-sample file detected: [{0}]", videoFile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rarFiles.Any(f => _diskProvider.GetFileSize(f) > 10.Megabytes()))
|
||||||
|
{
|
||||||
|
_logger.Warn("RAR file detected, will require manual cleanup");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode importMode, DownloadClientItem downloadClientItem)
|
||||||
|
{
|
||||||
|
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
||||||
|
var movie = _parsingService.GetMovie(cleanedUpName);
|
||||||
|
|
||||||
|
if (movie == null)
|
||||||
|
{
|
||||||
|
_logger.Debug("Unknown Movie {0}", cleanedUpName);
|
||||||
|
|
||||||
|
return new List<ImportResult>
|
||||||
|
{
|
||||||
|
UnknownMovieResult("Unknown Movie")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessFolder(directoryInfo, importMode, movie, downloadClientItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode importMode, Movie movie, DownloadClientItem downloadClientItem)
|
||||||
|
{
|
||||||
|
if (_movieService.MoviePathExists(directoryInfo.FullName))
|
||||||
|
{
|
||||||
|
_logger.Warn("Unable to process folder that is mapped to an existing show");
|
||||||
|
return new List<ImportResult>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var cleanedUpName = GetCleanedUpFolderName(directoryInfo.Name);
|
||||||
|
var folderInfo = Parser.Parser.ParseMovieTitle(directoryInfo.Name);
|
||||||
|
|
||||||
|
if (folderInfo != null)
|
||||||
|
{
|
||||||
|
_logger.Debug("{0} folder quality: {1}", cleanedUpName, folderInfo.Quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
var videoFiles = _diskScanService.GetVideoFiles(directoryInfo.FullName);
|
||||||
|
|
||||||
|
if (downloadClientItem == null)
|
||||||
|
{
|
||||||
|
foreach (var videoFile in videoFiles)
|
||||||
|
{
|
||||||
|
if (_diskProvider.IsFileLocked(videoFile))
|
||||||
|
{
|
||||||
|
return new List<ImportResult>
|
||||||
|
{
|
||||||
|
FileIsLockedResult(videoFile)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true);
|
||||||
|
var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
||||||
|
|
||||||
|
if ((downloadClientItem == null || !downloadClientItem.IsReadOnly) &&
|
||||||
|
importResults.Any(i => i.Result == ImportResultType.Imported) &&
|
||||||
|
ShouldDeleteFolder(directoryInfo, movie))
|
||||||
|
{
|
||||||
|
_logger.Debug("Deleting folder after importing valid files");
|
||||||
|
_diskProvider.DeleteFolder(directoryInfo.FullName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return importResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode, DownloadClientItem downloadClientItem)
|
||||||
|
{
|
||||||
|
var movie = _parsingService.GetMovie(Path.GetFileNameWithoutExtension(fileInfo.Name));
|
||||||
|
|
||||||
|
if (movie == null)
|
||||||
|
{
|
||||||
|
_logger.Debug("Unknown Movie for file: {0}", fileInfo.Name);
|
||||||
|
|
||||||
|
return new List<ImportResult>
|
||||||
|
{
|
||||||
|
UnknownMovieResult(string.Format("Unknown Movie for file: {0}", fileInfo.Name), fileInfo.FullName)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessFile(fileInfo, importMode, movie, downloadClientItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode, Movie movie, DownloadClientItem downloadClientItem)
|
||||||
|
{
|
||||||
|
if (Path.GetFileNameWithoutExtension(fileInfo.Name).StartsWith("._"))
|
||||||
|
{
|
||||||
|
_logger.Debug("[{0}] starts with '._', skipping", fileInfo.FullName);
|
||||||
|
|
||||||
|
return new List<ImportResult>
|
||||||
|
{
|
||||||
|
new ImportResult(new ImportDecision(new LocalEpisode { Path = fileInfo.FullName }, new Rejection("Invalid video file, filename starts with '._'")), "Invalid video file, filename starts with '._'")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloadClientItem == null)
|
||||||
|
{
|
||||||
|
if (_diskProvider.IsFileLocked(fileInfo.FullName))
|
||||||
|
{
|
||||||
|
return new List<ImportResult>
|
||||||
|
{
|
||||||
|
FileIsLockedResult(fileInfo.FullName)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true);
|
||||||
|
|
||||||
|
return _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetCleanedUpFolderName(string folder)
|
||||||
|
{
|
||||||
|
folder = folder.Replace("_UNPACK_", "")
|
||||||
|
.Replace("_FAILED_", "");
|
||||||
|
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImportResult FileIsLockedResult(string videoFile)
|
||||||
|
{
|
||||||
|
_logger.Debug("[{0}] is currently locked by another process, skipping", videoFile);
|
||||||
|
return new ImportResult(new ImportDecision(new LocalEpisode { Path = videoFile }, new Rejection("Locked file, try again later")), "Locked file, try again later");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImportResult UnknownMovieResult(string message, string videoFile = null)
|
||||||
|
{
|
||||||
|
var localEpisode = videoFile == null ? null : new LocalEpisode { Path = videoFile };
|
||||||
|
|
||||||
|
return new ImportResult(new ImportDecision(localEpisode, new Rejection("Unknown Movie")), message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -153,7 +153,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
private int GetMinimumAllowedRuntime(Movie movie)
|
private int GetMinimumAllowedRuntime(Movie movie)
|
||||||
{
|
{
|
||||||
return 120; //2 minutes
|
return 360; //6 minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetMinimumAllowedRuntime(Series series)
|
private int GetMinimumAllowedRuntime(Series series)
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
|||||||
public List<int> EpisodeIds { get; set; }
|
public List<int> EpisodeIds { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
|
public int MovieId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,5 +17,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
|||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
public IEnumerable<Rejection> Rejections { get; set; }
|
public IEnumerable<Rejection> Rejections { get; set; }
|
||||||
|
public Movie Movie { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
|||||||
private readonly IDiskScanService _diskScanService;
|
private readonly IDiskScanService _diskScanService;
|
||||||
private readonly IMakeImportDecision _importDecisionMaker;
|
private readonly IMakeImportDecision _importDecisionMaker;
|
||||||
private readonly ISeriesService _seriesService;
|
private readonly ISeriesService _seriesService;
|
||||||
|
private readonly IMovieService _movieService;
|
||||||
private readonly IEpisodeService _episodeService;
|
private readonly IEpisodeService _episodeService;
|
||||||
private readonly IVideoFileInfoReader _videoFileInfoReader;
|
private readonly IVideoFileInfoReader _videoFileInfoReader;
|
||||||
private readonly IImportApprovedEpisodes _importApprovedEpisodes;
|
private readonly IImportApprovedEpisodes _importApprovedEpisodes;
|
||||||
|
private readonly IImportApprovedMovie _importApprovedMovie;
|
||||||
private readonly ITrackedDownloadService _trackedDownloadService;
|
private readonly ITrackedDownloadService _trackedDownloadService;
|
||||||
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
|
private readonly IDownloadedEpisodesImportService _downloadedEpisodesImportService;
|
||||||
|
private readonly IDownloadedMovieImportService _downloadedMovieImportService;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
@@ -43,11 +46,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
|||||||
IDiskScanService diskScanService,
|
IDiskScanService diskScanService,
|
||||||
IMakeImportDecision importDecisionMaker,
|
IMakeImportDecision importDecisionMaker,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
|
IMovieService movieService,
|
||||||
IEpisodeService episodeService,
|
IEpisodeService episodeService,
|
||||||
IVideoFileInfoReader videoFileInfoReader,
|
IVideoFileInfoReader videoFileInfoReader,
|
||||||
IImportApprovedEpisodes importApprovedEpisodes,
|
IImportApprovedEpisodes importApprovedEpisodes,
|
||||||
|
IImportApprovedMovie importApprovedMovie,
|
||||||
ITrackedDownloadService trackedDownloadService,
|
ITrackedDownloadService trackedDownloadService,
|
||||||
IDownloadedEpisodesImportService downloadedEpisodesImportService,
|
IDownloadedEpisodesImportService downloadedEpisodesImportService,
|
||||||
|
IDownloadedMovieImportService downloadedMovieImportService,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
@@ -56,11 +62,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
|||||||
_diskScanService = diskScanService;
|
_diskScanService = diskScanService;
|
||||||
_importDecisionMaker = importDecisionMaker;
|
_importDecisionMaker = importDecisionMaker;
|
||||||
_seriesService = seriesService;
|
_seriesService = seriesService;
|
||||||
|
_movieService = movieService;
|
||||||
_episodeService = episodeService;
|
_episodeService = episodeService;
|
||||||
_videoFileInfoReader = videoFileInfoReader;
|
_videoFileInfoReader = videoFileInfoReader;
|
||||||
_importApprovedEpisodes = importApprovedEpisodes;
|
_importApprovedEpisodes = importApprovedEpisodes;
|
||||||
|
_importApprovedMovie = importApprovedMovie;
|
||||||
_trackedDownloadService = trackedDownloadService;
|
_trackedDownloadService = trackedDownloadService;
|
||||||
_downloadedEpisodesImportService = downloadedEpisodesImportService;
|
_downloadedEpisodesImportService = downloadedEpisodesImportService;
|
||||||
|
_downloadedMovieImportService = downloadedMovieImportService;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
@@ -126,62 +135,128 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
|||||||
|
|
||||||
var relativeFile = folder.GetRelativePath(file);
|
var relativeFile = folder.GetRelativePath(file);
|
||||||
|
|
||||||
var series = _parsingService.GetSeries(relativeFile.Split('\\', '/')[0]);
|
var movie = _parsingService.GetMovie(relativeFile.Split('\\', '/')[0]);
|
||||||
|
|
||||||
if (series == null)
|
if (movie == null)
|
||||||
{
|
{
|
||||||
series = _parsingService.GetSeries(relativeFile);
|
movie = _parsingService.GetMovie(relativeFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series == null && downloadId.IsNotNullOrWhiteSpace())
|
if (movie == null && downloadId.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
var trackedDownload = _trackedDownloadService.Find(downloadId);
|
var trackedDownload = _trackedDownloadService.Find(downloadId);
|
||||||
series = trackedDownload.RemoteEpisode.Series;
|
movie = trackedDownload.RemoteMovie.Movie;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series == null)
|
if (movie == null)
|
||||||
{
|
{
|
||||||
var localEpisode = new LocalEpisode();
|
var localMovie = new LocalMovie()
|
||||||
localEpisode.Path = file;
|
{
|
||||||
localEpisode.Quality = QualityParser.ParseQuality(file);
|
Path = file,
|
||||||
localEpisode.Size = _diskProvider.GetFileSize(file);
|
Quality = QualityParser.ParseQuality(file),
|
||||||
|
Size = _diskProvider.GetFileSize(file)
|
||||||
|
};
|
||||||
|
|
||||||
return MapItem(new ImportDecision(localEpisode, new Rejection("Unknown Series")), folder, downloadId);
|
return MapItem(new ImportDecision(localMovie, new Rejection("Unknown Movie")), folder, downloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> {file},
|
var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> { file },
|
||||||
series, null, SceneSource(series, folder));
|
movie, null, SceneSource(movie, folder));
|
||||||
|
|
||||||
return importDecisions.Any() ? MapItem(importDecisions.First(), folder, downloadId) : null;
|
return importDecisions.Any() ? MapItem(importDecisions.First(), folder, downloadId) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//private ManualImportItem ProcessFile(string file, string downloadId, string folder = null)
|
||||||
|
//{
|
||||||
|
// if (folder.IsNullOrWhiteSpace())
|
||||||
|
// {
|
||||||
|
// folder = new FileInfo(file).Directory.FullName;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var relativeFile = folder.GetRelativePath(file);
|
||||||
|
|
||||||
|
// var series = _parsingService.GetSeries(relativeFile.Split('\\', '/')[0]);
|
||||||
|
|
||||||
|
// if (series == null)
|
||||||
|
// {
|
||||||
|
// series = _parsingService.GetSeries(relativeFile);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (series == null && downloadId.IsNotNullOrWhiteSpace())
|
||||||
|
// {
|
||||||
|
// var trackedDownload = _trackedDownloadService.Find(downloadId);
|
||||||
|
// series = trackedDownload.RemoteEpisode.Series;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (series == null)
|
||||||
|
// {
|
||||||
|
// var localEpisode = new LocalEpisode();
|
||||||
|
// localEpisode.Path = file;
|
||||||
|
// localEpisode.Quality = QualityParser.ParseQuality(file);
|
||||||
|
// localEpisode.Size = _diskProvider.GetFileSize(file);
|
||||||
|
|
||||||
|
// return MapItem(new ImportDecision(localEpisode, new Rejection("Unknown Series")), folder, downloadId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> {file},
|
||||||
|
// series, null, SceneSource(series, folder));
|
||||||
|
|
||||||
|
// return importDecisions.Any() ? MapItem(importDecisions.First(), folder, downloadId) : null;
|
||||||
|
//}
|
||||||
|
|
||||||
private bool SceneSource(Series series, string folder)
|
private bool SceneSource(Series series, string folder)
|
||||||
{
|
{
|
||||||
return !(series.Path.PathEquals(folder) || series.Path.IsParentPath(folder));
|
return !(series.Path.PathEquals(folder) || series.Path.IsParentPath(folder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool SceneSource(Movie movie, string folder)
|
||||||
|
{
|
||||||
|
return !(movie.Path.PathEquals(folder) || movie.Path.IsParentPath(folder));
|
||||||
|
}
|
||||||
|
|
||||||
|
//private ManualImportItem MapItem(ImportDecision decision, string folder, string downloadId)
|
||||||
|
//{
|
||||||
|
// var item = new ManualImportItem();
|
||||||
|
|
||||||
|
// item.Path = decision.LocalEpisode.Path;
|
||||||
|
// item.RelativePath = folder.GetRelativePath(decision.LocalEpisode.Path);
|
||||||
|
// item.Name = Path.GetFileNameWithoutExtension(decision.LocalEpisode.Path);
|
||||||
|
// item.DownloadId = downloadId;
|
||||||
|
|
||||||
|
// if (decision.LocalEpisode.Series != null)
|
||||||
|
// {
|
||||||
|
// item.Series = decision.LocalEpisode.Series;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (decision.LocalEpisode.Episodes.Any())
|
||||||
|
// {
|
||||||
|
// item.SeasonNumber = decision.LocalEpisode.SeasonNumber;
|
||||||
|
// item.Episodes = decision.LocalEpisode.Episodes;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// item.Quality = decision.LocalEpisode.Quality;
|
||||||
|
// item.Size = _diskProvider.GetFileSize(decision.LocalEpisode.Path);
|
||||||
|
// item.Rejections = decision.Rejections;
|
||||||
|
|
||||||
|
// return item;
|
||||||
|
//}
|
||||||
|
|
||||||
private ManualImportItem MapItem(ImportDecision decision, string folder, string downloadId)
|
private ManualImportItem MapItem(ImportDecision decision, string folder, string downloadId)
|
||||||
{
|
{
|
||||||
var item = new ManualImportItem();
|
var item = new ManualImportItem();
|
||||||
|
|
||||||
item.Path = decision.LocalEpisode.Path;
|
item.Path = decision.LocalMovie.Path;
|
||||||
item.RelativePath = folder.GetRelativePath(decision.LocalEpisode.Path);
|
item.RelativePath = folder.GetRelativePath(decision.LocalMovie.Path);
|
||||||
item.Name = Path.GetFileNameWithoutExtension(decision.LocalEpisode.Path);
|
item.Name = Path.GetFileNameWithoutExtension(decision.LocalMovie.Path);
|
||||||
item.DownloadId = downloadId;
|
item.DownloadId = downloadId;
|
||||||
|
|
||||||
if (decision.LocalEpisode.Series != null)
|
if (decision.LocalMovie.Movie != null)
|
||||||
{
|
{
|
||||||
item.Series = decision.LocalEpisode.Series;
|
item.Movie = decision.LocalMovie.Movie;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decision.LocalEpisode.Episodes.Any())
|
item.Quality = decision.LocalMovie.Quality;
|
||||||
{
|
item.Size = _diskProvider.GetFileSize(decision.LocalMovie.Path);
|
||||||
item.SeasonNumber = decision.LocalEpisode.SeasonNumber;
|
|
||||||
item.Episodes = decision.LocalEpisode.Episodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
item.Quality = decision.LocalEpisode.Quality;
|
|
||||||
item.Size = _diskProvider.GetFileSize(decision.LocalEpisode.Path);
|
|
||||||
item.Rejections = decision.Rejections;
|
item.Rejections = decision.Rejections;
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
@@ -199,45 +274,43 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
|||||||
_logger.ProgressTrace("Processing file {0} of {1}", i + 1, message.Files.Count);
|
_logger.ProgressTrace("Processing file {0} of {1}", i + 1, message.Files.Count);
|
||||||
|
|
||||||
var file = message.Files[i];
|
var file = message.Files[i];
|
||||||
var series = _seriesService.GetSeries(file.SeriesId);
|
var movie = _movieService.GetMovie(file.MovieId);
|
||||||
var episodes = _episodeService.GetEpisodes(file.EpisodeIds);
|
var parsedMovieInfo = Parser.Parser.ParseMoviePath(file.Path) ?? new ParsedMovieInfo();
|
||||||
var parsedEpisodeInfo = Parser.Parser.ParsePath(file.Path) ?? new ParsedEpisodeInfo();
|
|
||||||
var mediaInfo = _videoFileInfoReader.GetMediaInfo(file.Path);
|
var mediaInfo = _videoFileInfoReader.GetMediaInfo(file.Path);
|
||||||
var existingFile = series.Path.IsParentPath(file.Path);
|
var existingFile = movie.Path.IsParentPath(file.Path);
|
||||||
|
|
||||||
var localEpisode = new LocalEpisode
|
var localMovie = new LocalMovie
|
||||||
{
|
{
|
||||||
ExistingFile = false,
|
ExistingFile = false,
|
||||||
Episodes = episodes,
|
|
||||||
MediaInfo = mediaInfo,
|
MediaInfo = mediaInfo,
|
||||||
ParsedEpisodeInfo = parsedEpisodeInfo,
|
ParsedMovieInfo = parsedMovieInfo,
|
||||||
Path = file.Path,
|
Path = file.Path,
|
||||||
Quality = file.Quality,
|
Quality = file.Quality,
|
||||||
Series = series,
|
Movie = movie,
|
||||||
Size = 0
|
Size = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: Cleanup non-tracked downloads
|
//TODO: Cleanup non-tracked downloads
|
||||||
|
|
||||||
var importDecision = new ImportDecision(localEpisode);
|
var importDecision = new ImportDecision(localMovie);
|
||||||
|
|
||||||
if (file.DownloadId.IsNullOrWhiteSpace())
|
if (file.DownloadId.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
imported.AddRange(_importApprovedEpisodes.Import(new List<ImportDecision> { importDecision }, !existingFile, null, message.ImportMode));
|
imported.AddRange(_importApprovedMovie.Import(new List<ImportDecision> { importDecision }, !existingFile, null, message.ImportMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var trackedDownload = _trackedDownloadService.Find(file.DownloadId);
|
var trackedDownload = _trackedDownloadService.Find(file.DownloadId);
|
||||||
var importResult = _importApprovedEpisodes.Import(new List<ImportDecision> { importDecision }, true, trackedDownload.DownloadItem, message.ImportMode).First();
|
var importResult = _importApprovedMovie.Import(new List<ImportDecision> { importDecision }, true, trackedDownload.DownloadItem, message.ImportMode).First();
|
||||||
|
|
||||||
imported.Add(importResult);
|
imported.Add(importResult);
|
||||||
|
|
||||||
importedTrackedDownload.Add(new ManuallyImportedFile
|
importedTrackedDownload.Add(new ManuallyImportedFile
|
||||||
{
|
{
|
||||||
TrackedDownload = trackedDownload,
|
TrackedDownload = trackedDownload,
|
||||||
ImportResult = importResult
|
ImportResult = importResult
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,20 +322,98 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
|||||||
|
|
||||||
if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath.FullPath))
|
if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath.FullPath))
|
||||||
{
|
{
|
||||||
if (_downloadedEpisodesImportService.ShouldDeleteFolder(
|
if (_downloadedMovieImportService.ShouldDeleteFolder(
|
||||||
new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath),
|
new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath),
|
||||||
trackedDownload.RemoteEpisode.Series) && !trackedDownload.DownloadItem.IsReadOnly)
|
trackedDownload.RemoteMovie.Movie) && !trackedDownload.DownloadItem.IsReadOnly)
|
||||||
{
|
{
|
||||||
_diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true);
|
_diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupedTrackedDownload.Select(c => c.ImportResult).Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count))
|
if (groupedTrackedDownload.Select(c => c.ImportResult).Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, 1)) //TODO: trackedDownload.RemoteMovie.Movie.Count is always 1?
|
||||||
{
|
{
|
||||||
trackedDownload.State = TrackedDownloadStage.Imported;
|
trackedDownload.State = TrackedDownloadStage.Imported;
|
||||||
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
|
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//public void Execute(ManualImportCommand message)
|
||||||
|
//{
|
||||||
|
// _logger.ProgressTrace("Manually importing {0} files using mode {1}", message.Files.Count, message.ImportMode);
|
||||||
|
|
||||||
|
// var imported = new List<ImportResult>();
|
||||||
|
// var importedTrackedDownload = new List<ManuallyImportedFile>();
|
||||||
|
|
||||||
|
// for (int i = 0; i < message.Files.Count; i++)
|
||||||
|
// {
|
||||||
|
// _logger.ProgressTrace("Processing file {0} of {1}", i + 1, message.Files.Count);
|
||||||
|
|
||||||
|
// var file = message.Files[i];
|
||||||
|
// var series = _seriesService.GetSeries(file.SeriesId);
|
||||||
|
// var episodes = _episodeService.GetEpisodes(file.EpisodeIds);
|
||||||
|
// var parsedEpisodeInfo = Parser.Parser.ParsePath(file.Path) ?? new ParsedEpisodeInfo();
|
||||||
|
// var mediaInfo = _videoFileInfoReader.GetMediaInfo(file.Path);
|
||||||
|
// var existingFile = series.Path.IsParentPath(file.Path);
|
||||||
|
|
||||||
|
// var localEpisode = new LocalEpisode
|
||||||
|
// {
|
||||||
|
// ExistingFile = false,
|
||||||
|
// Episodes = episodes,
|
||||||
|
// MediaInfo = mediaInfo,
|
||||||
|
// ParsedEpisodeInfo = parsedEpisodeInfo,
|
||||||
|
// Path = file.Path,
|
||||||
|
// Quality = file.Quality,
|
||||||
|
// Series = series,
|
||||||
|
// Size = 0
|
||||||
|
// };
|
||||||
|
|
||||||
|
// //TODO: Cleanup non-tracked downloads
|
||||||
|
|
||||||
|
// var importDecision = new ImportDecision(localEpisode);
|
||||||
|
|
||||||
|
// if (file.DownloadId.IsNullOrWhiteSpace())
|
||||||
|
// {
|
||||||
|
// imported.AddRange(_importApprovedEpisodes.Import(new List<ImportDecision> { importDecision }, !existingFile, null, message.ImportMode));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// var trackedDownload = _trackedDownloadService.Find(file.DownloadId);
|
||||||
|
// var importResult = _importApprovedEpisodes.Import(new List<ImportDecision> { importDecision }, true, trackedDownload.DownloadItem, message.ImportMode).First();
|
||||||
|
|
||||||
|
// imported.Add(importResult);
|
||||||
|
|
||||||
|
// importedTrackedDownload.Add(new ManuallyImportedFile
|
||||||
|
// {
|
||||||
|
// TrackedDownload = trackedDownload,
|
||||||
|
// ImportResult = importResult
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _logger.ProgressTrace("Manually imported {0} files", imported.Count);
|
||||||
|
|
||||||
|
// foreach (var groupedTrackedDownload in importedTrackedDownload.GroupBy(i => i.TrackedDownload.DownloadItem.DownloadId).ToList())
|
||||||
|
// {
|
||||||
|
// var trackedDownload = groupedTrackedDownload.First().TrackedDownload;
|
||||||
|
|
||||||
|
// if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath.FullPath))
|
||||||
|
// {
|
||||||
|
// if (_downloadedEpisodesImportService.ShouldDeleteFolder(
|
||||||
|
// new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath),
|
||||||
|
// trackedDownload.RemoteEpisode.Series) && !trackedDownload.DownloadItem.IsReadOnly)
|
||||||
|
// {
|
||||||
|
// _diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (groupedTrackedDownload.Select(c => c.ImportResult).Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count))
|
||||||
|
// {
|
||||||
|
// trackedDownload.State = TrackedDownloadStage.Imported;
|
||||||
|
// _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
|||||||
|
|
||||||
public Decision IsSatisfiedBy(LocalMovie localEpisode)
|
public Decision IsSatisfiedBy(LocalMovie localEpisode)
|
||||||
{
|
{
|
||||||
if (localEpisode.ExistingFile)
|
|
||||||
{
|
|
||||||
_logger.Debug("Existing file, skipping sample check");
|
|
||||||
return Decision.Accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
var sample = _detectSample.IsSample(localEpisode.Movie,
|
var sample = _detectSample.IsSample(localEpisode.Movie,
|
||||||
localEpisode.Quality,
|
localEpisode.Quality,
|
||||||
localEpisode.Path,
|
localEpisode.Path,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
|||||||
public Production_Companies[] production_companies { get; set; }
|
public Production_Companies[] production_companies { get; set; }
|
||||||
public Production_Countries[] production_countries { get; set; }
|
public Production_Countries[] production_countries { get; set; }
|
||||||
public string release_date { get; set; }
|
public string release_date { get; set; }
|
||||||
public int revenue { get; set; }
|
public long revenue { get; set; }
|
||||||
public int runtime { get; set; }
|
public int runtime { get; set; }
|
||||||
public Spoken_Languages[] spoken_languages { get; set; }
|
public Spoken_Languages[] spoken_languages { get; set; }
|
||||||
public string status { get; set; }
|
public string status { get; set; }
|
||||||
|
|||||||
@@ -92,8 +92,11 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||||||
movie.CleanTitle = Parser.Parser.CleanSeriesTitle(movie.Title);
|
movie.CleanTitle = Parser.Parser.CleanSeriesTitle(movie.Title);
|
||||||
movie.Overview = resource.overview;
|
movie.Overview = resource.overview;
|
||||||
movie.Website = resource.homepage;
|
movie.Website = resource.homepage;
|
||||||
movie.InCinemas = DateTime.Parse(resource.release_date);
|
if (resource.release_date.IsNotNullOrWhiteSpace())
|
||||||
movie.Year = movie.InCinemas.Value.Year;
|
{
|
||||||
|
movie.InCinemas = DateTime.Parse(resource.release_date);
|
||||||
|
movie.Year = movie.InCinemas.Value.Year;
|
||||||
|
}
|
||||||
|
|
||||||
var slugResult = _movieService.FindByTitleSlug(movie.TitleSlug);
|
var slugResult = _movieService.FindByTitleSlug(movie.TitleSlug);
|
||||||
if (slugResult != null)
|
if (slugResult != null)
|
||||||
@@ -186,7 +189,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||||||
{
|
{
|
||||||
var lowerTitle = title.ToLower();
|
var lowerTitle = title.ToLower();
|
||||||
|
|
||||||
var parserResult = Parser.Parser.ParseMovieTitle(title);
|
var parserResult = Parser.Parser.ParseMovieTitle(title, true);
|
||||||
|
|
||||||
var yearTerm = "";
|
var yearTerm = "";
|
||||||
|
|
||||||
@@ -324,11 +327,17 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
|
|||||||
imdbMovie.TmdbId = result.id;
|
imdbMovie.TmdbId = result.id;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
imdbMovie.SortTitle = result.title;
|
imdbMovie.SortTitle = Parser.Parser.NormalizeTitle(result.title);
|
||||||
imdbMovie.Title = result.title;
|
imdbMovie.Title = result.title;
|
||||||
string titleSlug = result.title;
|
string titleSlug = result.title;
|
||||||
imdbMovie.TitleSlug = titleSlug.ToLower().Replace(" ", "-");
|
imdbMovie.TitleSlug = titleSlug.ToLower().Replace(" ", "-");
|
||||||
imdbMovie.Year = DateTime.Parse(result.release_date).Year;
|
|
||||||
|
if (result.release_date.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
imdbMovie.Year = DateTime.Parse(result.release_date).Year;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var slugResult = _movieService.FindByTitleSlug(imdbMovie.TitleSlug);
|
var slugResult = _movieService.FindByTitleSlug(imdbMovie.TitleSlug);
|
||||||
if (slugResult != null)
|
if (slugResult != null)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace NzbDrone.Core.Notifications.Boxcar
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string title = "Test Notification";
|
const string title = "Test Notification";
|
||||||
const string body = "This is a test message from Sonarr";
|
const string body = "This is a test message from Radarr";
|
||||||
|
|
||||||
SendNotification(title, body, settings);
|
SendNotification(title, body, settings);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.Notifications.Email
|
|||||||
|
|
||||||
public override void OnGrab(GrabMessage grabMessage)
|
public override void OnGrab(GrabMessage grabMessage)
|
||||||
{
|
{
|
||||||
const string subject = "Sonarr [TV] - Grabbed";
|
const string subject = "Radarr [TV] - Grabbed";
|
||||||
var body = string.Format("{0} sent to queue.", grabMessage.Message);
|
var body = string.Format("{0} sent to queue.", grabMessage.Message);
|
||||||
|
|
||||||
_emailService.SendEmail(Settings, subject, body);
|
_emailService.SendEmail(Settings, subject, body);
|
||||||
@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Notifications.Email
|
|||||||
|
|
||||||
public override void OnDownload(DownloadMessage message)
|
public override void OnDownload(DownloadMessage message)
|
||||||
{
|
{
|
||||||
const string subject = "Sonarr [TV] - Downloaded";
|
const string subject = "Radarr [TV] - Downloaded";
|
||||||
var body = string.Format("{0} Downloaded and sorted.", message.Message);
|
var body = string.Format("{0} Downloaded and sorted.", message.Message);
|
||||||
|
|
||||||
_emailService.SendEmail(Settings, subject, body);
|
_emailService.SendEmail(Settings, subject, body);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace NzbDrone.Core.Notifications.Email
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SendEmail(settings, "Sonarr - Test Notification", body);
|
SendEmail(settings, "Radarr - Test Notification", body);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ namespace NzbDrone.Core.Notifications.Growl
|
|||||||
Register(settings.Host, settings.Port, settings.Password);
|
Register(settings.Host, settings.Port, settings.Password);
|
||||||
|
|
||||||
const string title = "Test Notification";
|
const string title = "Test Notification";
|
||||||
const string body = "This is a test message from Sonarr";
|
const string body = "This is a test message from Radarr";
|
||||||
|
|
||||||
SendNotification(title, body, "TEST", settings.Host, settings.Port, settings.Password);
|
SendNotification(title, body, "TEST", settings.Host, settings.Port, settings.Password);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ namespace NzbDrone.Core.Notifications.Join
|
|||||||
|
|
||||||
public override void OnGrab(GrabMessage grabMessage)
|
public override void OnGrab(GrabMessage grabMessage)
|
||||||
{
|
{
|
||||||
const string title = "Sonarr - Episode Grabbed";
|
const string title = "Radarr - Episode Grabbed";
|
||||||
|
|
||||||
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDownload(DownloadMessage message)
|
public override void OnDownload(DownloadMessage message)
|
||||||
{
|
{
|
||||||
const string title = "Sonarr - Episode Downloaded";
|
const string title = "Radarr - Episode Downloaded";
|
||||||
|
|
||||||
_proxy.SendNotification(title, message.Message, Settings);
|
_proxy.SendNotification(title, message.Message, Settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace NzbDrone.Core.Notifications.Join
|
|||||||
public ValidationFailure Test(JoinSettings settings)
|
public ValidationFailure Test(JoinSettings settings)
|
||||||
{
|
{
|
||||||
const string title = "Test Notification";
|
const string title = "Test Notification";
|
||||||
const string body = "This is a test message from Sonarr.";
|
const string body = "This is a test message from Radarr.";
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
|
|||||||
|
|
||||||
public override void OnGrab(GrabMessage grabMessage)
|
public override void OnGrab(GrabMessage grabMessage)
|
||||||
{
|
{
|
||||||
const string title = "Sonarr - Grabbed";
|
const string title = "Radarr - Grabbed";
|
||||||
|
|
||||||
if (Settings.Notify)
|
if (Settings.Notify)
|
||||||
{
|
{
|
||||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
|
|||||||
|
|
||||||
public override void OnDownload(DownloadMessage message)
|
public override void OnDownload(DownloadMessage message)
|
||||||
{
|
{
|
||||||
const string title = "Sonarr - Downloaded";
|
const string title = "Radarr - Downloaded";
|
||||||
|
|
||||||
if (Settings.Notify)
|
if (Settings.Notify)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace NzbDrone.Core.Notifications.NotifyMyAndroid
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string title = "Test Notification";
|
const string title = "Test Notification";
|
||||||
const string body = "This is a test message from Sonarr";
|
const string body = "This is a test message from Radarr";
|
||||||
Verify(settings.ApiKey);
|
Verify(settings.ApiKey);
|
||||||
SendNotification(title, body, settings.ApiKey, (NotifyMyAndroidPriority)settings.Priority);
|
SendNotification(title, body, settings.ApiKey, (NotifyMyAndroidPriority)settings.Priority);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ namespace NzbDrone.Core.Notifications.Plex
|
|||||||
|
|
||||||
public override void OnGrab(GrabMessage grabMessage)
|
public override void OnGrab(GrabMessage grabMessage)
|
||||||
{
|
{
|
||||||
const string header = "Sonarr [TV] - Grabbed";
|
const string header = "Radarr [TV] - Grabbed";
|
||||||
_plexClientService.Notify(Settings, header, grabMessage.Message);
|
_plexClientService.Notify(Settings, header, grabMessage.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDownload(DownloadMessage message)
|
public override void OnDownload(DownloadMessage message)
|
||||||
{
|
{
|
||||||
const string header = "Sonarr [TV] - Downloaded";
|
const string header = "Radarr [TV] - Downloaded";
|
||||||
_plexClientService.Notify(Settings, header, message.Message);
|
_plexClientService.Notify(Settings, header, message.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ namespace NzbDrone.Core.Notifications.Plex
|
|||||||
|
|
||||||
public override void OnGrab(GrabMessage grabMessage)
|
public override void OnGrab(GrabMessage grabMessage)
|
||||||
{
|
{
|
||||||
const string header = "Sonarr - Grabbed";
|
const string header = "Radarr - Grabbed";
|
||||||
|
|
||||||
Notify(Settings, header, grabMessage.Message);
|
Notify(Settings, header, grabMessage.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDownload(DownloadMessage message)
|
public override void OnDownload(DownloadMessage message)
|
||||||
{
|
{
|
||||||
const string header = "Sonarr - Downloaded";
|
const string header = "Radarr - Downloaded";
|
||||||
|
|
||||||
Notify(Settings, header, message.Message);
|
Notify(Settings, header, message.Message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
|||||||
{
|
{
|
||||||
return Json.Deserialize<PlexMediaContainerLegacy>(response.Content)
|
return Json.Deserialize<PlexMediaContainerLegacy>(response.Content)
|
||||||
.Sections
|
.Sections
|
||||||
.Where(d => d.Type == "show")
|
.Where(d => d.Type == "movie")
|
||||||
.Select(s => new PlexSection
|
.Select(s => new PlexSection
|
||||||
{
|
{
|
||||||
Id = s.Id,
|
Id = s.Id,
|
||||||
@@ -62,7 +62,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
|||||||
return Json.Deserialize<PlexResponse<PlexSectionsContainer>>(response.Content)
|
return Json.Deserialize<PlexResponse<PlexSectionsContainer>>(response.Content)
|
||||||
.MediaContainer
|
.MediaContainer
|
||||||
.Sections
|
.Sections
|
||||||
.Where(d => d.Type == "show")
|
.Where(d => d.Type == "movie")
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
|||||||
{
|
{
|
||||||
if (version >= new Version(1, 3, 0) && version < new Version(1, 3, 1))
|
if (version >= new Version(1, 3, 0) && version < new Version(1, 3, 1))
|
||||||
{
|
{
|
||||||
throw new PlexVersionException("Found version {0}, upgrade to PMS 1.3.1 to fix library updating and then restart Sonarr", version);
|
throw new PlexVersionException("Found version {0}, upgrade to PMS 1.3.1 to fix library updating and then restart Radarr", version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ namespace NzbDrone.Core.Notifications.Prowl
|
|||||||
Verify(settings.ApiKey);
|
Verify(settings.ApiKey);
|
||||||
|
|
||||||
const string title = "Test Notification";
|
const string title = "Test Notification";
|
||||||
const string body = "This is a test message from Sonarr";
|
const string body = "This is a test message from Radarr";
|
||||||
|
|
||||||
SendNotification(title, body, settings.ApiKey);
|
SendNotification(title, body, settings.ApiKey);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
|||||||
|
|
||||||
public override void OnGrab(GrabMessage grabMessage)
|
public override void OnGrab(GrabMessage grabMessage)
|
||||||
{
|
{
|
||||||
const string title = "Sonarr - Episode Grabbed";
|
const string title = "Radarr - Episode Grabbed";
|
||||||
|
|
||||||
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
_proxy.SendNotification(title, grabMessage.Message, Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDownload(DownloadMessage message)
|
public override void OnDownload(DownloadMessage message)
|
||||||
{
|
{
|
||||||
const string title = "Sonarr - Episode Downloaded";
|
const string title = "Radarr - Episode Downloaded";
|
||||||
|
|
||||||
_proxy.SendNotification(title, message.Message, Settings);
|
_proxy.SendNotification(title, message.Message, Settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string title = "Sonarr - Test Notification";
|
const string title = "Radarr - Test Notification";
|
||||||
const string body = "This is a test message from Sonarr";
|
const string body = "This is a test message from Radarr";
|
||||||
|
|
||||||
SendNotification(title, body, settings);
|
SendNotification(title, body, settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ namespace NzbDrone.Core.Notifications.Pushalot
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string title = "Test Notification";
|
const string title = "Test Notification";
|
||||||
const string body = "This is a test message from Sonarr";
|
const string body = "This is a test message from Radarr";
|
||||||
|
|
||||||
SendNotification(title, body, settings);
|
SendNotification(title, body, settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Notifications.Pushalot
|
|||||||
[FieldDefinition(1, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(PushalotPriority))]
|
[FieldDefinition(1, Label = "Priority", Type = FieldType.Select, SelectOptions = typeof(PushalotPriority))]
|
||||||
public int Priority { get; set; }
|
public int Priority { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(2, Label = "Image", Type = FieldType.Checkbox, HelpText = "Include Sonarr logo with notifications")]
|
[FieldDefinition(2, Label = "Image", Type = FieldType.Checkbox, HelpText = "Include Radarr logo with notifications")]
|
||||||
public bool Image { get; set; }
|
public bool Image { get; set; }
|
||||||
|
|
||||||
public bool IsValid => !string.IsNullOrWhiteSpace(AuthToken);
|
public bool IsValid => !string.IsNullOrWhiteSpace(AuthToken);
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace NzbDrone.Core.Notifications.Pushover
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string title = "Test Notification";
|
const string title = "Test Notification";
|
||||||
const string body = "This is a test message from Sonarr";
|
const string body = "This is a test message from Radarr";
|
||||||
|
|
||||||
SendNotification(title, body, settings);
|
SendNotification(title, body, settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ namespace NzbDrone.Core.Notifications.Slack
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var message = $"Test message from Sonarr posted at {DateTime.Now}";
|
var message = $"Test message from Radarr posted at {DateTime.Now}";
|
||||||
var payload = new SlackPayload
|
var payload = new SlackPayload
|
||||||
{
|
{
|
||||||
IconEmoji = Settings.Icon,
|
IconEmoji = Settings.Icon,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Notifications.Telegram
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string title = "Test Notification";
|
const string title = "Test Notification";
|
||||||
const string body = "This is a test message from Sonarr";
|
const string body = "This is a test message from Radarr";
|
||||||
|
|
||||||
SendNotification(title, body, settings);
|
SendNotification(title, body, settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ namespace NzbDrone.Core.Notifications.Twitter
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var body = "Sonarr: Test Message @ " + DateTime.Now;
|
var body = "Radarr: Test Message @ " + DateTime.Now;
|
||||||
|
|
||||||
SendNotification(body, settings);
|
SendNotification(body, settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
|||||||
|
|
||||||
public override void OnGrab(GrabMessage grabMessage)
|
public override void OnGrab(GrabMessage grabMessage)
|
||||||
{
|
{
|
||||||
const string header = "Sonarr - Grabbed";
|
const string header = "Radarr - Grabbed";
|
||||||
|
|
||||||
Notify(Settings, header, grabMessage.Message);
|
Notify(Settings, header, grabMessage.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDownload(DownloadMessage message)
|
public override void OnDownload(DownloadMessage message)
|
||||||
{
|
{
|
||||||
const string header = "Sonarr - Downloaded";
|
const string header = "Radarr - Downloaded";
|
||||||
|
|
||||||
Notify(Settings, header, message.Message);
|
Notify(Settings, header, message.Message);
|
||||||
UpdateAndClean(message.Series, message.OldFiles.Any());
|
UpdateAndClean(message.Series, message.OldFiles.Any());
|
||||||
|
|||||||
@@ -183,8 +183,10 @@
|
|||||||
<Compile Include="Datastore\Migration\002_remove_tvrage_imdb_unique_constraint.cs" />
|
<Compile Include="Datastore\Migration\002_remove_tvrage_imdb_unique_constraint.cs" />
|
||||||
<Compile Include="Datastore\Migration\003_remove_clean_title_from_scene_mapping.cs" />
|
<Compile Include="Datastore\Migration\003_remove_clean_title_from_scene_mapping.cs" />
|
||||||
<Compile Include="Datastore\Migration\004_updated_history.cs" />
|
<Compile Include="Datastore\Migration\004_updated_history.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\115_update_movie_sorttitle.cs" />
|
||||||
<Compile Include="Datastore\Migration\111_remove_bitmetv.cs" />
|
<Compile Include="Datastore\Migration\111_remove_bitmetv.cs" />
|
||||||
<Compile Include="Datastore\Migration\112_remove_torrentleech.cs" />
|
<Compile Include="Datastore\Migration\112_remove_torrentleech.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\114_remove_fanzub.cs" />
|
||||||
<Compile Include="Datastore\Migration\113_remove_broadcasthenet.cs" />
|
<Compile Include="Datastore\Migration\113_remove_broadcasthenet.cs" />
|
||||||
<Compile Include="Datastore\Migration\108_update_schedule_interval.cs" />
|
<Compile Include="Datastore\Migration\108_update_schedule_interval.cs" />
|
||||||
<Compile Include="Datastore\Migration\107_fix_movie_files.cs" />
|
<Compile Include="Datastore\Migration\107_fix_movie_files.cs" />
|
||||||
@@ -582,9 +584,6 @@
|
|||||||
<Compile Include="Indexers\Exceptions\RequestLimitReachedException.cs" />
|
<Compile Include="Indexers\Exceptions\RequestLimitReachedException.cs" />
|
||||||
<Compile Include="Indexers\Exceptions\UnsupportedFeedException.cs" />
|
<Compile Include="Indexers\Exceptions\UnsupportedFeedException.cs" />
|
||||||
<Compile Include="Indexers\EzrssTorrentRssParser.cs" />
|
<Compile Include="Indexers\EzrssTorrentRssParser.cs" />
|
||||||
<Compile Include="Indexers\Fanzub\Fanzub.cs" />
|
|
||||||
<Compile Include="Indexers\Fanzub\FanzubRequestGenerator.cs" />
|
|
||||||
<Compile Include="Indexers\Fanzub\FanzubSettings.cs" />
|
|
||||||
<Compile Include="Indexers\FetchAndParseRssService.cs" />
|
<Compile Include="Indexers\FetchAndParseRssService.cs" />
|
||||||
<Compile Include="Indexers\PassThePopcorn\PassThePopcorn.cs" />
|
<Compile Include="Indexers\PassThePopcorn\PassThePopcorn.cs" />
|
||||||
<Compile Include="Indexers\PassThePopcorn\PassThePopcornApi.cs" />
|
<Compile Include="Indexers\PassThePopcorn\PassThePopcornApi.cs" />
|
||||||
@@ -707,10 +706,12 @@
|
|||||||
<Compile Include="MediaFiles\Commands\BackendCommandAttribute.cs" />
|
<Compile Include="MediaFiles\Commands\BackendCommandAttribute.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\CleanUpRecycleBinCommand.cs" />
|
<Compile Include="MediaFiles\Commands\CleanUpRecycleBinCommand.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\DownloadedEpisodesScanCommand.cs" />
|
<Compile Include="MediaFiles\Commands\DownloadedEpisodesScanCommand.cs" />
|
||||||
|
<Compile Include="MediaFiles\Commands\DownloadedMovieScanCommand.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\RenameMovieCommand.cs" />
|
<Compile Include="MediaFiles\Commands\RenameMovieCommand.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\RenameMovieFilesCommand.cs" />
|
<Compile Include="MediaFiles\Commands\RenameMovieFilesCommand.cs" />
|
||||||
<Compile Include="MediaFiles\Commands\RescanMovieCommand.cs" />
|
<Compile Include="MediaFiles\Commands\RescanMovieCommand.cs" />
|
||||||
<Compile Include="MediaFiles\DownloadedMovieCommandService.cs" />
|
<Compile Include="MediaFiles\DownloadedMovieCommandService.cs" />
|
||||||
|
<Compile Include="MediaFiles\DownloadedMovieImportService.cs" />
|
||||||
<Compile Include="MediaFiles\MovieFileMovingService.cs" />
|
<Compile Include="MediaFiles\MovieFileMovingService.cs" />
|
||||||
<Compile Include="MediaFiles\Events\MovieDownloadedEvent.cs" />
|
<Compile Include="MediaFiles\Events\MovieDownloadedEvent.cs" />
|
||||||
<Compile Include="MediaFiles\Events\MovieFileAddedEvent.cs" />
|
<Compile Include="MediaFiles\Events\MovieFileAddedEvent.cs" />
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ namespace NzbDrone.Core.Organizer
|
|||||||
{
|
{
|
||||||
var value = context.PropertyValue as string;
|
var value = context.PropertyValue as string;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
if (!FileNameBuilder.SeasonEpisodePatternRegex.IsMatch(value) &&
|
if (!FileNameBuilder.SeasonEpisodePatternRegex.IsMatch(value) &&
|
||||||
!FileNameValidation.OriginalTokenRegex.IsMatch(value))
|
!FileNameValidation.OriginalTokenRegex.IsMatch(value))
|
||||||
{
|
{
|
||||||
@@ -89,6 +91,8 @@ namespace NzbDrone.Core.Organizer
|
|||||||
{
|
{
|
||||||
var value = context.PropertyValue as string;
|
var value = context.PropertyValue as string;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
if (!FileNameBuilder.SeasonEpisodePatternRegex.IsMatch(value) &&
|
if (!FileNameBuilder.SeasonEpisodePatternRegex.IsMatch(value) &&
|
||||||
!FileNameBuilder.AirDateRegex.IsMatch(value) &&
|
!FileNameBuilder.AirDateRegex.IsMatch(value) &&
|
||||||
!FileNameValidation.OriginalTokenRegex.IsMatch(value))
|
!FileNameValidation.OriginalTokenRegex.IsMatch(value))
|
||||||
@@ -112,6 +116,8 @@ namespace NzbDrone.Core.Organizer
|
|||||||
{
|
{
|
||||||
var value = context.PropertyValue as string;
|
var value = context.PropertyValue as string;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
if (!FileNameBuilder.SeasonEpisodePatternRegex.IsMatch(value) &&
|
if (!FileNameBuilder.SeasonEpisodePatternRegex.IsMatch(value) &&
|
||||||
!FileNameBuilder.AbsoluteEpisodePatternRegex.IsMatch(value) &&
|
!FileNameBuilder.AbsoluteEpisodePatternRegex.IsMatch(value) &&
|
||||||
!FileNameValidation.OriginalTokenRegex.IsMatch(value))
|
!FileNameValidation.OriginalTokenRegex.IsMatch(value))
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace NzbDrone.Core.Parser.Model
|
|||||||
public DownloadProtocol DownloadProtocol { get; set; }
|
public DownloadProtocol DownloadProtocol { get; set; }
|
||||||
public int TvdbId { get; set; }
|
public int TvdbId { get; set; }
|
||||||
public int TvRageId { get; set; }
|
public int TvRageId { get; set; }
|
||||||
|
public int ImdbId { get; set; }
|
||||||
public DateTime PublishDate { get; set; }
|
public DateTime PublishDate { get; set; }
|
||||||
|
|
||||||
public string Origin { get; set; }
|
public string Origin { get; set; }
|
||||||
@@ -82,6 +83,7 @@ namespace NzbDrone.Core.Parser.Model
|
|||||||
stringBuilder.AppendLine("DownloadProtocol: " + DownloadProtocol ?? "Empty");
|
stringBuilder.AppendLine("DownloadProtocol: " + DownloadProtocol ?? "Empty");
|
||||||
stringBuilder.AppendLine("TvdbId: " + TvdbId ?? "Empty");
|
stringBuilder.AppendLine("TvdbId: " + TvdbId ?? "Empty");
|
||||||
stringBuilder.AppendLine("TvRageId: " + TvRageId ?? "Empty");
|
stringBuilder.AppendLine("TvRageId: " + TvRageId ?? "Empty");
|
||||||
|
stringBuilder.AppendLine("ImdbId: " + ImdbId ?? "Empty");
|
||||||
stringBuilder.AppendLine("PublishDate: " + PublishDate ?? "Empty");
|
stringBuilder.AppendLine("PublishDate: " + PublishDate ?? "Empty");
|
||||||
return stringBuilder.ToString();
|
return stringBuilder.ToString();
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -18,16 +18,10 @@ namespace NzbDrone.Core.Parser
|
|||||||
private static readonly Regex[] ReportMovieTitleRegex = new[]
|
private static readonly Regex[] ReportMovieTitleRegex = new[]
|
||||||
{
|
{
|
||||||
//Special, Despecialized, etc. Edition Movies, e.g: Mission.Impossible.3.Special.Edition.2011
|
//Special, Despecialized, etc. Edition Movies, e.g: Mission.Impossible.3.Special.Edition.2011
|
||||||
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)\[!]))*(?<edition>(\w+\.?edition))\.(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)\[!]))*(?<edition>(\.?((Extended.|Ultimate.)?(Director.?s|Collector.?s|Theatrical|Ultimate|Final|Extended|Rogue|Special|Despecialized).(Cut|Edition|Version)|Extended|Uncensored|Remastered|Unrated|Uncut|IMAX)))\.(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
//Special, Despecialized, etc. Edition Movies, e.g: Mission.Impossible.3.2011.Special.Edition //TODO: Seems to slow down parsing heavily!
|
//Special, Despecialized, etc. Edition Movies, e.g: Mission.Impossible.3.2011.Special.Edition //TODO: Seems to slow down parsing heavily!
|
||||||
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)\[!]))*(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)(?<edition>((\w+\.?){1,3}edition))",
|
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)\[!]))*(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)(?<edition>((Extended.|Ultimate.)?(Director.?s|Collector.?s|Theatrical|Ultimate|Final|Extended|Rogue|Special|Despecialized).(Cut|Edition|Version)|Extended|Uncensored|Remastered|Unrated|Uncut|IMAX))",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
||||||
//Cut Movies, e.g: Mission.Impossible.3.Directors.Cut.2011
|
|
||||||
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)\[!]))*(?<edition>(\w+\.?cut))\.(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
||||||
//Cut Movies, e.g: Mission.Impossible.3.2011.Directors.Cut
|
|
||||||
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)\[!]))*(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)(?<edition>((\w+\.?){1,3}cut))",
|
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
//Normal movie format, e.g: Mission.Impossible.3.2011
|
//Normal movie format, e.g: Mission.Impossible.3.2011
|
||||||
@@ -36,6 +30,15 @@ namespace NzbDrone.Core.Parser
|
|||||||
//PassThePopcorn Torrent names: Star.Wars[PassThePopcorn]
|
//PassThePopcorn Torrent names: Star.Wars[PassThePopcorn]
|
||||||
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![()\[!]))*(?<year>(\[\w *\])))+(\W+|_|$)(?!\\)",
|
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![()\[!]))*(?<year>(\[\w *\])))+(\W+|_|$)(?!\\)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
//That did not work? Maybe some tool uses [] for years. Who would do that?
|
||||||
|
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)!]))*(?<year>(19|20)\d{2}(?!p|i|\d+|\W\d+)))+(\W+|_|$)(?!\\)",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly Regex[] ReportMovieTitleFolderRegex = new[]
|
||||||
|
{
|
||||||
|
//When year comes first.
|
||||||
|
new Regex(@"^(?:(?:[-_\W](?<![)!]))*(?<year>(19|20)\d{2}(?!p|i|\d+|\W\d+)))+(\W+|_|$)(?<title>.+?)?$")
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Regex[] ReportTitleRegex = new[]
|
private static readonly Regex[] ReportTitleRegex = new[]
|
||||||
@@ -327,7 +330,7 @@ namespace NzbDrone.Core.Parser
|
|||||||
{
|
{
|
||||||
var fileInfo = new FileInfo(path);
|
var fileInfo = new FileInfo(path);
|
||||||
|
|
||||||
var result = ParseMovieTitle(fileInfo.Name);
|
var result = ParseMovieTitle(fileInfo.Name, true);
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
@@ -345,7 +348,7 @@ namespace NzbDrone.Core.Parser
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ParsedMovieInfo ParseMovieTitle(string title)
|
public static ParsedMovieInfo ParseMovieTitle(string title, bool isDir = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
ParsedMovieInfo realResult = null;
|
ParsedMovieInfo realResult = null;
|
||||||
@@ -376,7 +379,14 @@ namespace NzbDrone.Core.Parser
|
|||||||
|
|
||||||
simpleTitle = CleanTorrentSuffixRegex.Replace(simpleTitle, string.Empty);
|
simpleTitle = CleanTorrentSuffixRegex.Replace(simpleTitle, string.Empty);
|
||||||
|
|
||||||
foreach (var regex in ReportMovieTitleRegex)
|
var allRegexes = ReportMovieTitleRegex.ToList();
|
||||||
|
|
||||||
|
if (isDir)
|
||||||
|
{
|
||||||
|
allRegexes.AddRange(ReportMovieTitleFolderRegex);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var regex in allRegexes)
|
||||||
{
|
{
|
||||||
var match = regex.Matches(simpleTitle);
|
var match = regex.Matches(simpleTitle);
|
||||||
|
|
||||||
|
|||||||
@@ -192,6 +192,11 @@ namespace NzbDrone.Core.Parser
|
|||||||
parsedEpisodeInfo.MovieTitleInfo.Year);
|
parsedEpisodeInfo.MovieTitleInfo.Year);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (series == null)
|
||||||
|
{
|
||||||
|
series = _movieService.FindByTitle(parsedEpisodeInfo.MovieTitle.Replace("DC", "").Trim());
|
||||||
|
}
|
||||||
|
|
||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,11 @@ namespace NzbDrone.Core.RootFolders
|
|||||||
foreach (string unmappedFolder in unmappedFolders)
|
foreach (string unmappedFolder in unmappedFolders)
|
||||||
{
|
{
|
||||||
var di = new DirectoryInfo(unmappedFolder.Normalize());
|
var di = new DirectoryInfo(unmappedFolder.Normalize());
|
||||||
results.Add(new UnmappedFolder { Name = di.Name, Path = di.FullName });
|
if (!di.Attributes.HasFlag(FileAttributes.System) && !di.Attributes.HasFlag(FileAttributes.Hidden))
|
||||||
|
{
|
||||||
|
results.Add(new UnmappedFolder { Name = di.Name, Path = di.FullName });
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var setToRemove = SpecialFolders;
|
var setToRemove = SpecialFolders;
|
||||||
|
|||||||
@@ -63,11 +63,11 @@ namespace NzbDrone.Core.Tv
|
|||||||
cleanNum = cleanNum.Replace(roman, num);
|
cleanNum = cleanNum.Replace(roman, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = Query.Where(s => s.CleanTitle == cleanTitle).SingleOrDefault();
|
var result = Query.Where(s => s.CleanTitle == cleanTitle).FirstOrDefault();
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
result = Query.Where(s => s.CleanTitle == cleanNum).OrWhere(s => s.CleanTitle == cleanRoman).SingleOrDefault();
|
result = Query.Where(s => s.CleanTitle == cleanNum).OrWhere(s => s.CleanTitle == cleanRoman).FirstOrDefault();
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
@@ -75,7 +75,7 @@ namespace NzbDrone.Core.Tv
|
|||||||
|
|
||||||
result = movies.Where(m => m.AlternativeTitles.Any(t => Parser.Parser.CleanSeriesTitle(t.ToLower()) == cleanTitle ||
|
result = movies.Where(m => m.AlternativeTitles.Any(t => Parser.Parser.CleanSeriesTitle(t.ToLower()) == cleanTitle ||
|
||||||
Parser.Parser.CleanSeriesTitle(t.ToLower()) == cleanRoman ||
|
Parser.Parser.CleanSeriesTitle(t.ToLower()) == cleanRoman ||
|
||||||
Parser.Parser.CleanSeriesTitle(t.ToLower()) == cleanNum)).SingleOrDefault();
|
Parser.Parser.CleanSeriesTitle(t.ToLower()) == cleanNum)).FirstOrDefault();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Radarr.Host
|
|||||||
SecurityProtocolPolicy.Register();
|
SecurityProtocolPolicy.Register();
|
||||||
X509CertificateValidationPolicy.Register();
|
X509CertificateValidationPolicy.Register();
|
||||||
|
|
||||||
Logger.Info("Starting Sonarr - {0} - Version {1}", Assembly.GetCallingAssembly().Location, Assembly.GetExecutingAssembly().GetName().Version);
|
Logger.Info("Starting Radarr - {0} - Version {1}", Assembly.GetCallingAssembly().Location, Assembly.GetExecutingAssembly().GetName().Version);
|
||||||
|
|
||||||
if (!PlatformValidation.IsValidate(userAlert))
|
if (!PlatformValidation.IsValidate(userAlert))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
{{/if_eq}}
|
{{/if_eq}}
|
||||||
|
|
||||||
{{#if_eq reason compare="MissingFromDisk"}}
|
{{#if_eq reason compare="MissingFromDisk"}}
|
||||||
Sonarr was unable to find the file on disk so it was removed
|
Radarr was unable to find the file on disk so it was removed
|
||||||
{{/if_eq}}
|
{{/if_eq}}
|
||||||
|
|
||||||
{{#if_eq reason compare="Upgrade"}}
|
{{#if_eq reason compare="Upgrade"}}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ var Marionette = require('marionette');
|
|||||||
var Backgrid = require('backgrid');
|
var Backgrid = require('backgrid');
|
||||||
var HistoryCollection = require('./HistoryCollection');
|
var HistoryCollection = require('./HistoryCollection');
|
||||||
var EventTypeCell = require('../../Cells/EventTypeCell');
|
var EventTypeCell = require('../../Cells/EventTypeCell');
|
||||||
var MovieTitleCell = require('../../Cells/MovieTitleCell');
|
var MovieTitleCell = require('../../Cells/MovieTitleHistoryCell');
|
||||||
var EpisodeNumberCell = require('../../Cells/EpisodeNumberCell');
|
var EpisodeNumberCell = require('../../Cells/EpisodeNumberCell');
|
||||||
var EpisodeTitleCell = require('../../Cells/EpisodeTitleCell');
|
var EpisodeTitleCell = require('../../Cells/EpisodeTitleCell');
|
||||||
var HistoryQualityCell = require('./HistoryQualityCell');
|
var HistoryQualityCell = require('./HistoryQualityCell');
|
||||||
@@ -31,7 +31,7 @@ module.exports = Marionette.Layout.extend({
|
|||||||
{
|
{
|
||||||
name : 'movies',
|
name : 'movies',
|
||||||
label : 'Movie Title',
|
label : 'Movie Title',
|
||||||
cell : MovieTitleCell
|
cell : MovieTitleCell,
|
||||||
},
|
},
|
||||||
/*{
|
/*{
|
||||||
name : 'episode',
|
name : 'episode',
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ var view = Marionette.ItemView.extend({
|
|||||||
var defaultProfile = Config.getValue(Config.Keys.DefaultProfileId);
|
var defaultProfile = Config.getValue(Config.Keys.DefaultProfileId);
|
||||||
var defaultRoot = Config.getValue(Config.Keys.DefaultRootFolderId);
|
var defaultRoot = Config.getValue(Config.Keys.DefaultRootFolderId);
|
||||||
var useSeasonFolder = Config.getValueBoolean(Config.Keys.UseSeasonFolder, true);
|
var useSeasonFolder = Config.getValueBoolean(Config.Keys.UseSeasonFolder, true);
|
||||||
var defaultMonitorEpisodes = Config.getValue(Config.Keys.MonitorEpisodes, 'missing');
|
var defaultMonitorEpisodes = Config.getValue(Config.Keys.MonitorEpisodes, 'all');
|
||||||
|
|
||||||
if (Profiles.get(defaultProfile)) {
|
if (Profiles.get(defaultProfile)) {
|
||||||
this.ui.profile.val(defaultProfile);
|
this.ui.profile.val(defaultProfile);
|
||||||
@@ -169,6 +169,7 @@ var view = Marionette.ItemView.extend({
|
|||||||
|
|
||||||
var profile = this.ui.profile.val();
|
var profile = this.ui.profile.val();
|
||||||
var rootFolderPath = this.ui.rootFolder.children(':selected').text();
|
var rootFolderPath = this.ui.rootFolder.children(':selected').text();
|
||||||
|
var monitor = this.ui.monitor.val();
|
||||||
|
|
||||||
var options = this._getAddMoviesOptions();
|
var options = this._getAddMoviesOptions();
|
||||||
options.searchForMovie = searchForMovie;
|
options.searchForMovie = searchForMovie;
|
||||||
@@ -178,7 +179,7 @@ var view = Marionette.ItemView.extend({
|
|||||||
profileId : profile,
|
profileId : profile,
|
||||||
rootFolderPath : rootFolderPath,
|
rootFolderPath : rootFolderPath,
|
||||||
addOptions : options,
|
addOptions : options,
|
||||||
monitored : true
|
monitored : (monitor === 'all' ? true : false)
|
||||||
}, { silent : true });
|
}, { silent : true });
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
@@ -229,44 +230,10 @@ var view = Marionette.ItemView.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_getAddMoviesOptions : function() {
|
_getAddMoviesOptions : function() {
|
||||||
var monitor = this.ui.monitor.val();
|
return {
|
||||||
|
|
||||||
var options = {
|
|
||||||
ignoreEpisodesWithFiles : false,
|
ignoreEpisodesWithFiles : false,
|
||||||
ignoreEpisodesWithoutFiles : false
|
ignoreEpisodesWithoutFiles : false
|
||||||
};
|
};
|
||||||
|
|
||||||
if (monitor === 'all') {
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (monitor === 'future') {
|
|
||||||
options.ignoreEpisodesWithFiles = true;
|
|
||||||
options.ignoreEpisodesWithoutFiles = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// else if (monitor === 'latest') {
|
|
||||||
// this.model.setSeasonPass(lastSeason.seasonNumber);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// else if (monitor === 'first') {
|
|
||||||
// this.model.setSeasonPass(lastSeason.seasonNumber + 1);
|
|
||||||
// this.model.setSeasonMonitored(firstSeason.seasonNumber);
|
|
||||||
// }
|
|
||||||
|
|
||||||
else if (monitor === 'missing') {
|
|
||||||
options.ignoreEpisodesWithFiles = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (monitor === 'existing') {
|
|
||||||
options.ignoreEpisodesWithoutFiles = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// else if (monitor === 'none') {
|
|
||||||
// this.model.setSeasonPass(lastSeason.seasonNumber + 1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="search-item {{#unless isExisting}}search-item-new{{/unless}}">
|
<div class="search-item {{#unless isExisting}}search-item-new{{/unless}}">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<a href="{{imdbUrl}}" target="_blank">
|
<a href="{{tmdbUrl}}" target="_blank">
|
||||||
{{#if remotePoster}}
|
{{#if remotePoster}}
|
||||||
{{remotePoster}}
|
{{remotePoster}}
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -41,9 +41,9 @@
|
|||||||
<div class="form-group col-md-2">
|
<div class="form-group col-md-2">
|
||||||
<label>Monitor <i class="icon-sonarr-form-info monitor-tooltip x-monitor-tooltip"></i></label>
|
<label>Monitor <i class="icon-sonarr-form-info monitor-tooltip x-monitor-tooltip"></i></label>
|
||||||
<select class="form-control col-md-2 x-monitor">
|
<select class="form-control col-md-2 x-monitor">
|
||||||
<option value="all">All</option>
|
<option value="all">Yes</option>
|
||||||
<option value="missing">Missing</option>
|
<!-- <option value="missing">Missing</option> -->
|
||||||
<option value="none">None</option>
|
<option value="none">No</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h3>Sonarr Calendar feed</h3>
|
<h3>Radarr Calendar feed</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body edit-series-modal">
|
<div class="modal-body edit-series-modal">
|
||||||
<div class="form-horizontal">
|
<div class="form-horizontal">
|
||||||
|
|||||||
34
src/UI/Cells/DownloadedQualityCell.js
Normal file
34
src/UI/Cells/DownloadedQualityCell.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
var Backgrid = require('backgrid');
|
||||||
|
var ProfileCollection = require('../Profile/ProfileCollection');
|
||||||
|
var _ = require('underscore');
|
||||||
|
|
||||||
|
module.exports = Backgrid.Cell.extend({
|
||||||
|
className : 'profile-cell',
|
||||||
|
|
||||||
|
_originalInit : Backgrid.Cell.prototype.initialize,
|
||||||
|
|
||||||
|
initialize : function () {
|
||||||
|
this._originalInit.apply(this, arguments);
|
||||||
|
|
||||||
|
this.listenTo(ProfileCollection, 'sync', this.render);
|
||||||
|
},
|
||||||
|
|
||||||
|
render : function() {
|
||||||
|
|
||||||
|
this.$el.empty();
|
||||||
|
if (this.model.get("movieFile")) {
|
||||||
|
var profileId = this.model.get("movieFile").quality.quality.id;
|
||||||
|
|
||||||
|
var profile = _.findWhere(ProfileCollection.models, { id : profileId });
|
||||||
|
|
||||||
|
if (profile) {
|
||||||
|
this.$el.html(profile.get('name'));
|
||||||
|
} else {
|
||||||
|
this.$el.html(this.model.get("movieFile").quality.quality.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -7,10 +7,16 @@ module.exports = TemplatedCell.extend({
|
|||||||
var monthNames = ["January", "February", "March", "April", "May", "June",
|
var monthNames = ["January", "February", "March", "April", "May", "June",
|
||||||
"July", "August", "September", "October", "November", "December"
|
"July", "August", "September", "October", "November", "December"
|
||||||
];
|
];
|
||||||
var cinemasDate = new Date(this.model.get("inCinemas"));
|
|
||||||
var year = cinemasDate.getFullYear();
|
this.$el.html("");
|
||||||
var month = monthNames[cinemasDate.getMonth()];
|
|
||||||
this.$el.html(month + " " + year); //Hack, but somehow handlebar helper does not work.
|
if (this.model.get("inCinemas")) {
|
||||||
return this;
|
var cinemasDate = new Date(this.model.get("inCinemas"));
|
||||||
|
var year = cinemasDate.getFullYear();
|
||||||
|
var month = monthNames[cinemasDate.getMonth()];
|
||||||
|
this.$el.html(month + " " + year); //Hack, but somehow handlebar helper does not work.
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ module.exports = NzbDroneCell.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_editSeries : function() {
|
_editSeries : function() {
|
||||||
vent.trigger(vent.Commands.EditSeriesCommand, { series : this.model });
|
vent.trigger(vent.Commands.EditMovieCommand, { movie : this.model });
|
||||||
},
|
},
|
||||||
|
|
||||||
_refreshSeries : function() {
|
_refreshSeries : function() {
|
||||||
|
|||||||
@@ -3,4 +3,8 @@ var TemplatedCell = require('./TemplatedCell');
|
|||||||
module.exports = TemplatedCell.extend({
|
module.exports = TemplatedCell.extend({
|
||||||
className : 'movie-title-cell',
|
className : 'movie-title-cell',
|
||||||
template : 'Cells/MovieDownloadStatusTemplate',
|
template : 'Cells/MovieDownloadStatusTemplate',
|
||||||
|
sortKey : function(model) {
|
||||||
|
debugger;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<span class="label label-{{DownloadedStatusColor}}">{{DownloadedStatus}}</span>
|
<span class="label label-{{DownloadedStatusColor}}" title="{{DownloadedQuality}}">{{DownloadedStatus}}</span>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user