mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-16 11:37:58 +02:00
parent
5251db7224
commit
a75e10c4c9
@ -3,6 +3,7 @@
|
|||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using Sonarr.Http;
|
using Sonarr.Http;
|
||||||
|
using Sonarr.Http.REST;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Parse
|
namespace NzbDrone.Api.Parse
|
||||||
{
|
{
|
||||||
@ -21,6 +22,12 @@ private ParseResource Parse()
|
|||||||
{
|
{
|
||||||
var title = Request.Query.Title.Value as string;
|
var title = Request.Query.Title.Value as string;
|
||||||
var path = Request.Query.Path.Value as string;
|
var path = Request.Query.Path.Value as string;
|
||||||
|
|
||||||
|
if (path.IsNullOrWhiteSpace() && title.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new BadRequestException("title or path is missing");
|
||||||
|
}
|
||||||
|
|
||||||
var parsedEpisodeInfo = path.IsNotNullOrWhiteSpace() ? Parser.ParsePath(path) : Parser.ParseTitle(title);
|
var parsedEpisodeInfo = path.IsNotNullOrWhiteSpace() ? Parser.ParsePath(path) : Parser.ParseTitle(title);
|
||||||
|
|
||||||
if (parsedEpisodeInfo == null)
|
if (parsedEpisodeInfo == null)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using Moq;
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.DataAugmentation.Scene;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
@ -43,5 +45,18 @@ public void should_fallback_to_title_without_year_and_year_when_title_lookup_fai
|
|||||||
.Verify(s => s.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear,
|
.Verify(s => s.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear,
|
||||||
parsedEpisodeInfo.SeriesTitleInfo.Year), Times.Once());
|
parsedEpisodeInfo.SeriesTitleInfo.Year), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_parse_concatenated_title()
|
||||||
|
{
|
||||||
|
var series = new Series { TvdbId = 100 };
|
||||||
|
Mocker.GetMock<ISeriesService>().Setup(v => v.FindByTitle("Welcome")).Returns(series);
|
||||||
|
Mocker.GetMock<ISceneMappingService>().Setup(v => v.FindTvdbId("Mairimashita", It.IsAny<string>())).Returns(100);
|
||||||
|
|
||||||
|
var result = Subject.GetSeries("Welcome (Mairimashita).S01E01.720p.WEB-DL-Viva");
|
||||||
|
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.TvdbId.Should().Be(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,6 @@ public class SeriesTitleInfo
|
|||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string TitleWithoutYear { get; set; }
|
public string TitleWithoutYear { get; set; }
|
||||||
public int Year { get; set; }
|
public int Year { get; set; }
|
||||||
|
public string[] AllTitles { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,6 +385,9 @@ public static class Parser
|
|||||||
private static readonly Regex YearInTitleRegex = new Regex(@"^(?<title>.+?)(?:\W|_)?(?<year>\d{4})",
|
private static readonly Regex YearInTitleRegex = new Regex(@"^(?<title>.+?)(?:\W|_)?(?<year>\d{4})",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
|
private static readonly Regex TitleComponentsRegex = new Regex(@"^(?<title>.+?) \((?<title>.+?)\)$",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly Regex WordDelimiterRegex = new Regex(@"(\s|\.|,|_|-|=|\|)+", RegexOptions.Compiled);
|
private static readonly Regex WordDelimiterRegex = new Regex(@"(\s|\.|,|_|-|=|\|)+", RegexOptions.Compiled);
|
||||||
private static readonly Regex PunctuationRegex = new Regex(@"[^\w\s]", RegexOptions.Compiled);
|
private static readonly Regex PunctuationRegex = new Regex(@"[^\w\s]", RegexOptions.Compiled);
|
||||||
private static readonly Regex CommonWordRegex = new Regex(@"\b(a|an|the|and|or|of)\b\s?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
private static readonly Regex CommonWordRegex = new Regex(@"\b(a|an|the|and|or|of)\b\s?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
@ -670,13 +673,19 @@ private static SeriesTitleInfo GetSeriesTitleInfo(string title)
|
|||||||
{
|
{
|
||||||
seriesTitleInfo.TitleWithoutYear = title;
|
seriesTitleInfo.TitleWithoutYear = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
seriesTitleInfo.TitleWithoutYear = match.Groups["title"].Value;
|
seriesTitleInfo.TitleWithoutYear = match.Groups["title"].Value;
|
||||||
seriesTitleInfo.Year = Convert.ToInt32(match.Groups["year"].Value);
|
seriesTitleInfo.Year = Convert.ToInt32(match.Groups["year"].Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var matchComponents = TitleComponentsRegex.Match(seriesTitleInfo.TitleWithoutYear);
|
||||||
|
|
||||||
|
if (matchComponents.Success)
|
||||||
|
{
|
||||||
|
seriesTitleInfo.AllTitles = matchComponents.Groups["title"].Captures.OfType<Capture>().Select(v => v.Value).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
return seriesTitleInfo;
|
return seriesTitleInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,11 @@ public Series GetSeries(string title)
|
|||||||
|
|
||||||
var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
||||||
|
|
||||||
|
if (series == null && parsedEpisodeInfo.SeriesTitleInfo.AllTitles != null)
|
||||||
|
{
|
||||||
|
series = GetSeriesByAllTitles(parsedEpisodeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
{
|
{
|
||||||
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear,
|
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear,
|
||||||
@ -66,6 +71,49 @@ public Series GetSeries(string title)
|
|||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Series GetSeriesByAllTitles(ParsedEpisodeInfo parsedEpisodeInfo)
|
||||||
|
{
|
||||||
|
Series foundSeries = null;
|
||||||
|
int? foundTvdbId = null;
|
||||||
|
|
||||||
|
// Match each title individually, they must all resolve to the same tvdbid
|
||||||
|
foreach (var title in parsedEpisodeInfo.SeriesTitleInfo.AllTitles)
|
||||||
|
{
|
||||||
|
var series = _seriesService.FindByTitle(title);
|
||||||
|
var tvdbId = series?.TvdbId;
|
||||||
|
|
||||||
|
if (series == null)
|
||||||
|
{
|
||||||
|
tvdbId = _sceneMappingService.FindTvdbId(title, parsedEpisodeInfo.ReleaseTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tvdbId.HasValue)
|
||||||
|
{
|
||||||
|
_logger.Trace("Title {0} not matching any series.", title);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundTvdbId.HasValue && tvdbId != foundTvdbId)
|
||||||
|
{
|
||||||
|
_logger.Trace("Title {0} both matches tvdbid {1} and {2}, no series selected.", parsedEpisodeInfo.SeriesTitle, foundTvdbId, tvdbId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundSeries == null)
|
||||||
|
{
|
||||||
|
foundSeries = series;
|
||||||
|
}
|
||||||
|
foundTvdbId = tvdbId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundSeries == null && foundTvdbId.HasValue)
|
||||||
|
{
|
||||||
|
foundSeries = _seriesService.FindByTvdbId(foundTvdbId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundSeries;
|
||||||
|
}
|
||||||
|
|
||||||
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null)
|
public RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null)
|
||||||
{
|
{
|
||||||
var remoteEpisode = new RemoteEpisode
|
var remoteEpisode = new RemoteEpisode
|
||||||
@ -270,6 +318,11 @@ private Series GetSeries(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tv
|
|||||||
|
|
||||||
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
|
||||||
|
|
||||||
|
if (series == null && parsedEpisodeInfo.SeriesTitleInfo.AllTitles != null)
|
||||||
|
{
|
||||||
|
series = GetSeriesByAllTitles(parsedEpisodeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
if (series == null && parsedEpisodeInfo.SeriesTitleInfo.Year > 0)
|
if (series == null && parsedEpisodeInfo.SeriesTitleInfo.Year > 0)
|
||||||
{
|
{
|
||||||
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear, parsedEpisodeInfo.SeriesTitleInfo.Year);
|
series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitleInfo.TitleWithoutYear, parsedEpisodeInfo.SeriesTitleInfo.Year);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
using Sonarr.Api.V3.Episodes;
|
using Sonarr.Api.V3.Episodes;
|
||||||
using Sonarr.Api.V3.Series;
|
using Sonarr.Api.V3.Series;
|
||||||
using Sonarr.Http;
|
using Sonarr.Http;
|
||||||
|
using Sonarr.Http.REST;
|
||||||
|
|
||||||
namespace Sonarr.Api.V3.Parse
|
namespace Sonarr.Api.V3.Parse
|
||||||
{
|
{
|
||||||
@ -21,6 +22,12 @@ private ParseResource Parse()
|
|||||||
{
|
{
|
||||||
var title = Request.Query.Title.Value as string;
|
var title = Request.Query.Title.Value as string;
|
||||||
var path = Request.Query.Path.Value as string;
|
var path = Request.Query.Path.Value as string;
|
||||||
|
|
||||||
|
if (path.IsNullOrWhiteSpace() && title.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new BadRequestException("title or path is missing");
|
||||||
|
}
|
||||||
|
|
||||||
var parsedEpisodeInfo = path.IsNotNullOrWhiteSpace() ? Parser.ParsePath(path) : Parser.ParseTitle(title);
|
var parsedEpisodeInfo = path.IsNotNullOrWhiteSpace() ? Parser.ParsePath(path) : Parser.ParseTitle(title);
|
||||||
|
|
||||||
if (parsedEpisodeInfo == null)
|
if (parsedEpisodeInfo == null)
|
||||||
|
Loading…
Reference in New Issue
Block a user