diff --git a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs index e60b3cefd..3e6d19d68 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParserFixture.cs @@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.ParserTests public class ParserFixture : CoreTest { Artist _artist = new Artist(); - private List _albums = new List{new Album()}; + private List _albums = new List { new Album() }; [SetUp] public void Setup() @@ -24,12 +24,17 @@ namespace NzbDrone.Core.Test.ParserTests _artist = Builder .CreateNew() .Build(); + _albums = Builder> + .CreateNew() + .Build(); } private void GivenSearchCriteria(string artistName, string albumTitle) { _artist.Name = artistName; - _albums.First().Title = albumTitle; + var a = new Album(); + a.Title = albumTitle; + _albums.Add(a); } [TestCase("Bad Format", "badformat")] @@ -43,7 +48,7 @@ namespace NzbDrone.Core.Test.ParserTests public void should_remove_accents_from_title() { const string title = "Carniv\u00E0le"; - + title.CleanArtistName().Should().Be("carnivale"); } @@ -82,16 +87,16 @@ namespace NzbDrone.Core.Test.ParserTests Parser.Parser.ParseAlbumTitle(postTitle).ArtistName.Should().Be(title); } - [TestCase("02 Unchained.flac")] - [TestCase("Fall Out Boy - 02 - Title.wav")] + [TestCase("02 Unchained.flac")] // This isn't valid on any regex we have. We must always have an artist + [TestCase("Fall Out Boy - 02 - Title.wav")] // This isn't valid on any regex we have. We don't support Artist - Track - TrackName public void should_parse_quality_from_extension(string title) { Parser.Parser.ParseAlbumTitle(title).Quality.Quality.Should().NotBe(Quality.Unknown); Parser.Parser.ParseAlbumTitle(title).Quality.QualitySource.Should().Be(QualitySource.Extension); } - [TestCase("of Montreal-Hissing Fauna, Are You The Destroyer? 2007", "Hissing Fauna, Are You The Destroyer", "of Montreal", "2007")] - [TestCase("of Montreal - 2007 - Hissing Fauna, Are You The Destroyer?", "Hissing Fauna, Are You The Destroyer", "of Montreal", "2007")] + [TestCase("of Montreal-Hissing Fauna, Are You The Destroyer? 2007", "Hissing Fauna, Are You The Destroyer?", "of Montreal", "2007")] + [TestCase("of Montreal - 2007 - Hissing Fauna, Are You The Destroyer?", "Hissing Fauna, Are You The Destroyer?", "of Montreal", "2007")] public void should_parse_album(string title, string correctAlbum, string correctArtist, string correctYear) { ParsedAlbumInfo result = Parser.Parser.ParseAlbumTitle(title); @@ -203,5 +208,29 @@ namespace NzbDrone.Core.Test.ParserTests var parseResult = Parser.Parser.ParseAlbumTitleWithSearchCriteria("Black Sabbath Black Sabbath FLAC", _artist, _albums); parseResult.Should().BeNull(); } + + [TestCase("Ed Sheeran", "I See Fire", "Ed Sheeran I See Fire[Mimp3.eu].mp3 FLAC")] + [TestCase("Ed Sheeran", "Divide", "Ed Sheeran ? Divide FLAC")] + [TestCase("Ed Sheeran", "+", "Ed Sheeran + FLAC")] + //[TestCase("Glasvegas", @"EUPHORIC /// HEARTBREAK \\\", @"EUPHORIC /// HEARTBREAK \\\ FLAC")] // slashes not being escaped properly + [TestCase("XXXTENTACION", "?", "XXXTENTACION ? FLAC")] + [TestCase("Hey", "BŁYSK", "Hey - BŁYSK FLAC")] + public void should_escape_albums(string artist, string album, string releaseTitle) + { + GivenSearchCriteria(artist, album); + var parseResult = Parser.Parser.ParseAlbumTitleWithSearchCriteria(releaseTitle, _artist, _albums); + parseResult.AlbumTitle.Should().Be(album); + } + + [TestCase("???", "Album", "??? Album FLAC")] + [TestCase("+", "Album", "+ Album FLAC")] + [TestCase(@"/\", "Album", @"/\ Album FLAC")] + [TestCase("+44", "When Your Heart Stops Beating", "+44 When Your Heart Stops Beating FLAC")] + public void should_escape_artists(string artist, string album, string releaseTitle) + { + GivenSearchCriteria(artist, album); + var parseResult = Parser.Parser.ParseAlbumTitleWithSearchCriteria(releaseTitle, _artist, _albums); + parseResult.ArtistName.Should().Be(artist); + } } } diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index c2d573a56..4765732c3 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -122,7 +122,7 @@ namespace NzbDrone.Core.Parser //Artist-Album Year //Hyphen no space between artist and album - new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\W*(?\d{4})", + new Regex(@"^(?:(?.+?)(?:-)+)(?.+?)\b(?\d{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled), @@ -163,7 +163,7 @@ namespace NzbDrone.Core.Parser private static readonly Regex FileExtensionRegex = new Regex(@"\.[a-z0-9]{2,4}$", RegexOptions.IgnoreCase | RegexOptions.Compiled); - private static readonly Regex SimpleTitleRegex = new Regex(@"(?:(480|720|1080|2160|320)[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*:|]|848x480|1280x720|1920x1080|3840x2160|4096x2160|(8|10)b(it)?)\s*", + private static readonly Regex SimpleTitleRegex = new Regex(@"(?:(480|720|1080|2160|320)[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>*:|]|848x480|1280x720|1920x1080|3840x2160|4096x2160|(8|10)b(it)?)\s*", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex WebsitePrefixRegex = new Regex(@"^\[\s*[a-z]+(\.[a-z]+)+\s*\][- ]*", @@ -351,8 +351,11 @@ namespace NzbDrone.Core.Parser simpleTitle = CleanTorrentSuffixRegex.Replace(simpleTitle, string.Empty); - var releaseRegex = new Regex(@"\b(?" + artist.Name + @")\b.*\b(?"+ string.Join("|",album.Select(s=>s.Title).ToList()) + @")\b", - RegexOptions.IgnoreCase | RegexOptions.Compiled); + var escapedArtist = Regex.Escape(artist.Name); + var escapedAlbums = Regex.Escape(string.Join("|", album.Select(s => s.Title).ToList())); + + var releaseRegex = new Regex(@"^(\W*|\b)(?" + escapedArtist + @")(\W*|\b).*(\W*|\b)(?" + escapedAlbums + @")(\W*|\b)", RegexOptions.IgnoreCase); + var match = releaseRegex.Matches(simpleTitle); diff --git a/src/NzbDrone.Core/Parser/QualityParser.cs b/src/NzbDrone.Core/Parser/QualityParser.cs index dd6b1893b..b5a1f78b6 100644 --- a/src/NzbDrone.Core/Parser/QualityParser.cs +++ b/src/NzbDrone.Core/Parser/QualityParser.cs @@ -122,6 +122,7 @@ namespace NzbDrone.Core.Parser else if (bitrate == BitRate.B256) { result.Quality = Quality.VORBIS_Q8; } else if (bitrate == BitRate.B320) { result.Quality = Quality.VORBIS_Q9; } else if (bitrate == BitRate.B500) { result.Quality = Quality.VORBIS_Q10; } + else { result.Quality = Quality.Unknown; } break; case Codec.Unknown: if (bitrate == BitRate.B192) { result.Quality = Quality.MP3_192; }