You've already forked Sonarr
							
							
				mirror of
				https://github.com/Sonarr/Sonarr.git
				synced 2025-10-31 00:07:55 +02:00 
			
		
		
		
	fixed diskscan
removed all stored status fields from episode
This commit is contained in:
		| @@ -2,6 +2,7 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using NzbDrone.Api.Extensions; | ||||
| using NzbDrone.Common.Composition; | ||||
| using NzbDrone.Common.Messaging; | ||||
|  | ||||
| namespace NzbDrone.Api.Commands | ||||
| @@ -9,20 +10,22 @@ namespace NzbDrone.Api.Commands | ||||
|     public class CommandModule : NzbDroneRestModule<CommandResource> | ||||
|     { | ||||
|         private readonly IMessageAggregator _messageAggregator; | ||||
|         private readonly IEnumerable<ICommand> _commands; | ||||
|         private readonly IContainer _container; | ||||
|  | ||||
|         public CommandModule(IMessageAggregator messageAggregator, IEnumerable<ICommand> commands) | ||||
|         public CommandModule(IMessageAggregator messageAggregator, IContainer container) | ||||
|         { | ||||
|             _messageAggregator = messageAggregator; | ||||
|             _commands = commands; | ||||
|             _container = container; | ||||
|  | ||||
|             CreateResource = RunCommand; | ||||
|         } | ||||
|  | ||||
|         private CommandResource RunCommand(CommandResource resource) | ||||
|         { | ||||
|             var commandType = _commands.Single(c => c.GetType().Name.Replace("Command", "").Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase)) | ||||
|                                        .GetType(); | ||||
|             var commandType = | ||||
|                 _container.GetImplementations(typeof(ICommand)) | ||||
|                           .Single(c => c.Name.Replace("Command", "") | ||||
|                                .Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase)); | ||||
|  | ||||
|  | ||||
|             var command = Request.Body.FromJson<ICommand>(commandType); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using TinyIoC; | ||||
|  | ||||
| namespace NzbDrone.Common.Composition | ||||
| @@ -7,10 +8,12 @@ namespace NzbDrone.Common.Composition | ||||
|     public class Container : IContainer | ||||
|     { | ||||
|         private readonly TinyIoCContainer _container; | ||||
|         private readonly List<Type> _loadedTypes; | ||||
|  | ||||
|         public Container(TinyIoCContainer container) | ||||
|         public Container(TinyIoCContainer container, List<Type> loadedTypes) | ||||
|         { | ||||
|             _container = container; | ||||
|             _loadedTypes = loadedTypes; | ||||
|             _container.Register<IContainer>(this); | ||||
|         } | ||||
|  | ||||
| @@ -92,5 +95,15 @@ namespace NzbDrone.Common.Composition | ||||
|         { | ||||
|             return _container.CanResolve(type); | ||||
|         } | ||||
|  | ||||
|         public IEnumerable<Type> GetImplementations(Type contractType) | ||||
|         { | ||||
|             return _loadedTypes | ||||
|                 .Where(implementation => | ||||
|                        contractType.IsAssignableFrom(implementation) && | ||||
|                        !implementation.IsInterface && | ||||
|                        !implementation.IsAbstract | ||||
|                 ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -18,8 +18,6 @@ namespace NzbDrone.Common.Composition | ||||
|  | ||||
|         protected ContainerBuilderBase(params string[] assemblies) | ||||
|         { | ||||
|             Container = new Container(new TinyIoCContainer()); | ||||
|  | ||||
|             _loadedTypes = new List<Type>(); | ||||
|  | ||||
|             foreach (var assembly in assemblies) | ||||
| @@ -27,6 +25,7 @@ namespace NzbDrone.Common.Composition | ||||
|                 _loadedTypes.AddRange(Assembly.Load(assembly).GetTypes()); | ||||
|             } | ||||
|  | ||||
|             Container = new Container(new TinyIoCContainer(), _loadedTypes); | ||||
|             AutoRegisterInterfaces(); | ||||
|         } | ||||
|  | ||||
| @@ -52,7 +51,7 @@ namespace NzbDrone.Common.Composition | ||||
|  | ||||
|         private void AutoRegisterImplementations(Type contractType) | ||||
|         { | ||||
|             var implementations = GetImplementations(contractType).Where(c => !c.IsGenericTypeDefinition).ToList(); | ||||
|             var implementations = Container.GetImplementations(contractType).Where(c => !c.IsGenericTypeDefinition).ToList(); | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -84,14 +83,5 @@ namespace NzbDrone.Common.Composition | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private IEnumerable<Type> GetImplementations(Type contractType) | ||||
|         { | ||||
|             return _loadedTypes | ||||
|                 .Where(implementation => | ||||
|                        contractType.IsAssignableFrom(implementation) && | ||||
|                        !implementation.IsInterface && | ||||
|                        !implementation.IsAbstract | ||||
|                 ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -26,5 +26,7 @@ namespace NzbDrone.Common.Composition | ||||
|         void Register(Type registrationType, object instance); | ||||
|         void RegisterAll(Type registrationType, IEnumerable<Type> implementationList); | ||||
|         bool IsTypeRegistered(Type type); | ||||
|  | ||||
|         IEnumerable<Type> GetImplementations(Type contractType); | ||||
|     } | ||||
| } | ||||
| @@ -34,8 +34,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests | ||||
|             firstFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, true), DateAdded = DateTime.Now }; | ||||
|             secondFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, true), DateAdded = DateTime.Now }; | ||||
|  | ||||
|             var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = null } }; | ||||
|             var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = secondFile }, new Episode { EpisodeFile = null } }; | ||||
|             var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } }; | ||||
|             var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = secondFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } }; | ||||
|  | ||||
|             var fakeSeries = Builder<Series>.CreateNew() | ||||
|                          .With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p }) | ||||
| @@ -66,6 +66,13 @@ namespace NzbDrone.Core.Test.DecisionEngineTests | ||||
|             secondFile.Quality = new QualityModel(Quality.SDTV); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_return_true_if_episode_has_no_existing_file() | ||||
|         { | ||||
|             parseResultSingle.Episodes.ForEach(c => c.EpisodeFileId = 0); | ||||
|             _upgradeDisk.IsSatisfiedBy(parseResultSingle).Should().BeTrue(); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_return_true_if_single_episode_doesnt_exist_on_disk() | ||||
|         { | ||||
|   | ||||
| @@ -11,79 +11,15 @@ using NzbDrone.Core.Test.Framework; | ||||
| namespace NzbDrone.Core.Test | ||||
| { | ||||
|     [TestFixture] | ||||
|      | ||||
|  | ||||
|     public class EpisodeStatusTest : CoreTest | ||||
|     { | ||||
|         [TestCase(1, false, false, EpisodeStatuses.NotAired)] | ||||
|         [TestCase(-2, false, false, EpisodeStatuses.Missing)] | ||||
|         [TestCase(0, false, false, EpisodeStatuses.AirsToday)] | ||||
|         [TestCase(1, true, false, EpisodeStatuses.Ready)] | ||||
|         public void no_grab_date(int offsetDays, bool hasEpisodes, bool ignored, EpisodeStatuses status) | ||||
|         { | ||||
|             Episode episode = Builder<Episode>.CreateNew() | ||||
|                 .With(e => e.AirDate = DateTime.Now.AddDays(offsetDays)) | ||||
|                 .With(e => e.Ignored = ignored) | ||||
|                 .With(e => e.GrabDate = null) | ||||
|                 .Build(); | ||||
|  | ||||
|             if (hasEpisodes) | ||||
|             { | ||||
|                 episode.EpisodeFile = new EpisodeFile(); | ||||
|             } | ||||
|  | ||||
|             episode.Status.Should().Be(status); | ||||
|         } | ||||
|  | ||||
|         [TestCase(1, false, false, EpisodeStatuses.Missing)] | ||||
|         [TestCase(-2, false, false, EpisodeStatuses.Missing)] | ||||
|         [TestCase(1, true, false, EpisodeStatuses.Ready)] | ||||
|         public void old_grab_date(int offsetDays, bool hasEpisodes, bool ignored, | ||||
|                                                  EpisodeStatuses status) | ||||
|         { | ||||
|             Episode episode = Builder<Episode>.CreateNew() | ||||
|                .With(e => e.Ignored = ignored) | ||||
|                 .With(e => e.GrabDate = DateTime.Now.AddDays(-2).AddHours(-1)) | ||||
|                 .With(e => e.AirDate = DateTime.Today.AddDays(-2)) | ||||
|                 .Build(); | ||||
|  | ||||
|             if (hasEpisodes) | ||||
|             { | ||||
|                 episode.EpisodeFile = new EpisodeFile(); | ||||
|             } | ||||
|  | ||||
|             episode.Status.Should().Be(status); | ||||
|         } | ||||
|  | ||||
|         [TestCase(1, false, false, EpisodeStatuses.Downloading)] | ||||
|         [TestCase(-2, false, false, EpisodeStatuses.Downloading)] | ||||
|         [TestCase(1, true, false, EpisodeStatuses.Ready)] | ||||
|         [TestCase(1, true, true, EpisodeStatuses.Ready)] | ||||
|         [TestCase(1, false, true, EpisodeStatuses.Downloading)] | ||||
|         public void recent_grab_date(int offsetDays, bool hasEpisodes, bool ignored, | ||||
|                                                     EpisodeStatuses status) | ||||
|         { | ||||
|             Episode episode = Builder<Episode>.CreateNew() | ||||
|             .With(e => e.AirDate = DateTime.Now.AddDays(offsetDays)) | ||||
|                 .With(e => e.Ignored = ignored) | ||||
|                 .With(e => e.GrabDate = DateTime.Now.AddHours(22)) | ||||
|                 .Build(); | ||||
|  | ||||
|             if (hasEpisodes) | ||||
|             { | ||||
|                 episode.EpisodeFile = new EpisodeFile(); | ||||
|             } | ||||
|  | ||||
|             episode.Status.Should().Be(status); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         [TestCase(1, true, true, EpisodeStatuses.Ready)] | ||||
|         public void ignored_episode(int offsetDays, bool ignored, bool hasEpisodes, EpisodeStatuses status) | ||||
|         { | ||||
|             Episode episode = Builder<Episode>.CreateNew() | ||||
|                 .With(e => e.AirDate = DateTime.Now.AddDays(offsetDays)) | ||||
|                 .With(e => e.Ignored = ignored) | ||||
|                 .With(e => e.GrabDate = null) | ||||
|                 .Build(); | ||||
|  | ||||
|             if (hasEpisodes) | ||||
| @@ -101,33 +37,11 @@ namespace NzbDrone.Core.Test | ||||
|             Episode episode = Builder<Episode>.CreateNew() | ||||
|                 .With(e => e.AirDate = DateTime.Now.AddDays(20)) | ||||
|                 .With(e => e.Ignored = false) | ||||
|                 .With(e => e.GrabDate = null) | ||||
|                 .With(e => e.EpisodeFileId = 0) | ||||
|                 .Build(); | ||||
|  | ||||
|  | ||||
|             episode.Status.Should().Be(EpisodeStatuses.NotAired); | ||||
|         } | ||||
|  | ||||
|         [TestCase(false, false, EpisodeStatuses.Failed, PostDownloadStatusType.Failed)] | ||||
|         [TestCase(false, false, EpisodeStatuses.Unpacking, PostDownloadStatusType.Unpacking)] | ||||
|         [TestCase(true, false, EpisodeStatuses.Ready, PostDownloadStatusType.Failed)] | ||||
|         [TestCase(true, true, EpisodeStatuses.Ready, PostDownloadStatusType.Unpacking)] | ||||
|         public void episode_downloaded_post_download_status_is_used(bool hasEpisodes, bool ignored, | ||||
|                                                     EpisodeStatuses status, PostDownloadStatusType postDownloadStatus) | ||||
|         { | ||||
|             Episode episode = Builder<Episode>.CreateNew() | ||||
|                 .With(e => e.Ignored = ignored) | ||||
|                 .With(e => e.GrabDate = DateTime.Now.AddHours(22)) | ||||
|                 .With(e => e.PostDownloadStatus = postDownloadStatus) | ||||
|                 .Build(); | ||||
|  | ||||
|             if (hasEpisodes) | ||||
|             { | ||||
|                 episode.EpisodeFile = new EpisodeFile(); | ||||
|             } | ||||
|  | ||||
|             episode.Status.Should().Be(status); | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -5,13 +5,14 @@ using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.MediaFiles; | ||||
| using NzbDrone.Core.MediaFiles.Commands; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Core.Tv; | ||||
| using System.Linq; | ||||
| 
 | ||||
| namespace NzbDrone.Core.Test.MediaFileTests | ||||
| { | ||||
|     public class GhostFileCleanupFixture : CoreTest<GhostFileCleanupService> | ||||
|     public class MediaFileTableCleanupServiceFixture : CoreTest<MediaFileTableCleanupService> | ||||
|     { | ||||
| 
 | ||||
|         private void GiveEpisodeFiles(IEnumerable<EpisodeFile> episodeFiles) | ||||
| @@ -30,6 +31,10 @@ namespace NzbDrone.Core.Test.MediaFileTests | ||||
|             Mocker.GetMock<IDiskProvider>() | ||||
|              .Setup(e => e.FileExists(It.Is<String>(c => c != DeletedPath))) | ||||
|              .Returns(true); | ||||
| 
 | ||||
|             Mocker.GetMock<IEpisodeService>() | ||||
|             .Setup(c => c.GetEpisodesByFileId(It.IsAny<int>())) | ||||
|             .Returns(new List<Episode> { new Episode() }); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
| @@ -40,7 +45,7 @@ namespace NzbDrone.Core.Test.MediaFileTests | ||||
| 
 | ||||
|             GiveEpisodeFiles(episodeFiles); | ||||
| 
 | ||||
|             Subject.RemoveNonExistingFiles(0); | ||||
|             Subject.Execute(new CleanMediaFileDb(0)); | ||||
| 
 | ||||
|             Mocker.GetMock<IEpisodeService>().Verify(c => c.UpdateEpisode(It.IsAny<Episode>()), Times.Never()); | ||||
|         } | ||||
| @@ -55,10 +60,33 @@ namespace NzbDrone.Core.Test.MediaFileTests | ||||
| 
 | ||||
|             GiveEpisodeFiles(episodeFiles); | ||||
| 
 | ||||
|             Subject.RemoveNonExistingFiles(0); | ||||
|             Subject.Execute(new CleanMediaFileDb(0)); | ||||
| 
 | ||||
|             Mocker.GetMock<IMediaFileService>().Verify(c => c.Delete(It.Is<EpisodeFile>(e => e.Path == DeletedPath)), Times.Exactly(2)); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void should_delete_files_that_dont_belong_to_any_episodes() | ||||
|         { | ||||
|             var episodeFiles = Builder<EpisodeFile>.CreateListOfSize(10) | ||||
|                                 .Random(10) | ||||
|                                 .With(c => c.Path = "ExistingPath") | ||||
|                                 .Build(); | ||||
| 
 | ||||
|             GiveEpisodeFiles(episodeFiles); | ||||
|             GivenFilesAreNotAttachedToEpisode(); | ||||
| 
 | ||||
|             Subject.Execute(new CleanMediaFileDb(0)); | ||||
| 
 | ||||
|             Mocker.GetMock<IMediaFileService>().Verify(c => c.Delete(It.IsAny<EpisodeFile>()), Times.Exactly(10)); | ||||
|         } | ||||
| 
 | ||||
|         private void GivenFilesAreNotAttachedToEpisode() | ||||
|         { | ||||
|             Mocker.GetMock<IEpisodeService>() | ||||
|                   .Setup(c => c.GetEpisodesByFileId(It.IsAny<int>())) | ||||
|                   .Returns(new List<Episode>()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -142,7 +142,7 @@ | ||||
|     <Compile Include="DecisionEngineTests\LanguageSpecificationFixture.cs" /> | ||||
|     <Compile Include="JobTests\TestJobs.cs" /> | ||||
|     <Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" /> | ||||
|     <Compile Include="MediaFileTests\GhostFileCleanupFixture.cs" /> | ||||
|     <Compile Include="MediaFileTests\MediaFileTableCleanupServiceFixture.cs" /> | ||||
|     <Compile Include="MediaFileTests\MediaFileRepositoryFixture.cs" /> | ||||
|     <Compile Include="MediaFileTests\EpisodeFileMoverFixture.cs" /> | ||||
|     <Compile Include="MetadataSourceTests\TracktProxyFixture.cs" /> | ||||
| @@ -160,6 +160,7 @@ | ||||
|     <Compile Include="ProviderTests\RecycleBinProviderTests\DeleteFileFixture.cs" /> | ||||
|     <Compile Include="ProviderTests\RecycleBinProviderTests\DeleteDirectoryFixture.cs" /> | ||||
|     <Compile Include="ProviderTests\PlexProviderTest.cs" /> | ||||
|     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesRepositoryReadFixture.cs" /> | ||||
|     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesWithoutFilesFixture.cs" /> | ||||
|     <Compile Include="TvTests\EpisodeRepositoryTests\EpisodesBetweenDatesFixture.cs" /> | ||||
|     <Compile Include="TvTests\SeasonProviderTest.cs" /> | ||||
|   | ||||
| @@ -4,6 +4,7 @@ using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.MediaFiles; | ||||
| using NzbDrone.Core.Providers; | ||||
|  | ||||
| using NzbDrone.Core.Test.Framework; | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| @@ -23,7 +22,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests | ||||
|  | ||||
|         private long _fileSize = 80.Megabytes(); | ||||
|         private Series _fakeSeries; | ||||
|         private List<Episode> _fakeEpisodes; | ||||
|         private Episode[] _fakeEpisodes; | ||||
|         private Episode _fakeEpisode; | ||||
|  | ||||
|         [SetUp] | ||||
| @@ -35,14 +34,16 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests | ||||
|  | ||||
|             _fakeEpisode = Builder<Episode> | ||||
|                     .CreateNew() | ||||
|                     .With(c => c.EpisodeFileId = 0) | ||||
|                     .Build(); | ||||
|  | ||||
|  | ||||
|             _fakeEpisodes = Builder<Episode>.CreateListOfSize(2) | ||||
|                                         .All() | ||||
|                                         .With(c => c.SeasonNumber = 3) | ||||
|                                         .With(c => c.EpisodeFileId = 1) | ||||
|                                         .With(e => e.EpisodeFile = new EpisodeFile()) | ||||
|                                         .BuildList(); | ||||
|                                         .BuildList().ToArray(); | ||||
|  | ||||
|             GivenNewFile(); | ||||
|  | ||||
| @@ -69,8 +70,20 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests | ||||
|         } | ||||
|  | ||||
|  | ||||
|         private void GivenEpisodes(IEnumerable<Episode> episodes, QualityModel quality) | ||||
|         private void GivenEpisodes(Episode[] episodes, QualityModel quality) | ||||
|         { | ||||
|             foreach (var episode in episodes) | ||||
|             { | ||||
|                 if (episode.EpisodeFile == null) | ||||
|                 { | ||||
|                     episode.EpisodeFileId = 0; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     episode.EpisodeFileId = episode.EpisodeFile.Value.Id; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             Mocker.GetMock<IParsingService>() | ||||
|                   .Setup(c => c.GetEpisodes(It.IsAny<string>(), It.IsAny<Series>())) | ||||
|                   .Returns(new LocalEpisode | ||||
| @@ -102,6 +115,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests | ||||
|         public void import_new_file_with_same_quality_should_succeed() | ||||
|         { | ||||
|             _fakeEpisode.EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.SDTV) }; | ||||
|  | ||||
|             GivenEpisodes(new[] { _fakeEpisode }, new QualityModel(Quality.SDTV)); | ||||
|  | ||||
|             var result = Subject.ImportFile(_fakeSeries, "file.ext"); | ||||
| @@ -112,6 +126,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests | ||||
|         public void import_new_file_with_better_quality_should_succeed() | ||||
|         { | ||||
|             _fakeEpisode.EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.SDTV) }; | ||||
|  | ||||
|             GivenEpisodes(new[] { _fakeEpisode }, new QualityModel(Quality.HDTV1080p)); | ||||
|  | ||||
|             var result = Subject.ImportFile(_fakeSeries, "file.ext"); | ||||
| @@ -121,7 +136,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests | ||||
|         [Test] | ||||
|         public void import_new_file_episode_has_better_quality_should_skip() | ||||
|         { | ||||
|             _fakeEpisode.EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p) }; | ||||
|             _fakeEpisode.EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p), Id = 1 }; | ||||
|  | ||||
|             GivenEpisodes(new[] { _fakeEpisode }, new QualityModel(Quality.SDTV)); | ||||
|  | ||||
|             var result = Subject.ImportFile(_fakeSeries, "file.ext"); | ||||
| @@ -158,7 +174,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests | ||||
|         [Test] | ||||
|         public void import_file_with_no_episode_in_db_should_skip() | ||||
|         { | ||||
|             GivenEpisodes(new List<Episode>(), new QualityModel()); | ||||
|             GivenEpisodes(new Episode[0], new QualityModel()); | ||||
|  | ||||
|             var result = Subject.ImportFile(_fakeSeries, "file.ext"); | ||||
|  | ||||
| @@ -185,8 +201,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests | ||||
|         [Test] | ||||
|         public void skip_import_new_multi_part_file_episode_existing_has_better_quality() | ||||
|         { | ||||
|             _fakeEpisodes[0].EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p) }; | ||||
|             _fakeEpisodes[1].EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p) }; | ||||
|             _fakeEpisodes[0].EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p), Id = 1 }; | ||||
|             _fakeEpisodes[1].EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p), Id = 1 }; | ||||
|  | ||||
|             GivenEpisodes(_fakeEpisodes, new QualityModel(Quality.SDTV)); | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,4 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| using NUnit.Framework; | ||||
|   | ||||
| @@ -0,0 +1,45 @@ | ||||
| using System; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Core.MediaFiles; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class EpisodesRepositoryReadFixture : DbTest<EpisodeRepository, Episode> | ||||
|     { | ||||
|         private Series series; | ||||
|  | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             series = Builder<Series>.CreateNew() | ||||
|                                         .With(s => s.Runtime = 30) | ||||
|                                         .BuildNew(); | ||||
|  | ||||
|             Db.Insert(series); | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void should_get_episodes_by_file() | ||||
|         { | ||||
|             var episodeFile = Builder<EpisodeFile>.CreateNew().BuildNew(); | ||||
|  | ||||
|             Db.Insert(episodeFile); | ||||
|  | ||||
|             var episode = Builder<Episode>.CreateListOfSize(2) | ||||
|                                         .All() | ||||
|                                         .With(e => e.SeriesId = series.Id) | ||||
|                                         .With(e => e.EpisodeFileId = episodeFile.Id) | ||||
|                                         .BuildListOfNew(); | ||||
|  | ||||
|             Db.InsertMany(episode); | ||||
|  | ||||
|             var episodes = Subject.GetEpisodeByFileId(episodeFile.Id); | ||||
|             episodes.Should().HaveCount(2); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,9 +1,4 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using FizzWare.NBuilder; | ||||
| using FizzWare.NBuilder; | ||||
| using FluentAssertions; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Core.Datastore; | ||||
|   | ||||
| @@ -59,8 +59,6 @@ namespace NzbDrone.Core.Datastore.Migration | ||||
|                 .WithColumn("Ignored").AsBoolean().Nullable() | ||||
|                 .WithColumn("EpisodeFileId").AsInt32().Nullable() | ||||
|                 .WithColumn("AirDate").AsDateTime().Nullable() | ||||
|                 .WithColumn("GrabDate").AsDateTime().Nullable() | ||||
|                 .WithColumn("PostDownloadStatus").AsInt32().Nullable() | ||||
|                 .WithColumn("AbsoluteEpisodeNumber").AsInt32().Nullable() | ||||
|                 .WithColumn("SceneAbsoluteEpisodeNumber").AsInt32().Nullable() | ||||
|                 .WithColumn("SceneSeasonNumber").AsInt32().Nullable() | ||||
|   | ||||
| @@ -14,7 +14,7 @@ namespace NzbDrone.Core.Datastore | ||||
|         { | ||||
|             return relationshipBuilder.For(portalExpression.GetMemberName()) | ||||
|                                 .LazyLoad((db, parent) => db.Query<TChild>() | ||||
|                                 .Single(c => c.Id == childIdSelector(parent))); | ||||
|                                 .SingleOrDefault(c => c.Id == childIdSelector(parent))); | ||||
|  | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -56,9 +56,12 @@ namespace NzbDrone.Core.Datastore | ||||
|  | ||||
|             Mapper.Entity<Episode>().RegisterModel("Episodes") | ||||
|                   .Ignore(e => e.SeriesTitle) | ||||
|                   .Relationships.AutoMapICollectionOrComplexProperties(); | ||||
|                   .Relationship() | ||||
|                   .HasOne(episode => episode.EpisodeFile, episode => episode.EpisodeFileId); | ||||
|             //.Relationships.AutoMapICollectionOrComplexProperties(); | ||||
|  | ||||
|             Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles"); | ||||
|             Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles") | ||||
|                   .Relationships.AutoMapICollectionOrComplexProperties(); | ||||
|  | ||||
|             Mapper.Entity<QualityProfile>().RegisterModel("QualityProfiles"); | ||||
|  | ||||
|   | ||||
| @@ -26,7 +26,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications | ||||
|  | ||||
|         public virtual bool IsSatisfiedBy(RemoteEpisode subject) | ||||
|         { | ||||
|             foreach (var file in subject.Episodes.Select(c => c.EpisodeFile).Where(c => c != null)) | ||||
|             foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value)) | ||||
|             { | ||||
|                 _logger.Trace("Comparing file quality with report. Existing file is {0}", file.Quality); | ||||
|  | ||||
|   | ||||
| @@ -69,8 +69,12 @@ namespace NzbDrone.Core.Jobs | ||||
|  | ||||
|         public void HandleAsync(CommandExecutedEvent message) | ||||
|         { | ||||
|             var commandId = _scheduledTaskRepository.GetDefinition(message.Command.GetType()).Id; | ||||
|             _scheduledTaskRepository.SetLastExecutionTime(commandId, DateTime.UtcNow); | ||||
|             var scheduledTask = _scheduledTaskRepository.All().SingleOrDefault(c => c.TypeName == message.Command.GetType().FullName); | ||||
|  | ||||
|             if (scheduledTask != null) | ||||
|             { | ||||
|                 _scheduledTaskRepository.SetLastExecutionTime(scheduledTask.Id, DateTime.UtcNow); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| using NzbDrone.Common.Messaging; | ||||
|  | ||||
| namespace NzbDrone.Core.MediaFiles.Commands | ||||
| { | ||||
|     public class CleanMediaFileDb : ICommand | ||||
|     { | ||||
|         public int SeriesId { get; private set; } | ||||
|  | ||||
|         public CleanMediaFileDb(int seriesId) | ||||
|         { | ||||
|             SeriesId = seriesId; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										17
									
								
								NzbDrone.Core/MediaFiles/Commands/DiskScanCommand.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								NzbDrone.Core/MediaFiles/Commands/DiskScanCommand.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| using NzbDrone.Common.Messaging; | ||||
|  | ||||
| namespace NzbDrone.Core.MediaFiles.Commands | ||||
| { | ||||
|     public class DiskScanCommand : ICommand | ||||
|     { | ||||
|         public int? SeriesId { get; private set; } | ||||
|  | ||||
|         public DiskScanCommand(int seriesId = 0) | ||||
|         { | ||||
|             if (seriesId != 0) | ||||
|             { | ||||
|                 SeriesId = seriesId; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -4,40 +4,43 @@ using System.IO; | ||||
| using System.Linq; | ||||
| using NLog; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.MediaFiles; | ||||
| using NzbDrone.Common.Messaging; | ||||
| using NzbDrone.Core.MediaFiles.Commands; | ||||
| using NzbDrone.Core.Parser; | ||||
| using NzbDrone.Core.Providers; | ||||
| using NzbDrone.Core.Tv; | ||||
| 
 | ||||
| namespace NzbDrone.Core.Providers | ||||
| namespace NzbDrone.Core.MediaFiles | ||||
| { | ||||
|     public interface IDiskScanService | ||||
|     { | ||||
|         void Scan(Series series); | ||||
|         EpisodeFile ImportFile(Series series, string filePath); | ||||
|         string[] GetVideoFiles(string path, bool allDirectories = true); | ||||
|     } | ||||
| 
 | ||||
|     public class DiskScanService : IDiskScanService | ||||
|     public class DiskScanService : IDiskScanService, IExecute<DiskScanCommand> | ||||
|     { | ||||
|         private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | ||||
|         private static readonly string[] MediaExtensions = new[] { ".mkv", ".avi", ".wmv", ".mp4", ".mpg", ".mpeg", ".xvid", ".flv", ".mov", ".rm", ".rmvb", ".divx", ".dvr-ms", ".ts", ".ogm", ".m4v", ".strm" }; | ||||
|         private readonly IDiskProvider _diskProvider; | ||||
|         private readonly ICleanGhostFiles _ghostFileCleaner; | ||||
|         private readonly ISeriesService _seriesService; | ||||
|         private readonly IMediaFileService _mediaFileService; | ||||
|         private readonly IVideoFileInfoReader _videoFileInfoReader; | ||||
|         private readonly IParsingService _parsingService; | ||||
|         private readonly IMessageAggregator _messageAggregator; | ||||
| 
 | ||||
|         public DiskScanService(IDiskProvider diskProvider, ICleanGhostFiles ghostFileCleaner, IMediaFileService mediaFileService, IVideoFileInfoReader videoFileInfoReader, | ||||
|             IParsingService parsingService) | ||||
|         public DiskScanService(IDiskProvider diskProvider, ISeriesService seriesService, IMediaFileService mediaFileService, IVideoFileInfoReader videoFileInfoReader, | ||||
|             IParsingService parsingService, IMessageAggregator messageAggregator) | ||||
|         { | ||||
|             _diskProvider = diskProvider; | ||||
|             _ghostFileCleaner = ghostFileCleaner; | ||||
|             _seriesService = seriesService; | ||||
|             _mediaFileService = mediaFileService; | ||||
|             _videoFileInfoReader = videoFileInfoReader; | ||||
|             _parsingService = parsingService; | ||||
|             _messageAggregator = messageAggregator; | ||||
|         } | ||||
| 
 | ||||
|         public virtual void Scan(Series series) | ||||
|         private void Scan(Series series) | ||||
|         { | ||||
|             if (!_diskProvider.FolderExists(series.Path)) | ||||
|             { | ||||
| @@ -45,7 +48,7 @@ namespace NzbDrone.Core.Providers | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             _ghostFileCleaner.RemoveNonExistingFiles(series.Id); | ||||
|             _messageAggregator.PublishCommand(new CleanMediaFileDb(series.Id)); | ||||
| 
 | ||||
|             var mediaFileList = GetVideoFiles(series.Path); | ||||
| 
 | ||||
| @@ -58,7 +61,7 @@ namespace NzbDrone.Core.Providers | ||||
|             //Todo: Move the episode linking to here, instead of import (or rename import) | ||||
|         } | ||||
| 
 | ||||
|         public virtual EpisodeFile ImportFile(Series series, string filePath) | ||||
|         public EpisodeFile ImportFile(Series series, string filePath) | ||||
|         { | ||||
|             Logger.Trace("Importing file to database [{0}]", filePath); | ||||
| 
 | ||||
| @@ -87,7 +90,7 @@ namespace NzbDrone.Core.Providers | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (parsedEpisode.Episodes.Any(e => e.EpisodeFile != null && e.EpisodeFile.Quality > parsedEpisode.Quality)) | ||||
|             if (parsedEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && e.EpisodeFile.Value.Quality > parsedEpisode.Quality)) | ||||
|             { | ||||
|                 Logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", filePath); | ||||
|                 return null; | ||||
| @@ -101,6 +104,7 @@ namespace NzbDrone.Core.Providers | ||||
|             episodeFile.Quality = parsedEpisode.Quality; | ||||
|             episodeFile.SeasonNumber = parsedEpisode.SeasonNumber; | ||||
|             episodeFile.SceneName = Path.GetFileNameWithoutExtension(filePath.CleanPath()); | ||||
|             episodeFile.Episodes = parsedEpisode.Episodes; | ||||
| 
 | ||||
|             //Todo: We shouldn't actually import the file until we confirm its the only one we want. | ||||
|             //Todo: Separate episodeFile creation from importing (pass file to import to import) | ||||
| @@ -108,7 +112,7 @@ namespace NzbDrone.Core.Providers | ||||
|             return episodeFile; | ||||
|         } | ||||
| 
 | ||||
|         public virtual string[] GetVideoFiles(string path, bool allDirectories = true) | ||||
|         public string[] GetVideoFiles(string path, bool allDirectories = true) | ||||
|         { | ||||
|             Logger.Debug("Scanning '{0}' for video files", path); | ||||
| 
 | ||||
| @@ -120,5 +124,24 @@ namespace NzbDrone.Core.Providers | ||||
|             Logger.Trace("{0} video files were found in {1}", mediaFileList.Count, path); | ||||
|             return mediaFileList.ToArray(); | ||||
|         } | ||||
| 
 | ||||
|         public void Execute(DiskScanCommand message) | ||||
|         { | ||||
|             var seriesToScan = new List<Series>(); | ||||
| 
 | ||||
|             if (message.SeriesId.HasValue) | ||||
|             { | ||||
|                 seriesToScan.Add(_seriesService.GetSeries(message.SeriesId.Value)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 seriesToScan.AddRange(_seriesService.GetAllSeries()); | ||||
|             } | ||||
| 
 | ||||
|             foreach (var series in seriesToScan) | ||||
|             { | ||||
|                 Scan(series); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -6,20 +6,6 @@ namespace NzbDrone.Core.MediaFiles | ||||
| { | ||||
|     public class EpisodeFile : ModelBase | ||||
|     { | ||||
|         public EpisodeFile() | ||||
|         { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public EpisodeFile(EpisodeFile source) | ||||
|         { | ||||
|             Id = source.Id; | ||||
|             SeriesId = source.SeriesId; | ||||
|             SeasonNumber = source.SeasonNumber; | ||||
|             Path = source.Path; | ||||
|             Size = source.Size; | ||||
|         } | ||||
|  | ||||
|         public int SeriesId { get; set; } | ||||
|         public int SeasonNumber { get; set; } | ||||
|         public string Path { get; set; } | ||||
|   | ||||
| @@ -1,48 +0,0 @@ | ||||
| using System; | ||||
| using NLog; | ||||
| using NzbDrone.Common; | ||||
|  | ||||
| namespace NzbDrone.Core.MediaFiles | ||||
| { | ||||
|     public interface ICleanGhostFiles | ||||
|     { | ||||
|         void RemoveNonExistingFiles(int seriesId); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public class GhostFileCleanupService : ICleanGhostFiles | ||||
|     { | ||||
|         private readonly IMediaFileService _mediaFileService; | ||||
|         private readonly IDiskProvider _diskProvider; | ||||
|         private readonly Logger _logger; | ||||
|  | ||||
|         public GhostFileCleanupService(IMediaFileService mediaFileService, IDiskProvider diskProvider, Logger logger) | ||||
|         { | ||||
|             _mediaFileService = mediaFileService; | ||||
|             _diskProvider = diskProvider; | ||||
|             _logger = logger; | ||||
|         } | ||||
|  | ||||
|         public void RemoveNonExistingFiles(int seriesId) | ||||
|         { | ||||
|             var seriesFile = _mediaFileService.GetFilesBySeries(seriesId); | ||||
|  | ||||
|             foreach (var episodeFile in seriesFile) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     if (!_diskProvider.FileExists(episodeFile.Path)) | ||||
|                     { | ||||
|                         _logger.Trace("File [{0}] no longer exists on disk. removing from db", episodeFile.Path); | ||||
|                         _mediaFileService.Delete(episodeFile); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     var message = String.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id); | ||||
|                     _logger.ErrorException(message, ex); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										55
									
								
								NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
| using NLog; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Common.Messaging; | ||||
| using NzbDrone.Core.MediaFiles.Commands; | ||||
| using NzbDrone.Core.Tv; | ||||
|  | ||||
| namespace NzbDrone.Core.MediaFiles | ||||
| { | ||||
|  | ||||
|     public class MediaFileTableCleanupService : IExecute<CleanMediaFileDb> | ||||
|     { | ||||
|         private readonly IMediaFileService _mediaFileService; | ||||
|         private readonly IDiskProvider _diskProvider; | ||||
|         private readonly IEpisodeService _episodeService; | ||||
|         private readonly Logger _logger; | ||||
|  | ||||
|         public MediaFileTableCleanupService(IMediaFileService mediaFileService, IDiskProvider diskProvider, IEpisodeService episodeService, Logger logger) | ||||
|         { | ||||
|             _mediaFileService = mediaFileService; | ||||
|             _diskProvider = diskProvider; | ||||
|             _episodeService = episodeService; | ||||
|             _logger = logger; | ||||
|         } | ||||
|  | ||||
|         public void Execute(CleanMediaFileDb message) | ||||
|         { | ||||
|             var seriesFile = _mediaFileService.GetFilesBySeries(message.SeriesId); | ||||
|  | ||||
|             foreach (var episodeFile in seriesFile) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     if (!_diskProvider.FileExists(episodeFile.Path)) | ||||
|                     { | ||||
|                         _logger.Trace("File [{0}] no longer exists on disk. removing from db", episodeFile.Path); | ||||
|                         _mediaFileService.Delete(episodeFile); | ||||
|                     } | ||||
|  | ||||
|                     if (!_episodeService.GetEpisodesByFileId(episodeFile.Id).Any()) | ||||
|                     { | ||||
|                         _logger.Trace("File [{0}] is not assigned to any episodes. removing from db", episodeFile.Path); | ||||
|                         _mediaFileService.Delete(episodeFile); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     var errorMessage = String.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id); | ||||
|                     _logger.ErrorException(errorMessage, ex); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -247,7 +247,9 @@ | ||||
|     <Compile Include="Indexers\RssSyncCommand.cs" /> | ||||
|     <Compile Include="Jobs\TaskManager.cs" /> | ||||
|     <Compile Include="Lifecycle\ApplicationShutdownRequested.cs" /> | ||||
|     <Compile Include="MediaFiles\Commands\CleanMediaFileDb.cs" /> | ||||
|     <Compile Include="MediaFiles\Commands\CleanUpRecycleBinCommand.cs" /> | ||||
|     <Compile Include="MediaFiles\Commands\DiskScanCommand.cs" /> | ||||
|     <Compile Include="MediaFiles\Events\EpisodeDownloadedEvent.cs" /> | ||||
|     <Compile Include="Download\EpisodeGrabbedEvent.cs" /> | ||||
|     <Compile Include="Download\SeriesRenamedEvent.cs" /> | ||||
| @@ -296,7 +298,7 @@ | ||||
|     <Compile Include="MediaFiles\EpisodeFileMovingService.cs" /> | ||||
|     <Compile Include="MediaFiles\Events\EpisodeFileAddedEvent.cs" /> | ||||
|     <Compile Include="MediaFiles\Events\EpisodeFileDeletedEvent.cs" /> | ||||
|     <Compile Include="MediaFiles\GhostFileCleanupService.cs" /> | ||||
|     <Compile Include="MediaFiles\MediaFileTableCleanupService.cs" /> | ||||
|     <Compile Include="MediaFiles\MediaFileRepository.cs" /> | ||||
|     <Compile Include="MetadataSource\IProvideEpisodeInfo.cs" /> | ||||
|     <Compile Include="MetadataSource\IProvideSeriesInfo.cs" /> | ||||
| @@ -404,7 +406,7 @@ | ||||
|     <Compile Include="DecisionEngine\Specifications\RetentionSpecification.cs"> | ||||
|       <SubType>Code</SubType> | ||||
|     </Compile> | ||||
|     <Compile Include="Providers\IDiskScanService.cs"> | ||||
|     <Compile Include="MediaFiles\DiskScanService.cs"> | ||||
|       <SubType>Code</SubType> | ||||
|     </Compile> | ||||
|     <Compile Include="Download\Clients\BlackholeProvider.cs"> | ||||
|   | ||||
| @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Providers.Converting | ||||
|             var outputFile = _configService.GetValue("iPodConvertDir", ""); | ||||
|  | ||||
|             var handBrakePreset = _configService.GetValue("HandBrakePreset", "iPhone & iPod Touch"); | ||||
|             var handBrakeCommand = String.Format("-i \"{0}\" -o \"{1}\" --preset=\"{2}\"", episode.EpisodeFile.Path, outputFile, handBrakePreset); | ||||
|             var handBrakeCommand = String.Format("-i \"{0}\" -o \"{1}\" --preset=\"{2}\"", episode.EpisodeFile.Value.Path, outputFile, handBrakePreset); | ||||
|             var handBrakeFile = @"C:\Program Files (x86)\Handbrake\HandBrakeCLI.exe"; | ||||
|  | ||||
|             try | ||||
|   | ||||
| @@ -30,7 +30,7 @@ namespace NzbDrone.Core.Providers | ||||
|  | ||||
|             var misnamedFilesSelect = episodesWithFiles.AsParallel().Where( | ||||
|                 w => | ||||
|                 w.First().EpisodeFile.Path != | ||||
|                 w.First().EpisodeFile.Value.Path != | ||||
|                 _buildFileNames.BuildFilename(w.Select(e => e).ToList(), w.First().Series, w.First().EpisodeFile)).Skip(Math.Max(pageSize * (pageNumber - 1), 0)).Take(pageSize); | ||||
|  | ||||
|             //Process the episodes | ||||
| @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Providers | ||||
|                     var properName = _buildFileNames.BuildFilename(episodes, firstEpisode.Series, | ||||
|                                                                    firstEpisode.EpisodeFile); | ||||
|  | ||||
|                     var currentName = Path.GetFileNameWithoutExtension(firstEpisode.EpisodeFile.Path); | ||||
|                     var currentName = Path.GetFileNameWithoutExtension(firstEpisode.EpisodeFile.Value.Path); | ||||
|  | ||||
|                     if (properName != currentName) | ||||
|                     { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System; | ||||
| using Marr.Data; | ||||
| using NzbDrone.Core.Datastore; | ||||
| using NzbDrone.Core.MediaFiles; | ||||
| using NzbDrone.Core.Model; | ||||
| @@ -18,38 +19,21 @@ namespace NzbDrone.Core.Tv | ||||
|  | ||||
|         public string Overview { get; set; } | ||||
|         public Boolean Ignored { get; set; } | ||||
|         public PostDownloadStatusType PostDownloadStatus { get; set; } | ||||
|         public Nullable<Int32> AbsoluteEpisodeNumber { get; set; } | ||||
|         public int SceneSeasonNumber { get; set; } | ||||
|         public int SceneEpisodeNumber { get; set; } | ||||
|         public DateTime? GrabDate { get; set; } | ||||
|  | ||||
|         public bool HasFile | ||||
|         { | ||||
|             get { return EpisodeFile != null; } | ||||
|             get { return EpisodeFileId != 0; } | ||||
|         } | ||||
|          | ||||
|  | ||||
|         public EpisodeStatuses Status | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 if (HasFile) return EpisodeStatuses.Ready; | ||||
|  | ||||
|                 if (GrabDate != null) | ||||
|                 { | ||||
|                     if (PostDownloadStatus == PostDownloadStatusType.Unpacking) | ||||
|                         return EpisodeStatuses.Unpacking; | ||||
|  | ||||
|                     if (PostDownloadStatus == PostDownloadStatusType.Failed) | ||||
|                         return EpisodeStatuses.Failed; | ||||
|  | ||||
|                     if (GrabDate.Value.AddDays(1) >= DateTime.Now) | ||||
|                         return EpisodeStatuses.Downloading; | ||||
|                 } | ||||
|  | ||||
|                 if (GrabDate != null && GrabDate.Value.AddDays(1) >= DateTime.Now) | ||||
|                     return EpisodeStatuses.Downloading; | ||||
|  | ||||
|                 if (AirDate != null && AirDate.Value.Date == DateTime.Today) | ||||
|                     return EpisodeStatuses.AirsToday; | ||||
|  | ||||
| @@ -75,7 +59,7 @@ namespace NzbDrone.Core.Tv | ||||
|  | ||||
|         public Series Series { get; set; } | ||||
|  | ||||
|         public EpisodeFile EpisodeFile { get; set; } | ||||
|         public LazyLoaded<EpisodeFile> EpisodeFile { get; set; } | ||||
|  | ||||
|         public override string ToString() | ||||
|         { | ||||
|   | ||||
| @@ -1,10 +1,6 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.Data; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using FluentMigrator.Runner; | ||||
| using Marr.Data; | ||||
| using Marr.Data.QGen; | ||||
| using NzbDrone.Common.Messaging; | ||||
| @@ -26,7 +22,6 @@ namespace NzbDrone.Core.Tv | ||||
|         List<Episode> EpisodesWithFiles(); | ||||
|         List<Episode> EpisodesBetweenDates(DateTime startDate, DateTime endDate); | ||||
|         void SetIgnoreFlat(Episode episode, bool ignoreFlag); | ||||
|         void SetPostDownloadStatus(int episodeId, PostDownloadStatusType status); | ||||
|         void SetFileId(int episodeId, int fileId); | ||||
|     } | ||||
|  | ||||
| @@ -62,7 +57,7 @@ namespace NzbDrone.Core.Tv | ||||
|  | ||||
|         public List<Episode> GetEpisodeByFileId(int fileId) | ||||
|         { | ||||
|             return Query.Where(s => s.EpisodeFile != null && s.EpisodeFile.Id == fileId).ToList(); | ||||
|             return Query.Where(e => e.EpisodeFileId == fileId).ToList(); | ||||
|         } | ||||
|  | ||||
|         public PagingSpec<Episode> EpisodesWithoutFiles(PagingSpec<Episode> pagingSpec, bool includeSpecials) | ||||
| @@ -74,7 +69,7 @@ namespace NzbDrone.Core.Tv | ||||
|             { | ||||
|                 startingSeasonNumber = 0; | ||||
|             } | ||||
|              | ||||
|  | ||||
|             var pagingQuery = Query.Join<Episode, Series>(JoinType.Inner, e => e.Series, (e, s) => e.SeriesId == s.Id) | ||||
|                                       .Where(e => e.EpisodeFileId == 0) | ||||
|                                       .AndWhere(e => e.SeasonNumber >= startingSeasonNumber) | ||||
| @@ -98,7 +93,7 @@ namespace NzbDrone.Core.Tv | ||||
|  | ||||
|         public List<Episode> EpisodesWithFiles() | ||||
|         { | ||||
|             return Query.Where(s => s.EpisodeFile != null).ToList(); | ||||
|             return Query.Where(s => s.EpisodeFileId != 0).ToList(); | ||||
|         } | ||||
|  | ||||
|         public List<Episode> EpisodesBetweenDates(DateTime startDate, DateTime endDate) | ||||
| @@ -113,11 +108,6 @@ namespace NzbDrone.Core.Tv | ||||
|             SetFields(episode, p => p.Ignored); | ||||
|         } | ||||
|  | ||||
|         public void SetPostDownloadStatus(int episodeId, PostDownloadStatusType status) | ||||
|         { | ||||
|             SetFields(new Episode { Id = episodeId, PostDownloadStatus = status }, episode => episode.PostDownloadStatus); | ||||
|         } | ||||
|  | ||||
|         public void SetFileId(int episodeId, int fileId) | ||||
|         { | ||||
|             SetFields(new Episode { Id = episodeId, EpisodeFileId = fileId }, episode => episode.EpisodeFileId); | ||||
|   | ||||
| @@ -29,16 +29,14 @@ namespace NzbDrone.Core.Tv | ||||
|         List<int> GetEpisodeNumbersBySeason(int seriesId, int seasonNumber); | ||||
|         void SetEpisodeIgnore(int episodeId, bool isIgnored); | ||||
|         bool IsFirstOrLastEpisodeOfSeason(int episodeId); | ||||
|         void SetPostDownloadStatus(List<int> episodeIds, PostDownloadStatusType postDownloadStatus); | ||||
|         void UpdateEpisodes(List<Episode> episodes); | ||||
|         List<Episode> EpisodesBetweenDates(DateTime start, DateTime end); | ||||
|     } | ||||
|  | ||||
|     public class EpisodeService : IEpisodeService, | ||||
|         IHandle<EpisodeGrabbedEvent>, | ||||
|         IHandle<EpisodeFileDeletedEvent>, | ||||
|         IHandle<EpisodeFileAddedEvent>, | ||||
|     IHandleAsync<SeriesDeletedEvent>, | ||||
|         IHandleAsync<SeriesDeletedEvent>, | ||||
|         IHandleAsync<SeriesAddedEvent> | ||||
|     { | ||||
|  | ||||
| @@ -166,7 +164,7 @@ namespace NzbDrone.Core.Tv | ||||
|                         episodeToUpdate.EpisodeFileId > 0) | ||||
|                     { | ||||
|                         logger.Info("Unlinking episode file because TheTVDB changed the episode number..."); | ||||
|                         episodeToUpdate.EpisodeFile = null; | ||||
|                         episodeToUpdate.EpisodeFileId = 0; | ||||
|                     } | ||||
|  | ||||
|                     episodeToUpdate.SeriesId = series.Id; | ||||
| @@ -268,22 +266,6 @@ namespace NzbDrone.Core.Tv | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         public void SetPostDownloadStatus(List<int> episodeIds, PostDownloadStatusType postDownloadStatus) | ||||
|         { | ||||
|             if (episodeIds.Count == 0) throw new ArgumentException("episodeIds should contain one or more episode ids."); | ||||
|  | ||||
|  | ||||
|             foreach (var episodeId in episodeIds) | ||||
|             { | ||||
|                 var episode = _episodeRepository.Get(episodeId); | ||||
|                 episode.PostDownloadStatus = postDownloadStatus; | ||||
|                 _episodeRepository.Update(episode); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             logger.Trace("Updating PostDownloadStatus for {0} episode(s) to {1}", episodeIds.Count, postDownloadStatus); | ||||
|         } | ||||
|  | ||||
|         public void UpdateEpisodes(List<Episode> episodes) | ||||
|         { | ||||
|             _episodeRepository.UpdateMany(episodes); | ||||
| @@ -296,16 +278,6 @@ namespace NzbDrone.Core.Tv | ||||
|             return LinkSeriesToEpisodes(episodes); | ||||
|         } | ||||
|  | ||||
|         public void Handle(EpisodeGrabbedEvent message) | ||||
|         { | ||||
|             foreach (var episode in message.Episode.Episodes) | ||||
|             { | ||||
|                 logger.Trace("Marking episode {0} as fetched.", episode.Id); | ||||
|                 episode.GrabDate = DateTime.UtcNow; | ||||
|                 _episodeRepository.Update(episode); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void HandleAsync(SeriesDeletedEvent message) | ||||
|         { | ||||
|             var episodes = GetEpisodeBySeries(message.Series.Id); | ||||
| @@ -317,10 +289,8 @@ namespace NzbDrone.Core.Tv | ||||
|             foreach (var episode in GetEpisodesByFileId(message.EpisodeFile.Id)) | ||||
|             { | ||||
|                 _logger.Trace("Detaching episode {0} from file.", episode.Id); | ||||
|                 episode.EpisodeFile = null; | ||||
|                 episode.EpisodeFileId = 0; | ||||
|                 episode.Ignored = _configService.AutoIgnorePreviouslyDownloadedEpisodes; | ||||
|                 episode.GrabDate = null; | ||||
|                 episode.PostDownloadStatus = PostDownloadStatusType.Unknown; | ||||
|                 UpdateEpisode(episode); | ||||
|             } | ||||
|         } | ||||
| @@ -335,7 +305,6 @@ namespace NzbDrone.Core.Tv | ||||
|             foreach (var episode in message.EpisodeFile.Episodes.Value) | ||||
|             { | ||||
|                 _episodeRepository.SetFileId(episode.Id, message.EpisodeFile.Id); | ||||
|                 _episodeRepository.SetPostDownloadStatus(episode.Id, PostDownloadStatusType.NoError); | ||||
|                 _logger.Debug("Linking [{0}] > [{1}]", message.EpisodeFile.Path, episode); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
|             layout="${date:format=yy-M-d HH\:mm\:ss.f}|${logger}}|${level}|${message}|${exception:format=ToString}"/> | ||||
|   </targets> | ||||
|   <rules> | ||||
|     <logger name="*" minlevel="Debug" writeTo="consoleLogger"/> | ||||
|     <logger name="*" minlevel="Trace" writeTo="consoleLogger"/> | ||||
|     <logger name="*" minlevel="Off" writeTo="udpTarget"/> | ||||
|     <logger name="*" minlevel="Warn" writeTo="rollingFileLogger"/> | ||||
|   </rules> | ||||
|   | ||||
| @@ -156,7 +156,7 @@ define([ | ||||
|                         { | ||||
|                             title         : 'Update Library', | ||||
|                             icon          : 'icon-refresh', | ||||
|                             command       : 'updatelibrary', | ||||
|                             command       : 'diskscan', | ||||
|                             successMessage: 'Library was updated!', | ||||
|                             errorMessage  : 'Library update failed!' | ||||
|                         }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user