diff --git a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs index 3a541227f..13e15ee8a 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs @@ -10,34 +10,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestFixture] public class ParserFixture : CoreTest { - /*Fucked-up hall of shame, - * WWE.Wrestlemania.27.PPV.HDTV.XviD-KYR - * Unreported.World.Chinas.Lost.Sons.WS.PDTV.XviD-FTP - * [TestCase("Big Time Rush 1x01 to 10 480i DD2 0 Sianto", "Big Time Rush", 1, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 10)] - * [TestCase("Desparate Housewives - S07E22 - 7x23 - And Lots of Security.. [HDTV-720p].mkv", "Desparate Housewives", 7, new[] { 22, 23 }, 2)] - * [TestCase("S07E22 - 7x23 - And Lots of Security.. [HDTV-720p].mkv", "", 7, new[] { 22, 23 }, 2)] - * (Game of Thrones s03 e - "Game of Thrones Season 3 Episode 10" - * The.Man.of.Steel.1994-05.33.hybrid.DreamGirl-Novus-HD - * Superman.-.The.Man.of.Steel.1994-06.34.hybrid.DreamGirl-Novus-HD - * Superman.-.The.Man.of.Steel.1994-05.33.hybrid.DreamGirl-Novus-HD - * Constantine S1-E1-WEB-DL-1080p-NZBgeek - */ - - [TestCase("Chuck - 4x05 - Title", "Chuck")] - [TestCase("Law & Order - 4x05 - Title", "laworder")] [TestCase("Bad Format", "badformat")] - [TestCase("Mad Men - Season 1 [Bluray720p]", "madmen")] - [TestCase("Mad Men - Season 1 [Bluray1080p]", "madmen")] - [TestCase("The Daily Show With Jon Stewart -", "thedailyshowwithjonstewart")] - [TestCase("The Venture Bros. (2004)", "theventurebros2004")] - [TestCase("Castle (2011)", "castle2011")] - [TestCase("Adventure Time S02 720p HDTV x264 CRON", "adventuretime")] - [TestCase("Hawaii Five 0", "hawaiifive0")] - [TestCase("Match of the Day", "matchday")] - [TestCase("Match of the Day 2", "matchday2")] - [TestCase("[ www.Torrenting.com ] - Revenge.S03E14.720p.HDTV.X264-DIMENSION", "Revenge")] - [TestCase("Seed S02E09 HDTV x264-2HD [eztv]-[rarbg.com]", "Seed")] - [TestCase("Reno.911.S01.DVDRip.DD2.0.x264-DEEP", "Reno 911")] public void should_parse_artist_name(string postTitle, string title) { var result = Parser.Parser.ParseArtistName(postTitle).CleanArtistName(); @@ -58,14 +31,14 @@ namespace NzbDrone.Core.Test.ParserTests Parser.Parser.ParseAlbumTitle(postTitle); } - [TestCase("[scnzbefnet][509103] 2.Broke.Girls.S03E18.720p.HDTV.X264-DIMENSION", "2 Broke Girls")] + [TestCase("[scnzbefnet][509103] Jay-Z - 4:44 (Deluxe Edition) (2017) 320", "Jay-Z")] public void should_remove_request_info_from_title(string postTitle, string title) { Parser.Parser.ParseAlbumTitle(postTitle).ArtistName.Should().Be(title); } - [TestCase("Revolution.S01E02.Chained.Heat.mkv")] - [TestCase("Dexter - S01E01 - Title.avi")] + [TestCase("02 Unchained.flac")] + [TestCase("Fall Out Boy - 02 - Title.wav")] public void should_parse_quality_from_extension(string title) { Parser.Parser.ParseAlbumTitle(title).Quality.Quality.Should().NotBe(Quality.Unknown); @@ -76,7 +49,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("ATCQ - The Love Movement 1998 2CD 192kbps RIP", "ATCQ", "The Love Movement")] [TestCase("A Tribe Called Quest - The Love Movement 1998 2CD [192kbps] RIP", "A Tribe Called Quest", "The Love Movement")] [TestCase("Maula - Jism 2 [2012] Mp3 - 192Kbps [Extended]- TK", "Maula", "Jism 2")] - [TestCase("VA - Complete Clubland - The Ultimate Ride Of Your Lfe [2014][MP3][192 kbps]", "VA", "")] + [TestCase("VA - Complete Clubland - The Ultimate Ride Of Your Lfe [2014][MP3][192 kbps]", "VA", "Complete Clubland - The Ultimate Ride Of Your Lfe")] [TestCase("Complete Clubland - The Ultimate Ride Of Your Lfe [2014][MP3](192kbps)", "Complete Clubland", "The Ultimate Ride Of Your Lfe")] [TestCase("The Ultimate Ride Of Your Lfe [192 KBPS][2014][MP3]", "", "The Ultimate Ride Of Your Lfe")] [TestCase("Gary Clark Jr - Live North America 2016 (2017) MP3 192kbps", "Gary Clark Jr", "Live North America 2016")] @@ -86,7 +59,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Ricardo Arjona - APNEA (Single 2014) (320 kbps)", "Ricardo Arjona", "APNEA")] [TestCase("Kehlani - SweetSexySavage (Deluxe Edition) (2017) 320", "Kehlani", "SweetSexySavage")] [TestCase("Anderson Paak - Malibu (320)(2016)", "Anderson Paak", "Malibu")] - [TestCase("Caetano Veloso Discografia Completa MP3 @256", "Caetano Veloso", "")] + [TestCase("Caetano Veloso Discografia Completa MP3 @256", "Caetano Veloso", "", true)] [TestCase("Little Mix - Salute [Deluxe Edition] [2013] [M4A-256]-V3nom [GLT", "Little Mix", "Salute")] [TestCase("Ricky Martin - A Quien Quiera Escuchar (2015) 256 kbps [GloDLS]", "Ricky Martin", "A Quien Quiera Escuchar")] [TestCase("Jake Bugg - Jake Bugg (Album) [2012] {MP3 256 kbps}", "Jake Bugg", "Jake Bugg")] @@ -107,7 +80,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("The Rolling Stones - The Very Best Of '75-'94 (1995) {FLAC}", "The Rolling Stones", "The Very Best Of '75-'94")] [TestCase("Migos-No_Label_II-CD-FLAC-2014-FORSAKEN", "Migos", "No Label II")] [TestCase("ADELE 25 CD FLAC 2015 PERFECT", "Adele", "25")] - [TestCase("A.I. - Sex & Robots [2007/MP3/V0(VBR)]", "A.I.", "Sex & Robots")] + [TestCase("A.I. - Sex & Robots [2007/MP3/V0(VBR)]", "A I", "Sex & Robots")] [TestCase("Jay-Z - 4:44 (Deluxe Edition) (2017) 320", "Jay-Z", "444")] [TestCase("Roberta Flack 2006 - The Very Best of", "Roberta Flack", "The Very Best of")] [TestCase("VA - NOW Thats What I Call Music 96 (2017) [Mp3~Kbps]", "VA", "NOW Thats What I Call Music 96")] @@ -118,12 +91,16 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("Dani_Sbert-Togheter-WEB-2017-FURY", "Dani Sbert", "Togheter")] [TestCase("New.Edition-One.Love-CD-FLAC-2017-MrFlac", "New Edition", "One Love")] [TestCase("David_Gray-The_Best_of_David_Gray-(Deluxe_Edition)-2CD-2016-MTD", "David Gray", "The Best of David Gray")] - public void should_parse_artist_name_and_album_title(string postTitle, string name, string title) + [TestCase("Shinedown-Us and Them-NMR-2005-NMR", "Shinedown", "Us and Them")] + [TestCase("Captain-Discography_1998_-_2001-CD-FLAC-2007-UTP", "Captain", "", true)] + [TestCase("Coolio - Gangsta's Paradise (1995) (FLAC Lossless)", "Coolio", "Gangsta's Paradise")] + public void should_parse_artist_name_and_album_title(string postTitle, string name, string title, bool discography = false) { var parseResult = Parser.Parser.ParseAlbumTitle(postTitle); parseResult.ArtistName.Should().Be(name); parseResult.AlbumTitle.Should().Be(title); + parseResult.Discography.Should().Be(discography); } } } diff --git a/src/NzbDrone.Core/Parser/Model/ParsedAlbumInfo.cs b/src/NzbDrone.Core/Parser/Model/ParsedAlbumInfo.cs index fadf4bbe2..534ec611a 100644 --- a/src/NzbDrone.Core/Parser/Model/ParsedAlbumInfo.cs +++ b/src/NzbDrone.Core/Parser/Model/ParsedAlbumInfo.cs @@ -15,6 +15,7 @@ namespace NzbDrone.Core.Parser.Model public ArtistTitleInfo ArtistTitleInfo { get; set; } public QualityModel Quality { get; set; } public string ReleaseDate { get; set; } + public bool Discography { get; set; } public Language Language { get; set; } public string ReleaseGroup { get; set; } public string ReleaseHash { get; set; } diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 7e90621d8..099521f64 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -19,74 +19,87 @@ namespace NzbDrone.Core.Parser private static readonly Regex[] ReportMusicTitleRegex = new[] { - // Track with artist (01 - artist - trackName) - new Regex(@"(?\d*){0,1}([-| ]{0,1})(?[a-zA-Z0-9, ().&_]*)[-| ]{0,1}(?[a-zA-Z0-9, ().&_]+)", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + // Track with artist (01 - artist - trackName) + new Regex(@"(?\d*){0,1}([-| ]{0,1})(?[a-zA-Z0-9, ().&_]*)[-| ]{0,1}(?[a-zA-Z0-9, ().&_]+)", + RegexOptions.IgnoreCase | RegexOptions.Compiled), - // Track without artist (01 - trackName) - new Regex(@"(?\d*)[-| .]{0,1}(?[a-zA-Z0-9, ().&_]+)", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + // Track without artist (01 - trackName) + new Regex(@"(?\d*)[-| .]{0,1}(?[a-zA-Z0-9, ().&_]+)", + RegexOptions.IgnoreCase | RegexOptions.Compiled), - // Track without trackNumber or artist(trackName) - new Regex(@"(?\d*)[-| .]{0,1}(?[a-zA-Z0-9, ().&_]+)", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + // Track without trackNumber or artist(trackName) + new Regex(@"(?\d*)[-| .]{0,1}(?[a-zA-Z0-9, ().&_]+)", + RegexOptions.IgnoreCase | RegexOptions.Compiled), - // Track without trackNumber and with artist(artist - trackName) - new Regex(@"(?\d*)[-| .]{0,1}(?[a-zA-Z0-9, ().&_]+)", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + // Track without trackNumber and with artist(artist - trackName) + new Regex(@"(?\d*)[-| .]{0,1}(?[a-zA-Z0-9, ().&_]+)", + RegexOptions.IgnoreCase | RegexOptions.Compiled), - // Track with artist and starting title (01 - artist - trackName) - new Regex(@"(?\d*){0,1}[-| ]{0,1}(?[a-zA-Z0-9, ().&_]*)[-| ]{0,1}(?[a-zA-Z0-9, ().&_]+)", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + // Track with artist and starting title (01 - artist - trackName) + new Regex(@"(?\d*){0,1}[-| ]{0,1}(?[a-zA-Z0-9, ().&_]*)[-| ]{0,1}(?[a-zA-Z0-9, ().&_]+)", + RegexOptions.IgnoreCase | RegexOptions.Compiled), }; private static readonly Regex[] ReportAlbumTitleRegex = new[] { - //Artist-Album-Version-Source-Year - //ex. Imagine Dragons-Smoke And Mirrors-Deluxe Edition-2CD-FLAC-2015-JLM - new Regex(@"^(?.+?)[-](?.+?)[-](?:[\(|\[]?)(?.+?(?:Edition)?)(?:[\)|\]]?)[-](?\d?CD|WEB).+?(?\d{4})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), - - //Artist-Album-Source-Year - //ex. Dani_Sbert-Togheter-WEB-2017-FURY - new Regex(@"^(?.+?)[-](?.+?)[-](?\d?CD|WEB).+?(?\d{4})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), - - //Artist - Album (Year) Strict - new Regex(@"^(?:(?.+?)(?: - )+)(?.+?)\W*(?:\(|\[).+?(?\d{4})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), - - //Artist - Album (Year) - new Regex(@"^(?:(?.+?)(?: - )+)(?.+?)\W*(?:\(|\[)(?\d{4})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), - - //Artist - Album - new Regex(@"^(?:(?.+?)(?: - )+)(?.+?)\W*(?:\(|\[)", - RegexOptions.IgnoreCase | RegexOptions.Compiled), - - //Artist - Album Year - new Regex(@"^(?:(?.+?)(?: - )+)(?.+?)\W*(\d{4}|\d{3})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), - - //Artist Discography - new Regex(@"^(?.+?)\W*(?Discograghy|Discografia).+(?\d{4}).+(?\d{4})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), - - //Artist - Album (Year) Strict - new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(?:\(|\[).+?(?\d{4})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), - //Artist - Album (Year) - new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(?:\(|\[)(?\d{4})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + //Artist Discography with two years + new Regex(@"^(?.+?)\W*(?Discography|Discografia).+?(?\d{4}).+?(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), - //Artist - Album - new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(?:\(|\[)", + //Artist Discography + new Regex(@"^(?.+?)\W*(?Discography|Discografia)", RegexOptions.IgnoreCase | RegexOptions.Compiled), - //Artist - Album Year - new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(\d{4}|\d{3})", - RegexOptions.IgnoreCase | RegexOptions.Compiled), + //Artist-Album-Version-Source-Year + //ex. Imagine Dragons-Smoke And Mirrors-Deluxe Edition-2CD-FLAC-2015-JLM + new Regex(@"^(?.+?)[-](?.+?)[-](?:[\(|\[]?)(?.+?(?:Edition)?)(?:[\)|\]]?)[-](?\d?CD|WEB).+?(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist-Album-Source-Year + //ex. Dani_Sbert-Togheter-WEB-2017-FURY + new Regex(@"^(?.+?)[-](?.+?)[-](?\d?CD|WEB).+?(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist - Album (Year) Strict + new Regex(@"^(?:(?.+?)(?: - )+)(?.+?)\W*(?:\(|\[).+?(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist - Album (Year) + new Regex(@"^(?:(?.+?)(?: - )+)(?.+?)\W*(?:\(|\[)(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist - Album [something] or Artist - Album (something) + new Regex(@"^(?:(?.+?)(?: - )+)(?.+?)\W*(?:\(|\[)", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist - Album Year + new Regex(@"^(?:(?.+?)(?: - )+)(?.+?)\W*(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist-Album (Year) Strict + //Hyphen no space between artist and album + new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(?:\(|\[).+?(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist-Album (Year) + //Hyphen no space between artist and album + new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(?:\(|\[)(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist-Album [something] or Artist-Album (something) + //Hyphen no space between artist and album + new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(?:\(|\[)", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist-Album-something-Year + new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)(?:-.+?)(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), + + //Artist-Album Year + //Hyphen no space between artist and album + new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(?\d{4})", + RegexOptions.IgnoreCase | RegexOptions.Compiled), }; private static readonly Regex[] RejectHashedReleasesRegex = new Regex[] @@ -166,7 +179,7 @@ namespace NzbDrone.Core.Parser var fileInfo = new FileInfo(path); - var result = new ParsedTrackInfo{ }; + var result = new ParsedTrackInfo { }; if (MediaFiles.MediaFileExtensions.Extensions.Contains(fileInfo.Extension)) { @@ -497,7 +510,7 @@ namespace NzbDrone.Core.Parser var trackNumber = file.Tag.Track; var trackTitle = file.Tag.Title; - var discNumber = (file.Tag.Disc > 0) ? Convert.ToInt32(file.Tag.Disc) : 1 ; + var discNumber = (file.Tag.Disc > 0) ? Convert.ToInt32(file.Tag.Disc) : 1; var artist = file.Tag.FirstAlbumArtist; @@ -528,12 +541,12 @@ namespace NzbDrone.Core.Parser Title = trackTitle }; - foreach (TagLib.ICodec codec in file.Properties.Codecs) + foreach (ICodec codec in file.Properties.Codecs) { - TagLib.IAudioCodec acodec = codec as TagLib.IAudioCodec; - TagLib.IVideoCodec vcodec = codec as TagLib.IVideoCodec; + IAudioCodec acodec = codec as IAudioCodec; + IVideoCodec vcodec = codec as IVideoCodec; - if (acodec != null && (acodec.MediaTypes & TagLib.MediaTypes.Audio) != TagLib.MediaTypes.None) + if (acodec != null && (acodec.MediaTypes & MediaTypes.Audio) != MediaTypes.None) { Logger.Debug("Audio Properties : " + acodec.Description + ", Bitrate: " + acodec.AudioBitrate + ", Sample Size: " + file.Properties.BitsPerSample + ", SampleRate: " + acodec.AudioSampleRate + ", Channels: " + acodec.AudioChannels); @@ -657,6 +670,11 @@ namespace NzbDrone.Core.Parser result.ReleaseDate = releaseYear.ToString(); result.ReleaseVersion = releaseVersion; + if (matchCollection[0].Groups["discography"].Success) + { + result.Discography = true; + } + Logger.Debug("Album Parsed. {0}", result); return result;