parent
84b9488cfb
commit
00821b7ad6
|
@ -44,6 +44,23 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
result.FullSeason.Should().BeFalse();
|
result.FullSeason.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase("Series.Title.2015.09.07.Part1.720p.HULU.WEBRip.AAC2.0.H.264-Sonarr", "Series Title", 2015, 9, 7, 1)]
|
||||||
|
[TestCase("Series.Title.2015.09.07.Part2.720p.HULU.WEBRip.AAC2.0.H.264-Sonarr", "Series Title", 2015, 9, 7, 2)]
|
||||||
|
[TestCase("Series.Title.2015.09.07.Part.1.720p.HULU.WEBRip.AAC2.0.H.264-Sonarr", "Series Title", 2015, 9, 7, 1)]
|
||||||
|
[TestCase("Series.Title.2015.09.07.Part.2.720p.HULU.WEBRip.AAC2.0.H.264-Sonarr", "Series Title", 2015, 9, 7, 2)]
|
||||||
|
public void should_parse_daily_episode_with_multiple_parts(string postTitle, string title, int year, int month, int day, int part)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
var airDate = new DateTime(year, month, day);
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.SeriesTitle.Should().Be(title);
|
||||||
|
result.AirDate.Should().Be(airDate.ToString(Episode.AIR_DATE_FORMAT));
|
||||||
|
result.EpisodeNumbers.Should().BeEmpty();
|
||||||
|
result.AbsoluteEpisodeNumbers.Should().BeEmpty();
|
||||||
|
result.FullSeason.Should().BeFalse();
|
||||||
|
result.DailyPart.Should().Be(part);
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase("Conan {year} {month} {day} Emma Roberts HDTV XviD BFF")]
|
[TestCase("Conan {year} {month} {day} Emma Roberts HDTV XviD BFF")]
|
||||||
[TestCase("The Tonight Show With Jay Leno {year} {month} {day} 1080i HDTV DD5 1 MPEG2 TrollHD")]
|
[TestCase("The Tonight Show With Jay Leno {year} {month} {day} 1080i HDTV DD5 1 MPEG2 TrollHD")]
|
||||||
[TestCase("The.Daily.Show.{year}.{month}.{day}.Johnny.Knoxville.iTouch-MW")]
|
[TestCase("The.Daily.Show.{year}.{month}.{day}.Johnny.Knoxville.iTouch-MW")]
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>()), Times.Once());
|
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), null), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -98,7 +98,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>()), Times.Never());
|
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), null), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -110,7 +110,20 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>()), Times.Once());
|
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), null), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_get_daily_episode_episode_should_lookup_including_daily_part()
|
||||||
|
{
|
||||||
|
GivenDailySeries();
|
||||||
|
GivenDailyParseResult();
|
||||||
|
_parsedEpisodeInfo.DailyPart = 1;
|
||||||
|
|
||||||
|
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId);
|
||||||
|
|
||||||
|
Mocker.GetMock<IEpisodeService>()
|
||||||
|
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), 1), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -125,7 +138,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
|
||||||
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
Subject.Map(_parsedEpisodeInfo, _series.TvdbId, _series.TvRageId, _singleEpisodeSearchCriteria);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>()
|
Mocker.GetMock<IEpisodeService>()
|
||||||
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>()), Times.Never());
|
.Verify(v => v.FindEpisode(It.IsAny<int>(), It.IsAny<string>(), null), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
using System;
|
|
||||||
using FizzWare.NBuilder;
|
|
||||||
using FluentAssertions;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
using NzbDrone.Core.Tv;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class ByAirDateFixture : DbTest<EpisodeRepository, Episode>
|
|
||||||
{
|
|
||||||
private const int SERIES_ID = 1;
|
|
||||||
private const string AIR_DATE = "2014-04-02";
|
|
||||||
|
|
||||||
private void GivenEpisode(int seasonNumber)
|
|
||||||
{
|
|
||||||
var episode = Builder<Episode>.CreateNew()
|
|
||||||
.With(e => e.SeriesId = 1)
|
|
||||||
.With(e => e.SeasonNumber = seasonNumber)
|
|
||||||
.With(e => e.AirDate = AIR_DATE)
|
|
||||||
.BuildNew();
|
|
||||||
|
|
||||||
Db.Insert(episode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_throw_when_multiple_regular_episodes_are_found()
|
|
||||||
{
|
|
||||||
GivenEpisode(1);
|
|
||||||
GivenEpisode(2);
|
|
||||||
|
|
||||||
Assert.Throws<InvalidOperationException>(() => Subject.Get(SERIES_ID, AIR_DATE));
|
|
||||||
Assert.Throws<InvalidOperationException>(() => Subject.Find(SERIES_ID, AIR_DATE));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_throw_when_get_finds_no_episode()
|
|
||||||
{
|
|
||||||
Assert.Throws<InvalidOperationException>(() => Subject.Get(SERIES_ID, AIR_DATE));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_get_episode_when_single_episode_exists_for_air_date()
|
|
||||||
{
|
|
||||||
GivenEpisode(1);
|
|
||||||
|
|
||||||
Subject.Get(SERIES_ID, AIR_DATE).Should().NotBeNull();
|
|
||||||
Subject.Find(SERIES_ID, AIR_DATE).Should().NotBeNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_get_episode_when_regular_episode_and_special_share_the_same_air_date()
|
|
||||||
{
|
|
||||||
GivenEpisode(1);
|
|
||||||
GivenEpisode(0);
|
|
||||||
|
|
||||||
Subject.Get(SERIES_ID, AIR_DATE).Should().NotBeNull();
|
|
||||||
Subject.Find(SERIES_ID, AIR_DATE).Should().NotBeNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_get_special_when_its_the_only_episode_for_the_date_provided()
|
|
||||||
{
|
|
||||||
GivenEpisode(0);
|
|
||||||
|
|
||||||
Subject.Get(SERIES_ID, AIR_DATE).Should().NotBeNull();
|
|
||||||
Subject.Find(SERIES_ID, AIR_DATE).Should().NotBeNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.TvTests.EpisodeServiceTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ByAirDateFixture : CoreTest<EpisodeService>
|
||||||
|
{
|
||||||
|
private const int SERIES_ID = 1;
|
||||||
|
private const string AIR_DATE = "2014-04-02";
|
||||||
|
|
||||||
|
private Episode CreateEpisode(int seasonNumber, int episodeNumber)
|
||||||
|
{
|
||||||
|
var episode = Builder<Episode>.CreateNew()
|
||||||
|
.With(e => e.SeriesId = 1)
|
||||||
|
.With(e => e.SeasonNumber = seasonNumber)
|
||||||
|
.With(e => e.EpisodeNumber = episodeNumber)
|
||||||
|
.With(e => e.AirDate = AIR_DATE)
|
||||||
|
.BuildNew();
|
||||||
|
|
||||||
|
return episode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenEpisodes(params Episode[] episodes)
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IEpisodeRepository>()
|
||||||
|
.Setup(s => s.Find(It.IsAny<int>(), It.IsAny<string>()))
|
||||||
|
.Returns(episodes.ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_throw_when_multiple_regular_episodes_are_found_and_not_part_provided()
|
||||||
|
{
|
||||||
|
GivenEpisodes(CreateEpisode(1, 1), CreateEpisode(2, 1));
|
||||||
|
|
||||||
|
Assert.Throws<InvalidOperationException>(() => Subject.FindEpisode(SERIES_ID, AIR_DATE, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_null_when_finds_no_episode()
|
||||||
|
{
|
||||||
|
GivenEpisodes();
|
||||||
|
|
||||||
|
Subject.FindEpisode(SERIES_ID, AIR_DATE, null).Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_get_episode_when_single_episode_exists_for_air_date()
|
||||||
|
{
|
||||||
|
GivenEpisodes(CreateEpisode(1, 1));
|
||||||
|
|
||||||
|
Subject.FindEpisode(SERIES_ID, AIR_DATE, null).Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_get_episode_when_regular_episode_and_special_share_the_same_air_date()
|
||||||
|
{
|
||||||
|
GivenEpisodes(CreateEpisode(1, 1), CreateEpisode(0, 1));
|
||||||
|
|
||||||
|
Subject.FindEpisode(SERIES_ID, AIR_DATE, null).Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_get_special_when_its_the_only_episode_for_the_date_provided()
|
||||||
|
{
|
||||||
|
GivenEpisodes(CreateEpisode(0, 1));
|
||||||
|
|
||||||
|
Subject.FindEpisode(SERIES_ID, AIR_DATE, null).Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_get_episode_when_two_regular_episodes_share_the_same_air_date_and_part_is_provided()
|
||||||
|
{
|
||||||
|
var episode1 = CreateEpisode(1, 1);
|
||||||
|
var episode2 = CreateEpisode(1, 2);
|
||||||
|
|
||||||
|
GivenEpisodes(episode1, episode2);
|
||||||
|
|
||||||
|
Subject.FindEpisode(SERIES_ID, AIR_DATE, 1).Should().Be(episode1);
|
||||||
|
Subject.FindEpisode(SERIES_ID, AIR_DATE, 2).Should().Be(episode2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public string ReleaseHash { get; set; }
|
public string ReleaseHash { get; set; }
|
||||||
public int SeasonPart { get; set; }
|
public int SeasonPart { get; set; }
|
||||||
public string ReleaseTokens { get; set; }
|
public string ReleaseTokens { get; set; }
|
||||||
|
public int? DailyPart { get; set; }
|
||||||
|
|
||||||
public ParsedEpisodeInfo()
|
public ParsedEpisodeInfo()
|
||||||
{
|
{
|
||||||
|
|
|
@ -148,6 +148,10 @@ namespace NzbDrone.Core.Parser
|
||||||
new Regex(@"^(?<title>.+?)(?:[-._ ][e])(?<episode>\d{2,3}(?!\d+))(?:(?:\-?[e])(?<episode>\d{2,3}(?!\d+)))+",
|
new Regex(@"^(?<title>.+?)(?:[-._ ][e])(?<episode>\d{2,3}(?!\d+))(?:(?:\-?[e])(?<episode>\d{2,3}(?!\d+)))+",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
|
//Episodes with airdate and part (2018.04.28.Part.2)
|
||||||
|
new Regex(@"^(?<title>.+?)?\W*(?<airyear>\d{4})[-_. ]+(?<airmonth>[0-1][0-9])[-_. ]+(?<airday>[0-3][0-9])(?![-_. ]+[0-3][0-9])[-_. ]+Part[-_. ]?(?<part>[1-9])",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
|
||||||
//Mini-Series, treated as season 1, episodes are labelled as Part01, Part 01, Part.1
|
//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+)))+)",
|
new Regex(@"^(?<title>.+?)(?:\W+(?:(?:Part\W?|(?<!\d+\W+)e)(?<episode>\d{1,2}(?!\d+)))+)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||||
|
@ -808,7 +812,7 @@ namespace NzbDrone.Core.Parser
|
||||||
//Try to Parse as a daily show
|
//Try to Parse as a daily show
|
||||||
var airmonth = Convert.ToInt32(matchCollection[0].Groups["airmonth"].Value);
|
var airmonth = Convert.ToInt32(matchCollection[0].Groups["airmonth"].Value);
|
||||||
var airday = Convert.ToInt32(matchCollection[0].Groups["airday"].Value);
|
var airday = Convert.ToInt32(matchCollection[0].Groups["airday"].Value);
|
||||||
|
|
||||||
//Swap day and month if month is bigger than 12 (scene fail)
|
//Swap day and month if month is bigger than 12 (scene fail)
|
||||||
if (airmonth > 12)
|
if (airmonth > 12)
|
||||||
{
|
{
|
||||||
|
@ -843,12 +847,23 @@ namespace NzbDrone.Core.Parser
|
||||||
ReleaseTitle = releaseTitle,
|
ReleaseTitle = releaseTitle,
|
||||||
AirDate = airDate.ToString(Episode.AIR_DATE_FORMAT),
|
AirDate = airDate.ToString(Episode.AIR_DATE_FORMAT),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var partMatch = matchCollection[0].Groups["part"];
|
||||||
|
|
||||||
|
if (partMatch.Success)
|
||||||
|
{
|
||||||
|
result.DailyPart = Convert.ToInt32(partMatch.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastSeasonEpisodeStringIndex != releaseTitle.Length)
|
if (lastSeasonEpisodeStringIndex != releaseTitle.Length)
|
||||||
|
{
|
||||||
result.ReleaseTokens = releaseTitle.Substring(lastSeasonEpisodeStringIndex);
|
result.ReleaseTokens = releaseTitle.Substring(lastSeasonEpisodeStringIndex);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
result.ReleaseTokens = releaseTitle;
|
result.ReleaseTokens = releaseTitle;
|
||||||
|
}
|
||||||
|
|
||||||
result.SeriesTitle = seriesName;
|
result.SeriesTitle = seriesName;
|
||||||
result.SeriesTitleInfo = GetSeriesTitleInfo(result.SeriesTitle);
|
result.SeriesTitleInfo = GetSeriesTitleInfo(result.SeriesTitle);
|
||||||
|
|
|
@ -113,7 +113,7 @@ namespace NzbDrone.Core.Parser
|
||||||
|
|
||||||
if (parsedEpisodeInfo.IsDaily)
|
if (parsedEpisodeInfo.IsDaily)
|
||||||
{
|
{
|
||||||
var episodeInfo = GetDailyEpisode(series, parsedEpisodeInfo.AirDate, searchCriteria);
|
var episodeInfo = GetDailyEpisode(series, parsedEpisodeInfo.AirDate, parsedEpisodeInfo.DailyPart, searchCriteria);
|
||||||
|
|
||||||
if (episodeInfo != null)
|
if (episodeInfo != null)
|
||||||
{
|
{
|
||||||
|
@ -314,7 +314,7 @@ namespace NzbDrone.Core.Parser
|
||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Episode GetDailyEpisode(Series series, string airDate, SearchCriteriaBase searchCriteria)
|
private Episode GetDailyEpisode(Series series, string airDate, int? part, SearchCriteriaBase searchCriteria)
|
||||||
{
|
{
|
||||||
Episode episodeInfo = null;
|
Episode episodeInfo = null;
|
||||||
|
|
||||||
|
@ -326,7 +326,7 @@ namespace NzbDrone.Core.Parser
|
||||||
|
|
||||||
if (episodeInfo == null)
|
if (episodeInfo == null)
|
||||||
{
|
{
|
||||||
episodeInfo = _episodeService.FindEpisode(series.Id, airDate);
|
episodeInfo = _episodeService.FindEpisode(series.Id, airDate, part);
|
||||||
}
|
}
|
||||||
|
|
||||||
return episodeInfo;
|
return episodeInfo;
|
||||||
|
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Marr.Data.QGen;
|
using Marr.Data.QGen;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Datastore.Extensions;
|
using NzbDrone.Core.Datastore.Extensions;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
@ -17,8 +16,7 @@ namespace NzbDrone.Core.Tv
|
||||||
{
|
{
|
||||||
Episode Find(int seriesId, int season, int episodeNumber);
|
Episode Find(int seriesId, int season, int episodeNumber);
|
||||||
Episode Find(int seriesId, int absoluteEpisodeNumber);
|
Episode Find(int seriesId, int absoluteEpisodeNumber);
|
||||||
Episode Get(int seriesId, string date);
|
List<Episode> Find(int seriesId, string date);
|
||||||
Episode Find(int seriesId, string date);
|
|
||||||
List<Episode> GetEpisodes(int seriesId);
|
List<Episode> GetEpisodes(int seriesId);
|
||||||
List<Episode> GetEpisodes(int seriesId, int seasonNumber);
|
List<Episode> GetEpisodes(int seriesId, int seasonNumber);
|
||||||
List<Episode> GetEpisodeByFileId(int fileId);
|
List<Episode> GetEpisodeByFileId(int fileId);
|
||||||
|
@ -61,21 +59,11 @@ namespace NzbDrone.Core.Tv
|
||||||
.SingleOrDefault();
|
.SingleOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Episode Get(int seriesId, string date)
|
public List<Episode> Find(int seriesId, string date)
|
||||||
{
|
{
|
||||||
var episode = FindOneByAirDate(seriesId, date);
|
return Query.Where(s => s.SeriesId == seriesId)
|
||||||
|
.AndWhere(s => s.AirDate == date)
|
||||||
if (episode == null)
|
.ToList();
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Expected at one episode");
|
|
||||||
}
|
|
||||||
|
|
||||||
return episode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Episode Find(int seriesId, string date)
|
|
||||||
{
|
|
||||||
return FindOneByAirDate(seriesId, date);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Episode> GetEpisodes(int seriesId)
|
public List<Episode> GetEpisodes(int seriesId)
|
||||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
@ -21,8 +20,7 @@ namespace NzbDrone.Core.Tv
|
||||||
Episode FindEpisodeByTitle(int seriesId, int seasonNumber, string releaseTitle);
|
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);
|
||||||
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
|
List<Episode> FindEpisodesBySceneNumbering(int seriesId, int sceneAbsoluteEpisodeNumber);
|
||||||
Episode GetEpisode(int seriesId, string date);
|
Episode FindEpisode(int seriesId, string date, int? part);
|
||||||
Episode FindEpisode(int seriesId, string date);
|
|
||||||
List<Episode> GetEpisodeBySeries(int seriesId);
|
List<Episode> GetEpisodeBySeries(int seriesId);
|
||||||
List<Episode> GetEpisodesBySeason(int seriesId, int seasonNumber);
|
List<Episode> GetEpisodesBySeason(int seriesId, int seasonNumber);
|
||||||
List<Episode> EpisodesWithFiles(int seriesId);
|
List<Episode> EpisodesWithFiles(int seriesId);
|
||||||
|
@ -85,14 +83,9 @@ namespace NzbDrone.Core.Tv
|
||||||
return _episodeRepository.FindEpisodesBySceneNumbering(seriesId, sceneAbsoluteEpisodeNumber);
|
return _episodeRepository.FindEpisodesBySceneNumbering(seriesId, sceneAbsoluteEpisodeNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Episode GetEpisode(int seriesId, string date)
|
public Episode FindEpisode(int seriesId, string date, int? part)
|
||||||
{
|
{
|
||||||
return _episodeRepository.Get(seriesId, date);
|
return FindOneByAirDate(seriesId, date, part);
|
||||||
}
|
|
||||||
|
|
||||||
public Episode FindEpisode(int seriesId, string date)
|
|
||||||
{
|
|
||||||
return _episodeRepository.Find(seriesId, date);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Episode> GetEpisodeBySeries(int seriesId)
|
public List<Episode> GetEpisodeBySeries(int seriesId)
|
||||||
|
@ -240,5 +233,34 @@ namespace NzbDrone.Core.Tv
|
||||||
_logger.Debug("Linking [{0}] > [{1}]", message.EpisodeFile.RelativePath, episode);
|
_logger.Debug("Linking [{0}] > [{1}]", message.EpisodeFile.RelativePath, episode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Episode FindOneByAirDate(int seriesId, string date, int? part)
|
||||||
|
{
|
||||||
|
var episodes = _episodeRepository.Find(seriesId, date);
|
||||||
|
|
||||||
|
if (!episodes.Any()) return null;
|
||||||
|
|
||||||
|
if (episodes.Count == 1) return episodes.First();
|
||||||
|
|
||||||
|
_logger.Debug("Multiple episodes with the same air date were found, will exclude specials");
|
||||||
|
|
||||||
|
var regularEpisodes = episodes.Where(e => e.SeasonNumber > 0).ToList();
|
||||||
|
|
||||||
|
if (regularEpisodes.Count == 1 && !part.HasValue)
|
||||||
|
{
|
||||||
|
_logger.Debug("Left with one episode after excluding specials");
|
||||||
|
return regularEpisodes.First();
|
||||||
|
}
|
||||||
|
else if (part.HasValue && part.Value <= regularEpisodes.Count)
|
||||||
|
{
|
||||||
|
var sortedEpisodes = regularEpisodes.OrderBy(e => e.SeasonNumber)
|
||||||
|
.ThenBy(e => e.EpisodeNumber)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return sortedEpisodes[part.Value - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Multiple episodes with the same air date found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue