1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-10-30 15:32:31 +01:00

Merge branch 'master' of git://github.com/kayone/NzbDrone

Conflicts:
	NzbDrone.Core/Providers/MediaFileProvider.cs
This commit is contained in:
Mark McDowall 2011-06-04 11:47:35 -07:00
commit 383dfe302f
37 changed files with 377 additions and 579 deletions

View File

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Supported values: nunit, xunit and mstest -->
<add key="FluentAssertions.TestFramework" value="nunit"/>
</appSettings>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite" />

View File

@ -9,13 +9,14 @@ using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
// ReSharper disable InconsistentNaming
namespace NzbDrone.Core.Test
{
[TestFixture]
public class DownloadProviderTest
public class DownloadProviderTest : TestBase
{
[Test]
public void Download_report_should_send_to_sab_and_add_to_history()

View File

@ -60,40 +60,6 @@ namespace NzbDrone.Core.Test
}
[Test]
public void EnsureSeason_is_called_once_per_season()
{
const int seriesId = 71663;
var fakeEpisodes = Builder<TvdbSeries>.CreateNew()
.With(c => c.Episodes = new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(6).
WhereAll().Have(
l => l.Language = new TvdbLanguage(0, "eng", "a"))
.WhereTheFirst(3).Have(d => d.SeasonNumber = 1).And(
d => d.SeasonId = 11)
.AndTheRemaining().Have(d => d.SeasonNumber = 2).And(
d => d.SeasonId = 22)
.Build())
).With(c => c.Id = seriesId).Build();
var fakeSeries = Builder<Series>.CreateNew().With(c => c.SeriesId = seriesId).Build();
var mocker = new AutoMoqer();
mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
.Setup(c => c.GetSeries(seriesId, true))
.Returns(fakeEpisodes);
mocker.Resolve<EpisodeProvider>().RefreshEpisodeInfo(fakeSeries);
mocker.GetMock<SeasonProvider>().Verify(c => c.EnsureSeason(seriesId, 11, 1), Times.Once());
mocker.GetMock<SeasonProvider>().Verify(c => c.EnsureSeason(seriesId, 22, 2), Times.Once());
mocker.VerifyAllMocks();
}
[Test]
public void new_episodes_only_calls_AddMany()
{

View File

@ -21,8 +21,6 @@ namespace NzbDrone.Core.Test
public void no_grab_date(int offsetDays, bool hasEpisodes, bool ignored, EpisodeStatusType status)
{
Episode episode = Builder<Episode>.CreateNew()
.With(e => e.Season = Builder<Season>.CreateNew()
.With(s => s.Monitored = true).Build())
.With(e => e.AirDate = DateTime.Now.AddDays(offsetDays))
.With(e => e.Ignored = ignored)
.With(e => e.EpisodeFileId = 0)
@ -39,7 +37,7 @@ namespace NzbDrone.Core.Test
[Test]
[TestCase(1, false, false, EpisodeStatusType.NotAired)]
[TestCase(1, false, false, EpisodeStatusType.Missing)]
[TestCase(-2, false, false, EpisodeStatusType.Missing)]
[TestCase(1, true, false, EpisodeStatusType.Ready)]
[TestCase(1, false, true, EpisodeStatusType.Ignored)]
@ -47,10 +45,7 @@ namespace NzbDrone.Core.Test
EpisodeStatusType status)
{
Episode episode = Builder<Episode>.CreateNew()
.With(e => e.Season = Builder<Season>.CreateNew()
.With(s => s.Monitored = true).Build()).With(
e => e.AirDate = DateTime.Now.AddDays(offsetDays))
.With(e => e.Ignored = ignored)
.With(e => e.Ignored = ignored)
.With(e => e.EpisodeFileId = 0)
.With(e => e.GrabDate = DateTime.Now.AddDays(-1).AddHours(-1))
.Build();
@ -74,9 +69,7 @@ namespace NzbDrone.Core.Test
EpisodeStatusType status)
{
Episode episode = Builder<Episode>.CreateNew()
.With(e => e.Season = Builder<Season>.CreateNew()
.With(s => s.Monitored = true).Build())
.With(e => e.AirDate = DateTime.Now.AddDays(offsetDays))
.With(e => e.AirDate = DateTime.Now.AddDays(offsetDays))
.With(e => e.Ignored = ignored)
.With(e => e.EpisodeFileId = 0)
.With(e => e.GrabDate = DateTime.Now.AddDays(-1))
@ -91,19 +84,16 @@ namespace NzbDrone.Core.Test
}
[Test]
[TestCase(1, false, false, EpisodeStatusType.Ignored)]
[TestCase(-2, false, false, EpisodeStatusType.Ignored)]
[TestCase(1, false, true, EpisodeStatusType.Ignored)]
public void skipped_season(int offsetDays, bool hasEpisodes, bool ignored, EpisodeStatusType status)
[TestCase(1, true, false, EpisodeStatusType.Ignored)]
[TestCase(-2, true, false, EpisodeStatusType.Ignored)]
[TestCase(1, true, true, EpisodeStatusType.Ready)]
public void ignored_episode(int offsetDays, bool ignored, bool hasEpisodes, EpisodeStatusType status)
{
Episode episode = Builder<Episode>.CreateNew()
.With(e => e.AirDate = DateTime.Now.AddDays(offsetDays))
.With(e => e.Ignored = ignored)
.With(e => e.EpisodeFileId = 0)
.With(e => e.GrabDate = null)
.With(e => e.Season = Builder<Season>.CreateNew()
.With(s => s.Monitored == false).Build())
.Build();
if (hasEpisodes)
@ -123,8 +113,6 @@ namespace NzbDrone.Core.Test
.With(e => e.Ignored = false)
.With(e => e.EpisodeFileId = 0)
.With(e => e.GrabDate = null)
.With(e => e.Season = Builder<Season>.CreateNew()
.With(s => s.Monitored = true).Build())
.Build();

View File

@ -3,6 +3,7 @@ using AutoMoq;
using Moq;
using System;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test
{
@ -103,7 +104,7 @@ namespace NzbDrone.Core.Test
//Arrange
var mocker = new AutoMoqer();
var constant = new VirtualDependency {PropValue = Guid.NewGuid().ToString()};
var constant = new VirtualDependency { PropValue = Guid.NewGuid().ToString() };
mocker.SetConstant(constant);

View File

@ -44,12 +44,15 @@ namespace NzbDrone.Core.Test.Framework
Console.WriteLine("Creating an empty SQLite database");
var provider = ProviderFactory.GetProvider("Data Source=" + Guid.NewGuid() + ".db;Version=3;New=True",
"System.Data.SQLite");
var repo = new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations);
ForceMigration(repo);
if (enableLogging)
{
provider.Log = new NlogWriter();
}
var repo = new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations);
ForceMigration(repo);
return repo;
}
@ -99,7 +102,6 @@ namespace NzbDrone.Core.Test.Framework
private static void ForceMigration(IRepository repository)
{
repository.All<Series>().Count();
repository.All<Season>().Count();
repository.All<Episode>().Count();
repository.All<EpisodeFile>().Count();
repository.All<QualityProfile>().Count();

View File

@ -23,7 +23,6 @@ namespace NzbDrone.Core.Test
public void AllItems()
{
//Setup
Season season = new Season { SeasonId = 4321, SeasonNumber = 1, SeriesId = 5656, Monitored = true };
var episode = new Episode
{
AirDate = DateTime.Today.AddDays(-1),
@ -31,8 +30,6 @@ namespace NzbDrone.Core.Test
EpisodeNumber = 5,
Overview = "This is an Overview",
SeasonNumber = 1,
SeasonId = 4321,
Season = season,
SeriesId = 5656
};

View File

@ -116,28 +116,7 @@ namespace NzbDrone.Core.Test
mocker.VerifyAllMocks();
}
[Test]
public void ignored_season_should_be_skipped()
{
var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<SeriesProvider>()
.Setup(p => p.FindSeries(It.IsAny<String>()))
.Returns(series);
mocker.GetMock<SeasonProvider>()
.Setup(p => p.IsIgnored(series.SeriesId, parseResultMulti.SeasonNumber))
.Returns(true);
//Act
var result = mocker.Resolve<InventoryProvider>().IsMonitored(parseResultMulti);
//Assert
Assert.IsFalse(result);
Assert.AreSame(series, parseResultMulti.Series);
mocker.VerifyAllMocks();
}
[Test]
public void IsMonitored_dailyshow_should_do_daily_lookup()
{
@ -155,12 +134,6 @@ namespace NzbDrone.Core.Test
.Setup(p => p.GetEpisode(episode.SeriesId, episode.AirDate))
.Returns(episode);
mocker.GetMock<SeasonProvider>()
.Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber))
.Returns(false);
var result = mocker.Resolve<InventoryProvider>().IsMonitored(parseResultSingle);
//Assert
@ -178,10 +151,6 @@ namespace NzbDrone.Core.Test
.Setup(p => p.FindSeries(It.IsAny<String>()))
.Returns(series);
mocker.GetMock<SeasonProvider>()
.Setup(p => p.IsIgnored(series.SeriesId, parseResultSingle.SeasonNumber))
.Returns(false);
mocker.GetMock<EpisodeProvider>()
.Setup(p => p.GetEpisode(episode.SeriesId, episode.SeasonNumber, episode.EpisodeNumber))
.Returns<Episode>(null);
@ -191,8 +160,7 @@ namespace NzbDrone.Core.Test
.Returns<Episode>(null);
mocker.GetMock<EpisodeProvider>()
.Setup(p => p.AddEpisode(It.IsAny<Episode>()))
.Returns(12);
.Setup(p => p.AddEpisode(It.IsAny<Episode>()));
//Act
var result = mocker.Resolve<InventoryProvider>().IsMonitored(parseResultSingle);

View File

@ -38,7 +38,10 @@ namespace NzbDrone.Core.Test
//Fakes
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build();
var fakeEpisode = Builder<Episode>.CreateNew()
.With(c => c.SeriesId = fakeSeries.SeriesId)
.With(c => c.SeasonNumber = seasonNumber)
.Build();
//Mocks
var mocker = new AutoMoqer();
@ -66,6 +69,8 @@ namespace NzbDrone.Core.Test
mocker.GetMock<IRepository>().Verify(r => r.Add(result), Times.Once());
mocker.VerifyAllMocks();
result.SeasonNumber.Should().Be(fakeEpisode.SeasonNumber);
Assert.AreEqual(fakeEpisode.SeriesId, result.SeriesId);
Assert.AreEqual(QualityTypes.DVD, result.Quality);
Assert.AreEqual(Parser.NormalizePath(fileName), result.Path);
@ -148,10 +153,6 @@ namespace NzbDrone.Core.Test
mocker.GetMock<IRepository>(MockBehavior.Strict)
.Setup(r => r.Exists(It.IsAny<Expression<Func<EpisodeFile, Boolean>>>())).Returns(true).Verifiable();
//mocker.GetMock<EpisodeProvider>()
// .Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode)
// .Verifiable();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(size).Verifiable();
@ -161,7 +162,7 @@ namespace NzbDrone.Core.Test
//Assert
mocker.VerifyAllMocks();
Assert.IsNull(result);
result.Should().BeNull();
}
@ -341,30 +342,24 @@ namespace NzbDrone.Core.Test
}
[Test]
public void get_season_files()
public void get_series_files()
{
var episodes = Builder<Episode>.CreateListOfSize(20)
.WhereTheFirst(8)
.Has(c => c.EpisodeFile = new EpisodeFile())
.AndTheRemaining()
.Has(c => c.EpisodeFile = null)
.Build().ToList();
var firstSeriesFiles = Builder<EpisodeFile>.CreateListOfSize(10)
.WhereAll().Have(s => s.SeriesId = 12).Build();
var secondSeriesFiles = Builder<EpisodeFile>.CreateListOfSize(10)
.WhereAll().Have(s => s.SeriesId = 20).Build();
var mocker = new AutoMoqer();
mocker.GetMock<SeasonProvider>()
.Setup(c => c.GetSeason(12))
.Returns(Builder<Season>.CreateNew().With(c => c.Episodes = episodes).Build())
.Verifiable();
var result = mocker.Resolve<MediaFileProvider>().GetSeasonFiles(12);
result.Should().HaveCount(8);
result.Should().NotContainNulls();
mocker.VerifyAllMocks();
var repo = MockLib.GetEmptyRepository(true);
repo.AddMany(firstSeriesFiles);
repo.AddMany(secondSeriesFiles);
mocker.SetConstant(repo);
var result = mocker.Resolve<MediaFileProvider>().GetSeriesFiles(12);
result.Should().HaveSameCount(firstSeriesFiles);
}
}
}

View File

@ -5,12 +5,13 @@ using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class QualityTest
public class QualityTest : TestBase
{
[Test]
[Ignore("No supported asserts are available")]

View File

@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test
var fakeEpisode = Builder<Episode>.CreateNew().With(c => c.SeriesId = 69).Build();
//Act
var repo = MockLib.GetEmptyRepository();
var repo = MockLib.GetEmptyRepository(true);
repo.Add(fakeSeries);
repo.Add(fakeEpisode);
var fetchedSeries = repo.Single<Series>(fakeSeries.SeriesId);
@ -42,32 +42,40 @@ namespace NzbDrone.Core.Test
}
[Test]
public void ToString_test_over_castle_proxy()
[Ignore]
public void query_scratch_pad()
{
//Arrange
var fakeSeries = Builder<Series>.CreateNew().With(s => s.SeriesId = 69).Build();
var fakeEpisode = Builder<Episode>.CreateNew().With(c => c.SeriesId = 69).Build();
var repo = MockLib.GetEmptyRepository(true);
repo.All<Episode>().Where(e => !e.Ignored && e.AirDate <= DateTime.Today && e.AirDate.Year > 1900).Select(
s => s.Title).ToList();
}
[Test]
[Ignore]
public void episode_proxy_to_string()
{
var episode = Builder<Episode>.CreateNew()
.Build();
var series = Builder<Series>.CreateNew()
.With(s => s.SeriesId = episode.SeriesId)
.Build();
var repo = MockLib.GetEmptyRepository(true);
repo.Add(episode);
repo.Add(series);
//Act
var repo = MockLib.GetEmptyRepository(true);
repo.Add(fakeSeries);
repo.Add(fakeEpisode);
Console.WriteLine("Getting single");
var fetchedEpisode = repo.Single<Episode>(fakeEpisode.EpisodeId);
var result = repo.Single<Episode>(episode.EpisodeId).ToString();
//Assert
Console.WriteLine("Doing assert");
Assert.AreEqual(fakeEpisode.EpisodeId, fetchedEpisode.EpisodeId);
Console.WriteLine("Doing assert");
Assert.AreEqual(fakeEpisode.Title, fetchedEpisode.Title);
Console.WriteLine("=======================");
var ttt = fetchedEpisode.Series;
Console.WriteLine("=======================");
var tttd = fetchedEpisode.Series;
Console.WriteLine("=======================");
//Assert.Contains(fetchedEpisode.ToString(), fakeSeries.Title);
Console.WriteLine(result);
result.Should().Contain(series.Title);
result.Should().Contain(episode.EpisodeNumber.ToString());
result.Should().Contain(episode.SeasonNumber.ToString());
}
@ -78,7 +86,7 @@ namespace NzbDrone.Core.Test
public void tvdbid_is_preserved()
{
//Arrange
var sonicRepo = MockLib.GetEmptyRepository();
var sonicRepo = MockLib.GetEmptyRepository(true);
var series = Builder<Series>.CreateNew().With(c => c.SeriesId = 18).Build();
//Act
@ -95,7 +103,6 @@ namespace NzbDrone.Core.Test
public void enteties_toString()
{
Console.WriteLine(new Episode().ToString());
Console.WriteLine(new Season().ToString());
Console.WriteLine(new Series().ToString());
Console.WriteLine(new EpisodeFile().ToString());
}
@ -106,7 +113,7 @@ namespace NzbDrone.Core.Test
//setup
var message = Guid.NewGuid().ToString();
var sonicRepo = MockLib.GetEmptyRepository();
var sonicRepo = MockLib.GetEmptyRepository(true);
var sonicTarget = new SubsonicTarget(sonicRepo);
@ -139,7 +146,7 @@ namespace NzbDrone.Core.Test
//setup
var message = Guid.NewGuid().ToString();
var sonicRepo = MockLib.GetEmptyRepository();
var sonicRepo = MockLib.GetEmptyRepository(true);
var sonicTarget = new SubsonicTarget(sonicRepo);
LogManager.Configuration.AddTarget("DbLogger", sonicTarget);
@ -172,7 +179,7 @@ namespace NzbDrone.Core.Test
//setup
var message = String.Empty;
var sonicRepo = MockLib.GetEmptyRepository();
var sonicRepo = MockLib.GetEmptyRepository(true);
var sonicTarget = new SubsonicTarget(sonicRepo);
LogManager.Configuration.AddTarget("DbLogger", sonicTarget);

View File

@ -20,7 +20,7 @@ namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class RepositoryProviderTest
public class RepositoryProviderTest : TestBase
{
[Test]
public void Get_Assembly_repos()
@ -36,8 +36,6 @@ namespace NzbDrone.Core.Test
types.Should().Contain(typeof(IndexerSetting));
types.Should().Contain(typeof(JobSetting));
types.Should().Contain(typeof(RootDir));
types.Should().Contain(typeof(Season));
types.Should().Contain(typeof(Season));
types.Should().Contain(typeof(Series));
types.Should().Contain(typeof(QualityProfile));

View File

@ -1,117 +1,153 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
using SubSonic.Repository;
namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class DbBenchmark
public class DbBenchmark : TestBase
{
const int COUNT = 10000;
private List<Episode> episodes;
private List<EpisodeFile> files;
const int Episodes_Per_Season = 20;
private readonly List<int> seasonsNumbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
private readonly List<int> seriesIds = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
private readonly List<Episode> episodes = new List<Episode>();
private readonly List<EpisodeFile> files = new List<EpisodeFile>();
private readonly IRepository repo = MockLib.GetEmptyRepository();
[SetUp]
public void Setup()
[TestFixtureSetUp]
public new void Setup()
{
episodes = new List<Episode>(COUNT);
files = new List<EpisodeFile>(COUNT);
base.Setup();
for (int i = 10; i < COUNT + 10; i++)
foreach (var _seriesId in seriesIds)
{
var file = Builder<EpisodeFile>.CreateNew().With(c => c.EpisodeFileId = i).Build();
files.Add(file);
int seriesId = _seriesId;
var series = Builder<Series>.CreateNew()
.With(s => s.SeriesId = seriesId)
.With(s => s.Monitored = true)
.Build();
var episode = Builder<Episode>.CreateNew()
.With(c => c.EpisodeId = i)
.And(c => c.EpisodeFileId = i)
.And(c => c.Title = DateTime.Now.ToLongTimeString())
.And(
c =>
c.Overview =
@"This adds support for silverlight. Both the 3.5 CLR and a Silverlight 3
version are included in the zip file. Also includes some other very minor bug fixes.").Build();
repo.Add(series);
foreach (var _seasonNumber in seasonsNumbers)
{
for (int i = 1; i <= Episodes_Per_Season; i++)
{
var episode = Builder<Episode>.CreateNew()
.With(e => e.SeriesId = seriesId)
.And(e => e.SeasonNumber = _seasonNumber)
.And(e => e.EpisodeNumber = i)
.And(e => e.Ignored = false)
.And(e => e.TvDbEpisodeId = episodes.Count + 1)
.And(e => e.AirDate = DateTime.Today.AddDays(-20))
.Build();
episodes.Add(episode);
if (i < 10)
{
var epFile = Builder<EpisodeFile>.CreateNew()
.With(e => e.SeriesId = seriesId)
.And(e => e.SeasonNumber = _seasonNumber)
.And(e => e.Path = Guid.NewGuid().ToString())
.Build();
files.Add(epFile);
}
}
}
repo.AddMany(episodes);
repo.AddMany(files);
episodes.Add(episode);
}
}
[Test]
public void Insert_into_episodes()
public void get_episode_by_series_seasons_episode_x1000()
{
var repo = MockLib.GetEmptyRepository();
var epProvider = new EpisodeProvider(repo, null);
Thread.Sleep(1000);
var sw = Stopwatch.StartNew();
repo.AddMany(episodes);
sw.Stop();
Console.WriteLine("Adding " + COUNT + " items at once took " + sw.Elapsed);
}
[Test]
public void Insert_into_episodes_single()
{
var repo = MockLib.GetEmptyRepository();
Thread.Sleep(1000);
var sw = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
repo.Add(episodes[i]);
}
sw.Stop();
Console.WriteLine("Adding " + 100 + " single items took " + sw.Elapsed);
}
[Test]
public void get_episode_file()
{
var repo = MockLib.GetEmptyRepository();
repo.AddMany(episodes);
repo.AddMany(files);
//var repoEpisodes = repo.All<Episode>().ToList();
Thread.Sleep(1000);
var count = 0;
var random = new Random();
Console.WriteLine("Starting Test");
var sw = Stopwatch.StartNew();
for (int i = 5000; i < 5000 + 1000; i++)
for (int i = 0; i < 1000; i++)
{
count++;
var file = repo.Single<Episode>(random.Next(10, COUNT - 100)).EpisodeFile;
epProvider.GetEpisode(6, random.Next(2, 5), random.Next(2, Episodes_Per_Season - 10)).Should().NotBeNull();
}
sw.Stop();
Console.WriteLine("Getting " + count + " episode files took " + sw.Elapsed);
Console.WriteLine("Took " + sw.Elapsed);
}
[Test]
public void get_episode_by_series_seasons_x500()
{
var epProvider = new EpisodeProvider(repo, null);
Thread.Sleep(1000);
var random = new Random();
Console.WriteLine("Starting Test");
var sw = Stopwatch.StartNew();
for (int i = 0; i < 500; i++)
{
epProvider.GetEpisodesBySeason(6, random.Next(2, 5)).Should().NotBeNull();
}
sw.Stop();
Console.WriteLine("Took " + sw.Elapsed);
}
[Test]
public void get_episode_file_count_x50()
{
var mocker = new AutoMoq.AutoMoqer();
mocker.SetConstant(repo);
mocker.SetConstant(mocker.Resolve<EpisodeProvider>());
var mediaProvider = mocker.Resolve<MediaFileProvider>();
Thread.Sleep(1000);
var random = new Random();
Console.WriteLine("Starting Test");
var sw = Stopwatch.StartNew();
for (int i = 0; i < 50; i++)
{
mediaProvider.GetEpisodeFilesCount(random.Next(1, 5)).Should().NotBeNull();
}
sw.Stop();
Console.WriteLine("Took " + sw.Elapsed);
}
}
}

View File

@ -56,7 +56,7 @@ namespace NzbDrone.Core
LogConfiguration.Setup();
Migrations.Run();
Migrations.Run(Connection.MainConnectionString);
ForceMigration(_kernel.Get<IRepository>());
SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up
@ -78,7 +78,6 @@ namespace NzbDrone.Core
_kernel.Bind<TvDbProvider>().ToSelf().InTransientScope();
_kernel.Bind<HttpProvider>().ToSelf().InSingletonScope();
_kernel.Bind<SeriesProvider>().ToSelf().InSingletonScope();
_kernel.Bind<SeasonProvider>().ToSelf().InSingletonScope();
_kernel.Bind<EpisodeProvider>().ToSelf().InSingletonScope();
_kernel.Bind<UpcomingEpisodesProvider>().ToSelf().InSingletonScope();
_kernel.Bind<DiskProvider>().ToSelf().InSingletonScope();
@ -98,9 +97,9 @@ namespace NzbDrone.Core
_kernel.Bind<WebTimer>().ToSelf().InSingletonScope();
_kernel.Bind<AutoConfigureProvider>().ToSelf().InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.MainDataRepository).InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.LogDataRepository).WhenInjectedInto<SubsonicTarget>().InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.LogDataRepository).WhenInjectedInto<LogProvider>().InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.CreateSimpleRepository(Connection.MainConnectionString)).InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.CreateSimpleRepository(Connection.LogConnectionString)).WhenInjectedInto<SubsonicTarget>().InSingletonScope();
_kernel.Bind<IRepository>().ToConstant(Connection.CreateSimpleRepository(Connection.LogConnectionString)).WhenInjectedInto<LogProvider>().InSingletonScope();
}
}
@ -138,7 +137,6 @@ namespace NzbDrone.Core
private static void ForceMigration(IRepository repository)
{
repository.All<Series>().Count();
repository.All<Season>().Count();
repository.All<Episode>().Count();
repository.All<EpisodeFile>().Count();
repository.All<QualityProfile>().Count();

View File

@ -18,11 +18,16 @@ namespace NzbDrone.Core.Datastore
}
public static string GetConnectionString(string path)
{
return String.Format("Data Source={0};Version=3;", path);
}
public static String MainConnectionString
{
get
{
return String.Format("Data Source={0};Version=3;", Path.Combine(AppDataPath.FullName, "nzbdrone.db"));
return GetConnectionString(Path.Combine(AppDataPath.FullName, "nzbdrone.db"));
}
}
@ -30,70 +35,19 @@ namespace NzbDrone.Core.Datastore
{
get
{
return String.Format("Data Source={0};Version=3;", Path.Combine(AppDataPath.FullName, "log.db"));
return GetConnectionString(Path.Combine(AppDataPath.FullName, "log.db"));
}
}
private static IDataProvider _mainDataProvider;
public static IDataProvider MainDataProvider
public static IDataProvider GetDataProvider(string connectionString)
{
get
{
if (_mainDataProvider == null)
{
_mainDataProvider = ProviderFactory.GetProvider(Connection.MainConnectionString, "System.Data.SQLite");
}
return _mainDataProvider;
}
return ProviderFactory.GetProvider(connectionString, "System.Data.SQLite");
}
private static IDataProvider _logDataProvider;
public static IDataProvider LogDataProvider
public static IRepository CreateSimpleRepository(string connectionString)
{
get
{
if (_logDataProvider == null)
{
_logDataProvider = ProviderFactory.GetProvider(Connection.LogConnectionString, "System.Data.SQLite");
}
return _logDataProvider;
}
return new SimpleRepository(GetDataProvider(connectionString), SimpleRepositoryOptions.RunMigrations);
}
private static SimpleRepository _mainDataRepository;
public static SimpleRepository MainDataRepository
{
get
{
if (_mainDataRepository == null)
{
_mainDataRepository = new SimpleRepository(MainDataProvider, SimpleRepositoryOptions.RunMigrations);
}
return _mainDataRepository;
}
}
private static SimpleRepository _logDataRepository;
public static SimpleRepository LogDataRepository
{
get
{
if (_logDataRepository == null)
{
_logDataRepository = new SimpleRepository(LogDataProvider, SimpleRepositoryOptions.RunMigrations);
}
return _logDataRepository;
}
}
}
}

View File

@ -16,16 +16,16 @@ namespace NzbDrone.Core.Datastore
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static void Run()
public static void Run(string connetionString)
{
Logger.Info("Preparing to migrate databse");
Logger.Info("Preparing run database migration");
try
{
var mig = new Migrator.Migrator("Sqlite", Connection.MainConnectionString,
var migrator = new Migrator.Migrator("Sqlite", connetionString,
Assembly.GetAssembly(typeof(Migrations)), true, new MigrationLogger());
mig.MigrateToLastVersion();
migrator.MigrateToLastVersion();
Logger.Info("Database migration completed");
}
@ -98,6 +98,20 @@ namespace NzbDrone.Core.Datastore
var jobTable = repoProvider.GetSchemaFromType(typeof(JobSetting));
Database.RemoveTable(jobTable.Name);
}
public override void Down()
{
throw new NotImplementedException();
}
}
[Migration(20110603)]
public class Migration20110603 : Migration
{
public override void Up()
{
Database.RemoveTable("Seasons");
Migrations.RemoveDeletedColumns(Database);
Migrations.AddNewColumns(Database);

View File

@ -26,7 +26,7 @@ namespace NzbDrone.Core.Datastore
public virtual ITable GetSchemaFromType(Type type)
{
return type.ToSchemaTable(Connection.MainDataProvider);
return type.ToSchemaTable(Connection.GetDataProvider(Connection.MainConnectionString));
}
public virtual Column[] GetColumnsFromDatabase(ITransformationProvider database, string tableName)

View File

@ -26,7 +26,7 @@ namespace NzbDrone.Core.Instrumentation
private static void DbAction(string value)
{
Logger.Trace(value);
Logger.Trace(value.Replace("`t0`.", ""));
}
}
}

View File

@ -231,14 +231,12 @@
<Compile Include="Providers\EpisodeProvider.cs" />
<Compile Include="Providers\Core\HttpProvider.cs" />
<Compile Include="Providers\SabProvider.cs" />
<Compile Include="Providers\SeasonProvider.cs" />
<Compile Include="Repository\Episode.cs" />
<Compile Include="Instrumentation\Log.cs" />
<Compile Include="Repository\History.cs" />
<Compile Include="Repository\Config.cs" />
<Compile Include="Repository\Quality\QualityProfile.cs" />
<Compile Include="Repository\RootDir.cs" />
<Compile Include="Repository\Season.cs" />
<Compile Include="Repository\Quality\QualityTypes.cs" />
<Compile Include="Repository\Series.cs" />
<Compile Include="CentralDispatch.cs" />

View File

@ -10,16 +10,14 @@ namespace NzbDrone.Core.Providers
public class InventoryProvider
{
private readonly SeriesProvider _seriesProvider;
private readonly SeasonProvider _seasonProvider;
private readonly EpisodeProvider _episodeProvider;
private readonly HistoryProvider _historyProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public InventoryProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider, EpisodeProvider episodeProvider, HistoryProvider historyProvider)
public InventoryProvider(SeriesProvider seriesProvider, EpisodeProvider episodeProvider, HistoryProvider historyProvider)
{
_seriesProvider = seriesProvider;
_seasonProvider = seasonProvider;
_episodeProvider = episodeProvider;
_historyProvider = historyProvider;
}
@ -49,12 +47,6 @@ namespace NzbDrone.Core.Providers
return false;
}
if (_seasonProvider.IsIgnored(series.SeriesId, parseResult.SeasonNumber))
{
Logger.Debug("Season {0} is currently set to ignore. skipping.", parseResult.SeasonNumber);
return false;
}
foreach (var episodeNumber in parseResult.EpisodeNumbers)
{
var episodeInfo = _episodeProvider.GetEpisode(series.SeriesId, parseResult.SeasonNumber, episodeNumber);

View File

@ -16,7 +16,6 @@ namespace NzbDrone.Core.Providers.Jobs
{
private readonly SeriesProvider _seriesProvider;
private readonly MediaFileProvider _mediaFileProvider;
private readonly SeasonProvider _seasonProvider;
private readonly UpdateInfoJob _updateInfoJob;
private readonly DiskScanJob _diskScanJob;
@ -24,13 +23,12 @@ namespace NzbDrone.Core.Providers.Jobs
private List<int> _attemptedSeries;
public ImportNewSeriesJob(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
public ImportNewSeriesJob(SeriesProvider seriesProvider,
MediaFileProvider mediaFileProvider, UpdateInfoJob updateInfoJob, DiskScanJob diskScanJob)
{
_seriesProvider = seriesProvider;
_mediaFileProvider = mediaFileProvider;
_seasonProvider = seasonProvider;
_updateInfoJob = updateInfoJob;
_updateInfoJob = updateInfoJob;
_diskScanJob = diskScanJob;
}
@ -84,9 +82,22 @@ namespace NzbDrone.Core.Providers.Jobs
private void AutoIgnoreSeasons(Series updatedSeries)
{
if (_mediaFileProvider.GetSeriesFiles(updatedSeries.SeriesId).Count() != 0)
var episodeFiles = _mediaFileProvider.GetSeriesFiles(updatedSeries.SeriesId);
var episodes = updatedSeries.Episodes;
if (episodeFiles.Count() != 0)
{
Logger.Debug("Looking for seasons to ignore");
var seasons = episodes.Select(c => c.SeasonNumber).Distinct();
var currentSeasons = seasons.Max();
foreach (var season in seasons)
{
if (season!=currentSeasons )
{
}
}
/* Logger.Debug("Looking for seasons to ignore");
foreach (var season in updatedSeries.Seasons)
{
if (season.SeasonNumber != updatedSeries.Seasons.Max(s => s.SeasonNumber) && _mediaFileProvider.GetSeasonFiles(season.SeasonId).Count() == 0)
@ -95,7 +106,7 @@ namespace NzbDrone.Core.Providers.Jobs
season.Monitored = false;
_seasonProvider.SaveSeason(season);
}
}
}*/
}
}
}

View File

@ -16,17 +16,15 @@ namespace NzbDrone.Core.Providers
private readonly DiskProvider _diskProvider;
private readonly EpisodeProvider _episodeProvider;
private readonly SeriesProvider _seriesProvider;
private readonly SeasonProvider _seasonProvider;
private readonly IRepository _repository;
public MediaFileProvider(IRepository repository, DiskProvider diskProvider,
EpisodeProvider episodeProvider, SeriesProvider seriesProvider, SeasonProvider seasonProvider)
EpisodeProvider episodeProvider, SeriesProvider seriesProvider)
{
_repository = repository;
_diskProvider = diskProvider;
_episodeProvider = episodeProvider;
_seriesProvider = seriesProvider;
_seasonProvider = seasonProvider;
}
public MediaFileProvider() { }
@ -125,6 +123,7 @@ namespace NzbDrone.Core.Providers
episodeFile.Size = size;
episodeFile.Quality = parseResult.Quality.QualityType;
episodeFile.Proper = parseResult.Quality.Proper;
episodeFile.SeasonNumber = parseResult.SeasonNumber;
var fileId = (int)_repository.Add(episodeFile);
//This is for logging + updating the episodes that are linked to this EpisodeFile
@ -183,25 +182,19 @@ namespace NzbDrone.Core.Providers
return _repository.All<EpisodeFile>().ToList();
}
public virtual IEnumerable<EpisodeFile> GetSeasonFiles(int seasonId)
{
return _seasonProvider.GetSeason(seasonId).Episodes.Where(c => c.EpisodeFile != null).Select(c => c.EpisodeFile);
}
public virtual IEnumerable<EpisodeFile> GetSeriesFiles(int seriesId)
{
return _seriesProvider.GetSeries(seriesId).Episodes.Where(c => c.EpisodeFile != null).Select(c => c.EpisodeFile);
return _repository.All<EpisodeFile>().Where(c => c.SeriesId == seriesId);
}
public virtual Tuple<int, int> GetEpisodeFilesCount(int seriesId)
{
var series = _seriesProvider.GetSeries(seriesId);
var allEpisodes = _episodeProvider.GetEpisodeBySeries(seriesId);
var monitoredSeasons = series.Seasons.Where(e => e.Monitored).Select(e => e.SeasonId);
var episodeTotal = series.Episodes.Where(e => monitoredSeasons.Contains(e.SeasonId) && e.AirDate <= DateTime.Today && e.AirDate > new DateTime(1899, 12, 31));
var episodes = episodeTotal.Where(e => e.EpisodeFileId > 0);
var episodeTotal = allEpisodes.Where(e => !e.Ignored && e.AirDate <= DateTime.Today && e.AirDate.Year > 1900).ToList();
var avilableEpisodes = episodeTotal.Where(e => e.EpisodeFileId > 0);
return new Tuple<int, int>(episodes.Count(), episodeTotal.Count());
return new Tuple<int, int>(episodeTotal.Count, avilableEpisodes.Count());
}
private List<string> GetMediaFileList(string path)

View File

@ -19,19 +19,17 @@ namespace NzbDrone.Core.Providers
private readonly DiskProvider _diskProvider;
private readonly EpisodeProvider _episodeProvider;
private readonly MediaFileProvider _mediaFileProvider;
private readonly SeasonProvider _seasonProvider;
private readonly SeriesProvider _seriesProvider;
private readonly List<EpisodeRenameModel> _epsToRename = new List<EpisodeRenameModel>();
private Thread _renameThread;
public RenameProvider(SeriesProvider seriesProvider, SeasonProvider seasonProvider,
public RenameProvider(SeriesProvider seriesProvider,
EpisodeProvider episodeProvider, MediaFileProvider mediaFileProvider,
DiskProvider diskProvider, ConfigProvider configProvider)
{
_seriesProvider = seriesProvider;
_seasonProvider = seasonProvider;
_episodeProvider = episodeProvider;
_mediaFileProvider = mediaFileProvider;
_diskProvider = diskProvider;
@ -45,7 +43,7 @@ namespace NzbDrone.Core.Providers
foreach (var episodeFile in _mediaFileProvider.GetEpisodeFiles())
{
var series = _seriesProvider.GetSeries(episodeFile.SeriesId);
var erm = new EpisodeRenameModel {SeriesName = series.Title, Folder = series.Path};
var erm = new EpisodeRenameModel { SeriesName = series.Title, Folder = series.Path };
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar +
@ -68,7 +66,7 @@ namespace NzbDrone.Core.Providers
foreach (var episodeFile in _mediaFileProvider.GetEpisodeFiles().Where(s => s.SeriesId == seriesId))
{
var erm = new EpisodeRenameModel {SeriesName = series.Title, Folder = series.Path};
var erm = new EpisodeRenameModel { SeriesName = series.Title, Folder = series.Path };
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar +
@ -85,26 +83,7 @@ namespace NzbDrone.Core.Providers
public virtual void RenameSeason(int seasonId)
{
//Get a list of all applicable episode files/episodes and rename them
var season = _seasonProvider.GetSeason(seasonId);
var series = _seriesProvider.GetSeries(season.SeriesId);
foreach (
var episodeFile in _mediaFileProvider.GetEpisodeFiles().Where(s => s.Episodes[0].SeasonId == seasonId))
{
var erm = new EpisodeRenameModel {SeriesName = series.Title, Folder = series.Path};
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar +
EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber,
_configProvider.GetValue(
"Sorting_SeasonFolderFormat", "Season %s",
true));
erm.EpisodeFile = episodeFile;
_epsToRename.Add(erm);
StartRename();
}
throw new NotImplementedException();
}
public virtual void RenameEpisode(int episodeId)
@ -116,7 +95,7 @@ namespace NzbDrone.Core.Providers
var episodeFile =
_mediaFileProvider.GetEpisodeFiles().Where(s => s.Episodes.Contains(episode)).FirstOrDefault();
var erm = new EpisodeRenameModel {SeriesName = series.Title, Folder = series.Path};
var erm = new EpisodeRenameModel { SeriesName = series.Title, Folder = series.Path };
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar +
@ -135,7 +114,7 @@ namespace NzbDrone.Core.Providers
var episodeFile = _mediaFileProvider.GetEpisodeFile(episodeFileId);
var series = _seriesProvider.GetSeries(episodeFile.Series.SeriesId);
var erm = new EpisodeRenameModel {SeriesName = series.Title, Folder = series.Path};
var erm = new EpisodeRenameModel { SeriesName = series.Title, Folder = series.Path };
if (series.SeasonFolder)
erm.Folder += Path.DirectorySeparatorChar +

View File

@ -1,92 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Repository;
using SubSonic.Repository;
namespace NzbDrone.Core.Providers
{
public class SeasonProvider
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly IRepository _repository;
public SeasonProvider(IRepository repository)
{
_repository = repository;
}
public SeasonProvider()
{
}
public virtual Season GetSeason(int seasonId)
{
return _repository.Single<Season>(seasonId);
}
public virtual Season GetSeason(int seriesId, int seasonNumber)
{
return _repository.Single<Season>(s => s.SeriesId == seriesId && s.SeasonNumber == seasonNumber);
}
public virtual List<Season> GetSeasons(int seriesId)
{
return _repository.All<Season>().Where(s => s.SeriesId == seriesId).ToList();
}
public virtual Season GetLatestSeason(int seriesId)
{
return _repository.All<Season>().Where(s => s.SeriesId == seriesId).OrderBy(s => s.SeasonNumber).Last();
}
public virtual void EnsureSeason(int seriesId, int seasonId, int seasonNumber)
{
if (_repository.Exists<Season>(s => s.SeasonId == seasonId))
return;
//TODO: Calculate Season Folder
Logger.Trace("Adding Season To DB. [SeriesID:{0} SeasonID:{1} SeasonNumber:{2}]", seriesId, seasonId,
seasonNumber, "????");
var newSeason = new Season
{
Monitored = true,
SeasonId = seasonId,
SeasonNumber = seasonNumber,
SeriesId = seriesId
};
_repository.Add(newSeason);
}
public virtual int SaveSeason(Season season)
{
if (_repository.Exists<Season>(s => s.SeasonId == season.SeasonId))
{
return _repository.Update(season);
}
return (int)_repository.Add(season);
}
public virtual bool IsIgnored(int seasonId)
{
if (_repository.Single<Season>(seasonId).Monitored)
return false;
Logger.Debug("Season {0} is not wanted.");
return true;
}
public virtual bool IsIgnored(int seriesId, int seasonNumber)
{
var season = _repository.Single<Season>(s => s.SeriesId == seriesId && s.SeasonNumber == seasonNumber);
return !season.Monitored;
}
public void DeleteSeason(int seasonId)
{
_repository.Delete<Season>(seasonId);
}
}
}

View File

@ -41,7 +41,7 @@ namespace NzbDrone.Core.Providers
public virtual Series GetSeries(int seriesId)
{
return _repository.Single<Series>(s => s.SeriesId == seriesId);
return _repository.Single<Series>(seriesId);
}
/// <summary>
@ -124,7 +124,7 @@ namespace NzbDrone.Core.Providers
Logger.Warn("Deleting Series [{0}]", seriesId);
var series = _repository.Single<Series>(seriesId);
//Delete Files, Episdes, Seasons then the Series
//Delete Files, Episodes, Seasons then the Series
//Can't use providers because episode provider needs series provider - Cyclic Dependency Injection, this will work
//Delete History Items for any episodes that belong to this series
@ -140,10 +140,6 @@ namespace NzbDrone.Core.Providers
Logger.Debug("Deleting Episodes from DB for Series: {0}", series.SeriesId);
_repository.DeleteMany(series.Episodes);
//Delete seasons for this series from the DB
Logger.Debug("Deleting Seasons from DB for Series: {0}", series.SeriesId);
_repository.DeleteMany(series.Seasons);
//Delete the Series
Logger.Debug("Deleting Series from DB {0}", series.Title);
_repository.Delete<Series>(seriesId);

View File

@ -6,7 +6,7 @@ using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Repository
{
public class Episode
public class Episode
{
[SubSonicPrimaryKey]
public virtual int EpisodeId { get; set; }
@ -15,7 +15,6 @@ namespace NzbDrone.Core.Repository
public virtual int SeriesId { get; set; }
public virtual int EpisodeFileId { get; set; }
public virtual int SeasonId { get; set; }
public virtual int SeasonNumber { get; set; }
public virtual int EpisodeNumber { get; set; }
public virtual string Title { get; set; }
@ -56,10 +55,9 @@ namespace NzbDrone.Core.Repository
if (EpisodeFileId != 0) return EpisodeStatusType.Ready;
var season = Season;
if (Ignored || (season != null && !season.Monitored)) return EpisodeStatusType.Ignored;
if (Ignored) return EpisodeStatusType.Ignored;
if (AirDate.Date.Year > 1900 && DateTime.Now.Date >= AirDate.Date)
{
return EpisodeStatusType.Missing;
@ -69,9 +67,6 @@ namespace NzbDrone.Core.Repository
}
}
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Season Season { get; set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Series Series { get; set; }

View File

@ -11,6 +11,7 @@ namespace NzbDrone.Core.Repository
public virtual int EpisodeFileId { get; set; }
public virtual int SeriesId { get; set; }
public virtual int SeasonNumber { get; set; }
public string Path { get; set; }
public QualityTypes Quality { get; set; }
public bool Proper { get; set; }

View File

@ -16,8 +16,6 @@ namespace NzbDrone.Core.Repository.Quality
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Name { get; set; }
public bool UserProfile { get; set; } //Allows us to tell the difference between default and user profiles
[SubSonicIgnore]
[DisplayName("Allowed Qualities")]
public List<QualityTypes> Allowed { get; set; }

View File

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Repository
{
public class Season
{
[SubSonicPrimaryKey(false)]
public virtual int SeasonId { get; set; }
public virtual int SeriesId { get; set; }
public virtual int SeasonNumber { get; set; }
public bool Monitored { get; set; }
public DayOfWeek? LastInfoSync { get; set; }
public DayOfWeek? LastDiskSync { get; set; }
[SubSonicToManyRelation]
public virtual IList<Episode> Episodes { get; set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Series Series { get; set; }
}
}

View File

@ -56,9 +56,6 @@ namespace NzbDrone.Core.Repository
[SubSonicToOneRelation(ThisClassContainsJoinKey = true, JoinKeyName = "QualityProfileId")]
public virtual QualityProfile QualityProfile { get; set; }
[SubSonicToManyRelation]
public virtual IList<Season> Seasons { get; protected set; }
[SubSonicToManyRelation]
public virtual IList<Episode> Episodes { get; set; }

View File

@ -20,7 +20,6 @@ namespace NzbDrone.Web.Controllers
private readonly SeriesProvider _seriesProvider;
private readonly TvDbProvider _tvDbProvider;
private readonly JobProvider _jobProvider;
private readonly SeasonProvider _seasonProvider;
private readonly MediaFileProvider _mediaFileProvider;
//
// GET: /Series/
@ -31,7 +30,6 @@ namespace NzbDrone.Web.Controllers
RenameProvider renameProvider,
TvDbProvider tvDbProvider,
JobProvider jobProvider,
SeasonProvider seasonProvider,
MediaFileProvider mediaFileProvider)
{
_seriesProvider = seriesProvider;
@ -40,7 +38,6 @@ namespace NzbDrone.Web.Controllers
_renameProvider = renameProvider;
_tvDbProvider = tvDbProvider;
_jobProvider = jobProvider;
_seasonProvider = seasonProvider;
_mediaFileProvider = mediaFileProvider;
}
@ -60,14 +57,21 @@ namespace NzbDrone.Web.Controllers
public ActionResult SeasonEditor(int seriesId)
{
var model =
_seriesProvider.GetSeries(seriesId).Seasons.Select(s => new SeasonEditModel
{
SeasonId = s.SeasonId,
SeasonNumber = s.SeasonNumber,
SeasonString = GetSeasonString(s.SeasonNumber),
Monitored = s.Monitored
}).OrderBy(s => s.SeasonNumber).ToList();
var model = new List<SeasonEditModel>();
var seasons = _episodeProvider.GetSeasons(seriesId);
foreach (var season in seasons)
{
var seasonEdit = new SeasonEditModel();
seasonEdit.Monitored = !_episodeProvider.IsIgnored(seriesId, season);
seasonEdit.SeasonNumber = season;
seasonEdit.SeriesId = seriesId;
seasonEdit.SeasonString = GetSeasonString(season);
model.Add(seasonEdit);
}
return View(model);
}
@ -117,9 +121,9 @@ namespace NzbDrone.Web.Controllers
}
[GridAction]
public ActionResult _AjaxSeasonGrid(int seasonId)
public ActionResult _AjaxSeasonGrid(int seriesId, int seasonNumber)
{
var episodes = _episodeProvider.GetEpisodeBySeason(seasonId).Select(c => new EpisodeModel
var episodes = _episodeProvider.GetEpisodesBySeason(seriesId, seasonNumber).Select(c => new EpisodeModel
{
EpisodeId = c.EpisodeId,
EpisodeNumber = c.EpisodeNumber,
@ -190,9 +194,10 @@ namespace NzbDrone.Web.Controllers
{
foreach (var season in seasons)
{
var seasonInDb = _seasonProvider.GetSeason(season.SeasonId);
seasonInDb.Monitored = season.Monitored;
_seasonProvider.SaveSeason(seasonInDb);
if (_episodeProvider.IsIgnored(season.SeriesId, season.SeasonNumber) != !season.Monitored)
{
_episodeProvider.SetSeasonIgnore(season.SeriesId, season.SeasonNumber, !season.Monitored);
}
}
return Content("Saved");
@ -201,7 +206,23 @@ namespace NzbDrone.Web.Controllers
public ActionResult Details(int seriesId)
{
var series = _seriesProvider.GetSeries(seriesId);
return View(series);
var model = new SeriesModel();
if (series.AirsDayOfWeek != null)
{
model.AirsDayOfWeek = series.AirsDayOfWeek.Value.ToString();
}
else
{
model.AirsDayOfWeek = "N/A";
}
model.Overview = series.Overview;
model.Seasons = _episodeProvider.GetSeasons(seriesId);
model.Title = series.Status;
model.SeriesId = series.SeriesId;
return View(model);
}
public ActionResult SyncEpisodesOnDisk(int seriesId)
@ -261,11 +282,8 @@ namespace NzbDrone.Web.Controllers
Path = s.Path,
QualityProfileId = s.QualityProfileId,
QualityProfileName = s.QualityProfile.Name,
SeasonsCount = s.Seasons.Where(x => x.SeasonNumber > 0).Count(),
SeasonFolder = s.SeasonFolder,
Status = s.Status,
Episodes = 0,
EpisodeTotal = 0
});
}

View File

@ -7,7 +7,7 @@ namespace NzbDrone.Web.Models
{
public class SeasonEditModel
{
public int SeasonId { get; set; }
public int SeriesId { get; set; }
public int SeasonNumber { get; set; }
public string SeasonString { get; set; }
public bool Monitored { get; set; }

View File

@ -19,7 +19,8 @@ namespace NzbDrone.Web.Models
public string QualityProfileName { get; set; }
public string Overview { get; set; }
public int Episodes { get; set; }
public int EpisodeTotal { get; set; }
public IList<int> Seasons { get; set; }
//View & Edit
[DisplayName("Path")]

View File

@ -1,4 +1,4 @@
@model NzbDrone.Core.Repository.Series
@model NzbDrone.Web.Models.SeriesModel
@using NzbDrone.Core.Repository
@using NzbDrone.Web.Models
@section TitleContent{
@ -31,68 +31,66 @@
<div class="display-label">
AirTimes</div>
<div class="display-field">
@Model.AirTimes</div>
@Model.AirsDayOfWeek.ToString()</div>
<div class="display-label">
Language</div>
<div class="display-field">
@Model.Language.ToUpper()</div>
<div class="display-label">
Location</div>
<div class="display-field">
@Model.Path</div>
</fieldset>
@*Todo: This breaks when using SQLServer... thoughts?*@
@foreach (var season in Model.Seasons.Where(s => s.SeasonNumber > 0).Reverse())
@*Todo: This breaks when using SQLServer... thoughts?*@ @*Easy, don't use SQL Server!!!*@
@foreach (var season in Model.Seasons.Where(s => s > 0).Reverse())
{
<br />
<h3>
Season @season.SeasonNumber</h3>
Season @season</h3>
<div class="grid-container">
@{Season season1 = season;
Html.Telerik().Grid<EpisodeModel>().Name("seasons_" + season.SeasonNumber)
.TableHtmlAttributes(new { @class = "Grid" })
.Columns(columns =>
{
columns.Bound(o => o.EpisodeId)
.ClientTemplate(
"<input type='checkbox' name='checkedEpisodes' value='<#= EpisodeId #>' />")
.Title("")
.Width(1)
.HtmlAttributes(new { style = "text-align:center" });
@{
Html.Telerik().Grid<EpisodeModel>().Name("seasons_" + season)
.TableHtmlAttributes(new { @class = "Grid" })
.Columns(columns =>
{
columns.Bound(o => o.EpisodeId)
.ClientTemplate(
"<input type='checkbox' name='checkedEpisodes' value='<#= EpisodeId #>' />")
.Title("")
.Width(1)
.HtmlAttributes(new { style = "text-align:center" });
columns.Bound(c => c.EpisodeNumber).Width(0).Title("Episode");
columns.Bound(c => c.Title).Title("Title");
columns.Bound(c => c.AirDate).Format("{0:d}").Width(0);
columns.Bound(c => c.Quality).Width(0);
columns.Bound(c => c.Status).Width(0);
columns.Bound(o => o.EpisodeId).Title("")
.ClientTemplate("<a href='#Search' onClick=\"searchForEpisode('<#= EpisodeId #>'); return false;\" >Search</a>");
})
.DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #> </br><#= Path #> </div>"))
.ClientEvents(clientEvents =>
{
clientEvents.OnDataBinding("grid_bind");
clientEvents.OnDataBound("grid_bound");
})
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(true))
.Footer(true)
.DataBinding(
d =>
d.Ajax().Select("_AjaxSeasonGrid", "Series",
new RouteValueDictionary { { "seasonId", season1.SeasonId.ToString() } }))
.ToolBar(
c =>
c.Custom().Text("Rename Season").Action("RenameSeason", "Series", new { seasonId = season1.SeasonId })
.ButtonType(GridButtonType.Text))
.Render();}
columns.Bound(c => c.EpisodeNumber).Width(0).Title("Episode");
columns.Bound(c => c.Title).Title("Title");
columns.Bound(c => c.AirDate).Format("{0:d}").Width(0);
columns.Bound(c => c.Quality).Width(0);
columns.Bound(c => c.Status).Width(0);
columns.Bound(o => o.EpisodeId).Title("")
.ClientTemplate("<a href='#Search' onClick=\"searchForEpisode('<#= EpisodeId #>'); return false;\" >Search</a>");
})
.DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #> </br><#= Path #> </div>"))
.ClientEvents(clientEvents =>
{
clientEvents.OnDataBinding("grid_bind");
clientEvents.OnDataBound("grid_bound");
})
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(true))
.Footer(true)
.DataBinding(
d =>
d.Ajax().Select("_AjaxSeasonGrid", "Series",
new RouteValueDictionary { { "seriesId", Model.SeriesId }, { "seasonNumber", season } }))
.ToolBar(
c =>
c.Custom().Text("Rename Season").Action("RenameSeason", "Series", new { seasonId = season })
.ButtonType(GridButtonType.Text))
.Render();}
<span class="grid-loader">
<img src="@Url.Content("~/Content/Images/Loading.gif")" alt="Loading"/>
Loading...</span>
</div>
}
@{var specialSeasons = Model.Seasons.Where(s => s.SeasonNumber == 0).FirstOrDefault();}
@if (specialSeasons != null)
@{var specialSeason = Model.Seasons.Where(s => s == 0).FirstOrDefault();}
@if (specialSeason != null)
{
<br />
@ -127,8 +125,8 @@
.DataBinding(
d =>
d.Ajax().Select("_AjaxSeasonGrid", "Series",
new RouteValueDictionary { { "seasonId", specialSeasons.SeasonId.ToString() } }))
.Render(); }
new RouteValueDictionary { { "seriesId", Model.SeriesId }, { "seasonNumber", specialSeason } }
)).Render(); }
<span class="grid-loader">
<img src="@Url.Content("~/Content/Images/Loading.gif")" alt="Loading"/>
Loading...</span>

View File

@ -8,7 +8,7 @@
@Html.DisplayFor(m => m.SeasonString)
<span style="float: right;">@Html.CheckBoxFor(m => m.Monitored, new { @class = "chkbox" })</span>
@Html.HiddenFor(m => m.SeasonId)
@Html.HiddenFor(m => m.SeasonNumber)
@Html.HiddenFor(m => m.SeasonNumber)
</fieldset>
}

View File

@ -2,17 +2,30 @@
@using System.Collections
@using NzbDrone.Core.Repository.Quality
@using NzbDrone.Web.Helpers
@{
Layout = null;
}
<style>
.quality-selectee { width: 75px; padding: 1px; padding-left: 3px; padding-right: 3px; margin: 2px; float: left; cursor: default; }
.quality-selecting { background: #85AEF9; }
.quality-selected { background: #065EFE; color: white; }
.quality-selectee
{
width: 75px;
padding: 1px;
padding-left: 3px;
padding-right: 3px;
margin: 2px;
float: left;
cursor: default;
}
.quality-selecting
{
background: #85AEF9;
}
.quality-selected
{
background: #065EFE;
color: white;
}
</style>
@using (Html.BeginCollectionItem("Profiles"))
{
var idClean = ViewData.TemplateInfo.HtmlFieldPrefix.Replace('[', '_').Replace(']', '_');
@ -25,27 +38,26 @@
string cutoff = String.Format("{0}_Cutoff", idClean);
<div class="profileSectionEditor" id="profile_@(ViewData["ProfileId"])" style="float: left; height: 175px; width: 285px; margin-bottom: -14px;">
<fieldset style="width:264px; margin:5px; margin-top: 0px; border-color:#CCCCCD">
<fieldset style="width: 264px; margin: 5px; margin-top: 0px; border-color: #CCCCCD">
<div class="header">
<div id="qualityHeader" style="padding-bottom: 5px; margin: 0px;">
<h2 style="display:inline; padding-right: 4px; margin-left: 4px;" id="@title">@{Html.DisplayTextFor(m => m.Name);}</h2>
<a href="#" id="@Model.QualityProfileId" class="deleteRow" onclick="deleteProfile('@ViewData["ProfileId"]'); return false;" style="float:right; padding-top:8px; padding-right: 5px;"><img src="../../Content/Images/X.png" alt="Delete" width="20px" height="20px"/></a>
<h2 style="display:inline; padding-right: 4px; margin-left: 4px;" id="@title">
@{Html.DisplayTextFor(m => m.Name);}
</h2>
<a href="#" id="@Model.QualityProfileId" class="deleteRow" onclick="deleteProfile('@ViewData["ProfileId"]'); return false;" style="float:right; padding-top:8px; padding-right: 5px;">
<img src="../../Content/Images/X.png" alt="Delete" width="20px" height="20px" /></a>
</div>
<div class="config-group" style="width: 255px; margin-bottom: 5px; margin-left: 5px;">
<div class="config-title">@Html.LabelFor(x => x.Name)</div>
<div class="config-value">@Html.TextBoxFor(x => x.Name, new { maxlength = 15 })</div>
<div class="config-validation">@Html.ValidationMessageFor(x => x.Name)</div>
</div>
<div class="config-group" style="width: 255px; margin-bottom: 5px; margin-left: 5px;">
<div class="config-title">@Html.LabelFor(x => x.Cutoff)</div>
<div class="config-value">@Html.DropDownListFor(m => m.Cutoff, new SelectList(Model.Allowed, Model.Cutoff))</div>
<div class="config-validation">@Html.ValidationMessageFor(x => x.Cutoff)</div>
</div>
</div>
</div>
<div class="selectableDiv" style="margin-top: 30px;">
<div id="@selectable">
@{var qualitiesList = (List<QualityTypes>)ViewData["Qualities"];}
@ -55,12 +67,12 @@
{
continue;
}
if (Model.Allowed != null)
{
if (Model.Allowed.Contains(qualitiesList[i]))
{
<fieldset class="quality-selectee quality-selected">@qualitiesList[i].ToString()</fieldset>
<fieldset class="quality-selectee quality-selected">@qualitiesList[i].ToString()</fieldset>
continue;
}
}
@ -69,10 +81,8 @@
}
</div>
</div>
<div class="hiddenProfileDetails">
@Html.HiddenFor(x => x.QualityProfileId)
@Html.HiddenFor(x => x.UserProfile)
@Html.HiddenFor(m => m.AllowedString)
</div>
</fieldset>
@ -100,13 +110,12 @@
}).keyup();
$('#@selectable .quality-selectee').click(function () {
if ($(this).hasClass('quality-selected'))
{
if ($(this).hasClass('quality-selected')) {
$(this).removeClass('quality-selected');
var toRemove = this.firstChild.data;
$('#@cutoff option').each(function () { if ($(this).text().indexOf(toRemove) > -1) $('#@cutoff option').remove(':contains("' + $(this).text() + '")'); });
}
else {
$(this).addClass('quality-selected');
$('<option>' + this.firstChild.data + '</option>').appendTo('#@cutoff');