diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 022d01d8d..016d07e16 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -191,6 +191,7 @@ + diff --git a/src/NzbDrone.Core.Test/ParserTests/CrapParserFixture.cs b/src/NzbDrone.Core.Test/ParserTests/CrapParserFixture.cs index 9ed19f36f..a304518f1 100644 --- a/src/NzbDrone.Core.Test/ParserTests/CrapParserFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/CrapParserFixture.cs @@ -28,6 +28,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("ce39afb7da6cf7c04eba3090f0a309f609883862")] [TestCase("THIS SHOULD NEVER PARSE")] [TestCase("Vh1FvU3bJXw6zs8EEUX4bMo5vbbMdHghxHirc.mkv")] + [TestCase("0e895c37245186812cb08aab1529cf8ee389dd05.mkv")] public void should_not_parse_crap(string title) { Parser.Parser.ParseTitle(title).Should().BeNull(); diff --git a/src/NzbDrone.Core.Test/ParserTests/HashedReleasesFixture.cs b/src/NzbDrone.Core.Test/ParserTests/HashedReleasesFixture.cs new file mode 100644 index 000000000..4f810789c --- /dev/null +++ b/src/NzbDrone.Core.Test/ParserTests/HashedReleasesFixture.cs @@ -0,0 +1,20 @@ +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.ParserTests +{ + [TestFixture] + public class hashedReleasesFixture : CoreTest + { + [TestCase(@"C:\Test\Some.Hashed.Release.S01E01.720p.WEB-DL.AAC2.0.H.264-Mercury\0e895c3724.mkv", "somehashedrelease", "WEBDL-720p", "Mercury")] + [TestCase(@"C:\Test\0e895c3724\Some.Hashed.Release.S01E01.720p.WEB-DL.AAC2.0.H.264-Mercury.mkv", "somehashedrelease", "WEBDL-720p", "Mercury")] + public void should_properly_parse_hashed_releases(string path, string title, string quality, string releaseGroup) + { + var result = Parser.Parser.ParsePath(path); + result.SeriesTitle.Should().Be(title); + result.Quality.ToString().Should().Be(quality); + result.ReleaseGroup.Should().Be(releaseGroup); + } + } +} diff --git a/src/NzbDrone.Core/Parser/Parser.cs b/src/NzbDrone.Core/Parser/Parser.cs index 0df8b6d6d..470ee4516 100644 --- a/src/NzbDrone.Core/Parser/Parser.cs +++ b/src/NzbDrone.Core/Parser/Parser.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using NLog; +using NzbDrone.Common; using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Tv; @@ -46,7 +47,7 @@ namespace NzbDrone.Core.Parser RegexOptions.IgnoreCase | RegexOptions.Compiled), //Episodes without a title, Single (S01E05, 1x05) AND Multi (S01E04E05, 1x04x05, etc) - new Regex(@"^(?:S?(?(?\d{2,3}(?!\d+)))+)", + new Regex(@"^(?:S?(?(?\d{2,3}(?!\d+)))+(?![\da-z]))", RegexOptions.IgnoreCase | RegexOptions.Compiled), //Episodes with a title, Single episodes (S01E05, 1x05, etc) & Multi-episode (S01E05E06, S01E05-06, S01E05 E06, etc) @@ -91,7 +92,7 @@ namespace NzbDrone.Core.Parser RegexOptions.IgnoreCase | RegexOptions.Compiled), //Episodes with a title, Single episodes (S01E05, 1x05, etc) & Multi-episode (S01E05E06, S01E05-06, S01E05 E06, etc) - new Regex(@"^(?.+?)(?:(\W|_)+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)\W?(?!\\)", + new Regex(@"^(?<title>.+?)(?:(\W|_)+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+(?![\da-z]))\W?(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled), //Anime - Title Absolute Episode Number @@ -126,6 +127,12 @@ namespace NzbDrone.Core.Parser var result = ParseTitle(fileInfo.Name); + if (result == null) + { + Logger.Debug("Attempting to parse episode info using directory path. {0}", fileInfo.Directory.Name); + result = ParseTitle(fileInfo.Directory.Name + fileInfo.Extension); + } + if (result == null) { Logger.Debug("Attempting to parse episode info using full path. {0}", fileInfo.FullName); @@ -138,8 +145,6 @@ namespace NzbDrone.Core.Parser return null; } - result.ReleaseGroup = ParseReleaseGroup(fileInfo.Name.Replace(fileInfo.Extension, "")); - return result; } @@ -239,6 +244,12 @@ namespace NzbDrone.Core.Parser const string defaultReleaseGroup = "DRONE"; title = title.Trim(); + + if (!title.ContainsInvalidPathChars() && MediaFiles.MediaFileExtensions.Extensions.Contains(Path.GetExtension(title).ToLower())) + { + title = Path.GetFileNameWithoutExtension(title).Trim(); + } + var index = title.LastIndexOf('-'); if (index < 0)