Added ability to filter scene mappings by regex via services.

Taloth Saldono 7 years ago
parent 2ae41a3404
commit a5bc4a8f11

@ -20,11 +20,14 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
private Mock<ISceneMappingProvider> _provider1; private Mock<ISceneMappingProvider> _provider1;
private Mock<ISceneMappingProvider> _provider2; private Mock<ISceneMappingProvider> _provider2;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_fakeMappings = Builder<SceneMapping>.CreateListOfSize(5).BuildListOfNew(); _fakeMappings = Builder<SceneMapping>.CreateListOfSize(5)
.All()
.With(v => v.FilterRegex = null)
.BuildListOfNew();
_fakeMappings[0].SearchTerm = "Words"; _fakeMappings[0].SearchTerm = "Words";
_fakeMappings[1].SearchTerm = "That"; _fakeMappings[1].SearchTerm = "That";
@ -193,7 +196,7 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings); Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
var tvdbId = Subject.FindTvdbId(parseTitle); var tvdbId = Subject.FindTvdbId(parseTitle);
var seasonNumber = Subject.GetSceneSeasonNumber(parseTitle); var seasonNumber = Subject.GetSceneSeasonNumber(parseTitle, null);
tvdbId.Should().Be(100); tvdbId.Should().Be(100);
seasonNumber.Should().Be(expectedSeasonNumber); seasonNumber.Should().Be(expectedSeasonNumber);
@ -314,6 +317,35 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
Subject.GetSceneNames(100, new List<int> { 4 }, new List<int> { 4 }).Should().BeEmpty(); Subject.GetSceneNames(100, new List<int> { 4 }, new List<int> { 4 }).Should().BeEmpty();
} }
[Test]
public void should_filter_by_regex()
{
var mappings = new List<SceneMapping>
{
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 100 },
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 101, FilterRegex="-Viva$" }
};
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
Subject.FindTvdbId("Amareto", "Amareto.S01E01.720p.WEB-DL-Viva").Should().Be(101);
Subject.FindTvdbId("Amareto", "Amareto.S01E01.720p.WEB-DL-DMO").Should().Be(100);
}
[Test]
public void should_throw_if_multiple_mappings()
{
var mappings = new List<SceneMapping>
{
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 100 },
new SceneMapping { Title = "Amareto", ParseTerm = "amareto", SearchTerm = "Amareto", TvdbId = 101 }
};
Mocker.GetMock<ISceneMappingRepository>().Setup(c => c.All()).Returns(mappings);
Assert.Throws<InvalidSceneMappingException>(() => Subject.FindTvdbId("Amareto", "Amareto.S01E01.720p.WEB-DL-Viva"));
}
private void AssertNoUpdate() private void AssertNoUpdate()
{ {
_provider1.Verify(c => c.GetSceneMappings(), Times.Once()); _provider1.Verify(c => c.GetSceneMappings(), Times.Once());

@ -192,7 +192,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
GivenAbsoluteNumberingSeries(); GivenAbsoluteNumberingSeries();
_parsedEpisodeInfo.Special = true; _parsedEpisodeInfo.Special = true;
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null); Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
@ -210,7 +210,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
GivenAbsoluteNumberingSeries(); GivenAbsoluteNumberingSeries();
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
.Returns(seasonNumber); .Returns(seasonNumber);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
@ -234,7 +234,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
GivenAbsoluteNumberingSeries(); GivenAbsoluteNumberingSeries();
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
.Returns(seasonNumber); .Returns(seasonNumber);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
@ -258,7 +258,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
GivenAbsoluteNumberingSeries(); GivenAbsoluteNumberingSeries();
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.GetSceneSeasonNumber(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
.Returns(seasonNumber); .Returns(seasonNumber);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
@ -280,7 +280,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
const int tvdbSeasonNumber = 5; const int tvdbSeasonNumber = 5;
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber }); .Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber });
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null); Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
@ -298,7 +298,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
const int tvdbSeasonNumber = 5; const int tvdbSeasonNumber = 5;
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber + 100 }); .Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber + 100 });
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null); Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);
@ -330,7 +330,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
const int tvdbSeasonNumber = -1; const int tvdbSeasonNumber = -1;
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle)) .Setup(s => s.FindSceneMapping(_parsedEpisodeInfo.SeriesTitle, It.IsAny<string>()))
.Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber }); .Returns(new SceneMapping { SeasonNumber = tvdbSeasonNumber, SceneSeasonNumber = _parsedEpisodeInfo.SeasonNumber });
Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null); Subject.GetEpisodes(_parsedEpisodeInfo, _series, true, null);

@ -118,7 +118,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
GivenMatchByTvRageId(); GivenMatchByTvRageId();
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(v => v.FindTvdbId(It.IsAny<string>())) .Setup(v => v.FindTvdbId(It.IsAny<string>(), It.IsAny<string>()))
.Returns(10); .Returns(10);
var result = Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId); var result = Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
@ -199,7 +199,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
public void should_use_tvdbid_matching_when_alias_is_found() public void should_use_tvdbid_matching_when_alias_is_found()
{ {
Mocker.GetMock<ISceneMappingService>() Mocker.GetMock<ISceneMappingService>()
.Setup(s => s.FindTvdbId(It.IsAny<string>())) .Setup(s => s.FindTvdbId(It.IsAny<string>(), It.IsAny<string>()))
.Returns(_series.TvdbId); .Returns(_series.TvdbId);
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria); Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NzbDrone.Common.Exceptions;
namespace NzbDrone.Core.DataAugmentation.Scene
{
public class InvalidSceneMappingException : NzbDroneException
{
public InvalidSceneMappingException(IEnumerable<SceneMapping> mappings)
: base(FormatMessage(mappings))
{
}
private static string FormatMessage(IEnumerable<SceneMapping> mappings)
{
return string.Format("Scene Mappings contains a conflict for tvdbids {0}, please notify Sonarr developers", mappings.Select(v => v.TvdbId));
}
}
}

@ -17,6 +17,9 @@ namespace NzbDrone.Core.DataAugmentation.Scene
public int? SeasonNumber { get; set; } public int? SeasonNumber { get; set; }
public int? SceneSeasonNumber { get; set; } public int? SceneSeasonNumber { get; set; }
public string FilterRegex { get; set; }
public string Type { get; set; } public string Type { get; set; }
} }
} }

@ -8,17 +8,18 @@ using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Core.Tv.Events; using NzbDrone.Core.Tv.Events;
using System.Text.RegularExpressions;
namespace NzbDrone.Core.DataAugmentation.Scene namespace NzbDrone.Core.DataAugmentation.Scene
{ {
public interface ISceneMappingService public interface ISceneMappingService
{ {
List<string> GetSceneNames(int tvdbId, List<int> seasonNumbers, List<int> sceneSeasonNumbers); List<string> GetSceneNames(int tvdbId, List<int> seasonNumbers, List<int> sceneSeasonNumbers);
int? FindTvdbId(string title); int? FindTvdbId(string sceneTitle, string releaseTitle);
List<SceneMapping> FindByTvdbId(int tvdbId); List<SceneMapping> FindByTvdbId(int tvdbId);
SceneMapping FindSceneMapping(string title); SceneMapping FindSceneMapping(string sceneTitle, string releaseTitle);
int? GetSceneSeasonNumber(string title); int? GetSceneSeasonNumber(string seriesTitle, string releaseTitle);
int? GetTvdbSeasonNumber(string title); int? GetTvdbSeasonNumber(string seriesTitle, string releaseTitle);
int? GetSceneSeasonNumber(int tvdbId, int seasonNumber); int? GetSceneSeasonNumber(int tvdbId, int seasonNumber);
} }
@ -65,14 +66,14 @@ namespace NzbDrone.Core.DataAugmentation.Scene
return FilterNonEnglish(names); return FilterNonEnglish(names);
} }
public int? FindTvdbId(string title) public int? FindTvdbId(string seriesTitle)
{ {
var mapping = FindMapping(title); return FindTvdbId(seriesTitle, null);
}
if (mapping == null)
return null;
return mapping.TvdbId; public int? FindTvdbId(string seriesTitle, string releaseTitle)
{
return FindSceneMapping(seriesTitle, releaseTitle)?.TvdbId;
} }
public List<SceneMapping> FindByTvdbId(int tvdbId) public List<SceneMapping> FindByTvdbId(int tvdbId)
@ -92,33 +93,31 @@ namespace NzbDrone.Core.DataAugmentation.Scene
return mappings; return mappings;
} }
public SceneMapping FindSceneMapping(string title) public SceneMapping FindSceneMapping(string seriesTitle, string releaseTitle)
{ {
return FindMapping(title); var mappings = FindMappings(seriesTitle, releaseTitle);
}
public int? GetSceneSeasonNumber(string title)
{
var mapping = FindMapping(title);
if (mapping == null) if (mappings == null)
{ {
return null; return null;
} }
return mapping.SceneSeasonNumber; if (mappings.Count <= 1)
{
return mappings.FirstOrDefault();
}
throw new InvalidSceneMappingException(mappings);
} }
public int? GetTvdbSeasonNumber(string title) public int? GetSceneSeasonNumber(string seriesTitle, string releaseTitle)
{ {
var mapping = FindMapping(title); return FindSceneMapping(seriesTitle, releaseTitle)?.SceneSeasonNumber;
}
if (mapping == null)
{
return null;
}
return mapping.SeasonNumber; public int? GetTvdbSeasonNumber(string seriesTitle, string releaseTitle)
{
return FindSceneMapping(seriesTitle, releaseTitle)?.SeasonNumber;
} }
public int? GetSceneSeasonNumber(int tvdbId, int seasonNumber) public int? GetSceneSeasonNumber(int tvdbId, int seasonNumber)
@ -184,44 +183,48 @@ namespace NzbDrone.Core.DataAugmentation.Scene
_logger.Error(ex, "Failed to Update Scene Mappings."); _logger.Error(ex, "Failed to Update Scene Mappings.");
} }
} }
RefreshCache(); RefreshCache();
_eventAggregator.PublishEvent(new SceneMappingsUpdatedEvent()); _eventAggregator.PublishEvent(new SceneMappingsUpdatedEvent());
} }
private SceneMapping FindMapping(string title) private List<SceneMapping> FindMappings(string seriesTitle, string releaseTitle)
{ {
if (_getTvdbIdCache.Count == 0) if (_getTvdbIdCache.Count == 0)
{ {
RefreshCache(); RefreshCache();
} }
var candidates = _getTvdbIdCache.Find(title.CleanSeriesTitle()); var candidates = _getTvdbIdCache.Find(seriesTitle.CleanSeriesTitle());
if (candidates == null) if (candidates == null)
{ {
return null; return null;
} }
if (candidates.Count == 1) candidates = FilterSceneMappings(candidates, releaseTitle);
if (candidates.Count <= 1)
{ {
return candidates.First(); return candidates;
} }
var exactMatch = candidates.OrderByDescending(v => v.SeasonNumber) var exactMatch = candidates.OrderByDescending(v => v.SeasonNumber)
.FirstOrDefault(v => v.Title == title); .Where(v => v.Title == seriesTitle)
.ToList();
if (exactMatch != null) if (exactMatch.Any())
{ {
return exactMatch; return exactMatch;
} }
var closestMatch = candidates.OrderBy(v => title.LevenshteinDistance(v.Title, 10, 1, 10)) var closestMatch = candidates.OrderBy(v => seriesTitle.LevenshteinDistance(v.Title, 10, 1, 10))
.ThenByDescending(v => v.SeasonNumber) .ThenByDescending(v => v.SeasonNumber)
.First(); .First();
return closestMatch;
return candidates.Where(v => v.Title == closestMatch.Title).ToList();
} }
private void RefreshCache() private void RefreshCache()
@ -232,6 +235,26 @@ namespace NzbDrone.Core.DataAugmentation.Scene
_findByTvdbIdCache.Update(mappings.GroupBy(v => v.TvdbId).ToDictionary(v => v.Key.ToString(), v => v.ToList())); _findByTvdbIdCache.Update(mappings.GroupBy(v => v.TvdbId).ToDictionary(v => v.Key.ToString(), v => v.ToList()));
} }
private List<SceneMapping> FilterSceneMappings(List<SceneMapping> candidates, string releaseTitle)
{
var filteredCandidates = candidates.Where(v => v.FilterRegex.IsNotNullOrWhiteSpace()).ToList();
var normalCandidates = candidates.Except(filteredCandidates).ToList();
if (releaseTitle.IsNullOrWhiteSpace())
{
return normalCandidates;
}
filteredCandidates = filteredCandidates.Where(v => Regex.IsMatch(releaseTitle, v.FilterRegex)).ToList();
if (filteredCandidates.Any())
{
return filteredCandidates;
}
return normalCandidates;
}
private List<string> FilterNonEnglish(List<string> titles) private List<string> FilterNonEnglish(List<string> titles)
{ {
return titles.Where(title => title.All(c => c <= 255)).ToList(); return titles.Where(title => title.All(c => c <= 255)).ToList();

@ -0,0 +1,16 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(112)]
public class added_regex_to_scenemapping : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("SceneMappings").AddColumn("FilterRegex").AsString().Nullable();
}
}
}

@ -140,6 +140,7 @@
<Compile Include="DataAugmentation\DailySeries\DailySeries.cs" /> <Compile Include="DataAugmentation\DailySeries\DailySeries.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxy.cs" /> <Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxy.cs" />
<Compile Include="DataAugmentation\DailySeries\DailySeriesService.cs" /> <Compile Include="DataAugmentation\DailySeries\DailySeriesService.cs" />
<Compile Include="DataAugmentation\Scene\InvalidSceneMappingException.cs" />
<Compile Include="DataAugmentation\Scene\ISceneMappingProvider.cs" /> <Compile Include="DataAugmentation\Scene\ISceneMappingProvider.cs" />
<Compile Include="DataAugmentation\Scene\SceneMapping.cs" /> <Compile Include="DataAugmentation\Scene\SceneMapping.cs" />
<Compile Include="DataAugmentation\Scene\SceneMappingProxy.cs" /> <Compile Include="DataAugmentation\Scene\SceneMappingProxy.cs" />
@ -249,6 +250,7 @@
<Compile Include="Datastore\Migration\069_quality_proper.cs" /> <Compile Include="Datastore\Migration\069_quality_proper.cs" />
<Compile Include="Datastore\Migration\070_delay_profile.cs" /> <Compile Include="Datastore\Migration\070_delay_profile.cs" />
<Compile Include="Datastore\Migration\102_add_language_to_episodeFiles_history_and_blacklist.cs" /> <Compile Include="Datastore\Migration\102_add_language_to_episodeFiles_history_and_blacklist.cs" />
<Compile Include="Datastore\Migration\112_added_regex_to_scenemapping.cs" />
<Compile Include="Datastore\Migration\110_fix_extra_files_config.cs" /> <Compile Include="Datastore\Migration\110_fix_extra_files_config.cs" />
<Compile Include="Datastore\Migration\109_import_extra_files.cs" /> <Compile Include="Datastore\Migration\109_import_extra_files.cs" />
<Compile Include="Datastore\Migration\108_fix_extra_file_extension.cs" /> <Compile Include="Datastore\Migration\108_fix_extra_file_extension.cs" />

@ -6,6 +6,7 @@ namespace NzbDrone.Core.Parser.Model
{ {
public class ParsedEpisodeInfo public class ParsedEpisodeInfo
{ {
public string ReleaseTitle { get; set; }
public string SeriesTitle { get; set; } public string SeriesTitle { get; set; }
public SeriesTitleInfo SeriesTitleInfo { get; set; } public SeriesTitleInfo SeriesTitleInfo { get; set; }
public QualityModel Quality { get; set; } public QualityModel Quality { get; set; }
@ -89,4 +90,4 @@ namespace NzbDrone.Core.Parser.Model
return string.Format("{0} - {1} {2}", SeriesTitle, episodeString, Quality); return string.Format("{0} - {1} {2}", SeriesTitle, episodeString, Quality);
} }
} }
} }

@ -316,9 +316,9 @@ namespace NzbDrone.Core.Parser
Logger.Debug("Reversed name detected. Converted to '{0}'", title); Logger.Debug("Reversed name detected. Converted to '{0}'", title);
} }
var simpleTitle = SimpleTitleRegex.Replace(title, string.Empty); title = RemoveFileExtension(title);
simpleTitle = RemoveFileExtension(simpleTitle); var simpleTitle = SimpleTitleRegex.Replace(title, string.Empty);
// TODO: Quick fix stripping [url] - prefixes. // TODO: Quick fix stripping [url] - prefixes.
simpleTitle = WebsitePrefixRegex.Replace(simpleTitle, string.Empty); simpleTitle = WebsitePrefixRegex.Replace(simpleTitle, string.Empty);
@ -355,7 +355,7 @@ namespace NzbDrone.Core.Parser
Logger.Trace(regex); Logger.Trace(regex);
try try
{ {
var result = ParseMatchCollection(match); var result = ParseMatchCollection(match, title);
if (result != null) if (result != null)
{ {
@ -522,7 +522,7 @@ namespace NzbDrone.Core.Parser
return seriesTitleInfo; return seriesTitleInfo;
} }
private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchCollection) private static ParsedEpisodeInfo ParseMatchCollection(MatchCollection matchCollection, string title)
{ {
var seriesName = matchCollection[0].Groups["title"].Value.Replace('.', ' ').Replace('_', ' '); var seriesName = matchCollection[0].Groups["title"].Value.Replace('.', ' ').Replace('_', ' ');
seriesName = RequestInfoRegex.Replace(seriesName, "").Trim(' '); seriesName = RequestInfoRegex.Replace(seriesName, "").Trim(' ');
@ -551,6 +551,7 @@ namespace NzbDrone.Core.Parser
result = new ParsedEpisodeInfo result = new ParsedEpisodeInfo
{ {
ReleaseTitle = title,
SeasonNumber = seasons.First(), SeasonNumber = seasons.First(),
EpisodeNumbers = new int[0], EpisodeNumbers = new int[0],
AbsoluteEpisodeNumbers = new int[0] AbsoluteEpisodeNumbers = new int[0]
@ -644,6 +645,7 @@ namespace NzbDrone.Core.Parser
result = new ParsedEpisodeInfo result = new ParsedEpisodeInfo
{ {
ReleaseTitle = title,
AirDate = airDate.ToString(Episode.AIR_DATE_FORMAT), AirDate = airDate.ToString(Episode.AIR_DATE_FORMAT),
}; };
} }

@ -19,7 +19,7 @@ namespace NzbDrone.Core.Parser
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null); RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null);
RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int seriesId, IEnumerable<int> episodeIds); RemoteEpisode Map(ParsedEpisodeInfo parsedEpisodeInfo, int seriesId, IEnumerable<int> episodeIds);
List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series, bool sceneSource, SearchCriteriaBase searchCriteria = null); List<Episode> GetEpisodes(ParsedEpisodeInfo parsedEpisodeInfo, Series series, bool sceneSource, SearchCriteriaBase searchCriteria = null);
ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null); ParsedEpisodeInfo ParseSpecialEpisodeTitle(string releaseTitle, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null);
} }
public class ParsingService : IParsingService public class ParsingService : IParsingService
@ -103,6 +103,13 @@ namespace NzbDrone.Core.Parser
return _seriesService.FindByTitle(title); return _seriesService.FindByTitle(title);
} }
var tvdbId = _sceneMappingService.FindTvdbId(parsedEpisodeInfo.SeriesTitle, parsedEpisodeInfo.ReleaseTitle);
if (tvdbId.HasValue)
{
return _seriesService.FindByTvdbId(tvdbId.Value);
}
var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle); var series = _seriesService.FindByTitle(parsedEpisodeInfo.SeriesTitle);
if (series == null) if (series == null)
@ -177,29 +184,26 @@ namespace NzbDrone.Core.Parser
return GetStandardEpisodes(series, parsedEpisodeInfo, sceneSource, searchCriteria); return GetStandardEpisodes(series, parsedEpisodeInfo, sceneSource, searchCriteria);
} }
public ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null) public ParsedEpisodeInfo ParseSpecialEpisodeTitle(string releaseTitle, int tvdbId, int tvRageId, SearchCriteriaBase searchCriteria = null)
{ {
if (searchCriteria != null) if (searchCriteria != null)
{ {
if (tvdbId == 0)
tvdbId = _sceneMappingService.FindTvdbId(title) ?? 0;
if (tvdbId != 0 && tvdbId == searchCriteria.Series.TvdbId) if (tvdbId != 0 && tvdbId == searchCriteria.Series.TvdbId)
{ {
return ParseSpecialEpisodeTitle(title, searchCriteria.Series); return ParseSpecialEpisodeTitle(releaseTitle, searchCriteria.Series);
} }
if (tvRageId != 0 && tvRageId == searchCriteria.Series.TvRageId) if (tvRageId != 0 && tvRageId == searchCriteria.Series.TvRageId)
{ {
return ParseSpecialEpisodeTitle(title, searchCriteria.Series); return ParseSpecialEpisodeTitle(releaseTitle, searchCriteria.Series);
} }
} }
var series = GetSeries(title); var series = GetSeries(releaseTitle);
if (series == null) if (series == null)
{ {
series = _seriesService.FindByTitleInexact(title); series = _seriesService.FindByTitleInexact(releaseTitle);
} }
if (series == null && tvdbId > 0) if (series == null && tvdbId > 0)
@ -214,34 +218,39 @@ namespace NzbDrone.Core.Parser
if (series == null) if (series == null)
{ {
_logger.Debug("No matching series {0}", title); _logger.Debug("No matching series {0}", releaseTitle);
return null; return null;
} }
return ParseSpecialEpisodeTitle(title, series); return ParseSpecialEpisodeTitle(releaseTitle, series);
} }
private ParsedEpisodeInfo ParseSpecialEpisodeTitle(string title, Series series) private ParsedEpisodeInfo ParseSpecialEpisodeTitle(string releaseTitle, Series series)
{ {
// find special episode in series season 0 // find special episode in series season 0
var episode = _episodeService.FindEpisodeByTitle(series.Id, 0, title); var episode = _episodeService.FindEpisodeByTitle(series.Id, 0, releaseTitle);
if (episode != null) if (episode != null)
{ {
// create parsed info from tv episode // create parsed info from tv episode
var info = new ParsedEpisodeInfo(); var info = new ParsedEpisodeInfo
info.SeriesTitle = series.Title; {
info.SeriesTitleInfo = new SeriesTitleInfo(); ReleaseTitle = releaseTitle,
info.SeriesTitleInfo.Title = info.SeriesTitle; SeriesTitle = series.Title,
info.SeasonNumber = episode.SeasonNumber; SeriesTitleInfo = new SeriesTitleInfo
info.EpisodeNumbers = new int[1] { episode.EpisodeNumber }; {
info.FullSeason = false; Title = series.Title
info.Quality = QualityParser.ParseQuality(title); },
info.ReleaseGroup = Parser.ParseReleaseGroup(title); SeasonNumber = episode.SeasonNumber,
info.Language = LanguageParser.ParseLanguage(title); EpisodeNumbers = new int[1] { episode.EpisodeNumber },
info.Special = true; FullSeason = false,
Quality = QualityParser.ParseQuality(releaseTitle),
_logger.Debug("Found special episode {0} for title '{1}'", info, title); ReleaseGroup = Parser.ParseReleaseGroup(releaseTitle),
Language = LanguageParser.ParseLanguage(releaseTitle),
Special = true
};
_logger.Debug("Found special episode {0} for title '{1}'", info, releaseTitle);
return info; return info;
} }
@ -252,7 +261,7 @@ namespace NzbDrone.Core.Parser
{ {
Series series = null; Series series = null;
var sceneMappingTvdbId = _sceneMappingService.FindTvdbId(parsedEpisodeInfo.SeriesTitle); var sceneMappingTvdbId = _sceneMappingService.FindTvdbId(parsedEpisodeInfo.SeriesTitle, parsedEpisodeInfo.ReleaseTitle);
if (sceneMappingTvdbId.HasValue) if (sceneMappingTvdbId.HasValue)
{ {
if (searchCriteria != null && searchCriteria.Series.TvdbId == sceneMappingTvdbId.Value) if (searchCriteria != null && searchCriteria.Series.TvdbId == sceneMappingTvdbId.Value)
@ -341,7 +350,7 @@ namespace NzbDrone.Core.Parser
{ {
var result = new List<Episode>(); var result = new List<Episode>();
var sceneSeasonNumber = _sceneMappingService.GetSceneSeasonNumber(parsedEpisodeInfo.SeriesTitle); var sceneSeasonNumber = _sceneMappingService.GetSceneSeasonNumber(parsedEpisodeInfo.SeriesTitle, parsedEpisodeInfo.ReleaseTitle);
foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers) foreach (var absoluteEpisodeNumber in parsedEpisodeInfo.AbsoluteEpisodeNumbers)
{ {
@ -405,7 +414,7 @@ namespace NzbDrone.Core.Parser
if (sceneSource) if (sceneSource)
{ {
var sceneMapping = _sceneMappingService.FindSceneMapping(parsedEpisodeInfo.SeriesTitle); var sceneMapping = _sceneMappingService.FindSceneMapping(parsedEpisodeInfo.SeriesTitle, parsedEpisodeInfo.ReleaseTitle);
if (sceneMapping != null && sceneMapping.SeasonNumber.HasValue && sceneMapping.SeasonNumber.Value >= 0 && if (sceneMapping != null && sceneMapping.SeasonNumber.HasValue && sceneMapping.SeasonNumber.Value >= 0 &&
sceneMapping.SceneSeasonNumber == seasonNumber) sceneMapping.SceneSeasonNumber == seasonNumber)
@ -475,4 +484,4 @@ namespace NzbDrone.Core.Parser
return result; return result;
} }
} }
} }

@ -35,21 +35,18 @@ namespace NzbDrone.Core.Tv
{ {
private readonly ISeriesRepository _seriesRepository; private readonly ISeriesRepository _seriesRepository;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly ISceneMappingService _sceneMappingService;
private readonly IEpisodeService _episodeService; private readonly IEpisodeService _episodeService;
private readonly IBuildFileNames _fileNameBuilder; private readonly IBuildFileNames _fileNameBuilder;
private readonly Logger _logger; private readonly Logger _logger;
public SeriesService(ISeriesRepository seriesRepository, public SeriesService(ISeriesRepository seriesRepository,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
ISceneMappingService sceneMappingService,
IEpisodeService episodeService, IEpisodeService episodeService,
IBuildFileNames fileNameBuilder, IBuildFileNames fileNameBuilder,
Logger logger) Logger logger)
{ {
_seriesRepository = seriesRepository; _seriesRepository = seriesRepository;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_sceneMappingService = sceneMappingService;
_episodeService = episodeService; _episodeService = episodeService;
_fileNameBuilder = fileNameBuilder; _fileNameBuilder = fileNameBuilder;
_logger = logger; _logger = logger;
@ -85,13 +82,6 @@ namespace NzbDrone.Core.Tv
public Series FindByTitle(string title) public Series FindByTitle(string title)
{ {
var tvdbId = _sceneMappingService.FindTvdbId(title);
if (tvdbId.HasValue)
{
return _seriesRepository.FindByTvdbId(tvdbId.Value);
}
return _seriesRepository.FindByTitle(title.CleanSeriesTitle()); return _seriesRepository.FindByTitle(title.CleanSeriesTitle());
} }
@ -107,11 +97,11 @@ namespace NzbDrone.Core.Tv
} }
if (list.Count == 1) if (list.Count == 1)
{ {
// return the first series if there is only one // return the first series if there is only one
return list.Single(); return list.Single();
} }
// build ordered list of series by position in the search string // build ordered list of series by position in the search string
var query = var query =
list.Select(series => new list.Select(series => new
{ {
position = cleanTitle.IndexOf(series.CleanTitle), position = cleanTitle.IndexOf(series.CleanTitle),
@ -192,7 +182,7 @@ namespace NzbDrone.Core.Tv
_logger.Trace("Not changing path for: {0}", s.Title); _logger.Trace("Not changing path for: {0}", s.Title);
} }
} }
_seriesRepository.UpdateMany(series); _seriesRepository.UpdateMany(series);
_logger.Debug("{0} series updated", series.Count); _logger.Debug("{0} series updated", series.Count);

Loading…
Cancel
Save