Updated JobProvider to allow jobs with two targets.
JobQueueItem class created instead of using Tuples. Added Search for Season and Rename Season jobs , plus links for them on Series/Details. Add GetSeasonFiles added to MediaFileProvider.
This commit is contained in:
parent
56da830296
commit
350e0388de
|
@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test
|
||||||
|
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), series.SeriesId);
|
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), series.SeriesId, 0);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
mocker.VerifyAllMocks();
|
mocker.VerifyAllMocks();
|
||||||
|
@ -66,7 +66,7 @@ namespace NzbDrone.Core.Test
|
||||||
.Setup(s => s.Scan(series[1]))
|
.Setup(s => s.Scan(series[1]))
|
||||||
.Returns(new List<EpisodeFile>());
|
.Returns(new List<EpisodeFile>());
|
||||||
|
|
||||||
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), 0);
|
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), 0, 0);
|
||||||
|
|
||||||
|
|
||||||
mocker.VerifyAllMocks();
|
mocker.VerifyAllMocks();
|
||||||
|
@ -94,7 +94,7 @@ namespace NzbDrone.Core.Test
|
||||||
.Setup(s => s.Scan(series[1]))
|
.Setup(s => s.Scan(series[1]))
|
||||||
.Throws(new InvalidOperationException("Bad Job"));
|
.Throws(new InvalidOperationException("Bad Job"));
|
||||||
|
|
||||||
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), 0);
|
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), 0, 0);
|
||||||
|
|
||||||
|
|
||||||
mocker.VerifyAllMocks();
|
mocker.VerifyAllMocks();
|
||||||
|
@ -123,7 +123,7 @@ namespace NzbDrone.Core.Test
|
||||||
.Setup(s => s.Scan(series[1]))
|
.Setup(s => s.Scan(series[1]))
|
||||||
.Returns(new List<EpisodeFile>());
|
.Returns(new List<EpisodeFile>());
|
||||||
|
|
||||||
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), 0);
|
mocker.Resolve<DiskScanJob>().Start(new ProgressNotification("Test"), 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ namespace NzbDrone.Core.Test
|
||||||
public void start_target_id_less_than_0_throws_exception(int target)
|
public void start_target_id_less_than_0_throws_exception(int target)
|
||||||
{
|
{
|
||||||
var mocker = new AutoMoqer(MockBehavior.Strict);
|
var mocker = new AutoMoqer(MockBehavior.Strict);
|
||||||
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), target);
|
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), target, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ namespace NzbDrone.Core.Test
|
||||||
.Setup(s => s.GetSceneName(It.IsAny<int>())).Returns("");
|
.Setup(s => s.GetSceneName(It.IsAny<int>())).Returns("");
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), episode.EpisodeId);
|
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), episode.EpisodeId, 0);
|
||||||
|
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
|
@ -302,7 +302,7 @@ namespace NzbDrone.Core.Test
|
||||||
.Setup(s => s.GetSceneName(71256)).Returns("The Daily Show");
|
.Setup(s => s.GetSceneName(71256)).Returns("The Daily Show");
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), episode.EpisodeId);
|
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), episode.EpisodeId, 0);
|
||||||
|
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
|
@ -359,7 +359,7 @@ namespace NzbDrone.Core.Test
|
||||||
.Setup(s => s.GetSceneName(It.IsAny<int>())).Returns("");
|
.Setup(s => s.GetSceneName(It.IsAny<int>())).Returns("");
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), episode.EpisodeId);
|
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), episode.EpisodeId, 0);
|
||||||
|
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
|
@ -385,7 +385,7 @@ namespace NzbDrone.Core.Test
|
||||||
.Returns<Episode>(null);
|
.Returns<Episode>(null);
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), 12);
|
mocker.Resolve<EpisodeSearchJob>().Start(new ProgressNotification("Test"), 12, 0);
|
||||||
|
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
|
|
|
@ -36,21 +36,21 @@ namespace NzbDrone.Core.Test
|
||||||
|
|
||||||
|
|
||||||
mocker.GetMock<DiskScanJob>()
|
mocker.GetMock<DiskScanJob>()
|
||||||
.Setup(j => j.Start(notification, series[0].SeriesId))
|
.Setup(j => j.Start(notification, series[0].SeriesId, 0))
|
||||||
.Callback(() => series[0].LastDiskSync = DateTime.Now);
|
.Callback(() => series[0].LastDiskSync = DateTime.Now);
|
||||||
|
|
||||||
|
|
||||||
mocker.GetMock<DiskScanJob>()
|
mocker.GetMock<DiskScanJob>()
|
||||||
.Setup(j => j.Start(notification, series[1].SeriesId))
|
.Setup(j => j.Start(notification, series[1].SeriesId, 0))
|
||||||
.Callback(() => series[1].LastDiskSync = DateTime.Now);
|
.Callback(() => series[1].LastDiskSync = DateTime.Now);
|
||||||
|
|
||||||
|
|
||||||
mocker.GetMock<UpdateInfoJob>()
|
mocker.GetMock<UpdateInfoJob>()
|
||||||
.Setup(j => j.Start(notification, series[0].SeriesId))
|
.Setup(j => j.Start(notification, series[0].SeriesId, 0))
|
||||||
.Callback(() => series[0].LastInfoSync = DateTime.Now);
|
.Callback(() => series[0].LastInfoSync = DateTime.Now);
|
||||||
|
|
||||||
mocker.GetMock<UpdateInfoJob>()
|
mocker.GetMock<UpdateInfoJob>()
|
||||||
.Setup(j => j.Start(notification, series[1].SeriesId))
|
.Setup(j => j.Start(notification, series[1].SeriesId, 0))
|
||||||
.Callback(() => series[1].LastInfoSync = DateTime.Now);
|
.Callback(() => series[1].LastInfoSync = DateTime.Now);
|
||||||
|
|
||||||
mocker.GetMock<SeriesProvider>()
|
mocker.GetMock<SeriesProvider>()
|
||||||
|
@ -63,16 +63,16 @@ namespace NzbDrone.Core.Test
|
||||||
.Setup(s => s.GetSeriesFiles(It.IsAny<int>())).Returns(new List<EpisodeFile>());
|
.Setup(s => s.GetSeriesFiles(It.IsAny<int>())).Returns(new List<EpisodeFile>());
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
mocker.Resolve<ImportNewSeriesJob>().Start(notification, 0);
|
mocker.Resolve<ImportNewSeriesJob>().Start(notification, 0, 0);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
mocker.VerifyAllMocks();
|
mocker.VerifyAllMocks();
|
||||||
|
|
||||||
mocker.GetMock<DiskScanJob>().Verify(j => j.Start(notification, series[0].SeriesId), Times.Once());
|
mocker.GetMock<DiskScanJob>().Verify(j => j.Start(notification, series[0].SeriesId, 0), Times.Once());
|
||||||
mocker.GetMock<DiskScanJob>().Verify(j => j.Start(notification, series[1].SeriesId), Times.Once());
|
mocker.GetMock<DiskScanJob>().Verify(j => j.Start(notification, series[1].SeriesId, 0), Times.Once());
|
||||||
|
|
||||||
mocker.GetMock<UpdateInfoJob>().Verify(j => j.Start(notification, series[0].SeriesId), Times.Once());
|
mocker.GetMock<UpdateInfoJob>().Verify(j => j.Start(notification, series[0].SeriesId, 0), Times.Once());
|
||||||
mocker.GetMock<UpdateInfoJob>().Verify(j => j.Start(notification, series[1].SeriesId), Times.Once());
|
mocker.GetMock<UpdateInfoJob>().Verify(j => j.Start(notification, series[1].SeriesId, 0), Times.Once());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,15 +98,15 @@ namespace NzbDrone.Core.Test
|
||||||
.Returns(series);
|
.Returns(series);
|
||||||
|
|
||||||
mocker.GetMock<UpdateInfoJob>()
|
mocker.GetMock<UpdateInfoJob>()
|
||||||
.Setup(j => j.Start(notification, series[0].SeriesId))
|
.Setup(j => j.Start(notification, series[0].SeriesId, 0))
|
||||||
.Callback(() => series[0].LastInfoSync = DateTime.Now);
|
.Callback(() => series[0].LastInfoSync = DateTime.Now);
|
||||||
|
|
||||||
mocker.GetMock<UpdateInfoJob>()
|
mocker.GetMock<UpdateInfoJob>()
|
||||||
.Setup(j => j.Start(notification, series[1].SeriesId))
|
.Setup(j => j.Start(notification, series[1].SeriesId, 0))
|
||||||
.Throws(new InvalidOperationException());
|
.Throws(new InvalidOperationException());
|
||||||
|
|
||||||
mocker.GetMock<DiskScanJob>()
|
mocker.GetMock<DiskScanJob>()
|
||||||
.Setup(j => j.Start(notification, series[0].SeriesId))
|
.Setup(j => j.Start(notification, series[0].SeriesId, 0))
|
||||||
.Callback(() => series[0].LastDiskSync = DateTime.Now);
|
.Callback(() => series[0].LastDiskSync = DateTime.Now);
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,15 +117,15 @@ namespace NzbDrone.Core.Test
|
||||||
.Setup(s => s.GetSeriesFiles(It.IsAny<int>())).Returns(new List<EpisodeFile>());
|
.Setup(s => s.GetSeriesFiles(It.IsAny<int>())).Returns(new List<EpisodeFile>());
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
mocker.Resolve<ImportNewSeriesJob>().Start(notification, 0);
|
mocker.Resolve<ImportNewSeriesJob>().Start(notification, 0, 0);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
mocker.VerifyAllMocks();
|
mocker.VerifyAllMocks();
|
||||||
|
|
||||||
mocker.GetMock<UpdateInfoJob>().Verify(j => j.Start(notification, series[0].SeriesId), Times.Once());
|
mocker.GetMock<UpdateInfoJob>().Verify(j => j.Start(notification, series[0].SeriesId, 0), Times.Once());
|
||||||
mocker.GetMock<UpdateInfoJob>().Verify(j => j.Start(notification, series[1].SeriesId), Times.Once());
|
mocker.GetMock<UpdateInfoJob>().Verify(j => j.Start(notification, series[1].SeriesId, 0), Times.Once());
|
||||||
|
|
||||||
mocker.GetMock<DiskScanJob>().Verify(j => j.Start(notification, series[0].SeriesId), Times.Once());
|
mocker.GetMock<DiskScanJob>().Verify(j => j.Start(notification, series[0].SeriesId, 0), Times.Once());
|
||||||
|
|
||||||
ExceptionVerification.ExcpectedErrors(1);
|
ExceptionVerification.ExcpectedErrors(1);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using AutoMoq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Model;
|
||||||
using NzbDrone.Core.Model.Notification;
|
using NzbDrone.Core.Model.Notification;
|
||||||
using NzbDrone.Core.Providers.Jobs;
|
using NzbDrone.Core.Providers.Jobs;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
@ -84,7 +85,7 @@ namespace NzbDrone.Core.Test
|
||||||
timerProvider.QueueScheduled();
|
timerProvider.QueueScheduled();
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
|
|
||||||
fakeJob.ExexutionCount.Should().Be(1);
|
fakeJob.ExecutionCount.Should().Be(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -106,7 +107,7 @@ namespace NzbDrone.Core.Test
|
||||||
timerProvider.QueueJob(typeof(FakeJob));
|
timerProvider.QueueJob(typeof(FakeJob));
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
JobProvider.Queue.Should().BeEmpty();
|
JobProvider.Queue.Should().BeEmpty();
|
||||||
fakeJob.ExexutionCount.Should().Be(2);
|
fakeJob.ExecutionCount.Should().Be(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -154,7 +155,7 @@ namespace NzbDrone.Core.Test
|
||||||
|
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
JobProvider.Queue.Should().BeEmpty();
|
JobProvider.Queue.Should().BeEmpty();
|
||||||
brokenJob.ExexutionCount.Should().Be(2);
|
brokenJob.ExecutionCount.Should().Be(2);
|
||||||
ExceptionVerification.ExcpectedErrors(2);
|
ExceptionVerification.ExcpectedErrors(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +185,7 @@ namespace NzbDrone.Core.Test
|
||||||
thread2.Join();
|
thread2.Join();
|
||||||
|
|
||||||
|
|
||||||
slowJob.ExexutionCount = 2;
|
slowJob.ExecutionCount = 2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +217,7 @@ namespace NzbDrone.Core.Test
|
||||||
|
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
|
|
||||||
Assert.AreEqual(1, slowJob.ExexutionCount);
|
Assert.AreEqual(1, slowJob.ExecutionCount);
|
||||||
JobProvider.Queue.Should().BeEmpty();
|
JobProvider.Queue.Should().BeEmpty();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -352,7 +353,7 @@ namespace NzbDrone.Core.Test
|
||||||
|
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.AreEqual(0, disabledJob.ExexutionCount);
|
Assert.AreEqual(0, disabledJob.ExecutionCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -411,7 +412,13 @@ namespace NzbDrone.Core.Test
|
||||||
mocker.SetConstant(MockLib.GetEmptyDatabase());
|
mocker.SetConstant(MockLib.GetEmptyDatabase());
|
||||||
mocker.SetConstant(fakeJobs);
|
mocker.SetConstant(fakeJobs);
|
||||||
|
|
||||||
var fakeQueueItem = new Tuple<Type, int>(fakeJob.GetType(), 12);
|
var fakeQueueItem = new JobQueueItem
|
||||||
|
{
|
||||||
|
JobType = fakeJob.GetType(),
|
||||||
|
TargetId = 12,
|
||||||
|
SecondaryTargetId = 0
|
||||||
|
};
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
var jobProvider = mocker.Resolve<JobProvider>();
|
var jobProvider = mocker.Resolve<JobProvider>();
|
||||||
jobProvider.Initialize();
|
jobProvider.Initialize();
|
||||||
|
@ -420,7 +427,7 @@ namespace NzbDrone.Core.Test
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
fakeJob.ExexutionCount.Should().Be(1);
|
fakeJob.ExecutionCount.Should().Be(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -449,8 +456,8 @@ namespace NzbDrone.Core.Test
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
JobProvider.Queue.Should().BeEmpty();
|
JobProvider.Queue.Should().BeEmpty();
|
||||||
slowJob.ExexutionCount.Should().Be(1);
|
slowJob.ExecutionCount.Should().Be(1);
|
||||||
disabledJob.ExexutionCount.Should().Be(1);
|
disabledJob.ExecutionCount.Should().Be(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,11 +473,11 @@ namespace NzbDrone.Core.Test
|
||||||
get { return 15; }
|
get { return 15; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ExexutionCount { get; set; }
|
public int ExecutionCount { get; set; }
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
ExexutionCount++;
|
ExecutionCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,11 +493,11 @@ namespace NzbDrone.Core.Test
|
||||||
get { return 0; }
|
get { return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ExexutionCount { get; set; }
|
public int ExecutionCount { get; set; }
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
ExexutionCount++;
|
ExecutionCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,11 +513,11 @@ namespace NzbDrone.Core.Test
|
||||||
get { return 15; }
|
get { return 15; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ExexutionCount { get; set; }
|
public int ExecutionCount { get; set; }
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
ExexutionCount++;
|
ExecutionCount++;
|
||||||
throw new ApplicationException("Broken job is broken");
|
throw new ApplicationException("Broken job is broken");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,13 +534,13 @@ namespace NzbDrone.Core.Test
|
||||||
get { return 15; }
|
get { return 15; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ExexutionCount { get; set; }
|
public int ExecutionCount { get; set; }
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Starting Job");
|
Console.WriteLine("Starting Job");
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
ExexutionCount++;
|
ExecutionCount++;
|
||||||
Console.WriteLine("Finishing Job");
|
Console.WriteLine("Finishing Job");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,35 @@ namespace NzbDrone.Core.Test
|
||||||
result.Should().HaveSameCount(firstSeriesFiles);
|
result.Should().HaveSameCount(firstSeriesFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void get_season_files()
|
||||||
|
{
|
||||||
|
var firstSeriesFiles = Builder<EpisodeFile>.CreateListOfSize(10)
|
||||||
|
.WhereAll()
|
||||||
|
.Have(s => s.SeriesId = 12)
|
||||||
|
.Have(s => s.SeasonNumber = 1)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var secondSeriesFiles = Builder<EpisodeFile>.CreateListOfSize(10)
|
||||||
|
.WhereAll()
|
||||||
|
.Have(s => s.SeriesId = 12)
|
||||||
|
.Have(s => s.SeasonNumber = 2)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var mocker = new AutoMoqer();
|
||||||
|
|
||||||
|
var database = MockLib.GetEmptyDatabase(true);
|
||||||
|
|
||||||
|
database.InsertMany(firstSeriesFiles);
|
||||||
|
database.InsertMany(secondSeriesFiles);
|
||||||
|
|
||||||
|
mocker.SetConstant(database);
|
||||||
|
|
||||||
|
var result = mocker.Resolve<MediaFileProvider>().GetSeasonFiles(12, 1);
|
||||||
|
|
||||||
|
result.Should().HaveSameCount(firstSeriesFiles);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Scan_series_should_skip_series_with_no_episodes()
|
public void Scan_series_should_skip_series_with_no_episodes()
|
||||||
{
|
{
|
||||||
|
|
|
@ -88,6 +88,7 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="SeasonSearchJobTest.cs" />
|
||||||
<Compile Include="EventClientProviderTest.cs" />
|
<Compile Include="EventClientProviderTest.cs" />
|
||||||
<Compile Include="CentralDispatchTest.cs" />
|
<Compile Include="CentralDispatchTest.cs" />
|
||||||
<Compile Include="XbmcProviderTest.cs" />
|
<Compile Include="XbmcProviderTest.cs" />
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using AutoMoq;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Model;
|
||||||
|
using NzbDrone.Core.Model.Notification;
|
||||||
|
using NzbDrone.Core.Providers;
|
||||||
|
using NzbDrone.Core.Providers.Indexer;
|
||||||
|
using NzbDrone.Core.Providers.Jobs;
|
||||||
|
using NzbDrone.Core.Repository;
|
||||||
|
using NzbDrone.Core.Repository.Quality;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
public class SeasonSearchJobTest : TestBase
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void SeasonSearch_success()
|
||||||
|
{
|
||||||
|
var episodes = Builder<Episode>.CreateListOfSize(5)
|
||||||
|
.WhereAll()
|
||||||
|
.Have(e => e.SeriesId = 1)
|
||||||
|
.Have(e => e.SeasonNumber = 1)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var mocker = new AutoMoqer(MockBehavior.Strict);
|
||||||
|
|
||||||
|
var notification = new ProgressNotification("Season Search");
|
||||||
|
|
||||||
|
mocker.GetMock<EpisodeProvider>()
|
||||||
|
.Setup(c => c.GetEpisodesBySeason(1, 1)).Returns(episodes);
|
||||||
|
|
||||||
|
mocker.GetMock<EpisodeSearchJob>()
|
||||||
|
.Setup(c => c.Start(notification, It.IsAny<int>(), 0)).Verifiable();
|
||||||
|
|
||||||
|
//Act
|
||||||
|
mocker.Resolve<SeasonSearchJob>().Start(notification, 1, 1);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
mocker.VerifyAllMocks();
|
||||||
|
mocker.GetMock<EpisodeSearchJob>().Verify(c => c.Start(notification, It.IsAny<int>(), 0),
|
||||||
|
Times.Exactly(episodes.Count));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SeasonSearch_no_episodes()
|
||||||
|
{
|
||||||
|
var mocker = new AutoMoqer(MockBehavior.Strict);
|
||||||
|
var notification = new ProgressNotification("Season Search");
|
||||||
|
List<Episode> nullList = null;
|
||||||
|
|
||||||
|
mocker.GetMock<EpisodeProvider>()
|
||||||
|
.Setup(c => c.GetEpisodesBySeason(1, 1)).Returns(nullList);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
mocker.Resolve<SeasonSearchJob>().Start(notification, 1, 1);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
mocker.VerifyAllMocks();
|
||||||
|
mocker.GetMock<EpisodeSearchJob>().Verify(c => c.Start(notification, It.IsAny<int>(), 0),
|
||||||
|
Times.Never());
|
||||||
|
ExceptionVerification.ExcpectedWarns(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -104,6 +104,8 @@ namespace NzbDrone.Core
|
||||||
_kernel.Bind<IJob>().To<RenameEpisodeJob>().InSingletonScope();
|
_kernel.Bind<IJob>().To<RenameEpisodeJob>().InSingletonScope();
|
||||||
_kernel.Bind<IJob>().To<PostDownloadScanJob>().InSingletonScope();
|
_kernel.Bind<IJob>().To<PostDownloadScanJob>().InSingletonScope();
|
||||||
_kernel.Bind<IJob>().To<UpdateSceneMappingsJob>().InSingletonScope();
|
_kernel.Bind<IJob>().To<UpdateSceneMappingsJob>().InSingletonScope();
|
||||||
|
_kernel.Bind<IJob>().To<SeasonSearchJob>().InSingletonScope();
|
||||||
|
_kernel.Bind<IJob>().To<RenameSeasonJob>().InSingletonScope();
|
||||||
|
|
||||||
_kernel.Get<JobProvider>().Initialize();
|
_kernel.Get<JobProvider>().Initialize();
|
||||||
_kernel.Get<WebTimer>().StartTimer(30);
|
_kernel.Get<WebTimer>().StartTimer(30);
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Model
|
||||||
|
{
|
||||||
|
public class JobQueueItem : IEquatable<JobQueueItem>
|
||||||
|
{
|
||||||
|
public Type JobType { get; set; }
|
||||||
|
public int TargetId { get; set; }
|
||||||
|
public int SecondaryTargetId { get; set; }
|
||||||
|
|
||||||
|
public bool Equals(JobQueueItem other)
|
||||||
|
{
|
||||||
|
if (JobType == other.JobType && TargetId == other.TargetId
|
||||||
|
&& SecondaryTargetId == other.SecondaryTargetId)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -188,6 +188,7 @@
|
||||||
<Compile Include="Datastore\PetaPoco\PetaPoco.cs" />
|
<Compile Include="Datastore\PetaPoco\PetaPoco.cs" />
|
||||||
<Compile Include="Model\ConnectionInfoModel.cs" />
|
<Compile Include="Model\ConnectionInfoModel.cs" />
|
||||||
<Compile Include="Model\ExternalNotificationType.cs" />
|
<Compile Include="Model\ExternalNotificationType.cs" />
|
||||||
|
<Compile Include="Model\JobQueueItem.cs" />
|
||||||
<Compile Include="Model\LanguageType.cs" />
|
<Compile Include="Model\LanguageType.cs" />
|
||||||
<Compile Include="Model\Quality.cs" />
|
<Compile Include="Model\Quality.cs" />
|
||||||
<Compile Include="Model\SabnzbdInfoModel.cs" />
|
<Compile Include="Model\SabnzbdInfoModel.cs" />
|
||||||
|
@ -196,6 +197,8 @@
|
||||||
<Compile Include="Model\Xbmc\ErrorResult.cs" />
|
<Compile Include="Model\Xbmc\ErrorResult.cs" />
|
||||||
<Compile Include="Model\Xbmc\IconType.cs" />
|
<Compile Include="Model\Xbmc\IconType.cs" />
|
||||||
<Compile Include="Providers\Core\UdpProvider.cs" />
|
<Compile Include="Providers\Core\UdpProvider.cs" />
|
||||||
|
<Compile Include="Providers\Jobs\RenameSeasonJob.cs" />
|
||||||
|
<Compile Include="Providers\Jobs\SeasonSearchJob.cs" />
|
||||||
<Compile Include="Providers\Xbmc\ResourceManager.cs" />
|
<Compile Include="Providers\Xbmc\ResourceManager.cs" />
|
||||||
<Compile Include="Model\Xbmc\TvShowResult.cs" />
|
<Compile Include="Model\Xbmc\TvShowResult.cs" />
|
||||||
<Compile Include="Model\Xbmc\Params.cs" />
|
<Compile Include="Model\Xbmc\Params.cs" />
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 0; }
|
get { return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
DeleteSeries(notification, targetId);
|
DeleteSeries(notification, targetId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 60; }
|
get { return 60; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Start(ProgressNotification notification, int targetId)
|
public virtual void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
IList<Series> seriesToScan;
|
IList<Series> seriesToScan;
|
||||||
if (targetId == 0)
|
if (targetId == 0)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using Ninject;
|
||||||
using NzbDrone.Core.Model;
|
using NzbDrone.Core.Model;
|
||||||
using NzbDrone.Core.Model.Notification;
|
using NzbDrone.Core.Model.Notification;
|
||||||
using NzbDrone.Core.Repository;
|
using NzbDrone.Core.Repository;
|
||||||
|
@ -18,6 +19,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
|
|
||||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
[Inject]
|
||||||
public EpisodeSearchJob(InventoryProvider inventoryProvider, DownloadProvider downloadProvider,
|
public EpisodeSearchJob(InventoryProvider inventoryProvider, DownloadProvider downloadProvider,
|
||||||
IndexerProvider indexerProvider, EpisodeProvider episodeProvider,
|
IndexerProvider indexerProvider, EpisodeProvider episodeProvider,
|
||||||
SceneMappingProvider sceneNameMappingProvider)
|
SceneMappingProvider sceneNameMappingProvider)
|
||||||
|
@ -29,6 +31,11 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
_sceneNameMappingProvider = sceneNameMappingProvider;
|
_sceneNameMappingProvider = sceneNameMappingProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EpisodeSearchJob()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return "Episode Search"; }
|
get { return "Episode Search"; }
|
||||||
|
@ -39,7 +46,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 0; }
|
get { return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public virtual void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
if (targetId <= 0)
|
if (targetId <= 0)
|
||||||
throw new ArgumentOutOfRangeException("targetId");
|
throw new ArgumentOutOfRangeException("targetId");
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Name of the timer.
|
/// Name of the timer.
|
||||||
/// This is the name that will be visible in all UI elements
|
/// This is the name that will be visible in all UI elements
|
||||||
/// </summary>
|
/// </summary>\\\
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
/// <param name="notification">Notification object that is passed in by JobProvider.
|
/// <param name="notification">Notification object that is passed in by JobProvider.
|
||||||
/// this object should be used to update the progress on the UI</param>
|
/// this object should be used to update the progress on the UI</param>
|
||||||
/// <param name="targetId">The that should be used to limit the target of this job</param>
|
/// <param name="targetId">The that should be used to limit the target of this job</param>
|
||||||
void Start(ProgressNotification notification, int targetId);
|
/// /// <param name="secondaryTargetId">The that should be used to limit the target of this job</param>
|
||||||
|
void Start(ProgressNotification notification, int targetId, int secondaryTargetId);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -46,7 +46,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 1; }
|
get { return 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId )
|
||||||
{
|
{
|
||||||
_attemptedSeries = new List<int>();
|
_attemptedSeries = new List<int>();
|
||||||
ScanSeries(notification);
|
ScanSeries(notification);
|
||||||
|
@ -67,8 +67,8 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
_attemptedSeries.Add(currentSeries.SeriesId);
|
_attemptedSeries.Add(currentSeries.SeriesId);
|
||||||
notification.CurrentMessage = String.Format("Searching for '{0}'", new DirectoryInfo(currentSeries.Path).Name);
|
notification.CurrentMessage = String.Format("Searching for '{0}'", new DirectoryInfo(currentSeries.Path).Name);
|
||||||
|
|
||||||
_updateInfoJob.Start(notification, currentSeries.SeriesId);
|
_updateInfoJob.Start(notification, currentSeries.SeriesId, 0);
|
||||||
_diskScanJob.Start(notification, currentSeries.SeriesId);
|
_diskScanJob.Start(notification, currentSeries.SeriesId, 0);
|
||||||
|
|
||||||
var updatedSeries = _seriesProvider.GetSeries(currentSeries.SeriesId);
|
var updatedSeries = _seriesProvider.GetSeries(currentSeries.SeriesId);
|
||||||
AutoIgnoreSeasons(updatedSeries.SeriesId);
|
AutoIgnoreSeasons(updatedSeries.SeriesId);
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Core.Model;
|
||||||
using NzbDrone.Core.Model.Notification;
|
using NzbDrone.Core.Model.Notification;
|
||||||
using NzbDrone.Core.Repository;
|
using NzbDrone.Core.Repository;
|
||||||
using PetaPoco;
|
using PetaPoco;
|
||||||
|
@ -28,7 +29,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
private Thread _jobThread;
|
private Thread _jobThread;
|
||||||
private static bool _isRunning;
|
private static bool _isRunning;
|
||||||
|
|
||||||
private static readonly List<Tuple<Type, Int32>> _queue = new List<Tuple<Type, int>>();
|
private static readonly List<JobQueueItem> _queue = new List<JobQueueItem>();
|
||||||
|
|
||||||
private ProgressNotification _notification;
|
private ProgressNotification _notification;
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the active queue.
|
/// Gets the active queue.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static List<Tuple<Type, Int32>> Queue
|
public static List<JobQueueItem> Queue
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -122,8 +123,10 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
/// <param name="jobType">Type of the job that should be queued.</param>
|
/// <param name="jobType">Type of the job that should be queued.</param>
|
||||||
/// <param name="targetId">The targetId could be any Id parameter eg. SeriesId. it will be passed to the job implementation
|
/// <param name="targetId">The targetId could be any Id parameter eg. SeriesId. it will be passed to the job implementation
|
||||||
/// to allow it to filter it's target of execution.</param>
|
/// to allow it to filter it's target of execution.</param>
|
||||||
|
/// /// <param name="secondaryTargetId">The secondaryTargetId could be any Id parameter eg. SeasonNumber. it will be passed to
|
||||||
|
/// the timer implementation to further allow it to filter it's target of execution</param>
|
||||||
/// <remarks>Job is only added to the queue if same job with the same targetId doesn't already exist in the queue.</remarks>
|
/// <remarks>Job is only added to the queue if same job with the same targetId doesn't already exist in the queue.</remarks>
|
||||||
public virtual void QueueJob(Type jobType, int targetId = 0)
|
public virtual void QueueJob(Type jobType, int targetId = 0, int secondaryTargetId = 0)
|
||||||
{
|
{
|
||||||
Logger.Debug("Adding [{0}:{1}] to the queue", jobType.Name, targetId);
|
Logger.Debug("Adding [{0}:{1}] to the queue", jobType.Name, targetId);
|
||||||
|
|
||||||
|
@ -131,11 +134,16 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
{
|
{
|
||||||
lock (Queue)
|
lock (Queue)
|
||||||
{
|
{
|
||||||
var queueTuple = new Tuple<Type, int>(jobType, targetId);
|
var queueItem = new JobQueueItem
|
||||||
|
|
||||||
if (!Queue.Contains(queueTuple))
|
|
||||||
{
|
{
|
||||||
Queue.Add(queueTuple);
|
JobType = jobType,
|
||||||
|
TargetId = targetId,
|
||||||
|
SecondaryTargetId = secondaryTargetId
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!Queue.Contains(queueItem))
|
||||||
|
{
|
||||||
|
Queue.Add(queueItem);
|
||||||
Logger.Trace("Job [{0}:{1}] added to the queue", jobType.Name, targetId);
|
Logger.Trace("Job [{0}:{1}] added to the queue", jobType.Name, targetId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -195,7 +203,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Tuple<Type, int> job = null;
|
JobQueueItem job = null;
|
||||||
|
|
||||||
lock (Queue)
|
lock (Queue)
|
||||||
{
|
{
|
||||||
|
@ -208,7 +216,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
|
|
||||||
if (job != null)
|
if (job != null)
|
||||||
{
|
{
|
||||||
Execute(job.Item1, job.Item2);
|
Execute(job.JobType, job.TargetId, job.SecondaryTargetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -231,7 +239,9 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
/// <param name="jobType">Type of the job that should be executed</param>
|
/// <param name="jobType">Type of the job that should be executed</param>
|
||||||
/// <param name="targetId">The targetId could be any Id parameter eg. SeriesId. it will be passed to the timer implementation
|
/// <param name="targetId">The targetId could be any Id parameter eg. SeriesId. it will be passed to the timer implementation
|
||||||
/// to allow it to filter it's target of execution</param>
|
/// to allow it to filter it's target of execution</param>
|
||||||
private void Execute(Type jobType, int targetId = 0)
|
/// /// <param name="secondaryTargetId">The secondaryTargetId could be any Id parameter eg. SeasonNumber. it will be passed to
|
||||||
|
/// the timer implementation to further allow it to filter it's target of execution</param>
|
||||||
|
private void Execute(Type jobType, int targetId = 0, int secondaryTargetId = 0)
|
||||||
{
|
{
|
||||||
var jobImplementation = _jobs.Where(t => t.GetType() == jobType).Single();
|
var jobImplementation = _jobs.Where(t => t.GetType() == jobType).Single();
|
||||||
if (jobImplementation == null)
|
if (jobImplementation == null)
|
||||||
|
@ -251,7 +261,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
var sw = Stopwatch.StartNew();
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
_notificationProvider.Register(_notification);
|
_notificationProvider.Register(_notification);
|
||||||
jobImplementation.Start(_notification, targetId);
|
jobImplementation.Start(_notification, targetId, secondaryTargetId);
|
||||||
_notification.Status = ProgressNotificationStatus.Completed;
|
_notification.Status = ProgressNotificationStatus.Completed;
|
||||||
|
|
||||||
settings.LastExecution = DateTime.Now;
|
settings.LastExecution = DateTime.Now;
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 1; }
|
get { return 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Start(ProgressNotification notification, int targetId)
|
public virtual void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
var dropFolder = _configProvider.SabDropDirectory;
|
var dropFolder = _configProvider.SabDropDirectory;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ninject;
|
using System;
|
||||||
|
using Ninject;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Model.Notification;
|
using NzbDrone.Core.Model.Notification;
|
||||||
using NzbDrone.Core.Providers.Core;
|
using NzbDrone.Core.Providers.Core;
|
||||||
|
@ -30,10 +31,14 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 0; }
|
get { return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
|
if (targetId <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException("targetId");
|
||||||
|
|
||||||
var episode = _mediaFileProvider.GetEpisodeFile(targetId);
|
var episode = _mediaFileProvider.GetEpisodeFile(targetId);
|
||||||
_diskScanProvider.MoveEpisodeFile(episode);
|
_diskScanProvider.MoveEpisodeFile(episode);
|
||||||
|
notification.CurrentMessage = String.Format("Episode rename completed for: {0} ", targetId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
using System;
|
||||||
|
using Ninject;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Model.Notification;
|
||||||
|
using NzbDrone.Core.Providers.Core;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Providers.Jobs
|
||||||
|
{
|
||||||
|
public class RenameSeasonJob : IJob
|
||||||
|
{
|
||||||
|
private readonly MediaFileProvider _mediaFileProvider;
|
||||||
|
private readonly DiskScanProvider _diskScanProvider;
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public RenameSeasonJob(MediaFileProvider mediaFileProvider, DiskScanProvider diskScanProvider)
|
||||||
|
{
|
||||||
|
_mediaFileProvider = mediaFileProvider;
|
||||||
|
_diskScanProvider = diskScanProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Rename Season"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int DefaultInterval
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
|
{
|
||||||
|
if (targetId <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException("targetId");
|
||||||
|
|
||||||
|
if (secondaryTargetId <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException("secondaryTargetId");
|
||||||
|
|
||||||
|
Logger.Debug("Getting episodes from database for series: {0} and season: {1}", targetId, secondaryTargetId);
|
||||||
|
var episodeFiles = _mediaFileProvider.GetSeasonFiles(targetId, secondaryTargetId);
|
||||||
|
|
||||||
|
if (episodeFiles == null || episodeFiles.Count == 0)
|
||||||
|
{
|
||||||
|
Logger.Warn("No episodes in database found for series: {0} and season: {1}. No", targetId, secondaryTargetId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var episodeFile in episodeFiles)
|
||||||
|
{
|
||||||
|
_diskScanProvider.MoveEpisodeFile(episodeFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
notification.CurrentMessage = String.Format("Season rename completed for Series: {0} Season: {1}", targetId, secondaryTargetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 15; }
|
get { return 15; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start(ProgressNotification notification, int targetId)
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
var reports = new List<EpisodeParseResult>();
|
var reports = new List<EpisodeParseResult>();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Model;
|
||||||
|
using NzbDrone.Core.Model.Notification;
|
||||||
|
using NzbDrone.Core.Repository;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Providers.Jobs
|
||||||
|
{
|
||||||
|
public class SeasonSearchJob : IJob
|
||||||
|
{
|
||||||
|
private readonly EpisodeProvider _episodeProvider;
|
||||||
|
private readonly EpisodeSearchJob _episodeSearchJob;
|
||||||
|
|
||||||
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
public SeasonSearchJob(EpisodeProvider episodeProvider, EpisodeSearchJob episodeSearchJob)
|
||||||
|
{
|
||||||
|
_episodeProvider = episodeProvider;
|
||||||
|
_episodeSearchJob = episodeSearchJob;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "Season Search"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int DefaultInterval
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
|
{
|
||||||
|
if (targetId <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException("targetId");
|
||||||
|
|
||||||
|
if (secondaryTargetId <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException("secondaryTargetId");
|
||||||
|
|
||||||
|
Logger.Debug("Getting episodes from database for series: {0} and season: {1}", targetId, secondaryTargetId);
|
||||||
|
var episodes = _episodeProvider.GetEpisodesBySeason(targetId, secondaryTargetId);
|
||||||
|
|
||||||
|
if (episodes == null)
|
||||||
|
{
|
||||||
|
Logger.Warn("No episodes in database found for series: {0} and season: {1}. No", targetId, secondaryTargetId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Todo: Search for a full season NZB before individual episodes
|
||||||
|
|
||||||
|
foreach (var episode in episodes)
|
||||||
|
{
|
||||||
|
_episodeSearchJob.Start(notification, episode.EpisodeId, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,7 +33,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 1440; } //Daily
|
get { return 1440; } //Daily
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Start(ProgressNotification notification, int targetId)
|
public virtual void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
IList<Series> seriesToUpdate;
|
IList<Series> seriesToUpdate;
|
||||||
if (targetId == 0)
|
if (targetId == 0)
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace NzbDrone.Core.Providers.Jobs
|
||||||
get { return 720; } //Every 12 hours
|
get { return 720; } //Every 12 hours
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Start(ProgressNotification notification, int targetId)
|
public virtual void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
|
||||||
{
|
{
|
||||||
_sceneNameMappingProvider.UpdateMappings();
|
_sceneNameMappingProvider.UpdateMappings();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@ namespace NzbDrone.Core.Providers
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public virtual int Add(EpisodeFile episodeFile)
|
public virtual int Add(EpisodeFile episodeFile)
|
||||||
{
|
{
|
||||||
return Convert.ToInt32(_database.Insert(episodeFile));
|
return Convert.ToInt32(_database.Insert(episodeFile));
|
||||||
|
@ -65,7 +63,12 @@ namespace NzbDrone.Core.Providers
|
||||||
|
|
||||||
public virtual IList<EpisodeFile> GetSeriesFiles(int seriesId)
|
public virtual IList<EpisodeFile> GetSeriesFiles(int seriesId)
|
||||||
{
|
{
|
||||||
return _database.Fetch<EpisodeFile>("WHERE seriesId= @0", seriesId);
|
return _database.Fetch<EpisodeFile>("WHERE SeriesId= @0", seriesId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IList<EpisodeFile> GetSeasonFiles(int seriesId, int seasonNumber)
|
||||||
|
{
|
||||||
|
return _database.Fetch<EpisodeFile>("WHERE SeriesId= @0 AND SeasonNumber = @1", seriesId, seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Tuple<int, int> GetEpisodeFilesCount(int seriesId)
|
public virtual Tuple<int, int> GetEpisodeFilesCount(int seriesId)
|
||||||
|
@ -132,7 +135,6 @@ namespace NzbDrone.Core.Providers
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual string GetNewFilename(IList<Episode> episodes, string seriesTitle, QualityTypes quality)
|
public virtual string GetNewFilename(IList<Episode> episodes, string seriesTitle, QualityTypes quality)
|
||||||
{
|
{
|
||||||
var separatorStyle = EpisodeSortingHelper.GetSeparatorStyle(_configProvider.SortingSeparatorStyle);
|
var separatorStyle = EpisodeSortingHelper.GetSeparatorStyle(_configProvider.SortingSeparatorStyle);
|
||||||
|
|
|
@ -11,27 +11,40 @@ namespace NzbDrone.Web.Controllers
|
||||||
{
|
{
|
||||||
public class EpisodeController : Controller
|
public class EpisodeController : Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly JobProvider _jobProvider;
|
private readonly JobProvider _jobProvider;
|
||||||
|
|
||||||
|
|
||||||
public EpisodeController(JobProvider jobProvider)
|
public EpisodeController(JobProvider jobProvider)
|
||||||
{
|
{
|
||||||
|
|
||||||
_jobProvider = jobProvider;
|
_jobProvider = jobProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
public JsonResult Search(int episodeId)
|
public JsonResult Search(int episodeId)
|
||||||
{
|
{
|
||||||
_jobProvider.QueueJob(typeof(EpisodeSearchJob), episodeId);
|
_jobProvider.QueueJob(typeof(EpisodeSearchJob), episodeId);
|
||||||
return new JsonResult { Data = "ok" };
|
return new JsonResult { Data = "ok" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public JsonResult SearchSeason(int seriesId, int seasonNumber)
|
||||||
|
{
|
||||||
|
_jobProvider.QueueJob(typeof(SeasonSearchJob), seriesId, seasonNumber);
|
||||||
|
return new JsonResult { Data = "ok" };
|
||||||
|
}
|
||||||
|
|
||||||
public JsonResult Rename(int episodeFileId)
|
public JsonResult Rename(int episodeFileId)
|
||||||
{
|
{
|
||||||
_jobProvider.QueueJob(typeof(RenameEpisodeJob), episodeFileId);
|
_jobProvider.QueueJob(typeof(RenameEpisodeJob), episodeFileId);
|
||||||
|
|
||||||
return new JsonResult { Data = "ok" };
|
return new JsonResult { Data = "ok" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JsonResult RenameSeason(int seriesId, int seasonNumber)
|
||||||
|
{
|
||||||
|
_jobProvider.QueueJob(typeof(RenameSeasonJob), seriesId, seasonNumber);
|
||||||
|
|
||||||
|
return new JsonResult { Data = "ok" };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using NzbDrone.Core.Helpers;
|
using NzbDrone.Core.Helpers;
|
||||||
|
using NzbDrone.Core.Model;
|
||||||
using NzbDrone.Core.Providers;
|
using NzbDrone.Core.Providers;
|
||||||
using NzbDrone.Core.Providers.Core;
|
using NzbDrone.Core.Providers.Core;
|
||||||
using NzbDrone.Core.Providers.Jobs;
|
using NzbDrone.Core.Providers.Jobs;
|
||||||
|
@ -29,7 +30,11 @@ namespace NzbDrone.Web.Controllers
|
||||||
|
|
||||||
public ActionResult Jobs()
|
public ActionResult Jobs()
|
||||||
{
|
{
|
||||||
ViewData["Queue"] = JobProvider.Queue.Select(c => new Tuple<String, int>(c.Item1.Name, c.Item2));
|
ViewData["Queue"] = JobProvider.Queue.Select(c => new JobQueueItemModel {
|
||||||
|
Name = c.JobType.Name,
|
||||||
|
TargetId = c.TargetId,
|
||||||
|
SecondaryTargetId = c.SecondaryTargetId
|
||||||
|
});
|
||||||
return View(_jobProvider.All());
|
return View(_jobProvider.All());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace NzbDrone.Web.Models
|
||||||
|
{
|
||||||
|
public class JobQueueItemModel
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int TargetId { get; set; }
|
||||||
|
public int SecondaryTargetId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -165,6 +165,7 @@
|
||||||
<Compile Include="Helpers\IsCurrentActionHelper.cs" />
|
<Compile Include="Helpers\IsCurrentActionHelper.cs" />
|
||||||
<Compile Include="Models\ExistingSeriesModel.cs" />
|
<Compile Include="Models\ExistingSeriesModel.cs" />
|
||||||
<Compile Include="Models\AddNewSeriesModel.cs" />
|
<Compile Include="Models\AddNewSeriesModel.cs" />
|
||||||
|
<Compile Include="Models\JobQueueItemModel.cs" />
|
||||||
<Compile Include="Models\NotificationResult.cs" />
|
<Compile Include="Models\NotificationResult.cs" />
|
||||||
<Compile Include="Models\PendingProcessingModel.cs" />
|
<Compile Include="Models\PendingProcessingModel.cs" />
|
||||||
<Compile Include="Models\QualityTypeModel.cs" />
|
<Compile Include="Models\QualityTypeModel.cs" />
|
||||||
|
|
|
@ -10,4 +10,3 @@ function searchForEpisode(id) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,11 @@ var ignoredImage = '../../Content/Images/ignored.png';
|
||||||
var seriesId = 0;
|
var seriesId = 0;
|
||||||
var saveSeasonIgnoreUrl = '../Series/SaveSeasonIgnore';
|
var saveSeasonIgnoreUrl = '../Series/SaveSeasonIgnore';
|
||||||
var saveEpisodeIgnoreUrl = '../Series/SaveEpisodeIgnore';
|
var saveEpisodeIgnoreUrl = '../Series/SaveEpisodeIgnore';
|
||||||
|
var renameEpisodeUrl = '../Episode/Rename';
|
||||||
|
var renameSeasonUrl = '../Episode/RenameSeason';
|
||||||
|
var searchSeasonUrl = '../Episode/SearchSeason';
|
||||||
|
|
||||||
|
//Episode Ignore Functions
|
||||||
$(".ignoreEpisode").live("click", function () {
|
$(".ignoreEpisode").live("click", function () {
|
||||||
var toggle = $(this);
|
var toggle = $(this);
|
||||||
var ignored = toggle.hasClass('ignored');
|
var ignored = toggle.hasClass('ignored');
|
||||||
|
@ -123,6 +127,7 @@ function grid_dataBound(e) {
|
||||||
toggleMaster(seasonNumber);
|
toggleMaster(seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Episode Ignore Saving
|
||||||
function saveSeasonIgnore(seasonNumber, ignored) {
|
function saveSeasonIgnore(seasonNumber, ignored) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
|
@ -144,3 +149,38 @@ function saveEpisodeIgnore(episodeId, ignored) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Episode Renaming
|
||||||
|
function renameEpisode(id) {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: renameEpisodeUrl,
|
||||||
|
data: jQuery.param({ episodeFileId: id }),
|
||||||
|
error: function (req, status, error) {
|
||||||
|
alert("Sorry! We could rename " + id + " at this time. " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameSeason(seriesId, seasonNumber) {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: renameSeasonUrl,
|
||||||
|
data: jQuery.param({ seriesId: seriesId, seasonNumber: seasonNumber }),
|
||||||
|
error: function (req, status, error) {
|
||||||
|
alert("Sorry! We could rename series: " + seriesId + " season: " + seasonNumber + " at this time. " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Season Search
|
||||||
|
function searchSeason(seriesId, seasonNumber) {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: searchSeasonUrl,
|
||||||
|
data: jQuery.param({ seriesId: seriesId, seasonNumber: seasonNumber }),
|
||||||
|
error: function (req, status, error) {
|
||||||
|
alert("Sorry! We could search for series: " + seriesId + " season: " + seasonNumber + " at this time. " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -84,8 +84,11 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@foreach (var season in Model.Seasons.Where(s => s > 0).Reverse())
|
@foreach (var s in Model.Seasons.Where(s => s > 0).Reverse())
|
||||||
{
|
{
|
||||||
|
var seriesId = @Model.SeriesId;
|
||||||
|
var season = s;
|
||||||
|
|
||||||
<h3>
|
<h3>
|
||||||
Season @season</h3>
|
Season @season</h3>
|
||||||
<div class="grid-container">
|
<div class="grid-container">
|
||||||
|
@ -107,9 +110,10 @@
|
||||||
columns.Bound(c => c.Quality).Width(0);
|
columns.Bound(c => c.Quality).Width(0);
|
||||||
columns.Bound(c => c.Status).Width(0);
|
columns.Bound(c => c.Status).Width(0);
|
||||||
columns.Bound(o => o.EpisodeId).Title("")
|
columns.Bound(o => o.EpisodeId).Title("")
|
||||||
.ClientTemplate("<a href='#Search' onClick=\"searchForEpisode('<#= EpisodeId #>'); return false;\">Search</a>"
|
.ClientTemplate("<a href=\"../Episode/Season?episodeId=<#= EpisodeId #>\" onclick=\"searchForEpisode('<#= EpisodeId #>'); return false;\">Search</a>"
|
||||||
+ " | " +
|
+ " | " +
|
||||||
"<a href='#Rename' onClick=\"renameEpisode('<#= EpisodeFileId #>'); return false;\">Rename</a>");
|
"<a href=\"../Episode/Rename?episodeFileId=<#= EpisodeId #>\" onclick=\"renameEpisode('<#= EpisodeFileId #>'); return false;\">Rename</a>"
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #> </br><#= Path #> </div>"))
|
.DetailView(detailView => detailView.ClientTemplate("<div><#= Overview #> </br><#= Path #> </div>"))
|
||||||
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(false))
|
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.EpisodeNumber).Descending()).Enabled(false))
|
||||||
|
@ -118,10 +122,13 @@
|
||||||
d =>
|
d =>
|
||||||
d.Ajax().Select("_AjaxSeasonGrid", "Series",
|
d.Ajax().Select("_AjaxSeasonGrid", "Series",
|
||||||
new RouteValueDictionary { { "seriesId", Model.SeriesId }, { "seasonNumber", season } }))
|
new RouteValueDictionary { { "seriesId", Model.SeriesId }, { "seasonNumber", season } }))
|
||||||
.ToolBar(
|
.ToolBar(toolbar => toolbar.Template(@<text>
|
||||||
c =>
|
<div>
|
||||||
c.Custom().Text("Rename Season").Action("RenameSeason", "Series", new { seasonId = season })
|
<a href="../Episode/SearchSeason?seriesId=@seriesId&seasonNumber=@season" onclick="searchSeason('@seriesId', @season); return false;">Search for Season</a>
|
||||||
.ButtonType(GridButtonType.Text))
|
|
|
||||||
|
<a href="../Episode/RenameSeason?seriesId=@seriesId&seasonNumber=@season" onclick="renameSeason('@seriesId', @season); return false;">Rename Season</a>
|
||||||
|
</div>
|
||||||
|
</text>))
|
||||||
.ClientEvents(clientEvents =>
|
.ClientEvents(clientEvents =>
|
||||||
{
|
{
|
||||||
clientEvents.OnRowDataBound("grid_rowBound");
|
clientEvents.OnRowDataBound("grid_rowBound");
|
||||||
|
@ -171,24 +178,6 @@
|
||||||
}
|
}
|
||||||
@section Scripts{
|
@section Scripts{
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function episodeDetailExpanded(e) {
|
|
||||||
$console.log("OnDetailViewExpand :: " + e.masterRow.cells[1].innerHTML);
|
|
||||||
}
|
|
||||||
|
|
||||||
var renameEpisodeUrl = '@Url.Action("Rename", "Episode")';
|
|
||||||
|
|
||||||
function renameEpisode(id) {
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: renameEpisodeUrl,
|
|
||||||
data: jQuery.param({ episodeFileId: id }),
|
|
||||||
error: function (req, status, error) {
|
|
||||||
alert("Sorry! We could rename " + id + " at this time. " + error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
seriesId = @Model.SeriesId;
|
seriesId = @Model.SeriesId;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
@using System.Collections
|
@using System.Collections
|
||||||
|
@using NzbDrone.Web.Models
|
||||||
@model IEnumerable<NzbDrone.Core.Repository.JobDefinition>
|
@model IEnumerable<NzbDrone.Core.Repository.JobDefinition>
|
||||||
@section TitleContent{
|
@section TitleContent{
|
||||||
Jobs
|
Jobs
|
||||||
|
@ -9,7 +10,9 @@ Jobs
|
||||||
|
|
||||||
Items currently in queue
|
Items currently in queue
|
||||||
|
|
||||||
@{Html.Telerik().Grid((IEnumerable<Tuple<String, int>>)ViewData["Queue"]).Name("QueueGrid")
|
@{Html.Telerik().Grid((IEnumerable<JobQueueItemModel>)ViewData["Queue"]).Name("QueueGrid")
|
||||||
.Columns(c => c.Bound(g => g.Item1).Title("Type").Width(100)).Columns(c => c.Bound(g => g.Item2).Title("Target"))
|
.Columns(c => c.Bound(g => g.Name).Title("Type").Width(100))
|
||||||
|
.Columns(c => c.Bound(g => g.TargetId).Title("Target"))
|
||||||
|
.Columns(c => c.Bound(g => g.SecondaryTargetId).Title("Secondary Target"))
|
||||||
.Render();}
|
.Render();}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue