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?(?(?\d{4}(?!\d+|i|p)))+)\W?(?!\\)",
+ new Regex(@"^(?.+?)(?:(\W|_)+S?(?(?\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)