mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-14 11:23:42 +02:00
Merge branch 'season-ignore'
Conflicts: NzbDrone.Core.Test/NzbDrone.Core.Test.csproj NzbDrone.Core/NzbDrone.Core.csproj
This commit is contained in:
commit
6116fdb032
@ -26,7 +26,7 @@ public void SeriesSearch_success()
|
||||
Mocker.GetMock<EpisodeProvider>()
|
||||
.Setup(c => c.GetSeasons(1)).Returns(seasons);
|
||||
|
||||
Mocker.GetMock<EpisodeProvider>()
|
||||
Mocker.GetMock<SeasonProvider>()
|
||||
.Setup(c => c.IsIgnored(It.IsAny<int>(), It.IsAny<int>())).Returns(false);
|
||||
|
||||
Mocker.GetMock<SeasonSearchJob>()
|
||||
|
@ -117,6 +117,7 @@
|
||||
<Compile Include="ProviderTests\AnalyticsProviderTests\AnalyticsProviderFixture.cs" />
|
||||
<Compile Include="ProviderTests\ConfigProviderTests\ConfigCachingFixture.cs" />
|
||||
<Compile Include="ProviderTests\PlexProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\SeasonProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\DecisionEngineTests\RetentionSpecificationFixture.cs" />
|
||||
<Compile Include="ProviderTests\DecisionEngineTests\QualityAllowedByProfileSpecificationFixtrue.cs" />
|
||||
<Compile Include="ProviderTests\DecisionEngineTests\UpgradeHistorySpecificationFixtrue.cs" />
|
||||
|
@ -439,7 +439,6 @@ public void RefreshEpisodeInfo_should_add_old_episodes_with_no_title()
|
||||
result.Should().HaveSameCount(fakeEpisodes.Episodes);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void RefreshEpisodeInfo_ignore_season_zero()
|
||||
{
|
||||
@ -466,6 +465,10 @@ public void RefreshEpisodeInfo_ignore_season_zero()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
Mocker.GetMock<SeasonProvider>()
|
||||
.Setup(s => s.IsIgnored(seriesId, 0))
|
||||
.Returns(true);
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
|
||||
|
||||
@ -694,6 +697,10 @@ public void RefreshEpisodeInfo_should_ignore_new_episode_for_ignored_season()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Returns(tvdbSeries);
|
||||
|
||||
Mocker.GetMock<SeasonProvider>()
|
||||
.Setup(s => s.IsIgnored(seriesId, It.IsAny<int>()))
|
||||
.Returns(true);
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
|
||||
|
||||
@ -704,180 +711,6 @@ public void RefreshEpisodeInfo_should_ignore_new_episode_for_ignored_season()
|
||||
result.Where(e => e.Ignored).Should().HaveCount(episodeCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_true_if_all_episodes_ignored()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(c => c.Ignored = true)
|
||||
.With(c => c.SeriesId = 10)
|
||||
.With(c => c.SeasonNumber = 2)
|
||||
.Build();
|
||||
|
||||
episodes.ToList().ForEach(c => Db.Insert(c));
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 2);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_false_if_none_of_episodes_are_ignored()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(c => c.Ignored = false)
|
||||
.With(c => c.SeriesId = 10)
|
||||
.With(c => c.SeasonNumber = 2)
|
||||
.Build();
|
||||
|
||||
episodes.ToList().ForEach(c => Db.Insert(c));
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 2);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_false_if_some_of_episodes_are_ignored()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(c => c.SeriesId = 10)
|
||||
.With(c => c.SeasonNumber = 2)
|
||||
.With(c => c.Ignored = true)
|
||||
.Build();
|
||||
|
||||
episodes[2].Ignored = false;
|
||||
|
||||
|
||||
episodes.ToList().ForEach(c => Db.Insert(c));
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 2);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_false_if_zero_episodes_in_db_for_season()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(c => c.SeriesId = 10)
|
||||
.With(c => c.SeasonNumber = 3)
|
||||
.With(c => c.Ignored = true)
|
||||
.Build();
|
||||
|
||||
episodes.ToList().ForEach(c => Db.Insert(c));
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 2);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_true_if_zero_episodes_in_db_for_season_and_previous_is_ignored()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(c => c.SeriesId = 10)
|
||||
.With(c => c.SeasonNumber = 3)
|
||||
.With(c => c.Ignored = true)
|
||||
.Build();
|
||||
|
||||
episodes.ToList().ForEach(c => Db.Insert(c));
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 4);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_false_if_zero_episodes_in_db_for_season_and_previous_is_not_ignored()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(c => c.SeriesId = 10)
|
||||
.With(c => c.SeasonNumber = 3)
|
||||
.With(c => c.Ignored = false)
|
||||
.Build();
|
||||
|
||||
episodes.ToList().ForEach(c => Db.Insert(c));
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 4);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_false_if_zero_episodes_in_db_for_season_one()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_true_if_zero_episodes_in_db_for_season_zero()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 0);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsSeasonIgnored_should_return_false_if_season_zero_is_not_ignored()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(c => c.SeriesId = 10)
|
||||
.With(c => c.SeasonNumber = 0)
|
||||
.With(c => c.Ignored = false)
|
||||
.Build();
|
||||
|
||||
episodes.ToList().ForEach(c => Db.Insert(c));
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<EpisodeProvider>().IsIgnored(10, 0);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Explicit]
|
||||
public void Add_daily_show_episodes()
|
||||
@ -1049,6 +882,10 @@ public void AddEpisode_episode_is_ignored_when_full_season_is_ignored()
|
||||
.With(e => e.Ignored = false)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<SeasonProvider>()
|
||||
.Setup(s => s.IsIgnored(newEpisode.SeriesId, newEpisode.SeasonNumber))
|
||||
.Returns(true);
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<EpisodeProvider>().AddEpisode(newEpisode);
|
||||
|
||||
@ -1263,6 +1100,42 @@ public void IgnoreSeason_Ignore_Half()
|
||||
Mocker.VerifyAllMocks();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IgnoreSeason_should_call_SetIgnore_in_season_provider_one_time_only()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(4)
|
||||
.All()
|
||||
.With(c => c.SeriesId = 10)
|
||||
.With(c => c.SeasonNumber = 1)
|
||||
.With(c => c.Ignored = false)
|
||||
.Build().ToList();
|
||||
|
||||
var season = new Season
|
||||
{
|
||||
SeriesId = 10,
|
||||
SeasonNumber = 1,
|
||||
Ignored = false
|
||||
};
|
||||
|
||||
Db.Insert(season);
|
||||
Db.InsertMany(episodes);
|
||||
|
||||
Mocker.GetMock<SeasonProvider>().Setup(s => s.SetIgnore(10, 1, true)).Verifiable();
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<EpisodeProvider>().SetSeasonIgnore(10, 1, true);
|
||||
|
||||
//Assert
|
||||
var episodesInDb = Db.Fetch<Episode>(@"SELECT * FROM Episodes");
|
||||
|
||||
episodesInDb.Should().HaveCount(4);
|
||||
episodesInDb.Where(e => e.Ignored).Should().HaveCount(4);
|
||||
|
||||
Mocker.GetMock<SeasonProvider>().Verify(s => s.SetIgnore(10, 1, true), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EpisodesWithoutFiles_no_specials()
|
||||
{
|
||||
|
281
NzbDrone.Core.Test/ProviderTests/SeasonProviderTest.cs
Normal file
281
NzbDrone.Core.Test/ProviderTests/SeasonProviderTest.cs
Normal file
@ -0,0 +1,281 @@
|
||||
// ReSharper disable RedundantUsingDirective
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
using PetaPoco;
|
||||
using TvdbLib.Data;
|
||||
|
||||
namespace NzbDrone.Core.Test.ProviderTests
|
||||
{
|
||||
[TestFixture]
|
||||
// ReSharper disable InconsistentNaming
|
||||
public class SeasonProviderTest : CoreTest
|
||||
{
|
||||
[Test]
|
||||
public void AddSeason_should_insert_season_to_database_with_ignored_false()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var seriesId = 10;
|
||||
var seasonNumber = 50;
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<SeasonProvider>().Add(seriesId, seasonNumber);
|
||||
|
||||
//Assert
|
||||
var result = Db.Fetch<Season>();
|
||||
result.Should().HaveCount(1);
|
||||
result.First().SeriesId.Should().Be(seriesId);
|
||||
result.First().SeasonNumber.Should().Be(seasonNumber);
|
||||
result.First().Ignored.Should().BeFalse();
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void AddSeason_should_insert_season_to_database_with_preset_ignored_status(bool isIgnored)
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var seriesId = 10;
|
||||
var seasonNumber = 50;
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<SeasonProvider>().Add(seriesId, seasonNumber, isIgnored);
|
||||
|
||||
//Assert
|
||||
var result = Db.Fetch<Season>();
|
||||
result.Should().HaveCount(1);
|
||||
result.First().SeriesId.Should().Be(seriesId);
|
||||
result.First().SeasonNumber.Should().Be(seasonNumber);
|
||||
result.First().Ignored.Should().Be(isIgnored);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeleteSeason_should_remove_season_from_database()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var fakeSeason = Builder<Season>.CreateNew().Build();
|
||||
|
||||
Db.Insert(fakeSeason);
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<SeasonProvider>().Delete(fakeSeason.SeriesId, fakeSeason.SeasonNumber);
|
||||
|
||||
//Assert
|
||||
var result = Db.Fetch<Season>();
|
||||
result.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetIgnore_should_update_ignored_status()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
var fakeSeason = Builder<Season>.CreateNew()
|
||||
.With(s => s.Ignored = false)
|
||||
.Build();
|
||||
|
||||
var id = Db.Insert(fakeSeason);
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<SeasonProvider>().SetIgnore(fakeSeason.SeriesId, fakeSeason.SeasonNumber, true);
|
||||
|
||||
//Assert
|
||||
var result = Db.SingleOrDefault<Season>(id);
|
||||
result.Ignored.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIgnored_should_return_ignored_status_of_season()
|
||||
{
|
||||
WithRealDb();
|
||||
|
||||
//Setup
|
||||
var fakeSeason = Builder<Season>.CreateNew()
|
||||
.With(s => s.Ignored = false)
|
||||
.Build();
|
||||
|
||||
Db.Insert(fakeSeason);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(fakeSeason.SeriesId, fakeSeason.SeasonNumber);
|
||||
|
||||
//Assert
|
||||
result.Should().Be(fakeSeason.Ignored);
|
||||
Db.Fetch<Season>().Count.Should().Be(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIgnored_should_return_true_if_not_in_db_and_is_season_zero()
|
||||
{
|
||||
//Setup
|
||||
WithRealDb();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 0);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
Db.Fetch<Season>().Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIgnored_should_return_false_if_not_in_db_and_is_season_one()
|
||||
{
|
||||
//Setup
|
||||
WithRealDb();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 1);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
Db.Fetch<Season>().Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIgnored_should_return_false_if_not_in_db_and_previous_season_is_not_ignored()
|
||||
{
|
||||
//Setup
|
||||
WithRealDb();
|
||||
|
||||
var lastSeason = Builder<Season>.CreateNew()
|
||||
.With(s => s.SeriesId = 10)
|
||||
.With(s => s.SeasonNumber = 4)
|
||||
.With(s => s.Ignored = false)
|
||||
.Build();
|
||||
|
||||
Db.Insert(lastSeason);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 5);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
Db.Fetch<Season>().Should().HaveCount(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIgnored_should_return_true_if_not_in_db_and_previous_season_is_ignored()
|
||||
{
|
||||
//Setup
|
||||
WithRealDb();
|
||||
|
||||
var lastSeason = Builder<Season>.CreateNew()
|
||||
.With(s => s.SeriesId = 10)
|
||||
.With(s => s.SeasonNumber = 4)
|
||||
.With(s => s.Ignored = true)
|
||||
.Build();
|
||||
|
||||
Db.Insert(lastSeason);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 5);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
Db.Fetch<Season>().Should().HaveCount(2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsIgnored_should_return_false_if_not_in_db_and_previous_season_does_not_exist()
|
||||
{
|
||||
//Setup
|
||||
WithRealDb();
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SeasonProvider>().IsIgnored(10, 5);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
Db.Fetch<Season>().Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void All_should_return_seasons_with_episodes()
|
||||
{
|
||||
const int seriesId = 10;
|
||||
|
||||
//Setup
|
||||
WithRealDb();
|
||||
|
||||
var season = Builder<Season>.CreateNew()
|
||||
.With(s => s.SeriesId = seriesId)
|
||||
.With(s => s.SeasonNumber = 4)
|
||||
.With(s => s.Ignored = true)
|
||||
.Build();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(10)
|
||||
.All()
|
||||
.With(e => e.SeriesId = seriesId)
|
||||
.With(e => e.SeasonNumber = season.SeasonNumber)
|
||||
.Build();
|
||||
|
||||
Db.Insert(season);
|
||||
Db.InsertMany(episodes);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SeasonProvider>().All(seriesId);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(1);
|
||||
result.First().Episodes.Should().HaveCount(episodes.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void All_should_return_all_seasons_with_episodes()
|
||||
{
|
||||
const int seriesId = 10;
|
||||
|
||||
//Setup
|
||||
WithRealDb();
|
||||
|
||||
var seasons = Builder<Season>.CreateListOfSize(5)
|
||||
.All()
|
||||
.With(s => s.SeriesId = seriesId)
|
||||
.Build();
|
||||
|
||||
var episodes = new List<Episode>();
|
||||
|
||||
for (int i = 0; i < seasons.Count; i++)
|
||||
{
|
||||
var newEps = Builder<Episode>.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(e => e.SeriesId = seriesId)
|
||||
.With(e => e.SeasonNumber = i + 1)
|
||||
.Build();
|
||||
|
||||
episodes.AddRange(newEps);
|
||||
}
|
||||
|
||||
Db.InsertMany(seasons);
|
||||
Db.InsertMany(episodes);
|
||||
|
||||
//Act
|
||||
var result = Mocker.Resolve<SeasonProvider>().All(seriesId);
|
||||
|
||||
//Assert
|
||||
result.Should().HaveCount(5);
|
||||
|
||||
foreach(var season in result)
|
||||
{
|
||||
season.Episodes.Count.Should().Be(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
NzbDrone.Core/Datastore/Migrations/Migration20120220.cs
Normal file
29
NzbDrone.Core/Datastore/Migrations/Migration20120220.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using Migrator.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migrations
|
||||
{
|
||||
|
||||
[Migration(20120220)]
|
||||
public class Migration20120220 : NzbDroneMigration
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Database.AddTable("Seasons", new[]
|
||||
{
|
||||
new Column("SeasonId", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity),
|
||||
new Column("SeriesId", DbType.Int32, ColumnProperty.NotNull),
|
||||
new Column("SeasonNumber", DbType.Int32, ColumnProperty.NotNull),
|
||||
new Column("Ignored", DbType.Boolean, ColumnProperty.NotNull)
|
||||
});
|
||||
|
||||
Database.ExecuteNonQuery(@"INSERT INTO Seasons (SeriesId, SeasonNumber, Ignored)
|
||||
SELECT SeriesId, SeasonNumber,
|
||||
CASE WHEN Count(*) =
|
||||
SUM(CASE WHEN Ignored = 1 THEN 1 ELSE 0 END) THEN 1 ELSE 0 END AS Ignored
|
||||
FROM Episodes
|
||||
GROUP BY SeriesId, SeasonNumber");
|
||||
}
|
||||
}
|
||||
}
|
46
NzbDrone.Core/Datastore/PetaPoco/EpisodeSeasonRelator.cs
Normal file
46
NzbDrone.Core/Datastore/PetaPoco/EpisodeSeasonRelator.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NzbDrone.Core.Repository;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.PetaPoco
|
||||
{
|
||||
public class EpisodeSeasonRelator
|
||||
{
|
||||
public Season _current;
|
||||
public Season MapIt(Season season, Episode episode)
|
||||
{
|
||||
// Terminating call. Since we can return null from this function
|
||||
// we need to be ready for PetaPoco to callback later with null
|
||||
// parameters
|
||||
if (season == null)
|
||||
return _current;
|
||||
|
||||
// Is this the same season as the current one we're processing
|
||||
if (_current != null && _current.SeasonId == season.SeasonId)
|
||||
{
|
||||
// Yes, just add this post to the current author's collection of posts
|
||||
_current.Episodes.Add(episode);
|
||||
|
||||
// Return null to indicate we're not done with this author yet
|
||||
return null;
|
||||
}
|
||||
|
||||
// This is season different author to the current one, or this is the
|
||||
// first time through and we don't have an season yet
|
||||
|
||||
// Save the current author
|
||||
var prev = _current;
|
||||
|
||||
// Setup the new current season
|
||||
_current = season;
|
||||
_current.Episodes = new List<Episode>();
|
||||
_current.Episodes.Add(episode);
|
||||
|
||||
// Return the now populated previous season (or null if first time through)
|
||||
return prev;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -8,15 +8,16 @@ namespace NzbDrone.Core.Jobs
|
||||
{
|
||||
public class SeriesSearchJob : IJob
|
||||
{
|
||||
private readonly EpisodeProvider _episodeProvider;
|
||||
private readonly SeasonSearchJob _seasonSearchJob;
|
||||
private readonly SeasonProvider _seasonProvider;
|
||||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public SeriesSearchJob(EpisodeProvider episodeProvider, SeasonSearchJob seasonSearchJob)
|
||||
public SeriesSearchJob(SeasonSearchJob seasonSearchJob,
|
||||
SeasonProvider seasonProvider)
|
||||
{
|
||||
_episodeProvider = episodeProvider;
|
||||
_seasonSearchJob = seasonSearchJob;
|
||||
_seasonProvider = seasonProvider;
|
||||
}
|
||||
|
||||
public string Name
|
||||
@ -35,12 +36,12 @@ public void Start(ProgressNotification notification, int targetId, int secondary
|
||||
throw new ArgumentOutOfRangeException("targetId");
|
||||
|
||||
Logger.Debug("Getting seasons from database for series: {0}", targetId);
|
||||
var seasons = _episodeProvider.GetSeasons(targetId).Where(s => s > 0);
|
||||
var seasons = _seasonProvider.GetSeasons(targetId).Where(s => s > 0);
|
||||
|
||||
foreach (var season in seasons)
|
||||
{
|
||||
//Skip ignored seasons
|
||||
if (_episodeProvider.IsIgnored(targetId, season))
|
||||
if (_seasonProvider.IsIgnored(targetId, season))
|
||||
continue;
|
||||
|
||||
_seasonSearchJob.Start(notification, targetId, season);
|
||||
|
@ -222,6 +222,7 @@
|
||||
<Compile Include="Datastore\MigrationLogger.cs" />
|
||||
<Compile Include="Datastore\MigrationsHelper.cs" />
|
||||
<Compile Include="Datastore\CustomeMapper.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20120220.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20120123.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20120118.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20111125.cs" />
|
||||
@ -233,6 +234,7 @@
|
||||
<Compile Include="Datastore\DbProviderFactory.cs" />
|
||||
<Compile Include="Datastore\Migrations\NzbDroneMigration.cs" />
|
||||
<Compile Include="Datastore\Migrations\SchemaInfo.cs" />
|
||||
<Compile Include="Datastore\PetaPoco\EpisodeSeasonRelator.cs" />
|
||||
<Compile Include="Fluent.cs" />
|
||||
<Compile Include="Helpers\EpisodeSortingHelper.cs" />
|
||||
<Compile Include="Helpers\FileSizeFormatHelper.cs" />
|
||||
@ -267,6 +269,7 @@
|
||||
<Compile Include="Model\Xbmc\TvShowResult.cs" />
|
||||
<Compile Include="Model\Xbmc\ErrorResult.cs" />
|
||||
<Compile Include="Model\Xbmc\IconType.cs" />
|
||||
<Compile Include="Providers\SeasonProvider.cs" />
|
||||
<Compile Include="Jobs\RecentBacklogSearchJob.cs" />
|
||||
<Compile Include="Jobs\TrimLogsJob.cs" />
|
||||
<Compile Include="Jobs\JobProvider.cs" />
|
||||
@ -294,6 +297,7 @@
|
||||
<Compile Include="Providers\AnalyticsProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Repository\Season.cs" />
|
||||
<Compile Include="Providers\AutoConfigureProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
@ -20,13 +20,16 @@ public class EpisodeProvider
|
||||
private static readonly Regex multiPartCleanupRegex = new Regex(@"\(\d+\)$", RegexOptions.Compiled);
|
||||
|
||||
private readonly TvDbProvider _tvDbProvider;
|
||||
private readonly SeasonProvider _seasonProvider;
|
||||
private readonly IDatabase _database;
|
||||
private readonly SeriesProvider _seriesProvider;
|
||||
|
||||
[Inject]
|
||||
public EpisodeProvider(IDatabase database, SeriesProvider seriesProvider, TvDbProvider tvDbProviderProvider)
|
||||
public EpisodeProvider(IDatabase database, SeriesProvider seriesProvider,
|
||||
TvDbProvider tvDbProviderProvider, SeasonProvider seasonProvider)
|
||||
{
|
||||
_tvDbProvider = tvDbProviderProvider;
|
||||
_seasonProvider = seasonProvider;
|
||||
_database = database;
|
||||
_seriesProvider = seriesProvider;
|
||||
}
|
||||
@ -38,8 +41,7 @@ public EpisodeProvider()
|
||||
public virtual void AddEpisode(Episode episode)
|
||||
{
|
||||
//If Season is ignored ignore this episode
|
||||
if (IsIgnored(episode.SeriesId, episode.SeasonNumber))
|
||||
episode.Ignored = true;
|
||||
episode.Ignored = _seasonProvider.IsIgnored(episode.SeriesId, episode.SeasonNumber);
|
||||
|
||||
_database.Insert(episode);
|
||||
}
|
||||
@ -278,7 +280,7 @@ public virtual void RefreshEpisodeInfo(Series series)
|
||||
var updateList = new List<Episode>();
|
||||
var newList = new List<Episode>();
|
||||
|
||||
foreach (var episode in tvDbSeriesInfo.Episodes)
|
||||
foreach (var episode in tvDbSeriesInfo.Episodes.OrderBy(e => e.SeasonNumber).ThenBy(e => e.EpisodeNumber))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -312,7 +314,7 @@ public virtual void RefreshEpisodeInfo(Series series)
|
||||
//Else we need to check if this episode should be ignored based on IsIgnored rules
|
||||
else
|
||||
{
|
||||
episodeToUpdate.Ignored = IsIgnored(series.SeriesId, episode.SeasonNumber);
|
||||
episodeToUpdate.Ignored = _seasonProvider.IsIgnored(series.SeriesId, episode.SeasonNumber);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -396,10 +398,14 @@ public virtual IList<int> GetEpisodeNumbersBySeason(int seriesId, int seasonNumb
|
||||
return _database.Fetch<int>("SELECT EpisodeNumber FROM Episodes WHERE SeriesId=@0 AND SeasonNumber=@1", seriesId, seasonNumber).OrderBy(c => c).ToList();
|
||||
}
|
||||
|
||||
public virtual void SetSeasonIgnore(long seriesId, int seasonNumber, bool isIgnored)
|
||||
public virtual void SetSeasonIgnore(int seriesId, int seasonNumber, bool isIgnored)
|
||||
{
|
||||
logger.Info("Setting ignore flag on Series:{0} Season:{1} to {2}", seriesId, seasonNumber, isIgnored);
|
||||
|
||||
//Set the SeasonIgnore
|
||||
_seasonProvider.SetIgnore(seriesId, seasonNumber, isIgnored);
|
||||
|
||||
//Ignore all the episodes in the season
|
||||
_database.Execute(@"UPDATE Episodes SET Ignored = @0
|
||||
WHERE SeriesId = @1 AND SeasonNumber = @2 AND Ignored = @3",
|
||||
isIgnored, seriesId, seasonNumber, !isIgnored);
|
||||
|
BIN
NzbDrone.Core/Providers/SeasonProvider.cs
Normal file
BIN
NzbDrone.Core/Providers/SeasonProvider.cs
Normal file
Binary file not shown.
20
NzbDrone.Core/Repository/Season.cs
Normal file
20
NzbDrone.Core/Repository/Season.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Model;
|
||||
using PetaPoco;
|
||||
|
||||
namespace NzbDrone.Core.Repository
|
||||
{
|
||||
[TableName("Seasons")]
|
||||
[PrimaryKey("SeasonId", autoIncrement = true)]
|
||||
public class Season
|
||||
{
|
||||
public int SeasonId { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
public Boolean Ignored { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public List<Episode> Episodes { get; set; }
|
||||
}
|
||||
}
|
@ -24,16 +24,19 @@ public class SeriesController : Controller
|
||||
private readonly QualityProvider _qualityProvider;
|
||||
private readonly SeriesProvider _seriesProvider;
|
||||
private readonly JobProvider _jobProvider;
|
||||
private readonly SeasonProvider _seasonProvider;
|
||||
//
|
||||
// GET: /Series/
|
||||
|
||||
public SeriesController(SeriesProvider seriesProvider, EpisodeProvider episodeProvider,
|
||||
QualityProvider qualityProvider, JobProvider jobProvider)
|
||||
QualityProvider qualityProvider, JobProvider jobProvider,
|
||||
SeasonProvider seasonProvider)
|
||||
{
|
||||
_seriesProvider = seriesProvider;
|
||||
_episodeProvider = episodeProvider;
|
||||
_qualityProvider = qualityProvider;
|
||||
_jobProvider = jobProvider;
|
||||
_seasonProvider = seasonProvider;
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
@ -117,25 +120,14 @@ public ActionResult Details(int seriesId)
|
||||
model.SeriesId = series.SeriesId;
|
||||
model.HasBanner = !String.IsNullOrEmpty(series.BannerUrl);
|
||||
|
||||
var seasons = new List<SeasonModel>();
|
||||
var episodes = _episodeProvider.GetEpisodeBySeries(seriesId);
|
||||
|
||||
foreach (var season in episodes.Select(s => s.SeasonNumber).Distinct())
|
||||
{
|
||||
var episodesInSeason = episodes.Where(e => e.SeasonNumber == season).ToList();
|
||||
var commonStatusList = episodesInSeason.Select(s => s.Status).Distinct().ToList();
|
||||
var commonStatus = commonStatusList.Count > 1 ? "Missing" : commonStatusList.First().ToString();
|
||||
|
||||
seasons.Add(new SeasonModel
|
||||
{
|
||||
SeriesId = seriesId,
|
||||
SeasonNumber = season,
|
||||
Episodes = GetEpisodeModels(episodesInSeason).OrderByDescending(e=> e.EpisodeNumber).ToList(),
|
||||
AnyWanted = episodesInSeason.Any(e => !e.Ignored),
|
||||
CommonStatus = commonStatus
|
||||
});
|
||||
}
|
||||
|
||||
var seasons = _seasonProvider.All(seriesId).Select(s => new SeasonModel
|
||||
{
|
||||
SeriesId = seriesId,
|
||||
SeasonNumber = s.SeasonNumber,
|
||||
Ignored = s.Ignored,
|
||||
Episodes = GetEpisodeModels(s.Episodes).OrderByDescending(e => e.EpisodeNumber).ToList(),
|
||||
CommonStatus = GetCommonStatus(s.Episodes)
|
||||
}).ToList();
|
||||
model.Seasons = seasons;
|
||||
|
||||
return View(model);
|
||||
@ -254,5 +246,12 @@ private List<EpisodeModel> GetEpisodeModels(IList<Episode> episodesInDb)
|
||||
|
||||
return episodes;
|
||||
}
|
||||
|
||||
private string GetCommonStatus(IList<Episode> episodes)
|
||||
{
|
||||
var commonStatusList = episodes.Select(s => s.Status).Distinct().ToList();
|
||||
var commonStatus = commonStatusList.Count > 1 ? "Missing" : commonStatusList.First().ToString();
|
||||
return commonStatus;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,5 +9,6 @@ public class SeasonModel
|
||||
public List<EpisodeModel> Episodes { get; set; }
|
||||
public bool AnyWanted { get; set; }
|
||||
public string CommonStatus { get; set; }
|
||||
public bool Ignored { get; set; }
|
||||
}
|
||||
}
|
@ -40,9 +40,7 @@ $(".ignoreEpisode").live("click", function () {
|
||||
|
||||
else {
|
||||
//Check to see if this is the last one ignored or the first not ignored
|
||||
seasonNumber = toggle.attr('class').split(/\s+/)[1].replace('ignoreEpisode_', '');
|
||||
var episodeId = toggle.attr('id');
|
||||
toggleMaster(seasonNumber, ignored);
|
||||
saveEpisodeIgnore(episodeId, ignored);
|
||||
}
|
||||
});
|
||||
@ -68,26 +66,6 @@ function toggleChildren(seasonNumber, ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
function toggleMaster(seasonNumber) {
|
||||
//Toggles all master toggles when the childen changes
|
||||
|
||||
var ignoreEpisodes = $('.ignoreEpisode_' + seasonNumber);
|
||||
var ignoredCount = ignoreEpisodes.filter('.ignored').length;
|
||||
var masters = $('.ignoreSeason_' + seasonNumber);
|
||||
|
||||
masters.each(function (index) {
|
||||
if (ignoreEpisodes.length == ignoredCount) {
|
||||
$(this).attr('src', ignoredImage);
|
||||
$(this).addClass('ignored');
|
||||
}
|
||||
|
||||
else {
|
||||
$(this).attr('src', notIgnoredImage);
|
||||
$(this).removeClass('ignored');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function toggleMasters(seasonNumber, ignored) {
|
||||
//Toggles the other master(s) to match the one that was just changed
|
||||
var masters = $('.ignoreSeason_' + seasonNumber);
|
||||
|
@ -79,8 +79,8 @@
|
||||
{
|
||||
var ignoreSeason = "ignoreSeason_" + season.SeasonNumber;
|
||||
<div class="seasonToggleTop">
|
||||
<img src='../../Content/Images/@(season.AnyWanted ? "notIgnored" : "ignored").png'
|
||||
class='ignoredEpisodesMaster ignoreEpisode @ignoreSeason@(season.AnyWanted ? " " : " ignored") gridImage'
|
||||
<img src='../../Content/Images/@(season.Ignored ? "ignored" : "notIgnored").png'
|
||||
class='ignoredEpisodesMaster ignoreEpisode @ignoreSeason@(season.Ignored ? " ignored" : " ") gridImage'
|
||||
title='Click to toggle season ignore status' />
|
||||
<a href="@string.Format("#SeasonSection_{0}", season.SeasonNumber)" class="seasonToggleLabel">@(season.SeasonNumber == 0 ? "Specials" : "Season " + season.SeasonNumber)</a>
|
||||
</div>
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
@*Commands Column*@
|
||||
<th>
|
||||
<img src='../../Content/Images/@(Model.AnyWanted ? "notIgnored" : "ignored").png' class='ignoredEpisodesMaster ignoreEpisode ignoreSeason_@(Model.SeasonNumber) @(Model.AnyWanted ? "" : "ignored") gridImage' title='Click to toggle season ignore status' />
|
||||
<img src='../../Content/Images/@(Model.Ignored ? "ignored" : "notIgnored").png' class='ignoredEpisodesMaster ignoreEpisode ignoreSeason_@(Model.SeasonNumber)@(Model.Ignored ? " ignored" : " ") gridImage' title='Click to toggle season ignore status' />
|
||||
<img src='../../Content/Images/@(Model.CommonStatus).png' alt='Status' title='Season Status' class='gridImage' />
|
||||
@Ajax.ImageActionLink("../../Content/Images/Search.png", new { Alt = "Search", Title = "Search for all episodes in this season", @class = "gridImage" }, "SearchSeason", "Episode", new { SeriesId = Model.SeriesId, SeasonNumber = Model.SeasonNumber }, null, null)
|
||||
@Ajax.ImageActionLink("../../Content/Images/Rename.png", new { Alt = "Rename", Title = "Rename all episodes in this season", @class = "gridImage" }, "RenameSeason", "Episode", new { SeriesId = Model.SeriesId, SeasonNumber = Model.SeasonNumber }, null, null)
|
||||
|
Loading…
Reference in New Issue
Block a user