mirror of
https://github.com/Radarr/Radarr.git
synced 2024-11-04 10:02:40 +01:00
fixed diskscan
removed all stored status fields from episode
This commit is contained in:
parent
feb947fb74
commit
cbe4be814c
@ -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 @@ public bool IsTypeRegistered(Type type)
|
||||
{
|
||||
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 @@ public abstract class ContainerBuilderBase
|
||||
|
||||
protected ContainerBuilderBase(params string[] assemblies)
|
||||
{
|
||||
Container = new Container(new TinyIoCContainer());
|
||||
|
||||
_loadedTypes = new List<Type>();
|
||||
|
||||
foreach (var assembly in assemblies)
|
||||
@ -27,6 +25,7 @@ protected ContainerBuilderBase(params string[] assemblies)
|
||||
_loadedTypes.AddRange(Assembly.Load(assembly).GetTypes());
|
||||
}
|
||||
|
||||
Container = new Container(new TinyIoCContainer(), _loadedTypes);
|
||||
AutoRegisterInterfaces();
|
||||
}
|
||||
|
||||
@ -52,7 +51,7 @@ protected void AutoRegisterImplementations<TContract>()
|
||||
|
||||
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 @@ private void AutoRegisterImplementations(Type contractType)
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<Type> GetImplementations(Type contractType)
|
||||
{
|
||||
return _loadedTypes
|
||||
.Where(implementation =>
|
||||
contractType.IsAssignableFrom(implementation) &&
|
||||
!implementation.IsInterface &&
|
||||
!implementation.IsAbstract
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -26,5 +26,7 @@ void RegisterSingleton<TService, TImplementation>()
|
||||
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 @@ public void Setup()
|
||||
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 @@ private void WithSecondFileUpgradable()
|
||||
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 @@
|
||||
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 @@ public void low_air_date()
|
||||
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 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 @@ public void SetUp()
|
||||
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 @@ public void should_skip_files_that_exist_in_disk()
|
||||
|
||||
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 @@ public void should_delete_none_existing_files()
|
||||
|
||||
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 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 @@ public class ImportFileFixture : CoreTest<DiskScanService>
|
||||
|
||||
private long _fileSize = 80.Megabytes();
|
||||
private Series _fakeSeries;
|
||||
private List<Episode> _fakeEpisodes;
|
||||
private Episode[] _fakeEpisodes;
|
||||
private Episode _fakeEpisode;
|
||||
|
||||
[SetUp]
|
||||
@ -35,14 +34,16 @@ public void Setup()
|
||||
|
||||
_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 @@ private void GivenVideoDuration(TimeSpan duration)
|
||||
}
|
||||
|
||||
|
||||
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 @@ public void import_new_file_should_succeed()
|
||||
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 @@ public void import_new_file_with_same_quality_should_succeed()
|
||||
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 @@ public void import_new_file_with_better_quality_should_succeed()
|
||||
[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 @@ public void import_existing_file_should_skip()
|
||||
[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 @@ public void import_new_multi_part_file_episode_with_better_quality_than_existing
|
||||
[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 @@ protected override void MainDbUpgrade()
|
||||
.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 @@ public static RelationshipBuilder<TParent> HasOne<TParent, TChild>(this Relation
|
||||
{
|
||||
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 @@ public static void Map()
|
||||
|
||||
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 @@ public string RejectionReason
|
||||
|
||||
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 @@ public void Handle(ApplicationStartedEvent message)
|
||||
|
||||
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.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 @@ public virtual void Scan(Series series)
|
||||
return;
|
||||
}
|
||||
|
||||
_ghostFileCleaner.RemoveNonExistingFiles(series.Id);
|
||||
_messageAggregator.PublishCommand(new CleanMediaFileDb(series.Id));
|
||||
|
||||
var mediaFileList = GetVideoFiles(series.Path);
|
||||
|
||||
@ -58,7 +61,7 @@ public virtual void Scan(Series series)
|
||||
//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 @@ public virtual EpisodeFile ImportFile(Series series, string filePath)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public virtual EpisodeFile ImportFile(Series series, string filePath)
|
||||
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 @@ public virtual EpisodeFile ImportFile(Series series, string filePath)
|
||||
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 @@ public virtual string[] GetVideoFiles(string path, bool allDirectories = true)
|
||||
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 @@ public virtual string ConvertFile(Episode episode, ProgressNotification notifica
|
||||
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 @@ public virtual List<MisnamedEpisodeModel> MisnamedFiles(int pageNumber, int page
|
||||
|
||||
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 @@ public virtual List<MisnamedEpisodeModel> MisnamedFiles(int pageNumber, int page
|
||||
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 @@ public class Episode : ModelBase
|
||||
|
||||
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 @@ public DateTime? EndTime
|
||||
|
||||
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 @@ public interface IEpisodeRepository : IBasicRepository<Episode>
|
||||
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 @@ public List<Episode> GetEpisodes(int seriesId, int seasonNumber)
|
||||
|
||||
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 @@ public PagingSpec<Episode> EpisodesWithoutFiles(PagingSpec<Episode> pagingSpec,
|
||||
{
|
||||
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 @@ public Episode GetEpisodeBySceneNumbering(int seriesId, int seasonNumber, int ep
|
||||
|
||||
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 @@ public void SetIgnoreFlat(Episode episode, bool ignoreFlag)
|
||||
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 @@ public interface IEpisodeService
|
||||
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 @@ public void RefreshEpisodeInfo(Series series)
|
||||
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 @@ public bool IsFirstOrLastEpisodeOfSeason(int episodeId)
|
||||
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 @@ public List<Episode> EpisodesBetweenDates(DateTime start, DateTime end)
|
||||
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 @@ public void Handle(EpisodeFileDeletedEvent message)
|
||||
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 @@ public void Handle(EpisodeFileAddedEvent message)
|
||||
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!'
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user