mirror of
https://github.com/Radarr/Radarr.git
synced 2024-11-05 10:32:35 +01:00
Merge remote-tracking branch 'origin/metadata'
This commit is contained in:
commit
7c803c4691
19
NzbDrone.App.Test/NzbDrone.App.Test.ncrunchproject
Normal file
19
NzbDrone.App.Test/NzbDrone.App.Test.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
19
NzbDrone.Common.Test/NzbDrone.Common.Test.ncrunchproject
Normal file
19
NzbDrone.Common.Test/NzbDrone.Common.Test.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
@ -200,6 +200,10 @@ public virtual string ReadAllText(string filePath)
|
||||
return File.ReadAllText(filePath);
|
||||
}
|
||||
|
||||
public virtual void WriteAllText(string filename, string contents)
|
||||
{
|
||||
File.WriteAllText(filename, contents);
|
||||
}
|
||||
|
||||
public static bool PathEquals(string firstPath, string secondPath)
|
||||
{
|
||||
|
19
NzbDrone.Common/NzbDrone.Common.ncrunchproject
Normal file
19
NzbDrone.Common/NzbDrone.Common.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
@ -114,6 +114,8 @@
|
||||
<Compile Include="ProviderTests\AnalyticsProviderTests\AnalyticsProviderFixture.cs" />
|
||||
<Compile Include="ProviderTests\ConfigProviderTests\ConfigCachingFixture.cs" />
|
||||
<Compile Include="ProviderTests\BannerProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\Metadata\Xbmc_ForEpisodeFile_Fixture.cs" />
|
||||
<Compile Include="ProviderTests\Metadata\Xbmc_ForSeries_Fixture.cs" />
|
||||
<Compile Include="ProviderTests\SearchHistoryProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\PlexProviderTest.cs" />
|
||||
<Compile Include="ProviderTests\SeasonProviderTest.cs" />
|
||||
|
19
NzbDrone.Core.Test/NzbDrone.Core.Test.ncrunchproject
Normal file
19
NzbDrone.Core.Test/NzbDrone.Core.Test.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
@ -212,7 +212,7 @@ public void move_should_not_move_file_if_source_and_destination_are_the_same_pat
|
||||
var result = Mocker.Resolve<DiskScanProvider>().MoveEpisodeFile(file, false);
|
||||
|
||||
//Assert
|
||||
result.Should().BeFalse();
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -368,7 +368,7 @@ public void MoveEpisodeFile_should_use_EpisodeFiles_quality()
|
||||
var result = Mocker.Resolve<DiskScanProvider>().MoveEpisodeFile(file, true);
|
||||
|
||||
//Assert
|
||||
result.Should().BeTrue();
|
||||
result.Should().NotBeNull();
|
||||
Mocker.GetMock<ExternalNotificationProvider>()
|
||||
.Verify(e => e.OnDownload("30 Rock - 1x01 - [WEBDL]", It.IsAny<Series>()), Times.Once());
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ public void RefreshEpisodeInfo_emptyRepo()
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
//Act
|
||||
@ -207,7 +207,7 @@ public void RefreshEpisodeInfo_should_set_older_than_1900_to_null()
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
|
||||
@ -248,7 +248,7 @@ public void RefreshEpisodeInfo_should_set_older_than_1900_to_null_for_existing_e
|
||||
Db.Insert(fakeEpisode);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeTvDbEpisodes);
|
||||
|
||||
//Act
|
||||
@ -285,7 +285,7 @@ public void RefreshEpisodeInfo_ignore_episode_zero()
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
|
||||
@ -324,7 +324,7 @@ public void RefreshEpisodeInfo_should_skip_future_episodes_with_no_title()
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
|
||||
@ -362,7 +362,7 @@ public void RefreshEpisodeInfo_should_skip_older_than_1900_year_episodes_with_no
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
|
||||
@ -395,7 +395,7 @@ public void RefreshEpisodeInfo_should_add_future_episodes_with_title()
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
|
||||
@ -428,7 +428,7 @@ public void RefreshEpisodeInfo_should_add_old_episodes_with_no_title()
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
|
||||
@ -463,7 +463,7 @@ public void RefreshEpisodeInfo_ignore_season_zero()
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeEpisodes);
|
||||
|
||||
Mocker.GetMock<SeasonProvider>()
|
||||
@ -493,7 +493,7 @@ public void new_episodes_only_calls_Insert()
|
||||
var currentEpisodes = new List<Episode>();
|
||||
|
||||
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(tvdbSeries);
|
||||
|
||||
Mocker.GetMock<IDatabase>()
|
||||
@ -528,7 +528,7 @@ public void existing_episodes_only_calls_Update()
|
||||
}
|
||||
|
||||
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(tvdbSeries);
|
||||
|
||||
Mocker.GetMock<IDatabase>()
|
||||
@ -565,7 +565,7 @@ public void should_try_to_get_existing_episode_using_tvdbid_first()
|
||||
.Returns(fakeEpisodeList);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(fakeTvDbResult);
|
||||
|
||||
//Act
|
||||
@ -602,7 +602,7 @@ public void should_try_to_get_existing_episode_using_tvdbid_first_then_season_ep
|
||||
var fakeSeries = Builder<Series>.CreateNew().With(c => c.SeriesId = seriesId).Build();
|
||||
|
||||
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(tvdbSeries);
|
||||
|
||||
Mocker.GetMock<IDatabase>()
|
||||
@ -634,7 +634,7 @@ public void existing_episodes_keep_their_episodeId_file_id()
|
||||
}
|
||||
|
||||
Mocker.GetMock<TvDbProvider>(MockBehavior.Strict)
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(tvdbSeries);
|
||||
|
||||
var updatedEpisodes = new List<Episode>();
|
||||
@ -695,7 +695,7 @@ public void RefreshEpisodeInfo_should_ignore_new_episode_for_ignored_season()
|
||||
Db.Insert(fakeEpisode);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(tvdbSeries);
|
||||
|
||||
Mocker.GetMock<SeasonProvider>()
|
||||
@ -1407,7 +1407,7 @@ public void RefreshEpisodeInfo_should_ignore_episode_zero_except_if_season_one()
|
||||
Db.Insert(fakeSeries);
|
||||
|
||||
Mocker.GetMock<TvDbProvider>()
|
||||
.Setup(c => c.GetSeries(seriesId, true))
|
||||
.Setup(c => c.GetSeries(seriesId, true, false))
|
||||
.Returns(tvdbSeries);
|
||||
|
||||
//Act
|
||||
|
@ -0,0 +1,153 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Providers.Metadata;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
using NzbDrone.Test.Common;
|
||||
using TvdbLib.Data;
|
||||
using TvdbLib.Data.Banner;
|
||||
|
||||
namespace NzbDrone.Core.Test.ProviderTests.Metadata
|
||||
{
|
||||
[TestFixture]
|
||||
// ReSharper disable InconsistentNaming
|
||||
public class Xbmc_ForEpisoddeFile_Fixture : CoreTest
|
||||
{
|
||||
private Series series;
|
||||
private EpisodeFile episodeFile;
|
||||
private TvdbSeries tvdbSeries;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
WithTempAsAppPath();
|
||||
|
||||
series = Builder<Series>
|
||||
.CreateNew()
|
||||
.With(s => s.SeriesId == 79488)
|
||||
.With(s => s.Title == "30 Rock")
|
||||
.Build();
|
||||
|
||||
episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(f => f.SeriesId = 79488)
|
||||
.With(f => f.SeasonNumber = 1)
|
||||
.With(f => f.Path = @"C:\Test\30 Rock\Season 01\30 Rock - S01E01 - Pilot.avi")
|
||||
.Build();
|
||||
|
||||
var tvdbEpisodes = Builder<TvdbEpisode>.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(e => e.SeriesId = 79488)
|
||||
.With(e => e.SeasonNumber = 1)
|
||||
.With(e => e.Directors = new List<string>{ "Fake Director" })
|
||||
.With(e => e.Writer = new List<string>{ "Fake Writer" })
|
||||
.With(e => e.GuestStars = new List<string> { "Guest Star 1", "Guest Star 2", "Guest Star 3", "" })
|
||||
.Build();
|
||||
|
||||
var seasonBanners = Builder<TvdbSeasonBanner>
|
||||
.CreateListOfSize(4)
|
||||
.TheFirst(2)
|
||||
.With(b => b.Season = 1)
|
||||
.TheLast(2)
|
||||
.With(b => b.Season = 2)
|
||||
.TheFirst(1)
|
||||
.With(b => b.BannerType = TvdbSeasonBanner.Type.season)
|
||||
.With(b => b.BannerPath = "seasons/79488-1-1.jpg")
|
||||
.TheNext(2)
|
||||
.With(b => b.BannerType = TvdbSeasonBanner.Type.seasonwide)
|
||||
.With(b => b.BannerPath = "banners/seasons/79488-test.jpg")
|
||||
.TheLast(1)
|
||||
.With(b => b.BannerType = TvdbSeasonBanner.Type.season)
|
||||
.With(b => b.BannerPath = "seasons/79488-2-1.jpg")
|
||||
.Build();
|
||||
|
||||
var seriesActors = Builder<TvdbActor>
|
||||
.CreateListOfSize(5)
|
||||
.Build();
|
||||
|
||||
tvdbSeries = Builder<TvdbSeries>
|
||||
.CreateNew()
|
||||
.With(s => s.Id = 79488)
|
||||
.With(s => s.SeriesName = "30 Rock")
|
||||
.With(s => s.TvdbActors = seriesActors.ToList())
|
||||
.With(s => s.Episodes = tvdbEpisodes.ToList())
|
||||
.Build();
|
||||
|
||||
tvdbSeries.Banners.AddRange(seasonBanners);
|
||||
}
|
||||
|
||||
private void WithUseBanners()
|
||||
{
|
||||
Mocker.GetMock<ConfigProvider>().SetupGet(s => s.MetadataUseBanners).Returns(true);
|
||||
}
|
||||
|
||||
private void WithSingleEpisodeFile()
|
||||
{
|
||||
var episode = Builder<Episode>.CreateNew()
|
||||
.With(e => e.SeasonNumber = 1)
|
||||
.With(e => e.SeriesId = 79488)
|
||||
.With(e => e.EpisodeNumber = 1)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<EpisodeProvider>()
|
||||
.Setup(s => s.GetEpisodesByFileId(episodeFile.EpisodeFileId))
|
||||
.Returns(new List<Episode> { episode });
|
||||
}
|
||||
|
||||
private void WithMultiEpisodeFile()
|
||||
{
|
||||
var episodes = Builder<Episode>.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(e => e.SeriesId = 79488)
|
||||
.With(e => e.SeasonNumber = 1)
|
||||
.Build();
|
||||
|
||||
Mocker.GetMock<EpisodeProvider>()
|
||||
.Setup(s => s.GetEpisodesByFileId(episodeFile.EpisodeFileId))
|
||||
.Returns(episodes.ToList());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_blowup()
|
||||
{
|
||||
WithSingleEpisodeFile();
|
||||
Mocker.Resolve<Xbmc>().CreateForEpisodeFile(episodeFile, tvdbSeries);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_call_diskprovider_writeAllText_once_for_single_episode()
|
||||
{
|
||||
WithSingleEpisodeFile();
|
||||
Mocker.Resolve<Xbmc>().CreateForEpisodeFile(episodeFile, tvdbSeries);
|
||||
Mocker.GetMock<DiskProvider>().Verify(v => v.WriteAllText(episodeFile.Path.Replace("avi", "nfo"), It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_call_diskprovider_writeAllText_once_for_multi_episode()
|
||||
{
|
||||
WithMultiEpisodeFile();
|
||||
Mocker.Resolve<Xbmc>().CreateForEpisodeFile(episodeFile, tvdbSeries);
|
||||
Mocker.GetMock<DiskProvider>().Verify(v => v.WriteAllText(episodeFile.Path.Replace("avi", "nfo"), It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_download_thumbnail_when_thumbnail_path_is_not_null()
|
||||
{
|
||||
WithSingleEpisodeFile();
|
||||
Mocker.Resolve<Xbmc>().CreateForEpisodeFile(episodeFile, tvdbSeries);
|
||||
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.Episodes.First().BannerPath, episodeFile.Path.Replace("avi", "tbn")), Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Providers.Metadata;
|
||||
using NzbDrone.Core.Repository;
|
||||
using NzbDrone.Core.Repository.Quality;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common.AutoMoq;
|
||||
using NzbDrone.Test.Common;
|
||||
using TvdbLib.Data;
|
||||
using TvdbLib.Data.Banner;
|
||||
|
||||
namespace NzbDrone.Core.Test.ProviderTests.Metadata
|
||||
{
|
||||
[TestFixture]
|
||||
// ReSharper disable InconsistentNaming
|
||||
public class Xbmc_ForSeries_Fixture : CoreTest
|
||||
{
|
||||
private Series series;
|
||||
private TvdbSeries tvdbSeries;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
WithTempAsAppPath();
|
||||
|
||||
series = Builder<Series>
|
||||
.CreateNew()
|
||||
.With(s => s.SeriesId == 79488)
|
||||
.With(s => s.Title == "30 Rock")
|
||||
.Build();
|
||||
|
||||
var seasonBanners = Builder<TvdbSeasonBanner>
|
||||
.CreateListOfSize(4)
|
||||
.TheFirst(2)
|
||||
.With(b => b.Season = 1)
|
||||
.TheLast(2)
|
||||
.With(b => b.Season = 2)
|
||||
.TheFirst(1)
|
||||
.With(b => b.BannerType = TvdbSeasonBanner.Type.season)
|
||||
.With(b => b.BannerPath = "seasons/79488-1-1.jpg")
|
||||
.TheNext(2)
|
||||
.With(b => b.BannerType = TvdbSeasonBanner.Type.seasonwide)
|
||||
.With(b => b.BannerPath = "banners/seasons/79488-test.jpg")
|
||||
.TheLast(1)
|
||||
.With(b => b.BannerType = TvdbSeasonBanner.Type.season)
|
||||
.With(b => b.BannerPath = "seasons/79488-2-1.jpg")
|
||||
.Build();
|
||||
|
||||
var seriesActors = Builder<TvdbActor>
|
||||
.CreateListOfSize(5)
|
||||
.Build();
|
||||
|
||||
tvdbSeries = Builder<TvdbSeries>
|
||||
.CreateNew()
|
||||
.With(s => s.Id = 79488)
|
||||
.With(s => s.SeriesName = "30 Rock")
|
||||
.With(s => s.TvdbActors = seriesActors.ToList())
|
||||
.Build();
|
||||
|
||||
tvdbSeries.Banners.AddRange(seasonBanners);
|
||||
}
|
||||
|
||||
private void WithUseBanners()
|
||||
{
|
||||
Mocker.GetMock<ConfigProvider>().SetupGet(s => s.MetadataUseBanners).Returns(true);
|
||||
}
|
||||
|
||||
private void WithSpecials()
|
||||
{
|
||||
var seasonBanners = Builder<TvdbSeasonBanner>
|
||||
.CreateListOfSize(2)
|
||||
.All()
|
||||
.With(b => b.Season = 0)
|
||||
.TheFirst(1)
|
||||
.With(b => b.BannerType = TvdbSeasonBanner.Type.season)
|
||||
.With(b => b.BannerPath = "seasons/79488-0-1.jpg")
|
||||
.TheLast(1)
|
||||
.With(b => b.BannerType = TvdbSeasonBanner.Type.seasonwide)
|
||||
.With(b => b.BannerPath = "banners/seasons/79488-0-1.jpg")
|
||||
.Build();
|
||||
|
||||
var seriesActors = Builder<TvdbActor>
|
||||
.CreateListOfSize(5)
|
||||
.Build();
|
||||
|
||||
tvdbSeries = Builder<TvdbSeries>
|
||||
.CreateNew()
|
||||
.With(s => s.Id = 79488)
|
||||
.With(s => s.SeriesName = "30 Rock")
|
||||
.With(s => s.TvdbActors = seriesActors.ToList())
|
||||
.Build();
|
||||
|
||||
tvdbSeries.Banners.AddRange(seasonBanners);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_blowup()
|
||||
{
|
||||
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_call_diskprovider_writeAllText()
|
||||
{
|
||||
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
|
||||
Mocker.GetMock<DiskProvider>().Verify(v => v.WriteAllText(Path.Combine(series.Path, "tvshow.nfo"), It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_download_fanart()
|
||||
{
|
||||
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
|
||||
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.FanartPath, Path.Combine(series.Path, "fanart.jpg")), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_download_poster_when_useBanners_is_false()
|
||||
{
|
||||
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
|
||||
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.PosterPath, Path.Combine(series.Path, "folder.jpg")), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_download_banner_when_useBanners_is_true()
|
||||
{
|
||||
WithUseBanners();
|
||||
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
|
||||
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(tvdbSeries.BannerPath, Path.Combine(series.Path, "folder.jpg")), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_download_season_poster_when_useBanners_is_false()
|
||||
{
|
||||
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
|
||||
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(It.Is<string>(s => !s.Contains("banners")), It.IsRegex(@"season\d{2}\.tbn")), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_download_season_banner_when_useBanners_is_true()
|
||||
{
|
||||
WithUseBanners();
|
||||
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
|
||||
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(It.Is<string>(s => s.Contains("banners")), It.IsRegex(@"season\d{2}\.tbn")), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_download_special_thumb_with_proper_name()
|
||||
{
|
||||
WithUseBanners();
|
||||
WithSpecials();
|
||||
Mocker.Resolve<Xbmc>().CreateForSeries(series, tvdbSeries);
|
||||
Mocker.GetMock<BannerProvider>().Verify(v => v.Download(It.Is<string>(s => s.Contains("banners")), It.IsRegex(@"season-specials.tbn")), Times.Exactly(1));
|
||||
}
|
||||
}
|
||||
}
|
@ -210,7 +210,7 @@ public void when_no_file_are_imported_and_folder_size_isnt_small_enought_folder_
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.MoveDirectory(droppedFolder.FullName, taggedFolder));
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.GetDirectorySize(droppedFolder.FullName)).Returns(Constants.IgnoreFileSize + 10.Megabytes());
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.Scan(fakeSeries, droppedFolder.FullName)).Returns(fakeEpisodeFiles);
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.MoveEpisodeFile(It.IsAny<EpisodeFile>(), true)).Returns(true);
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.MoveEpisodeFile(It.IsAny<EpisodeFile>(), true)).Returns(new EpisodeFile());
|
||||
|
||||
Mocker.Resolve<PostDownloadProvider>().ProcessDownload(droppedFolder);
|
||||
|
||||
@ -281,9 +281,10 @@ public void when_files_are_imported_and_folder_is_small_enought_dir_should_be_de
|
||||
Mocker.GetMock<SeriesProvider>().Setup(s => s.FindSeries("office")).Returns(fakeSeries);
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.CleanUpDropFolder(droppedFolder.FullName));
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.Scan(fakeSeries, droppedFolder.FullName)).Returns(fakeEpisodeFiles);
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.MoveEpisodeFile(It.IsAny<EpisodeFile>(), true)).Returns(true);
|
||||
Mocker.GetMock<DiskScanProvider>().Setup(s => s.MoveEpisodeFile(It.IsAny<EpisodeFile>(), true)).Returns(new EpisodeFile());
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.GetDirectorySize(droppedFolder.FullName)).Returns(Constants.IgnoreFileSize - 1.Megabytes());
|
||||
Mocker.GetMock<DiskProvider>().Setup(s => s.DeleteFolder(droppedFolder.FullName, true));
|
||||
Mocker.GetMock<MetadataProvider>().Setup(s => s.CreateForEpisodeFiles(It.IsAny<List<EpisodeFile>>()));
|
||||
|
||||
//Act
|
||||
Mocker.Resolve<PostDownloadProvider>().ProcessDownload(droppedFolder);
|
||||
|
@ -13,6 +13,7 @@
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Providers.ExternalNotification;
|
||||
using NzbDrone.Core.Providers.Indexer;
|
||||
using NzbDrone.Core.Providers.Metadata;
|
||||
using NzbDrone.Core.Repository;
|
||||
using PetaPoco;
|
||||
using SignalR;
|
||||
@ -20,6 +21,7 @@
|
||||
using SignalR.Infrastructure;
|
||||
using SignalR.Ninject;
|
||||
using Connection = NzbDrone.Core.Datastore.Connection;
|
||||
using Xbmc = NzbDrone.Core.Providers.ExternalNotification.Xbmc;
|
||||
|
||||
namespace NzbDrone.Core
|
||||
{
|
||||
@ -45,8 +47,9 @@ public CentralDispatch()
|
||||
|
||||
InitQuality();
|
||||
InitExternalNotifications();
|
||||
InitMetadataProviders();
|
||||
InitIndexers();
|
||||
InitJobs();
|
||||
InitJobs();
|
||||
}
|
||||
|
||||
private void InitDatabase()
|
||||
@ -161,6 +164,16 @@ private void InitExternalNotifications()
|
||||
Kernel.Get<ExternalNotificationProvider>().InitializeNotifiers(notifiers.ToList());
|
||||
}
|
||||
|
||||
private void InitMetadataProviders()
|
||||
{
|
||||
logger.Debug("Initializing Metadata Providers...");
|
||||
|
||||
Kernel.Bind<MetadataBase>().To<Providers.Metadata.Xbmc>().InSingletonScope();
|
||||
|
||||
var providers = Kernel.GetAll<MetadataBase>();
|
||||
Kernel.Get<MetadataProvider>().Initialize(providers.ToList());
|
||||
}
|
||||
|
||||
public void DedicateToHost()
|
||||
{
|
||||
try
|
||||
|
21
NzbDrone.Core/Datastore/Migrations/Migration20120707.cs
Normal file
21
NzbDrone.Core/Datastore/Migrations/Migration20120707.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Data;
|
||||
using Migrator.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migrations
|
||||
{
|
||||
|
||||
[Migration(20120707)]
|
||||
public class Migration20120707 : NzbDroneMigration
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Database.AddTable("MetadataDefinitions", new[]
|
||||
{
|
||||
new Column("Id", DbType.Int32, ColumnProperty.PrimaryKeyWithIdentity),
|
||||
new Column("Enable", DbType.Boolean, ColumnProperty.NotNull),
|
||||
new Column("MetadataProviderType", DbType.String, ColumnProperty.NotNull),
|
||||
new Column("Name", DbType.String, ColumnProperty.NotNull)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using NLog;
|
||||
using Ninject;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Repository;
|
||||
|
||||
namespace NzbDrone.Core.Jobs
|
||||
{
|
||||
@ -13,17 +15,20 @@ public class RenameSeasonJob : IJob
|
||||
private readonly DiskScanProvider _diskScanProvider;
|
||||
private readonly ExternalNotificationProvider _externalNotificationProvider;
|
||||
private readonly SeriesProvider _seriesProvider;
|
||||
private readonly MetadataProvider _metadataProvider;
|
||||
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
[Inject]
|
||||
public RenameSeasonJob(MediaFileProvider mediaFileProvider, DiskScanProvider diskScanProvider,
|
||||
ExternalNotificationProvider externalNotificationProvider, SeriesProvider seriesProvider)
|
||||
ExternalNotificationProvider externalNotificationProvider, SeriesProvider seriesProvider,
|
||||
MetadataProvider metadataProvider)
|
||||
{
|
||||
_mediaFileProvider = mediaFileProvider;
|
||||
_diskScanProvider = diskScanProvider;
|
||||
_externalNotificationProvider = externalNotificationProvider;
|
||||
_seriesProvider = seriesProvider;
|
||||
_metadataProvider = metadataProvider;
|
||||
}
|
||||
|
||||
public string Name
|
||||
@ -57,18 +62,32 @@ public void Start(ProgressNotification notification, int targetId, int secondary
|
||||
return;
|
||||
}
|
||||
|
||||
var newEpisodeFiles = new List<EpisodeFile>();
|
||||
var oldEpisodeFiles = new List<EpisodeFile>();
|
||||
|
||||
foreach (var episodeFile in episodeFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
_diskScanProvider.MoveEpisodeFile(episodeFile);
|
||||
var newFile = _diskScanProvider.MoveEpisodeFile(episodeFile);
|
||||
|
||||
if (newFile != null)
|
||||
{
|
||||
newEpisodeFiles.Add(newFile);
|
||||
oldEpisodeFiles.Add(episodeFile);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.WarnException("An error has occurred while renaming file", exception);
|
||||
logger.WarnException("An error has occurred while renaming file", e);
|
||||
}
|
||||
}
|
||||
|
||||
//Remove & Create Metadata for episode files
|
||||
_metadataProvider.RemoveForEpisodeFiles(oldEpisodeFiles);
|
||||
_metadataProvider.CreateForEpisodeFiles(newEpisodeFiles);
|
||||
|
||||
//Start AfterRename
|
||||
|
||||
var message = String.Format("Renamed: Series {0}, Season: {1}", series.Title, secondaryTargetId);
|
||||
|
@ -1,9 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using NLog;
|
||||
using Ninject;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Repository;
|
||||
|
||||
namespace NzbDrone.Core.Jobs
|
||||
{
|
||||
@ -13,17 +15,20 @@ public class RenameSeriesJob : IJob
|
||||
private readonly DiskScanProvider _diskScanProvider;
|
||||
private readonly ExternalNotificationProvider _externalNotificationProvider;
|
||||
private readonly SeriesProvider _seriesProvider;
|
||||
private readonly MetadataProvider _metadataProvider;
|
||||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
[Inject]
|
||||
public RenameSeriesJob(MediaFileProvider mediaFileProvider, DiskScanProvider diskScanProvider,
|
||||
ExternalNotificationProvider externalNotificationProvider, SeriesProvider seriesProvider)
|
||||
ExternalNotificationProvider externalNotificationProvider, SeriesProvider seriesProvider,
|
||||
MetadataProvider metadataProvider)
|
||||
{
|
||||
_mediaFileProvider = mediaFileProvider;
|
||||
_diskScanProvider = diskScanProvider;
|
||||
_externalNotificationProvider = externalNotificationProvider;
|
||||
_seriesProvider = seriesProvider;
|
||||
_metadataProvider = metadataProvider;
|
||||
}
|
||||
|
||||
public string Name
|
||||
@ -54,19 +59,32 @@ public void Start(ProgressNotification notification, int targetId, int secondary
|
||||
return;
|
||||
}
|
||||
|
||||
var newEpisodeFiles = new List<EpisodeFile>();
|
||||
var oldEpisodeFiles = new List<EpisodeFile>();
|
||||
|
||||
foreach (var episodeFile in episodeFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
_diskScanProvider.MoveEpisodeFile(episodeFile);
|
||||
var newFile = _diskScanProvider.MoveEpisodeFile(episodeFile);
|
||||
|
||||
if (newFile != null)
|
||||
{
|
||||
newEpisodeFiles.Add(newFile);
|
||||
oldEpisodeFiles.Add(episodeFile);
|
||||
}
|
||||
}
|
||||
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.WarnException("An error has occurred while renaming file", e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Remove & Create Metadata for episode files
|
||||
_metadataProvider.RemoveForEpisodeFiles(oldEpisodeFiles);
|
||||
_metadataProvider.CreateForEpisodeFiles(newEpisodeFiles);
|
||||
|
||||
//Start AfterRename
|
||||
|
||||
var message = String.Format("Renamed: Series {0}", series.Title);
|
||||
|
@ -239,6 +239,7 @@
|
||||
<Compile Include="Datastore\Migrations\Migration20110726.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20110707.cs" />
|
||||
<Compile Include="Datastore\DbProviderFactory.cs" />
|
||||
<Compile Include="Datastore\Migrations\Migration20120707.cs" />
|
||||
<Compile Include="Datastore\Migrations\NzbDroneMigration.cs" />
|
||||
<Compile Include="Datastore\Migrations\SchemaInfo.cs" />
|
||||
<Compile Include="Datastore\PetaPoco\EpisodeSeasonRelator.cs" />
|
||||
@ -285,6 +286,9 @@
|
||||
<Compile Include="Providers\Indexer\NzbIndex.cs" />
|
||||
<Compile Include="Providers\Indexer\FileSharingTalk.cs" />
|
||||
<Compile Include="Providers\Indexer\Wombles.cs" />
|
||||
<Compile Include="Providers\MetadataProvider.cs" />
|
||||
<Compile Include="Providers\Metadata\MetadataBase.cs" />
|
||||
<Compile Include="Providers\Metadata\Xbmc.cs" />
|
||||
<Compile Include="Providers\SearchHistoryProvider.cs" />
|
||||
<Compile Include="Providers\SeasonProvider.cs" />
|
||||
<Compile Include="Jobs\RecentBacklogSearchJob.cs" />
|
||||
@ -314,6 +318,7 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Providers\StatsProvider.cs" />
|
||||
<Compile Include="Repository\MetadataDefinition.cs" />
|
||||
<Compile Include="Repository\Search\SearchHistoryItem.cs" />
|
||||
<Compile Include="Repository\Search\SearchHistory.cs" />
|
||||
<Compile Include="Model\ReportRejectionType.cs" />
|
||||
|
19
NzbDrone.Core/NzbDrone.Core.ncrunchproject
Normal file
19
NzbDrone.Core/NzbDrone.Core.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
@ -81,5 +81,22 @@ public virtual bool Delete(int seriesId)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void Download(string remotePath, string filename)
|
||||
{
|
||||
var url = BANNER_URL_PREFIX + remotePath;
|
||||
|
||||
try
|
||||
{
|
||||
_httpProvider.DownloadFile(url, filename);
|
||||
logger.Trace("Successfully download banner from '{0}' to '{1}'", url, filename);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = String.Format("Failed to download Banner from '{0}' to '{1}'", url, filename);
|
||||
logger.DebugException(message, ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -501,6 +501,13 @@ public virtual string PlexPassword
|
||||
set { SetValue("PlexPassword", value); }
|
||||
}
|
||||
|
||||
public virtual Boolean MetadataUseBanners
|
||||
{
|
||||
get { return GetValueBoolean("MetadataUseBanners"); }
|
||||
|
||||
set { SetValue("MetadataUseBanners", value); }
|
||||
}
|
||||
|
||||
private string GetValue(string key)
|
||||
{
|
||||
return GetValue(key, String.Empty);
|
||||
|
@ -168,7 +168,7 @@ public virtual EpisodeFile ImportFile(Series series, string filePath)
|
||||
return episodeFile;
|
||||
}
|
||||
|
||||
public virtual bool MoveEpisodeFile(EpisodeFile episodeFile, bool newDownload = false)
|
||||
public virtual EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, bool newDownload = false)
|
||||
{
|
||||
if (episodeFile == null)
|
||||
throw new ArgumentNullException("episodeFile");
|
||||
@ -182,14 +182,14 @@ public virtual bool MoveEpisodeFile(EpisodeFile episodeFile, bool newDownload =
|
||||
if (DiskProvider.PathEquals(episodeFile.Path, newFile.FullName))
|
||||
{
|
||||
Logger.Debug("Skipping file rename, source and destination are the same: {0}", episodeFile.Path);
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
_diskProvider.CreateDirectory(newFile.DirectoryName);
|
||||
|
||||
Logger.Debug("Moving [{0}] > [{1}]", episodeFile.Path, newFile.FullName);
|
||||
_diskProvider.MoveFile(episodeFile.Path, newFile.FullName);
|
||||
|
||||
|
||||
_diskProvider.InheritFolderPermissions(newFile.FullName);
|
||||
|
||||
episodeFile.Path = newFile.FullName;
|
||||
@ -213,7 +213,7 @@ public virtual bool MoveEpisodeFile(EpisodeFile episodeFile, bool newDownload =
|
||||
_externalNotificationProvider.OnRename(message, series);
|
||||
}
|
||||
|
||||
return true;
|
||||
return episodeFile;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
65
NzbDrone.Core/Providers/Metadata/MetadataBase.cs
Normal file
65
NzbDrone.Core/Providers/Metadata/MetadataBase.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Repository;
|
||||
using TvdbLib.Data;
|
||||
|
||||
namespace NzbDrone.Core.Providers.Metadata
|
||||
{
|
||||
public abstract class MetadataBase
|
||||
{
|
||||
protected readonly Logger _logger;
|
||||
protected readonly ConfigProvider _configProvider;
|
||||
protected readonly DiskProvider _diskProvider;
|
||||
protected readonly BannerProvider _bannerProvider;
|
||||
protected readonly EpisodeProvider _episodeProvider;
|
||||
|
||||
protected MetadataBase(ConfigProvider configProvider, DiskProvider diskProvider,
|
||||
BannerProvider bannerProvider, EpisodeProvider episodeProvider)
|
||||
{
|
||||
_configProvider = configProvider;
|
||||
_diskProvider = diskProvider;
|
||||
_bannerProvider = bannerProvider;
|
||||
_episodeProvider = episodeProvider;
|
||||
_logger = LogManager.GetLogger(GetType().ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name for the metabase provider
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates metadata for a series
|
||||
/// </summary>
|
||||
/// <param name = "series">The series to create the metadata for</param>
|
||||
/// <param name = "tvDbSeries">Series information from TheTvDb</param>
|
||||
public abstract void CreateForSeries(Series series, TvdbSeries tvDbSeries);
|
||||
|
||||
/// <summary>
|
||||
/// Creates metadata for the episode file
|
||||
/// </summary>
|
||||
/// <param name = "episodeFile">The episode file to create the metadata</param>
|
||||
/// <param name = "tvDbSeries">Series information from TheTvDb</param>
|
||||
public abstract void CreateForEpisodeFile(EpisodeFile episodeFile, TvdbSeries tvDbSeries);
|
||||
|
||||
/// <summary>
|
||||
/// Removes metadata for a series
|
||||
/// </summary>
|
||||
/// <param name = "series">The series to create the metadata for</param>
|
||||
public abstract void RemoveForSeries(Series series);
|
||||
|
||||
/// <summary>
|
||||
/// Removes metadata for the episode file
|
||||
/// </summary>
|
||||
/// <param name = "episodeFile">The episode file to create the metadata</param>
|
||||
public abstract void RemoveForEpisodeFile(EpisodeFile episodeFile);
|
||||
|
||||
public virtual string GetEpisodeGuideUrl(int seriesId)
|
||||
{
|
||||
return String.Format("http://www.thetvdb.com/api/{0}/series/{1}/all/en.zip", TvDbProvider.TVDB_APIKEY, seriesId);
|
||||
}
|
||||
}
|
||||
}
|
248
NzbDrone.Core/Providers/Metadata/Xbmc.cs
Normal file
248
NzbDrone.Core/Providers/Metadata/Xbmc.cs
Normal file
@ -0,0 +1,248 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Providers.Core;
|
||||
using NzbDrone.Core.Repository;
|
||||
using TvdbLib.Data;
|
||||
using TvdbLib.Data.Banner;
|
||||
|
||||
namespace NzbDrone.Core.Providers.Metadata
|
||||
{
|
||||
public class Xbmc : MetadataBase
|
||||
{
|
||||
protected readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public Xbmc(ConfigProvider configProvider, DiskProvider diskProvider, BannerProvider bannerProvider, EpisodeProvider episodeProvider)
|
||||
: base(configProvider, diskProvider, bannerProvider, episodeProvider)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "XBMC"; }
|
||||
}
|
||||
|
||||
public override void CreateForSeries(Series series, TvdbSeries tvDbSeries)
|
||||
{
|
||||
//Create tvshow.nfo, fanart.jpg, folder.jpg and season##.tbn
|
||||
var episodeGuideUrl = GetEpisodeGuideUrl(series.SeriesId);
|
||||
|
||||
_logger.Debug("Generating tvshow.nfo for: {0}", series.Title);
|
||||
var sb = new StringBuilder();
|
||||
var xws = new XmlWriterSettings();
|
||||
xws.OmitXmlDeclaration = true;
|
||||
xws.Indent = false;
|
||||
|
||||
using (var xw = XmlWriter.Create(sb, xws))
|
||||
{
|
||||
var tvShow = new XElement("tvshow");
|
||||
tvShow.Add(new XElement("title", tvDbSeries.SeriesName));
|
||||
tvShow.Add(new XElement("rating", tvDbSeries.Rating));
|
||||
tvShow.Add(new XElement("plot", tvDbSeries.Overview));
|
||||
tvShow.Add(new XElement("episodeguide", new XElement("url"), episodeGuideUrl));
|
||||
tvShow.Add(new XElement("episodeguideurl", episodeGuideUrl));
|
||||
tvShow.Add(new XElement("mpaa", tvDbSeries.ContentRating));
|
||||
tvShow.Add(new XElement("genre", tvDbSeries.GenreString));
|
||||
tvShow.Add(new XElement("premiered", tvDbSeries.FirstAired.ToString("yyyy-MM-dd")));
|
||||
tvShow.Add(new XElement("studio", tvDbSeries.Network));
|
||||
|
||||
foreach(var actor in tvDbSeries.TvdbActors)
|
||||
{
|
||||
tvShow.Add(new XElement("actor",
|
||||
new XElement("name", actor.Name),
|
||||
new XElement("role", actor.Role),
|
||||
new XElement("thumb", actor.ActorImage)
|
||||
));
|
||||
}
|
||||
|
||||
var doc = new XDocument(tvShow);
|
||||
doc.Save(xw);
|
||||
|
||||
_logger.Debug("Saving tvshow.nfo for {0}", series.Title);
|
||||
_diskProvider.WriteAllText(Path.Combine(series.Path, "tvshow.nfo"), doc.ToString());
|
||||
}
|
||||
|
||||
_logger.Debug("Downloading fanart for: {0}", series.Title);
|
||||
_bannerProvider.Download(tvDbSeries.FanartPath, Path.Combine(series.Path, "fanart.jpg"));
|
||||
|
||||
if (_configProvider.MetadataUseBanners)
|
||||
{
|
||||
_logger.Debug("Downloading series banner for: {0}", series.Title);
|
||||
_bannerProvider.Download(tvDbSeries.BannerPath, Path.Combine(series.Path, "folder.jpg"));
|
||||
|
||||
_logger.Debug("Downloading Season banners for {0}", series.Title);
|
||||
DownloadSeasonThumbnails(series, tvDbSeries, TvdbSeasonBanner.Type.seasonwide);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_logger.Debug("Downloading series thumbnail for: {0}", series.Title);
|
||||
_bannerProvider.Download(tvDbSeries.PosterPath, Path.Combine(series.Path, "folder.jpg"));
|
||||
|
||||
_logger.Debug("Downloading Season posters for {0}", series.Title);
|
||||
DownloadSeasonThumbnails(series, tvDbSeries, TvdbSeasonBanner.Type.season);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CreateForEpisodeFile(EpisodeFile episodeFile, TvdbSeries tvDbSeries)
|
||||
{
|
||||
//Create filename.tbn and filename.nfo
|
||||
var episodes = _episodeProvider.GetEpisodesByFileId(episodeFile.EpisodeFileId);
|
||||
|
||||
if (!episodes.Any())
|
||||
{
|
||||
_logger.Debug("No episodes where found for this episode file: {0}", episodeFile.EpisodeFileId);
|
||||
return;
|
||||
}
|
||||
|
||||
var episodeFileThumbnail = tvDbSeries.Episodes.FirstOrDefault(
|
||||
e =>
|
||||
e.SeasonNumber == episodeFile.SeasonNumber &&
|
||||
e.EpisodeNumber == episodes.First().EpisodeNumber);
|
||||
|
||||
if (episodeFileThumbnail == null || String.IsNullOrWhiteSpace(episodeFileThumbnail.BannerPath))
|
||||
{
|
||||
_logger.Debug("No thumbnail is available for this episode");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Debug("Downloading episode thumbnail for: {0}", episodeFile.EpisodeFileId);
|
||||
_bannerProvider.Download(episodeFileThumbnail.BannerPath, episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn"));
|
||||
|
||||
_logger.Debug("Generating filename.nfo for: {0}", episodeFile.EpisodeFileId);
|
||||
|
||||
var xmlResult = String.Empty;
|
||||
foreach (var episode in episodes)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var xws = new XmlWriterSettings();
|
||||
xws.OmitXmlDeclaration = true;
|
||||
xws.Indent = false;
|
||||
|
||||
using (var xw = XmlWriter.Create(sb, xws))
|
||||
{
|
||||
var doc = new XDocument();
|
||||
var tvdbEpisode = tvDbSeries.Episodes.FirstOrDefault(
|
||||
e =>
|
||||
e.Id == episode.TvDbEpisodeId);
|
||||
|
||||
if (tvdbEpisode == null)
|
||||
{
|
||||
_logger.Debug("Looking up by TvDbEpisodeId failed, trying to match via season/episode number combination");
|
||||
tvdbEpisode = tvDbSeries.Episodes.FirstOrDefault(
|
||||
e =>
|
||||
e.SeasonNumber == episode.SeasonNumber &&
|
||||
e.EpisodeNumber == episode.EpisodeNumber);
|
||||
}
|
||||
|
||||
if (tvdbEpisode == null)
|
||||
{
|
||||
_logger.Debug("Unable to find episode from TvDb - skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
var details = new XElement("episodedetails");
|
||||
details.Add(new XElement("title", tvdbEpisode.EpisodeName));
|
||||
details.Add(new XElement("season", tvdbEpisode.SeasonNumber));
|
||||
details.Add(new XElement("episode", tvdbEpisode.EpisodeNumber));
|
||||
details.Add(new XElement("aired", tvdbEpisode.FirstAired));
|
||||
details.Add(new XElement("plot", tvDbSeries.Overview));
|
||||
details.Add(new XElement("displayseason"));
|
||||
details.Add(new XElement("displayepisode"));
|
||||
details.Add(new XElement("thumb", "http://www.thetvdb.com/banners/" + tvdbEpisode.BannerPath));
|
||||
details.Add(new XElement("watched", "false"));
|
||||
details.Add(new XElement("credits", tvdbEpisode.Writer.First()));
|
||||
details.Add(new XElement("director", tvdbEpisode.Directors.First()));
|
||||
details.Add(new XElement("rating", tvDbSeries.Rating));
|
||||
|
||||
foreach(var actor in tvdbEpisode.GuestStars)
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(actor))
|
||||
continue;
|
||||
|
||||
details.Add(new XElement("actor",
|
||||
new XElement("name", actor)
|
||||
));
|
||||
}
|
||||
|
||||
foreach(var actor in tvDbSeries.TvdbActors)
|
||||
{
|
||||
details.Add(new XElement("actor",
|
||||
new XElement("name", actor.Name),
|
||||
new XElement("role", actor.Role),
|
||||
new XElement("thumb", actor.ActorImage)
|
||||
));
|
||||
}
|
||||
|
||||
doc.Add(details);
|
||||
doc.Save(xw);
|
||||
|
||||
xmlResult += doc.ToString();
|
||||
}
|
||||
}
|
||||
var filename = episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".nfo");
|
||||
_logger.Debug("Saving episodedetails to: {0}", filename);
|
||||
_diskProvider.WriteAllText(filename, xmlResult);
|
||||
}
|
||||
|
||||
public override void RemoveForSeries(Series series)
|
||||
{
|
||||
//Remove tvshow.nfo, fanart.jpg, folder.jpg and season##.tbn
|
||||
_logger.Debug("Deleting series metadata for: ", series.Title);
|
||||
|
||||
_diskProvider.DeleteFile(Path.Combine(series.Path, "tvshow.nfo"));
|
||||
_diskProvider.DeleteFile(Path.Combine(series.Path, "fanart.jpg"));
|
||||
_diskProvider.DeleteFile(Path.Combine(series.Path, "fanart.jpg"));
|
||||
|
||||
foreach (var file in _diskProvider.GetFiles(series.Path, SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
if (Path.GetExtension(file) != ".tbn")
|
||||
continue;
|
||||
|
||||
if (!Path.GetFileName(file).StartsWith("season"))
|
||||
continue;
|
||||
|
||||
_logger.Debug("Deleting season thumbnail: {0}", file);
|
||||
_diskProvider.DeleteFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveForEpisodeFile(EpisodeFile episodeFile)
|
||||
{
|
||||
//Remove filename.tbn and filename.nfo
|
||||
_logger.Debug("Deleting episode metadata for: {0}", episodeFile);
|
||||
|
||||
_diskProvider.DeleteFile(episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".nfo"));
|
||||
_diskProvider.DeleteFile(episodeFile.Path.Replace(Path.GetExtension(episodeFile.Path), ".tbn"));
|
||||
}
|
||||
|
||||
private void DownloadSeasonThumbnails(Series series, TvdbSeries tvDbSeries, TvdbSeasonBanner.Type bannerType)
|
||||
{
|
||||
var seasons = tvDbSeries.SeasonBanners.Where(s => s.BannerType == bannerType).Select(s => s.Season);
|
||||
|
||||
foreach (var season in seasons)
|
||||
{
|
||||
var banner = tvDbSeries.SeasonBanners.FirstOrDefault(b => b.BannerType == bannerType && b.Season == season);
|
||||
_logger.Debug("Downloading banner for Season: {0} Series: {1}", season, series.Title);
|
||||
|
||||
if (season == 0)
|
||||
{
|
||||
_bannerProvider.Download(banner.BannerPath,
|
||||
Path.Combine(series.Path, "season-specials.tbn"));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_bannerProvider.Download(banner.BannerPath,
|
||||
Path.Combine(series.Path, String.Format("season{0:00}.tbn", season)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
167
NzbDrone.Core/Providers/MetadataProvider.cs
Normal file
167
NzbDrone.Core/Providers/MetadataProvider.cs
Normal file
@ -0,0 +1,167 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Ninject;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Model;
|
||||
using NzbDrone.Core.Providers.ExternalNotification;
|
||||
using NzbDrone.Core.Providers.Metadata;
|
||||
using NzbDrone.Core.Repository;
|
||||
using PetaPoco;
|
||||
using TvdbLib.Data;
|
||||
|
||||
namespace NzbDrone.Core.Providers
|
||||
{
|
||||
public class MetadataProvider
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private readonly IDatabase _database;
|
||||
|
||||
private IEnumerable<MetadataBase> _metadataProviders;
|
||||
private readonly TvDbProvider _tvDbProvider;
|
||||
|
||||
[Inject]
|
||||
public MetadataProvider(IDatabase database, IEnumerable<MetadataBase> metadataProviders, TvDbProvider tvDbProvider)
|
||||
{
|
||||
_database = database;
|
||||
_metadataProviders = metadataProviders;
|
||||
_tvDbProvider = tvDbProvider;
|
||||
}
|
||||
|
||||
public MetadataProvider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual List<MetadataDefinition> All()
|
||||
{
|
||||
return _database.Fetch<MetadataDefinition>();
|
||||
}
|
||||
|
||||
public virtual void SaveSettings(MetadataDefinition settings)
|
||||
{
|
||||
if (settings.Id == 0)
|
||||
{
|
||||
Logger.Debug("Adding Metabase definition for {0}", settings.Name);
|
||||
_database.Insert(settings);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Logger.Debug("Updating Metabase definition for {0}", settings.Name);
|
||||
_database.Update(settings);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual MetadataDefinition GetSettings(Type type)
|
||||
{
|
||||
return _database.SingleOrDefault<MetadataDefinition>("WHERE MetadataProviderType = @0", type.ToString());
|
||||
}
|
||||
|
||||
public virtual IList<MetadataBase> GetEnabledMetabaseProviders()
|
||||
{
|
||||
var all = All();
|
||||
return _metadataProviders.Where(i => all.Exists(c => c.MetadataProviderType == i.GetType().ToString() && c.Enable)).ToList();
|
||||
}
|
||||
|
||||
public virtual void Initialize(IList<MetadataBase> metabaseProviders)
|
||||
{
|
||||
Logger.Debug("Initializing metabases. Count {0}", metabaseProviders.Count);
|
||||
|
||||
_metadataProviders = metabaseProviders;
|
||||
|
||||
var currentNotifiers = All();
|
||||
|
||||
foreach (var notificationProvider in metabaseProviders)
|
||||
{
|
||||
MetadataBase metadataProviderLocal = notificationProvider;
|
||||
if (!currentNotifiers.Exists(c => c.MetadataProviderType == metadataProviderLocal.GetType().ToString()))
|
||||
{
|
||||
var settings = new MetadataDefinition
|
||||
{
|
||||
Enable = false,
|
||||
MetadataProviderType = metadataProviderLocal.GetType().ToString(),
|
||||
Name = metadataProviderLocal.Name
|
||||
};
|
||||
|
||||
SaveSettings(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CreateForSeries(Series series)
|
||||
{
|
||||
var tvDbSeries = _tvDbProvider.GetSeries(series.SeriesId, false, true);
|
||||
|
||||
CreateForSeries(series, tvDbSeries);
|
||||
}
|
||||
|
||||
public virtual void CreateForSeries(Series series, TvdbSeries tvDbSeries)
|
||||
{
|
||||
foreach (var provider in _metadataProviders.Where(i => GetSettings(i.GetType()).Enable))
|
||||
{
|
||||
provider.CreateForSeries(series, tvDbSeries);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CreateForEpisodeFile(EpisodeFile episodeFile)
|
||||
{
|
||||
var tvDbSeries = _tvDbProvider.GetSeries(episodeFile.SeriesId, true, true);
|
||||
|
||||
CreateForEpisodeFile(episodeFile, tvDbSeries);
|
||||
}
|
||||
|
||||
public virtual void CreateForEpisodeFile(EpisodeFile episodeFile, TvdbSeries tvDbSeries)
|
||||
{
|
||||
foreach (var provider in _metadataProviders.Where(i => GetSettings(i.GetType()).Enable))
|
||||
{
|
||||
provider.CreateForEpisodeFile(episodeFile, tvDbSeries);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CreateForEpisodeFiles(List<EpisodeFile> episodeFiles)
|
||||
{
|
||||
var tvDbSeries = _tvDbProvider.GetSeries(episodeFiles.First().SeriesId, true, true);
|
||||
|
||||
foreach(var episodeFile in episodeFiles)
|
||||
{
|
||||
foreach (var provider in _metadataProviders.Where(i => GetSettings(i.GetType()).Enable))
|
||||
{
|
||||
provider.CreateForEpisodeFile(episodeFile, tvDbSeries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RemoveForSeries(Series series)
|
||||
{
|
||||
foreach (var provider in _metadataProviders.Where(i => GetSettings(i.GetType()).Enable))
|
||||
{
|
||||
provider.RemoveForSeries(series);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RemoveForEpisodeFile(EpisodeFile episodeFile)
|
||||
{
|
||||
foreach (var provider in _metadataProviders.Where(i => GetSettings(i.GetType()).Enable))
|
||||
{
|
||||
provider.RemoveForEpisodeFile(episodeFile);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RemoveForEpisodeFiles(List<EpisodeFile> episodeFiles)
|
||||
{
|
||||
foreach (var episodeFile in episodeFiles)
|
||||
{
|
||||
foreach (var provider in _metadataProviders.Where(i => GetSettings(i.GetType()).Enable))
|
||||
{
|
||||
provider.RemoveForEpisodeFile(episodeFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RenameForEpisodeFile(EpisodeFile episodeFile)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -16,14 +16,16 @@ public class PostDownloadProvider
|
||||
private readonly DiskProvider _diskProvider;
|
||||
private readonly DiskScanProvider _diskScanProvider;
|
||||
private readonly SeriesProvider _seriesProvider;
|
||||
private readonly MetadataProvider _metadataProvider;
|
||||
|
||||
[Inject]
|
||||
public PostDownloadProvider(DiskProvider diskProvider, DiskScanProvider diskScanProvider,
|
||||
SeriesProvider seriesProvider)
|
||||
SeriesProvider seriesProvider, MetadataProvider metadataProvider)
|
||||
{
|
||||
_diskProvider = diskProvider;
|
||||
_diskScanProvider = diskScanProvider;
|
||||
_seriesProvider = seriesProvider;
|
||||
_metadataProvider = metadataProvider;
|
||||
}
|
||||
|
||||
public PostDownloadProvider()
|
||||
@ -71,6 +73,9 @@ public virtual void ProcessDownload(DirectoryInfo subfolderInfo)
|
||||
var importedFiles = _diskScanProvider.Scan(series, subfolderInfo.FullName);
|
||||
importedFiles.ForEach(file => _diskScanProvider.MoveEpisodeFile(file, true));
|
||||
|
||||
//Create Metadata for all the episode files found
|
||||
_metadataProvider.CreateForEpisodeFiles(importedFiles);
|
||||
|
||||
//Delete the folder only if folder is small enough
|
||||
if (_diskProvider.GetDirectorySize(subfolderInfo.FullName) < Constants.IgnoreFileSize)
|
||||
{
|
||||
|
@ -20,17 +20,19 @@ public class SeriesProvider
|
||||
private readonly IDatabase _database;
|
||||
private readonly SceneMappingProvider _sceneNameMappingProvider;
|
||||
private readonly BannerProvider _bannerProvider;
|
||||
private readonly MetadataProvider _metadataProvider;
|
||||
private static readonly Regex TimeRegex = new Regex(@"^(?<time>\d+:?\d*)\W*(?<meridiem>am|pm)?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public SeriesProvider(IDatabase database, ConfigProvider configProviderProvider,
|
||||
TvDbProvider tvDbProviderProvider, SceneMappingProvider sceneNameMappingProvider,
|
||||
BannerProvider bannerProvider)
|
||||
BannerProvider bannerProvider, MetadataProvider metadataProvider)
|
||||
{
|
||||
_database = database;
|
||||
_configProvider = configProviderProvider;
|
||||
_tvDbProvider = tvDbProviderProvider;
|
||||
_sceneNameMappingProvider = sceneNameMappingProvider;
|
||||
_bannerProvider = bannerProvider;
|
||||
_metadataProvider = metadataProvider;
|
||||
}
|
||||
|
||||
public SeriesProvider()
|
||||
@ -86,7 +88,7 @@ public virtual bool IsMonitored(long id)
|
||||
|
||||
public virtual Series UpdateSeriesInfo(int seriesId)
|
||||
{
|
||||
var tvDbSeries = _tvDbProvider.GetSeries(seriesId, false);
|
||||
var tvDbSeries = _tvDbProvider.GetSeries(seriesId, false, true);
|
||||
var series = GetSeries(seriesId);
|
||||
|
||||
series.SeriesId = tvDbSeries.Id;
|
||||
@ -103,6 +105,8 @@ public virtual Series UpdateSeriesInfo(int seriesId)
|
||||
series.Network = tvDbSeries.Network;
|
||||
|
||||
UpdateSeries(series);
|
||||
_metadataProvider.CreateForSeries(series, tvDbSeries);
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace NzbDrone.Core.Providers
|
||||
public class TvDbProvider
|
||||
{
|
||||
private readonly EnvironmentProvider _environmentProvider;
|
||||
private const string TVDB_APIKEY = "5D2D188E86E07F4F";
|
||||
public const string TVDB_APIKEY = "5D2D188E86E07F4F";
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly TvdbHandler _handler;
|
||||
@ -44,13 +44,12 @@ public virtual IList<TvdbSearchResult> SearchSeries(string title)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual TvdbSeries GetSeries(int id, bool loadEpisodes)
|
||||
public virtual TvdbSeries GetSeries(int id, bool loadEpisodes, bool loadActors = false)
|
||||
{
|
||||
lock (_handler)
|
||||
{
|
||||
Logger.Debug("Fetching SeriesId'{0}' from tvdb", id);
|
||||
var result = _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, false, true, true);
|
||||
var result = _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, loadActors, true, true);
|
||||
|
||||
//Fix American Dad's scene gongshow
|
||||
if (result != null && result.Id == 73141)
|
||||
@ -86,6 +85,5 @@ public virtual TvdbSeries GetSeries(int id, bool loadEpisodes)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
17
NzbDrone.Core/Repository/MetadataDefinition.cs
Normal file
17
NzbDrone.Core/Repository/MetadataDefinition.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using PetaPoco;
|
||||
|
||||
namespace NzbDrone.Core.Repository
|
||||
{
|
||||
[TableName("MetadataDefinitions")]
|
||||
[PrimaryKey("Id", autoIncrement = true)]
|
||||
public class MetadataDefinition
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public bool Enable { get; set; }
|
||||
|
||||
public string MetadataProviderType { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
19
NzbDrone.Test.Common/NzbDrone.Test.Common.ncrunchproject
Normal file
19
NzbDrone.Test.Common/NzbDrone.Test.Common.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
19
NzbDrone.Test.Dummy/NzbDrone.Test.Dummy.ncrunchproject
Normal file
19
NzbDrone.Test.Dummy/NzbDrone.Test.Dummy.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
19
NzbDrone.Update.Test/NzbDrone.Update.Test.ncrunchproject
Normal file
19
NzbDrone.Update.Test/NzbDrone.Update.Test.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
19
NzbDrone.Update/NzbDrone.Update.ncrunchproject
Normal file
19
NzbDrone.Update/NzbDrone.Update.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
@ -31,17 +31,19 @@ public class SettingsController : Controller
|
||||
private readonly QualityTypeProvider _qualityTypeProvider;
|
||||
private readonly ConfigFileProvider _configFileProvider;
|
||||
private readonly NewznabProvider _newznabProvider;
|
||||
private readonly MetadataProvider _metadataProvider;
|
||||
|
||||
public SettingsController(ConfigProvider configProvider, IndexerProvider indexerProvider,
|
||||
QualityProvider qualityProvider, AutoConfigureProvider autoConfigureProvider,
|
||||
SeriesProvider seriesProvider, ExternalNotificationProvider externalNotificationProvider,
|
||||
QualityTypeProvider qualityTypeProvider,
|
||||
ConfigFileProvider configFileProvider, NewznabProvider newznabProvider)
|
||||
QualityProvider qualityProvider, AutoConfigureProvider autoConfigureProvider,
|
||||
SeriesProvider seriesProvider, ExternalNotificationProvider externalNotificationProvider,
|
||||
QualityTypeProvider qualityTypeProvider, ConfigFileProvider configFileProvider,
|
||||
NewznabProvider newznabProvider, MetadataProvider metadataProvider)
|
||||
{
|
||||
_externalNotificationProvider = externalNotificationProvider;
|
||||
_qualityTypeProvider = qualityTypeProvider;
|
||||
_configFileProvider = configFileProvider;
|
||||
_newznabProvider = newznabProvider;
|
||||
_metadataProvider = metadataProvider;
|
||||
_configProvider = configProvider;
|
||||
_indexerProvider = indexerProvider;
|
||||
_qualityProvider = qualityProvider;
|
||||
@ -207,6 +209,10 @@ public ActionResult Naming()
|
||||
model.SeparatorStyles = new SelectList(EpisodeSortingHelper.GetSeparatorStyles(), "Id", "Name");
|
||||
model.NumberStyles = new SelectList(EpisodeSortingHelper.GetNumberStyles(), "Id", "Name");
|
||||
model.MultiEpisodeStyles = new SelectList(EpisodeSortingHelper.GetMultiEpisodeStyles(), "Id", "Name");
|
||||
|
||||
//Metadata
|
||||
model.MetadataXbmcEnabled = _metadataProvider.GetSettings(typeof(Core.Providers.Metadata.Xbmc)).Enable;
|
||||
model.MetadataUseBanners = _configProvider.MetadataUseBanners;
|
||||
|
||||
return View(model);
|
||||
}
|
||||
@ -589,6 +595,14 @@ public JsonResult SaveNaming(EpisodeNamingModel data)
|
||||
_configProvider.SortingNumberStyle = data.NumberStyle;
|
||||
_configProvider.SortingMultiEpisodeStyle = data.MultiEpisodeStyle;
|
||||
|
||||
//Metadata
|
||||
_configProvider.MetadataUseBanners = data.MetadataUseBanners;
|
||||
|
||||
//Xbmc
|
||||
var xbmc = _metadataProvider.GetSettings(typeof(Core.Providers.Metadata.Xbmc));
|
||||
xbmc.Enable = data.MetadataXbmcEnabled;
|
||||
_metadataProvider.SaveSettings(xbmc);
|
||||
|
||||
return GetSuccessResult();
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,14 @@ public class EpisodeNamingModel
|
||||
[Description("How will multi-episode files be named?")]
|
||||
public int MultiEpisodeStyle { get; set; }
|
||||
|
||||
[DisplayName("XBMC")]
|
||||
[Description("Enable creating metadata for XBMC")]
|
||||
public bool MetadataXbmcEnabled { get; set; }
|
||||
|
||||
[DisplayName("Use Banners")]
|
||||
[Description("Use banners instead of posters?")]
|
||||
public bool MetadataUseBanners { get; set; }
|
||||
|
||||
public SelectList SeparatorStyles { get; set; }
|
||||
public SelectList NumberStyles { get; set; }
|
||||
public SelectList MultiEpisodeStyles { get; set; }
|
||||
|
@ -543,6 +543,12 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Views\System\Stats.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Settings\EpisodeNamingPartial.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Settings\MetadataPartial.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
19
NzbDrone.Web/NzbDrone.Web.ncrunchproject
Normal file
19
NzbDrone.Web/NzbDrone.Web.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
53
NzbDrone.Web/Views/Settings/EpisodeNamingPartial.cshtml
Normal file
53
NzbDrone.Web/Views/Settings/EpisodeNamingPartial.cshtml
Normal file
@ -0,0 +1,53 @@
|
||||
@using NzbDrone.Web.Helpers
|
||||
@model NzbDrone.Web.Models.EpisodeNamingModel
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<div class="settingsContainer">
|
||||
@Html.ValidationSummary(true, "Unable to save your settings. Please correct the errors and try again.")
|
||||
<label class="labelClass">@Html.LabelFor(m => m.SeriesName)
|
||||
<span class="small">@Html.DescriptionFor(m => m.SeriesName)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.SeriesName, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.EpisodeName)
|
||||
<span class="small">@Html.DescriptionFor(m => m.EpisodeName)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.EpisodeName, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.ReplaceSpaces)
|
||||
<span class="small">@Html.DescriptionFor(m => m.ReplaceSpaces)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.ReplaceSpaces, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.AppendQuality)
|
||||
<span class="small">@Html.DescriptionFor(m => m.AppendQuality)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.AppendQuality, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.SeasonFolders)
|
||||
<span class="small">@Html.DescriptionFor(m => m.SeasonFolders)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.SeasonFolders, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.SeasonFolderFormat)
|
||||
<span class="small">@Html.DescriptionFor(m => m.SeasonFolderFormat)</span>
|
||||
</label>
|
||||
@Html.TextBoxFor(m => m.SeasonFolderFormat, new { @class = "inputClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.SeparatorStyle)
|
||||
<span class="small">@Html.DescriptionFor(m => m.SeparatorStyle)</span>
|
||||
</label>
|
||||
@Html.DropDownListFor(m => m.SeparatorStyle, Model.SeparatorStyles, new { @class = "inputClass selectClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.NumberStyle)
|
||||
<span class="small">@Html.DescriptionFor(m => m.NumberStyle)</span>
|
||||
</label>
|
||||
@Html.DropDownListFor(m => m.NumberStyle, Model.NumberStyles, new { @class = "inputClass selectClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.MultiEpisodeStyle)
|
||||
<span class="small">@Html.DescriptionFor(m => m.MultiEpisodeStyle)</span>
|
||||
</label>
|
||||
@Html.DropDownListFor(m => m.MultiEpisodeStyle, Model.MultiEpisodeStyles, new { @class = "inputClass selectClass" })
|
||||
</div>
|
||||
<div id="examples">
|
||||
<div id="singleEpisodeExample">
|
||||
<b>Single Episode Example: </b><span class="result"></span>
|
||||
</div>
|
||||
<div id="multiEpisodeExample">
|
||||
<b>Multi-Episode Example: </b><span class="result"></span>
|
||||
</div>
|
||||
</div>
|
15
NzbDrone.Web/Views/Settings/MetadataPartial.cshtml
Normal file
15
NzbDrone.Web/Views/Settings/MetadataPartial.cshtml
Normal file
@ -0,0 +1,15 @@
|
||||
@using NzbDrone.Web.Helpers
|
||||
@model NzbDrone.Web.Models.EpisodeNamingModel
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<label class="labelClass">@Html.LabelFor(m => m.MetadataXbmcEnabled)
|
||||
<span class="small">@Html.DescriptionFor(m => m.MetadataXbmcEnabled)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.MetadataXbmcEnabled, new { @class = "inputClass checkClass" })
|
||||
|
||||
<label class="labelClass">@Html.LabelFor(m => m.MetadataUseBanners)
|
||||
<span class="small">@Html.DescriptionFor(m => m.MetadataUseBanners)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.MetadataUseBanners, new { @class = "inputClass checkClass" })
|
@ -20,51 +20,15 @@
|
||||
<div id="stylized">
|
||||
@using (Html.BeginForm("SaveNaming", "Settings", FormMethod.Post, new { id = "NamingForm", name = "NamingForm", @class = "settingsForm" }))
|
||||
{
|
||||
<div class="settingsContainer">
|
||||
@Html.ValidationSummary(true, "Unable to save your settings. Please correct the errors and try again.")
|
||||
<label class="labelClass">@Html.LabelFor(m => m.SeriesName)
|
||||
<span class="small">@Html.DescriptionFor(m => m.SeriesName)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.SeriesName, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.EpisodeName)
|
||||
<span class="small">@Html.DescriptionFor(m => m.EpisodeName)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.EpisodeName, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.ReplaceSpaces)
|
||||
<span class="small">@Html.DescriptionFor(m => m.ReplaceSpaces)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.ReplaceSpaces, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.AppendQuality)
|
||||
<span class="small">@Html.DescriptionFor(m => m.AppendQuality)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.AppendQuality, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.SeasonFolders)
|
||||
<span class="small">@Html.DescriptionFor(m => m.SeasonFolders)</span>
|
||||
</label>
|
||||
@Html.CheckBoxFor(m => m.SeasonFolders, new { @class = "inputClass checkClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.SeasonFolderFormat)
|
||||
<span class="small">@Html.DescriptionFor(m => m.SeasonFolderFormat)</span>
|
||||
</label>
|
||||
@Html.TextBoxFor(m => m.SeasonFolderFormat, new { @class = "inputClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.SeparatorStyle)
|
||||
<span class="small">@Html.DescriptionFor(m => m.SeparatorStyle)</span>
|
||||
</label>
|
||||
@Html.DropDownListFor(m => m.SeparatorStyle, Model.SeparatorStyles, new { @class = "inputClass selectClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.NumberStyle)
|
||||
<span class="small">@Html.DescriptionFor(m => m.NumberStyle)</span>
|
||||
</label>
|
||||
@Html.DropDownListFor(m => m.NumberStyle, Model.NumberStyles, new { @class = "inputClass selectClass" })
|
||||
<label class="labelClass">@Html.LabelFor(m => m.MultiEpisodeStyle)
|
||||
<span class="small">@Html.DescriptionFor(m => m.MultiEpisodeStyle)</span>
|
||||
</label>
|
||||
@Html.DropDownListFor(m => m.MultiEpisodeStyle, Model.MultiEpisodeStyles, new { @class = "inputClass selectClass" })
|
||||
</div>
|
||||
<div id="examples">
|
||||
<div id="singleEpisodeExample">
|
||||
<b>Single Episode Example: </b><span class="result"></span>
|
||||
<div class="jquery-accordion">
|
||||
<h3><a href="#">Episode Naming</a></h3>
|
||||
<div id="episodeNamingContainer">
|
||||
@{Html.RenderPartial("EpisodeNamingPartial", Model);}
|
||||
</div>
|
||||
<div id="multiEpisodeExample">
|
||||
<b>Multi-Episode Example: </b><span class="result"></span>
|
||||
|
||||
<h3><a href="#">Metadata</a></h3>
|
||||
<div id="metadataContainer">
|
||||
@{Html.RenderPartial("MetaDataPartial", Model);}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
<SolutionConfiguration>
|
||||
<FileVersion>0</FileVersion>
|
||||
<AutoEnableOnStartup>Default</AutoEnableOnStartup>
|
||||
<FileVersion>1</FileVersion>
|
||||
<AutoEnableOnStartup>True</AutoEnableOnStartup>
|
||||
<AllowParallelTestExecution>false</AllowParallelTestExecution>
|
||||
<FrameworkUtilisationTypeForNUnit>UseDynamicAnalysis</FrameworkUtilisationTypeForNUnit>
|
||||
<FrameworkUtilisationTypeForGallio>UseStaticAnalysis</FrameworkUtilisationTypeForGallio>
|
||||
<FrameworkUtilisationTypeForMSpec>UseStaticAnalysis</FrameworkUtilisationTypeForMSpec>
|
||||
<FrameworkUtilisationTypeForMSTest>UseStaticAnalysis</FrameworkUtilisationTypeForMSTest>
|
||||
<EngineModes>Run all tests automatically:BFRydWU=;Run all tests manually:BUZhbHNl;Run impacted tests automatically, others manually (experimental!):CklzSW1wYWN0ZWQ=;Run pinned tests automatically, others manually:CElzUGlubmVk</EngineModes>
|
||||
<MetricsExclusionList>
|
||||
</MetricsExclusionList>
|
||||
</SolutionConfiguration>
|
19
NzbDrone/NzbDrone.ncrunchproject
Normal file
19
NzbDrone/NzbDrone.ncrunchproject
Normal file
@ -0,0 +1,19 @@
|
||||
<ProjectConfiguration>
|
||||
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
|
||||
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
|
||||
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
|
||||
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
|
||||
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
|
||||
<IgnoreThisComponentCompletely>false</IgnoreThisComponentCompletely>
|
||||
<RunPreBuildEvents>false</RunPreBuildEvents>
|
||||
<RunPostBuildEvents>false</RunPostBuildEvents>
|
||||
<PreviouslyBuiltSuccessfully>true</PreviouslyBuiltSuccessfully>
|
||||
<InstrumentAssembly>true</InstrumentAssembly>
|
||||
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
|
||||
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
|
||||
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
|
||||
<DefaultTestTimeout>60000</DefaultTestTimeout>
|
||||
<UseBuildConfiguration />
|
||||
<ProxyProcessPath />
|
||||
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
|
||||
</ProjectConfiguration>
|
Loading…
Reference in New Issue
Block a user