mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-24 22:35:49 -04:00
Added: A Huge Cleanup of old Series Code. (Let's pray nothing breaks :P) (#2589)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -9,7 +9,7 @@ using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Movies;
|
||||
using TinyIoC;
|
||||
|
||||
namespace NzbDrone.Core.Parser
|
||||
@@ -59,196 +59,6 @@ namespace NzbDrone.Core.Parser
|
||||
|
||||
};
|
||||
|
||||
private static readonly Regex[] ReportTitleRegex = new[]
|
||||
{
|
||||
//Anime - Absolute Episode Number + Title + Season+Episode
|
||||
//Todo: This currently breaks series that start with numbers
|
||||
// new Regex(@"^(?:(?<absoluteepisode>\d{2,3})(?:_|-|\s|\.)+)+(?<title>.+?)(?:\W|_)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)",
|
||||
// RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Multi-Part episodes without a title (S01E05.S01E06)
|
||||
new Regex(@"^(?:\W*S?(?<season>(?<!\d+)(?:\d{1,2}|\d{4})(?!\d+))(?:(?:[ex]){1,2}(?<episode>\d{1,3}(?!\d+)))+){2,}",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Matches Movie name with AirYear
|
||||
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![()\[!]))*(?<year>(?<!e|x)\d{4}(?!p|i|\d+|\)|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes without a title, Single (S01E05, 1x05) AND Multi (S01E04E05, 1x04x05, etc)
|
||||
new Regex(@"^(?:S?(?<season>(?<!\d+)(?:\d{1,2}|\d{4})(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{2,3}(?!\d+)))+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title Episode Absolute Episode Number ([SubGroup] Series Title Episode 01)
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)(?<title>.+?)[-_. ](?:Episode)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,3}(?!\d+)))+(?:_|-|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title Absolute Episode Number + Season+Episode
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.)?)(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+(?<absoluteepisode>\d{2,3}))+(?:_|-|\s|\.)+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+).*?(?<hash>[(\[]\w{8}[)\]])?(?:$|\.)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title Season+Episode + Absolute Episode Number
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.)?)(?<title>.+?)(?:[-_\W](?<![()\[!]))+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:(?:_|-|\s|\.)+(?<absoluteepisode>(?<!\d+)\d{2,3}(?!\d+)))+.*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title Season+Episode
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\](?:_|-|\s|\.)?)(?<title>.+?)(?:[-_\W](?<![()\[!]))+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]|\W[ex]){1,2}(?<episode>\d{2}(?!\d+)))+)(?:\s|\.).*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title with trailing number Absolute Episode Number
|
||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>[^-]+?\d+?)[-_. ]+(?:[-_. ]?(?<absoluteepisode>\d{3}(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title - Absolute Episode Number
|
||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)(?:[. ]-[. ](?<absoluteepisode>\d{2,3}(?!\d+|[-])))+(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - [SubGroup] Title Absolute Episode Number
|
||||
new Regex(@"^\[(?<subgroup>.+?)\][-_. ]?(?<title>.+?)[-_. ]+\(?(?:[-_. ]?(?<absoluteepisode>\d{2,3}(?!\d+)))+\)?(?:[-_. ]+(?<special>special|ova|ovd))?.*?(?<hash>\[\w{8}\])?(?:$|\.mkv)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title Season EpisodeNumber + Absolute Episode Number [SubGroup]
|
||||
new Regex(@"^(?<title>.+?)(?:[-_\W](?<![()\[!]))+(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:[ex]|\W[ex]){1,2}(?<episode>(?<!\d+)\d{2}(?!\d+)))+).+?(?:[-_. ]?(?<absoluteepisode>(?<!\d+)\d{3}(?!\d+)))+.+?\[(?<subgroup>.+?)\](?:$|\.mkv)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title Absolute Episode Number [SubGroup]
|
||||
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{3}(?!\d+)))+(?:.+?)\[(?<subgroup>.+?)\].*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title Absolute Episode Number [Hash]
|
||||
new Regex(@"^(?<title>.+?)(?:(?:_|-|\s|\.)+(?<absoluteepisode>\d{2,3}(?!\d+)))+(?:[-_. ]+(?<special>special|ova|ovd))?[-_. ]+.*?(?<hash>\[\w{8}\])(?:$|\.)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes with airdate AND season/episode number, capture season/epsiode only
|
||||
new Regex(@"^(?<title>.+?)?\W*(?<airdate>\d{4}\W+[0-1][0-9]\W+[0-3][0-9])(?!\W+[0-3][0-9])[-_. ](?:s?(?<season>(?<!\d+)(?:\d{1,2})(?!\d+)))(?:[ex](?<episode>(?<!\d+)(?:\d{1,3})(?!\d+)))",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes with airdate AND season/episode number
|
||||
new Regex(@"^(?<title>.+?)?\W*(?<airyear>\d{4})\W+(?<airmonth>[0-1][0-9])\W+(?<airday>[0-3][0-9])(?!\W+[0-3][0-9]).+?(?:s?(?<season>(?<!\d+)(?:\d{1,2})(?!\d+)))(?:[ex](?<episode>(?<!\d+)(?:\d{1,3})(?!\d+)))",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Multi-episode Repeated (S01E05 - S01E06, 1x05 - 1x06, etc)
|
||||
new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+S?(?<season>(?<!\d+)(?:\d{1,2}|\d{4})(?!\d+))(?:(?:[ex]|[-_. ]e){1,2}(?<episode>\d{1,3}(?!\d+)))+){2,}",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes with a title, Single episodes (S01E05, 1x05, etc) & Multi-episode (S01E05E06, S01E05-06, S01E05 E06, etc)
|
||||
new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+S?(?<season>(?<!\d+)(?:\d{1,2})(?!\d+))(?:[ex]|\W[ex]|_){1,2}(?<episode>\d{2,3}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{2,3}(?!\d+)))*)\W?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes with a title, 4 digit season number, Single episodes (S2016E05, etc) & Multi-episode (S2016E05E06, S2016E05-06, S2016E05 E06, etc)
|
||||
new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+S(?<season>(?<!\d+)(?:\d{4})(?!\d+))(?:[ex]|\W[ex]|_){1,2}(?<episode>\d{2,3}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{2,3}(?!\d+)))*)\W?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Mini-Series with year in title, treated as season 1, episodes are labelled as Part01, Part 01, Part.1
|
||||
new Regex(@"^(?<title>.+?\d{4})(?:\W+(?:(?:Part\W?|e)(?<episode>\d{1,2}(?!\d+)))+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Mini-Series, treated as season 1, episodes are labelled as Part01, Part 01, Part.1
|
||||
new Regex(@"^(?<title>.+?)(?:\W+(?:(?:Part\W?|(?<!\d+\W+)e)(?<episode>\d{1,2}(?!\d+)))+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Mini-Series, treated as season 1, episodes are labelled as Part One/Two/Three/...Nine, Part.One, Part_One
|
||||
new Regex(@"^(?<title>.+?)(?:\W+(?:Part[-._ ](?<episode>One|Two|Three|Four|Five|Six|Seven|Eight|Nine)(?>[-._ ])))",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Mini-Series, treated as season 1, episodes are labelled as XofY
|
||||
new Regex(@"^(?<title>.+?)(?:\W+(?:(?<episode>(?<!\d+)\d{1,2}(?!\d+))of\d+)+)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Supports Season 01 Episode 03
|
||||
new Regex(@"(?:.*(?:\""|^))(?<title>.*?)(?:[-_\W](?<![()\[]))+(?:\W?Season\W?)(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:\W|_)+(?:Episode\W)(?:[-_. ]?(?<episode>(?<!\d+)\d{1,2}(?!\d+)))+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Multi-episode release with no space between series title and season (S01E11E12)
|
||||
new Regex(@"(?:.*(?:^))(?<title>.*?)(?:\W?|_)S(?<season>(?<!\d+)\d{2}(?!\d+))(?:E(?<episode>(?<!\d+)\d{2}(?!\d+)))+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Multi-episode with single episode numbers (S6.E1-E2, S6.E1E2, S6E1E2, etc)
|
||||
new Regex(@"^(?<title>.+?)[-_. ]S(?<season>(?<!\d+)(?:\d{1,2}|\d{4})(?!\d+))(?:[-_. ]?[ex]?(?<episode>(?<!\d+)\d{1,2}(?!\d+)))+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Single episode season or episode S1E1 or S1-E1
|
||||
new Regex(@"(?:.*(?:\""|^))(?<title>.*?)(?:\W?|_)S(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:\W|_)?E(?<episode>(?<!\d+)\d{1,2}(?!\d+))",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//3 digit season S010E05
|
||||
new Regex(@"(?:.*(?:\""|^))(?<title>.*?)(?:\W?|_)S(?<season>(?<!\d+)\d{3}(?!\d+))(?:\W|_)?E(?<episode>(?<!\d+)\d{1,2}(?!\d+))",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//5 digit episode number with a title
|
||||
new Regex(@"^(?:(?<title>.+?)(?:_|-|\s|\.)+)(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+)))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>(?<!\d+)\d{5}(?!\d+)))",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//5 digit multi-episode with a title
|
||||
new Regex(@"^(?:(?<title>.+?)(?:_|-|\s|\.)+)(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+)))(?:(?:[-_. ]{1,3}ep){1,2}(?<episode>(?<!\d+)\d{5}(?!\d+)))+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
// Separated season and episode numbers S01 - E01
|
||||
new Regex(@"^(?<title>.+?)(?:_|-|\s|\.)+S(?<season>\d{2}(?!\d+))(\W-\W)E(?<episode>(?<!\d+)\d{2}(?!\d+))(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Season only releases
|
||||
new Regex(@"^(?<title>.+?)\W(?:S|Season)\W?(?<season>\d{1,2}(?!\d+))(\W+|_|$)(?<extras>EXTRAS|SUBPACK)?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//4 digit season only releases
|
||||
new Regex(@"^(?<title>.+?)\W(?:S|Season)\W?(?<season>\d{4}(?!\d+))(\W+|_|$)(?<extras>EXTRAS|SUBPACK)?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes with a title and season/episode in square brackets
|
||||
new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+\[S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>(?<!\d+)\d{2}(?!\d+|i|p)))+\])\W?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Supports 103/113 naming
|
||||
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![()\[!]))+(?<season>(?<!\d+)[1-9])(?<episode>[1-9][0-9]|[0][1-9])(?![a-z]|\d+))+",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes with airdate
|
||||
new Regex(@"^(?<title>.+?)?\W*(?<airyear>\d{4})\W+(?<airmonth>[0-1][0-9])\W+(?<airday>[0-3][0-9])(?!\W+[0-3][0-9])",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Supports 1103/1113 naming
|
||||
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![()\[!]))*(?<season>(?<!\d+|\(|\[|e|x)\d{2})(?<episode>(?<!e|x)\d{2}(?!p|i|\d+|\)|\]|\W\d+)))+(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//4 digit episode number
|
||||
//Episodes without a title, Single (S01E05, 1x05) AND Multi (S01E04E05, 1x04x05, etc)
|
||||
new Regex(@"^(?:S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//4 digit episode number
|
||||
//Episodes with a title, Single episodes (S01E05, 1x05, etc) & Multi-episode (S01E05E06, S01E05-06, S01E05 E06, etc)
|
||||
new Regex(@"^(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]|\W[ex]|_){1,2}(?<episode>\d{4}(?!\d+|i|p)))+)\W?(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Episodes with single digit episode number (S01E1, S01E5E6, etc)
|
||||
new Regex(@"^(?<title>.*?)(?:(?:[-_\W](?<![()\[!]))+S?(?<season>(?<!\d+)\d{1,2}(?!\d+))(?:(?:\-|[ex]){1,2}(?<episode>\d{1}))+)+(\W+|_|$)(?!\\)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//iTunes Season 1\05 Title (Quality).ext
|
||||
new Regex(@"^(?:Season(?:_|-|\s|\.)(?<season>(?<!\d+)\d{1,2}(?!\d+)))(?:_|-|\s|\.)(?<episode>(?<!\d+)\d{1,2}(?!\d+))",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title Absolute Episode Number (e66)
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:(?:_|-|\s|\.)+(?:e|ep)(?<absoluteepisode>\d{2,3}))+.*?(?<hash>\[\w{8}\])?(?:$|\.)",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title Episode Absolute Episode Number (Series Title Episode 01)
|
||||
new Regex(@"^(?<title>.+?)[-_. ](?:Episode)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,3}(?!\d+)))+(?:_|-|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title Absolute Episode Number
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:[-_. ]+(?<absoluteepisode>(?<!\d+)\d{2,3}(?!\d+)))+(?:_|-|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Anime - Title {Absolute Episode Number}
|
||||
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)?(?<title>.+?)(?:(?:[-_\W](?<![()\[!]))+(?<absoluteepisode>(?<!\d+)\d{2,3}(?!\d+)))+(?:_|-|\s|\.)*?(?<hash>\[.{8}\])?(?:$|\.)?",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
|
||||
//Extant, terrible multi-episode naming (extant.10708.hdtv-lol.mp4)
|
||||
new Regex(@"^(?<title>.+?)[-_. ](?<season>[0]?\d?)(?:(?<episode>\d{2}){2}(?!\d+))[-_. ]",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled)
|
||||
};
|
||||
|
||||
private static readonly Regex[] RejectHashedReleasesRegex = new Regex[]
|
||||
{
|
||||
// Generic match for md5 and mixed-case hashes.
|
||||
@@ -334,27 +144,6 @@ namespace NzbDrone.Core.Parser
|
||||
{"ü", "ue"},
|
||||
};
|
||||
|
||||
public static ParsedEpisodeInfo ParsePath(string path)
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
|
||||
var result = ParseTitle(fileInfo.Name);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
Logger.Debug("Attempting to parse episode info using directory and file names. {0}", fileInfo.Directory.Name);
|
||||
result = ParseTitle(fileInfo.Directory.Name + " " + fileInfo.Name);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
Logger.Debug("Attempting to parse episode info using directory name. {0}", fileInfo.Directory.Name);
|
||||
result = ParseTitle(fileInfo.Directory.Name + fileInfo.Extension);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ParsedMovieInfo ParseMoviePath(string path, bool isLenient)
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
@@ -363,13 +152,13 @@ namespace NzbDrone.Core.Parser
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
Logger.Debug("Attempting to parse episode info using directory and file names. {0}", fileInfo.Directory.Name);
|
||||
Logger.Debug("Attempting to parse movie info using directory and file names. {0}", fileInfo.Directory.Name);
|
||||
result = ParseMovieTitle(fileInfo.Directory.Name + " " + fileInfo.Name, isLenient);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
Logger.Debug("Attempting to parse episode info using directory name. {0}", fileInfo.Directory.Name);
|
||||
Logger.Debug("Attempting to parse movie info using directory name. {0}", fileInfo.Directory.Name);
|
||||
result = ParseMovieTitle(fileInfo.Directory.Name + fileInfo.Extension, isLenient);
|
||||
}
|
||||
|
||||
@@ -568,122 +357,6 @@ namespace NzbDrone.Core.Parser
|
||||
return "";
|
||||
}
|
||||
|
||||
public static ParsedEpisodeInfo ParseTitle(string title)
|
||||
{
|
||||
|
||||
ParsedEpisodeInfo realResult = null;
|
||||
try
|
||||
{
|
||||
if (!ValidateBeforeParsing(title)) return null;
|
||||
|
||||
Logger.Debug("Parsing string '{0}'", title);
|
||||
|
||||
if (ReversedTitleRegex.IsMatch(title))
|
||||
{
|
||||
var titleWithoutExtension = RemoveFileExtension(title).ToCharArray();
|
||||
Array.Reverse(titleWithoutExtension);
|
||||
|
||||
title = new string(titleWithoutExtension) + title.Substring(titleWithoutExtension.Length);
|
||||
|
||||
Logger.Debug("Reversed name detected. Converted to '{0}'", title);
|
||||
}
|
||||
|
||||
var simpleTitle = SimpleTitleRegex.Replace(title, string.Empty);
|
||||
|
||||
simpleTitle = RemoveFileExtension(simpleTitle);
|
||||
|
||||
// TODO: Quick fix stripping [url] - prefixes.
|
||||
simpleTitle = WebsitePrefixRegex.Replace(simpleTitle, string.Empty);
|
||||
|
||||
simpleTitle = CleanTorrentSuffixRegex.Replace(simpleTitle, string.Empty);
|
||||
|
||||
var airDateMatch = AirDateRegex.Match(simpleTitle);
|
||||
if (airDateMatch.Success)
|
||||
{
|
||||
simpleTitle = airDateMatch.Groups[1].Value + airDateMatch.Groups["airyear"].Value + "." + airDateMatch.Groups["airmonth"].Value + "." + airDateMatch.Groups["airday"].Value;
|
||||
}
|
||||
|
||||
var sixDigitAirDateMatch = SixDigitAirDateRegex.Match(simpleTitle);
|
||||
if (sixDigitAirDateMatch.Success)
|
||||
{
|
||||
var airYear = sixDigitAirDateMatch.Groups["airyear"].Value;
|
||||
var airMonth = sixDigitAirDateMatch.Groups["airmonth"].Value;
|
||||
var airDay = sixDigitAirDateMatch.Groups["airday"].Value;
|
||||
|
||||
if (airMonth != "00" || airDay != "00")
|
||||
{
|
||||
var fixedDate = string.Format("20{0}.{1}.{2}", airYear, airMonth, airDay);
|
||||
|
||||
simpleTitle = simpleTitle.Replace(sixDigitAirDateMatch.Groups["airdate"].Value, fixedDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
foreach (var regex in ReportTitleRegex)
|
||||
{
|
||||
var match = regex.Matches(simpleTitle);
|
||||
|
||||
if (match.Count != 0)
|
||||
{
|
||||
Logger.Trace(regex);
|
||||
try
|
||||
{
|
||||
var result = ParseMatchCollection(match);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
if (result.FullSeason && title.ContainsIgnoreCase("Special"))
|
||||
{
|
||||
result.FullSeason = false;
|
||||
result.Special = true;
|
||||
}
|
||||
|
||||
result.Language = LanguageParser.ParseLanguage(title);
|
||||
Logger.Debug("Language parsed: {0}", result.Language);
|
||||
|
||||
result.Quality = QualityParser.ParseQuality(title);
|
||||
Logger.Debug("Quality parsed: {0}", result.Quality);
|
||||
|
||||
result.ReleaseGroup = ParseReleaseGroup(title);
|
||||
|
||||
var subGroup = GetSubGroup(match);
|
||||
if (!subGroup.IsNullOrWhiteSpace())
|
||||
{
|
||||
result.ReleaseGroup = subGroup;
|
||||
}
|
||||
|
||||
Logger.Debug("Release Group parsed: {0}", result.ReleaseGroup);
|
||||
|
||||
result.ReleaseHash = GetReleaseHash(match);
|
||||
if (!result.ReleaseHash.IsNullOrWhiteSpace())
|
||||
{
|
||||
Logger.Debug("Release Hash parsed: {0}", result.ReleaseHash);
|
||||
}
|
||||
|
||||
realResult = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (InvalidDateException ex)
|
||||
{
|
||||
Logger.Debug(ex, ex.Message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!title.ToLower().Contains("password") && !title.ToLower().Contains("yenc"))
|
||||
Logger.Error(e, "An error has occurred while trying to parse " + title);
|
||||
}
|
||||
|
||||
Logger.Debug("Unable to parse {0}", title);
|
||||
return realResult;
|
||||
}
|
||||
|
||||
public static string ReplaceGermanUmlauts(string s)
|
||||
{
|
||||
var t = s;
|
||||
@@ -731,20 +404,6 @@ namespace NzbDrone.Core.Parser
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string ParseSeriesName(string title)
|
||||
{
|
||||
Logger.Debug("Parsing string '{0}'", title);
|
||||
|
||||
var parseResult = ParseTitle(title);
|
||||
|
||||
if (parseResult == null)
|
||||
{
|
||||
return CleanSeriesTitle(title);
|
||||
}
|
||||
|
||||
return parseResult.SeriesTitle;
|
||||
}
|
||||
|
||||
public static string CleanSeriesTitle(this string title)
|
||||
{
|
||||
long number = 0;
|
||||
@@ -854,11 +513,11 @@ namespace NzbDrone.Core.Parser
|
||||
}
|
||||
|
||||
|
||||
var seriesName = matchCollection[0].Groups["title"].Value./*Replace('.', ' ').*/Replace('_', ' ');
|
||||
seriesName = RequestInfoRegex.Replace(seriesName, "").Trim(' ');
|
||||
var movieName = matchCollection[0].Groups["title"].Value./*Replace('.', ' ').*/Replace('_', ' ');
|
||||
movieName = RequestInfoRegex.Replace(movieName, "").Trim(' ');
|
||||
|
||||
var parts = seriesName.Split('.');
|
||||
seriesName = "";
|
||||
var parts = movieName.Split('.');
|
||||
movieName = "";
|
||||
int n = 0;
|
||||
bool previousAcronym = false;
|
||||
string nextPart = "";
|
||||
@@ -870,27 +529,27 @@ namespace NzbDrone.Core.Parser
|
||||
}
|
||||
if (part.Length == 1 && part.ToLower() != "a" && !int.TryParse(part, out n))
|
||||
{
|
||||
seriesName += part + ".";
|
||||
movieName += part + ".";
|
||||
previousAcronym = true;
|
||||
}
|
||||
else if (part.ToLower() == "a" && (previousAcronym == true || nextPart.Length == 1))
|
||||
{
|
||||
seriesName += part + ".";
|
||||
movieName += part + ".";
|
||||
previousAcronym = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (previousAcronym)
|
||||
{
|
||||
seriesName += " ";
|
||||
movieName += " ";
|
||||
previousAcronym = false;
|
||||
}
|
||||
seriesName += part + " ";
|
||||
movieName += part + " ";
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
seriesName = seriesName.Trim(' ');
|
||||
movieName = movieName.Trim(' ');
|
||||
|
||||
int airYear;
|
||||
int.TryParse(matchCollection[0].Groups["year"].Value, out airYear);
|
||||
@@ -904,7 +563,7 @@ namespace NzbDrone.Core.Parser
|
||||
result.Edition = matchCollection[0].Groups["edition"].Value.Replace(".", " ");
|
||||
}
|
||||
|
||||
result.MovieTitle = seriesName;
|
||||
result.MovieTitle = movieName;
|
||||
result.MovieTitleInfo = GetSeriesTitleInfo(result.MovieTitle);
|
||||
|
||||
Logger.Debug("Movie Parsed. {0}", result);
|
||||
@@ -912,141 +571,6 @@ namespace NzbDrone.Core.Parser
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchCollection)
|
||||
{
|
||||
var seriesName = matchCollection[0].Groups["title"].Value.Replace('.', ' ').Replace('_', ' ');
|
||||
seriesName = RequestInfoRegex.Replace(seriesName, "").Trim(' ');
|
||||
|
||||
int airYear;
|
||||
int.TryParse(matchCollection[0].Groups["airyear"].Value, out airYear);
|
||||
//int.TryParse(matchCollection[0].Groups["year"].Value, out airYear);
|
||||
|
||||
ParsedEpisodeInfo result;
|
||||
|
||||
if (airYear < 1900)
|
||||
{
|
||||
var seasons = new List<int>();
|
||||
|
||||
foreach (Capture seasonCapture in matchCollection[0].Groups["season"].Captures)
|
||||
{
|
||||
int parsedSeason;
|
||||
if (int.TryParse(seasonCapture.Value, out parsedSeason))
|
||||
seasons.Add(parsedSeason);
|
||||
}
|
||||
|
||||
//If no season was found it should be treated as a mini series and season 1
|
||||
if (seasons.Count == 0) seasons.Add(1);
|
||||
|
||||
//If more than 1 season was parsed go to the next REGEX (A multi-season release is unlikely)
|
||||
if (seasons.Distinct().Count() > 1) return null;
|
||||
|
||||
result = new ParsedEpisodeInfo
|
||||
{
|
||||
SeasonNumber = seasons.First(),
|
||||
EpisodeNumbers = new int[0],
|
||||
AbsoluteEpisodeNumbers = new int[0]
|
||||
};
|
||||
|
||||
foreach (Match matchGroup in matchCollection)
|
||||
{
|
||||
var episodeCaptures = matchGroup.Groups["episode"].Captures.Cast<Capture>().ToList();
|
||||
var absoluteEpisodeCaptures = matchGroup.Groups["absoluteepisode"].Captures.Cast<Capture>().ToList();
|
||||
|
||||
//Allows use to return a list of 0 episodes (We can handle that as a full season release)
|
||||
if (episodeCaptures.Any())
|
||||
{
|
||||
var first = ParseNumber(episodeCaptures.First().Value);
|
||||
var last = ParseNumber(episodeCaptures.Last().Value);
|
||||
|
||||
if (first > last)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var count = last - first + 1;
|
||||
result.EpisodeNumbers = Enumerable.Range(first, count).ToArray();
|
||||
}
|
||||
|
||||
if (absoluteEpisodeCaptures.Any())
|
||||
{
|
||||
var first = Convert.ToInt32(absoluteEpisodeCaptures.First().Value);
|
||||
var last = Convert.ToInt32(absoluteEpisodeCaptures.Last().Value);
|
||||
|
||||
if (first > last)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var count = last - first + 1;
|
||||
result.AbsoluteEpisodeNumbers = Enumerable.Range(first, count).ToArray();
|
||||
|
||||
if (matchGroup.Groups["special"].Success)
|
||||
{
|
||||
result.Special = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!episodeCaptures.Any() && !absoluteEpisodeCaptures.Any())
|
||||
{
|
||||
//Check to see if this is an "Extras" or "SUBPACK" release, if it is, return NULL
|
||||
//Todo: Set a "Extras" flag in EpisodeParseResult if we want to download them ever
|
||||
if (!matchCollection[0].Groups["extras"].Value.IsNullOrWhiteSpace()) return null;
|
||||
|
||||
result.FullSeason = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.AbsoluteEpisodeNumbers.Any() && !result.EpisodeNumbers.Any())
|
||||
{
|
||||
result.SeasonNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//Try to Parse as a daily show
|
||||
var airmonth = Convert.ToInt32(matchCollection[0].Groups["airmonth"].Value);
|
||||
var airday = Convert.ToInt32(matchCollection[0].Groups["airday"].Value);
|
||||
|
||||
//Swap day and month if month is bigger than 12 (scene fail)
|
||||
if (airmonth > 12)
|
||||
{
|
||||
var tempDay = airday;
|
||||
airday = airmonth;
|
||||
airmonth = tempDay;
|
||||
}
|
||||
|
||||
DateTime airDate;
|
||||
|
||||
try
|
||||
{
|
||||
airDate = new DateTime(airYear, airmonth, airday);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new InvalidDateException("Invalid date found: {0}-{1}-{2}", airYear, airmonth, airday);
|
||||
}
|
||||
|
||||
//Check if episode is in the future (most likely a parse error)
|
||||
if (airDate > DateTime.Now.AddDays(1).Date || airDate < new DateTime(1970, 1, 1))
|
||||
{
|
||||
throw new InvalidDateException("Invalid date found: {0}", airDate);
|
||||
}
|
||||
|
||||
result = new ParsedEpisodeInfo
|
||||
{
|
||||
AirDate = airDate.ToString(Episode.AIR_DATE_FORMAT),
|
||||
};
|
||||
}
|
||||
|
||||
result.SeriesTitle = seriesName;
|
||||
result.SeriesTitleInfo = GetSeriesTitleInfo(result.SeriesTitle);
|
||||
|
||||
Logger.Debug("Episode Parsed. {0}", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool ValidateBeforeParsing(string title)
|
||||
{
|
||||
if (title.ToLower().Contains("password") && title.ToLower().Contains("yenc"))
|
||||
|
||||
Reference in New Issue
Block a user