mirror of https://github.com/Sonarr/Sonarr
Add GetBestMatch to TvDbProvider (Provides a way to get the best result from a list of results)
Default value for Quality Dropbox in AddExisting is now the default value from Settings.
This commit is contained in:
parent
148fd044ef
commit
460e48d6a1
|
@ -1,153 +0,0 @@
|
||||||
<Configuration>
|
|
||||||
<CodeStyleSettings>
|
|
||||||
<ExternalPath IsNull="False">
|
|
||||||
</ExternalPath>
|
|
||||||
<Sharing>SOLUTION</Sharing>
|
|
||||||
<CSharp>
|
|
||||||
<FormatSettings>
|
|
||||||
<MODIFIERS_ORDER IsNull="False">
|
|
||||||
<Item>public</Item>
|
|
||||||
<Item>protected</Item>
|
|
||||||
<Item>internal</Item>
|
|
||||||
<Item>private</Item>
|
|
||||||
<Item>new</Item>
|
|
||||||
<Item>abstract</Item>
|
|
||||||
<Item>virtual</Item>
|
|
||||||
<Item>override</Item>
|
|
||||||
<Item>sealed</Item>
|
|
||||||
<Item>static</Item>
|
|
||||||
<Item>readonly</Item>
|
|
||||||
<Item>extern</Item>
|
|
||||||
<Item>unsafe</Item>
|
|
||||||
<Item>volatile</Item>
|
|
||||||
</MODIFIERS_ORDER>
|
|
||||||
</FormatSettings>
|
|
||||||
<UsingsSettings />
|
|
||||||
<Naming2>
|
|
||||||
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
|
|
||||||
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PublicFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Constants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateStaticReadonly" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
|
|
||||||
</Naming2>
|
|
||||||
</CSharp>
|
|
||||||
<VB>
|
|
||||||
<FormatSettings>
|
|
||||||
<BLANK_LINES_AROUND_NAMESPACE>2</BLANK_LINES_AROUND_NAMESPACE>
|
|
||||||
<KEEP_USER_LINEBREAKS>False</KEEP_USER_LINEBREAKS>
|
|
||||||
<SPACE_AFTER_ATTRIBUTE_TARGET_COLON>False</SPACE_AFTER_ATTRIBUTE_TARGET_COLON>
|
|
||||||
<SPACE_BEFORE_INVOCATION_PARENTHESES>False</SPACE_BEFORE_INVOCATION_PARENTHESES>
|
|
||||||
<SPACE_BEFORE_METHOD_PARENTHESES>False</SPACE_BEFORE_METHOD_PARENTHESES>
|
|
||||||
<SPACE_BEFORE_TYPE_PARAMETER_PARENTHESES>False</SPACE_BEFORE_TYPE_PARAMETER_PARENTHESES>
|
|
||||||
<WRAP_ARGUMENTS_STYLE>CHOP_IF_LONG</WRAP_ARGUMENTS_STYLE>
|
|
||||||
<WRAP_EXTENDS_LIST_STYLE>CHOP_IF_LONG</WRAP_EXTENDS_LIST_STYLE>
|
|
||||||
<WRAP_LIMIT>200</WRAP_LIMIT>
|
|
||||||
<WRAP_PARAMETERS_STYLE>CHOP_IF_LONG</WRAP_PARAMETERS_STYLE>
|
|
||||||
</FormatSettings>
|
|
||||||
<ImportsSettings>
|
|
||||||
<AllowAlias>False</AllowAlias>
|
|
||||||
</ImportsSettings>
|
|
||||||
<Naming2>
|
|
||||||
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
|
|
||||||
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PublicFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Constants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateStaticReadonly" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
|
|
||||||
</Naming2>
|
|
||||||
</VB>
|
|
||||||
<Web>
|
|
||||||
<Naming2>
|
|
||||||
<UserRule Name="ASP_TAG_NAME" Inspect="True" Prefix="" Suffix="" Style="AaBb" />
|
|
||||||
<UserRule Name="ASP_TAG_PREFIX" Inspect="True" Prefix="" Suffix="" Style="AaBb" />
|
|
||||||
<UserRule Name="ASP_FIELD" Inspect="True" Prefix="" Suffix="" Style="AaBb" />
|
|
||||||
<UserRule Name="ASP_HTML_CONTROL" Inspect="True" Prefix="" Suffix="" Style="AaBb" />
|
|
||||||
</Naming2>
|
|
||||||
</Web>
|
|
||||||
<Xaml>
|
|
||||||
<Naming2>
|
|
||||||
<UserRule Name="XAML_FIELD" Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
|
|
||||||
<UserRule Name="NAMESPACE_ALIAS" Inspect="True" Prefix="" Suffix="" Style="AaBb" />
|
|
||||||
<UserRule Name="XAML_RESOURCE" Inspect="True" Prefix="" Suffix="" Style="AaBb" />
|
|
||||||
</Naming2>
|
|
||||||
</Xaml>
|
|
||||||
<XML>
|
|
||||||
<FormatSettings />
|
|
||||||
</XML>
|
|
||||||
<FileHeader><![CDATA['
|
|
||||||
' DotNetNuke® - http://www.dotnetnuke.com
|
|
||||||
' Copyright (c) 2002-2010
|
|
||||||
' by DotNetNuke Corporation
|
|
||||||
'
|
|
||||||
' Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
||||||
' documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
||||||
' the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
||||||
' to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
'
|
|
||||||
' The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
|
||||||
' of the Software.
|
|
||||||
'
|
|
||||||
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
' TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
||||||
' CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
' DEALINGS IN THE SOFTWARE.
|
|
||||||
']]></FileHeader>
|
|
||||||
<GenerateMemberBody />
|
|
||||||
<Naming2>
|
|
||||||
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
|
|
||||||
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PublicFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AA_BB" ElementKind="Constants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AA_BB" ElementKind="PrivateConstants" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateStaticReadonly" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
|
|
||||||
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
|
|
||||||
<Abbreviation Text="IIS" />
|
|
||||||
<Abbreviation Text="ID" />
|
|
||||||
<Abbreviation Text="SHA" />
|
|
||||||
<Abbreviation Text="WCF" />
|
|
||||||
<Abbreviation Text="XML" />
|
|
||||||
<Abbreviation Text="XSL" />
|
|
||||||
<Abbreviation Text="AJAX" />
|
|
||||||
<Abbreviation Text="GUID" />
|
|
||||||
<Abbreviation Text="URL" />
|
|
||||||
<Abbreviation Text="DNN" />
|
|
||||||
</Naming2>
|
|
||||||
</CodeStyleSettings>
|
|
||||||
</Configuration>
|
|
|
@ -13,7 +13,8 @@ namespace NzbDrone.Core.Test
|
||||||
public class ParserTest
|
public class ParserTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
[Row("Sonny.With.a.Chance.S02E15", 2,15)]
|
[Row("Sonny.With.a.Chance.S02E15", 2, 15)]
|
||||||
|
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)]
|
||||||
[Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)]
|
[Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)]
|
||||||
[Row("Two.and.a.Half.Me.113.720p.HDTV.X264-DIMENSION", 1, 13)]
|
[Row("Two.and.a.Half.Me.113.720p.HDTV.X264-DIMENSION", 1, 13)]
|
||||||
[Row("Two.and.a.Half.Me.1013.720p.HDTV.X264-DIMENSION", 10, 13)]
|
[Row("Two.and.a.Half.Me.1013.720p.HDTV.X264-DIMENSION", 10, 13)]
|
||||||
|
@ -34,18 +35,6 @@ namespace NzbDrone.Core.Test
|
||||||
Assert.AreEqual(episode, result.Episodes[0]);
|
Assert.AreEqual(episode, result.Episodes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
[Row("The.Office.US.S03E01E02.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1, 2)]
|
|
||||||
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1, 6)]
|
|
||||||
public void episode_parse_multi(string path, int season, int episodeOne, int episodeTwo)
|
|
||||||
{
|
|
||||||
var result = Parser.ParseEpisodeInfo(path);
|
|
||||||
Assert.Count(2, result);
|
|
||||||
Assert.AreEqual(season, result[0].SeasonNumber);
|
|
||||||
Assert.AreEqual(episodeOne, result[0].EpisodeNumber);
|
|
||||||
Assert.AreEqual(episodeTwo, result[1].EpisodeNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.BDRip)]
|
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.BDRip)]
|
||||||
[Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.BDRip)]
|
[Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.BDRip)]
|
||||||
|
|
|
@ -9,64 +9,6 @@ using NzbDrone.Core.Model;
|
||||||
using NzbDrone.Core.Providers;
|
using NzbDrone.Core.Providers;
|
||||||
using NzbDrone.Core.Repository.Quality;
|
using NzbDrone.Core.Repository.Quality;
|
||||||
|
|
||||||
namespace NzbDrone.Core
|
|
||||||
{
|
|
||||||
internal static class Parser
|
|
||||||
{
|
|
||||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
private static readonly Regex[] ReportTitleRegex = new[]
|
|
||||||
{
|
|
||||||
new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)((?:\-|\.|[a-z])(?<episode>\d+))+\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
||||||
new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?<episode>\d{2})\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled) //Supports 103/113 naming
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly Regex[] SeasonReportTitleRegex = new[]
|
|
||||||
{
|
|
||||||
new Regex(@"(?<title>.+?)?\W?(?<year>\d{4}?)?\W(?:S|Season)?\W?(?<season>\d+)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly Regex NormalizeRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a post title into list of episodes it contains
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">Title of the report</param>
|
|
||||||
/// <returns>List of episodes contained to the post</returns>
|
|
||||||
internal static EpisodeParseResult ParseEpisodeInfo(string title)
|
|
||||||
{
|
|
||||||
Logger.Trace("Parsing string '{0}'", title);
|
|
||||||
|
|
||||||
foreach (var regex in ReportTitleRegex)
|
|
||||||
{
|
|
||||||
var match = regex.Matches(title);
|
|
||||||
|
|
||||||
if (match.Count != 0)
|
|
||||||
{
|
|
||||||
var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
|
|
||||||
var year = 0;
|
|
||||||
Int32.TryParse(match[0].Groups["year"].Value, out year);
|
|
||||||
|
|
||||||
if (year < 1900 || year > DateTime.Now.Year + 1)
|
|
||||||
{
|
|
||||||
year = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var seasonNumber = Convert.ToInt32(matchGroup.Groups["season"].Value);
|
|
||||||
|
|
||||||
foreach (Capture episode in matchGroup.Groups["episode"].Captures)
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Core.Model;
|
|
||||||
using NzbDrone.Core.Providers;
|
|
||||||
using NzbDrone.Core.Repository.Quality;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core
|
namespace NzbDrone.Core
|
||||||
{
|
{
|
||||||
internal static class Parser
|
internal static class Parser
|
||||||
|
@ -315,471 +257,5 @@ namespace NzbDrone.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Core.Model;
|
|
||||||
using NzbDrone.Core.Providers;
|
|
||||||
using NzbDrone.Core.Repository.Quality;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core
|
|
||||||
{
|
|
||||||
internal static class Parser
|
|
||||||
{
|
|
||||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
private static readonly Regex[] ReportTitleRegex = new[]
|
|
||||||
{
|
|
||||||
new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?:\-|\.|[a-z])(?<episode>\d+)\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
||||||
new Regex(@"(?<title>.+?)?\W?(?<year>\d+?)?\WS?(?<season>\d+)(?<episode>\d{2})\W(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled) //Supports 103/113 naming
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly Regex[] SeasonReportTitleRegex = new[]
|
|
||||||
{
|
|
||||||
new Regex(@"(?<title>.+?)?\W?(?<year>\d{4}?)?\W(?:S|Season)?\W?(?<season>\d+)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly Regex NormalizeRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a post title into list of episodes it contains
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">Title of the report</param>
|
|
||||||
/// <returns>List of episodes contained to the post</returns>
|
|
||||||
internal static EpisodeParseResult ParseEpisodeInfo(string title)
|
|
||||||
{
|
|
||||||
Logger.Trace("Parsing string '{0}'", title);
|
|
||||||
|
|
||||||
foreach (var regex in ReportTitleRegex)
|
|
||||||
{
|
|
||||||
var match = regex.Matches(title);
|
|
||||||
|
|
||||||
if (match.Count != 0)
|
|
||||||
{
|
|
||||||
var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
|
|
||||||
var year = 0;
|
|
||||||
Int32.TryParse(match[0].Groups["year"].Value, out year);
|
|
||||||
|
|
||||||
if (year < 1900 || year > DateTime.Now.Year + 1)
|
|
||||||
{
|
|
||||||
year = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var parsedEpisode = new EpisodeParseResult
|
|
||||||
{
|
|
||||||
Proper = title.ToLower().Contains("proper"),
|
|
||||||
SeriesTitle = seriesName,
|
|
||||||
SeasonNumber = Convert.ToInt32(match[0].Groups["season"].Value),
|
|
||||||
Year = year,
|
|
||||||
Episodes = new List<int>()
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (Match matchGroup in match)
|
|
||||||
{
|
|
||||||
parsedEpisode.Episodes.Add(Convert.ToInt32(matchGroup.Groups["episode"].Value));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
parsedEpisode.Quality = ParseQuality(title);
|
|
||||||
|
|
||||||
Logger.Trace("Episode Parsed. {0}", parsedEpisode);
|
|
||||||
|
|
||||||
return parsedEpisode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a post title into season it contains
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">Title of the report</param>
|
|
||||||
/// <returns>Season information contained in the post</returns>
|
|
||||||
internal static SeasonParseResult ParseSeasonInfo(string title)
|
|
||||||
{
|
|
||||||
Logger.Trace("Parsing string '{0}'", title);
|
|
||||||
|
|
||||||
foreach (var regex in ReportTitleRegex)
|
|
||||||
{
|
|
||||||
var match = regex.Matches(title);
|
|
||||||
|
|
||||||
if (match.Count != 0)
|
|
||||||
{
|
|
||||||
var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
|
|
||||||
var year = 0;
|
|
||||||
Int32.TryParse(match[0].Groups["year"].Value, out year);
|
|
||||||
|
|
||||||
if (year < 1900 || year > DateTime.Now.Year + 1)
|
|
||||||
{
|
|
||||||
year = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var seasonNumber = Convert.ToInt32(match[0].Groups["season"].Value);
|
|
||||||
|
|
||||||
var result = new SeasonParseResult
|
|
||||||
{
|
|
||||||
SeriesTitle = seriesName,
|
|
||||||
SeasonNumber = seasonNumber,
|
|
||||||
Year = year
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
result.Quality = ParseQuality(title);
|
|
||||||
|
|
||||||
Logger.Trace("Season Parsed. {0}", result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null; //Return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a post title to find the series that relates to it
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">Title of the report</param>
|
|
||||||
/// <returns>Normalized Series Name</returns>
|
|
||||||
internal static string ParseSeriesName(string title)
|
|
||||||
{
|
|
||||||
Logger.Trace("Parsing string '{0}'", title);
|
|
||||||
|
|
||||||
foreach (var regex in ReportTitleRegex)
|
|
||||||
{
|
|
||||||
var match = regex.Matches(title);
|
|
||||||
|
|
||||||
if (match.Count != 0)
|
|
||||||
{
|
|
||||||
var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
|
|
||||||
var year = 0;
|
|
||||||
Int32.TryParse(match[0].Groups["year"].Value, out year);
|
|
||||||
|
|
||||||
if (year < 1900 || year > DateTime.Now.Year + 1)
|
|
||||||
{
|
|
||||||
year = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Trace("Series Parsed. {0}", seriesName);
|
|
||||||
return seriesName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses proper status out of a report title
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">Title of the report</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static bool ParseProper(string title)
|
|
||||||
{
|
|
||||||
return title.ToLower().Contains("proper");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static QualityTypes ParseQuality(string name)
|
|
||||||
{
|
|
||||||
Logger.Trace("Trying to parse quality for {0}", name);
|
|
||||||
|
|
||||||
var result = QualityTypes.Unknown;
|
|
||||||
name = name.ToLowerInvariant();
|
|
||||||
|
|
||||||
if (name.Contains("dvd"))
|
|
||||||
return QualityTypes.DVD;
|
|
||||||
|
|
||||||
if (name.Contains("bdrip") || name.Contains("brrip"))
|
|
||||||
{
|
|
||||||
return QualityTypes.BDRip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.Contains("xvid") || name.Contains("divx"))
|
|
||||||
{
|
|
||||||
if (name.Contains("bluray"))
|
|
||||||
{
|
|
||||||
return QualityTypes.BDRip;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QualityTypes.TV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.Contains("bluray"))
|
|
||||||
{
|
|
||||||
if (name.Contains("720p"))
|
|
||||||
return QualityTypes.Bluray720;
|
|
||||||
|
|
||||||
if (name.Contains("1080p"))
|
|
||||||
return QualityTypes.Bluray1080;
|
|
||||||
|
|
||||||
return QualityTypes.Bluray720;
|
|
||||||
}
|
|
||||||
if (name.Contains("web-dl"))
|
|
||||||
return QualityTypes.WEBDL;
|
|
||||||
if (name.Contains("x264") || name.Contains("h264") || name.Contains("720p"))
|
|
||||||
return QualityTypes.HDTV;
|
|
||||||
|
|
||||||
//Based on extension
|
|
||||||
if (result == QualityTypes.Unknown)
|
|
||||||
{
|
|
||||||
switch (new FileInfo(name).Extension.ToLower())
|
|
||||||
{
|
|
||||||
case ".avi":
|
|
||||||
case ".xvid":
|
|
||||||
case ".wmv":
|
|
||||||
{
|
|
||||||
result = QualityTypes.TV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ".mkv":
|
|
||||||
{
|
|
||||||
result = QualityTypes.HDTV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Trace("Quality Parsed:{0} Title:", result, name);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Normalizes the title. removing all non-word characters as well as common tokens
|
|
||||||
/// such as 'the' and 'and'
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">title</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static string NormalizeTitle(string title)
|
|
||||||
{
|
|
||||||
return NormalizeRegex.Replace(title, String.Empty).ToLower();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Note: changing case on path is a problem for running on mono/*nix
|
|
||||||
//Not going to change the casing any more... Looks Ugly in UI anyways :P
|
|
||||||
public static string NormalizePath(string path)
|
|
||||||
{
|
|
||||||
if (String.IsNullOrEmpty(path))
|
|
||||||
throw new ArgumentException("Path can not be null or empty");
|
|
||||||
|
|
||||||
var info = new FileInfo(path);
|
|
||||||
|
|
||||||
if (info.FullName.StartsWith(@"\\")) //UNC
|
|
||||||
{
|
|
||||||
return info.FullName.TrimEnd('/', '\\', ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
return info.FullName.Trim('/', '\\', ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Proper = title.ToLower().Contains("proper"),
|
|
||||||
SeriesTitle = seriesName,
|
|
||||||
SeasonNumber = Convert.ToInt32(match[0].Groups["season"].Value),
|
|
||||||
Year = year,
|
|
||||||
Episodes = new List<int>()
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (Match matchGroup in match)
|
|
||||||
{
|
|
||||||
parsedEpisode.Episodes.Add(Convert.ToInt32(matchGroup.Groups["episode"].Value));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
parsedEpisode.Quality = ParseQuality(title);
|
|
||||||
Logger.Trace("Episode Parsed. {0}", parsedEpisode);
|
|
||||||
|
|
||||||
return parsedEpisode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a post title into season it contains
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">Title of the report</param>
|
|
||||||
/// <returns>Season information contained in the post</returns>
|
|
||||||
internal static SeasonParseResult ParseSeasonInfo(string title)
|
|
||||||
{
|
|
||||||
Logger.Trace("Parsing string '{0}'", title);
|
|
||||||
|
|
||||||
foreach (var regex in ReportTitleRegex)
|
|
||||||
{
|
|
||||||
var match = regex.Matches(title);
|
|
||||||
|
|
||||||
if (match.Count != 0)
|
|
||||||
{
|
|
||||||
var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
|
|
||||||
var year = 0;
|
|
||||||
Int32.TryParse(match[0].Groups["year"].Value, out year);
|
|
||||||
|
|
||||||
if (year < 1900 || year > DateTime.Now.Year + 1)
|
|
||||||
{
|
|
||||||
year = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var seasonNumber = Convert.ToInt32(match[0].Groups["season"].Value);
|
|
||||||
|
|
||||||
var result = new SeasonParseResult
|
|
||||||
{
|
|
||||||
SeriesTitle = seriesName,
|
|
||||||
SeasonNumber = seasonNumber,
|
|
||||||
Year = year
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
result.Quality = ParseQuality(title);
|
|
||||||
|
|
||||||
Logger.Trace("Season Parsed. {0}", result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null; //Return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a post title to find the series that relates to it
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">Title of the report</param>
|
|
||||||
/// <returns>Normalized Series Name</returns>
|
|
||||||
internal static string ParseSeriesName(string title)
|
|
||||||
{
|
|
||||||
Logger.Trace("Parsing string '{0}'", title);
|
|
||||||
|
|
||||||
foreach (var regex in ReportTitleRegex)
|
|
||||||
{
|
|
||||||
var match = regex.Matches(title);
|
|
||||||
|
|
||||||
if (match.Count != 0)
|
|
||||||
{
|
|
||||||
var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
|
|
||||||
var year = 0;
|
|
||||||
Int32.TryParse(match[0].Groups["year"].Value, out year);
|
|
||||||
|
|
||||||
if (year < 1900 || year > DateTime.Now.Year + 1)
|
|
||||||
{
|
|
||||||
year = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Trace("Series Parsed. {0}", seriesName);
|
|
||||||
return seriesName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses proper status out of a report title
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">Title of the report</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static bool ParseProper(string title)
|
|
||||||
{
|
|
||||||
return title.ToLower().Contains("proper");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static QualityTypes ParseQuality(string name)
|
|
||||||
{
|
|
||||||
Logger.Trace("Trying to parse quality for {0}", name);
|
|
||||||
|
|
||||||
var result = QualityTypes.Unknown;
|
|
||||||
name = name.ToLowerInvariant();
|
|
||||||
|
|
||||||
if (name.Contains("dvd"))
|
|
||||||
return QualityTypes.DVD;
|
|
||||||
|
|
||||||
if (name.Contains("bdrip") || name.Contains("brrip"))
|
|
||||||
{
|
|
||||||
return QualityTypes.BDRip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.Contains("xvid") || name.Contains("divx"))
|
|
||||||
{
|
|
||||||
if (name.Contains("bluray"))
|
|
||||||
{
|
|
||||||
return QualityTypes.BDRip;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QualityTypes.TV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.Contains("bluray"))
|
|
||||||
{
|
|
||||||
if (name.Contains("720p"))
|
|
||||||
return QualityTypes.Bluray720;
|
|
||||||
|
|
||||||
if (name.Contains("1080p"))
|
|
||||||
return QualityTypes.Bluray1080;
|
|
||||||
|
|
||||||
return QualityTypes.Bluray720;
|
|
||||||
}
|
|
||||||
if (name.Contains("web-dl"))
|
|
||||||
return QualityTypes.WEBDL;
|
|
||||||
if (name.Contains("x264") || name.Contains("h264") || name.Contains("720p"))
|
|
||||||
return QualityTypes.HDTV;
|
|
||||||
|
|
||||||
//Based on extension
|
|
||||||
if (result == QualityTypes.Unknown)
|
|
||||||
{
|
|
||||||
switch (new FileInfo(name).Extension.ToLower())
|
|
||||||
{
|
|
||||||
case ".avi":
|
|
||||||
case ".xvid":
|
|
||||||
case ".wmv":
|
|
||||||
{
|
|
||||||
result = QualityTypes.TV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ".mkv":
|
|
||||||
{
|
|
||||||
result = QualityTypes.HDTV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Trace("Quality Parsed:{0} Title:", result, name);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Normalizes the title. removing all non-word characters as well as common tokens
|
|
||||||
/// such as 'the' and 'and'
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="title">title</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static string NormalizeTitle(string title)
|
|
||||||
{
|
|
||||||
return NormalizeRegex.Replace(title, String.Empty).ToLower();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Note: changing case on path is a problem for running on mono/*nix
|
|
||||||
//Not going to change the casing any more... Looks Ugly in UI anyways :P
|
|
||||||
public static string NormalizePath(string path)
|
|
||||||
{
|
|
||||||
if (String.IsNullOrEmpty(path))
|
|
||||||
throw new ArgumentException("Path can not be null or empty");
|
|
||||||
|
|
||||||
var info = new FileInfo(path);
|
|
||||||
|
|
||||||
if (info.FullName.StartsWith(@"\\")) //UNC
|
|
||||||
{
|
|
||||||
return info.FullName.TrimEnd('/', '\\', ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
return info.FullName.Trim('/', '\\', ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@ namespace NzbDrone.Core.Providers
|
||||||
public interface ITvDbProvider
|
public interface ITvDbProvider
|
||||||
{
|
{
|
||||||
IList<TvdbSearchResult> SearchSeries(string name);
|
IList<TvdbSearchResult> SearchSeries(string name);
|
||||||
|
int GetBestMatch(List<TvdbSearchResult> searchResults, string searchString);
|
||||||
TvdbSearchResult GetSeries(string title);
|
TvdbSearchResult GetSeries(string title);
|
||||||
TvdbSeries GetSeries(int id, bool loadEpisodes);
|
TvdbSeries GetSeries(int id, bool loadEpisodes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,23 @@ namespace NzbDrone.Core.Providers
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetBestMatch(List<TvdbSearchResult> searchResults, string title)
|
||||||
|
{
|
||||||
|
if (searchResults.Count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
foreach (var tvdbSearchResult in searchResults)
|
||||||
|
{
|
||||||
|
if (IsTitleMatch(tvdbSearchResult.SeriesName, title))
|
||||||
|
{
|
||||||
|
Logger.Debug("Search for '{0}' was successful", title);
|
||||||
|
return tvdbSearchResult.Id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchResults[0].Id;
|
||||||
|
}
|
||||||
|
|
||||||
public TvdbSeries GetSeries(int id, bool loadEpisodes)
|
public TvdbSeries GetSeries(int id, bool loadEpisodes)
|
||||||
{
|
{
|
||||||
Logger.Debug("Fetching SeriesId'{0}' from tvdb", id);
|
Logger.Debug("Fetching SeriesId'{0}' from tvdb", id);
|
||||||
|
|
|
@ -80,12 +80,14 @@ namespace NzbDrone.Web.Controllers
|
||||||
ViewData["path"] = path;
|
ViewData["path"] = path;
|
||||||
ViewData["javaPath"] = path.Replace(Path.DirectorySeparatorChar, '|').Replace(Path.VolumeSeparatorChar, '^');
|
ViewData["javaPath"] = path.Replace(Path.DirectorySeparatorChar, '|').Replace(Path.VolumeSeparatorChar, '^');
|
||||||
|
|
||||||
|
var defaultQuality = _configProvider.DefaultQualityProfile;
|
||||||
var qualityProfiles = _qualityProvider.GetAllProfiles();
|
var qualityProfiles = _qualityProvider.GetAllProfiles();
|
||||||
|
|
||||||
ViewData["quality"] = new SelectList(
|
ViewData["quality"] = new SelectList(
|
||||||
qualityProfiles,
|
qualityProfiles,
|
||||||
"QualityProfileId",
|
"QualityProfileId",
|
||||||
"Name",
|
"Name",
|
||||||
"HD");
|
defaultQuality); ;
|
||||||
|
|
||||||
return PartialView("AddSeriesItem", suggestions);
|
return PartialView("AddSeriesItem", suggestions);
|
||||||
|
|
||||||
|
@ -117,8 +119,9 @@ namespace NzbDrone.Web.Controllers
|
||||||
public SelectList GetSuggestionList(string searchString)
|
public SelectList GetSuggestionList(string searchString)
|
||||||
{
|
{
|
||||||
var dataVal = _tvDbProvider.SearchSeries(searchString);
|
var dataVal = _tvDbProvider.SearchSeries(searchString);
|
||||||
|
var bestResult = _tvDbProvider.GetBestMatch(dataVal.ToList(), searchString);
|
||||||
|
|
||||||
return new SelectList(dataVal, "Id", "SeriesName");
|
return new SelectList(dataVal, "Id", "SeriesName", bestResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
|
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
|
||||||
<%
|
<%
|
||||||
|
if (Model.Count() == 0)
|
||||||
|
Html.DisplayText("No Series to Add");
|
||||||
|
|
||||||
foreach (var path in Model)
|
foreach (var path in Model)
|
||||||
{
|
{
|
||||||
Html.RenderAction("RenderPartial", "AddSeries", new { path });
|
Html.RenderAction("RenderPartial", "AddSeries", new { path });
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
@using NzbDrone.Core.Repository.Quality
|
@using NzbDrone.Core.Repository.Quality
|
||||||
@model SelectList
|
@model SelectList
|
||||||
<div padding: 10px" id="div_@(ViewData["guid"])">
|
<div style="padding:3px" id="div_@(ViewData["guid"])">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>@ViewData["path"].ToString()</legend>
|
<legend>@ViewData["path"].ToString()</legend>
|
||||||
<div>
|
<div>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
.Filterable(f => f.FilterMode(AutoCompleteFilterMode.Contains))
|
.Filterable(f => f.FilterMode(AutoCompleteFilterMode.Contains))
|
||||||
.HighlightFirstMatch(true)
|
.HighlightFirstMatch(true)
|
||||||
.HtmlAttributes(new { style = "width: 300px;" })
|
.HtmlAttributes(new { style = "width: 300px;" })
|
||||||
.SelectedIndex(0).Render();}
|
.Render();}
|
||||||
@Html.Telerik().DropDownList().Name("qualityList_" + ViewData["guid"].ToString()).BindTo((SelectList)ViewData["quality"]).HtmlAttributes(new { style = "width: 100px;" })
|
@Html.Telerik().DropDownList().Name("qualityList_" + ViewData["guid"].ToString()).BindTo((SelectList)ViewData["quality"]).HtmlAttributes(new { style = "width: 100px;" })
|
||||||
<button class="listButton" onclick="addSeries('@ViewData["guid"]','@ViewData["javaPath"].ToString()' )">
|
<button class="listButton" onclick="addSeries('@ViewData["guid"]','@ViewData["javaPath"].ToString()' )">
|
||||||
Add</button>
|
Add</button>
|
||||||
|
|
Loading…
Reference in New Issue