diff --git a/src/NzbDrone.Core.Test/CustomFormat/QualityTagFixture.cs b/src/NzbDrone.Core.Test/CustomFormat/QualityTagFixture.cs index 723a2b040..c6aa65ea8 100644 --- a/src/NzbDrone.Core.Test/CustomFormat/QualityTagFixture.cs +++ b/src/NzbDrone.Core.Test/CustomFormat/QualityTagFixture.cs @@ -12,11 +12,11 @@ namespace NzbDrone.Core.Test.CustomFormat [TestFixture] public class QualityTagFixture : CoreTest { - [TestCase("R_1080", TagType.Resolution, Resolution.R1080P)] - [TestCase("R_720", TagType.Resolution, Resolution.R720P)] - [TestCase("R_576", TagType.Resolution, Resolution.R576P)] - [TestCase("R_480", TagType.Resolution, Resolution.R480P)] - [TestCase("R_2160", TagType.Resolution, Resolution.R2160P)] + [TestCase("R_1080", TagType.Resolution, Resolution.R1080p)] + [TestCase("R_720", TagType.Resolution, Resolution.R720p)] + [TestCase("R_576", TagType.Resolution, Resolution.R576p)] + [TestCase("R_480", TagType.Resolution, Resolution.R480p)] + [TestCase("R_2160", TagType.Resolution, Resolution.R2160p)] [TestCase("S_BLURAY", TagType.Source, Source.BLURAY)] [TestCase("s_tv", TagType.Source, Source.TV)] [TestCase("s_workPRINT", TagType.Source, Source.WORKPRINT)] @@ -38,7 +38,7 @@ namespace NzbDrone.Core.Test.CustomFormat [TestCase("G_10<>20", TagType.Size, new[] { 10737418240L, 21474836480L})] [TestCase("G_15.55<>20", TagType.Size, new[] { 16696685363L, 21474836480L})] [TestCase("G_15.55<>25.1908754", TagType.Size, new[] { 16696685363L, 27048496500L})] - [TestCase("R__1080", TagType.Resolution, Resolution.R1080P)] + [TestCase("R__1080", TagType.Resolution, Resolution.R1080p)] public void should_parse_tag_from_string(string raw, TagType type, object value, params TagModifier[] modifiers) { var parsed = new FormatTag(raw); diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/159_add_webrip_qualitiesFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/159_add_webrip_qualitiesFixture.cs new file mode 100644 index 000000000..2a96afb12 --- /dev/null +++ b/src/NzbDrone.Core.Test/Datastore/Migration/159_add_webrip_qualitiesFixture.cs @@ -0,0 +1,123 @@ +using System.Linq; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Datastore.Migration; +using NzbDrone.Core.Qualities; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.Datastore.Migration +{ + [TestFixture] + public class add_webrip_qualitesFixture : MigrationTest + { + private string GenerateQualityJson(int quality, bool allowed) + { + return $"{{ \"quality\": {quality}, \"allowed\": {allowed.ToString().ToLowerInvariant()} }}"; + } + + private string GenerateQualityGroupJson(int quality, bool allowed, string groupname, int group) + { + return $"{{\"id\": {group}, \"name\": \"{groupname}\", \"items\": [ {{ \"quality\": {quality}, \"allowed\": {allowed.ToString().ToLowerInvariant()} }} ] }}"; + } + + [Test] + public void should_add_webrip_qualities_and_group_with_webdl() + { + var db = WithMigrationTestDb(c => + { + c.Insert.IntoTable("Profiles").Row(new + { + Id = 0, + Name = "SDTV", + Cutoff = 1, + Items = $"[{GenerateQualityJson(1, true)}, {GenerateQualityJson((int)Quality.WEBRip480p, false)}, {GenerateQualityJson((int)Quality.WEBRip720p, false)}, {GenerateQualityJson((int)Quality.WEBRip1080p, false)}, {GenerateQualityJson((int)Quality.WEBRip2160p, false)}]" + }); + }); + + var profiles = db.Query("SELECT Items FROM Profiles LIMIT 1"); + + var items = profiles.First().Items; + items.Should().HaveCount(5); + items.Select(v => v.Quality).Should().BeEquivalentTo(1, null, null, null, null); + items.Select(v => v.Items.Count).Should().BeEquivalentTo(0, 2, 2, 2, 2); + items.Select(v => v.Allowed).Should().BeEquivalentTo(true, false, false, false, false); + } + + [Test] + public void should_add_webrip_and_webdl_if_webdl_is_missing() + { + var db = WithMigrationTestDb(c => + { + c.Insert.IntoTable("Profiles").Row(new + { + Id = 0, + Name = "SDTV", + Cutoff = 1, + Items = $"[{GenerateQualityJson(1, true)}, {GenerateQualityJson((int)Quality.WEBRip480p, false)}, {GenerateQualityJson((int)Quality.WEBRip720p, false)}, {GenerateQualityJson((int)Quality.WEBRip1080p, false)}]" + }); + }); + + var profiles = db.Query("SELECT Items FROM Profiles LIMIT 1"); + + var items = profiles.First().Items; + items.Should().HaveCount(5); + items.Select(v => v.Quality).Should().BeEquivalentTo(1, null, null, null, null); + items.Select(v => v.Items.Count).Should().BeEquivalentTo(0, 2, 2, 2, 2); + items.Select(v => v.Allowed).Should().BeEquivalentTo(true, false, false, false, false); + } + + [Test] + public void should_add_webrip_beside_webdl_is_grouped() + { + var db = WithMigrationTestDb(c => + { + c.Insert.IntoTable("Profiles").Row(new + { + Id = 0, + Name = "SDTV", + Cutoff = 1, + Items = $"[{GenerateQualityJson(1, true)}, {GenerateQualityGroupJson(5, true, "smegrup", 1001)}]" + }); + }); + + var profiles = db.Query("SELECT Items FROM Profiles LIMIT 1"); + + var items = profiles.First().Items; + items.Count(c => c.Id == 1001).Should().Be(1); + items.Should().HaveCount(5); + items.Select(v => v.Quality).Should().BeEquivalentTo(1, null, null, null, null); + items.Select(v => v.Items.Count).Should().BeEquivalentTo(0, 2, 2, 2, 2); + items.Select(v => v.Allowed).Should().BeEquivalentTo(true, false, false, false, false); + } + + [Test] + public void should_group_webrip_and_webdl_with_the_same_resolution() + { + var db = WithMigrationTestDb(c => + { + c.Insert.IntoTable("Profiles").Row(new + { + Id = 0, + Name = "SDTV", + Cutoff = 1, + Items = $"[{GenerateQualityJson(1, true)}, {GenerateQualityJson((int)Quality.WEBRip480p, false)}, {GenerateQualityJson((int)Quality.WEBRip720p, false)}, {GenerateQualityJson((int)Quality.WEBRip1080p, false)}, {GenerateQualityJson((int)Quality.WEBRip2160p, false)}]" + }); + }); + + var profiles = db.Query("SELECT Items FROM Profiles LIMIT 1"); + var items = profiles.First().Items; + + items[1].Items.First().Quality.Should().Be((int)Quality.WEBRip480p); + items[1].Items.Last().Quality.Should().Be((int)Quality.WEBDL480p); + + items[2].Items.First().Quality.Should().Be((int)Quality.WEBRip720p); + items[2].Items.Last().Quality.Should().Be((int)Quality.WEBDL720p); + + items[3].Items.First().Quality.Should().Be((int)Quality.WEBRip1080p); + items[3].Items.Last().Quality.Should().Be((int)Quality.WEBDL1080p); + + items[4].Items.First().Quality.Should().Be((int)Quality.WEBRip2160p); + items[4].Items.Last().Quality.Should().Be((int)Quality.WEBDL2160p); + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQualityFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQualityFixture.cs index 653f2193d..acdbcf10b 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQualityFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQualityFixture.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using NzbDrone.Core.CustomFormats; using NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators; using NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality; +using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Qualities; using NzbDrone.Core.Test.Framework; @@ -27,13 +28,13 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators _nameAugmenter = new Mock(); _mediaInfoAugmenter.Setup(s => s.AugmentQuality(It.IsAny())) - .Returns(AugmentQualityResult.ResolutionOnly(Resolution.R1080P, Confidence.MediaInfo)); + .Returns(AugmentQualityResult.ResolutionOnly((int)Resolution.R1080p, Confidence.MediaInfo)); _fileExtensionAugmenter.Setup(s => s.AugmentQuality(It.IsAny())) - .Returns(new AugmentQualityResult(Source.TV, Confidence.Fallback, Resolution.R720P, Confidence.Fallback, Modifier.NONE, Confidence.Fallback, new Revision())); + .Returns(new AugmentQualityResult(Source.TV, Confidence.Fallback, (int)Resolution.R720p, Confidence.Fallback, Modifier.NONE, Confidence.Fallback, new Revision(), new List())); _nameAugmenter.Setup(s => s.AugmentQuality(It.IsAny())) - .Returns(new AugmentQualityResult(Source.TV, Confidence.Default, Resolution.R480P, Confidence.Default, Modifier.NONE, Confidence.Default, new Revision())); + .Returns(new AugmentQualityResult(Source.TV, Confidence.Default, (int)Resolution.R480p, Confidence.Default, Modifier.NONE, Confidence.Default, new Revision(), new List())); } private void GivenAugmenters(params Mock[] mocks) diff --git a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromMediaInfoFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromMediaInfoFixture.cs index fe8c647dc..177d1cd9f 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromMediaInfoFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromMediaInfoFixture.cs @@ -6,6 +6,7 @@ using NzbDrone.Core.MediaFiles.MediaInfo; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser; namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality { @@ -36,20 +37,20 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators.Augm Subject.AugmentQuality(localMovie).Should().Be(null); } - [TestCase(4096, Resolution.R2160P)] // True 4K - [TestCase(4000, Resolution.R2160P)] - [TestCase(3840, Resolution.R2160P)] // 4K UHD - [TestCase(3200, Resolution.R2160P)] - [TestCase(2000, Resolution.R1080P)] - [TestCase(1920, Resolution.R1080P)] // Full HD - [TestCase(1800, Resolution.R1080P)] - [TestCase(1490, Resolution.R720P)] - [TestCase(1280, Resolution.R720P)] // HD - [TestCase(1200, Resolution.R720P)] - [TestCase(800, Resolution.R480P)] - [TestCase(720, Resolution.R480P)] // SDTV - [TestCase(600, Resolution.R480P)] - [TestCase(100, Resolution.R480P)] + [TestCase(4096, Resolution.R2160p)] // True 4K + [TestCase(4000, Resolution.R2160p)] + [TestCase(3840, Resolution.R2160p)] // 4K UHD + [TestCase(3200, Resolution.R2160p)] + [TestCase(2000, Resolution.R1080p)] + [TestCase(1920, Resolution.R1080p)] // Full HD + [TestCase(1800, Resolution.R1080p)] + [TestCase(1490, Resolution.R720p)] + [TestCase(1280, Resolution.R720p)] // HD + [TestCase(1200, Resolution.R720p)] + [TestCase(800, Resolution.R480p)] + [TestCase(720, Resolution.R480p)] // SDTV + [TestCase(600, Resolution.R480p)] + [TestCase(100, Resolution.R480p)] public void should_return_closest_resolution(int mediaInfoWidth, Resolution expectedResolution) { var mediaInfo = Builder.CreateNew() @@ -63,7 +64,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators.Augm var result = Subject.AugmentQuality(localMovie); result.Should().NotBe(null); - result.Resolution.Should().Be(expectedResolution); + result.Resolution.Should().Be((int)expectedResolution); } } } diff --git a/src/NzbDrone.Core.Test/ParserTests/ExtendedQualityParserRegex.cs b/src/NzbDrone.Core.Test/ParserTests/ExtendedQualityParserRegex.cs index a8e53844f..1c58c3dd6 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ExtendedQualityParserRegex.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ExtendedQualityParserRegex.cs @@ -65,7 +65,7 @@ namespace NzbDrone.Core.Test.ParserTests public void should_parse_ultrahd_from_title(string title, int version) { var parsed = QualityParser.ParseQuality(title); - parsed.Resolution.Should().Be(Resolution.R2160P); + parsed.Quality.Resolution.Should().Be((int)Resolution.R2160p); } } } diff --git a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs index 97cd784ec..383987d52 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs @@ -113,24 +113,13 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("My.Movie.GERMAN.Extended.Cut.2016", "Extended Cut")] [TestCase("My.Movie.GERMAN.Extended.Cut", "Extended Cut")] [TestCase("Mission Impossible: Rogue Nation 2012 Bluray", "")] - [TestCase("Loving.Pablo.2018.TS.FRENCH.MD.x264-DROGUERiE","")] + [TestCase("Loving.Pablo.2018.TS.FRENCH.MD.x264-DROGUERiE", "")] public void should_parse_edition(string postTitle, string edition) { var parsed = Parser.Parser.ParseMovieTitle(postTitle, true); - if (parsed.Edition.IsNullOrWhiteSpace()) - { - parsed.Edition = Parser.Parser.ParseEdition(parsed.SimpleReleaseTitle); - } parsed.Edition.Should().Be(edition); } - [TestCase("The Lord of the Rings The Fellowship of the Ring (Extended Edition) 1080p BD25", "The Lord Of The Rings The Fellowship Of The Ring", "Extended Edition")] - [TestCase("The.Lord.of.the.Rings.The.Fellowship.of.the.Ring.(Extended.Edition).1080p.BD25", "The Lord Of The Rings The Fellowship Of The Ring", "Extended Edition")] - public void should_parse_edition_lenient_mapping(string postTitle, string foundTitle, string edition) - { - Parser.Parser.ParseMinimalMovieTitle(postTitle, foundTitle, 1290).Edition.Should().Be(edition); - } - [TestCase("123", "tt0000123")] [TestCase("1234567", "tt1234567")] [TestCase("tt1234567", "tt1234567")] diff --git a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/AugmentersTests/AugmentWithMediaInfoFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/AugmentersTests/AugmentWithMediaInfoFixture.cs index f271597ad..f61fa5813 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/AugmentersTests/AugmentWithMediaInfoFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/AugmentersTests/AugmentWithMediaInfoFixture.cs @@ -1,89 +1,90 @@ -using FluentAssertions; -using NUnit.Framework; -using NzbDrone.Core.CustomFormats; -using NzbDrone.Core.MediaFiles.MediaInfo; -using NzbDrone.Core.Parser.Augmenters; -using NzbDrone.Core.Qualities; +//using FluentAssertions; +//using NUnit.Framework; +//using NzbDrone.Core.CustomFormats; +//using NzbDrone.Core.MediaFiles.MediaInfo; +//using NzbDrone.Core.Parser; +//using NzbDrone.Core.Parser.Augmenters; +//using NzbDrone.Core.Qualities; -namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests -{ - [TestFixture] - public class AugmentWithMediaInfoFixture : AugmentMovieInfoFixture - { - [TestCase(Resolution.R720P, Source.BLURAY, Resolution.R1080P)] - [TestCase(Resolution.R1080P, Source.TV, Resolution.R720P)] - public void should_correct_resolution(Resolution resolution, Source source, Resolution realResolution) - { - var quality = new QualityModel - { - Source = source, - Resolution = resolution, - }; - MovieInfo.Quality = quality; +//namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests +//{ +// [TestFixture] +// public class AugmentWithMediaInfoFixture : AugmentMovieInfoFixture +// { +// [TestCase(Resolution.R720p, Source.BLURAY, Resolution.R1080p)] +// [TestCase(Resolution.R1080p, Source.TV, Resolution.R720p)] +// public void should_correct_resolution(Resolution resolution, Source source, Resolution realResolution) +// { +// var quality = new QualityModel +// { +// Source = source, +// Resolution = resolution, +// }; +// MovieInfo.Quality = quality; - var realWidth = 480; - switch (realResolution) - { - case Resolution.R720P: - realWidth = 1280; - break; - case Resolution.R1080P: - realWidth = 1920; - break; - case Resolution.R2160P: - realWidth = 2160; - break; +// var realWidth = 480; +// switch (realResolution) +// { +// case Resolution.R720p: +// realWidth = 1280; +// break; +// case Resolution.R1080p: +// realWidth = 1920; +// break; +// case Resolution.R2160p: +// realWidth = 2160; +// break; - } +// } - var mediaInfo = new MediaInfoModel - { - Width = realWidth - }; +// var mediaInfo = new MediaInfoModel +// { +// Width = realWidth +// }; - var movieInfo = Subject.AugmentMovieInfo(MovieInfo, mediaInfo); - movieInfo.Quality.Resolution.Should().BeEquivalentTo(realResolution); - movieInfo.Quality.QualityDetectionSource.Should().BeEquivalentTo(QualityDetectionSource.MediaInfo); - } +// var movieInfo = Subject.AugmentMovieInfo(MovieInfo, mediaInfo); +// movieInfo.Quality.Resolution.Should().BeEquivalentTo(realResolution); +// movieInfo.Quality.QualityDetectionSource.Should().BeEquivalentTo(QualityDetectionSource.MediaInfo); +// } - [TestCase(Resolution.R720P, Source.BLURAY, Resolution.R1080P, Modifier.BRDISK)] - [TestCase(Resolution.R1080P, Source.BLURAY, Resolution.R720P, Modifier.REMUX)] - [TestCase(Resolution.R480P, Source.BLURAY, Resolution.R720P)] - [TestCase(Resolution.R720P, Source.DVD, Resolution.R480P)] - public void should_not_correct_resolution(Resolution resolution, Source source, Resolution realResolution, Modifier modifier = Modifier.NONE) - { - var quality = new QualityModel - { - Source = source, - Resolution = resolution, - Modifier = modifier, - }; +// [TestCase(Resolution.R720P, Source.BLURAY, Resolution.R1080P, Modifier.BRDISK)] +// [TestCase(Resolution.R1080P, Source.BLURAY, Resolution.R720P, Modifier.REMUX)] +// [TestCase(Resolution.R480P, Source.BLURAY, Resolution.R720P)] +// [TestCase(Resolution.R720P, Source.DVD, Resolution.R480P)] +// public void should_not_correct_resolution(Resolution resolution, Source source, Resolution realResolution, Modifier modifier = Modifier.NONE) +// { +// var quality = new QualityModel +// { +// Source = source, +// Resolution = resolution, +// Modifier = modifier, +// }; - MovieInfo.Quality = quality; +// MovieInfo.Quality = quality; - var realWidth = 480; - switch (realResolution) - { - case Resolution.R720P: - realWidth = 1280; - break; - case Resolution.R1080P: - realWidth = 1920; - break; - case Resolution.R2160P: - realWidth = 2160; - break; +// var realWidth = 480; +// switch (realResolution) +// { +// case Resolution.R720P: +// realWidth = 1280; +// break; +// case Resolution.R1080P: +// realWidth = 1920; +// break; +// case Resolution.R2160P: +// realWidth = 2160; +// break; - } +// } - var mediaInfo = new MediaInfoModel - { - Width = realWidth - }; +// var mediaInfo = new MediaInfoModel +// { +// Width = realWidth +// }; - var movieInfo = Subject.AugmentMovieInfo(MovieInfo, mediaInfo); - movieInfo.Quality.Resolution.Should().BeEquivalentTo(resolution); - movieInfo.Quality.QualityDetectionSource.Should().BeEquivalentTo(QualityDetectionSource.Name); - } - } -} +// var movieInfo = Subject.AugmentMovieInfo(MovieInfo, mediaInfo); +// movieInfo.Quality.Resolution.Should().BeEquivalentTo(resolution); +// movieInfo.Quality.QualityDetectionSource.Should().BeEquivalentTo(QualityDetectionSource.Name); +// } +// } +//} diff --git a/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs index 72f031043..2387c1017 100644 --- a/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs @@ -24,27 +24,26 @@ namespace NzbDrone.Core.Test.ParserTests public static object[] OtherSourceQualityParserCases = { - new object[] { "SD TV", Source.TV, Resolution.R480P, Modifier.NONE }, - new object[] { "SD DVD", Source.DVD, Resolution.R480P, Modifier.NONE }, - new object[] { "480p WEB-DL", Source.WEBDL, Resolution.R480P, Modifier.NONE }, - new object[] { "HD TV", Source.TV, Resolution.R720P, Modifier.NONE }, - new object[] { "1080p HD TV", Source.TV, Resolution.R1080P, Modifier.NONE }, - new object[] { "2160p HD TV", Source.TV, Resolution.R2160P, Modifier.NONE }, - new object[] { "720p WEB-DL", Source.WEBDL, Resolution.R720P, Modifier.NONE }, - new object[] { "1080p WEB-DL", Source.WEBDL, Resolution.R1080P, Modifier.NONE }, - new object[] { "2160p WEB-DL", Source.WEBDL, Resolution.R2160P, Modifier.NONE }, - new object[] { "720p BluRay", Source.BLURAY, Resolution.R720P, Modifier.NONE }, - new object[] { "1080p BluRay", Source.BLURAY, Resolution.R1080P, Modifier.NONE }, - new object[] { "2160p BluRay", Source.BLURAY, Resolution.R2160P, Modifier.NONE }, - new object[] { "1080p Remux", Source.BLURAY, Resolution.R1080P, Modifier.REMUX }, - new object[] { "2160p Remux", Source.BLURAY, Resolution.R2160P, Modifier.REMUX }, + new object[] { "SD TV", Source.TV, Resolution.R480p, Modifier.NONE }, + new object[] { "SD DVD", Source.DVD, Resolution.R480p, Modifier.NONE }, + new object[] { "480p WEB-DL", Source.WEBDL, Resolution.R480p, Modifier.NONE }, + new object[] { "HD TV", Source.TV, Resolution.R720p, Modifier.NONE }, + new object[] { "1080p HD TV", Source.TV, Resolution.R1080p, Modifier.NONE }, + new object[] { "2160p HD TV", Source.TV, Resolution.R2160p, Modifier.NONE }, + new object[] { "720p WEB-DL", Source.WEBDL, Resolution.R720p, Modifier.NONE }, + new object[] { "1080p WEB-DL", Source.WEBDL, Resolution.R1080p, Modifier.NONE }, + new object[] { "2160p WEB-DL", Source.WEBDL, Resolution.R2160p, Modifier.NONE }, + new object[] { "720p BluRay", Source.BLURAY, Resolution.R720p, Modifier.NONE }, + new object[] { "1080p BluRay", Source.BLURAY, Resolution.R1080p, Modifier.NONE }, + new object[] { "2160p BluRay", Source.BLURAY, Resolution.R2160p, Modifier.NONE }, + new object[] { "1080p Remux", Source.BLURAY, Resolution.R1080p, Modifier.REMUX }, + new object[] { "2160p Remux", Source.BLURAY, Resolution.R2160p, Modifier.REMUX }, }; [TestCase("Despicable.Me.3.2017.720p.TSRip.x264.AAC-Ozlem", false)] - [TestCase("IT.2017.HDTSRip.x264.AAC-Ozlem[ETRG]", false)] public void should_parse_ts(string title, bool proper) { - ParseAndVerifyQuality(title, Source.TELESYNC, proper, Resolution.R720P); + ParseAndVerifyQuality(title, Source.TELESYNC, proper, Resolution.R720p); } [TestCase("S07E23 .avi ", false)] @@ -65,38 +64,32 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Muppet.Babies.S03.TVRip.XviD-NOGRP", false)] public void should_parse_sdtv_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.TV, proper, Resolution.R480P); + ParseAndVerifyQuality(title, Source.TV, proper, Resolution.R480p); } - [TestCase("WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3-REPACK.-HELLYWOOD.avi", true)] [TestCase("The.Shield.S01E13.NTSC.x264-CtrlSD", false)] - [TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", false)] - [TestCase("WEEDS.S03E01-06.DUAL.BDRip.X-viD.AC3.-HELLYWOOD", false)] - [TestCase("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi", false)] - [TestCase("WEEDS.S03E01-06.DUAL.XviD.Bluray.AC3.-HELLYWOOD.avi", false)] [TestCase("The.Girls.Next.Door.S03E06.DVDRip.XviD-WiDE", false)] [TestCase("The.Girls.Next.Door.S03E06.DVD.Rip.XviD-WiDE", false)] [TestCase("the.shield.1x13.circles.ws.xvidvd-tns", false)] [TestCase("the_x-files.9x18.sunshine_days.ac3.ws_dvdrip_xvid-fov.avi", false)] - [TestCase("[FroZen] Miyuki - 23 [DVD][7F6170E6]", false)] - [TestCase("[Doki] Clannad - 02 (848x480 XviD BD MP3) [95360783]", false)] - [TestCase("The.Shield.S01E13.x264-CtrlSD", false)] - [TestCase("[HorribleSubs] Yowamushi Pedal - 32 [480p]", false)] - [TestCase("[CR] Sailor Moon - 004 [480p][48CE2D0F]", false)] - [TestCase("[Hatsuyuki] Naruto Shippuuden - 363 [848x480][ADE35E38]", false)] public void should_parse_dvd_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.DVD, proper, Resolution.R480P); + ParseAndVerifyQuality(title, Source.DVD, proper, Resolution.R480p); } [TestCase("Elementary.S01E10.The.Leviathan.480p.WEB-DL.x264-mSD", false)] [TestCase("Glee.S04E10.Glee.Actually.480p.WEB-DL.x264-mSD", false)] [TestCase("The.Big.Bang.Theory.S06E11.The.Santa.Simulation.480p.WEB-DL.x264-mSD", false)] [TestCase("Da.Vincis.Demons.S02E04.480p.WEB.DL.nSD.x264-NhaNc3", false)] - [TestCase("Series.Title.1x04.ITA.WEBMux.x264-NovaRip", false)] public void should_parse_webdl480p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R480P); + ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R480p); + } + + [TestCase("Series.Title.1x04.ITA.WEBMux.x264-NovaRip", false)] + public void should_parse_webrip480p_quality(string title, bool proper) + { + ParseAndVerifyQuality(title, Source.WEBRIP, proper, Resolution.R480p); } [TestCase("Heidi Girl of the Alps (BD)(640x480(RAW) (BATCH 1) (1-13)", false)] @@ -104,7 +97,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", false)] public void should_parse_bluray480p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.BLURAY, proper, Resolution.R480P); + ParseAndVerifyQuality(title, Source.BLURAY, proper, Resolution.R480p); } [TestCase("Dexter - S01E01 - Title [HDTV]", false)] @@ -119,7 +112,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Survivorman.The.Lost.Pilots.Summer.HR.WS.PDTV.x264-DHD", false)] public void should_parse_hdtv720p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.TV, proper, Resolution.R720P); + ParseAndVerifyQuality(title, Source.TV, proper, Resolution.R720p); } @@ -129,10 +122,9 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Dexter - S01E01 - Title [HDTV-1080p]", false)] public void should_parse_hdtv1080p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.TV, proper, Resolution.R1080P); + ParseAndVerifyQuality(title, Source.TV, proper, Resolution.R1080p); } - [TestCase("Arrested.Development.S04E01.720p.WEBRip.AAC2.0.x264-NFRiP", false)] [TestCase("Vanguard S01E04 Mexicos Death Train 720p WEB DL", false)] [TestCase("Hawaii Five 0 S02E21 720p WEB DL DD5 1 H 264", false)] [TestCase("Castle S04E22 720p WEB DL DD5 1 H 264 NFHD", false)] @@ -146,24 +138,19 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Castle.S06E23.720p.WebHD.h264-euHD", false)] [TestCase("The.Nightly.Show.2016.03.14.720p.WEB.x264-spamTV", false)] [TestCase("The.Nightly.Show.2016.03.14.720p.WEB.h264-spamTV", false)] - [TestCase("Sonny.With.a.Chance.S02E15.720p", false)] - [TestCase("S07E23.mkv ", false)] - [TestCase("Sonny.With.a.Chance.S02E15.mkv", false)] - [TestCase("[Underwater-FFF] No Game No Life - 01 (720p) [27AAA0A0]", false)] - [TestCase("[Doki] Mahouka Koukou no Rettousei - 07 (1280x720 Hi10P AAC) [80AF7DDE]", false)] - [TestCase("[Doremi].Yes.Pretty.Cure.5.Go.Go!.31.[1280x720].[C65D4B1F].mkv", false)] - [TestCase("[HorribleSubs]_Fairy_Tail_-_145_[720p]", false)] - [TestCase("[Eveyuu] No Game No Life - 10 [Hi10P 1280x720 H264][10B23BD8]", false)] - [TestCase("Movie.Title.ITA.720p.WEBMux.x264-NovaRip", false)] [TestCase("BrainDead.S01E01.The.Insanity.Principle.720p.WEB-DL.DD5.1.H.264-BD", false)] public void should_parse_webdl720p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R720P); + ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R720p); + } + + [TestCase("Movie.Title.ITA.720p.WEBMux.x264-NovaRip", false)] + [TestCase("Arrested.Development.S04E01.720p.WEBRip.AAC2.0.x264-NFRiP", false)] + public void should_parse_webrip720p_quality(string title, bool proper) + { + ParseAndVerifyQuality(title, Source.WEBRIP, proper, Resolution.R720p); } - [TestCase("[HorribleSubs] Yowamushi Pedal - 32 [1080p]", false)] - [TestCase("Under the Dome S01E10 Let the Games Begin 1080p", false)] - [TestCase("Arrested.Development.S04E01.iNTERNAL.1080p.WEBRip.x264-QRUS", false)] [TestCase("CSI NY S09E03 1080p WEB DL DD5 1 H264 NFHD", false)] [TestCase("Two and a Half Men S10E03 1080p WEB DL DD5 1 H 264 NFHD", false)] [TestCase("Criminal.Minds.S08E01.1080p.WEB-DL.DD5.1.H264-NFHD", false)] @@ -180,23 +167,34 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Series Title S06E08 No One PROPER 1080p WEB H 264-EXCLUSIVE", true)] [TestCase("The.Simpsons.S25E21.Pay.Pal.1080p.WEB-DL.DD5.1.H.264-NTb", false)] [TestCase("The.Simpsons.2017.1080p.WEB-DL.DD5.1.H.264.Remux.-NTb", false)] - [TestCase("Series.Title.1x04.ITA.1080p.WEBMux.x264-NovaRip", false)] [TestCase("Fast.and.Furious.Presents.Hobbs.and.Shaw.2019.1080p.AMZN.WEB-DL.DDP5.1.H.264-NTG", false)] public void should_parse_webdl1080p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R1080P); + ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R1080p); + } + + [TestCase("Arrested.Development.S04E01.iNTERNAL.1080p.WEBRip.x264-QRUS", false)] + [TestCase("Series.Title.1x04.ITA.1080p.WEBMux.x264-NovaRip", false)] + public void should_parse_webrip1080p_quality(string title, bool proper) + { + ParseAndVerifyQuality(title, Source.WEBRIP, proper, Resolution.R1080p); } - [TestCase("CASANOVA S01E01.2160P AMZN WEBRIP DD2.0 HI10P X264-TROLLUHD", false)] - [TestCase("JUST ADD MAGIC S01E01.2160P AMZN WEBRIP DD2.0 X264-TROLLUHD", false)] - [TestCase("The.Man.In.The.High.Castle.S01E01.2160p.AMZN.WEBRip.DD2.0.Hi10p.X264-TrollUHD", false)] - [TestCase("The Man In the High Castle S01E01 2160p AMZN WEBRip DD2.0 Hi10P x264-TrollUHD", false)] [TestCase("The.Nightly.Show.2016.03.14.2160p.WEB.x264-spamTV", false)] [TestCase("The.Nightly.Show.2016.03.14.2160p.WEB.h264-spamTV", false)] [TestCase("The.Nightly.Show.2016.03.14.2160p.WEB.PROPER.h264-spamTV", true)] public void should_parse_webdl2160p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R2160P); + ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R2160p); + } + + [TestCase("CASANOVA S01E01.2160P AMZN WEBRIP DD2.0 HI10P X264-TROLLUHD", false)] + [TestCase("JUST ADD MAGIC S01E01.2160P AMZN WEBRIP DD2.0 X264-TROLLUHD", false)] + [TestCase("The.Man.In.The.High.Castle.S01E01.2160p.AMZN.WEBRip.DD2.0.Hi10p.X264-TrollUHD", false)] + [TestCase("The Man In the High Castle S01E01 2160p AMZN WEBRip DD2.0 Hi10P x264-TrollUHD", false)] + public void should_parse_webrip2160p_quality(string title, bool proper) + { + ParseAndVerifyQuality(title, Source.WEBRIP, proper, Resolution.R2160p); } [TestCase("WEEDS.S03E01-06.DUAL.Bluray.AC3.-HELLYWOOD.avi", false)] @@ -217,7 +215,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Opeth.Garden.Of.The.Titans.Live.At.Red.Rocks.Amphitheatre.2017.720p.MBluRay.x264-TREBLE.mkv", false)] public void should_parse_bluray720p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.BLURAY, proper, Resolution.R720P); + ParseAndVerifyQuality(title, Source.BLURAY, proper, Resolution.R720p); } [TestCase("Chuck - S01E03 - Come Fly With Me - 1080p BluRay.mkv", false)] @@ -234,14 +232,14 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Opeth.Garden.Of.The.Titans.Live.At.Red.Rocks.Amphitheatre.2017.1080p.MBluRay.x264-TREBLE.mkv", false)] public void should_parse_bluray1080p_quality(string title, bool proper) { - ParseAndVerifyQuality(title, Source.BLURAY, proper, Resolution.R1080P); + ParseAndVerifyQuality(title, Source.BLURAY, proper, Resolution.R1080p); } [TestCase("Movie.Name.2004.576p.BDRip.x264-HANDJOB")] [TestCase("Hannibal.S01E05.576p.BluRay.DD5.1.x264-HiSD")] public void should_parse_bluray576p_quality(string title) { - ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R576P); + ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R576p); } [TestCase("Contract.to.Kill.2016.REMUX.1080p.BluRay.AVC.DTS-HD.MA.5.1-iFT")] @@ -251,7 +249,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Wildling.2018.1080p.BluRay.REMUX.MPEG-2.DTS-HD.MA.5.1-EPSiLON")] public void should_parse_remux1080p_quality(string title) { - ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R1080P, Modifier.REMUX); + ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R1080p, Modifier.REMUX); } [TestCase("Contract.to.Kill.2016.REMUX.2160p.BluRay.AVC.DTS-HD.MA.5.1-iFT")] @@ -259,7 +257,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("The.Shining.1980.2160p.UHD.BluRay.Remux.HDR.HEVC.DTS-HD.MA.5.1-PmP.mkv")] public void should_parse_remux2160p_quality(string title) { - ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R2160P, Modifier.REMUX); + ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R2160p, Modifier.REMUX); } [TestCase("G.I.Joe.Retaliation.2013.BDISO")] @@ -270,13 +268,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Daylight.1996.Bluray.ISO")] public void should_parse_brdisk_1080p_quality(string title) { - ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R1080P, Modifier.BRDISK); - } - - [TestCase("Stripes (1981) 1080i HDTV DD5.1 MPEG2-TrollHD")] - public void should_parse_rawhd_quality(string title) - { - ParseAndVerifyQuality(title, Source.TV, false, Resolution.Unknown, Modifier.RAWHD); + ParseAndVerifyQuality(title, Source.BLURAY, false, Resolution.R1080p, Modifier.BRDISK); } //[TestCase("POI S02E11 1080i HDTV DD5.1 MPEG2-TrollHD", false)] @@ -371,12 +363,12 @@ namespace NzbDrone.Core.Test.ParserTests var result = QualityParser.ParseQuality(title); if (resolution != Resolution.Unknown) { - result.Resolution.Should().Be(resolution); + result.Quality.Resolution.Should().Be((int)resolution); } - result.Source.Should().Be(source); + result.Quality.Source.Should().Be(source); if (modifier != Modifier.NONE) { - result.Modifier.Should().Be(modifier); + result.Quality.Modifier.Should().Be(modifier); } var version = proper ? 2 : 1; diff --git a/src/NzbDrone.Core.Test/Qualities/QualityFinderFixture.cs b/src/NzbDrone.Core.Test/Qualities/QualityFinderFixture.cs index 63c30397f..8742a7769 100644 --- a/src/NzbDrone.Core.Test/Qualities/QualityFinderFixture.cs +++ b/src/NzbDrone.Core.Test/Qualities/QualityFinderFixture.cs @@ -1,6 +1,7 @@ using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser; using NzbDrone.Core.Qualities; namespace NzbDrone.Core.Test.Qualities @@ -11,52 +12,52 @@ namespace NzbDrone.Core.Test.Qualities [TestCase(Source.CAM, 480, Modifier.NONE)] [TestCase(Source.CAM, 1080, Modifier.NONE)] [TestCase(Source.CAM, 0, Modifier.NONE)] - public void should_return_CAM(Source source, Resolution resolution, Modifier modifier) + public void should_return_CAM(Source source, int resolution, Modifier modifier) { QualityFinder.FindBySourceAndResolution(source, resolution, modifier).Should().Be(Quality.CAM); } [TestCase(Source.CAM, 1080, Modifier.SCREENER)] [TestCase(Source.CAM, 0, Modifier.SCREENER)] - public void should_return_Unknown(Source source, Resolution resolution, Modifier modifier) + public void should_return_Unknown(Source source, int resolution, Modifier modifier) { QualityFinder.FindBySourceAndResolution(source, resolution, modifier).Should().Be(Quality.Unknown); } [TestCase(Source.DVD, 480, Modifier.REMUX)] - public void should_return_DVD_Remux(Source source, Resolution resolution, Modifier modifier) + public void should_return_DVD_Remux(Source source, int resolution, Modifier modifier) { QualityFinder.FindBySourceAndResolution(source, resolution, modifier).Should().Be(Quality.DVDR); } [TestCase(Source.DVD, 480, Modifier.NONE)] - public void should_return_DVD(Source source, Resolution resolution, Modifier modifier) + public void should_return_DVD(Source source, int resolution, Modifier modifier) { QualityFinder.FindBySourceAndResolution(source, resolution, modifier).Should().Be(Quality.DVD); } [TestCase(Source.TV, 480, Modifier.NONE)] - public void should_return_SDTV(Source source, Resolution resolution, Modifier modifier) + public void should_return_SDTV(Source source, int resolution, Modifier modifier) { QualityFinder.FindBySourceAndResolution(source, resolution, modifier).Should().Be(Quality.SDTV); } [TestCase(Source.TV, 720, Modifier.NONE)] [TestCase(Source.UNKNOWN, 720, Modifier.NONE)] - public void should_return_HDTV_720p(Source source, Resolution resolution, Modifier modifier) + public void should_return_HDTV_720p(Source source, int resolution, Modifier modifier) { QualityFinder.FindBySourceAndResolution(source, resolution, modifier).Should().Be(Quality.HDTV720p); } [TestCase(Source.TV, 1080, Modifier.NONE)] [TestCase(Source.UNKNOWN, 1080, Modifier.NONE)] - public void should_return_HDTV_1080p(Source source, Resolution resolution, Modifier modifier) + public void should_return_HDTV_1080p(Source source, int resolution, Modifier modifier) { QualityFinder.FindBySourceAndResolution(source, resolution, modifier).Should().Be(Quality.HDTV1080p); } [TestCase(Source.BLURAY, 720, Modifier.NONE)] - public void should_return_Bluray720p(Source source, Resolution resolution, Modifier modifier) + public void should_return_Bluray720p(Source source, int resolution, Modifier modifier) { QualityFinder.FindBySourceAndResolution(source, resolution, modifier).Should().Be(Quality.Bluray720p); } diff --git a/src/NzbDrone.Core/CustomFormats/FormatTag.cs b/src/NzbDrone.Core/CustomFormats/FormatTag.cs index 5a0ca7b92..63d896541 100644 --- a/src/NzbDrone.Core/CustomFormats/FormatTag.cs +++ b/src/NzbDrone.Core/CustomFormats/FormatTag.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text.RegularExpressions; using NzbDrone.Common.Extensions; using NzbDrone.Core.Languages; +using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.CustomFormats @@ -74,11 +75,11 @@ namespace NzbDrone.Core.CustomFormats case TagType.Language: return movieInfo.Languages.Contains((Language)Value); case TagType.Resolution: - return movieInfo.Quality.Resolution == (Resolution) Value; + return movieInfo.Quality.Quality.Resolution == (int)(Resolution) Value; case TagType.Modifier: - return movieInfo.Quality.Modifier == (Modifier) Value; + return movieInfo.Quality.Quality.Modifier == (Modifier) Value; case TagType.Source: - return movieInfo.Quality.Source == (Source) Value; + return movieInfo.Quality.Quality.Source == (Source) Value; case TagType.Size: var size = (movieInfo.ExtraInfo.GetValueOrDefault("Size", 0.0) as long?) ?? 0; var tuple = Value as (long, long)? ?? (0, 0); @@ -108,19 +109,19 @@ namespace NzbDrone.Core.CustomFormats switch (value) { case "2160": - Value = Resolution.R2160P; + Value = Resolution.R2160p; break; case "1080": - Value = Resolution.R1080P; + Value = Resolution.R1080p; break; case "720": - Value = Resolution.R720P; + Value = Resolution.R720p; break; case "576": - Value = Resolution.R576P; + Value = Resolution.R576p; break; case "480": - Value = Resolution.R480P; + Value = Resolution.R480p; break; } break; @@ -248,16 +249,6 @@ namespace NzbDrone.Core.CustomFormats AbsolutelyRequired = 4 } - public enum Resolution - { - Unknown = 0, - R480P = 480, - R576P = 576, - R720P = 720, - R1080P = 1080, - R2160P = 2160 - } - public enum Source { UNKNOWN = 0, @@ -268,6 +259,7 @@ namespace NzbDrone.Core.CustomFormats DVD, TV, WEBDL, + WEBRIP, BLURAY } diff --git a/src/NzbDrone.Core/Datastore/Migration/159_add_webrip_qualities.cs b/src/NzbDrone.Core/Datastore/Migration/159_add_webrip_qualities.cs new file mode 100644 index 000000000..c91e83ec6 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/159_add_webrip_qualities.cs @@ -0,0 +1,245 @@ +using System.Collections.Generic; +using System.Data; +using System.Linq; +using FluentMigrator; +using Newtonsoft.Json; +using NzbDrone.Common.Serializer; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(159)] + public class add_webrip_qualites : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Execute.WithConnection(ConvertProfile); + } + + private void ConvertProfile(IDbConnection conn, IDbTransaction tran) + { + var updater = new ProfileUpdater159(conn, tran); + + // updater.SplitQualityAppend(8, 12); // APE after Flac + // updater.SplitQualityAppend(5, 14); // APE after Flac + // updater.SplitQualityAppend(3, 15); // APE after Flacupdater.SplitQualityAppend(8, 12); // APE after Flac + // updater.SplitQualityAppend(18, 17); // APE after Flac + + updater.CreateGroupAt(8, "WEB 480p", new int[]{12}); // Group WEBRip480p with WEBDL480p + updater.CreateGroupAt(5, "WEB 720p", new int[]{14}); // Group WEBRip720p with WEBDL720p + updater.CreateGroupAt(3, "WEB 1080p", new int[]{15}); // Group WEBRip1080p with WEBDL1080p + updater.CreateGroupAt(18, "WEB 2160p", new int[]{17}); // Group WEBRip2160p with WEBDL2160p + + updater.Commit(); + } + } + + public class Profile159 + { + public int Id { get; set; } + public string Name { get; set; } + public int Cutoff { get; set; } + public List Items { get; set; } + } + + public class ProfileItem159 + { + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] + public int Id { get; set; } + + public string Name { get; set; } + public int? Quality { get; set; } + public List Items { get; set; } + public bool Allowed { get; set; } + + public ProfileItem159() + { + Items = new List(); + } + } + + public class ProfileUpdater159 + { + private readonly IDbConnection _connection; + private readonly IDbTransaction _transaction; + + private List _profiles; + private HashSet _changedProfiles = new HashSet(); + + public ProfileUpdater159(IDbConnection conn, IDbTransaction tran) + { + _connection = conn; + _transaction = tran; + + _profiles = GetProfiles(); + } + + public void Commit() + { + foreach (var profile in _changedProfiles) + { + using (var updateProfileCmd = _connection.CreateCommand()) + { + updateProfileCmd.Transaction = _transaction; + updateProfileCmd.CommandText = + "UPDATE Profiles SET Name = ?, Cutoff = ?, Items = ? WHERE Id = ?"; + updateProfileCmd.AddParameter(profile.Name); + updateProfileCmd.AddParameter(profile.Cutoff); + updateProfileCmd.AddParameter(profile.Items.ToJson()); + updateProfileCmd.AddParameter(profile.Id); + + updateProfileCmd.ExecuteNonQuery(); + } + } + + _changedProfiles.Clear(); + } + + public void CreateGroupAt(int find, string name, int[] newQualities) + { + foreach (var profile in _profiles) + { + var nextGroup = 1000; + + while (true) + { + if (profile.Items.FindIndex(v => v.Id == nextGroup) > -1) + { + nextGroup++; + } + else + { + break; + } + } + + + var findIndex = profile.Items.FindIndex(v => + { + return v.Quality == find || (v.Items != null && v.Items.Any(b => b.Quality == find)); + }); + + var isGrouped = !profile.Items.Any(p => p.Quality == find); + + + if (findIndex > -1 && !isGrouped) + { + var findQuality = profile.Items[findIndex]; + + var groupItems = new List(); + + foreach (var newQuality in newQualities) + { + groupItems.Add(new ProfileItem159 + { + Quality = newQuality, + Allowed = findQuality.Allowed + }); + } + + groupItems.Add(new ProfileItem159 + { + Quality = find, + Allowed = findQuality.Allowed + }); + + profile.Items.Insert(findIndex, new ProfileItem159 + { + Id = nextGroup, + Name = name, + Quality = null, + Items = groupItems, + Allowed = findQuality.Allowed + }); + } + else if (findIndex > -1 && isGrouped) + { + var findQuality = profile.Items[findIndex]; + + foreach (var newQuality in newQualities) + { + profile.Items[findIndex].Items.Insert(findIndex, new ProfileItem159 + { + Quality = newQuality, + Allowed = findQuality.Allowed + }); + } + } + else + { + // If the ID isn't found for some reason (mangled migration 71?) + + var groupItems = new List(); + + foreach (var newQuality in newQualities) + { + groupItems.Add(new ProfileItem159 + { + Quality = newQuality, + Allowed = false + }); + } + + groupItems.Add(new ProfileItem159 + { + Quality = find, + Allowed = false + }); + + profile.Items.Add(new ProfileItem159 + { + Id = nextGroup, + Name = name, + Quality = null, + Items = groupItems, + Allowed = false + }); + } + + foreach (var quality in newQualities) + { + var index = profile.Items.FindIndex(v => v.Quality == quality); + + if (index > -1) + { + profile.Items.RemoveAt(index); + } + + if (profile.Cutoff == quality) + { + profile.Cutoff = nextGroup; + } + } + + _changedProfiles.Add(profile); + } + } + + private List GetProfiles() + { + var profiles = new List(); + + using (var getProfilesCmd = _connection.CreateCommand()) + { + getProfilesCmd.Transaction = _transaction; + getProfilesCmd.CommandText = @"SELECT Id, Name, Cutoff, Items FROM Profiles"; + + using (var profileReader = getProfilesCmd.ExecuteReader()) + { + while (profileReader.Read()) + { + profiles.Add(new Profile159 + { + Id = profileReader.GetInt32(0), + Name = profileReader.GetString(1), + Cutoff = profileReader.GetInt32(2), + Items = Json.Deserialize>(profileReader.GetString(3)) + }); + } + } + } + + return profiles; + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs index cf82d886f..922f4001b 100644 --- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs +++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionMaker.cs @@ -42,15 +42,15 @@ namespace NzbDrone.Core.DecisionEngine public List GetRssDecision(List reports) { - return GetMovieDecisions(reports).ToList(); + return GetDecisions(reports).ToList(); } public List GetSearchDecision(List reports, SearchCriteriaBase searchCriteriaBase) { - return GetMovieDecisions(reports, searchCriteriaBase).ToList(); + return GetDecisions(reports, searchCriteriaBase).ToList(); } - private IEnumerable GetMovieDecisions(List reports, SearchCriteriaBase searchCriteria = null) + private IEnumerable GetDecisions(List reports, SearchCriteriaBase searchCriteria = null) { if (reports.Any()) { @@ -98,12 +98,6 @@ namespace NzbDrone.Core.DecisionEngine result.Movie = null; //To ensure we have a remote movie, else null exception on next line! result.RemoteMovie.ParsedMovieInfo = parsedMovieInfo; } - else - { - //Enhance Parsed Movie Info! - result.RemoteMovie.ParsedMovieInfo = Parser.Parser.ParseMinimalMovieTitle(parsedMovieInfo.MovieTitle, - result.RemoteMovie.Movie.Title, parsedMovieInfo.Year); - } } else @@ -148,7 +142,8 @@ namespace NzbDrone.Core.DecisionEngine } else { - remoteMovie.DownloadAllowed = true; + // _aggregationService.Augment(remoteMovie); + remoteMovie.DownloadAllowed = remoteMovie.Movie != null; decision = GetDecisionForReport(remoteMovie, searchCriteria); } diff --git a/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs b/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs index 2cbb7d417..43bc66264 100644 --- a/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs +++ b/src/NzbDrone.Core/Download/TrackedDownloads/TrackedDownloadService.cs @@ -75,24 +75,12 @@ namespace NzbDrone.Core.Download.TrackedDownloads public TrackedDownload TrackDownload(DownloadClientDefinition downloadClient, DownloadClientItem downloadItem) { - if (downloadItem.DownloadId.IsNullOrWhiteSpace()) - { - _logger.Warn("The following download client item ({0}) has no download hash (id), so it cannot be tracked: {1}", - downloadClient.Name, downloadItem.Title); - return null; - } - - if (downloadItem.Title.IsNullOrWhiteSpace()) - { - _logger.Warn("The following download client item ({0}) has no title so it cannot be tracked: {1}", - downloadClient.Name, downloadItem.Title); - return null; - } - var existingItem = Find(downloadItem.DownloadId); if (existingItem != null && existingItem.State != TrackedDownloadStage.Downloading) { + LogItemChange(existingItem, existingItem.DownloadItem, downloadItem); + existingItem.DownloadItem = downloadItem; existingItem.IsTrackable = true; @@ -141,9 +129,10 @@ namespace NzbDrone.Core.Download.TrackedDownloads } } + // Track it so it can be displayed in the queue even though we can't determine which movie it is for if (trackedDownload.RemoteMovie == null) { - return null; + _logger.Trace("No Movie found for download '{0}'", trackedDownload.DownloadItem.Title); } } catch (Exception e) @@ -152,6 +141,8 @@ namespace NzbDrone.Core.Download.TrackedDownloads return null; } + LogItemChange(trackedDownload, existingItem?.DownloadItem, trackedDownload.DownloadItem); + _cache.Set(trackedDownload.DownloadItem.DownloadId, trackedDownload); return trackedDownload; } diff --git a/src/NzbDrone.Core/MediaFiles/MediaFileExtensions.cs b/src/NzbDrone.Core/MediaFiles/MediaFileExtensions.cs index 4215fa253..b85ffaf1b 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaFileExtensions.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaFileExtensions.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using NzbDrone.Core.CustomFormats; using NzbDrone.Core.Qualities; @@ -9,115 +7,82 @@ namespace NzbDrone.Core.MediaFiles { public static class MediaFileExtensions { - private static Dictionary _fileExtensions; - private static Dictionary _resolutionExt; + private static Dictionary _fileExtensions; static MediaFileExtensions() { - _fileExtensions = new Dictionary + _fileExtensions = new Dictionary { //Unknown - { ".webm", Source.UNKNOWN }, + { ".webm", Quality.Unknown }, //SDTV - { ".m4v", Source.TV }, - { ".3gp", Source.TV }, - { ".nsv", Source.TV }, - { ".ty", Source.TV }, - { ".strm", Source.TV }, - { ".rm", Source.TV }, - { ".rmvb", Source.TV }, - { ".m3u", Source.TV }, - { ".ifo", Source.TV }, - { ".mov", Source.TV }, - { ".qt", Source.TV }, - { ".divx", Source.TV }, - { ".xvid", Source.TV }, - { ".bivx", Source.TV }, - { ".nrg", Source.TV }, - { ".pva", Source.TV }, - { ".wmv", Source.TV }, - { ".asf", Source.TV }, - { ".asx", Source.TV }, - { ".ogm", Source.TV }, - { ".ogv", Source.TV }, - { ".m2v", Source.TV }, - { ".avi", Source.TV }, - { ".bin", Source.TV }, - { ".dat", Source.TV }, - { ".dvr-ms", Source.TV }, - { ".mpg", Source.TV }, - { ".mpeg", Source.TV }, - { ".mp4", Source.TV }, - { ".avc", Source.TV }, - { ".vp3", Source.TV }, - { ".svq3", Source.TV }, - { ".nuv", Source.TV }, - { ".viv", Source.TV }, - { ".dv", Source.TV }, - { ".fli", Source.TV }, - { ".flv", Source.TV }, - { ".wpl", Source.TV }, + { ".m4v", Quality.SDTV }, + { ".3gp", Quality.SDTV }, + { ".nsv", Quality.SDTV }, + { ".ty", Quality.SDTV }, + { ".strm", Quality.SDTV }, + { ".rm", Quality.SDTV }, + { ".rmvb", Quality.SDTV }, + { ".m3u", Quality.SDTV }, + { ".ifo", Quality.SDTV }, + { ".mov", Quality.SDTV }, + { ".qt", Quality.SDTV }, + { ".divx", Quality.SDTV }, + { ".xvid", Quality.SDTV }, + { ".bivx", Quality.SDTV }, + { ".nrg", Quality.SDTV }, + { ".pva", Quality.SDTV }, + { ".wmv", Quality.SDTV }, + { ".asf", Quality.SDTV }, + { ".asx", Quality.SDTV }, + { ".ogm", Quality.SDTV }, + { ".ogv", Quality.SDTV }, + { ".m2v", Quality.SDTV }, + { ".avi", Quality.SDTV }, + { ".bin", Quality.SDTV }, + { ".dat", Quality.SDTV }, + { ".dvr-ms", Quality.SDTV }, + { ".mpg", Quality.SDTV }, + { ".mpeg", Quality.SDTV }, + { ".mp4", Quality.SDTV }, + { ".avc", Quality.SDTV }, + { ".vp3", Quality.SDTV }, + { ".svq3", Quality.SDTV }, + { ".nuv", Quality.SDTV }, + { ".viv", Quality.SDTV }, + { ".dv", Quality.SDTV }, + { ".fli", Quality.SDTV }, + { ".flv", Quality.SDTV }, + { ".wpl", Quality.SDTV }, //DVD - { ".img", Source.DVD }, - { ".iso", Source.DVD }, - { ".vob", Source.DVD }, + { ".img", Quality.DVD }, + { ".iso", Quality.DVD }, + { ".vob", Quality.DVD }, //HD - { ".mkv", Source.WEBDL }, - { ".mk3d", Source.WEBDL}, - { ".ts", Source.TV }, - { ".wtv", Source.TV }, + { ".mkv", Quality.WEBDL720p }, + { ".mk3d", Quality.WEBDL720p}, + { ".ts", Quality.SDTV }, + { ".wtv", Quality.SDTV }, //Bluray - { ".m2ts", Source.BLURAY } - }; - - _resolutionExt = new Dictionary - { - //HD - { ".mkv", Resolution.R720P }, - { ".mk3d", Resolution.R720P }, - { ".ts", Resolution.R720P }, - { ".wtv", Resolution.R720P }, - - //Bluray - { ".m2ts", Resolution.R720P } + { ".m2ts", Quality.Bluray720p} }; } public static HashSet Extensions => new HashSet(_fileExtensions.Keys, StringComparer.OrdinalIgnoreCase); - public static Source GetSourceForExtension(string extension) + public static Quality GetQualityForExtension(string extension) { if (_fileExtensions.ContainsKey(extension)) { return _fileExtensions[extension]; } - return Source.UNKNOWN; + return Quality.Unknown; } - public static Resolution GetResolutionForExtension(string extension) - { - if (_resolutionExt.ContainsKey(extension)) - { - return _resolutionExt[extension]; - } - - var source = Source.UNKNOWN; - if (_fileExtensions.ContainsKey(extension)) - { - source = _fileExtensions[extension]; - } - - if (source == Source.DVD || source == Source.TV) - { - return Resolution.R480P; - } - - return Resolution.Unknown; - } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQuality.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQuality.cs index a5474ff20..25cbff192 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQuality.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateQuality.cs @@ -3,6 +3,7 @@ using System.Linq; using NLog; using NzbDrone.Core.CustomFormats; using NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality; +using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Qualities; @@ -28,11 +29,12 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators var source = Source.UNKNOWN; var sourceConfidence = Confidence.Default; - var resolution = Resolution.Unknown; + var resolution = 0; var resolutionConfidence = Confidence.Default; var modifier = Modifier.NONE; var modifierConfidence = Confidence.Default; var revison = new Revision(); + var customFormats = new List(); foreach (var augmentedQuality in augmentedQualities) { @@ -61,11 +63,18 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators { revison = augmentedQuality.Revision; } + + if (augmentedQuality.CustomFormats != null) + { + var newFormats = augmentedQuality.CustomFormats.Where(c => !customFormats.Any(p => p.Id == c.Id)); + + customFormats.AddRange(newFormats); + } } _logger.Trace("Finding quality. Source: {0}. Resolution: {1}. Modifier {2}", source, resolution, modifier); - var quality = new QualityModel(QualityFinder.FindBySourceAndResolution(source, resolution, modifier), revison); + var quality = new QualityModel(QualityFinder.FindBySourceAndResolution(source, resolution, modifier), revison, customFormats); if (resolutionConfidence == Confidence.MediaInfo) { diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromDownloadClientItem.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromDownloadClientItem.cs index 09f02fe6b..1d3dd3a37 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromDownloadClientItem.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromDownloadClientItem.cs @@ -19,7 +19,8 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenter Confidence.Tag, quality.Quality.Modifier, Confidence.Tag, - quality.Revision); + quality.Revision, + quality.CustomFormats); } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFileName.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFileName.cs index e45db6f80..4636d359b 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFileName.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFileName.cs @@ -24,7 +24,8 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenter confidence, quality.Quality.Modifier, confidence, - quality.Revision); + quality.Revision, + quality.CustomFormats); } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFolder.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFolder.cs index 574212c20..6604cc2a2 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFolder.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromFolder.cs @@ -19,7 +19,8 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenter Confidence.Tag, quality.Quality.Modifier, Confidence.Tag, - quality.Revision); + quality.Revision, + quality.CustomFormats); } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromMediaInfo.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromMediaInfo.cs index 9f7fdc401..4de0de53a 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromMediaInfo.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityFromMediaInfo.cs @@ -1,4 +1,4 @@ -using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality @@ -16,22 +16,22 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenter if (width >= 3200) { - return AugmentQualityResult.ResolutionOnly(Resolution.R2160P, Confidence.MediaInfo); + return AugmentQualityResult.ResolutionOnly((int)Resolution.R2160p, Confidence.MediaInfo); } if (width >= 1800) { - return AugmentQualityResult.ResolutionOnly(Resolution.R1080P, Confidence.MediaInfo); + return AugmentQualityResult.ResolutionOnly((int)Resolution.R1080p, Confidence.MediaInfo); } if (width >= 1200) { - return AugmentQualityResult.ResolutionOnly(Resolution.R720P, Confidence.MediaInfo); + return AugmentQualityResult.ResolutionOnly((int)Resolution.R720p, Confidence.MediaInfo); } if (width > 0) { - return AugmentQualityResult.ResolutionOnly(Resolution.R480P, Confidence.MediaInfo); + return AugmentQualityResult.ResolutionOnly((int)Resolution.R480p, Confidence.MediaInfo); } return null; diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityResult.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityResult.cs index 11d40e55a..5adabb0bc 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityResult.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/Augmenters/Quality/AugmentQualityResult.cs @@ -1,5 +1,7 @@ using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser; using NzbDrone.Core.Qualities; +using System.Collections.Generic; namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenters.Quality { @@ -7,19 +9,22 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenter { public Source Source { get; set; } public Confidence SourceConfidence { get; set; } - public Resolution Resolution { get; set; } + public int Resolution { get; set; } public Confidence ResolutionConfidence { get; set; } public Modifier Modifier { get; set; } public Confidence ModifierConfidence { get; set; } public Revision Revision { get; set; } + public List CustomFormats { get; set; } + public AugmentQualityResult(Source source, Confidence sourceConfidence, - Resolution resolution, + int resolution, Confidence resolutionConfidence, Modifier modifier, Confidence modifierConfidence, - Revision revision) + Revision revision, + List customFormats) { Source = source; SourceConfidence = sourceConfidence; @@ -28,21 +33,22 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators.Augmenter Modifier = modifier; ModifierConfidence = modifierConfidence; Revision = revision; + CustomFormats = customFormats; } public static AugmentQualityResult SourceOnly(Source source, Confidence sourceConfidence) { - return new AugmentQualityResult(source, sourceConfidence, 0, Confidence.Default, Modifier.NONE, Confidence.Default, null); + return new AugmentQualityResult(source, sourceConfidence, 0, Confidence.Default, Modifier.NONE, Confidence.Default, null, null); } - public static AugmentQualityResult ResolutionOnly(Resolution resolution, Confidence resolutionConfidence) + public static AugmentQualityResult ResolutionOnly(int resolution, Confidence resolutionConfidence) { - return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, resolution, resolutionConfidence, Modifier.NONE, Confidence.Default, null); + return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, resolution, resolutionConfidence, Modifier.NONE, Confidence.Default, null, null); } public static AugmentQualityResult ModifierOnly(Modifier modifier, Confidence modifierConfidence) { - return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, 0, Confidence.Default, modifier, modifierConfidence, null); + return new AugmentQualityResult(Source.UNKNOWN, Confidence.Default, 0, Confidence.Default, modifier, modifierConfidence, null, null); } } } diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/ImportDecisionMaker.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/ImportDecisionMaker.cs index 7e626b441..c25d3c99f 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/ImportDecisionMaker.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/ImportDecisionMaker.cs @@ -36,6 +36,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport private readonly IQualityDefinitionService _qualitiesService; private readonly IConfigService _config; private readonly IHistoryService _historyService; + private readonly IParsingService _parsingService; private readonly ICached _warnedFiles; private readonly Logger _logger; @@ -47,6 +48,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport IQualityDefinitionService qualitiesService, IConfigService config, IHistoryService historyService, + IParsingService parsingService, ICacheManager cacheManager, Logger logger) { @@ -58,6 +60,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport _qualitiesService = qualitiesService; _config = config; _historyService = historyService; + _parsingService = parsingService; _warnedFiles = cacheManager.GetCache(this.GetType()); _logger = logger; } @@ -78,6 +81,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport if (downloadClientItem != null) { downloadClientItemInfo = Parser.Parser.ParseMovieTitle(downloadClientItem.Title, false); + downloadClientItemInfo = _parsingService.EnhanceMovieInfo(downloadClientItemInfo); } var nonSampleVideoFileCount = GetNonSampleVideoFileCount(newFiles, movie, downloadClientItemInfo, folderInfo); @@ -107,6 +111,11 @@ namespace NzbDrone.Core.MediaFiles.MovieImport var fileMovieInfo = Parser.Parser.ParseMoviePath(localMovie.Path, false); + if (fileMovieInfo != null) + { + fileMovieInfo = _parsingService.EnhanceMovieInfo(fileMovieInfo); + } + localMovie.FileMovieInfo = fileMovieInfo; localMovie.Size = _diskProvider.GetFileSize(localMovie.Path); diff --git a/src/NzbDrone.Core/Parser/Augmenters/AugmentWithMediaInfo.cs b/src/NzbDrone.Core/Parser/Augmenters/AugmentWithMediaInfo.cs index 6a7493b2a..5caed6efc 100644 --- a/src/NzbDrone.Core/Parser/Augmenters/AugmentWithMediaInfo.cs +++ b/src/NzbDrone.Core/Parser/Augmenters/AugmentWithMediaInfo.cs @@ -24,30 +24,30 @@ namespace NzbDrone.Core.Parser.Augmenters if (helper is MediaInfoModel mediaInfo) { var quality = movieInfo.Quality; - if (!(quality.Modifier == Modifier.BRDISK || quality.Modifier == Modifier.REMUX) && - (quality.Source == Source.BLURAY || quality.Source == Source.TV || - quality.Source == Source.WEBDL) && - !(quality.Resolution == Resolution.R480P || quality.Resolution == Resolution.R576P)) + if (!(quality.Quality.Modifier == Modifier.BRDISK || quality.Quality.Modifier == Modifier.REMUX) && + (quality.Quality.Source == Source.BLURAY || quality.Quality.Source == Source.TV || + quality.Quality.Source == Source.WEBDL) && + !(quality.Quality.Resolution == (int)Resolution.R480p || quality.Quality.Resolution == (int)Resolution.R576p)) { var width = mediaInfo.Width; - var existing = quality.Resolution; + var existing = quality.Quality.Resolution; if (width > 854) { - quality.Resolution = Resolution.R720P; + quality.Quality.Resolution = (int)Resolution.R720p; } if (width > 1280) { - quality.Resolution = Resolution.R1080P; + quality.Quality.Resolution = (int)Resolution.R1080p; } if (width > 1920) { - quality.Resolution = Resolution.R2160P; + quality.Quality.Resolution = (int)Resolution.R2160p; } - if (existing != quality.Resolution) + if (existing != quality.Quality.Resolution) { //_logger.Debug("Overwriting resolution info {0} with info from media info {1}", existing, quality.Resolution); quality.QualityDetectionSource = QualityDetectionSource.MediaInfo; diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 9012831f4..f67bc6435 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -99,24 +99,25 @@ namespace NzbDrone.Core.Parser private static readonly Regex ReportImdbId = new Regex(@"(?tt\d{7})", RegexOptions.IgnoreCase | RegexOptions.Compiled); - private static readonly Regex SimpleTitleRegex = new Regex(@"\s*(?:480[ip]|576[ip]|720[ip]|1080[ip]|2160[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*:|]|848x480|1280x720|1920x1080|(8|10)b(it)?)", + private static readonly RegexReplace SimpleTitleRegex = new RegexReplace(@"\s*(?:480[ip]|576[ip]|720[ip]|1080[ip]|2160[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*:|]|848x480|1280x720|1920x1080|(8|10)b(it)?)", + string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex SimpleReleaseTitleRegex = new Regex(@"\s*(?:[<>?*:|])", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex WebsitePrefixRegex = new Regex(@"^\[\s*[a-z]+(\.[a-z]+)+\s*\][- ]*|^www\.[a-z]+\.(?:com|net)[ -]*", - RegexOptions.IgnoreCase | RegexOptions.Compiled); - - private static readonly Regex AirDateRegex = new Regex(@"^(.*?)(?\d{4})[_.-](?[0-1][0-9])[_.-](?[0-3][0-9])|(?[0-1][0-9])[_.-](?[0-3][0-9])[_.-](?\d{4}))(?!\d)", + private static readonly RegexReplace WebsitePrefixRegex = new RegexReplace(@"^\[\s*[a-z]+(\.[a-z]+)+\s*\][- ]*|^www\.[a-z]+\.(?:com|net)[ -]*", + string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled); - private static readonly Regex SixDigitAirDateRegex = new Regex(@"(?<=[_.-])(?(?[1-9]\d{1})(?[0-1][0-9])(?[0-3][0-9]))(?=[_.-])", - RegexOptions.IgnoreCase | RegexOptions.Compiled); + private static readonly RegexReplace CleanReleaseGroupRegex = new RegexReplace(@"^(.*?[-._ ](S\d+E\d+)[-._ ])|(-(RP|1|NZBGeek|Obfuscated|Scrambled|sample|Pre|postbot|xpost|Rakuv[a-z0-9]*|WhiteRev|BUYMORE|AsRequested|AlternativeToRequested|GEROV|Z0iDS3N|Chamele0n|4P|4Planet))+$", + string.Empty, + RegexOptions.IgnoreCase | RegexOptions.Compiled); - private static readonly Regex CleanReleaseGroupRegex = new Regex(@"^(.*?[-._ ](S\d+E\d+)[-._ ])|(-(RP|1|NZBGeek|Obfuscated|sample|Pre|postbot|xpost|Rakuv[a-z0-9]*|WhiteRev|BUYMORE|AsRequested|AlternativeToRequested|GEROV|Z0iDS3N|Chamele0n))+$", + private static readonly RegexReplace CleanTorrentSuffixRegex = new RegexReplace(@"\[(?:ettv|rartv|rarbg|cttv)\]$", + string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled); - private static readonly Regex CleanTorrentSuffixRegex = new Regex(@"\[(?:ettv|rartv|rarbg|cttv)\]$", + private static readonly Regex CleanQualityBracketsRegex = new Regex(@"\[[a-z0-9 ._-]+\]$", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex ReleaseGroupRegex = new Regex(@"-(?[a-z0-9]+(?!.+?(?:480p|720p|1080p|2160p)))(?[a-z0-9]+)\]$", @@ -173,8 +174,6 @@ namespace NzbDrone.Core.Parser public static ParsedMovieInfo ParseMovieTitle(string title, bool isLenient, bool isDir = false) { - - ParsedMovieInfo realResult = null; try { if (!ValidateBeforeParsing(title)) return null; @@ -191,17 +190,26 @@ namespace NzbDrone.Core.Parser Logger.Debug("Reversed name detected. Converted to '{0}'", title); } - var simpleTitle = SimpleTitleRegex.Replace(title, string.Empty); + var releaseTitle = RemoveFileExtension(title); - simpleTitle = RemoveFileExtension(simpleTitle); + releaseTitle = releaseTitle.Replace("【", "[").Replace("】", "]"); - var simpleReleaseTitle = SimpleReleaseTitleRegex.Replace(title, string.Empty); - simpleReleaseTitle = RemoveFileExtension(simpleReleaseTitle); + var simpleTitle = SimpleTitleRegex.Replace(releaseTitle); // TODO: Quick fix stripping [url] - prefixes. - simpleTitle = WebsitePrefixRegex.Replace(simpleTitle, string.Empty); + simpleTitle = WebsitePrefixRegex.Replace(simpleTitle); - simpleTitle = CleanTorrentSuffixRegex.Replace(simpleTitle, string.Empty); + simpleTitle = CleanTorrentSuffixRegex.Replace(simpleTitle); + + simpleTitle = CleanQualityBracketsRegex.Replace(simpleTitle, m => + { + if (QualityParser.ParseQualityName(m.Value).Quality != Qualities.Quality.Unknown) + { + return string.Empty; + } + + return m.Value; + }); var allRegexes = ReportMovieTitleRegex.ToList(); @@ -231,14 +239,44 @@ namespace NzbDrone.Core.Parser if (result != null) { //TODO: Add tests for this! + + var simpleReleaseTitle = SimpleReleaseTitleRegex.Replace(title, string.Empty); + if (result.MovieTitle.IsNotNullOrWhiteSpace()) { simpleReleaseTitle = simpleReleaseTitle.Replace(result.MovieTitle, result.MovieTitle.Contains(".") ? "A.Movie" : "A Movie"); } + result.Languages = LanguageParser.EnhanceLanguages(simpleReleaseTitle, LanguageParser.ParseLanguages(releaseTitle)); + Logger.Debug("Languages parsed: {0}", result.Languages); + + result.Quality = QualityParser.ParseQuality(title); + Logger.Debug("Quality parsed: {0}", result.Quality); + + if (result.Edition.IsNullOrWhiteSpace()) + { + result.Edition = ParseEdition(simpleReleaseTitle); + } + + result.ReleaseGroup = ParseReleaseGroup(releaseTitle); + + var subGroup = GetSubGroup(match); + if (!subGroup.IsNullOrWhiteSpace()) + { + result.ReleaseGroup = subGroup; + } + + Logger.Debug("Release Group parsed: {0}", result.ReleaseGroup); + + result.ReleaseHash = GetReleaseHash(match); + if (!result.ReleaseHash.IsNullOrWhiteSpace()) + { + Logger.Debug("Release Hash parsed: {0}", result.ReleaseHash); + } + result.SimpleReleaseTitle = simpleReleaseTitle; - realResult = result; + result.ImdbId = ParseImdbId(simpleReleaseTitle); return result; } @@ -254,58 +292,11 @@ namespace NzbDrone.Core.Parser catch (Exception e) { if (!title.ToLower().Contains("password") && !title.ToLower().Contains("yenc")) - Logger.Error(e, "An error has occurred while trying to parse " + title); + Logger.Error(e, "An error has occurred while trying to parse {0}", title); } Logger.Debug("Unable to parse {0}", title); - return realResult; - } - - public static ParsedMovieInfo ParseMinimalMovieTitle(string title, string foundTitle, int foundYear) - { - var result = new ParsedMovieInfo {MovieTitle = foundTitle}; - - var languageTitle = Regex.Replace(title.Replace(".", " "), foundTitle, "A Movie", RegexOptions.IgnoreCase); - - result.Languages = LanguageParser.ParseLanguages(title); - Logger.Debug("Language parsed: {0}", result.Languages.ToExtendedString()); - - result.Quality = QualityParser.ParseQuality(title); - Logger.Debug("Quality parsed: {0}", result.Quality); - - if (result.Edition.IsNullOrWhiteSpace()) - { - result.Edition = ParseEdition(languageTitle); - } - - result.ReleaseGroup = ParseReleaseGroup(title); - - result.ImdbId = ParseImdbId(title); - - Logger.Debug("Release Group parsed: {0}", result.ReleaseGroup); - - if (foundYear > 1800) - { - result.Year = foundYear; - } - else - { - var match = ReportYearRegex.Match(title); - if (match.Success && match.Groups["year"].Value != null) - { - int year = 1290; - if (int.TryParse(match.Groups["year"].Value, out year)) - { - result.Year = year; - } - else - { - result.Year = year; - } - } - } - - return result; + return null; } public static string ParseImdbId(string title) @@ -421,7 +412,7 @@ namespace NzbDrone.Core.Parser { title = title.Trim(); title = RemoveFileExtension(title); - title = WebsitePrefixRegex.Replace(title, ""); + title = WebsitePrefixRegex.Replace(title); var animeMatch = AnimeReleaseGroupRegex.Match(title); @@ -430,7 +421,7 @@ namespace NzbDrone.Core.Parser return animeMatch.Groups["subgroup"].Value; } - title = CleanReleaseGroupRegex.Replace(title, ""); + title = CleanReleaseGroupRegex.Replace(title); var matches = ReleaseGroupRegex.Matches(title); diff --git a/src/NzbDrone.Core/Parser/ParsingService.cs b/src/NzbDrone.Core/Parser/ParsingService.cs index 4118ac166..3cfde5f37 100644 --- a/src/NzbDrone.Core/Parser/ParsingService.cs +++ b/src/NzbDrone.Core/Parser/ParsingService.cs @@ -25,9 +25,9 @@ namespace NzbDrone.Core.Parser Movie GetMovie(string title); MappingResult Map(ParsedMovieInfo parsedMovieInfo, string imdbId, SearchCriteriaBase searchCriteria = null); ParsedMovieInfo ParseMovieInfo(string title, List helpers); + ParsedMovieInfo EnhanceMovieInfo(ParsedMovieInfo parsedMovieInfo, List helpers = null); ParsedMovieInfo ParseMinimalMovieInfo(string path, bool isDir = false); ParsedMovieInfo ParseMinimalPathMovieInfo(string path); - List ParseCustomFormat(ParsedMovieInfo movieInfo); List MatchFormatTags(ParsedMovieInfo movieInfo); } @@ -65,40 +65,26 @@ namespace NzbDrone.Core.Parser public ParsedMovieInfo ParseMovieInfo(string title, List helpers) { var result = Parser.ParseMovieTitle(title, _config.ParsingLeniency > 0); + if (result == null) { return null; } - result = EnhanceMinimalInfo(result, helpers); + result = EnhanceMovieInfo(result, helpers); return result; } - private ParsedMovieInfo EnhanceMinimalInfo(ParsedMovieInfo minimalInfo, List helpers) + public ParsedMovieInfo EnhanceMovieInfo(ParsedMovieInfo minimalInfo, List helpers = null) { - minimalInfo.Languages = LanguageParser.ParseLanguages(minimalInfo.SimpleReleaseTitle); - _logger.Debug("Language(s) parsed: {0}", string.Join(", ", minimalInfo.Languages.ToExtendedString())); - - minimalInfo.Quality = QualityParser.ParseQuality(minimalInfo.SimpleReleaseTitle); - - if (minimalInfo.Edition.IsNullOrWhiteSpace()) + if (helpers != null) { - minimalInfo.Edition = Parser.ParseEdition(minimalInfo.SimpleReleaseTitle); + minimalInfo = AugmentMovieInfo(minimalInfo, helpers); } - minimalInfo.ReleaseGroup = Parser.ParseReleaseGroup(minimalInfo.SimpleReleaseTitle); - - minimalInfo.ImdbId = Parser.ParseImdbId(minimalInfo.SimpleReleaseTitle); - - minimalInfo = AugmentMovieInfo(minimalInfo, helpers); - - // After the augmenters have done their job on languages we can do our static method as well. - minimalInfo.Languages = - LanguageParser.EnhanceLanguages(minimalInfo.SimpleReleaseTitle, minimalInfo.Languages); - - minimalInfo.Quality.Quality = QualityFinder.FindBySourceAndResolution(minimalInfo.Quality.Source, minimalInfo.Quality.Resolution, - minimalInfo.Quality.Modifier); + // minimalInfo.Quality.Quality = QualityFinder.FindBySourceAndResolution(minimalInfo.Quality.Quality.Source, minimalInfo.Quality.Quality.Resolution, + // minimalInfo.Quality.Quality.Modifier); minimalInfo.Quality.CustomFormats = ParseCustomFormat(minimalInfo); @@ -120,7 +106,7 @@ namespace NzbDrone.Core.Parser return minimalInfo; } - public List ParseCustomFormat(ParsedMovieInfo movieInfo) + private List ParseCustomFormat(ParsedMovieInfo movieInfo) { var matches = MatchFormatTags(movieInfo); var goodMatches = matches.Where(m => m.GoodMatch); diff --git a/src/NzbDrone.Core/Parser/QualityParser.cs b/src/NzbDrone.Core/Parser/QualityParser.cs index facc425e2..026bba801 100644 --- a/src/NzbDrone.Core/Parser/QualityParser.cs +++ b/src/NzbDrone.Core/Parser/QualityParser.cs @@ -17,9 +17,11 @@ namespace NzbDrone.Core.Parser private static readonly Regex SourceRegex = new Regex(@"\b(?: (?M?BluRay|Blu-Ray|HDDVD|BD(?!$)|BDISO|BD25|BD50|BR.?DISK)| - (?WEB[-_. ]DL|HDRIP|WEBDL|WebRip|Web-Rip|iTunesHD|MaxdomeHD|NetflixU?HD|WebHD|WEBMux|[. ]WEB[. ](?:[xh]26[45]|DDP?5[. ]1)|\d+0p[-. ]WEB[-. ]|WEB-DLMux|\b\s\/\sWEB\s\/\s\b)| + (?WEB[-_. ]DL|WEBDL|AmazonHD|iTunesHD|MaxdomeHD|NetflixU?HD|WebHD|[. ]WEB[. ](?:[xh]26[45]|DDP?5[. ]1)|\d+0p[-. ]WEB[-. ]|WEB-DLMux|\b\s\/\sWEB\s\/\s\b)| + (?WebRip|Web-Rip|WEBMux)| (?HDTV)| - (?BDRip)|(?BRRip)| + (?BDRip)| + (?BRRip)| (?DVD-R|DVDR)| (?DVD|DVDRip|NTSC|PAL|xvidvd)| (?WS[-_. ]DSR|DSR)| @@ -35,13 +37,11 @@ namespace NzbDrone.Core.Parser )\b", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - private static readonly Regex HardcodedSubsRegex = new Regex(@"\b(?(\w+SUBS?)\b)|(?(HC|SUBBED))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - - private static readonly Regex RemuxRegex = new Regex(@"\b(?(BD)?[-_. ]?Remux)\b", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex RawHDRegex = new Regex(@"\b(?RawHD|1080i[-_. ]HDTV|Raw[-_. ]HD|MPEG[-_. ]?2)\b", + RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex BRDISKRegex = new Regex(@"\b(COMPLETE|ISO|BDISO|BD25|BD50|BR.?DISK)\b", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ProperRegex = new Regex(@"\b(?proper)\b", RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -55,7 +55,7 @@ namespace NzbDrone.Core.Parser private static readonly Regex RealRegex = new Regex(@"\b(?REAL)\b", RegexOptions.Compiled); - private static readonly Regex ResolutionRegex = new Regex(@"\b(?:(?480(i|p)|640x480|848x480)|(?576(i|p))|(?720(i|p)|1280x720)|(?1080p|1920x1080|1440p|FHD|1080i)|(?2160p|4k[-_. ](?:UHD|HEVC|BD)|(?:UHD|HEVC|BD)[-_. ]4k))\b", + private static readonly Regex ResolutionRegex = new Regex(@"\b(?:(?480p|640x480|848x480)|(?576p)|(?720p|1280x720)|(?1080p|1920x1080|1440p|FHD|1080i)|(?2160p|4k[-_. ](?:UHD|HEVC|BD)|(?:UHD|HEVC|BD)[-_. ]4k))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex CodecRegex = new Regex(@"\b(?:(?x264)|(?h264)|(?XvidHD)|(?X-?vid)|(?divx))\b", @@ -67,16 +67,41 @@ namespace NzbDrone.Core.Parser private static readonly Regex HighDefPdtvRegex = new Regex(@"hr[-_. ]ws", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex RemuxRegex = new Regex(@"\b(?(BD)?[-_. ]?Remux)\b", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex HDShitQualityRegex = new Regex(@"(HD-TS|HDTS|HDTSRip|HD-TC|HDTC|HDCAM|HD-CAM)", RegexOptions.Compiled | RegexOptions.IgnoreCase); - private static readonly Regex RawHDRegex = new Regex(@"\b(?RawHD|1080i[-_. ]HDTV|Raw[-_. ]HD|MPEG[-_. ]?2)\b", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex HardcodedSubsRegex = new Regex(@"\b(?(\w+SUBS?)\b)|(?(HC|SUBBED))\b", + RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); public static QualityModel ParseQuality(string name) { Logger.Debug("Trying to parse quality for {0}", name); name = name.Trim(); + + var result = ParseQualityName(name); + + // Based on extension + if (result.Quality == Quality.Unknown && !name.ContainsInvalidPathChars()) + { + try + { + result.Quality = MediaFileExtensions.GetQualityForExtension(Path.GetExtension(name)); + result.QualityDetectionSource = QualityDetectionSource.Extension; + } + catch (ArgumentException) + { + // Swallow exception for cases where string contains illegal + // path characters. + } + } + + return result; + } + + public static QualityModel ParseQualityName(string name) + { var normalizedName = name.Replace('_', ' ').Trim().ToLower(); var result = ParseQualityModifiers(name, normalizedName); var subMatch = HardcodedSubsRegex.Matches(normalizedName).OfType().LastOrDefault(); @@ -93,139 +118,210 @@ namespace NzbDrone.Core.Parser } } + var test = SourceRegex.Matches(normalizedName); var sourceMatch = SourceRegex.Matches(normalizedName).OfType().LastOrDefault(); var resolution = ParseResolution(normalizedName); var codecRegex = CodecRegex.Match(normalizedName); - - result.Resolution = resolution; - - if (BRDISKRegex.IsMatch(normalizedName) && sourceMatch?.Groups["bluray"].Success == true) - { - result.Modifier = Modifier.BRDISK; - result.Source = Source.BLURAY; - } - - if (RemuxRegex.IsMatch(normalizedName) && sourceMatch?.Groups["webdl"].Success != true && sourceMatch?.Groups["hdtv"].Success != true) - { - result.Modifier = Modifier.REMUX; - result.Source = Source.BLURAY; - return result; //We found remux! - } - - if (RawHDRegex.IsMatch(normalizedName) && result.Modifier != Modifier.BRDISK) - { - result.Modifier = Modifier.RAWHD; - result.Source = Source.TV; - return result; - } + var remuxMatch = RemuxRegex.IsMatch(normalizedName); + var brDiskMatch = BRDISKRegex.IsMatch(normalizedName); if (sourceMatch != null && sourceMatch.Success) { if (sourceMatch.Groups["bluray"].Success) { - result.Source = Source.BLURAY; + + if (brDiskMatch) + { + result.Quality = Quality.BRDISK; + return result; + } if (codecRegex.Groups["xvid"].Success || codecRegex.Groups["divx"].Success) { - result.Resolution = Resolution.R480P; - result.Source = Source.DVD; + result.Quality = Quality.Bluray480p; return result; } - if (resolution == Resolution.Unknown) result.Resolution = Resolution.R720P; //Blurays are always at least 720p - if (resolution == Resolution.Unknown && result.Modifier == Modifier.BRDISK) result.Resolution = Resolution.R1080P; // BRDISKS are 1080p + if (resolution == Resolution.R2160p) + { + result.Quality = remuxMatch ? Quality.Remux2160p : Quality.Bluray2160p; + + return result; + } + if (resolution == Resolution.R1080p) + { + result.Quality = remuxMatch ? Quality.Remux1080p : Quality.Bluray1080p; + return result; + } + + if (resolution == Resolution.R576p) + { + result.Quality = Quality.Bluray576p; + return result; + } + + if (resolution == Resolution.R480p) + { + result.Quality = Quality.Bluray480p; + return result; + } + + // Treat a remux without a source as 1080p, not 720p. + if (remuxMatch) + { + result.Quality = Quality.Remux1080p; + return result; + } + + result.Quality = Quality.Bluray720p; return result; } if (sourceMatch.Groups["webdl"].Success) { - result.Source = Source.WEBDL; - if (resolution == Resolution.Unknown) result.Resolution = Resolution.R480P; - if (resolution == Resolution.Unknown && name.Contains("[WEBDL]")) result.Resolution = Resolution.R720P; - return result; - } + if (resolution == Resolution.R2160p) + { + result.Quality = Quality.WEBDL2160p; + return result; + } - if (sourceMatch.Groups["hdtv"].Success) - { - result.Source = Source.TV; - if (resolution == Resolution.Unknown) result.Resolution = Resolution.R480P; //hdtvs are always at least 480p (they might have been downscaled - if (resolution == Resolution.Unknown && name.Contains("[HDTV]")) result.Resolution = Resolution.R720P; + if (resolution == Resolution.R1080p) + { + result.Quality = Quality.WEBDL1080p; + return result; + } + + if (resolution == Resolution.R720p) + { + result.Quality = Quality.WEBDL720p; + return result; + } + + if (name.Contains("[WEBDL]")) + { + result.Quality = Quality.WEBDL720p; + return result; + } + + result.Quality = Quality.WEBDL480p; return result; } - if (sourceMatch.Groups["bdrip"].Success || - sourceMatch.Groups["brrip"].Success) + if (sourceMatch.Groups["webrip"].Success) { - if (codecRegex.Groups["xvid"].Success || codecRegex.Groups["divx"].Success) + if (resolution == Resolution.R2160p) + { + result.Quality = Quality.WEBRip2160p; + return result; + } + + if (resolution == Resolution.R1080p) + { + result.Quality = Quality.WEBRip1080p; + return result; + } + + if (resolution == Resolution.R720p) { - // Since it's a dvd, res is 480p - result.Resolution = Resolution.R480P; - result.Source = Source.DVD; + result.Quality = Quality.WEBRip720p; return result; } - if (resolution == Resolution.Unknown) result.Resolution = Resolution.R480P; //BDRip are always 480p or more. + result.Quality = Quality.WEBRip480p; + return result; + } - result.Source = Source.BLURAY; + if (sourceMatch.Groups["scr"].Success) + { + result.Quality = Quality.DVDSCR; return result; } - if (sourceMatch.Groups["wp"].Success) + if (sourceMatch.Groups["cam"].Success) { - result.Source = Source.WORKPRINT; + result.Quality = Quality.CAM; return result; } - if (sourceMatch.Groups["dvd"].Success) + if (sourceMatch.Groups["ts"].Success) { - result.Resolution = Resolution.R480P; - result.Source = Source.DVD; + result.Quality = Quality.TELESYNC; + result.Quality.Resolution = (int)resolution; return result; } - if (sourceMatch.Groups["dvdr"].Success) + if (sourceMatch.Groups["tc"].Success) { - result.Resolution = Resolution.R480P; - result.Source = Source.DVD; - //result.Modifier = Modifier.REGIONAL; + result.Quality = Quality.TELECINE; return result; } - if (sourceMatch.Groups["scr"].Success) + if (sourceMatch.Groups["wp"].Success) { - result.Resolution = Resolution.R480P; - result.Source = Source.DVD; - result.Modifier = Modifier.SCREENER; + result.Quality = Quality.WORKPRINT; return result; } if (sourceMatch.Groups["regional"].Success) { - result.Resolution = Resolution.R480P; - result.Source = Source.DVD; - result.Modifier = Modifier.REGIONAL; + result.Quality = Quality.REGIONAL; return result; } - // they're shit, but at least 720p - if (HDShitQualityRegex.IsMatch(normalizedName)) result.Resolution = Resolution.R720P; - - if (sourceMatch.Groups["cam"].Success) + if (sourceMatch.Groups["hdtv"].Success) { - result.Source = Source.CAM; + if (resolution == Resolution.R2160p) + { + result.Quality = Quality.HDTV2160p; + return result; + } + + if (resolution == Resolution.R1080p) + { + result.Quality = Quality.HDTV1080p; + return result; + } + + if (resolution == Resolution.R720p) + { + result.Quality = Quality.HDTV720p; + return result; + } + + if (name.Contains("[HDTV]")) + { + result.Quality = Quality.HDTV720p; + return result; + } + + result.Quality = Quality.SDTV; return result; } - if (sourceMatch.Groups["ts"].Success) + if (sourceMatch.Groups["bdrip"].Success || + sourceMatch.Groups["brrip"].Success) { - result.Source = Source.TELESYNC; - return result; + switch (resolution) + { + case Resolution.R720p: + result.Quality = Quality.Bluray720p; + return result; + case Resolution.R1080p: + result.Quality = Quality.Bluray1080p; + return result; + case Resolution.R576p: + result.Quality = Quality.Bluray576p; + return result; + default: + result.Quality = Quality.Bluray480p; + return result; + } } - if (sourceMatch.Groups["tc"].Success) + if (sourceMatch.Groups["dvd"].Success) { - result.Source = Source.TELECINE; + result.Quality = Quality.DVD; return result; } @@ -234,128 +330,142 @@ namespace NzbDrone.Core.Parser sourceMatch.Groups["dsr"].Success || sourceMatch.Groups["tvrip"].Success) { - result.Source = Source.TV; + if (resolution == Resolution.R1080p || normalizedName.Contains("1080p")) + { + result.Quality = Quality.HDTV1080p; + return result; + } + + if (resolution == Resolution.R720p || normalizedName.Contains("720p")) + { + result.Quality = Quality.HDTV720p; + return result; + } + if (HighDefPdtvRegex.IsMatch(normalizedName)) { - result.Resolution = Resolution.R720P; + result.Quality = Quality.HDTV720p; return result; } - result.Resolution = Resolution.R480P; + result.Quality = Quality.SDTV; return result; } } - //Anime Bluray matching + + // Anime Bluray matching if (AnimeBlurayRegex.Match(normalizedName).Success) { - if (resolution == Resolution.R480P || resolution == Resolution.R576P || normalizedName.Contains("480p")) + if (resolution == Resolution.R480p || resolution == Resolution.R576p || normalizedName.Contains("480p")) { - result.Resolution = Resolution.R480P; - result.Source = Source.DVD; + result.Quality = Quality.DVD; return result; } - if (resolution == Resolution.R1080P || normalizedName.Contains("1080p")) + if (resolution == Resolution.R1080p || normalizedName.Contains("1080p")) { - result.Resolution = Resolution.R1080P; - result.Source = Source.BLURAY; + result.Quality = remuxMatch ? Quality.Remux1080p : Quality.Bluray1080p; return result; } - result.Resolution = Resolution.R720P; - result.Source = Source.BLURAY; + if (resolution == Resolution.R2160p || normalizedName.Contains("2160p")) + { + result.Quality = remuxMatch ? Quality.Remux2160p : Quality.Bluray2160p; + return result; + } + + // Treat a remux without a source as 1080p, not 720p. + if (remuxMatch) + { + result.Quality = Quality.Bluray1080p; + return result; + } + + result.Quality = Quality.Bluray720p; return result; } - var otherSourceMatch = OtherSourceMatch(normalizedName); + if (resolution == Resolution.R2160p) + { + result.Quality = remuxMatch ? Quality.Remux2160p : Quality.HDTV2160p; + return result; + } - if (otherSourceMatch.Source != Source.UNKNOWN) + if (resolution == Resolution.R1080p) { - result.Source = otherSourceMatch.Source; - result.Resolution = resolution == Resolution.Unknown ? otherSourceMatch.Resolution : resolution; + result.Quality = remuxMatch ? Quality.Remux1080p : Quality.HDTV1080p; return result; } - if (resolution == Resolution.R2160P || resolution == Resolution.R1080P || resolution == Resolution.R720P) + if (resolution == Resolution.R720p) { - result.Source = Source.WEBDL; + result.Quality = Quality.HDTV720p; return result; } - if (resolution == Resolution.R480P) + if (resolution == Resolution.R480p) { - result.Source = Source.DVD; + result.Quality = Quality.SDTV; return result; } if (codecRegex.Groups["x264"].Success) { - result.Source = Source.DVD; - result.Resolution = Resolution.R480P; + result.Quality = Quality.SDTV; return result; } if (normalizedName.Contains("848x480")) { + if (normalizedName.Contains("dvd")) + { + result.Quality = Quality.DVD; + } - result.Source = Source.DVD; - result.Resolution = Resolution.R480P; - return result; - + result.Quality = Quality.SDTV; } if (normalizedName.Contains("1280x720")) { - result.Resolution = Resolution.R720P; - result.Source = Source.WEBDL; if (normalizedName.Contains("bluray")) { - result.Source = Source.BLURAY; + result.Quality = Quality.Bluray720p; } - return result; + + result.Quality = Quality.HDTV720p; } if (normalizedName.Contains("1920x1080")) { - result.Resolution = Resolution.R1080P; - result.Source = Source.WEBDL; if (normalizedName.Contains("bluray")) { - result.Source = Source.BLURAY; + result.Quality = Quality.Bluray1080p; } - return result; + + result.Quality = Quality.HDTV1080p; } if (normalizedName.Contains("bluray720p")) { - result.Resolution = Resolution.R720P; - result.Source = Source.BLURAY; - return result; + result.Quality = Quality.Bluray720p; } if (normalizedName.Contains("bluray1080p")) { - result.Resolution = Resolution.R1080P; - result.Source = Source.BLURAY; - return result; + result.Quality = Quality.Bluray1080p; } - //Based on extension - if (result.Source == Source.UNKNOWN && !name.ContainsInvalidPathChars()) + if (normalizedName.Contains("bluray2160p")) { - try - { - result.Source = MediaFileExtensions.GetSourceForExtension(Path.GetExtension(name)); - result.Resolution = MediaFileExtensions.GetResolutionForExtension(Path.GetExtension(name)); + result.Quality = Quality.Bluray2160p; + } - result.QualityDetectionSource = QualityDetectionSource.Extension; - } - catch (ArgumentException) - { - //Swallow exception for cases where string contains illegal - //path characters. - } + var otherSourceMatch = OtherSourceMatch(normalizedName); + + if (otherSourceMatch != Quality.Unknown) + { + result.Quality = otherSourceMatch; } return result; @@ -366,29 +476,29 @@ namespace NzbDrone.Core.Parser var match = ResolutionRegex.Match(name); if (!match.Success) return Resolution.Unknown; - if (match.Groups["R480p"].Success) return Resolution.R480P; - if (match.Groups["R576p"].Success) return Resolution.R576P; - if (match.Groups["R720p"].Success) return Resolution.R720P; - if (match.Groups["R1080p"].Success) return Resolution.R1080P; - if (match.Groups["R2160p"].Success) return Resolution.R2160P; + if (match.Groups["R480p"].Success) return Resolution.R480p; + if (match.Groups["R576p"].Success) return Resolution.R576p; + if (match.Groups["R720p"].Success) return Resolution.R720p; + if (match.Groups["R1080p"].Success) return Resolution.R1080p; + if (match.Groups["R2160p"].Success) return Resolution.R2160p; return Resolution.Unknown; } - private static QualityModel OtherSourceMatch(string name) + private static Quality OtherSourceMatch(string name) { var match = OtherSourceRegex.Match(name); - if (!match.Success) return new QualityModel(); - if (match.Groups["sdtv"].Success) return new QualityModel {Source = Source.TV, Resolution = Resolution.R480P}; - if (match.Groups["hdtv"].Success) return new QualityModel {Source = Source.TV, Resolution = Resolution.R720P}; + if (!match.Success) return Quality.Unknown; + if (match.Groups["sdtv"].Success) return Quality.SDTV; + if (match.Groups["hdtv"].Success) return Quality.HDTV720p; - return new QualityModel(); + return Quality.Unknown; } private static QualityModel ParseQualityModifiers(string name, string normalizedName) { - var result = new QualityModel(); + var result = new QualityModel { Quality = Quality.Unknown }; if (ProperRegex.IsMatch(normalizedName)) { @@ -408,8 +518,8 @@ namespace NzbDrone.Core.Parser result.Revision.Version = Convert.ToInt32(versionRegexResult.Groups["version"].Value); } - //TODO: re-enable this when we have a reliable way to determine real - //TODO: Only treat it as a real if it comes AFTER the season/epsiode number + // TODO: re-enable this when we have a reliable way to determine real + // TODO: Only treat it as a real if it comes AFTER the season/episode number var realRegexResult = RealRegex.Matches(name); if (realRegexResult.Count > 0) @@ -420,4 +530,14 @@ namespace NzbDrone.Core.Parser return result; } } + + public enum Resolution + { + Unknown, + R480p = 480, + R576p = 576, + R720p = 720, + R1080p = 1080, + R2160p = 2160 + } } diff --git a/src/NzbDrone.Core/Parser/RegexReplace.cs b/src/NzbDrone.Core/Parser/RegexReplace.cs new file mode 100644 index 000000000..11fdf579f --- /dev/null +++ b/src/NzbDrone.Core/Parser/RegexReplace.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace NzbDrone.Core.Parser +{ + public class RegexReplace + { + private readonly Regex _regex; + private readonly string _replacementFormat; + private readonly MatchEvaluator _replacementFunc; + + public RegexReplace(string pattern, string replacement, RegexOptions regexOptions) + { + _regex = new Regex(pattern, regexOptions); + _replacementFormat = replacement; + } + + public RegexReplace(string pattern, MatchEvaluator replacement, RegexOptions regexOptions) + { + _regex = new Regex(pattern, regexOptions); + _replacementFunc = replacement; + } + + public string Replace(string input) + { + if (_replacementFunc != null) + return _regex.Replace(input, _replacementFunc); + else + return _regex.Replace(input, _replacementFormat); + } + + public bool TryReplace(ref string input) + { + var result = _regex.IsMatch(input); + if (_replacementFunc != null) + input = _regex.Replace(input, _replacementFunc); + else + input = _regex.Replace(input, _replacementFormat); + return result; + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Core/Profiles/ProfileService.cs b/src/NzbDrone.Core/Profiles/ProfileService.cs index 080cbb379..26144318b 100644 --- a/src/NzbDrone.Core/Profiles/ProfileService.cs +++ b/src/NzbDrone.Core/Profiles/ProfileService.cs @@ -130,9 +130,13 @@ namespace NzbDrone.Core.Profiles Quality.HDTV1080p, Quality.HDTV2160p, Quality.WEBDL480p, + Quality.WEBRip480p, Quality.WEBDL720p, + Quality.WEBRip720p, Quality.WEBDL1080p, + Quality.WEBRip1080p, Quality.WEBDL2160p, + Quality.WEBRip2160p, Quality.Bluray480p, Quality.Bluray576p, Quality.Bluray720p, @@ -152,23 +156,27 @@ namespace NzbDrone.Core.Profiles Quality.SDTV, Quality.DVD, Quality.WEBDL480p, + Quality.WEBRip480p, Quality.Bluray480p, Quality.Bluray576p); AddDefaultProfile("HD-720p", Quality.Bluray720p, Quality.HDTV720p, Quality.WEBDL720p, + Quality.WEBRip720p, Quality.Bluray720p); AddDefaultProfile("HD-1080p", Quality.Bluray1080p, Quality.HDTV1080p, Quality.WEBDL1080p, + Quality.WEBRip1080p, Quality.Bluray1080p, Quality.Remux1080p); AddDefaultProfile("Ultra-HD", Quality.Remux2160p, Quality.HDTV2160p, Quality.WEBDL2160p, + Quality.WEBRip2160p, Quality.Bluray2160p, Quality.Remux2160p); @@ -176,7 +184,9 @@ namespace NzbDrone.Core.Profiles Quality.HDTV720p, Quality.HDTV1080p, Quality.WEBDL720p, + Quality.WEBRip720p, Quality.WEBDL1080p, + Quality.WEBRip1080p, Quality.Bluray720p, Quality.Bluray1080p, Quality.Remux1080p, diff --git a/src/NzbDrone.Core/Qualities/Quality.cs b/src/NzbDrone.Core/Qualities/Quality.cs index e417f84f2..c43b850cb 100644 --- a/src/NzbDrone.Core/Qualities/Quality.cs +++ b/src/NzbDrone.Core/Qualities/Quality.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser; using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Qualities @@ -11,14 +12,14 @@ namespace NzbDrone.Core.Qualities public int Id { get; set; } public string Name { get; set; } public Source Source { get; set; } - public Resolution Resolution { get; set; } + public int Resolution { get; set; } public Modifier Modifier { get; set; } public Quality() { } - private Quality(int id, string name, Source source, Resolution resolution, Modifier modifier = Modifier.NONE) + private Quality(int id, string name, Source source, int resolution, Modifier modifier = Modifier.NONE) { Id = id; Name = name; @@ -27,12 +28,6 @@ namespace NzbDrone.Core.Qualities Modifier = modifier; } - private Quality(int id, string name, Source source, int resolution, Modifier modifier = Modifier.NONE) - : this(id, name, source, (Resolution) resolution, modifier) - { - - } - public override string ToString() { return Name; @@ -105,11 +100,16 @@ namespace NzbDrone.Core.Qualities public static Quality Remux1080p => new Quality(30, "Remux-1080p", Source.BLURAY, 1080, Modifier.REMUX); public static Quality Remux2160p => new Quality(31, "Remux-2160p", Source.BLURAY, 2160, Modifier.REMUX); - public static Quality BRDISK => new Quality(22, "BR-DISK", Source.BLURAY, 0, Modifier.BRDISK); // new + public static Quality BRDISK => new Quality(22, "BR-DISK", Source.BLURAY, 1080, Modifier.BRDISK); // new // Others public static Quality RAWHD => new Quality(10, "Raw-HD", Source.TV, 1080, Modifier.RAWHD); + public static Quality WEBRip480p => new Quality(12, "WEBRip-480p", Source.WEBRIP, 480); + public static Quality WEBRip720p => new Quality(14, "WEBRip-720p", Source.WEBRIP, 720); + public static Quality WEBRip1080p => new Quality(15, "WEBRip-1080p", Source.WEBRIP, 1080); + public static Quality WEBRip2160p => new Quality(17, "WEBRip-2160p", Source.WEBRIP, 2160); + static Quality() { All = new List @@ -131,6 +131,10 @@ namespace NzbDrone.Core.Qualities WEBDL720p, WEBDL1080p, WEBDL2160p, + WEBRip480p, + WEBRip720p, + WEBRip1080p, + WEBRip2160p, Bluray480p, Bluray576p, Bluray720p, @@ -161,21 +165,25 @@ namespace NzbDrone.Core.Qualities new QualityDefinition(Quality.DVD) { Weight = 9, MinSize = 0, MaxSize = 100 }, new QualityDefinition(Quality.DVDR) { Weight = 10, MinSize = 0, MaxSize = 100 }, - new QualityDefinition(Quality.WEBDL480p) { Weight = 11, MinSize = 0, MaxSize = 100 }, + new QualityDefinition(Quality.WEBDL480p) { Weight = 11, MinSize = 0, MaxSize = 100, GroupName = "WEB 480p" }, + new QualityDefinition(Quality.WEBRip480p) { Weight = 11, MinSize = 0, MaxSize = 100, GroupName = "WEB 480p" }, new QualityDefinition(Quality.Bluray480p) { Weight = 12, MinSize = 0, MaxSize = 100 }, new QualityDefinition(Quality.Bluray576p) { Weight = 13, MinSize = 0, MaxSize = 100 }, new QualityDefinition(Quality.HDTV720p) { Weight = 14, MinSize = 0, MaxSize = 100 }, - new QualityDefinition(Quality.WEBDL720p) { Weight = 15, MinSize = 0, MaxSize = 100 }, + new QualityDefinition(Quality.WEBDL720p) { Weight = 15, MinSize = 0, MaxSize = 100, GroupName = "WEB 720p" }, + new QualityDefinition(Quality.WEBRip720p) { Weight = 15, MinSize = 0, MaxSize = 100, GroupName = "WEB 720p" }, new QualityDefinition(Quality.Bluray720p) { Weight = 16, MinSize = 0, MaxSize = 100 }, new QualityDefinition(Quality.HDTV1080p) { Weight = 17, MinSize = 0, MaxSize = 100 }, - new QualityDefinition(Quality.WEBDL1080p) { Weight = 18, MinSize = 0, MaxSize = 100 }, + new QualityDefinition(Quality.WEBDL1080p) { Weight = 18, MinSize = 0, MaxSize = 100, GroupName = "WEB 1080p" }, + new QualityDefinition(Quality.WEBRip1080p) { Weight = 18, MinSize = 0, MaxSize = 100, GroupName = "WEB 1080p" }, new QualityDefinition(Quality.Bluray1080p) { Weight = 19, MinSize = 0, MaxSize = null }, new QualityDefinition(Quality.Remux1080p) { Weight = 20, MinSize = 0, MaxSize = null }, new QualityDefinition(Quality.HDTV2160p) { Weight = 21, MinSize = 0, MaxSize = null }, - new QualityDefinition(Quality.WEBDL2160p) { Weight = 22, MinSize = 0, MaxSize = null }, + new QualityDefinition(Quality.WEBDL2160p) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "WEB 2160p" }, + new QualityDefinition(Quality.WEBRip2160p) { Weight = 22, MinSize = 0, MaxSize = null, GroupName = "WEB 2160p" }, new QualityDefinition(Quality.Bluray2160p) { Weight = 23, MinSize = 0, MaxSize = null }, new QualityDefinition(Quality.Remux2160p) { Weight = 24, MinSize = 0, MaxSize = null }, diff --git a/src/NzbDrone.Core/Qualities/QualityFinder.cs b/src/NzbDrone.Core/Qualities/QualityFinder.cs index fd4a2ae30..2c3dd754f 100644 --- a/src/NzbDrone.Core/Qualities/QualityFinder.cs +++ b/src/NzbDrone.Core/Qualities/QualityFinder.cs @@ -2,6 +2,7 @@ using System.Linq; using NLog; using NzbDrone.Common.Instrumentation; using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser; namespace NzbDrone.Core.Qualities { @@ -9,7 +10,7 @@ namespace NzbDrone.Core.Qualities { private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(QualityFinder)); - public static Quality FindBySourceAndResolution(Source source, Resolution resolution, Modifier modifer) + public static Quality FindBySourceAndResolution(Source source, int resolution, Modifier modifer) { // Check for a perfect 3-way match var matchingQuality = Quality.All.SingleOrDefault(q => q.Source == source && q.Resolution == resolution && q.Modifier == modifer); @@ -20,7 +21,7 @@ namespace NzbDrone.Core.Qualities } // Check for Source and Modifier Match for Qualities with Unknown Resolution - var matchingQualitiesUnknownResolution = Quality.All.Where(q => q.Source == source && (q.Resolution == Resolution.Unknown) && q.Modifier == modifer && q != Quality.Unknown); + var matchingQualitiesUnknownResolution = Quality.All.Where(q => q.Source == source && (q.Resolution == 0) && q.Modifier == modifer && q != Quality.Unknown); if (matchingQualitiesUnknownResolution.Any()) { diff --git a/src/NzbDrone.Core/Qualities/QualityModel.cs b/src/NzbDrone.Core/Qualities/QualityModel.cs index 99a033e86..2dc53cb73 100644 --- a/src/NzbDrone.Core/Qualities/QualityModel.cs +++ b/src/NzbDrone.Core/Qualities/QualityModel.cs @@ -12,13 +12,6 @@ namespace NzbDrone.Core.Qualities public List CustomFormats { get; set; } - [JsonIgnore] - public Resolution Resolution { get; set; } - [JsonIgnore] - public Source Source { get; set; } - [JsonIgnore] - public Modifier Modifier { get; set; } - public Revision Revision { get; set; } @@ -33,11 +26,11 @@ namespace NzbDrone.Core.Qualities } - public QualityModel(Quality quality, Revision revision = null) + public QualityModel(Quality quality, Revision revision = null, List customFormats = null) { Quality = quality; Revision = revision ?? new Revision(); - CustomFormats = new List(); + CustomFormats = customFormats ?? new List(); } public override string ToString()