diff --git a/src/Jackett.Test/Jackett.Test.csproj b/src/Jackett.Test/Jackett.Test.csproj
index cf5bac2f9..e502d514b 100644
--- a/src/Jackett.Test/Jackett.Test.csproj
+++ b/src/Jackett.Test/Jackett.Test.csproj
@@ -165,6 +165,7 @@
+
diff --git a/src/Jackett.Test/Util/TvCategoryParserTests.cs b/src/Jackett.Test/Util/TvCategoryParserTests.cs
new file mode 100644
index 000000000..95d9c6f28
--- /dev/null
+++ b/src/Jackett.Test/Util/TvCategoryParserTests.cs
@@ -0,0 +1,27 @@
+using NUnit.Framework;
+using Jackett.Utils;
+
+namespace JackettTest.Util
+{
+ [TestFixture]
+ internal class ParseTvShowQualityTest : TestBase
+ {
+ [TestCase("Chuck.S04E05.HDTV.XviD-LOL", 5030)]
+ [TestCase("Gold.Rush.S04E05.Garnets.or.Gold.REAL.REAL.PROPER.HDTV.x264-W4F", 5030)]
+ [TestCase("Chuck.S03E17.REAL.PROPER.720p.HDTV.x264-ORENJI-RP", 5040)]
+ [TestCase("Covert.Affairs.S05E09.REAL.PROPER.HDTV.x264-KILLERS", 5030)]
+ [TestCase("Mythbusters.S14E01.REAL.PROPER.720p.HDTV.x264-KILLERS", 5040)]
+ [TestCase("Orange.Is.the.New.Black.s02e06.real.proper.720p.webrip.x264-2hd", 5040)]
+ [TestCase("Top.Gear.S21E07.Super.Duper.Real.Proper.HDTV.x264-FTP", 5030)]
+ [TestCase("Top.Gear.S21E07.PROPER.HDTV.x264-RiVER-RP", 5030)]
+ [TestCase("House.S07E11.PROPER.REAL.RERIP.1080p.BluRay.x264-TENEIGHTY", 5040)]
+ [TestCase("The.Blacklist.S02E05", 5000)]
+ [TestCase("The.IT.Crowd.S01.DVD.REMUX.DD2.0.MPEG2-DTG", 5030)]
+
+ public void should_parse_quality_from_title(string title, int quality)
+ {
+ Assert.That(TvCategoryParser.ParseTvShowQuality(title), Is.EqualTo(quality));
+ }
+ }
+}
+
diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj
index ad65375f4..c893c46ba 100644
--- a/src/Jackett/Jackett.csproj
+++ b/src/Jackett/Jackett.csproj
@@ -311,6 +311,7 @@
+
diff --git a/src/Jackett/Utils/TvCategoryParser.cs b/src/Jackett/Utils/TvCategoryParser.cs
new file mode 100644
index 000000000..a45902f97
--- /dev/null
+++ b/src/Jackett/Utils/TvCategoryParser.cs
@@ -0,0 +1,115 @@
+//Regex sourced from Sonarr - https://github.com/Sonarr/Sonarr/blob/develop/src/NzbDrone.Core/Parser/QualityParser.cs
+
+using System.Text.RegularExpressions;
+using Jackett.Models;
+
+namespace Jackett.Utils
+{
+ public static class TvCategoryParser
+ {
+
+ private static readonly Regex SourceRegex = new Regex(@"\b(?:
+ (?BluRay|Blu-Ray|HDDVD|BD)|
+ (?WEB[-_. ]DL|WEBDL|WebRip|iTunesHD|WebHD)|
+ (?HDTV)|
+ (?BDRip)|
+ (?BRRip)|
+ (?DVD|DVDRip|NTSC|PAL|xvidvd)|
+ (?WS[-_. ]DSR|DSR)|
+ (?PDTV)|
+ (?SDTV)|
+ (?TVRip)
+ )\b",
+ RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
+
+ private static readonly Regex RawHdRegex = new Regex(@"\b(?TrollHD|RawHD|1080i[-_. ]HDTV|Raw[-_. ]HD|MPEG[-_. ]?2)\b",
+ RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
+ private static readonly Regex ResolutionRegex = new Regex(@"\b(?:(?480p|640x480|848x480)|(?576p)|(?720p|1280x720)|(?1080p|1920x1080))\b",
+ RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
+ private static readonly Regex CodecRegex = new Regex(@"\b(?:(?x264)|(?h264)|(?XvidHD)|(?Xvid)|(?divx))\b",
+ RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
+ private static readonly Regex HighDefPdtvRegex = new Regex(@"hr[-_. ]ws", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
+
+
+ public static int ParseTvShowQuality(string tvShowFileName)
+ {
+ string normalizedName = tvShowFileName.Trim().Replace('_', ' ').Trim().ToLower();
+
+ var sourceMatch = SourceRegex.Match(normalizedName);
+ var resolutionMatch = ResolutionRegex.Match(normalizedName);
+ var codecMatch = CodecRegex.Match(normalizedName);
+
+ if (sourceMatch.Groups["webdl"].Success)
+ {
+ if (resolutionMatch.Groups["q1080p"].Success || resolutionMatch.Groups["q720p"].Success)
+ {
+ return TorznabCatType.TVHD.ID;
+ }
+
+ if (resolutionMatch.Groups["q480p"].Success)
+ {
+ return TorznabCatType.TVSD.ID;
+ }
+ }
+
+ if (sourceMatch.Groups["hdtv"].Success)
+ {
+ if (resolutionMatch.Groups["q1080p"].Success || resolutionMatch.Groups["q720p"].Success)
+ {
+ return TorznabCatType.TVHD.ID;
+ }
+ else
+ {
+ return TorznabCatType.TVSD.ID;
+ }
+ }
+
+ if (sourceMatch.Groups["bluray"].Success || sourceMatch.Groups["bdrip"].Success || sourceMatch.Groups["brrip"].Success)
+ {
+ if (codecMatch.Groups["xvid"].Success || codecMatch.Groups["divx"].Success)
+ {
+ return TorznabCatType.TVSD.ID;
+ }
+
+ if (resolutionMatch.Groups["q1080p"].Success || resolutionMatch.Groups["q720p"].Success)
+ {
+ return TorznabCatType.TVHD.ID;
+ }
+
+ if (resolutionMatch.Groups["q480p"].Success || resolutionMatch.Groups["q576p"].Success)
+ {
+ return TorznabCatType.TVSD.ID;
+ }
+ }
+
+ if (sourceMatch.Groups["dvd"].Success)
+ {
+ return TorznabCatType.TVSD.ID;
+ }
+
+ if (sourceMatch.Groups["pdtv"].Success || sourceMatch.Groups["sdtv"].Success || sourceMatch.Groups["dsr"].Success || sourceMatch.Groups["tvrip"].Success)
+ {
+ if (HighDefPdtvRegex.IsMatch(normalizedName))
+ {
+ return TorznabCatType.TVHD.ID;
+ }
+ else
+ {
+ return TorznabCatType.TVSD.ID;
+ }
+ }
+
+ if (RawHdRegex.IsMatch(normalizedName))
+ {
+ return TorznabCatType.TVHD.ID;
+ }
+
+ return TorznabCatType.TV.ID;
+ }
+
+ }
+}