mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-11 12:02:35 +02:00
release endpoint now returns fully parsed rss info with decisions.
This commit is contained in:
parent
7e473ca78d
commit
ca8eba9cf1
@ -6,8 +6,10 @@
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.RootFolders;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
@ -21,6 +23,9 @@ public class ResourceMappingFixture : TestBase
|
||||
[TestCase(typeof(RootFolder), typeof(RootFolderResource))]
|
||||
[TestCase(typeof(NamingConfig), typeof(NamingConfigResource))]
|
||||
[TestCase(typeof(IndexerDefinition), typeof(IndexerResource))]
|
||||
[TestCase(typeof(ReportInfo), typeof(ReleaseResource))]
|
||||
[TestCase(typeof(ParsedEpisodeInfo), typeof(ReleaseResource))]
|
||||
[TestCase(typeof(DownloadDecision), typeof(ReleaseResource))]
|
||||
public void matching_fields(Type modelType, Type resourceType)
|
||||
{
|
||||
MappingValidation.ValidateMapping(modelType, resourceType);
|
||||
|
68
NzbDrone.Api/Indexers/ReleaseModule.cs
Normal file
68
NzbDrone.Api/Indexers/ReleaseModule.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser;
|
||||
using Omu.ValueInjecter;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
{
|
||||
public class ReleaseModule : NzbDroneRestModule<ReleaseResource>
|
||||
{
|
||||
private readonly IFetchAndParseRss _rssFetcherAndParser;
|
||||
private readonly IMakeDownloadDecision _downloadDecisionMaker;
|
||||
|
||||
public ReleaseModule(IFetchAndParseRss rssFetcherAndParser, IMakeDownloadDecision downloadDecisionMaker)
|
||||
{
|
||||
_rssFetcherAndParser = rssFetcherAndParser;
|
||||
_downloadDecisionMaker = downloadDecisionMaker;
|
||||
GetResourceAll = GetRss;
|
||||
}
|
||||
|
||||
private List<ReleaseResource> GetRss()
|
||||
{
|
||||
var reports = _rssFetcherAndParser.Fetch();
|
||||
var decisions = _downloadDecisionMaker.GetRssDecision(reports);
|
||||
|
||||
var result = new List<ReleaseResource>();
|
||||
|
||||
foreach (var downloadDecision in decisions)
|
||||
{
|
||||
var release = new ReleaseResource();
|
||||
|
||||
release.InjectFrom(downloadDecision.RemoteEpisode.Report);
|
||||
release.InjectFrom(downloadDecision.RemoteEpisode.ParsedEpisodeInfo);
|
||||
release.InjectFrom(downloadDecision);
|
||||
release.Rejections = downloadDecision.Rejections.ToList();
|
||||
|
||||
result.Add(release);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class ReleaseResource : RestResource
|
||||
{
|
||||
public Int32 Age { get; set; }
|
||||
public Int64 Size { get; set; }
|
||||
public String Indexer { get; set; }
|
||||
public String NzbInfoUrl { get; set; }
|
||||
public String NzbUrl { get; set; }
|
||||
public String ReleaseGroup { get; set; }
|
||||
public String Title { get; set; }
|
||||
public Boolean FullSeason { get; set; }
|
||||
public Boolean SceneSource { get; set; }
|
||||
public Int32 SeasonNumber { get; set; }
|
||||
public Language Language { get; set; }
|
||||
public DateTime? AirDate { get; set; }
|
||||
public String OriginalString { get; set; }
|
||||
public String SeriesTitle { get; set; }
|
||||
public int[] EpisodeNumbers { get; set; }
|
||||
public Boolean Approved { get; set; }
|
||||
public List<string> Rejections { get; set; }
|
||||
}
|
||||
}
|
71
NzbDrone.Api/Mapping/CloneInjection.cs
Normal file
71
NzbDrone.Api/Mapping/CloneInjection.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Mapping
|
||||
{
|
||||
public class CloneInjection : ConventionInjection
|
||||
{
|
||||
protected override bool Match(ConventionInfo conventionInfo)
|
||||
{
|
||||
return conventionInfo.SourceProp.Name == conventionInfo.TargetProp.Name &&
|
||||
conventionInfo.SourceProp.Value != null;
|
||||
}
|
||||
|
||||
protected override object SetValue(ConventionInfo conventionInfo)
|
||||
{
|
||||
//for value types and string just return the value as is
|
||||
if (conventionInfo.SourceProp.Type.IsValueType || conventionInfo.SourceProp.Type == typeof(string))
|
||||
return conventionInfo.SourceProp.Value;
|
||||
|
||||
//handle arrays
|
||||
if (conventionInfo.SourceProp.Type.IsArray)
|
||||
{
|
||||
var array = (Array)conventionInfo.SourceProp.Value;
|
||||
var clone = (Array)array.Clone();
|
||||
|
||||
for (var index = 0; index < array.Length; index++)
|
||||
{
|
||||
var item = array.GetValue(index);
|
||||
if (!item.GetType().IsValueType && !(item is string))
|
||||
{
|
||||
clone.SetValue(Activator.CreateInstance(item.GetType()).InjectFrom<CloneInjection>(item), index);
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
if (conventionInfo.SourceProp.Type.IsGenericType)
|
||||
{
|
||||
//handle IEnumerable<> also ICollection<> IList<> List<>
|
||||
if (conventionInfo.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces().Any(d => d == typeof(IEnumerable)))
|
||||
{
|
||||
var t = conventionInfo.SourceProp.Type.GetGenericArguments()[0];
|
||||
if (t.IsValueType || t == typeof(string)) return conventionInfo.SourceProp.Value;
|
||||
|
||||
var tlist = typeof(List<>).MakeGenericType(t);
|
||||
var list = Activator.CreateInstance(tlist);
|
||||
|
||||
var addMethod = tlist.GetMethod("Add");
|
||||
foreach (var o in (IEnumerable)conventionInfo.SourceProp.Value)
|
||||
{
|
||||
var e = Activator.CreateInstance(t).InjectFrom<CloneInjection>(o);
|
||||
addMethod.Invoke(list, new[] { e }); // in 4.0 you can use dynamic and just do list.Add(e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
//unhandled generic type, you could also return null or throw
|
||||
return conventionInfo.SourceProp.Value;
|
||||
}
|
||||
|
||||
//for simple object types create a new instace and apply the clone injection on it
|
||||
return Activator.CreateInstance(conventionInfo.SourceProp.Type)
|
||||
.InjectFrom<CloneInjection>(conventionInfo.SourceProp.Value);
|
||||
}
|
||||
}
|
||||
}
|
@ -96,6 +96,8 @@
|
||||
<Compile Include="Frontend\StaticResourceMapper.cs" />
|
||||
<Compile Include="Indexers\IndexerModule.cs" />
|
||||
<Compile Include="Indexers\IndexerResource.cs" />
|
||||
<Compile Include="Indexers\ReleaseModule.cs" />
|
||||
<Compile Include="Mapping\CloneInjection.cs" />
|
||||
<Compile Include="Mapping\MappingValidation.cs" />
|
||||
<Compile Include="Mapping\ResourceMappingException.cs" />
|
||||
<Compile Include="Mapping\ValueInjectorExtensions.cs" />
|
||||
|
@ -22,11 +22,12 @@ public static List<Type> ImplementationsOf<T>(this Assembly assembly)
|
||||
|
||||
public static bool IsSimpleType(this Type type)
|
||||
{
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
if (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>) || type.GetGenericTypeDefinition() == typeof(List<>)))
|
||||
{
|
||||
type = type.GetGenericArguments()[0];
|
||||
}
|
||||
|
||||
|
||||
return type.IsPrimitive
|
||||
|| type.IsEnum
|
||||
|| type == typeof(string)
|
||||
|
@ -32,7 +32,6 @@ public class TypeWithAllMappableProperties
|
||||
public class TypeWithNoMappableProperties
|
||||
{
|
||||
public Series Series { get; set; }
|
||||
public List<string> ListOfStrings { get; set; }
|
||||
|
||||
public int ReadOnly { get; private set; }
|
||||
public int WriteOnly { private get; set; }
|
||||
|
@ -27,14 +27,14 @@ public void Setup()
|
||||
parseResultMulti = new RemoteEpisode
|
||||
{
|
||||
Report = new ReportInfo(),
|
||||
Quality = new QualityModel(Quality.SDTV, true),
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.SDTV, true) },
|
||||
Episodes = new List<Episode> { new Episode(), new Episode() }
|
||||
};
|
||||
|
||||
parseResultSingle = new RemoteEpisode
|
||||
{
|
||||
Report = new ReportInfo(),
|
||||
Quality = new QualityModel(Quality.SDTV, true),
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.SDTV, true) },
|
||||
Episodes = new List<Episode> { new Episode() }
|
||||
|
||||
};
|
||||
@ -115,7 +115,7 @@ public void IsAcceptableSize_false_single_episode_not_first_or_last_30_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_false_single_episode_not_first_or_last_60_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultSingle.Series = series60minutes;
|
||||
parseResultSingle.Report.Size = 1.Gigabytes();
|
||||
@ -136,7 +136,7 @@ public void IsAcceptableSize_false_single_episode_not_first_or_last_60_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_true_multi_episode_not_first_or_last_30_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultMulti.Series = series30minutes;
|
||||
parseResultMulti.Report.Size = 184572800;
|
||||
@ -157,7 +157,7 @@ public void IsAcceptableSize_true_multi_episode_not_first_or_last_30_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_true_multi_episode_not_first_or_last_60_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultMulti.Series = series60minutes;
|
||||
parseResultMulti.Report.Size = 368572800;
|
||||
@ -178,7 +178,7 @@ public void IsAcceptableSize_true_multi_episode_not_first_or_last_60_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_false_multi_episode_not_first_or_last_30_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultMulti.Series = series30minutes;
|
||||
parseResultMulti.Report.Size = 1.Gigabytes();
|
||||
@ -199,7 +199,7 @@ public void IsAcceptableSize_false_multi_episode_not_first_or_last_30_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_false_multi_episode_not_first_or_last_60_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultMulti.Series = series60minutes;
|
||||
parseResultMulti.Report.Size = 10.Gigabytes();
|
||||
@ -220,7 +220,7 @@ public void IsAcceptableSize_false_multi_episode_not_first_or_last_60_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_true_single_episode_first_30_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultSingle.Series = series30minutes;
|
||||
parseResultSingle.Report.Size = 184572800;
|
||||
@ -241,7 +241,7 @@ public void IsAcceptableSize_true_single_episode_first_30_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_true_single_episode_first_60_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultSingle.Series = series60minutes;
|
||||
parseResultSingle.Report.Size = 368572800;
|
||||
@ -262,7 +262,7 @@ public void IsAcceptableSize_true_single_episode_first_60_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_false_single_episode_first_30_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultSingle.Series = series30minutes;
|
||||
parseResultSingle.Report.Size = 1.Gigabytes();
|
||||
@ -283,7 +283,7 @@ public void IsAcceptableSize_false_single_episode_first_30_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_false_single_episode_first_60_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultSingle.Series = series60minutes;
|
||||
parseResultSingle.Report.Size = 10.Gigabytes();
|
||||
@ -304,7 +304,7 @@ public void IsAcceptableSize_false_single_episode_first_60_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_true_unlimited_30_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultSingle.Series = series30minutes;
|
||||
parseResultSingle.Report.Size = 18457280000;
|
||||
@ -326,7 +326,7 @@ public void IsAcceptableSize_true_unlimited_30_minute()
|
||||
[Test]
|
||||
public void IsAcceptableSize_true_unlimited_60_minute()
|
||||
{
|
||||
|
||||
|
||||
|
||||
parseResultSingle.Series = series60minutes;
|
||||
parseResultSingle.Report.Size = 36857280000;
|
||||
@ -374,7 +374,7 @@ public void should_return_true_if_RAWHD()
|
||||
{
|
||||
var parseResult = new RemoteEpisode
|
||||
{
|
||||
Quality = new QualityModel(Quality.RAWHD, false)
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.RAWHD, false) },
|
||||
};
|
||||
|
||||
Subject.IsSatisfiedBy(parseResult).Should().BeTrue();
|
||||
|
@ -7,6 +7,7 @@
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
@ -43,10 +44,10 @@ public void Setup()
|
||||
_fail2.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
|
||||
_fail3.Setup(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>())).Returns(false);
|
||||
|
||||
_reports = new List<ReportInfo> { new ReportInfo() };
|
||||
_remoteEpisode = new RemoteEpisode();
|
||||
_reports = new List<ReportInfo> { new ReportInfo { Title = "The.Office.S03E115.DVDRip.XviD-OSiTV" } };
|
||||
_remoteEpisode = new RemoteEpisode { Series = new Series() };
|
||||
|
||||
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ReportInfo>()))
|
||||
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ParsedEpisodeInfo>()))
|
||||
.Returns(_remoteEpisode);
|
||||
|
||||
}
|
||||
@ -102,21 +103,50 @@ public void should_have_same_number_of_rejections_as_specs_that_failed()
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_not_attempt_to_make_decision_if_remote_episode_is_null()
|
||||
public void should_not_attempt_to_map_episode_if_not_parsable()
|
||||
{
|
||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||
|
||||
Mocker.GetMock<IParsingService>().Setup(c => c.Map(It.IsAny<ReportInfo>()))
|
||||
.Returns<RemoteEpisode>(null);
|
||||
_reports[0].Title = "Not parsable";
|
||||
|
||||
var results = Subject.GetRssDecision(_reports).ToList();
|
||||
|
||||
Mocker.GetMock<IParsingService>().Verify(c => c.Map(It.IsAny<ParsedEpisodeInfo>()), Times.Never());
|
||||
|
||||
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
|
||||
results.Should().BeEmpty();
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_not_attempt_to_make_decision_if_series_is_unknow()
|
||||
{
|
||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||
|
||||
_remoteEpisode.Series = null;
|
||||
|
||||
Subject.GetRssDecision(_reports);
|
||||
|
||||
_pass1.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_return_unknow_series_rejectio_if_series_is_unknow()
|
||||
{
|
||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||
|
||||
_remoteEpisode.Series = null;
|
||||
|
||||
var result = Subject.GetRssDecision(_reports);
|
||||
|
||||
result.Should().HaveCount(1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,43 +1,38 @@
|
||||
|
||||
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
[TestFixture]
|
||||
|
||||
|
||||
public class LanguageSpecificationFixture : CoreTest
|
||||
{
|
||||
private RemoteEpisode parseResult;
|
||||
|
||||
private void WithEnglishRelease()
|
||||
{
|
||||
parseResult = Builder<RemoteEpisode>
|
||||
.CreateNew()
|
||||
.With(p => p.Language = Language.English)
|
||||
.Build();
|
||||
parseResult = new RemoteEpisode
|
||||
{
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||
{
|
||||
Language = Language.English
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void WithGermanRelease()
|
||||
{
|
||||
parseResult = Builder<RemoteEpisode>
|
||||
.CreateNew()
|
||||
.With(p => p.Language = Language.German)
|
||||
.Build();
|
||||
parseResult = new RemoteEpisode
|
||||
{
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||
{
|
||||
Language = Language.German
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -1,6 +1,4 @@
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
@ -16,7 +14,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
|
||||
public class QualityAllowedByProfileSpecificationFixture : CoreTest<QualityAllowedByProfileSpecification>
|
||||
{
|
||||
private RemoteEpisode parseResult;
|
||||
private RemoteEpisode remoteEpisode;
|
||||
|
||||
public static object[] AllowedTestCases =
|
||||
{
|
||||
@ -39,29 +37,29 @@ public void Setup()
|
||||
.With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p })
|
||||
.Build();
|
||||
|
||||
parseResult = new RemoteEpisode
|
||||
remoteEpisode = new RemoteEpisode
|
||||
{
|
||||
Series = fakeSeries,
|
||||
Quality = new QualityModel(Quality.DVD, true),
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, true) },
|
||||
};
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("AllowedTestCases")]
|
||||
public void should_allow_if_quality_is_defined_in_profile(Quality qualityType)
|
||||
{
|
||||
parseResult.Quality.Quality = qualityType;
|
||||
parseResult.Series.QualityProfile.Allowed = new List<Quality> { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p };
|
||||
remoteEpisode.ParsedEpisodeInfo.Quality.Quality = qualityType;
|
||||
remoteEpisode.Series.QualityProfile.Allowed = new List<Quality> { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p };
|
||||
|
||||
Subject.IsSatisfiedBy(parseResult).Should().BeTrue();
|
||||
Subject.IsSatisfiedBy(remoteEpisode).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test, TestCaseSource("DeniedTestCases")]
|
||||
public void should_not_allow_if_quality_is_not_defined_in_profile(Quality qualityType)
|
||||
{
|
||||
parseResult.Quality.Quality = qualityType;
|
||||
parseResult.Series.QualityProfile.Allowed = new List<Quality> { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p };
|
||||
remoteEpisode.ParsedEpisodeInfo.Quality.Quality = qualityType;
|
||||
remoteEpisode.Series.QualityProfile.Allowed = new List<Quality> { Quality.DVD, Quality.HDTV720p, Quality.Bluray1080p };
|
||||
|
||||
Subject.IsSatisfiedBy(parseResult).Should().BeFalse();
|
||||
Subject.IsSatisfiedBy(remoteEpisode).Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
@ -44,14 +44,14 @@ public void Setup()
|
||||
parseResultMulti = new RemoteEpisode
|
||||
{
|
||||
Series = fakeSeries,
|
||||
Quality = new QualityModel(Quality.DVD, true),
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, true) },
|
||||
Episodes = doubleEpisodeList
|
||||
};
|
||||
|
||||
parseResultSingle = new RemoteEpisode
|
||||
{
|
||||
Series = fakeSeries,
|
||||
Quality = new QualityModel(Quality.DVD, true),
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, true) },
|
||||
Episodes = singleEpisodeList
|
||||
};
|
||||
}
|
||||
@ -113,7 +113,7 @@ public void should_be_not_upgradable_if_only_second_episodes_is_upgradable()
|
||||
public void should_not_be_upgradable_if_qualities_are_the_same()
|
||||
{
|
||||
firstFile.Quality = new QualityModel(Quality.WEBDL1080p);
|
||||
parseResultSingle.Quality = new QualityModel(Quality.WEBDL1080p, false);
|
||||
parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, false);
|
||||
_upgradeDisk.IsSatisfiedBy(parseResultSingle).Should().BeFalse();
|
||||
}
|
||||
|
||||
|
@ -44,14 +44,14 @@ public void Setup()
|
||||
_parseResultMulti = new RemoteEpisode
|
||||
{
|
||||
Series = _fakeSeries,
|
||||
Quality = new QualityModel(Quality.DVD, true),
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, true) },
|
||||
Episodes = doubleEpisodeList
|
||||
};
|
||||
|
||||
_parseResultSingle = new RemoteEpisode
|
||||
{
|
||||
Series = _fakeSeries,
|
||||
Quality = new QualityModel(Quality.DVD, true),
|
||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, true) },
|
||||
Episodes = singleEpisodeList
|
||||
};
|
||||
|
||||
@ -115,7 +115,7 @@ public void should_be_not_upgradable_if_only_second_episodes_is_upgradable()
|
||||
public void should_not_be_upgradable_if_episode_is_of_same_quality_as_existing()
|
||||
{
|
||||
_fakeSeries.QualityProfile = new QualityProfile { Cutoff = Quality.WEBDL1080p };
|
||||
_parseResultSingle.Quality = new QualityModel(Quality.WEBDL1080p, false);
|
||||
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, false);
|
||||
_upgradableQuality = new QualityModel(Quality.WEBDL1080p, false);
|
||||
|
||||
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(1)).Returns(_upgradableQuality);
|
||||
|
@ -12,11 +12,11 @@
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabProviderTests
|
||||
{
|
||||
[TestFixture]
|
||||
|
||||
public class SabProviderFixture : CoreTest
|
||||
|
||||
public class SabProviderFixture : CoreTest<SabnzbdClient>
|
||||
{
|
||||
private const string url = "http://www.nzbclub.com/nzb_download.aspx?mid=1950232";
|
||||
private const string title = "My Series Name - 5x2-5x3 - My title [Bluray720p] [Proper]";
|
||||
private const string URL = "http://www.nzbclub.com/nzb_download.aspx?mid=1950232";
|
||||
private const string TITLE = "My Series Name - 5x2-5x3 - My title [Bluray720p] [Proper]";
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
@ -44,40 +44,34 @@ public void add_url_should_format_request_properly()
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=0&pp=3&cat=tv&nzbname=My+Series+Name+-+5x2-5x3+-+My+title+%5bBluray720p%5d+%5bProper%5d&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns("{ \"status\": true }");
|
||||
|
||||
|
||||
Mocker.Resolve<SabnzbdClient>().DownloadNzb(url, title, false).Should().BeTrue();
|
||||
|
||||
Subject.DownloadNzb(URL, TITLE, false).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void add_by_url_should_detect_and_handle_sab_errors()
|
||||
{
|
||||
WithFailResponse();
|
||||
|
||||
|
||||
Assert.Throws<ApplicationException>(() => Mocker.Resolve<SabnzbdClient>().DownloadNzb(url, title, false).Should().BeFalse());
|
||||
//ExceptionVerification.ExpectedErrors(1);
|
||||
Assert.Throws<ApplicationException>(() => Subject.DownloadNzb(URL, TITLE, false).Should().BeFalse());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_get_categories_when_config_is_passed_in()
|
||||
{
|
||||
|
||||
|
||||
const string host = "192.168.5.22";
|
||||
const int port = 1111;
|
||||
const string apikey = "5c770e3197e4fe763423ee7c392c25d2";
|
||||
const string username = "admin2";
|
||||
const string password = "pass2";
|
||||
|
||||
|
||||
|
||||
Mocker.GetMock<IHttpProvider>(MockBehavior.Strict)
|
||||
.Setup(s => s.DownloadString("http://192.168.5.22:1111/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d2&ma_username=admin2&ma_password=pass2"))
|
||||
.Returns(ReadAllText("Files","Categories_json.txt"));
|
||||
.Returns(ReadAllText("Files", "Categories_json.txt"));
|
||||
|
||||
var result = Subject.GetCategories(host, port, apikey, username, password);
|
||||
|
||||
|
||||
var result = Mocker.Resolve<SabnzbdClient>().GetCategories(host, port, apikey, username, password);
|
||||
|
||||
|
||||
result.Should().NotBeNull();
|
||||
result.categories.Should().NotBeEmpty();
|
||||
}
|
||||
@ -87,12 +81,12 @@ public void should_be_able_to_get_categories_using_config()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>(MockBehavior.Strict)
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=get_cats&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns(ReadAllText("Files","Categories_json.txt"));
|
||||
.Returns(ReadAllText("Files", "Categories_json.txt"));
|
||||
|
||||
|
||||
var result = Subject.GetCategories();
|
||||
|
||||
|
||||
var result = Mocker.Resolve<SabnzbdClient>().GetCategories();
|
||||
|
||||
|
||||
result.Should().NotBeNull();
|
||||
result.categories.Should().NotBeEmpty();
|
||||
}
|
||||
@ -104,10 +98,10 @@ public void GetHistory_should_return_a_list_with_items_when_the_history_has_item
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns(ReadAllText("Files", "History.txt"));
|
||||
|
||||
|
||||
var result = Mocker.Resolve<SabnzbdClient>().GetHistory();
|
||||
|
||||
|
||||
var result = Subject.GetHistory();
|
||||
|
||||
|
||||
result.Should().HaveCount(1);
|
||||
}
|
||||
|
||||
@ -116,12 +110,12 @@ public void GetHistory_should_return_an_empty_list_when_the_queue_is_empty()
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns(ReadAllText("Files","HistoryEmpty.txt"));
|
||||
.Returns(ReadAllText("Files", "HistoryEmpty.txt"));
|
||||
|
||||
|
||||
var result = Subject.GetHistory();
|
||||
|
||||
|
||||
var result = Mocker.Resolve<SabnzbdClient>().GetHistory();
|
||||
|
||||
|
||||
result.Should().BeEmpty();
|
||||
}
|
||||
|
||||
@ -130,10 +124,10 @@ public void GetHistory_should_return_an_empty_list_when_there_is_an_error_gettin
|
||||
{
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=history&output=json&start=0&limit=0&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns(ReadAllText("Files","JsonError.txt"));
|
||||
.Returns(ReadAllText("Files", "JsonError.txt"));
|
||||
|
||||
|
||||
Assert.Throws<ApplicationException>(() => Mocker.Resolve<SabnzbdClient>().GetHistory(), "API Key Incorrect");
|
||||
|
||||
Assert.Throws<ApplicationException>(() => Subject.GetHistory(), "API Key Incorrect");
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -145,10 +139,10 @@ public void GetVersion_should_return_the_version_using_passed_in_values()
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns(response);
|
||||
|
||||
|
||||
var result = Mocker.Resolve<SabnzbdClient>().GetVersion("192.168.5.55", 2222, "5c770e3197e4fe763423ee7c392c25d1", "admin", "pass");
|
||||
|
||||
|
||||
var result = Subject.GetVersion("192.168.5.55", 2222, "5c770e3197e4fe763423ee7c392c25d1", "admin", "pass");
|
||||
|
||||
|
||||
result.Should().NotBeNull();
|
||||
result.Version.Should().Be("0.6.9");
|
||||
}
|
||||
@ -162,10 +156,10 @@ public void GetVersion_should_return_the_version_using_saved_values()
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns(response);
|
||||
|
||||
|
||||
var result = Mocker.Resolve<SabnzbdClient>().GetVersion();
|
||||
|
||||
|
||||
var result = Subject.GetVersion();
|
||||
|
||||
|
||||
result.Should().NotBeNull();
|
||||
result.Version.Should().Be("0.6.9");
|
||||
}
|
||||
@ -173,16 +167,16 @@ public void GetVersion_should_return_the_version_using_saved_values()
|
||||
[Test]
|
||||
public void Test_should_return_version_as_a_string()
|
||||
{
|
||||
var response = "{ \"version\": \"0.6.9\" }";
|
||||
const string response = "{ \"version\": \"0.6.9\" }";
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=version&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns(response);
|
||||
|
||||
|
||||
var result = Mocker.Resolve<SabnzbdClient>().Test("192.168.5.55", 2222, "5c770e3197e4fe763423ee7c392c25d1", "admin", "pass");
|
||||
|
||||
|
||||
var result = Subject.Test("192.168.5.55", 2222, "5c770e3197e4fe763423ee7c392c25d1", "admin", "pass");
|
||||
|
||||
|
||||
result.Should().Be("0.6.9");
|
||||
}
|
||||
|
||||
@ -192,7 +186,7 @@ public void should_return_false_when_WebException_is_thrown()
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Setup(s => s.DownloadString(It.IsAny<String>())).Throws(new WebException());
|
||||
|
||||
Mocker.Resolve<SabnzbdClient>().DownloadNzb(url, title, false).Should().BeFalse();
|
||||
Subject.DownloadNzb(URL, TITLE, false).Should().BeFalse();
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
}
|
||||
|
||||
@ -211,8 +205,8 @@ public void downloadNzb_should_use_sabRecentTvPriority_when_recentEpisode_is_tru
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=1&pp=3&cat=tv&nzbname=My+Series+Name+-+5x2-5x3+-+My+title+%5bBluray720p%5d+%5bProper%5d&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns("{ \"status\": true }");
|
||||
|
||||
|
||||
Mocker.Resolve<SabnzbdClient>().DownloadNzb(url, title, true).Should().BeTrue();
|
||||
|
||||
Subject.DownloadNzb(URL, TITLE, true).Should().BeTrue();
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Verify(v => v.DownloadString("http://192.168.5.55:2222/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=1&pp=3&cat=tv&nzbname=My+Series+Name+-+5x2-5x3+-+My+title+%5bBluray720p%5d+%5bProper%5d&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"), Times.Once());
|
||||
@ -233,8 +227,8 @@ public void downloadNzb_should_use_sabBackogTvPriority_when_recentEpisode_is_fal
|
||||
.Setup(s => s.DownloadString("http://192.168.5.55:2222/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=-1&pp=3&cat=tv&nzbname=My+Series+Name+-+5x2-5x3+-+My+title+%5bBluray720p%5d+%5bProper%5d&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"))
|
||||
.Returns("{ \"status\": true }");
|
||||
|
||||
|
||||
Mocker.Resolve<SabnzbdClient>().DownloadNzb(url, title, false).Should().BeTrue();
|
||||
|
||||
Subject.DownloadNzb(URL, TITLE, false).Should().BeTrue();
|
||||
|
||||
Mocker.GetMock<IHttpProvider>()
|
||||
.Verify(v => v.DownloadString("http://192.168.5.55:2222/api?mode=addurl&name=http://www.nzbclub.com/nzb_download.aspx?mid=1950232&priority=-1&pp=3&cat=tv&nzbname=My+Series+Name+-+5x2-5x3+-+My+title+%5bBluray720p%5d+%5bProper%5d&output=json&apikey=5c770e3197e4fe763423ee7c392c25d1&ma_username=admin&ma_password=pass"), Times.Once());
|
||||
|
@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
@ -31,7 +28,6 @@ public void Setup()
|
||||
.Build().ToList();
|
||||
|
||||
_parseResult = Builder<RemoteEpisode>.CreateNew()
|
||||
.With(c => c.Quality = new QualityModel(Quality.DVD))
|
||||
.With(c => c.Series = Builder<Series>.CreateNew().Build())
|
||||
.With(c=>c.Report = Builder<ReportInfo>.CreateNew().Build())
|
||||
.With(c => c.Episodes = episodes)
|
||||
|
@ -88,7 +88,6 @@ public void ParseTitle_single(string postTitle, string title, int seasonNumber,
|
||||
result.SeasonNumber.Should().Be(seasonNumber);
|
||||
result.EpisodeNumbers.First().Should().Be(episodeNumber);
|
||||
result.SeriesTitle.Should().Be(Parser.Parser.NormalizeTitle(title));
|
||||
result.OriginalString.Should().Be(postTitle);
|
||||
}
|
||||
|
||||
[TestCase(@"z:\tv shows\battlestar galactica (2003)\Season 3\S03E05 - Collaborators.mkv", 3, 5)]
|
||||
@ -107,7 +106,6 @@ public void PathParse_tests(string path, int season, int episode)
|
||||
result.EpisodeNumbers.Should().HaveCount(1);
|
||||
result.SeasonNumber.Should().Be(season);
|
||||
result.EpisodeNumbers[0].Should().Be(episode);
|
||||
result.OriginalString.Should().Be(path);
|
||||
|
||||
ExceptionVerification.IgnoreWarns();
|
||||
}
|
||||
@ -159,7 +157,6 @@ public void TitleParse_multi(string postTitle, string title, int season, int[] e
|
||||
result.SeasonNumber.Should().Be(season);
|
||||
result.EpisodeNumbers.Should().BeEquivalentTo(episodes);
|
||||
result.SeriesTitle.Should().Be(Parser.Parser.NormalizeTitle(title));
|
||||
result.OriginalString.Should().Be(postTitle);
|
||||
}
|
||||
|
||||
|
||||
@ -181,7 +178,6 @@ public void parse_daily_episodes(string postTitle, string title, int year, int m
|
||||
result.SeriesTitle.Should().Be(Parser.Parser.NormalizeTitle(title));
|
||||
result.AirDate.Should().Be(airDate);
|
||||
result.EpisodeNumbers.Should().BeNull();
|
||||
result.OriginalString.Should().Be(postTitle);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -203,9 +199,8 @@ public void full_season_release_parse(string postTitle, string title, int season
|
||||
var result = Parser.Parser.ParseTitle(postTitle);
|
||||
result.SeasonNumber.Should().Be(season);
|
||||
result.SeriesTitle.Should().Be(Parser.Parser.NormalizeTitle(title));
|
||||
result.EpisodeNumbers.Count.Should().Be(0);
|
||||
result.EpisodeNumbers.Length.Should().Be(0);
|
||||
result.FullSeason.Should().BeTrue();
|
||||
result.OriginalString.Should().Be(postTitle);
|
||||
}
|
||||
|
||||
[TestCase("Conan", "conan")]
|
||||
@ -346,7 +341,6 @@ public void parse_season_info(string postTitle, string seriesName, int seasonNum
|
||||
result.SeriesTitle.Should().Be(Parser.Parser.NormalizeTitle(seriesName));
|
||||
result.SeasonNumber.Should().Be(seasonNumber);
|
||||
result.FullSeason.Should().BeTrue();
|
||||
result.OriginalString.Should().Be(postTitle);
|
||||
}
|
||||
|
||||
[TestCase("Acropolis Now S05 EXTRAS DVDRip XviD RUNNER")]
|
||||
|
@ -408,13 +408,6 @@ public Boolean IgnoreArticlesWhenSortingSeries
|
||||
set { SetValue("IgnoreArticlesWhenSortingSeries", value); }
|
||||
}
|
||||
|
||||
public Boolean DownloadClientUseSceneName
|
||||
{
|
||||
get { return GetValueBoolean("DownloadClientUseSceneName", false); }
|
||||
|
||||
set { SetValue("DownloadClientUseSceneName", value); }
|
||||
}
|
||||
|
||||
public String NzbgetUsername
|
||||
{
|
||||
get { return GetValue("NzbgetUsername", "nzbget"); }
|
||||
|
@ -68,7 +68,6 @@ public interface IConfigService
|
||||
string OmgwtfnzbsUsername { get; set; }
|
||||
string OmgwtfnzbsApiKey { get; set; }
|
||||
Boolean IgnoreArticlesWhenSortingSeries { get; set; }
|
||||
Boolean DownloadClientUseSceneName { get; set; }
|
||||
String NzbgetUsername { get; set; }
|
||||
String NzbgetPassword { get; set; }
|
||||
String NzbgetHost { get; set; }
|
||||
|
@ -1,14 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
public class DownloadDecision
|
||||
{
|
||||
public RemoteEpisode Episode { get; private set; }
|
||||
public RemoteEpisode RemoteEpisode { get; private set; }
|
||||
public IEnumerable<string> Rejections { get; private set; }
|
||||
|
||||
public bool Approved
|
||||
@ -21,7 +19,7 @@ public bool Approved
|
||||
|
||||
public DownloadDecision(RemoteEpisode episode, params string[] rejections)
|
||||
{
|
||||
Episode = episode;
|
||||
RemoteEpisode = episode;
|
||||
Rejections = rejections.ToList();
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications.Search;
|
||||
@ -9,8 +10,8 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
public interface IMakeDownloadDecision
|
||||
{
|
||||
IEnumerable<DownloadDecision> GetRssDecision(IEnumerable<ReportInfo> reports);
|
||||
IEnumerable<DownloadDecision> GetSearchDecision(IEnumerable<ReportInfo> reports, SearchDefinitionBase searchDefinitionBase);
|
||||
List<DownloadDecision> GetRssDecision(IEnumerable<ReportInfo> reports);
|
||||
List<DownloadDecision> GetSearchDecision(IEnumerable<ReportInfo> reports, SearchDefinitionBase searchDefinitionBase);
|
||||
}
|
||||
|
||||
public class DownloadDecisionMaker : IMakeDownloadDecision
|
||||
@ -24,29 +25,19 @@ public DownloadDecisionMaker(IEnumerable<IRejectWithReason> specifications, IPar
|
||||
_parsingService = parsingService;
|
||||
}
|
||||
|
||||
public IEnumerable<DownloadDecision> GetRssDecision(IEnumerable<ReportInfo> reports)
|
||||
public List<DownloadDecision> GetRssDecision(IEnumerable<ReportInfo> reports)
|
||||
{
|
||||
foreach (var report in reports)
|
||||
{
|
||||
var parseResult = _parsingService.Map(report);
|
||||
if (parseResult != null)
|
||||
{
|
||||
|
||||
yield return new DownloadDecision(parseResult, GetGeneralRejectionReasons(parseResult).ToArray());
|
||||
}
|
||||
}
|
||||
return GetDecisions(reports, GetGeneralRejectionReasons).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<DownloadDecision> GetSearchDecision(IEnumerable<ReportInfo> reports, SearchDefinitionBase searchDefinitionBase)
|
||||
public List<DownloadDecision> GetSearchDecision(IEnumerable<ReportInfo> reports, SearchDefinitionBase searchDefinitionBase)
|
||||
{
|
||||
foreach (var report in reports)
|
||||
{
|
||||
var remoteEpisode = _parsingService.Map(report);
|
||||
var generalReasons = GetGeneralRejectionReasons(remoteEpisode);
|
||||
var searchReasons = GetSearchRejectionReasons(remoteEpisode, searchDefinitionBase);
|
||||
|
||||
yield return new DownloadDecision(remoteEpisode, generalReasons.Union(searchReasons).ToArray());
|
||||
}
|
||||
return GetDecisions(reports, remoteEpisode =>
|
||||
{
|
||||
var generalReasons = GetGeneralRejectionReasons(remoteEpisode);
|
||||
var searchReasons = GetSearchRejectionReasons(remoteEpisode, searchDefinitionBase);
|
||||
return generalReasons.Union(searchReasons);
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
|
||||
@ -58,6 +49,29 @@ private IEnumerable<string> GetGeneralRejectionReasons(RemoteEpisode report)
|
||||
.Select(spec => spec.RejectionReason);
|
||||
}
|
||||
|
||||
private IEnumerable<DownloadDecision> GetDecisions(IEnumerable<ReportInfo> reports, Func<RemoteEpisode, IEnumerable<string>> decisionCallback)
|
||||
{
|
||||
foreach (var report in reports)
|
||||
{
|
||||
var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title);
|
||||
|
||||
if (parsedEpisodeInfo != null)
|
||||
{
|
||||
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo);
|
||||
remoteEpisode.Report = report;
|
||||
|
||||
if (remoteEpisode.Series != null)
|
||||
{
|
||||
yield return new DownloadDecision(remoteEpisode, decisionCallback(remoteEpisode).ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new DownloadDecision(remoteEpisode, "Unknown Series");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetSearchRejectionReasons(RemoteEpisode report, SearchDefinitionBase searchDefinitionBase)
|
||||
{
|
||||
return _specifications
|
||||
|
@ -30,13 +30,13 @@ public virtual bool IsSatisfiedBy(RemoteEpisode subject)
|
||||
{
|
||||
_logger.Trace("Beginning size check for: {0}", subject);
|
||||
|
||||
if (subject.Quality.Quality == Quality.RAWHD)
|
||||
if (subject.ParsedEpisodeInfo.Quality.Quality == Quality.RAWHD)
|
||||
{
|
||||
_logger.Trace("Raw-HD release found, skipping size check.");
|
||||
return true;
|
||||
}
|
||||
|
||||
var qualityType = _qualityTypeProvider.Get((int)subject.Quality.Quality);
|
||||
var qualityType = _qualityTypeProvider.Get((int)subject.ParsedEpisodeInfo.Quality.Quality);
|
||||
|
||||
if (qualityType.MaxSize == 0)
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
@ -24,10 +23,10 @@ public string RejectionReason
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject)
|
||||
{
|
||||
_logger.Trace("Checking if report meets language requirements. {0}", subject.Language);
|
||||
if (subject.Language != Language.English)
|
||||
_logger.Trace("Checking if report meets language requirements. {0}", subject.ParsedEpisodeInfo.Language);
|
||||
if (subject.ParsedEpisodeInfo.Language != Language.English)
|
||||
{
|
||||
_logger.Trace("Report Language: {0} rejected because it is not English", subject.Language);
|
||||
_logger.Trace("Report Language: {0} rejected because it is not English", subject.ParsedEpisodeInfo.Language);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
@ -27,7 +24,7 @@ public string RejectionReason
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject)
|
||||
public bool IsSatisfiedBy(RemoteEpisode subject)
|
||||
{
|
||||
var downloadClient = _downloadClientProvider.GetDownloadClient();
|
||||
|
||||
@ -36,25 +33,25 @@ public virtual bool IsSatisfiedBy(RemoteEpisode subject)
|
||||
return !IsInQueue(subject, queue);
|
||||
}
|
||||
|
||||
public virtual bool IsInQueue(RemoteEpisode newEpisode, IEnumerable<ParsedEpisodeInfo> queue)
|
||||
private bool IsInQueue(RemoteEpisode newEpisode, IEnumerable<ParsedEpisodeInfo> queue)
|
||||
{
|
||||
var matchingTitle = queue.Where(q => String.Equals(q.SeriesTitle, newEpisode.Series.CleanTitle, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
var matchingTitleWithQuality = matchingTitle.Where(q => q.Quality >= newEpisode.Quality);
|
||||
var matchingTitleWithQuality = matchingTitle.Where(q => q.Quality >= newEpisode.ParsedEpisodeInfo.Quality);
|
||||
|
||||
if (newEpisode.Series.SeriesType == SeriesTypes.Daily)
|
||||
{
|
||||
return matchingTitleWithQuality.Any(q => q.AirDate.Value.Date == newEpisode.AirDate.Value.Date);
|
||||
return matchingTitleWithQuality.Any(q => q.AirDate.Value.Date == newEpisode.ParsedEpisodeInfo.AirDate.Value.Date);
|
||||
}
|
||||
|
||||
var matchingSeason = matchingTitleWithQuality.Where(q => q.SeasonNumber == newEpisode.SeasonNumber);
|
||||
var matchingSeason = matchingTitleWithQuality.Where(q => q.SeasonNumber == newEpisode.ParsedEpisodeInfo.SeasonNumber);
|
||||
|
||||
if (newEpisode.FullSeason)
|
||||
if (newEpisode.ParsedEpisodeInfo.FullSeason)
|
||||
{
|
||||
return matchingSeason.Any();
|
||||
}
|
||||
|
||||
return matchingSeason.Any(q => q.EpisodeNumbers != null && q.EpisodeNumbers.Any(e => newEpisode.EpisodeNumbers.Contains(e)));
|
||||
return matchingSeason.Any(q => q.EpisodeNumbers != null && q.EpisodeNumbers.Any(e => newEpisode.ParsedEpisodeInfo.EpisodeNumbers.Contains(e)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,10 +24,10 @@ public string RejectionReason
|
||||
|
||||
public virtual bool IsSatisfiedBy(RemoteEpisode subject)
|
||||
{
|
||||
_logger.Trace("Checking if report meets quality requirements. {0}", subject.Quality);
|
||||
if (!subject.Series.QualityProfile.Allowed.Contains(subject.Quality.Quality))
|
||||
_logger.Trace("Checking if report meets quality requirements. {0}", subject.ParsedEpisodeInfo.Quality);
|
||||
if (!subject.Series.QualityProfile.Allowed.Contains(subject.ParsedEpisodeInfo.Quality.Quality))
|
||||
{
|
||||
_logger.Trace("Quality {0} rejected by Series' quality profile", subject.Quality);
|
||||
_logger.Trace("Quality {0} rejected by Series' quality profile", subject.ParsedEpisodeInfo.Quality);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ public bool IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchDefinitionBase sear
|
||||
|
||||
var episode = _episodeService.GetEpisode(dailySearchSpec.SeriesId, dailySearchSpec.Airtime);
|
||||
|
||||
if (!remoteEpisode.AirDate.HasValue || remoteEpisode.AirDate.Value != episode.AirDate.Value)
|
||||
if (!remoteEpisode.ParsedEpisodeInfo.AirDate.HasValue || remoteEpisode.ParsedEpisodeInfo.AirDate.Value.Date != episode.AirDate.Value.Date)
|
||||
{
|
||||
_logger.Trace("Episode AirDate does not match searched episode number, skipping.");
|
||||
return false;
|
||||
|
@ -1,7 +1,5 @@
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
@ -28,7 +26,7 @@ public bool IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchDefinitionBase sear
|
||||
var singleEpisodeSpec = searchDefinitionBase as SeasonSearchDefinition;
|
||||
if (singleEpisodeSpec == null) return true;
|
||||
|
||||
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.SeasonNumber)
|
||||
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
|
||||
{
|
||||
_logger.Trace("Season number does not match searched season number, skipping.");
|
||||
return false;
|
||||
|
@ -1,8 +1,6 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.Search
|
||||
@ -29,7 +27,7 @@ public bool IsSatisfiedBy(RemoteEpisode remoteEpisode, SearchDefinitionBase sear
|
||||
var singleEpisodeSpec = searchDefinitionBase as SingleEpisodeSearchDefinition;
|
||||
if (singleEpisodeSpec == null) return true;
|
||||
|
||||
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.SeasonNumber)
|
||||
if (singleEpisodeSpec.SeasonNumber != remoteEpisode.ParsedEpisodeInfo.SeasonNumber)
|
||||
{
|
||||
_logger.Trace("Season number does not match searched season number, skipping.");
|
||||
return false;
|
||||
|
@ -30,12 +30,12 @@ public virtual bool IsSatisfiedBy(RemoteEpisode subject)
|
||||
{
|
||||
_logger.Trace("Comparing file quality with report. Existing file is {0}", file.Quality);
|
||||
|
||||
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.QualityProfile, file.Quality, subject.Quality))
|
||||
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.QualityProfile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (subject.Quality.Proper && file.DateAdded < DateTime.Today.AddDays(-7))
|
||||
if (subject.ParsedEpisodeInfo.Quality.Proper && file.DateAdded < DateTime.Today.AddDays(-7))
|
||||
{
|
||||
_logger.Trace("Proper for old file, skipping: {0}", subject);
|
||||
return false;
|
||||
|
@ -33,7 +33,7 @@ public virtual bool IsSatisfiedBy(RemoteEpisode subject)
|
||||
if (bestQualityInHistory != null)
|
||||
{
|
||||
_logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory);
|
||||
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.QualityProfile, bestQualityInHistory, subject.Quality))
|
||||
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.QualityProfile, bestQualityInHistory, subject.ParsedEpisodeInfo.Quality))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -7,19 +7,61 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using RestSharp;
|
||||
|
||||
namespace NzbDrone.Core.Download.Clients.Sabnzbd
|
||||
{
|
||||
public class SabRequestBuilder
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
|
||||
public SabRequestBuilder(IConfigService configService)
|
||||
{
|
||||
_configService = configService;
|
||||
}
|
||||
|
||||
public IRestRequest AddToQueueRequest(RemoteEpisode remoteEpisode)
|
||||
{
|
||||
string cat = _configService.SabTvCategory;
|
||||
int priority = remoteEpisode.IsRecentEpisode() ? (int)_configService.SabRecentTvPriority : (int)_configService.SabBacklogTvPriority;
|
||||
|
||||
string name = remoteEpisode.Report.NzbUrl.Replace("&", "%26");
|
||||
string nzbName = HttpUtility.UrlEncode(remoteEpisode.Report.Title);
|
||||
|
||||
string action = string.Format("mode=addurl&name={0}&priority={1}&pp=3&cat={2}&nzbname={3}&output=json",
|
||||
name, priority, cat, nzbName);
|
||||
|
||||
string request = GetSabRequest(action);
|
||||
|
||||
return new RestRequest(request);
|
||||
}
|
||||
|
||||
|
||||
private string GetSabRequest(string action)
|
||||
{
|
||||
return string.Format(@"http://{0}:{1}/api?{2}&apikey={3}&ma_username={4}&ma_password={5}",
|
||||
_configService.SabHost,
|
||||
_configService.SabPort,
|
||||
action,
|
||||
_configService.SabApiKey,
|
||||
_configService.SabUsername,
|
||||
_configService.SabPassword);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SabnzbdClient : IDownloadClient
|
||||
{
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IHttpProvider _httpProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public SabnzbdClient(IConfigService configService, IHttpProvider httpProvider)
|
||||
public SabnzbdClient(IConfigService configService, IHttpProvider httpProvider, Logger logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_httpProvider = httpProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public virtual bool DownloadNzb(string url, string title, bool recentlyAired)
|
||||
@ -36,11 +78,11 @@ public virtual bool DownloadNzb(string url, string title, bool recentlyAired)
|
||||
name, priority, cat, nzbName);
|
||||
|
||||
string request = GetSabRequest(action);
|
||||
logger.Info("Adding report [{0}] to the queue.", title);
|
||||
_logger.Info("Adding report [{0}] to the queue.", title);
|
||||
|
||||
var response = _httpProvider.DownloadString(request);
|
||||
|
||||
logger.Debug("Queue Response: [{0}]", response);
|
||||
_logger.Debug("Queue Response: [{0}]", response);
|
||||
|
||||
CheckForError(response);
|
||||
return true;
|
||||
@ -48,7 +90,7 @@ public virtual bool DownloadNzb(string url, string title, bool recentlyAired)
|
||||
|
||||
catch (WebException ex)
|
||||
{
|
||||
logger.Error("Error communicating with SAB: " + ex.Message);
|
||||
_logger.Error("Error communicating with SAB: " + ex.Message);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -62,9 +104,9 @@ public IEnumerable<QueueItem> GetQueue()
|
||||
|
||||
CheckForError(response);
|
||||
|
||||
var sabQeueu = JsonConvert.DeserializeObject<SabQueue>(JObject.Parse(response).SelectToken("queue").ToString()).Items;
|
||||
var sabQueue = JsonConvert.DeserializeObject<SabQueue>(JObject.Parse(response).SelectToken("queue").ToString()).Items;
|
||||
|
||||
foreach (var sabQueueItem in sabQeueu)
|
||||
foreach (var sabQueueItem in sabQueue)
|
||||
{
|
||||
var queueItem = new QueueItem();
|
||||
queueItem.Id = sabQueueItem.Id;
|
||||
@ -163,7 +205,7 @@ public virtual string Test(string host, int port, string apiKey, string username
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.DebugException("Failed to Test SABnzbd", ex);
|
||||
_logger.DebugException("Failed to Test SABnzbd", ex);
|
||||
}
|
||||
|
||||
return String.Empty;
|
||||
|
@ -37,10 +37,6 @@ public DownloadService(IProvideDownloadClient downloadClientProvider, IConfigSer
|
||||
public bool DownloadReport(RemoteEpisode episode)
|
||||
{
|
||||
var downloadTitle = episode.Report.Title;
|
||||
if (!_configService.DownloadClientUseSceneName)
|
||||
{
|
||||
downloadTitle = episode.GetDownloadTitle();
|
||||
}
|
||||
|
||||
var provider = _downloadClientProvider.GetDownloadClient();
|
||||
var recentEpisode = ContainsRecentEpisode(episode);
|
||||
|
@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.Download.Clients.Sabnzbd;
|
||||
using NzbDrone.Core.Download.Clients.Sabnzbd.JsonConverters;
|
||||
using NzbDrone.Core.Model;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
@ -14,8 +10,6 @@ public class QueueItem
|
||||
|
||||
public decimal SizeLeft { get; set; }
|
||||
|
||||
public int Percentage { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public TimeSpan Timeleft { get; set; }
|
||||
|
@ -83,7 +83,8 @@ public void Handle(EpisodeGrabbedEvent message)
|
||||
try
|
||||
{
|
||||
_logger.Trace("Sending grab notification to {0}", Name);
|
||||
OnGrab(message.Episode.GetDownloadTitle());
|
||||
//todo: pass all the info to grab event and let the handlers deal with it.
|
||||
OnGrab(message.Episode.ToString());
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -56,7 +56,7 @@ public void Handle(EpisodeGrabbedEvent message)
|
||||
{
|
||||
Date = DateTime.Now,
|
||||
Indexer = message.Episode.Report.Indexer,
|
||||
Quality = message.Episode.Quality,
|
||||
Quality = message.Episode.ParsedEpisodeInfo.Quality,
|
||||
NzbTitle = message.Episode.Report.Title,
|
||||
EpisodeId = episode.Id,
|
||||
NzbInfoUrl = message.Episode.Report.NzbInfoUrl,
|
||||
|
@ -40,8 +40,8 @@ public void Sync()
|
||||
|
||||
var qualifiedReports = decisions
|
||||
.Where(c => c.Approved)
|
||||
.Select(c => c.Episode)
|
||||
.OrderByDescending(c => c.Quality)
|
||||
.Select(c => c.RemoteEpisode)
|
||||
.OrderByDescending(c => c.ParsedEpisodeInfo.Quality)
|
||||
.ThenBy(c => c.Episodes.Select(e => e.EpisodeNumber).MinOrDefault())
|
||||
.ThenBy(c => c.Report.Age);
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Parser.Model
|
||||
@ -9,10 +7,9 @@ namespace NzbDrone.Core.Parser.Model
|
||||
public class ParsedEpisodeInfo
|
||||
{
|
||||
public string SeriesTitle { get; set; }
|
||||
public string OriginalString { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
public List<int> EpisodeNumbers { get; set; }
|
||||
public int[] EpisodeNumbers { get; set; }
|
||||
public DateTime? AirDate { get; set; }
|
||||
public Language Language { get; set; }
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Parser.Model
|
||||
@ -9,100 +8,16 @@ namespace NzbDrone.Core.Parser.Model
|
||||
public class RemoteEpisode
|
||||
{
|
||||
public ReportInfo Report { get; set; }
|
||||
|
||||
public bool FullSeason { get; set; }
|
||||
|
||||
public ParsedEpisodeInfo ParsedEpisodeInfo { get; set; }
|
||||
|
||||
public Series Series { get; set; }
|
||||
|
||||
public List<Episode> Episodes { get; set; }
|
||||
|
||||
public QualityModel Quality { get; set; }
|
||||
|
||||
public Language Language { get; set; }
|
||||
|
||||
public int SeasonNumber
|
||||
public bool IsRecentEpisode()
|
||||
{
|
||||
get { return Episodes.Select(e => e.SeasonNumber).Distinct().SingleOrDefault(); }
|
||||
}
|
||||
|
||||
|
||||
public DateTime? AirDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return Episodes.Single().AirDate;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<int> EpisodeNumbers
|
||||
{
|
||||
get
|
||||
{
|
||||
return Episodes.Select(c => c.EpisodeNumber).Distinct();
|
||||
}
|
||||
}
|
||||
|
||||
public string GetDownloadTitle()
|
||||
{
|
||||
var seriesTitle = FileNameBuilder.CleanFilename(Series.Title);
|
||||
|
||||
//Handle Full Naming
|
||||
if (FullSeason)
|
||||
{
|
||||
var seasonResult = String.Format("{0} - Season {1} [{2}]", seriesTitle, SeasonNumber, Quality);
|
||||
|
||||
if (Quality.Proper)
|
||||
seasonResult += " [Proper]";
|
||||
|
||||
return seasonResult;
|
||||
}
|
||||
|
||||
if (Series.SeriesType == SeriesTypes.Daily)
|
||||
{
|
||||
var dailyResult = String.Format("{0} - {1:yyyy-MM-dd} - {2} [{3}]", seriesTitle,
|
||||
AirDate, Episodes.First().Title, Quality);
|
||||
|
||||
if (Quality.Proper)
|
||||
dailyResult += " [Proper]";
|
||||
|
||||
return dailyResult;
|
||||
}
|
||||
|
||||
//Show Name - 1x01-1x02 - Episode Name
|
||||
//Show Name - 1x01 - Episode Name
|
||||
var episodeString = new List<string>();
|
||||
var episodeNames = new List<string>();
|
||||
|
||||
foreach (var episode in Episodes)
|
||||
{
|
||||
episodeString.Add(String.Format("{0}x{1:00}", episode.SeasonNumber, episode.EpisodeNumber));
|
||||
episodeNames.Add(Core.Parser.Parser.CleanupEpisodeTitle(episode.Title));
|
||||
}
|
||||
|
||||
var epNumberString = String.Join("-", episodeString);
|
||||
string episodeName;
|
||||
|
||||
|
||||
if (episodeNames.Distinct().Count() == 1)
|
||||
episodeName = episodeNames.First();
|
||||
|
||||
else
|
||||
episodeName = String.Join(" + ", episodeNames.Distinct());
|
||||
|
||||
var result = String.Format("{0} - {1} - {2} [{3}]", seriesTitle, epNumberString, episodeName, Quality);
|
||||
|
||||
if (Quality.Proper)
|
||||
{
|
||||
result += " [Proper]";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Episodes.Any(e => e.AirDate >= DateTime.Today.AddDays(-7));
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
@ -90,11 +89,7 @@ public static ParsedEpisodeInfo ParsePath(string path)
|
||||
result = ParseTitle(fileInfo.FullName);
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
result.OriginalString = path;
|
||||
}
|
||||
else
|
||||
if (result == null)
|
||||
{
|
||||
Logger.Warn("Unable to parse episode info from path {0}", path);
|
||||
}
|
||||
@ -124,7 +119,6 @@ public static ParsedEpisodeInfo ParseTitle(string title)
|
||||
|
||||
result.Language = ParseLanguage(title);
|
||||
result.Quality = ParseQuality(title);
|
||||
result.OriginalString = title;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -172,7 +166,7 @@ private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchColle
|
||||
result = new ParsedEpisodeInfo
|
||||
{
|
||||
SeasonNumber = seasons.First(),
|
||||
EpisodeNumbers = new List<int>()
|
||||
EpisodeNumbers = new int[0],
|
||||
};
|
||||
|
||||
foreach (Match matchGroup in matchCollection)
|
||||
@ -184,7 +178,7 @@ private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchColle
|
||||
{
|
||||
var first = Convert.ToInt32(episodeCaptures.First().Value);
|
||||
var last = Convert.ToInt32(episodeCaptures.Last().Value);
|
||||
result.EpisodeNumbers = Enumerable.Range(first, last - first + 1).ToList();
|
||||
result.EpisodeNumbers = Enumerable.Range(first, last - first + 1).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
@ -11,7 +10,7 @@ public interface IParsingService
|
||||
{
|
||||
LocalEpisode GetEpisodes(string fileName, Series series);
|
||||
Series GetSeries(string title);
|
||||
RemoteEpisode Map(ReportInfo reportInfo);
|
||||
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo);
|
||||
}
|
||||
|
||||
public class ParsingService : IParsingService
|
||||
@ -65,32 +64,23 @@ public Series GetSeries(string title)
|
||||
return _seriesService.FindByTitle(searchTitle);
|
||||
}
|
||||
|
||||
public RemoteEpisode Map(ReportInfo reportInfo)
|
||||
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo)
|
||||
{
|
||||
var parsedInfo = Parser.ParseTitle(reportInfo.Title);
|
||||
var remoteEpisode = new RemoteEpisode
|
||||
{
|
||||
ParsedEpisodeInfo = parsedEpisodeInfo,
|
||||
};
|
||||
|
||||
if (parsedInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var series = _seriesService.FindByTitle(parsedInfo.SeriesTitle);
|
||||
var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
||||
|
||||
if (series == null)
|
||||
{
|
||||
_logger.Trace("No matching series {0}", parsedInfo.SeriesTitle);
|
||||
return null;
|
||||
_logger.Trace("No matching series {0}", parsedEpisodeInfo.SeriesTitle);
|
||||
return remoteEpisode;
|
||||
}
|
||||
|
||||
var remoteEpisode = new RemoteEpisode
|
||||
{
|
||||
Series = series,
|
||||
Episodes = GetEpisodes(parsedInfo, series),
|
||||
FullSeason = parsedInfo.FullSeason,
|
||||
Language = parsedInfo.Language,
|
||||
Quality = parsedInfo.Quality,
|
||||
Report = reportInfo
|
||||
};
|
||||
remoteEpisode.Series = series;
|
||||
remoteEpisode.Episodes = GetEpisodes(parsedEpisodeInfo, series);
|
||||
|
||||
return remoteEpisode;
|
||||
}
|
||||
@ -104,7 +94,7 @@ private List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series se
|
||||
if (series.SeriesType == SeriesTypes.Standard)
|
||||
{
|
||||
//Todo: Collect this as a Series we want to treat as a daily series, or possible parsing error
|
||||
_logger.Warn("Found daily-style episode for non-daily series: {0}. {1}", series.Title, parsedEpisodeInfo.OriginalString);
|
||||
_logger.Warn("Found daily-style episode for non-daily series: {0}.", series.Title);
|
||||
return new List<Episode>();
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
using FluentAssertions;
|
||||
using NLog;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Common;
|
||||
using RestSharp;
|
||||
|
||||
namespace NzbDrone.Integration.Test.Client
|
||||
@ -13,6 +14,7 @@ namespace NzbDrone.Integration.Test.Client
|
||||
private readonly string _resource;
|
||||
|
||||
private readonly Logger _logger;
|
||||
private readonly JsonSerializer _jsonSerializer;
|
||||
|
||||
public ClientBase(IRestClient restClient, string resource = null)
|
||||
{
|
||||
@ -23,6 +25,11 @@ public ClientBase(IRestClient restClient, string resource = null)
|
||||
|
||||
_restClient = restClient;
|
||||
_resource = resource;
|
||||
|
||||
_jsonSerializer = new JsonSerializer();
|
||||
|
||||
|
||||
|
||||
_logger = LogManager.GetLogger("REST");
|
||||
}
|
||||
|
||||
@ -60,13 +67,13 @@ protected RestRequest BuildRequest(string command = "")
|
||||
};
|
||||
}
|
||||
|
||||
protected T Get<T>(IRestRequest request, HttpStatusCode statusCode = HttpStatusCode.OK) where T : new()
|
||||
protected T Get<T>(IRestRequest request, HttpStatusCode statusCode = HttpStatusCode.OK) where T : class, new()
|
||||
{
|
||||
request.Method = Method.GET;
|
||||
return Execute<T>(request, statusCode);
|
||||
}
|
||||
|
||||
public T Post<T>(IRestRequest request, HttpStatusCode statusCode = HttpStatusCode.Created) where T : new()
|
||||
public T Post<T>(IRestRequest request, HttpStatusCode statusCode = HttpStatusCode.Created) where T : class, new()
|
||||
{
|
||||
request.Method = Method.POST;
|
||||
return Execute<T>(request, statusCode);
|
||||
@ -78,11 +85,11 @@ public void Delete(IRestRequest request, HttpStatusCode statusCode = HttpStatusC
|
||||
Execute<object>(request, statusCode);
|
||||
}
|
||||
|
||||
private T Execute<T>(IRestRequest request, HttpStatusCode statusCode) where T : new()
|
||||
private T Execute<T>(IRestRequest request, HttpStatusCode statusCode) where T : class, new()
|
||||
{
|
||||
_logger.Info("{0}: {1}", request.Method, _restClient.BuildUri(request));
|
||||
|
||||
var response = _restClient.Execute<T>(request);
|
||||
var response = _restClient.Execute(request);
|
||||
_logger.Info("Response: {0}", response.Content);
|
||||
|
||||
response.StatusCode.Should().Be(statusCode);
|
||||
@ -94,7 +101,7 @@ public void Delete(IRestRequest request, HttpStatusCode statusCode = HttpStatusC
|
||||
|
||||
response.ErrorMessage.Should().BeBlank();
|
||||
|
||||
return response.Data;
|
||||
return _jsonSerializer.Deserialize<T>(response.Content);
|
||||
}
|
||||
|
||||
}
|
||||
|
16
NzbDrone.Integration.Test/Client/SeriesClient - Copy.cs
Normal file
16
NzbDrone.Integration.Test/Client/SeriesClient - Copy.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using NzbDrone.Api.Indexers;
|
||||
using RestSharp;
|
||||
|
||||
namespace NzbDrone.Integration.Test.Client
|
||||
{
|
||||
public class ReleaseClient : ClientBase<ReleaseResource>
|
||||
{
|
||||
public ReleaseClient(IRestClient restClient)
|
||||
: base(restClient)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -31,15 +31,16 @@ public abstract class IntegrationTest
|
||||
protected SeriesClient Series;
|
||||
protected ClientBase<RootFolderResource> RootFolders;
|
||||
protected ClientBase<CommandResource> Commands;
|
||||
protected ReleaseClient Releases;
|
||||
|
||||
static IntegrationTest()
|
||||
{
|
||||
if (LogManager.Configuration == null || LogManager.Configuration is XmlLoggingConfiguration)
|
||||
{
|
||||
LogManager.Configuration = new LoggingConfiguration();
|
||||
var consoleTarget = new ConsoleTarget { Layout = "${logger} - ${message} ${exception}" };
|
||||
var consoleTarget = new ConsoleTarget { Layout = "${time} - ${logger} - ${message} ${exception}" };
|
||||
LogManager.Configuration.AddTarget(consoleTarget.GetType().Name, consoleTarget);
|
||||
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, consoleTarget));
|
||||
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget));
|
||||
}
|
||||
|
||||
|
||||
@ -85,6 +86,7 @@ public void SmokeTestSetup()
|
||||
|
||||
RestClient = new RestClient(url + "/api/");
|
||||
Series = new SeriesClient(RestClient);
|
||||
Releases = new ReleaseClient(RestClient);
|
||||
RootFolders = new ClientBase<RootFolderResource>(RestClient);
|
||||
Commands = new ClientBase<CommandResource>(RestClient);
|
||||
|
||||
|
@ -75,8 +75,10 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Client\ClientBase.cs" />
|
||||
<Compile Include="Client\SeriesClient - Copy.cs" />
|
||||
<Compile Include="Client\SeriesClient.cs" />
|
||||
<Compile Include="CommandIntegerationTests.cs" />
|
||||
<Compile Include="ReleaseIntegrationTest.cs" />
|
||||
<Compile Include="IntegrationTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RootFolderIntegrationTest.cs" />
|
||||
|
17
NzbDrone.Integration.Test/ReleaseIntegrationTest.cs
Normal file
17
NzbDrone.Integration.Test/ReleaseIntegrationTest.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace NzbDrone.Integration.Test
|
||||
{
|
||||
[TestFixture]
|
||||
public class ReleaseIntegrationTest : IntegrationTest
|
||||
{
|
||||
[Test]
|
||||
public void should_only_have_unknown_series_releases()
|
||||
{
|
||||
Releases.All().Should().OnlyContain(c => c.Rejections.Contains("Unknown Series"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user