mirror of
https://github.com/lidarr/Lidarr
synced 2025-01-30 19:02:06 +00:00
Fixed: Improved special episode parsing for multiple matching titles
This commit is contained in:
parent
0adea0ded6
commit
8aa6969aee
3 changed files with 48 additions and 21 deletions
|
@ -14,32 +14,50 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeServiceTests
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class FindEpisodeByTitleFixture : CoreTest<EpisodeService>
|
public class FindEpisodeByTitleFixture : CoreTest<EpisodeService>
|
||||||
{
|
{
|
||||||
private Episode _episode;
|
private List<Episode> _episodes;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_episode = Builder<Episode>.CreateNew().Build();
|
_episodes = Builder<Episode>.CreateListOfSize(5)
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenEpisodeTitle(string title)
|
private void GivenEpisodesWithTitles(params string[] titles)
|
||||||
{
|
{
|
||||||
_episode.Title = title;
|
for (int i = 0; i < titles.Count(); i++)
|
||||||
|
{
|
||||||
|
_episodes[i].Title = titles[i];
|
||||||
|
}
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeRepository>()
|
Mocker.GetMock<IEpisodeRepository>()
|
||||||
.Setup(s => s.GetEpisodes(It.IsAny<int>(), It.IsAny<int>()))
|
.Setup(s => s.GetEpisodes(It.IsAny<int>(), It.IsAny<int>()))
|
||||||
.Returns(new List<Episode> { _episode });
|
.Returns(_episodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_find_episode_by_title()
|
public void should_find_episode_by_title()
|
||||||
{
|
{
|
||||||
GivenEpisodeTitle("A Journey to the Highlands");
|
const string expectedTitle = "A Journey to the Highlands";
|
||||||
|
GivenEpisodesWithTitles(expectedTitle);
|
||||||
|
|
||||||
Subject.FindEpisodeByTitle(1, 1, "Downton.Abbey.A.Journey.To.The.Highlands.720p.BluRay.x264-aAF")
|
Subject.FindEpisodeByTitle(1, 1, "Downton.Abbey.A.Journey.To.The.Highlands.720p.BluRay.x264-aAF")
|
||||||
.Title
|
.Title
|
||||||
.Should()
|
.Should()
|
||||||
.Be(_episode.Title);
|
.Be(expectedTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_prefer_longer_match()
|
||||||
|
{
|
||||||
|
const string expectedTitle = "Inside The Walking Dead: Walker University";
|
||||||
|
GivenEpisodesWithTitles("Inside The Walking Dead", expectedTitle);
|
||||||
|
|
||||||
|
Subject.FindEpisodeByTitle(1, 1, "The.Walking.Dead.S04.Special.Inside.The.Walking.Dead.Walker.University.720p.HDTV.x264-W4F")
|
||||||
|
.Title
|
||||||
|
.Should()
|
||||||
|
.Be(expectedTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -357,9 +357,12 @@ public static string CleanSeriesTitle(this string title)
|
||||||
|
|
||||||
public static string NormalizeEpisodeTitle(string title)
|
public static string NormalizeEpisodeTitle(string title)
|
||||||
{
|
{
|
||||||
return SpecialEpisodeWordRegex.Replace(title, String.Empty)
|
title = SpecialEpisodeWordRegex.Replace(title, String.Empty);
|
||||||
.Trim()
|
title = PunctuationRegex.Replace(title, " ");
|
||||||
.ToLower();
|
title = DuplicateSpacesRegex.Replace(title, " ");
|
||||||
|
|
||||||
|
return title.Trim()
|
||||||
|
.ToLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string NormalizeTitle(string title)
|
public static string NormalizeTitle(string title)
|
||||||
|
|
|
@ -17,7 +17,7 @@ public interface IEpisodeService
|
||||||
List<Episode> GetEpisodes(IEnumerable<Int32> ids);
|
List<Episode> GetEpisodes(IEnumerable<Int32> ids);
|
||||||
Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber);
|
Episode FindEpisode(int seriesId, int seasonNumber, int episodeNumber);
|
||||||
Episode FindEpisode(int seriesId, int absoluteEpisodeNumber);
|
Episode FindEpisode(int seriesId, int absoluteEpisodeNumber);
|
||||||
Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string episodeTitle);
|
Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string releaseTitle);
|
||||||
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber);
|
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int seasonNumber, int episodeNumber);
|
||||||
Episode FindEpisodeBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
|
Episode FindEpisodeBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
|
||||||
Episode GetEpisode(int seriesId, String date);
|
Episode GetEpisode(int seriesId, String date);
|
||||||
|
@ -103,19 +103,25 @@ public List<Episode> GetEpisodesBySeason(int seriesId, int seasonNumber)
|
||||||
return _episodeRepository.GetEpisodes(seriesId, seasonNumber);
|
return _episodeRepository.GetEpisodes(seriesId, seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string episodeTitle)
|
public Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string releaseTitle)
|
||||||
{
|
{
|
||||||
// TODO: can replace this search mechanism with something smarter/faster/better
|
// TODO: can replace this search mechanism with something smarter/faster/better
|
||||||
var search = Parser.Parser.NormalizeEpisodeTitle(episodeTitle).Replace(".", " ");
|
var normalizedReleaseTitle = Parser.Parser.NormalizeEpisodeTitle(releaseTitle).Replace(".", " ");
|
||||||
|
var episodes = _episodeRepository.GetEpisodes(seriesId, seasonNumber);
|
||||||
|
|
||||||
return _episodeRepository.GetEpisodes(seriesId, seasonNumber)
|
var query = episodes.Select(
|
||||||
.FirstOrDefault(e =>
|
episode => new
|
||||||
{
|
{
|
||||||
// normalize episode title
|
Position = normalizedReleaseTitle.IndexOf(Parser.Parser.NormalizeEpisodeTitle(episode.Title), StringComparison.CurrentCultureIgnoreCase),
|
||||||
var title = Parser.Parser.NormalizeEpisodeTitle(e.Title);
|
Length = Parser.Parser.NormalizeEpisodeTitle(episode.Title).Length,
|
||||||
// find episode title within search string
|
Episode = episode
|
||||||
return (title.Length > 0) && search.Contains(title);
|
})
|
||||||
});
|
.Where(e => e.Episode.Title.Length > 0 && e.Position >= 0)
|
||||||
|
.OrderBy(e => e.Position)
|
||||||
|
.ThenByDescending(e => e.Length)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return query.First().Episode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Episode> EpisodesWithFiles(int seriesId)
|
public List<Episode> EpisodesWithFiles(int seriesId)
|
||||||
|
|
Loading…
Reference in a new issue