mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-11 03:52:33 +02:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
54e57bf16a
@ -82,7 +82,7 @@ ignore_regexps = [
|
||||
## whenever you are tweaking this variable.
|
||||
##
|
||||
section_regexps = [
|
||||
('**New Features**', [
|
||||
('**New features**', [
|
||||
r'^[aA]dded?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
|
||||
r'^[uU]pdated?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
|
||||
r'^[cC]hanged?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -150,3 +150,6 @@ Thumbs.db
|
||||
# AppVeyor
|
||||
/tools-cake/
|
||||
/_artifacts/
|
||||
|
||||
# Cake
|
||||
/tools/Addins/*
|
7566
CHANGELOG.md
7566
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
14
README.md
14
README.md
@ -50,6 +50,13 @@ The project was inspired by other Usenet/BitTorrent movie downloaders such as Co
|
||||
| AppVeyor | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr/master.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr) | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr-usby1/develop.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
|
||||
| Travis | [![Travis](https://img.shields.io/travis/Radarr/Radarr/master.svg?maxAge=60&style=flat-square)](https://travis-ci.org/Radarr/Radarr) | [![Travis](https://img.shields.io/travis/Radarr/Radarr/develop.svg?maxAge=60&style=flat-square)](https://travis-ci.org/Radarr/Radarr) |
|
||||
|
||||
### [Site and API Status](https://status.radarr.video)
|
||||
|
||||
| API | Updates | Sites |
|
||||
|-------|:----:|:----:|
|
||||
| [![API V2](http://status.radarr.video/component/1/shield?style=flat-square)](https://api.radarr.video/v2/) | [![Update Server](http://status.radarr.video/component/4/shield?style=flat-square)](https://radarr.aeonlucid.com) | [![Radarr Mappings](http://status.radarr.video/component/6/shield?style=flat-square)](https://mappings.radarr.video/)
|
||||
| [![API Staging](http://status.radarr.video/component/2/shield?style=flat-square)](https://staging.api.radarr.video/) | [![Github Updates](http://status.radarr.video/component/5/shield?style=flat-square)](https://api.github.com/v3/) | [![Main Site](http://status.radarr.video/component/7/shield?style=flat-square)](https://radarr.video/)
|
||||
|
||||
Radarr is currently undergoing rapid development and pull requests are actively added into the repository.
|
||||
|
||||
## Features
|
||||
@ -108,10 +115,17 @@ Radarr is currently undergoing rapid development and pull requests are actively
|
||||
> **Notice**
|
||||
> Gulp must be running at all times while you are working with Radarr client source files.
|
||||
|
||||
### Build
|
||||
|
||||
* To build run `sh build.sh`
|
||||
|
||||
**Note:** Windows users must have bash available to do this. [cmder](http://cmder.net/) which is a console emulator for windows has bash as part of it's default installation.
|
||||
|
||||
### Development
|
||||
|
||||
* Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed
|
||||
* Make sure `NzbDrone.Console` is set as the startup project
|
||||
* Run `build.sh` before running
|
||||
|
||||
### License
|
||||
|
||||
|
@ -32,7 +32,7 @@ artifacts:
|
||||
|
||||
cache:
|
||||
- '%USERPROFILE%\.nuget\packages'
|
||||
- node_modules
|
||||
- node_modules -> package.json
|
||||
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
|
@ -5,11 +5,10 @@
|
||||
|
||||
{{#sections}}
|
||||
### {{{label}}}
|
||||
|
||||
{{#commits}}
|
||||
- {{{subject}}} [{{{author}}}]
|
||||
|
||||
{{/commits}}
|
||||
|
||||
{{/sections}}
|
||||
|
||||
{{/versions}}
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,9 +1,10 @@
|
||||
using Nancy;
|
||||
using Nancy;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ical.Net;
|
||||
using Ical.Net.DataTypes;
|
||||
using Ical.Net.General;
|
||||
using Ical.Net.Interfaces.Serialization;
|
||||
using Ical.Net.Serialization;
|
||||
using Ical.Net.Serialization.iCalendar.Factory;
|
||||
@ -86,6 +87,10 @@ private Response GetCalendarFeed()
|
||||
ProductId = "-//radarr.video//Radarr//EN"
|
||||
};
|
||||
|
||||
var calendarName = "Radarr Movies Calendar";
|
||||
calendar.AddProperty(new CalendarProperty("NAME", calendarName));
|
||||
calendar.AddProperty(new CalendarProperty("X-WR-CALNAME", calendarName));
|
||||
|
||||
foreach (var movie in movies.OrderBy(v => v.Added))
|
||||
{
|
||||
if (tags.Any() && tags.None(movie.Tags.Contains))
|
||||
@ -114,8 +119,10 @@ private Response GetCalendarFeed()
|
||||
occurrence.End = new CalDateTime(movie.InCinemas.Value.AddMinutes(movie.Runtime)) { HasTime = true };
|
||||
}
|
||||
break;
|
||||
|
||||
case MovieStatusType.Announced:
|
||||
continue; // no date
|
||||
|
||||
default:
|
||||
if (movie.PhysicalRelease != null)
|
||||
{
|
||||
|
@ -41,6 +41,16 @@ public static List<Field> ToSchema(object model)
|
||||
};
|
||||
|
||||
var value = propertyInfo.GetValue(model, null);
|
||||
|
||||
if (propertyInfo.PropertyType.HasAttribute<FlagsAttribute>())
|
||||
{
|
||||
int intVal = (int)value;
|
||||
value = Enum.GetValues(propertyInfo.PropertyType)
|
||||
.Cast<int>()
|
||||
.Where(f=> (f & intVal) == f)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
field.Value = value;
|
||||
@ -131,6 +141,12 @@ public static object ReadFromSchema(List<Field> fields, Type targetType)
|
||||
|
||||
propertyInfo.SetValue(target, value, null);
|
||||
}
|
||||
|
||||
else if (propertyInfo.PropertyType.HasAttribute<FlagsAttribute>())
|
||||
{
|
||||
int value = field.Value.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToInt32(s)).Sum();
|
||||
propertyInfo.SetValue(target, value, null);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
@ -23,6 +23,8 @@ public void Register(IPipelines pipelines)
|
||||
|
||||
private void Handle(NancyContext context)
|
||||
{
|
||||
if (context.Request.Method == "OPTIONS") return;
|
||||
|
||||
if (_cacheableSpecification.IsCacheable(context))
|
||||
{
|
||||
context.Response.Headers.EnableCache();
|
||||
@ -33,4 +35,4 @@ private void Handle(NancyContext context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using Nancy.Bootstrapper;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Api.Extensions.Pipelines
|
||||
{
|
||||
@ -11,10 +12,25 @@ public class CorsPipeline : IRegisterNancyPipeline
|
||||
|
||||
public void Register(IPipelines pipelines)
|
||||
{
|
||||
pipelines.AfterRequest.AddItemToEndOfPipeline((Action<NancyContext>) Handle);
|
||||
pipelines.BeforeRequest.AddItemToEndOfPipeline(HandleRequest);
|
||||
pipelines.AfterRequest.AddItemToEndOfPipeline(HandleResponse);
|
||||
}
|
||||
|
||||
private void Handle(NancyContext context)
|
||||
private Response HandleRequest(NancyContext context)
|
||||
{
|
||||
if (context == null || context.Request.Method != "OPTIONS")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var response = new Response()
|
||||
.WithStatusCode(HttpStatusCode.OK)
|
||||
.WithContentType("");
|
||||
ApplyResponseHeaders(response, context.Request);
|
||||
return response;
|
||||
}
|
||||
|
||||
private void HandleResponse(NancyContext context)
|
||||
{
|
||||
if (context == null || context.Response.Headers.ContainsKey(AccessControlHeaders.AllowOrigin))
|
||||
{
|
||||
@ -26,21 +42,39 @@ private void Handle(NancyContext context)
|
||||
|
||||
private static void ApplyResponseHeaders(Response response, Request request)
|
||||
{
|
||||
var allowedMethods = "GET, OPTIONS, PATCH, POST, PUT, DELETE";
|
||||
|
||||
if (response.Headers.ContainsKey("Allow"))
|
||||
if (request.IsApiRequest())
|
||||
{
|
||||
allowedMethods = response.Headers["Allow"];
|
||||
// Allow Cross-Origin access to the API since it's protected with the apikey, and nothing else.
|
||||
ApplyCorsResponseHeaders(response, request, "*", "GET, OPTIONS, PATCH, POST, PUT, DELETE");
|
||||
}
|
||||
|
||||
var requestedHeaders = string.Join(", ", request.Headers[AccessControlHeaders.RequestHeaders]);
|
||||
|
||||
response.Headers.Add(AccessControlHeaders.AllowOrigin, "*");
|
||||
response.Headers.Add(AccessControlHeaders.AllowMethods, allowedMethods);
|
||||
|
||||
if (request.Headers[AccessControlHeaders.RequestHeaders].Any())
|
||||
else if (request.IsSharedContentRequest())
|
||||
{
|
||||
response.Headers.Add(AccessControlHeaders.AllowHeaders, requestedHeaders);
|
||||
// Allow Cross-Origin access to specific shared content such as mediacovers and images.
|
||||
ApplyCorsResponseHeaders(response, request, "*", "GET, OPTIONS");
|
||||
}
|
||||
|
||||
// Disallow Cross-Origin access for any other route.
|
||||
}
|
||||
|
||||
private static void ApplyCorsResponseHeaders(Response response, Request request, string allowOrigin, string allowedMethods)
|
||||
{
|
||||
response.Headers.Add(AccessControlHeaders.AllowOrigin, allowOrigin);
|
||||
|
||||
if (request.Method == "OPTIONS")
|
||||
{
|
||||
if (response.Headers.ContainsKey("Allow"))
|
||||
{
|
||||
allowedMethods = response.Headers["Allow"];
|
||||
}
|
||||
|
||||
response.Headers.Add(AccessControlHeaders.AllowMethods, allowedMethods);
|
||||
|
||||
if (request.Headers[AccessControlHeaders.RequestHeaders].Any())
|
||||
{
|
||||
var requestedHeaders = string.Join(", ", request.Headers[AccessControlHeaders.RequestHeaders]);
|
||||
|
||||
response.Headers.Add(AccessControlHeaders.AllowHeaders, requestedHeaders);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,8 @@ private void CompressResponse(NancyContext context)
|
||||
try
|
||||
{
|
||||
if (
|
||||
!response.ContentType.Contains("image")
|
||||
response.Contents != Response.NoBody
|
||||
&& !response.ContentType.Contains("image")
|
||||
&& !response.ContentType.Contains("font")
|
||||
&& request.Headers.AcceptEncoding.Any(x => x.Contains("gzip"))
|
||||
&& !AlreadyGzipEncoded(response)
|
||||
@ -80,4 +81,4 @@ private static bool AlreadyGzipEncoded(Response response)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,5 +36,11 @@ public static bool IsContentRequest(this Request request)
|
||||
{
|
||||
return request.Path.StartsWith("/Content/", StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool IsSharedContentRequest(this Request request)
|
||||
{
|
||||
return request.Path.StartsWith("/MediaCover/", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
request.Path.StartsWith("/Content/Images/", StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,12 @@ public override string Map(string resourceUrl)
|
||||
|
||||
public override bool CanHandle(string resourceUrl)
|
||||
{
|
||||
return !resourceUrl.Contains(".") && !resourceUrl.StartsWith("/login");
|
||||
resourceUrl = resourceUrl.ToLowerInvariant();
|
||||
|
||||
return !resourceUrl.StartsWith("/content") &&
|
||||
!resourceUrl.StartsWith("/mediacover") &&
|
||||
!resourceUrl.Contains(".") &&
|
||||
!resourceUrl.StartsWith("/login");
|
||||
}
|
||||
|
||||
public override Response GetResponse(string resourceUrl)
|
||||
@ -113,4 +118,4 @@ private string GetIndexText()
|
||||
return _generatedContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
@ -42,7 +43,7 @@ public override string Map(string resourceUrl)
|
||||
|
||||
public override bool CanHandle(string resourceUrl)
|
||||
{
|
||||
return resourceUrl.StartsWith("/MediaCover");
|
||||
return resourceUrl.StartsWith("/MediaCover", StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
@ -28,7 +29,9 @@ public override string Map(string resourceUrl)
|
||||
|
||||
public override bool CanHandle(string resourceUrl)
|
||||
{
|
||||
return resourceUrl.StartsWith("/Content") ||
|
||||
resourceUrl = resourceUrl.ToLowerInvariant();
|
||||
|
||||
return resourceUrl.StartsWith("/content") ||
|
||||
resourceUrl.EndsWith(".js") ||
|
||||
resourceUrl.EndsWith(".map") ||
|
||||
resourceUrl.EndsWith(".css") ||
|
||||
@ -37,4 +40,4 @@ public override bool CanHandle(string resourceUrl)
|
||||
resourceUrl.EndsWith("oauth.html");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy.Responses;
|
||||
using NLog;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Frontend.Mappers;
|
||||
|
@ -34,7 +34,6 @@ protected override void ApplicationStartup(TinyIoCContainer container, IPipeline
|
||||
RegisterPipelines(pipelines);
|
||||
|
||||
container.Resolve<DatabaseTarget>().Register();
|
||||
container.Resolve<IEventAggregator>().PublishEvent(new ApplicationStartedEvent());
|
||||
}
|
||||
|
||||
private void RegisterPipelines(IPipelines pipelines)
|
||||
@ -56,4 +55,4 @@ protected override TinyIoCContainer GetApplicationContainer()
|
||||
|
||||
protected override byte[] FavIcon => null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ public static MovieFileResource ToResource(this MovieFile model)
|
||||
Path = model.Path,
|
||||
Size = model.Size,
|
||||
DateAdded = model.DateAdded,
|
||||
SceneName = model.SceneName,
|
||||
ReleaseGroup = model.ReleaseGroup,
|
||||
Quality = model.Quality,
|
||||
Movie = movie,
|
||||
|
@ -15,6 +15,7 @@ public class CleanseLogMessageFixture
|
||||
[TestCase(@"https://rss.omgwtfnzbs.org/rss-search.php?catid=19,20&user=sonarr&api=mySecret&eng=1")]
|
||||
[TestCase(@"https://dognzb.cr/fetch/2b51db35e1912ffc138825a12b9933d2/2b51db35e1910123321025a12b9933d2")]
|
||||
[TestCase(@"https://baconbits.org/feeds.php?feed=torrents_tv&user=12345&auth=2b51db35e1910123321025a12b9933d2&passkey=mySecret&authkey=2b51db35e1910123321025a12b9933d2")]
|
||||
[TestCase(@"http://127.0.0.1:9117/dl/indexername?jackett_apikey=flwjiefewklfjacketmySecretsdfldskjfsdlk&path=we0re9f0sdfbase64sfdkfjsdlfjk&file=The+Torrent+File+Name.torrent")]
|
||||
// NzbGet
|
||||
[TestCase(@"{ ""Name"" : ""ControlUsername"", ""Value"" : ""mySecret"" }, { ""Name"" : ""ControlPassword"", ""Value"" : ""mySecret"" }, ")]
|
||||
[TestCase(@"{ ""Name"" : ""Server1.Username"", ""Value"" : ""mySecret"" }, { ""Name"" : ""Server1.Password"", ""Value"" : ""mySecret"" }, ")]
|
||||
|
@ -6,10 +6,10 @@ namespace NzbDrone.Common.Instrumentation
|
||||
{
|
||||
public class CleanseLogMessage
|
||||
{
|
||||
private static readonly Regex[] CleansingRules = new[]
|
||||
private static readonly Regex[] CleansingRules = new[]
|
||||
{
|
||||
// Url
|
||||
new Regex(@"(?<=\?|&)(apikey|token|passkey|auth|authkey|user|uid|api)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"(?<=\?|&)(apikey|token|passkey|auth|authkey|user|uid|api|[a-z_]*apikey)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"(?<=\?|&)[^=]*?(username|password)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"torrentleech\.org/(?!rss)(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
new Regex(@"torrentleech\.org/rss/download/[0-9]+/(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
@ -11,6 +11,13 @@ public static class ConsoleApp
|
||||
{
|
||||
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(ConsoleApp));
|
||||
|
||||
private enum ExitCodes : int
|
||||
{
|
||||
Normal = 0,
|
||||
UnknownFailure = 1,
|
||||
RecoverableFailure = 2
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
@ -19,30 +26,41 @@ public static void Main(string[] args)
|
||||
NzbDroneLogger.Register(startupArgs, false, true);
|
||||
Bootstrap.Start(startupArgs, new ConsoleAlerts());
|
||||
}
|
||||
catch (SocketException exception)
|
||||
catch (SocketException e)
|
||||
{
|
||||
System.Console.WriteLine("");
|
||||
System.Console.WriteLine("");
|
||||
Logger.Fatal(exception.Message + ". This can happen if another instance of Radarr is already running another application is using the same port (default: 7878) or the user has insufficient permissions");
|
||||
System.Console.WriteLine("Press enter to exit...");
|
||||
System.Console.ReadLine();
|
||||
Environment.Exit(1);
|
||||
Logger.Fatal(e.Message + ". This can happen if another instance of Radarr is already running another application is using the same port (default: 7878) or the user has insufficient permissions");
|
||||
Exit(ExitCodes.RecoverableFailure);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.Console.WriteLine("");
|
||||
System.Console.WriteLine("");
|
||||
Logger.Fatal(e, "EPIC FAIL!");
|
||||
System.Console.WriteLine("Press enter to exit...");
|
||||
System.Console.ReadLine();
|
||||
Environment.Exit(1);
|
||||
Exit(ExitCodes.UnknownFailure);
|
||||
}
|
||||
|
||||
Logger.Info("Exiting main.");
|
||||
|
||||
//Need this to terminate on mono (thanks nlog)
|
||||
LogManager.Configuration = null;
|
||||
Environment.Exit(0);
|
||||
Exit(ExitCodes.Normal);
|
||||
}
|
||||
|
||||
private static void Exit(ExitCodes exitCode)
|
||||
{
|
||||
LogManager.Shutdown();
|
||||
|
||||
if (exitCode != ExitCodes.Normal)
|
||||
{
|
||||
System.Console.WriteLine("Press enter to exit...");
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
|
||||
// Please note that ReadLine silently succeeds if there is no console, KeyAvailable does not.
|
||||
System.Console.ReadLine();
|
||||
}
|
||||
|
||||
Environment.Exit((int)exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public void Setup()
|
||||
Port = 2222,
|
||||
Username = "admin",
|
||||
Password = "pass",
|
||||
TvCategory = "tv",
|
||||
MovieCategory = "movie",
|
||||
RecentTvPriority = (int)NzbgetPriority.High
|
||||
};
|
||||
|
||||
@ -38,7 +38,7 @@ public void Setup()
|
||||
{
|
||||
FileSizeLo = 1000,
|
||||
RemainingSizeLo = 10,
|
||||
Category = "tv",
|
||||
Category = "movie",
|
||||
NzbName = "Droned.1998.1080p.WEB-DL-DRONE",
|
||||
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } }
|
||||
};
|
||||
@ -46,7 +46,7 @@ public void Setup()
|
||||
_failed = new NzbgetHistoryItem
|
||||
{
|
||||
FileSizeLo = 1000,
|
||||
Category = "tv",
|
||||
Category = "movie",
|
||||
Name = "Droned.1998.1080p.WEB-DL-DRONE",
|
||||
DestDir = "somedirectory",
|
||||
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } },
|
||||
@ -61,7 +61,7 @@ public void Setup()
|
||||
_completed = new NzbgetHistoryItem
|
||||
{
|
||||
FileSizeLo = 1000,
|
||||
Category = "tv",
|
||||
Category = "movie",
|
||||
Name = "Droned.1998.1080p.WEB-DL-DRONE",
|
||||
DestDir = "/remote/mount/tv/Droned.1998.1080p.WEB-DL-DRONE",
|
||||
Parameters = new List<NzbgetParameter> { new NzbgetParameter { Name = "drone", Value = "id" } },
|
||||
@ -81,8 +81,8 @@ public void Setup()
|
||||
});
|
||||
|
||||
var configItems = new Dictionary<string, string>();
|
||||
configItems.Add("Category1.Name", "tv");
|
||||
configItems.Add("Category1.DestDir", @"/remote/mount/tv");
|
||||
configItems.Add("Category1.Name", "movie");
|
||||
configItems.Add("Category1.DestDir", @"/remote/mount/movie");
|
||||
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(v => v.GetConfig(It.IsAny<NzbgetSettings>()))
|
||||
@ -340,7 +340,7 @@ public void should_return_status_with_outputdir()
|
||||
|
||||
result.IsLocalhost.Should().BeTrue();
|
||||
result.OutputRootFolders.Should().NotBeNull();
|
||||
result.OutputRootFolders.First().Should().Be(@"/remote/mount/tv");
|
||||
result.OutputRootFolders.First().Should().Be(@"/remote/mount/movie");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -36,7 +36,7 @@ public void Setup()
|
||||
ApiKey = "5c770e3197e4fe763423ee7c392c25d1",
|
||||
Username = "admin",
|
||||
Password = "pass",
|
||||
TvCategory = "tv",
|
||||
MovieCategory = "movie",
|
||||
RecentTvPriority = (int)SabnzbdPriority.High
|
||||
};
|
||||
_queued = new SabnzbdQueue
|
||||
@ -51,7 +51,7 @@ public void Setup()
|
||||
Size = 1000,
|
||||
Sizeleft = 10,
|
||||
Timeleft = TimeSpan.FromSeconds(10),
|
||||
Category = "tv",
|
||||
Category = "movie",
|
||||
Id = "sabnzbd_nzb12345",
|
||||
Title = "Droned.1998.1080p.WEB-DL-DRONE"
|
||||
}
|
||||
@ -66,7 +66,7 @@ public void Setup()
|
||||
{
|
||||
Status = SabnzbdDownloadStatus.Failed,
|
||||
Size = 1000,
|
||||
Category = "tv",
|
||||
Category = "movie",
|
||||
Id = "sabnzbd_nzb12345",
|
||||
Title = "Droned.1998.1080p.WEB-DL-DRONE"
|
||||
}
|
||||
@ -81,7 +81,7 @@ public void Setup()
|
||||
{
|
||||
Status = SabnzbdDownloadStatus.Completed,
|
||||
Size = 1000,
|
||||
Category = "tv",
|
||||
Category = "movie",
|
||||
Id = "sabnzbd_nzb12345",
|
||||
Title = "Droned.1998.1080p.WEB-DL-DRONE",
|
||||
Storage = "/remote/mount/vv/Droned.1998.1080p.WEB-DL-DRONE"
|
||||
@ -97,7 +97,7 @@ public void Setup()
|
||||
},
|
||||
Categories = new List<SabnzbdCategory>
|
||||
{
|
||||
new SabnzbdCategory { Name = "tv", Dir = "vv" }
|
||||
new SabnzbdCategory { Name = "movie", Dir = "vv" }
|
||||
}
|
||||
};
|
||||
|
||||
@ -111,7 +111,7 @@ public void Setup()
|
||||
|
||||
_fullStatus = new SabnzbdFullStatus
|
||||
{
|
||||
CompleteDir = @"Y:\nzbget\root\complete".AsOsAgnostic()
|
||||
CompleteDir = @"Y:\sabnzbd\root\complete".AsOsAgnostic()
|
||||
};
|
||||
|
||||
Mocker.GetMock<ISabnzbdProxy>()
|
||||
@ -408,10 +408,10 @@ public void should_not_blow_up_if_storage_doesnt_have_jobfolder()
|
||||
result.OutputPath.Should().Be(@"C:\sorted\somewhere\asdfasdf\asdfasdf.mkv".AsOsAgnostic());
|
||||
}
|
||||
|
||||
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads", @"Y:\nzbget\root\completed\downloads\vv")]
|
||||
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed", @"Y:\nzbget\root\completed\vv")]
|
||||
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads", @"/nzbget/root/completed/downloads/vv")]
|
||||
[TestCase(@"/nzbget/root", @"completed", @"vv", @"/nzbget/root/completed", @"/nzbget/root/completed/vv")]
|
||||
[TestCase(@"Y:\sabnzbd\root", @"completed\downloads", @"vv", @"Y:\sabnzbd\root\completed\downloads", @"Y:\sabnzbd\root\completed\downloads\vv")]
|
||||
[TestCase(@"Y:\sabnzbd\root", @"completed", @"vv", @"Y:\sabnzbd\root\completed", @"Y:\sabnzbd\root\completed\vv")]
|
||||
[TestCase(@"/sabnzbd/root", @"completed/downloads", @"vv", @"/sabnzbd/root/completed/downloads", @"/sabnzbd/root/completed/downloads/vv")]
|
||||
[TestCase(@"/sabnzbd/root", @"completed", @"vv", @"/sabnzbd/root/completed", @"/sabnzbd/root/completed/vv")]
|
||||
public void should_return_status_with_outputdir_for_version_lt_2(string rootFolder, string completeDir, string categoryDir, string fullCompleteDir, string fullCategoryDir)
|
||||
{
|
||||
_fullStatus.CompleteDir = null;
|
||||
@ -429,10 +429,10 @@ public void should_return_status_with_outputdir_for_version_lt_2(string rootFold
|
||||
result.OutputRootFolders.First().Should().Be(fullCategoryDir);
|
||||
}
|
||||
|
||||
[TestCase(@"Y:\nzbget\root", @"completed\downloads", @"vv", @"Y:\nzbget\root\completed\downloads", @"Y:\nzbget\root\completed\downloads\vv")]
|
||||
[TestCase(@"Y:\nzbget\root", @"completed", @"vv", @"Y:\nzbget\root\completed", @"Y:\nzbget\root\completed\vv")]
|
||||
[TestCase(@"/nzbget/root", @"completed/downloads", @"vv", @"/nzbget/root/completed/downloads", @"/nzbget/root/completed/downloads/vv")]
|
||||
[TestCase(@"/nzbget/root", @"completed", @"vv", @"/nzbget/root/completed", @"/nzbget/root/completed/vv")]
|
||||
[TestCase(@"Y:\sabnzbd\root", @"completed\downloads", @"vv", @"Y:\sabnzbd\root\completed\downloads", @"Y:\sabnzbd\root\completed\downloads\vv")]
|
||||
[TestCase(@"Y:\sabnzbd\root", @"completed", @"vv", @"Y:\sabnzbd\root\completed", @"Y:\sabnzbd\root\completed\vv")]
|
||||
[TestCase(@"/sabnzbd/root", @"completed/downloads", @"vv", @"/sabnzbd/root/completed/downloads", @"/sabnzbd/root/completed/downloads/vv")]
|
||||
[TestCase(@"/sabnzbd/root", @"completed", @"vv", @"/sabnzbd/root/completed", @"/sabnzbd/root/completed/vv")]
|
||||
public void should_return_status_with_outputdir_for_version_gte_2(string rootFolder, string completeDir, string categoryDir, string fullCompleteDir, string fullCategoryDir)
|
||||
{
|
||||
_fullStatus.CompleteDir = fullCompleteDir;
|
||||
@ -544,7 +544,7 @@ public void should_test_success_if_tv_sorting_contains_different_category()
|
||||
public void should_test_failed_if_tv_sorting_contains_category()
|
||||
{
|
||||
_config.Misc.enable_tv_sorting = true;
|
||||
_config.Misc.tv_categories = new[] { "tv" };
|
||||
_config.Misc.tv_categories = new[] { "movie" };
|
||||
|
||||
var result = new NzbDroneValidationResult(Subject.Test());
|
||||
|
||||
@ -554,7 +554,7 @@ public void should_test_failed_if_tv_sorting_contains_category()
|
||||
[Test]
|
||||
public void should_test_failed_if_tv_sorting_default_category()
|
||||
{
|
||||
Subject.Definition.Settings.As<SabnzbdSettings>().TvCategory = null;
|
||||
Subject.Definition.Settings.As<SabnzbdSettings>().MovieCategory = null;
|
||||
|
||||
_config.Misc.enable_tv_sorting = true;
|
||||
_config.Misc.tv_categories = new[] { "Default" };
|
||||
|
@ -30,7 +30,7 @@ public void Setup()
|
||||
Port = 2222,
|
||||
Username = "admin",
|
||||
Password = "pass",
|
||||
TvCategory = "tv"
|
||||
MovieCategory = "movie"
|
||||
};
|
||||
|
||||
_queued = new UTorrentTorrent
|
||||
@ -41,7 +41,7 @@ public void Setup()
|
||||
Size = 1000,
|
||||
Remaining = 1000,
|
||||
Progress = 0,
|
||||
Label = "tv",
|
||||
Label = "movie",
|
||||
DownloadUrl = _downloadUrl,
|
||||
RootDownloadPath = "somepath"
|
||||
};
|
||||
@ -54,7 +54,7 @@ public void Setup()
|
||||
Size = 1000,
|
||||
Remaining = 100,
|
||||
Progress = 0.9,
|
||||
Label = "tv",
|
||||
Label = "movie",
|
||||
DownloadUrl = _downloadUrl,
|
||||
RootDownloadPath = "somepath"
|
||||
};
|
||||
@ -67,7 +67,7 @@ public void Setup()
|
||||
Size = 1000,
|
||||
Remaining = 100,
|
||||
Progress = 0.9,
|
||||
Label = "tv",
|
||||
Label = "movie",
|
||||
DownloadUrl = _downloadUrl,
|
||||
RootDownloadPath = "somepath"
|
||||
};
|
||||
@ -80,7 +80,7 @@ public void Setup()
|
||||
Size = 1000,
|
||||
Remaining = 0,
|
||||
Progress = 1.0,
|
||||
Label = "tv",
|
||||
Label = "movie",
|
||||
DownloadUrl = _downloadUrl,
|
||||
RootDownloadPath = "somepath"
|
||||
};
|
||||
@ -328,7 +328,7 @@ public void should_return_status_with_outputdirs()
|
||||
|
||||
result.IsLocalhost.Should().BeTrue();
|
||||
result.OutputRootFolders.Should().NotBeNull();
|
||||
result.OutputRootFolders.First().Should().Be(@"C:\Downloads\Finished\utorrent\tv".AsOsAgnostic());
|
||||
result.OutputRootFolders.First().Should().Be(@"C:\Downloads\Finished\utorrent\movie".AsOsAgnostic());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -47,7 +47,7 @@ public void should_convert_cover_urls_to_local()
|
||||
Subject.ConvertToLocalUrls(12, covers);
|
||||
|
||||
|
||||
covers.Single().Url.Should().Be("/MediaCover/12/banner.jpg?lastWrite=1234");
|
||||
covers.Single().Url.Should().Be("/MediaCover/12/banner.jpg");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -14,6 +14,7 @@
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
using FluentAssertions;
|
||||
using NzbDrone.Core.Download;
|
||||
|
||||
namespace NzbDrone.Core.Test.MediaFiles
|
||||
{
|
||||
@ -77,7 +78,7 @@ public void should_skip_if_no_series_found()
|
||||
Subject.ProcessRootFolder(new DirectoryInfo(_droneFactory));
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(c => c.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<ParsedMovieInfo>(), It.IsAny<bool>()),
|
||||
.Verify(c => c.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), It.IsAny<ParsedMovieInfo>(), It.IsAny<bool>()),
|
||||
Times.Never());
|
||||
|
||||
VerifyNoImport();
|
||||
@ -128,7 +129,7 @@ public void should_not_delete_folder_if_files_were_imported_and_video_files_rema
|
||||
imported.Add(new ImportDecision(localMovie));
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), null, true))
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), null, true))
|
||||
.Returns(imported);
|
||||
|
||||
Mocker.GetMock<IImportApprovedMovie>()
|
||||
@ -154,7 +155,7 @@ public void should_delete_folder_if_files_were_imported_and_only_sample_files_re
|
||||
imported.Add(new ImportDecision(localMovie));
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), null, true))
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), null, true))
|
||||
.Returns(imported);
|
||||
|
||||
Mocker.GetMock<IImportApprovedMovie>()
|
||||
@ -226,7 +227,7 @@ public void should_not_delete_if_there_is_large_rar_file()
|
||||
imported.Add(new ImportDecision(localMovie));
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), null, true))
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), null, true))
|
||||
.Returns(imported);
|
||||
|
||||
Mocker.GetMock<IImportApprovedMovie>()
|
||||
@ -280,7 +281,7 @@ public void should_use_folder_if_folder_import()
|
||||
Subject.ProcessPath(fileName);
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<ParsedMovieInfo>(), true, false), Times.Once());
|
||||
.Verify(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), It.IsAny<ParsedMovieInfo>(), true, false), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -304,7 +305,7 @@ public void should_not_use_folder_if_file_import()
|
||||
var result = Subject.ProcessPath(fileName);
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Verify(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), null, true, false), Times.Once());
|
||||
.Verify(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), null, true, false), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -337,7 +338,7 @@ public void should_not_delete_if_no_files_were_imported()
|
||||
imported.Add(new ImportDecision(localMovie));
|
||||
|
||||
Mocker.GetMock<IMakeImportDecision>()
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), null, true))
|
||||
.Setup(s => s.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Movie>(), It.IsAny<DownloadClientItem>(), null, true))
|
||||
.Returns(imported);
|
||||
|
||||
Mocker.GetMock<IImportApprovedEpisodes>()
|
||||
|
@ -38,8 +38,8 @@ public void should_fetch_imdb_list()
|
||||
|
||||
var result = Subject.Fetch();
|
||||
|
||||
result.First().Title.Should().Be("Think Like a Man Too");
|
||||
result.First().ImdbId.Should().Be("tt2239832");
|
||||
result.Movies.First().Title.Should().Be("Think Like a Man Too");
|
||||
result.Movies.First().ImdbId.Should().Be("tt2239832");
|
||||
}
|
||||
}
|
||||
}
|
@ -19,29 +19,29 @@ public class SynologyIndexerFixture : CoreTest<SynologyIndexer>
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_movie = new Movie()
|
||||
_movie = new Movie
|
||||
{
|
||||
Path = @"C:\Test\".AsOsAgnostic()
|
||||
};
|
||||
|
||||
_upgrade = new DownloadMessage()
|
||||
_upgrade = new DownloadMessage
|
||||
{
|
||||
Movie = _movie,
|
||||
|
||||
MovieFile = new MovieFile
|
||||
{
|
||||
RelativePath = "file1.S01E01E02.mkv"
|
||||
RelativePath = "moviefile1.mkv"
|
||||
},
|
||||
|
||||
OldMovieFiles = new List<MovieFile>
|
||||
{
|
||||
new MovieFile
|
||||
{
|
||||
RelativePath = "file1.S01E01.mkv"
|
||||
RelativePath = "oldmoviefile1.mkv"
|
||||
},
|
||||
new MovieFile
|
||||
{
|
||||
RelativePath = "file1.S01E02.mkv"
|
||||
RelativePath = "oldmoviefile2.mkv"
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -63,37 +63,37 @@ public void should_not_update_library_if_disabled()
|
||||
Subject.OnMovieRename(_movie);
|
||||
|
||||
Mocker.GetMock<ISynologyIndexerProxy>()
|
||||
.Verify(v => v.UpdateFolder(_movie.Path), Times.Never());
|
||||
.Verify(v => v.UpdateFolder(_movie.Path), Times.Never());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_remove_old_episodes_on_upgrade()
|
||||
public void should_remove_old_movie_on_upgrade()
|
||||
{
|
||||
Subject.OnDownload(_upgrade);
|
||||
|
||||
Mocker.GetMock<ISynologyIndexerProxy>()
|
||||
.Verify(v => v.DeleteFile(@"C:\Test\file1.S01E01.mkv".AsOsAgnostic()), Times.Once());
|
||||
.Verify(v => v.DeleteFile(@"C:\Test\oldmoviefile1.mkv".AsOsAgnostic()), Times.Once());
|
||||
|
||||
Mocker.GetMock<ISynologyIndexerProxy>()
|
||||
.Verify(v => v.DeleteFile(@"C:\Test\file1.S01E02.mkv".AsOsAgnostic()), Times.Once());
|
||||
.Verify(v => v.DeleteFile(@"C:\Test\oldmoviefile2.mkv".AsOsAgnostic()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_new_episode_on_upgrade()
|
||||
public void should_add_new_movie_on_upgrade()
|
||||
{
|
||||
Subject.OnDownload(_upgrade);
|
||||
|
||||
Mocker.GetMock<ISynologyIndexerProxy>()
|
||||
.Verify(v => v.AddFile(@"C:\Test\file1.S01E01E02.mkv".AsOsAgnostic()), Times.Once());
|
||||
.Verify(v => v.AddFile(@"C:\Test\moviefile1.mkv".AsOsAgnostic()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_entire_series_folder_on_rename()
|
||||
public void should_update_entire_movie_folder_on_rename()
|
||||
{
|
||||
Subject.OnMovieRename(_movie);
|
||||
|
||||
Mocker.GetMock<ISynologyIndexerProxy>()
|
||||
.Verify(v => v.UpdateFolder(@"C:\Test\".AsOsAgnostic()), Times.Once());
|
||||
.Verify(v => v.UpdateFolder(@"C:\Test\".AsOsAgnostic()), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,70 +0,0 @@
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Http
|
||||
{
|
||||
[TestFixture]
|
||||
public class ActivePlayersFixture : CoreTest<HttpApiProvider>
|
||||
{
|
||||
private XbmcSettings _settings;
|
||||
private string _expectedUrl;
|
||||
|
||||
private void WithNoActivePlayers()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(_expectedUrl, _settings.Username, _settings.Password))
|
||||
.Returns("<html><li>Filename:[Nothing Playing]</html>");
|
||||
}
|
||||
|
||||
private void WithVideoPlayerActive()
|
||||
{
|
||||
var activePlayers = @"<html><li>Filename:C:\Test\TV\2 Broke Girls\Season 01\2 Broke Girls - S01E01 - Pilot [SDTV].avi" +
|
||||
"<li>PlayStatus:Playing<li>VideoNo:0<li>Type:Video<li>Thumb:special://masterprofile/Thumbnails/Video/a/auto-a664d5a2.tbn" +
|
||||
"<li>Time:00:06<li>Duration:21:35<li>Percentage:0<li>File size:183182590<li>Changed:True</html>";
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(_expectedUrl, _settings.Username, _settings.Password))
|
||||
.Returns(activePlayers);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_settings = new XbmcSettings
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 8080,
|
||||
Username = "xbmc",
|
||||
Password = "xbmc",
|
||||
AlwaysUpdate = false,
|
||||
CleanLibrary = false,
|
||||
UpdateLibrary = true
|
||||
};
|
||||
|
||||
_expectedUrl = string.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", _settings.Address, "getcurrentlyplaying");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void _should_be_empty_when_no_active_players()
|
||||
{
|
||||
WithNoActivePlayers();
|
||||
|
||||
Subject.GetActivePlayers(_settings).Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_have_active_video_player()
|
||||
{
|
||||
WithVideoPlayerActive();
|
||||
|
||||
var result = Subject.GetActivePlayers(_settings);
|
||||
|
||||
result.Should().HaveCount(1);
|
||||
result.First().Type.Should().Be("video");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Http
|
||||
{
|
||||
[TestFixture]
|
||||
public class CheckForErrorFixture : CoreTest<HttpApiProvider>
|
||||
{
|
||||
[Test]
|
||||
public void should_be_true_when_the_response_contains_an_error()
|
||||
{
|
||||
const string response = "html><li>Error:Unknown command</html>";
|
||||
|
||||
Subject.CheckForError(response).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonError_true_empty_response()
|
||||
{
|
||||
var response = string.Empty;
|
||||
|
||||
Subject.CheckForError(response).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonError_false()
|
||||
{
|
||||
const string response = "html><li>Filename:[Nothing Playing]</html>";
|
||||
|
||||
Subject.CheckForError(response).Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Http
|
||||
{
|
||||
[TestFixture]
|
||||
public class GetSeriesPathFixture : CoreTest<HttpApiProvider>
|
||||
{
|
||||
private XbmcSettings _settings;
|
||||
private Series _series;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_settings = new XbmcSettings
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 8080,
|
||||
Username = "xbmc",
|
||||
Password = "xbmc",
|
||||
AlwaysUpdate = false,
|
||||
CleanLibrary = false,
|
||||
UpdateLibrary = true
|
||||
};
|
||||
|
||||
_series = new Series
|
||||
{
|
||||
TvdbId = 79488,
|
||||
Title = "30 Rock"
|
||||
};
|
||||
|
||||
const string setResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat(webheader;false;webfooter;false;header;<xml>;footer;</xml>;opentag;<tag>;closetag;</tag>;closefinaltag;false)";
|
||||
const string resetResponseUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=SetResponseFormat()";
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(setResponseUrl, _settings.Username, _settings.Password))
|
||||
.Returns("<xml><tag>OK</xml>");
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(resetResponseUrl, _settings.Username, _settings.Password))
|
||||
.Returns(@"<html>
|
||||
<li>OK
|
||||
</html>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_get_series_path()
|
||||
{
|
||||
const string queryResult = @"<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/</field></record></xml>";
|
||||
var query = string.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)");
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(query, _settings.Username, _settings.Password))
|
||||
.Returns(queryResult);
|
||||
|
||||
Subject.GetSeriesPath(_settings, _series)
|
||||
.Should().Be("smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_get_null_for_series_path()
|
||||
{
|
||||
const string queryResult = @"<xml></xml>";
|
||||
var query = string.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)");
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(query, _settings.Username, _settings.Password))
|
||||
.Returns(queryResult);
|
||||
|
||||
|
||||
Subject.GetSeriesPath(_settings, _series)
|
||||
.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_get_series_path_with_special_characters_in_it()
|
||||
{
|
||||
const string queryResult = @"<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/Law & Order- Special Victims Unit/</field></record></xml>";
|
||||
var query = string.Format("http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)");
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(query, _settings.Username, _settings.Password))
|
||||
.Returns(queryResult);
|
||||
|
||||
|
||||
Subject.GetSeriesPath(_settings, _series)
|
||||
.Should().Be("smb://xbmc:xbmc@HOMESERVER/TV/Law & Order- Special Victims Unit/");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
using FizzWare.NBuilder;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Http
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpdateFixture : CoreTest<HttpApiProvider>
|
||||
{
|
||||
private XbmcSettings _settings;
|
||||
private string _seriesQueryUrl = "http://localhost:8080/xbmcCmds/xbmcHttp?command=QueryVideoDatabase(select path.strPath from path, tvshow, tvshowlinkpath where tvshow.c12 = 79488 and tvshowlinkpath.idShow = tvshow.idShow and tvshowlinkpath.idPath = path.idPath)";
|
||||
private Series _fakeSeries;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_settings = new XbmcSettings
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 8080,
|
||||
Username = "xbmc",
|
||||
Password = "xbmc",
|
||||
AlwaysUpdate = false,
|
||||
CleanLibrary = false,
|
||||
UpdateLibrary = true
|
||||
};
|
||||
|
||||
_fakeSeries = Builder<Series>.CreateNew()
|
||||
.With(s => s.TvdbId = 79488)
|
||||
.With(s => s.Title = "30 Rock")
|
||||
.Build();
|
||||
}
|
||||
|
||||
private void WithSeriesPath()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(_seriesQueryUrl, _settings.Username, _settings.Password))
|
||||
.Returns("<xml><record><field>smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/</field></record></xml>");
|
||||
}
|
||||
|
||||
private void WithoutSeriesPath()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(_seriesQueryUrl, _settings.Username, _settings.Password))
|
||||
.Returns("<xml></xml>");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_using_series_path()
|
||||
{
|
||||
WithSeriesPath();
|
||||
const string url = "http://localhost:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn(UpdateLibrary(video,smb://xbmc:xbmc@HOMESERVER/TV/30 Rock/))";
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Setup(s => s.DownloadString(url, _settings.Username, _settings.Password));
|
||||
|
||||
Subject.Update(_settings, _fakeSeries);
|
||||
Mocker.VerifyAllMocks();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_all_paths_when_series_path_not_found()
|
||||
{
|
||||
WithoutSeriesPath();
|
||||
const string url = "http://localhost:8080/xbmcCmds/xbmcHttp?command=ExecBuiltIn(UpdateLibrary(video))";
|
||||
|
||||
Mocker.GetMock<IHttpProvider>().Setup(s => s.DownloadString(url, _settings.Username, _settings.Password));
|
||||
|
||||
Subject.Update(_settings, _fakeSeries);
|
||||
Mocker.VerifyAllMocks();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Notifications.Xbmc.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json
|
||||
{
|
||||
[TestFixture]
|
||||
public class GetMoviePathFixture : CoreTest<JsonApiProvider>
|
||||
{
|
||||
private const string IMDB_ID = "tt67890";
|
||||
private XbmcSettings _settings;
|
||||
private Movie _movie;
|
||||
private List<XbmcMovie> _xbmcMovies;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_settings = Builder<XbmcSettings>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_xbmcMovies = Builder<XbmcMovie>.CreateListOfSize(3)
|
||||
.All()
|
||||
.With(s => s.ImdbNumber = "tt00000")
|
||||
.TheFirst(1)
|
||||
.With(s => s.ImdbNumber = IMDB_ID)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Setup(s => s.GetMovies(_settings))
|
||||
.Returns(_xbmcMovies);
|
||||
}
|
||||
|
||||
private void GivenMatchingImdbId()
|
||||
{
|
||||
_movie = new Movie
|
||||
{
|
||||
ImdbId = IMDB_ID,
|
||||
Title = "Movie"
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenMatchingTitle()
|
||||
{
|
||||
_movie = new Movie
|
||||
{
|
||||
ImdbId = "tt01000",
|
||||
Title = _xbmcMovies.First().Label
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenMatchingMovie()
|
||||
{
|
||||
_movie = new Movie
|
||||
{
|
||||
ImdbId = "tt01000",
|
||||
Title = "Does not exist"
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_null_when_movie_is_not_found()
|
||||
{
|
||||
GivenMatchingMovie();
|
||||
|
||||
Subject.GetMoviePath(_settings, _movie).Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_path_when_tvdbId_matches()
|
||||
{
|
||||
GivenMatchingImdbId();
|
||||
|
||||
Subject.GetMoviePath(_settings, _movie).Should().Be(_xbmcMovies.First().File);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_path_when_title_matches()
|
||||
{
|
||||
GivenMatchingTitle();
|
||||
|
||||
Subject.GetMoviePath(_settings, _movie).Should().Be(_xbmcMovies.First().File);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Notifications.Xbmc.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json
|
||||
{
|
||||
[TestFixture]
|
||||
public class GetSeriesPathFixture : CoreTest<JsonApiProvider>
|
||||
{
|
||||
private const int TVDB_ID = 5;
|
||||
private XbmcSettings _settings;
|
||||
private Series _series;
|
||||
private List<TvShow> _xbmcSeries;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_settings = Builder<XbmcSettings>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_xbmcSeries = Builder<TvShow>.CreateListOfSize(3)
|
||||
.All()
|
||||
.With(s => s.ImdbNumber = "0")
|
||||
.TheFirst(1)
|
||||
.With(s => s.ImdbNumber = TVDB_ID.ToString())
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Setup(s => s.GetSeries(_settings))
|
||||
.Returns(_xbmcSeries);
|
||||
}
|
||||
|
||||
private void GivenMatchingTvdbId()
|
||||
{
|
||||
_series = new Series
|
||||
{
|
||||
TvdbId = TVDB_ID,
|
||||
Title = "TV Show"
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenMatchingTitle()
|
||||
{
|
||||
_series = new Series
|
||||
{
|
||||
TvdbId = 1000,
|
||||
Title = _xbmcSeries.First().Label
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenMatchingSeries()
|
||||
{
|
||||
_series = new Series
|
||||
{
|
||||
TvdbId = 1000,
|
||||
Title = "Does not exist"
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_null_when_series_is_not_found()
|
||||
{
|
||||
GivenMatchingSeries();
|
||||
|
||||
Subject.GetSeriesPath(_settings, _series).Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_path_when_tvdbId_matches()
|
||||
{
|
||||
GivenMatchingTvdbId();
|
||||
|
||||
Subject.GetSeriesPath(_settings, _series).Should().Be(_xbmcSeries.First().File);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_path_when_title_matches()
|
||||
{
|
||||
GivenMatchingTitle();
|
||||
|
||||
Subject.GetSeriesPath(_settings, _series).Should().Be(_xbmcSeries.First().File);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_throw_when_imdb_number_is_not_a_number()
|
||||
{
|
||||
GivenMatchingTvdbId();
|
||||
|
||||
_xbmcSeries.ForEach(s => s.ImdbNumber = "tt12345");
|
||||
_xbmcSeries.Last().ImdbNumber = TVDB_ID.ToString();
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Setup(s => s.GetSeries(_settings))
|
||||
.Returns(_xbmcSeries);
|
||||
|
||||
Subject.GetSeriesPath(_settings, _series).Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Notifications.Xbmc.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpdateFixture : CoreTest<JsonApiProvider>
|
||||
{
|
||||
private const int TVDB_ID = 5;
|
||||
private XbmcSettings _settings;
|
||||
private List<TvShow> _xbmcSeries;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_settings = Builder<XbmcSettings>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_xbmcSeries = Builder<TvShow>.CreateListOfSize(3)
|
||||
.TheFirst(1)
|
||||
.With(s => s.ImdbNumber = TVDB_ID.ToString())
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Setup(s => s.GetSeries(_settings))
|
||||
.Returns(_xbmcSeries);
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Setup(s => s.GetActivePlayers(_settings))
|
||||
.Returns(new List<ActivePlayer>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_using_series_path()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.With(s => s.TvdbId = TVDB_ID)
|
||||
.Build();
|
||||
|
||||
Subject.Update(_settings, series);
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Verify(v => v.UpdateLibrary(_settings, It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_all_paths_when_series_path_not_found()
|
||||
{
|
||||
var fakeSeries = Builder<Series>.CreateNew()
|
||||
.With(s => s.TvdbId = 1000)
|
||||
.With(s => s.Title = "Not 30 Rock")
|
||||
.Build();
|
||||
|
||||
Subject.Update(_settings, fakeSeries);
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Verify(v => v.UpdateLibrary(_settings, null), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Notifications.Xbmc;
|
||||
using NzbDrone.Core.Notifications.Xbmc.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.NotificationTests.Xbmc.Json
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpdateMovieFixture : CoreTest<JsonApiProvider>
|
||||
{
|
||||
private const string IMDB_ID = "tt67890";
|
||||
private XbmcSettings _settings;
|
||||
private List<XbmcMovie> _xbmcMovies;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_settings = Builder<XbmcSettings>.CreateNew()
|
||||
.Build();
|
||||
|
||||
_xbmcMovies = Builder<XbmcMovie>.CreateListOfSize(3)
|
||||
.TheFirst(1)
|
||||
.With(s => s.ImdbNumber = IMDB_ID)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Setup(s => s.GetMovies(_settings))
|
||||
.Returns(_xbmcMovies);
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Setup(s => s.GetActivePlayers(_settings))
|
||||
.Returns(new List<ActivePlayer>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_using_movie_path()
|
||||
{
|
||||
var movie = Builder<Movie>.CreateNew()
|
||||
.With(s => s.ImdbId = IMDB_ID)
|
||||
.Build();
|
||||
|
||||
Subject.UpdateMovie(_settings, movie);
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Verify(v => v.UpdateLibrary(_settings, It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_update_all_paths_when_movie_path_not_found()
|
||||
{
|
||||
var fakeMovie = Builder<Movie>.CreateNew()
|
||||
.With(s => s.ImdbId = "tt01000")
|
||||
.With(s => s.Title = "Not A Real Movie")
|
||||
.Build();
|
||||
|
||||
Subject.UpdateMovie(_settings, fakeMovie);
|
||||
|
||||
Mocker.GetMock<IXbmcJsonApiProxy>()
|
||||
.Verify(v => v.UpdateLibrary(_settings, null), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
@ -41,8 +41,8 @@ public void Setup()
|
||||
private void GivenOldFiles()
|
||||
{
|
||||
_downloadMessage.OldMovieFiles = Builder<MovieFile>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
Subject.Definition.Settings = new XbmcSettings
|
||||
{
|
||||
@ -52,7 +52,7 @@ private void GivenOldFiles()
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_clean_if_no_episode_was_replaced()
|
||||
public void should_not_clean_if_no_movie_was_replaced()
|
||||
{
|
||||
Subject.OnDownload(_downloadMessage);
|
||||
|
||||
@ -60,7 +60,7 @@ public void should_not_clean_if_no_episode_was_replaced()
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_clean_if_episode_was_replaced()
|
||||
public void should_clean_if_movie_was_replaced()
|
||||
{
|
||||
GivenOldFiles();
|
||||
Subject.OnDownload(_downloadMessage);
|
||||
|
@ -317,12 +317,6 @@
|
||||
<Compile Include="Metadata\Consumers\Wdtv\FindMetadataFileFixture.cs" />
|
||||
<Compile Include="NotificationTests\PlexClientServiceTest.cs" />
|
||||
<Compile Include="NotificationTests\ProwlProviderTest.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Http\ActivePlayersFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Http\CheckForErrorFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Http\GetSeriesPathFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Http\UpdateFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Json\GetSeriesPathFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Json\UpdateFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\OnDownloadFixture.cs" />
|
||||
<Compile Include="OrganizerTests\BuildFilePathFixture.cs" />
|
||||
<Compile Include="OrganizerTests\GetSeasonFolderFixture.cs" />
|
||||
@ -395,6 +389,8 @@
|
||||
<None Include="Files\Indexers\PTP\imdbsearch.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Compile Include="NotificationTests\Xbmc\Json\GetMoviePathFixture.cs" />
|
||||
<Compile Include="NotificationTests\Xbmc\Json\UpdateMovieFixture.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
|
||||
|
@ -14,6 +14,7 @@ public class LanguageParserFixture : CoreTest
|
||||
[TestCase("Ouija.Origin.of.Evil.2016.MULTi.TRUEFRENCH.1080p.BluRay.x264-MELBA", Language.French)]
|
||||
[TestCase("Everest.2015.FRENCH.VFQ.BDRiP.x264-CNF30", Language.French)]
|
||||
[TestCase("Showdown.In.Little.Tokyo.1991.MULTI.VFQ.VFF.DTSHD-MASTER.1080p.BluRay.x264-ZombiE", Language.French)]
|
||||
[TestCase("The.Polar.Express.2004.MULTI.VF2.1080p.BluRay.x264-PopHD", Language.French)]
|
||||
[TestCase("Castle.2009.S01E14.Spanish.HDTV.XviD-LOL", Language.Spanish)]
|
||||
[TestCase("Castle.2009.S01E14.German.HDTV.XviD-LOL", Language.German)]
|
||||
[TestCase("Castle.2009.S01E14.Germany.HDTV.XviD-LOL", Language.English)]
|
||||
|
@ -144,7 +144,7 @@ public static void Map()
|
||||
.Ignore(s => s.RootFolderPath)
|
||||
.Ignore(m => m.Actors)
|
||||
.Ignore(m => m.Genres)
|
||||
.Ignore(m => m.Tags)
|
||||
// .Ignore(m => m.Tags)
|
||||
.Relationship()
|
||||
.HasOne(s => s.Profile, s => s.ProfileId);
|
||||
//.HasOne(m => m.MovieFile, m => m.MovieFileId);
|
||||
|
@ -0,0 +1,110 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
{
|
||||
public class RequiredIndexerFlagsSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public RequiredIndexerFlagsSpecification(IIndexerFactory indexerFactory, Logger logger)
|
||||
{
|
||||
_indexerFactory = indexerFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
//public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var torrentInfo = remoteEpisode.Release as TorrentInfo;
|
||||
|
||||
if (torrentInfo == null || torrentInfo.IndexerId == 0)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
IndexerDefinition indexer;
|
||||
try
|
||||
{
|
||||
indexer = _indexerFactory.Get(torrentInfo.IndexerId);
|
||||
}
|
||||
catch (ModelNotFoundException)
|
||||
{
|
||||
_logger.Debug("Indexer with id {0} does not exist, skipping seeders check", torrentInfo.IndexerId);
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
var torrentIndexerSettings = indexer.Settings as ITorrentIndexerSettings;
|
||||
|
||||
if (torrentIndexerSettings != null)
|
||||
{
|
||||
var minimumSeeders = torrentIndexerSettings.MinimumSeeders;
|
||||
|
||||
if (torrentInfo.Seeders.HasValue && torrentInfo.Seeders.Value < minimumSeeders)
|
||||
{
|
||||
_logger.Debug("Not enough seeders: {0}. Minimum seeders: {1}", torrentInfo.Seeders, minimumSeeders);
|
||||
return Decision.Reject("Not enough seeders: {0}. Minimum seeders: {1}", torrentInfo.Seeders, minimumSeeders);
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(RemoteMovie remoteEpisode, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var torrentInfo = remoteEpisode.Release;
|
||||
|
||||
|
||||
if (torrentInfo == null || torrentInfo.IndexerId == 0)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
IndexerDefinition indexer;
|
||||
try
|
||||
{
|
||||
indexer = _indexerFactory.Get(torrentInfo.IndexerId);
|
||||
}
|
||||
catch (ModelNotFoundException)
|
||||
{
|
||||
_logger.Debug("Indexer with id {0} does not exist, skipping seeders check", torrentInfo.IndexerId);
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
var torrentIndexerSettings = indexer.Settings as ITorrentIndexerSettings;
|
||||
|
||||
if (torrentIndexerSettings != null)
|
||||
{
|
||||
var requiredFlags = torrentIndexerSettings.RequiredFlags;
|
||||
var requiredFlag = (IndexerFlags) 0;
|
||||
|
||||
if (requiredFlags == null || requiredFlags.Count() == 0)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
foreach (var flag in requiredFlags)
|
||||
{
|
||||
if (torrentInfo.IndexerFlags.HasFlag((IndexerFlags)flag))
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
requiredFlag |= (IndexerFlags)flag;
|
||||
}
|
||||
|
||||
_logger.Debug("None of the required indexer flags {0} where found. Found flags: {1}", requiredFlag, torrentInfo.IndexerFlags);
|
||||
return Decision.Reject("None of the required indexer flags {0} where found. Found flags: {1}", requiredFlag, torrentInfo.IndexerFlags);
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
@ -38,7 +38,7 @@ protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string fil
|
||||
|
||||
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents)
|
||||
{
|
||||
var category = Settings.TvCategory; // TODO: Update this to MovieCategory?
|
||||
var category = Settings.MovieCategory;
|
||||
|
||||
var priority = Settings.RecentTvPriority;
|
||||
|
||||
@ -204,7 +204,7 @@ private IEnumerable<DownloadClientItem> GetHistory()
|
||||
|
||||
public override IEnumerable<DownloadClientItem> GetItems()
|
||||
{
|
||||
return GetQueue().Concat(GetHistory()).Where(downloadClientItem => downloadClientItem.Category == Settings.TvCategory);
|
||||
return GetQueue().Concat(GetHistory()).Where(downloadClientItem => downloadClientItem.Category == Settings.MovieCategory);
|
||||
}
|
||||
|
||||
public override void RemoveItem(string downloadId, bool deleteData)
|
||||
@ -221,7 +221,7 @@ public override DownloadClientStatus GetStatus()
|
||||
{
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
|
||||
var category = GetCategories(config).FirstOrDefault(v => v.Name == Settings.TvCategory);
|
||||
var category = GetCategories(config).FirstOrDefault(v => v.Name == Settings.MovieCategory);
|
||||
|
||||
var status = new DownloadClientStatus
|
||||
{
|
||||
@ -283,7 +283,7 @@ private ValidationFailure TestConnection()
|
||||
|
||||
if (Version.Parse(version) < Version.Parse("12.0"))
|
||||
{
|
||||
return new ValidationFailure(string.Empty, "Nzbget version too low, need 12.0 or higher");
|
||||
return new ValidationFailure(string.Empty, "NZBGet version too low, need 12.0 or higher");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -304,12 +304,12 @@ private ValidationFailure TestCategory()
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
var categories = GetCategories(config);
|
||||
|
||||
if (!Settings.TvCategory.IsNullOrWhiteSpace() && !categories.Any(v => v.Name == Settings.TvCategory))
|
||||
if (!Settings.MovieCategory.IsNullOrWhiteSpace() && !categories.Any(v => v.Name == Settings.MovieCategory))
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "Category does not exist")
|
||||
return new NzbDroneValidationFailure("MovieCategory", "Category does not exist")
|
||||
{
|
||||
InfoLink = string.Format("http://{0}:{1}/", Settings.Host, Settings.Port),
|
||||
DetailedDescription = "The Category your entered doesn't exist in NzbGet. Go to NzbGet to create it."
|
||||
DetailedDescription = "The category you entered doesn't exist in NZBGet. Go to NZBGet to create it."
|
||||
};
|
||||
}
|
||||
|
||||
@ -323,10 +323,10 @@ private ValidationFailure TestSettings()
|
||||
var keepHistory = config.GetValueOrDefault("KeepHistory");
|
||||
if (keepHistory == "0")
|
||||
{
|
||||
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),
|
||||
DetailedDescription = "NzbGet setting KeepHistory is set to 0. Which prevents Radarr from seeing completed downloads."
|
||||
DetailedDescription = "NZBGet setting KeepHistory is set to 0. Which prevents Radarr from seeing completed downloads."
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
@ -88,7 +88,7 @@ private string DownloadNzbLegacy13(byte[] nzbData, string title, string category
|
||||
var editResult = EditQueue("GroupSetParameter", 0, "drone=" + droneId, item.NzbId, settings);
|
||||
if (editResult)
|
||||
{
|
||||
_logger.Debug("Nzbget download drone parameter set to: {0}", droneId);
|
||||
_logger.Debug("NZBGet download drone parameter set to: {0}", droneId);
|
||||
}
|
||||
|
||||
return droneId;
|
||||
@ -114,7 +114,7 @@ private string DownloadNzbLegacy12(byte[] nzbData, string title, string category
|
||||
|
||||
if (editResult)
|
||||
{
|
||||
_logger.Debug("Nzbget download drone parameter set to: {0}", droneId);
|
||||
_logger.Debug("NZBGet download drone parameter set to: {0}", droneId);
|
||||
}
|
||||
|
||||
return droneId;
|
||||
@ -175,7 +175,7 @@ public void RemoveItem(string id, NzbgetSettings settings)
|
||||
{
|
||||
if (!EditQueue("GroupFinalDelete", 0, "", queueItem.NzbId, settings))
|
||||
{
|
||||
_logger.Warn("Failed to remove item from nzbget queue, {0} [{1}]", queueItem.NzbName, queueItem.NzbId);
|
||||
_logger.Warn("Failed to remove item from NZBGet, {0} [{1}]", queueItem.NzbName, queueItem.NzbId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,13 +183,13 @@ public void RemoveItem(string id, NzbgetSettings settings)
|
||||
{
|
||||
if (!EditQueue("HistoryDelete", 0, "", historyItem.Id, settings))
|
||||
{
|
||||
_logger.Warn("Failed to remove item from nzbget history, {0} [{1}]", historyItem.Name, historyItem.Id);
|
||||
_logger.Warn("Failed to remove item from NZBGet history, {0} [{1}]", historyItem.Name, historyItem.Id);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_logger.Warn("Unable to remove item from nzbget, Unknown ID: {0}", id);
|
||||
_logger.Warn("Unable to remove item from NZBGet, Unknown ID: {0}", id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -235,21 +235,21 @@ private T ProcessRequest<T>(NzbgetSettings settings, string method, params objec
|
||||
{
|
||||
if (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
throw new DownloadClientException("Authentication failed for NzbGet, please check your settings", ex);
|
||||
throw new DownloadClientException("Authentication failed for NZBGet, please check your settings", ex);
|
||||
}
|
||||
|
||||
throw new DownloadClientException("Unable to connect to NzbGet. " + ex.Message, ex);
|
||||
throw new DownloadClientException("Unable to connect to NZBGet. " + ex.Message, ex);
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
throw new DownloadClientException("Unable to connect to NzbGet. " + ex.Message, ex);
|
||||
throw new DownloadClientException("Unable to connect to NZBGet. " + ex.Message, ex);
|
||||
}
|
||||
|
||||
var result = Json.Deserialize<JsonRpcResponse<T>>(response.Content);
|
||||
|
||||
if (result.Error != null)
|
||||
{
|
||||
throw new DownloadClientException("Error response received from nzbget: {0}", result.Error.ToString());
|
||||
throw new DownloadClientException("Error response received from NZBGet: {0}", result.Error.ToString());
|
||||
}
|
||||
|
||||
return result.Result;
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
namespace NzbDrone.Core.Download.Clients.Nzbget
|
||||
{
|
||||
public class NzbgetResponse<T>
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
@ -14,7 +14,7 @@ public NzbgetSettingsValidator()
|
||||
RuleFor(c => c.Username).NotEmpty().When(c => !string.IsNullOrWhiteSpace(c.Password));
|
||||
RuleFor(c => c.Password).NotEmpty().When(c => !string.IsNullOrWhiteSpace(c.Username));
|
||||
|
||||
RuleFor(c => c.TvCategory).NotEmpty().WithMessage("A category is recommended").AsWarning();
|
||||
RuleFor(c => c.MovieCategory).NotEmpty().WithMessage("A category is recommended").AsWarning();
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ public NzbgetSettings()
|
||||
{
|
||||
Host = "localhost";
|
||||
Port = 6789;
|
||||
TvCategory = "Movies";
|
||||
MovieCategory = "Movies";
|
||||
Username = "nzbget";
|
||||
Password = "tegbzn6789";
|
||||
RecentTvPriority = (int)NzbgetPriority.Normal;
|
||||
@ -46,7 +46,7 @@ public NzbgetSettings()
|
||||
public string Password { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||
public string TvCategory { get; set; }
|
||||
public string MovieCategory { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing releases that aired within the last 14 days")]
|
||||
public int RecentTvPriority { get; set; }
|
||||
@ -57,7 +57,7 @@ public NzbgetSettings()
|
||||
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
|
||||
public bool UseSsl { get; set; }
|
||||
|
||||
[FieldDefinition(8, Label = "Add Paused", Type = FieldType.Checkbox, HelpText = "This option requires at least NzbGet version 16.0")]
|
||||
[FieldDefinition(8, Label = "Add Paused", Type = FieldType.Checkbox, HelpText = "This option requires at least NZBGet version 16.0")]
|
||||
public bool AddPaused { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
|
@ -50,6 +50,8 @@ protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash
|
||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.MovieCategory, Settings);
|
||||
}
|
||||
|
||||
SetInitialState(hash.ToLower());
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -62,6 +64,8 @@ protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string has
|
||||
_proxy.SetTorrentLabel(hash.ToLower(), Settings.MovieCategory, Settings);
|
||||
}
|
||||
|
||||
SetInitialState(hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -261,5 +265,28 @@ private ValidationFailure TestGetTorrents()
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void SetInitialState(string hash)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch ((QBittorrentState)Settings.InitialState)
|
||||
{
|
||||
case QBittorrentState.ForceStart:
|
||||
_proxy.SetForceStart(hash, true, Settings);
|
||||
break;
|
||||
case QBittorrentState.Start:
|
||||
_proxy.ResumeTorrent(hash, Settings);
|
||||
break;
|
||||
case QBittorrentState.Pause:
|
||||
_proxy.PauseTorrent(hash, Settings);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Failed to set inital state for {0}.", hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ public interface IQBittorrentProxy
|
||||
void RemoveTorrent(string hash, Boolean removeData, QBittorrentSettings settings);
|
||||
void SetTorrentLabel(string hash, string label, QBittorrentSettings settings);
|
||||
void MoveTorrentToTopInQueue(string hash, QBittorrentSettings settings);
|
||||
void PauseTorrent(string hash, QBittorrentSettings settings);
|
||||
void ResumeTorrent(string hash, QBittorrentSettings settings);
|
||||
void SetForceStart(string hash, bool enabled, QBittorrentSettings settings);
|
||||
}
|
||||
|
||||
public class QBittorrentProxy : IQBittorrentProxy
|
||||
@ -154,6 +157,34 @@ public void MoveTorrentToTopInQueue(string hash, QBittorrentSettings settings)
|
||||
|
||||
}
|
||||
|
||||
public void PauseTorrent(string hash, QBittorrentSettings settings)
|
||||
{
|
||||
var request = BuildRequest(settings).Resource("/command/pause")
|
||||
.Post()
|
||||
.AddFormParameter("hash", hash);
|
||||
|
||||
ProcessRequest(request, settings);
|
||||
}
|
||||
|
||||
public void ResumeTorrent(string hash, QBittorrentSettings settings)
|
||||
{
|
||||
var request = BuildRequest(settings).Resource("/command/resume")
|
||||
.Post()
|
||||
.AddFormParameter("hash", hash);
|
||||
|
||||
ProcessRequest(request, settings);
|
||||
}
|
||||
|
||||
public void SetForceStart(string hash, bool enabled, QBittorrentSettings settings)
|
||||
{
|
||||
var request = BuildRequest(settings).Resource("/command/setForceStart")
|
||||
.Post()
|
||||
.AddFormParameter("hashes", hash)
|
||||
.AddFormParameter("value", enabled ? "true": "false");
|
||||
|
||||
ProcessRequest(request, settings);
|
||||
}
|
||||
|
||||
private HttpRequestBuilder BuildRequest(QBittorrentSettings settings)
|
||||
{
|
||||
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port);
|
||||
|
@ -1,4 +1,4 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
@ -21,7 +21,7 @@ public class QBittorrentSettings : IProviderConfig
|
||||
public QBittorrentSettings()
|
||||
{
|
||||
Host = "localhost";
|
||||
Port = 9091;
|
||||
Port = 8080;
|
||||
MovieCategory = "radarr";
|
||||
}
|
||||
|
||||
@ -40,7 +40,10 @@ public QBittorrentSettings()
|
||||
[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 MovieCategory { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection. See Options -> Web UI -> 'Use HTTPS instead of HTTP' in qBittorrent.")]
|
||||
[FieldDefinition(5, Label = "Initial State", Type = FieldType.Select, SelectOptions = typeof(QBittorrentState), HelpText = "Initial state for torrents added to qBittorrent")]
|
||||
public int InitialState { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection. See Options -> Web UI -> 'Use HTTPS instead of HTTP' in qBittorrent.")]
|
||||
public bool UseSsl { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
|
@ -0,0 +1,9 @@
|
||||
namespace NzbDrone.Core.Download.Clients.QBittorrent
|
||||
{
|
||||
public enum QBittorrentState
|
||||
{
|
||||
Start = 0,
|
||||
ForceStart = 1,
|
||||
Pause = 2
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -39,7 +39,7 @@ protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string fil
|
||||
|
||||
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents)
|
||||
{
|
||||
var category = Settings.TvCategory;
|
||||
var category = Settings.MovieCategory;
|
||||
var priority = Settings.RecentTvPriority;
|
||||
|
||||
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
|
||||
@ -119,7 +119,7 @@ private IEnumerable<DownloadClientItem> GetHistory()
|
||||
|
||||
try
|
||||
{
|
||||
sabHistory = _proxy.GetHistory(0, _configService.DownloadClientHistoryLimit, Settings.TvCategory, Settings);
|
||||
sabHistory = _proxy.GetHistory(0, _configService.DownloadClientHistoryLimit, Settings.MovieCategory, Settings);
|
||||
}
|
||||
catch (DownloadClientException ex)
|
||||
{
|
||||
@ -200,7 +200,7 @@ public override IEnumerable<DownloadClientItem> GetItems()
|
||||
{
|
||||
foreach (var downloadClientItem in GetQueue().Concat(GetHistory()))
|
||||
{
|
||||
if (downloadClientItem.Category == Settings.TvCategory || downloadClientItem.Category == "*" && Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
if (downloadClientItem.Category == Settings.MovieCategory || downloadClientItem.Category == "*" && Settings.MovieCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
yield return downloadClientItem;
|
||||
}
|
||||
@ -254,7 +254,7 @@ public override DownloadClientStatus GetStatus()
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
var categories = GetCategories(config).ToArray();
|
||||
|
||||
var category = categories.FirstOrDefault(v => v.Name == Settings.TvCategory);
|
||||
var category = categories.FirstOrDefault(v => v.Name == Settings.MovieCategory);
|
||||
|
||||
if (category == null)
|
||||
{
|
||||
@ -366,7 +366,7 @@ private ValidationFailure TestConnectionAndVersion()
|
||||
|
||||
if (rawVersion.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
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,
|
||||
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
|
||||
@ -419,10 +419,10 @@ private ValidationFailure TestGlobalConfig()
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
if (config.Misc.pre_check && !HasVersion(1, 1))
|
||||
{
|
||||
return new NzbDroneValidationFailure("", "Disable 'Check before download' option in Sabnbzd")
|
||||
return new NzbDroneValidationFailure("", "Disable 'Check before download' option in SABnzbd")
|
||||
{
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/switches/", Settings.Host, Settings.Port),
|
||||
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."
|
||||
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."
|
||||
};
|
||||
}
|
||||
|
||||
@ -432,52 +432,52 @@ private ValidationFailure TestGlobalConfig()
|
||||
private ValidationFailure TestCategory()
|
||||
{
|
||||
var config = _proxy.GetConfig(Settings);
|
||||
var category = GetCategories(config).FirstOrDefault((SabnzbdCategory v) => v.Name == Settings.TvCategory);
|
||||
var category = GetCategories(config).FirstOrDefault((SabnzbdCategory v) => v.Name == Settings.MovieCategory);
|
||||
|
||||
if (category != null)
|
||||
{
|
||||
if (category.Dir.EndsWith("*"))
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "Enable Job folders")
|
||||
return new NzbDroneValidationFailure("MovieCategory", "Enable Job folders")
|
||||
{
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port),
|
||||
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."
|
||||
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."
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Settings.TvCategory.IsNullOrWhiteSpace())
|
||||
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "Category does not exist")
|
||||
return new NzbDroneValidationFailure("MovieCategory", "Category does not exist")
|
||||
{
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/categories/", Settings.Host, Settings.Port),
|
||||
DetailedDescription = "The Category your entered doesn't exist in Sabnzbd. Go to Sabnzbd to create it."
|
||||
DetailedDescription = "The category you entered doesn't exist in SABnzbd. Go to SABnzbd to create it."
|
||||
};
|
||||
}
|
||||
}
|
||||
if (config.Misc.enable_tv_sorting && ContainsCategory(config.Misc.tv_categories, Settings.TvCategory))
|
||||
if (config.Misc.enable_tv_sorting && ContainsCategory(config.Misc.tv_categories, Settings.MovieCategory))
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "Disable TV Sorting")
|
||||
return new NzbDroneValidationFailure("MovieCategory", "Disable TV Sorting")
|
||||
{
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||
DetailedDescription = "You must disable Sabnzbd TV Sorting for the category Radarr 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."
|
||||
};
|
||||
}
|
||||
if (config.Misc.enable_movie_sorting && ContainsCategory(config.Misc.movie_categories, Settings.TvCategory))
|
||||
if (config.Misc.enable_movie_sorting && ContainsCategory(config.Misc.movie_categories, Settings.MovieCategory))
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "Disable Movie Sorting")
|
||||
return new NzbDroneValidationFailure("MovieCategory", "Disable Movie Sorting")
|
||||
{
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||
DetailedDescription = "You must disable Sabnzbd Movie Sorting for the category Radarr 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."
|
||||
};
|
||||
}
|
||||
if (config.Misc.enable_date_sorting && ContainsCategory(config.Misc.date_categories, Settings.TvCategory))
|
||||
if (config.Misc.enable_date_sorting && ContainsCategory(config.Misc.date_categories, Settings.MovieCategory))
|
||||
{
|
||||
return new NzbDroneValidationFailure("TvCategory", "Disable Date Sorting")
|
||||
return new NzbDroneValidationFailure("MovieCategory", "Disable Date Sorting")
|
||||
{
|
||||
InfoLink = string.Format("http://{0}:{1}/sabnzbd/config/sorting/", Settings.Host, Settings.Port),
|
||||
DetailedDescription = "You must disable Sabnzbd Date Sorting for the category Radarr 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."
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using FluentValidation;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
@ -24,7 +24,7 @@ public SabnzbdSettingsValidator()
|
||||
.WithMessage("Password is required when API key is not configured")
|
||||
.When(c => string.IsNullOrWhiteSpace(c.ApiKey));
|
||||
|
||||
RuleFor(c => c.TvCategory).NotEmpty()
|
||||
RuleFor(c => c.MovieCategory).NotEmpty()
|
||||
.WithMessage("A category is recommended")
|
||||
.AsWarning();
|
||||
}
|
||||
@ -38,7 +38,7 @@ public SabnzbdSettings()
|
||||
{
|
||||
Host = "localhost";
|
||||
Port = 8080;
|
||||
TvCategory = "movies";
|
||||
MovieCategory = "movies";
|
||||
RecentTvPriority = (int)SabnzbdPriority.Default;
|
||||
OlderTvPriority = (int)SabnzbdPriority.Default;
|
||||
}
|
||||
@ -59,7 +59,7 @@ public SabnzbdSettings()
|
||||
public string Password { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||
public string TvCategory { get; set; }
|
||||
public string MovieCategory { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing releases that aired within the last 14 days")]
|
||||
public int RecentTvPriority { get; set; }
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Disk;
|
||||
@ -49,7 +49,7 @@ protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string
|
||||
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
|
||||
{
|
||||
_proxy.AddTorrentFromUrl(magnetLink, Settings);
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
|
||||
|
||||
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
@ -59,13 +59,15 @@ protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash
|
||||
_proxy.MoveTorrentToTopInQueue(hash, Settings);
|
||||
}*/
|
||||
|
||||
_proxy.SetState(hash, (UTorrentState)Settings.IntialState, Settings);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
|
||||
{
|
||||
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
|
||||
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
|
||||
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
|
||||
|
||||
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
|
||||
|
||||
@ -75,6 +77,8 @@ protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string has
|
||||
_proxy.MoveTorrentToTopInQueue(hash, Settings);
|
||||
}*/
|
||||
|
||||
_proxy.SetState(hash, (UTorrentState)Settings.IntialState, Settings);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -86,7 +90,7 @@ public override IEnumerable<DownloadClientItem> GetItems()
|
||||
|
||||
try
|
||||
{
|
||||
var cacheKey = string.Format("{0}:{1}:{2}", Settings.Host, Settings.Port, Settings.TvCategory);
|
||||
var cacheKey = string.Format("{0}:{1}:{2}", Settings.Host, Settings.Port, Settings.MovieCategory);
|
||||
var cache = _torrentCache.Find(cacheKey);
|
||||
|
||||
var response = _proxy.GetTorrents(cache == null ? null : cache.CacheID, Settings);
|
||||
@ -123,7 +127,7 @@ public override IEnumerable<DownloadClientItem> GetItems()
|
||||
|
||||
foreach (var torrent in torrents)
|
||||
{
|
||||
if (torrent.Label != Settings.TvCategory)
|
||||
if (torrent.Label != Settings.MovieCategory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -205,7 +209,7 @@ public override DownloadClientStatus GetStatus()
|
||||
|
||||
if (config.GetValueOrDefault("dir_add_label") == "true")
|
||||
{
|
||||
destDir = destDir + Settings.TvCategory;
|
||||
destDir = destDir + Settings.MovieCategory;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ public interface IUTorrentProxy
|
||||
void RemoveTorrent(string hash, bool removeData, UTorrentSettings settings);
|
||||
void SetTorrentLabel(string hash, string label, UTorrentSettings settings);
|
||||
void MoveTorrentToTopInQueue(string hash, UTorrentSettings settings);
|
||||
void SetState(string hash, UTorrentState state, UTorrentSettings settings);
|
||||
}
|
||||
|
||||
public class UTorrentProxy : IUTorrentProxy
|
||||
@ -157,6 +158,15 @@ public void MoveTorrentToTopInQueue(string hash, UTorrentSettings settings)
|
||||
ProcessRequest(requestBuilder, settings);
|
||||
}
|
||||
|
||||
public void SetState(string hash, UTorrentState state, UTorrentSettings settings)
|
||||
{
|
||||
var requestBuilder = BuildRequest(settings)
|
||||
.AddQueryParam("action", state.ToString().ToLowerInvariant())
|
||||
.AddQueryParam("hash", hash);
|
||||
|
||||
ProcessRequest(requestBuilder, settings);
|
||||
}
|
||||
|
||||
private HttpRequestBuilder BuildRequest(UTorrentSettings settings)
|
||||
{
|
||||
var requestBuilder = new HttpRequestBuilder(false, settings.Host, settings.Port)
|
||||
|
@ -11,7 +11,7 @@ public UTorrentSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Host).ValidHost();
|
||||
RuleFor(c => c.Port).InclusiveBetween(1, 65535);
|
||||
RuleFor(c => c.TvCategory).NotEmpty();
|
||||
RuleFor(c => c.MovieCategory).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,8 +22,8 @@ public class UTorrentSettings : IProviderConfig
|
||||
public UTorrentSettings()
|
||||
{
|
||||
Host = "localhost";
|
||||
Port = 9091;
|
||||
TvCategory = "radarr";
|
||||
Port = 8080;
|
||||
MovieCategory = "radarr";
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
|
||||
@ -39,7 +39,7 @@ public UTorrentSettings()
|
||||
public string Password { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
|
||||
public string TvCategory { get; set; }
|
||||
public string MovieCategory { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(UTorrentPriority), HelpText = "Priority to use when grabbing releases that aired within the last 14 days")]
|
||||
public int RecentTvPriority { get; set; }
|
||||
@ -47,6 +47,9 @@ public UTorrentSettings()
|
||||
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(UTorrentPriority), HelpText = "Priority to use when grabbing releases that aired over 14 days ago")]
|
||||
public int OlderTvPriority { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "Initial State", Type = FieldType.Select, SelectOptions = typeof(UTorrentState), HelpText = "Initial state for torrents added to uTorrent")]
|
||||
public int IntialState { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
10
src/NzbDrone.Core/Download/Clients/uTorrent/UtorrentState.cs
Normal file
10
src/NzbDrone.Core/Download/Clients/uTorrent/UtorrentState.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace NzbDrone.Core.Download.Clients.UTorrent
|
||||
{
|
||||
public enum UTorrentState
|
||||
{
|
||||
Start = 0,
|
||||
ForceStart = 1,
|
||||
Pause = 2,
|
||||
Stop = 3
|
||||
}
|
||||
}
|
@ -27,19 +27,13 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC
|
||||
|
||||
private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
|
||||
{
|
||||
var onlyInternal = "";
|
||||
if (Settings.Internal)
|
||||
{
|
||||
onlyInternal = "&internal=true";
|
||||
}
|
||||
|
||||
if (searchParameters != null)
|
||||
{
|
||||
yield return new IndexerRequest($"{Settings.BaseUrl.Trim().TrimEnd('/')}/searchapi.php?action=imdbsearch&passkey={Settings.Passkey.Trim()}&imdb={searchParameters}", HttpAccept.Rss);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new IndexerRequest($"{Settings.BaseUrl.Trim().TrimEnd('/')}/searchapi.php?action=latestmovies&passkey={Settings.Passkey.Trim()}{onlyInternal}", HttpAccept.Rss);
|
||||
yield return new IndexerRequest($"{Settings.BaseUrl.Trim().TrimEnd('/')}/searchapi.php?action=latestmovies&passkey={Settings.Passkey.Trim()}", HttpAccept.Rss);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
using FluentValidation;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
@ -30,11 +32,11 @@ public AwesomeHDSettings()
|
||||
[FieldDefinition(1, Label = "Passkey")]
|
||||
public string Passkey { get; set; }
|
||||
|
||||
[FieldDefinition(2, Type = FieldType.Checkbox, Label = "Require Internal", HelpText = "Will only include internal releases for RSS Sync.")]
|
||||
public bool Internal { get; set; }
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
[FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -82,15 +82,6 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
});
|
||||
}
|
||||
|
||||
// order by internal
|
||||
if (_settings.PreferInternal)
|
||||
{
|
||||
return
|
||||
torrentInfos.OrderByDescending(o => o.PublishDate)
|
||||
.ThenBy(o => ((dynamic)o).Internal ? 0 : 1)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
return torrentInfos.ToArray();
|
||||
}
|
||||
|
||||
|
@ -63,12 +63,6 @@ private IEnumerable<IndexerRequest> GetRequest(TorrentQuery query)
|
||||
query.Codec = Settings.Codecs.ToArray();
|
||||
query.Medium = Settings.Mediums.ToArray();
|
||||
|
||||
// Require Internal only if came from RSS sync
|
||||
if (Settings.RequireInternal && query.ImdbInfo == null)
|
||||
{
|
||||
query.Origin = 1;
|
||||
}
|
||||
|
||||
request.SetContent(query.ToJson());
|
||||
|
||||
yield return new IndexerRequest(request);
|
||||
|
@ -6,6 +6,7 @@
|
||||
using System.Linq.Expressions;
|
||||
using FluentValidation.Results;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.HDBits
|
||||
{
|
||||
@ -41,23 +42,20 @@ public HDBitsSettings()
|
||||
[FieldDefinition(2, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since your API key will be sent to that host.")]
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "Prefer Internal", Type = FieldType.Checkbox, HelpText = "Favors Internal releases over all other releases.")]
|
||||
public bool PreferInternal { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Require Internal", Type = FieldType.Checkbox, HelpText = "Require Internal releases for release to be accepted.")]
|
||||
public bool RequireInternal { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Categories", Type = FieldType.Tag, SelectOptions = typeof(HdBitsCategory), Advanced = true, HelpText = "Options: Movie, TV, Documentary, Music, Sport, Audio, XXX, MiscDemo. If unspecified, all options are used.")]
|
||||
[FieldDefinition(3, Label = "Categories", Type = FieldType.Tag, SelectOptions = typeof(HdBitsCategory), Advanced = true, HelpText = "Options: Movie, TV, Documentary, Music, Sport, Audio, XXX, MiscDemo. If unspecified, all options are used.")]
|
||||
public IEnumerable<int> Categories { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Codecs", Type = FieldType.Tag, SelectOptions = typeof(HdBitsCodec), Advanced = true, HelpText = "Options: h264, Mpeg2, VC1, Xvid. If unspecified, all options are used.")]
|
||||
[FieldDefinition(4, Label = "Codecs", Type = FieldType.Tag, SelectOptions = typeof(HdBitsCodec), Advanced = true, HelpText = "Options: h264, Mpeg2, VC1, Xvid. If unspecified, all options are used.")]
|
||||
public IEnumerable<int> Codecs { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "Mediums", Type = FieldType.Tag, SelectOptions = typeof(HdBitsMedium), Advanced = true, HelpText = "Options: BluRay, Encode, Capture, Remux, WebDL. If unspecified, all options are used.")]
|
||||
[FieldDefinition(5, Label = "Mediums", Type = FieldType.Tag, SelectOptions = typeof(HdBitsMedium), Advanced = true, HelpText = "Options: BluRay, Encode, Capture, Remux, WebDL. If unspecified, all options are used.")]
|
||||
public IEnumerable<int> Mediums { get; set; }
|
||||
|
||||
[FieldDefinition(8, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
[FieldDefinition(6, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(7, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -1,7 +1,9 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
@ -36,6 +38,9 @@ public IPTorrentsSettings()
|
||||
|
||||
[FieldDefinition(1, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(2, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -1,7 +1,10 @@
|
||||
namespace NzbDrone.Core.Indexers
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
public interface ITorrentIndexerSettings : IIndexerSettings
|
||||
{
|
||||
int MinimumSeeders { get; set; }
|
||||
IEnumerable<int> RequiredFlags { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Validation;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Nyaa
|
||||
{
|
||||
public class NyaaSettingsValidator : AbstractValidator<NyaaSettings>
|
||||
@ -32,6 +35,9 @@ public NyaaSettings()
|
||||
|
||||
[FieldDefinition(2, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -73,8 +73,7 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
}
|
||||
|
||||
// Only add approved torrents
|
||||
if (_settings.RequireApproved && torrent.Checked)
|
||||
{
|
||||
|
||||
torrentInfos.Add(new PassThePopcornInfo()
|
||||
{
|
||||
Guid = string.Format("PassThePopcorn-{0}", id),
|
||||
@ -91,67 +90,10 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
|
||||
IndexerFlags = flags
|
||||
});
|
||||
}
|
||||
|
||||
// Add all torrents
|
||||
else if (!_settings.RequireApproved)
|
||||
{
|
||||
torrentInfos.Add(new PassThePopcornInfo()
|
||||
{
|
||||
Guid = string.Format("PassThePopcorn-{0}", id),
|
||||
Title = title,
|
||||
Size = long.Parse(torrent.Size),
|
||||
DownloadUrl = GetDownloadUrl(id, jsonResponse.AuthKey, jsonResponse.PassKey),
|
||||
InfoUrl = GetInfoUrl(result.GroupId, id),
|
||||
Seeders = int.Parse(torrent.Seeders),
|
||||
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
|
||||
PublishDate = torrent.UploadTime.ToUniversalTime(),
|
||||
Golden = torrent.GoldenPopcorn,
|
||||
Scene = torrent.Scene,
|
||||
Approved = torrent.Checked,
|
||||
ImdbId = (result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0),
|
||||
IndexerFlags = flags
|
||||
});
|
||||
}
|
||||
// Don't add any torrents
|
||||
else if (_settings.RequireApproved && !torrent.Checked)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prefer golden
|
||||
if (_settings.Golden)
|
||||
{
|
||||
if (_settings.Scene)
|
||||
{
|
||||
return
|
||||
torrentInfos.OrderByDescending(o => o.PublishDate)
|
||||
.ThenBy(o => ((dynamic)o).Golden ? 0 : 1)
|
||||
.ThenBy(o => ((dynamic)o).Scene ? 0 : 1)
|
||||
.ToArray();
|
||||
}
|
||||
return
|
||||
torrentInfos.OrderByDescending(o => o.PublishDate)
|
||||
.ThenBy(o => ((dynamic)o).Golden ? 0 : 1)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
// prefer scene
|
||||
if (_settings.Scene)
|
||||
{
|
||||
return
|
||||
torrentInfos.OrderByDescending(o => o.PublishDate)
|
||||
.ThenBy(o => ((dynamic)o).Scene ? 0 : 1)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
// order by date
|
||||
return
|
||||
torrentInfos
|
||||
.OrderByDescending(o => o.PublishDate)
|
||||
.ToArray();
|
||||
torrentInfos;
|
||||
|
||||
}
|
||||
|
||||
|
@ -40,10 +40,8 @@ private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
|
||||
var filter = "";
|
||||
if (searchParameters == null)
|
||||
{
|
||||
if (Settings.RequireGolden)
|
||||
{
|
||||
filter = "&scene=2";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
var request =
|
||||
|
@ -1,8 +1,10 @@
|
||||
using FluentValidation;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.PassThePopcorn
|
||||
{
|
||||
@ -39,20 +41,11 @@ public PassThePopcornSettings()
|
||||
[FieldDefinition(3, Label = "Passkey", HelpText = "PTP Passkey")]
|
||||
public string Passkey { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Prefer Golden", Type = FieldType.Checkbox , HelpText = "Favors Golden Popcorn-releases over all other releases.")]
|
||||
public bool Golden { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Prefer Scene", Type = FieldType.Checkbox, HelpText = "Favors scene-releases over non-scene releases.")]
|
||||
public bool Scene { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Require Approved", Type = FieldType.Checkbox, HelpText = "Require staff-approval for releases to be accepted.")]
|
||||
public bool RequireApproved { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "Require Golden", Type = FieldType.Checkbox, HelpText = "Require Golden Popcorn-releases for releases to be accepted.")]
|
||||
public bool RequireGolden { get; set; }
|
||||
|
||||
[FieldDefinition(8, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
[FieldDefinition(4, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(5, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -29,9 +29,10 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
|
||||
if (jsonResponse.Resource.error_code.HasValue)
|
||||
{
|
||||
if (jsonResponse.Resource.error_code == 20 || jsonResponse.Resource.error_code == 8)
|
||||
if (jsonResponse.Resource.error_code == 20 || jsonResponse.Resource.error_code == 8
|
||||
|| jsonResponse.Resource.error_code == 9 || jsonResponse.Resource.error_code == 10)
|
||||
{
|
||||
// No results found
|
||||
// No results or imdbid not found
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,15 @@ private IEnumerable<IndexerRequest> GetMovieRequest(MovieSearchCriteria searchCr
|
||||
|
||||
requestBuilder.AddQueryParam("mode", "search");
|
||||
|
||||
requestBuilder.AddQueryParam("search_imdb", searchCriteria.Movie.ImdbId);
|
||||
if (searchCriteria.Movie.ImdbId != null)
|
||||
{
|
||||
requestBuilder.AddQueryParam("search_imdb", searchCriteria.Movie.ImdbId);
|
||||
}
|
||||
else
|
||||
{
|
||||
requestBuilder.AddQueryParam("search_string", $"{searchCriteria.Movie.Title} {searchCriteria.Movie.Year}");
|
||||
}
|
||||
|
||||
|
||||
if (!Settings.RankedOnly)
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
using FluentValidation;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Rarbg
|
||||
@ -34,6 +36,9 @@ public RarbgSettings()
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(4, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
@ -34,6 +36,9 @@ public TorrentPotatoSettings()
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(4, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
using FluentValidation;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.TorrentRss
|
||||
@ -34,6 +36,9 @@ public TorrentRssIndexerSettings()
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(4, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -1,10 +1,12 @@
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.Indexers.Newznab;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Torznab
|
||||
@ -58,6 +60,9 @@ public TorznabSettings()
|
||||
|
||||
[FieldDefinition(7, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
public int MinimumSeeders { get; set; }
|
||||
|
||||
[FieldDefinition(8, Type = FieldType.Tag, SelectOptions = typeof(IndexerFlags), Label = "Required Flags", HelpText = "What indexer flags are required?", Advanced = true)]
|
||||
public IEnumerable<int> RequiredFlags { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
|
@ -187,7 +187,7 @@ private List<ImportResult> ProcessFolder(DirectoryInfo directoryInfo, ImportMode
|
||||
}
|
||||
}
|
||||
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true, false);
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, null, folderInfo, true, false);
|
||||
var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
||||
|
||||
if ((downloadClientItem == null || !downloadClientItem.IsReadOnly) &&
|
||||
@ -241,7 +241,7 @@ private List<ImportResult> ProcessFile(FileInfo fileInfo, ImportMode importMode,
|
||||
}
|
||||
}
|
||||
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true, false);
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, null, true, false);
|
||||
|
||||
return _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
@ -7,6 +8,6 @@ public interface IImportDecisionEngineSpecification
|
||||
{
|
||||
Decision IsSatisfiedBy(LocalEpisode localEpisode);
|
||||
|
||||
Decision IsSatisfiedBy(LocalMovie localMovie);
|
||||
Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -131,7 +131,7 @@ public List<ImportResult> Import(List<ImportDecision> decisions, bool newDownloa
|
||||
|
||||
if (newDownload)
|
||||
{
|
||||
_eventAggregator.PublishEvent(new MovieDownloadedEvent(localMovie, movieFile, oldFiles));
|
||||
_eventAggregator.PublishEvent(new MovieDownloadedEvent(localMovie, movieFile, oldFiles, downloadClientItem));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -6,6 +6,7 @@
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
@ -20,8 +21,8 @@ public interface IMakeImportDecision
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, bool shouldCheckQuality);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource);
|
||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource);
|
||||
}
|
||||
|
||||
@ -62,12 +63,12 @@ public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series s
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie)
|
||||
{
|
||||
return GetImportDecisions(videoFiles, movie, null, true, false);
|
||||
return GetImportDecisions(videoFiles, movie, null, null, true, false);
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, bool shouldCheckQuality = false)
|
||||
{
|
||||
return GetImportDecisions(videoFiles, movie, null, true, shouldCheckQuality);
|
||||
return GetImportDecisions(videoFiles, movie, null, null, true, shouldCheckQuality);
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource)
|
||||
@ -87,7 +88,7 @@ public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series s
|
||||
return decisions;
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource)
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource)
|
||||
{
|
||||
var newFiles = _mediaFileService.FilterExistingFiles(videoFiles.ToList(), movie);
|
||||
|
||||
@ -98,13 +99,13 @@ public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie mo
|
||||
|
||||
foreach (var file in newFiles)
|
||||
{
|
||||
decisions.AddIfNotNull(GetDecision(file, movie, folderInfo, sceneSource, shouldUseFolderName));
|
||||
decisions.AddIfNotNull(GetDecision(file, movie, downloadClientItem, folderInfo, sceneSource, shouldUseFolderName));
|
||||
}
|
||||
|
||||
return decisions;
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality = false)
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality)
|
||||
{
|
||||
var newFiles = _mediaFileService.FilterExistingFiles(videoFiles.ToList(), movie);
|
||||
|
||||
@ -115,13 +116,13 @@ public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie mo
|
||||
|
||||
foreach (var file in newFiles)
|
||||
{
|
||||
decisions.AddIfNotNull(GetDecision(file, movie, folderInfo, sceneSource, shouldUseFolderName, shouldCheckQuality));
|
||||
decisions.AddIfNotNull(GetDecision(file, movie, downloadClientItem, folderInfo, sceneSource, shouldUseFolderName, shouldCheckQuality));
|
||||
}
|
||||
|
||||
return decisions;
|
||||
}
|
||||
|
||||
private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
|
||||
private ImportDecision GetDecision(string file, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
|
||||
{
|
||||
ImportDecision decision = null;
|
||||
|
||||
@ -136,10 +137,11 @@ private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo fol
|
||||
|
||||
_logger.Debug("Size: {0}", localMovie.Size);
|
||||
var current = localMovie.Quality;
|
||||
localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
|
||||
//TODO: make it so media info doesn't ruin the import process of a new series
|
||||
if (sceneSource && ShouldCheckQualityForParsedQuality(current.Quality))
|
||||
{
|
||||
localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
|
||||
|
||||
if (shouldCheckQuality)
|
||||
{
|
||||
_logger.Debug("Checking quality for this video file to make sure nothing mismatched.");
|
||||
@ -282,11 +284,11 @@ private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo fol
|
||||
|
||||
|
||||
|
||||
decision = GetDecision(localMovie);
|
||||
decision = GetDecision(localMovie, downloadClientItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
decision = GetDecision(localMovie);
|
||||
decision = GetDecision(localMovie, downloadClientItem);
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,9 +315,9 @@ private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo fol
|
||||
return decision;
|
||||
}
|
||||
|
||||
private ImportDecision GetDecision(LocalMovie localMovie)
|
||||
private ImportDecision GetDecision(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
var reasons = _specifications.Select(c => EvaluateSpec(c, localMovie))
|
||||
var reasons = _specifications.Select(c => EvaluateSpec(c, localMovie, downloadClientItem))
|
||||
.Where(c => c != null);
|
||||
|
||||
return new ImportDecision(localMovie, reasons.ToArray());
|
||||
@ -384,11 +386,11 @@ private ImportDecision GetDecision(LocalEpisode localEpisode)
|
||||
return new ImportDecision(localEpisode, reasons.ToArray());
|
||||
}
|
||||
|
||||
private Rejection EvaluateSpec(IImportDecisionEngineSpecification spec, LocalMovie localMovie)
|
||||
private Rejection EvaluateSpec(IImportDecisionEngineSpecification spec, LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = spec.IsSatisfiedBy(localMovie);
|
||||
var result = spec.IsSatisfiedBy(localMovie, downloadClientItem);
|
||||
|
||||
if (!result.Accepted)
|
||||
{
|
||||
|
@ -104,13 +104,19 @@ public List<ManualImportItem> GetMediaFiles(string path, string downloadId)
|
||||
|
||||
private List<ManualImportItem> ProcessFolder(string folder, string downloadId)
|
||||
{
|
||||
DownloadClientItem downloadClientItem = null;
|
||||
var directoryInfo = new DirectoryInfo(folder);
|
||||
var series = _parsingService.GetMovie(directoryInfo.Name);
|
||||
|
||||
if (series == null && downloadId.IsNotNullOrWhiteSpace())
|
||||
if (downloadId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var trackedDownload = _trackedDownloadService.Find(downloadId);
|
||||
series = trackedDownload.RemoteMovie.Movie;
|
||||
downloadClientItem = trackedDownload.DownloadItem;
|
||||
|
||||
if (series == null)
|
||||
{
|
||||
series = trackedDownload.RemoteMovie.Movie;
|
||||
}
|
||||
}
|
||||
|
||||
if (series == null)
|
||||
@ -122,7 +128,7 @@ private List<ManualImportItem> ProcessFolder(string folder, string downloadId)
|
||||
|
||||
var folderInfo = Parser.Parser.ParseMovieTitle(directoryInfo.Name, _config.ParsingLeniency > 0);
|
||||
var seriesFiles = _diskScanService.GetVideoFiles(folder).ToList();
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(seriesFiles, series, folderInfo, SceneSource(series, folder), false);
|
||||
var decisions = _importDecisionMaker.GetImportDecisions(seriesFiles, series, downloadClientItem, folderInfo, SceneSource(series, folder), false);
|
||||
|
||||
return decisions.Select(decision => MapItem(decision, folder, downloadId)).ToList();
|
||||
}
|
||||
@ -134,6 +140,7 @@ private ManualImportItem ProcessFile(string file, string downloadId, string fold
|
||||
folder = new FileInfo(file).Directory.FullName;
|
||||
}
|
||||
|
||||
DownloadClientItem downloadClientItem = null;
|
||||
var relativeFile = folder.GetRelativePath(file);
|
||||
|
||||
var movie = _parsingService.GetMovie(relativeFile.Split('\\', '/')[0]);
|
||||
@ -143,10 +150,15 @@ private ManualImportItem ProcessFile(string file, string downloadId, string fold
|
||||
movie = _parsingService.GetMovie(relativeFile);
|
||||
}
|
||||
|
||||
if (movie == null && downloadId.IsNotNullOrWhiteSpace())
|
||||
if (downloadId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var trackedDownload = _trackedDownloadService.Find(downloadId);
|
||||
movie = trackedDownload.RemoteMovie.Movie;
|
||||
downloadClientItem = trackedDownload.DownloadItem;
|
||||
|
||||
if (movie == null)
|
||||
{
|
||||
movie = trackedDownload.RemoteMovie.Movie;
|
||||
}
|
||||
}
|
||||
|
||||
if (movie == null)
|
||||
@ -162,7 +174,7 @@ private ManualImportItem ProcessFile(string file, string downloadId, string fold
|
||||
}
|
||||
|
||||
var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> { file },
|
||||
movie, null, SceneSource(movie, folder), true);
|
||||
movie, downloadClientItem, null, SceneSource(movie, folder), true);
|
||||
|
||||
return importDecisions.Any() ? MapItem(importDecisions.First(), folder, downloadId) : new ManualImportItem
|
||||
{
|
||||
|
@ -4,6 +4,7 @@
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
@ -64,7 +65,7 @@ public Decision IsSatisfiedBy(LocalEpisode localEpisode)
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie)
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (_configService.SkipFreeSpaceCheckWhenImporting)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
@ -24,7 +25,7 @@ public Decision IsSatisfiedBy(LocalEpisode localEpisode)
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie)
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
@ -0,0 +1,73 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
{
|
||||
public class GrabbedReleaseQualitySpecification : IImportDecisionEngineSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
private readonly IHistoryService _historyService;
|
||||
|
||||
public GrabbedReleaseQualitySpecification(Logger logger, IHistoryService historyService)
|
||||
{
|
||||
_logger = logger;
|
||||
_historyService = historyService;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalEpisode localEpisode)
|
||||
{
|
||||
var qualityComparer = new QualityModelComparer(localEpisode.Series.Profile);
|
||||
if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0))
|
||||
{
|
||||
_logger.Debug("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path);
|
||||
return Decision.Reject("Not an upgrade for existing episode file(s)");
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localEpisode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (downloadClientItem == null)
|
||||
{
|
||||
_logger.Debug("No download client item provided, skipping.");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
var grabbedHistory = _historyService.FindByDownloadId(downloadClientItem.DownloadId)
|
||||
.Where(h => h.EventType == HistoryEventType.Grabbed)
|
||||
.ToList();
|
||||
|
||||
if (grabbedHistory.Empty())
|
||||
{
|
||||
_logger.Debug("No grabbed history for this download client item");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
var parsedReleaseName = Parser.Parser.ParseTitle(grabbedHistory.First().SourceTitle);
|
||||
|
||||
if (parsedReleaseName != null && parsedReleaseName.FullSeason)
|
||||
{
|
||||
_logger.Debug("File is part of a season pack, skipping.");
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
foreach (var item in grabbedHistory)
|
||||
{
|
||||
if (item.Quality.Quality != Quality.Unknown && item.Quality != localEpisode.Quality)
|
||||
{
|
||||
_logger.Debug("Quality for grabbed release ({0}) does not match the quality of the file ({1})", item.Quality, localEpisode.Quality);
|
||||
return Decision.Reject("File quality does not match quality of the grabbed release");
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
@ -16,7 +17,7 @@ public MatchesFolderSpecification(Logger logger)
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie)
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (localMovie.ExistingFile)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
@ -38,7 +39,7 @@ public Decision IsSatisfiedBy(LocalEpisode localEpisode)
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localEpisode)
|
||||
public Decision IsSatisfiedBy(LocalMovie localEpisode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
var sample = _detectSample.IsSample(localEpisode.Movie,
|
||||
localEpisode.Quality,
|
||||
|
@ -5,6 +5,7 @@
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
@ -57,7 +58,7 @@ public Decision IsSatisfiedBy(LocalEpisode localEpisode)
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localEpisode)
|
||||
public Decision IsSatisfiedBy(LocalMovie localEpisode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
if (localEpisode.ExistingFile)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
@ -29,7 +30,7 @@ public Decision IsSatisfiedBy(LocalEpisode localEpisode)
|
||||
return Decision.Reject("Episode file on disk contains more episodes than this file contains");
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie)
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
{
|
||||
@ -14,7 +15,7 @@ public UnverifiedSceneNumberingSpecification(Logger logger)
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie)
|
||||
public Decision IsSatisfiedBy(LocalMovie localMovie, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
@ -27,7 +28,7 @@ public Decision IsSatisfiedBy(LocalEpisode localEpisode)
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
||||
public Decision IsSatisfiedBy(LocalMovie localEpisode)
|
||||
public Decision IsSatisfiedBy(LocalMovie localEpisode, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
return Decision.Accept();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Download;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.Events
|
||||
{
|
||||
@ -9,12 +10,17 @@ public class MovieDownloadedEvent : IEvent
|
||||
public LocalMovie Movie { get; private set; }
|
||||
public MovieFile MovieFile { get; private set; }
|
||||
public List<MovieFile> OldFiles { get; private set; }
|
||||
public string DownloadId { get; private set; }
|
||||
|
||||
public MovieDownloadedEvent(LocalMovie episode, MovieFile episodeFile, List<MovieFile> oldFiles)
|
||||
public MovieDownloadedEvent(LocalMovie episode, MovieFile episodeFile, List<MovieFile> oldFiles, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
Movie = episode;
|
||||
MovieFile = episodeFile;
|
||||
OldFiles = oldFiles;
|
||||
if (downloadClientItem != null)
|
||||
{
|
||||
DownloadId = downloadClientItem.DownloadId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ public Tuple<Series, List<Episode>> GetSeriesInfo(int tvdbSeriesId)
|
||||
|
||||
public Movie GetMovieInfo(int TmdbId, Profile profile = null, bool hasPreDBEntry = false)
|
||||
{
|
||||
var langCode = profile != null ? IsoLanguages.Get(profile.Language).TwoLetterCode : "us";
|
||||
var langCode = profile != null ? IsoLanguages.Get(profile.Language).TwoLetterCode : "en";
|
||||
|
||||
var request = _movieBuilder.Create()
|
||||
.SetSegment("route", "movie")
|
||||
|
@ -34,19 +34,21 @@ public HttpNetImportBase(IHttpClient httpClient, IConfigService configService, I
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public override IList<Movie> Fetch()
|
||||
public override NetImportFetchResult Fetch()
|
||||
{
|
||||
var generator = GetRequestGenerator();
|
||||
return FetchMovies(generator.GetMovies());
|
||||
}
|
||||
|
||||
protected virtual IList<Movie> FetchMovies(NetImportPageableRequestChain pageableRequestChain, bool isRecent = false)
|
||||
protected virtual NetImportFetchResult FetchMovies(NetImportPageableRequestChain pageableRequestChain, bool isRecent = false)
|
||||
{
|
||||
var movies = new List<Movie>();
|
||||
var url = string.Empty;
|
||||
|
||||
var parser = GetParser();
|
||||
|
||||
var anyFailure = false;
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < pageableRequestChain.Tiers; i++)
|
||||
@ -73,6 +75,7 @@ protected virtual IList<Movie> FetchMovies(NetImportPageableRequestChain pageabl
|
||||
}
|
||||
catch (WebException webException)
|
||||
{
|
||||
anyFailure = true;
|
||||
if (webException.Message.Contains("502") || webException.Message.Contains("503") ||
|
||||
webException.Message.Contains("timed out"))
|
||||
{
|
||||
@ -85,6 +88,7 @@ protected virtual IList<Movie> FetchMovies(NetImportPageableRequestChain pageabl
|
||||
}
|
||||
catch (HttpException httpException)
|
||||
{
|
||||
anyFailure = true;
|
||||
if ((int)httpException.Response.StatusCode == 429)
|
||||
{
|
||||
_logger.Warn("API Request Limit reached for {0}", this);
|
||||
@ -96,11 +100,12 @@ protected virtual IList<Movie> FetchMovies(NetImportPageableRequestChain pageabl
|
||||
}
|
||||
catch (Exception feedEx)
|
||||
{
|
||||
anyFailure = true;
|
||||
feedEx.Data.Add("FeedUrl", url);
|
||||
_logger.Error(feedEx, "An error occurred while processing feed. " + url);
|
||||
}
|
||||
|
||||
return movies;
|
||||
return new NetImportFetchResult {Movies = movies, AnyFailure = anyFailure};
|
||||
}
|
||||
|
||||
protected virtual IList<Movie> FetchPage(NetImportRequest request, IParseNetImportResponse parser)
|
||||
|
@ -9,6 +9,6 @@ public interface INetImport : IProvider
|
||||
bool Enabled { get; }
|
||||
bool EnableAuto { get; }
|
||||
|
||||
IList<Movie> Fetch();
|
||||
NetImportFetchResult Fetch();
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ namespace NzbDrone.Core.NetImport.ImportExclusions
|
||||
public interface IImportExclusionsRepository : IBasicRepository<ImportExclusion>
|
||||
{
|
||||
bool IsMovieExcluded(int tmdbid);
|
||||
ImportExclusion GetByTmdbid(int tmdbid);
|
||||
}
|
||||
|
||||
public class ImportExclusionsRepository : BasicRepository<ImportExclusion>, IImportExclusionsRepository
|
||||
@ -31,5 +32,10 @@ public bool IsMovieExcluded(int tmdbid)
|
||||
{
|
||||
return Query.Where(ex => ex.TmdbId == tmdbid).Any();
|
||||
}
|
||||
|
||||
public ImportExclusion GetByTmdbid(int tmdbid)
|
||||
{
|
||||
return Query.Where(ex => ex.TmdbId == tmdbid).First();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,10 @@ public ImportExclusionsService(IImportExclusionsRepository exclusionRepository,
|
||||
|
||||
public ImportExclusion AddExclusion(ImportExclusion exclusion)
|
||||
{
|
||||
if (_exclusionRepository.IsMovieExcluded(exclusion.TmdbId))
|
||||
{
|
||||
return _exclusionRepository.GetByTmdbid(exclusion.TmdbId);
|
||||
}
|
||||
return _exclusionRepository.Insert(exclusion);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,12 @@
|
||||
|
||||
namespace NzbDrone.Core.NetImport
|
||||
{
|
||||
public class NetImportFetchResult
|
||||
{
|
||||
public IList<Movie> Movies { get; set; }
|
||||
public bool AnyFailure { get; set; }
|
||||
}
|
||||
|
||||
public abstract class NetImportBase<TSettings> : INetImport
|
||||
where TSettings : IProviderConfig, new()
|
||||
{
|
||||
@ -20,7 +26,7 @@ public abstract class NetImportBase<TSettings> : INetImport
|
||||
public abstract bool Enabled { get; }
|
||||
public abstract bool EnableAuto { get; }
|
||||
|
||||
public abstract IList<Movie> Fetch();
|
||||
public abstract NetImportFetchResult Fetch();
|
||||
|
||||
public NetImportBase(IConfigService configService, IParsingService parsingService, Logger logger)
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ namespace NzbDrone.Core.NetImport
|
||||
{
|
||||
public interface IFetchNetImport
|
||||
{
|
||||
List<Movie> Fetch(int listId, bool onlyEnableAuto);
|
||||
NetImportFetchResult Fetch(int listId, bool onlyEnableAuto);
|
||||
List<Movie> FetchAndFilter(int listId, bool onlyEnableAuto);
|
||||
}
|
||||
|
||||
@ -54,21 +54,22 @@ public NetImportSearchService(INetImportFactory netImportFactory, IMovieService
|
||||
}
|
||||
|
||||
|
||||
public List<Movie> Fetch(int listId, bool onlyEnableAuto = false)
|
||||
public NetImportFetchResult Fetch(int listId, bool onlyEnableAuto = false)
|
||||
{
|
||||
return MovieListSearch(listId, onlyEnableAuto);
|
||||
}
|
||||
|
||||
public List<Movie> FetchAndFilter(int listId, bool onlyEnableAuto)
|
||||
{
|
||||
var movies = MovieListSearch(listId, onlyEnableAuto);
|
||||
var movies = MovieListSearch(listId, onlyEnableAuto).Movies;
|
||||
|
||||
return _movieService.FilterExistingMovies(movies);
|
||||
return _movieService.FilterExistingMovies(movies.ToList());
|
||||
}
|
||||
|
||||
public List<Movie> MovieListSearch(int listId, bool onlyEnableAuto = false)
|
||||
public NetImportFetchResult MovieListSearch(int listId, bool onlyEnableAuto = false)
|
||||
{
|
||||
var movies = new List<Movie>();
|
||||
var anyFailure = false;
|
||||
|
||||
var importLists = _netImportFactory.GetAvailableProviders();
|
||||
|
||||
@ -81,24 +82,31 @@ public List<Movie> MovieListSearch(int listId, bool onlyEnableAuto = false)
|
||||
|
||||
foreach (var list in lists)
|
||||
{
|
||||
movies.AddRange(list.Fetch());
|
||||
var result = list.Fetch();
|
||||
movies.AddRange(result.Movies);
|
||||
anyFailure |= result.AnyFailure;
|
||||
}
|
||||
|
||||
_logger.Debug("Found {0} movies from list(s) {1}", movies.Count, string.Join(", ", lists.Select(l => l.Definition.Name)));
|
||||
|
||||
return movies.DistinctBy(x => {
|
||||
if (x.TmdbId != 0)
|
||||
{
|
||||
return x.TmdbId.ToString();
|
||||
}
|
||||
return new NetImportFetchResult
|
||||
{
|
||||
Movies = movies.DistinctBy(x =>
|
||||
{
|
||||
if (x.TmdbId != 0)
|
||||
{
|
||||
return x.TmdbId.ToString();
|
||||
}
|
||||
|
||||
if (x.ImdbId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return x.ImdbId;
|
||||
}
|
||||
if (x.ImdbId.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return x.ImdbId;
|
||||
}
|
||||
|
||||
return x.Title;
|
||||
}).ToList();
|
||||
return x.Title;
|
||||
}).ToList(),
|
||||
AnyFailure = anyFailure
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -112,9 +120,13 @@ public void Execute(NetImportSyncCommand message)
|
||||
return;
|
||||
}
|
||||
|
||||
var listedMovies = Fetch(0, true);
|
||||
var result = Fetch(0, true);
|
||||
var listedMovies = result.Movies.ToList();
|
||||
|
||||
CleanLibrary(listedMovies);
|
||||
if (!result.AnyFailure)
|
||||
{
|
||||
CleanLibrary(listedMovies);
|
||||
}
|
||||
|
||||
listedMovies = listedMovies.Where(x => !_movieService.MovieExists(x)).ToList();
|
||||
if (listedMovies.Any())
|
||||
|
@ -36,19 +36,19 @@ public TMDbSettingsValidator()
|
||||
RuleFor(c => c.Ceritification)
|
||||
.Matches(@"^\bNR\b|\bG\b|\bPG\b|\bPG\-13\b|\bR\b|\bNC\-17\b$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.Ceritification.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Not a valid cerification");
|
||||
.WithMessage("Not a valid certification");
|
||||
|
||||
// CSV of numbers
|
||||
RuleFor(c => c.IncludeGenreIds)
|
||||
.Matches(@"^\d+([,]\d+)*$", RegexOptions.IgnoreCase)
|
||||
.Matches(@"^\d+([,|]\d+)*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.IncludeGenreIds.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Genre Ids must be comma separated number ids");
|
||||
.WithMessage("Genre Ids must be comma (,) or pipe (|) separated number ids");
|
||||
|
||||
// CSV of numbers
|
||||
RuleFor(c => c.ExcludeGenreIds)
|
||||
.Matches(@"^\d+([,]\d+)*$", RegexOptions.IgnoreCase)
|
||||
.Matches(@"^\d+([,|]\d+)*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.ExcludeGenreIds.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Genre Ids must be comma separated number ids");
|
||||
.WithMessage("Genre Ids must be comma (,) or pipe (|) separated number ids");
|
||||
|
||||
}
|
||||
}
|
||||
@ -99,4 +99,4 @@ public NzbDroneValidationResult Validate()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +34,6 @@ public override void OnMovieRename(Movie movie)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => "Boxcar";
|
||||
|
||||
public override bool SupportsOnRename => false;
|
||||
|
16
src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs
Normal file → Executable file
16
src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs
Normal file → Executable file
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
@ -31,6 +31,7 @@ public override void OnGrab(GrabMessage message)
|
||||
{
|
||||
var movie = message.Movie;
|
||||
var remoteMovie = message.RemoteMovie;
|
||||
var quality = message.Quality;
|
||||
var environmentVariables = new StringDictionary();
|
||||
|
||||
environmentVariables.Add("Radarr_EventType", "Grab");
|
||||
@ -42,6 +43,8 @@ public override void OnGrab(GrabMessage message)
|
||||
environmentVariables.Add("Radarr_Release_Indexer", remoteMovie.Release.Indexer);
|
||||
environmentVariables.Add("Radarr_Release_Size", remoteMovie.Release.Size.ToString());
|
||||
environmentVariables.Add("Radarr_Release_ReleaseGroup", remoteMovie.ParsedMovieInfo.ReleaseGroup ?? string.Empty);
|
||||
environmentVariables.Add("Radarr_Release_Quality", quality.Quality.Name);
|
||||
environmentVariables.Add("Radarr_Release_QualityVersion", quality.Revision.Version.ToString());
|
||||
|
||||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
@ -54,6 +57,7 @@ public override void OnDownload(DownloadMessage message)
|
||||
var environmentVariables = new StringDictionary();
|
||||
|
||||
environmentVariables.Add("Radarr_EventType", "Download");
|
||||
environmentVariables.Add("Radarr_IsUpgrade", message.OldMovieFiles.Any().ToString());
|
||||
environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString());
|
||||
environmentVariables.Add("Radarr_Movie_Title", movie.Title);
|
||||
environmentVariables.Add("Radarr_Movie_Path", movie.Path);
|
||||
@ -68,7 +72,13 @@ public override void OnDownload(DownloadMessage message)
|
||||
environmentVariables.Add("Radarr_MovieFile_SceneName", movieFile.SceneName ?? string.Empty);
|
||||
environmentVariables.Add("Radarr_MovieFile_SourcePath", sourcePath);
|
||||
environmentVariables.Add("Radarr_MovieFile_SourceFolder", Path.GetDirectoryName(sourcePath));
|
||||
environmentVariables.Add("Radarr_Download_Id", message.DownloadId ?? string.Empty);
|
||||
|
||||
if (message.OldMovieFiles.Any())
|
||||
{
|
||||
environmentVariables.Add("Radarr_DeletedRelativePaths", string.Join("|", message.OldMovieFiles.Select(e => e.RelativePath)));
|
||||
environmentVariables.Add("Radarr_DeletedPaths", string.Join("|", message.OldMovieFiles.Select(e => Path.Combine(movie.Path, e.RelativePath))));
|
||||
}
|
||||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
|
||||
@ -86,10 +96,6 @@ public override void OnMovieRename(Movie movie)
|
||||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
|
||||
public override void OnRename(Series series)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => "Custom Script";
|
||||
|
||||
public override ValidationResult Test()
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
@ -7,13 +7,11 @@ namespace NzbDrone.Core.Notifications
|
||||
public class DownloadMessage
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public Series Series { get; set; }
|
||||
public Movie Movie { get; set; }
|
||||
public EpisodeFile EpisodeFile { get; set; }
|
||||
public List<EpisodeFile> OldFiles { get; set; }
|
||||
public MovieFile MovieFile { get; set; }
|
||||
public List<MovieFile> OldMovieFiles { get; set; }
|
||||
public string SourcePath { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user