1
0
Fork 0
mirror of https://github.com/Radarr/Radarr synced 2024-12-24 17:01:38 +00:00

Added two new Episode Statuses - Unpacking and Failed.

Tests added to support new Statuses.
PostDownloadScanJob will update PostDownloadStatus for failed or unpacking.
ImportFile will set the PostDownloadStatus to Processed when added to the database.
This commit is contained in:
Mark McDowall 2011-10-11 20:44:19 -07:00
parent c534d47b0a
commit 5098ea3249
15 changed files with 234 additions and 10 deletions

View file

@ -7,6 +7,7 @@
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
@ -1464,5 +1465,42 @@ public void IsFirstOrLastEpisodeInSeason_true_last()
//Assert
result.Should().BeFalse();
}
[TestCase("The Office (US) - S01E05 - Episode Title", PostDownloadStatusType.Unpacking, 1)]
[TestCase("The Office (US) - S01E05 - Episode Title", PostDownloadStatusType.Failed, 1)]
[TestCase("The Office (US) - S01E05E06 - Episode Title", PostDownloadStatusType.Unpacking, 2)]
[TestCase("The Office (US) - S01E05E06 - Episode Title", PostDownloadStatusType.Failed, 2)]
[TestCase("The Office (US) - Season 01 - Episode Title", PostDownloadStatusType.Unpacking, 10)]
[TestCase("The Office (US) - Season 01 - Episode Title", PostDownloadStatusType.Failed, 10)]
public void SetPostDownloadStatus(string folderName, PostDownloadStatusType postDownloadStatus, int episodeCount)
{
var db = MockLib.GetEmptyDatabase();
var mocker = new AutoMoqer();
mocker.SetConstant(db);
var fakeSeries = Builder<Series>.CreateNew()
.With(s => s.SeriesId = 12345)
.With(s => s.CleanTitle = "officeus")
.Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10)
.WhereAll()
.Have(c => c.SeriesId = 12345)
.Have(c => c.SeasonNumber = 1)
.Have(c => c.PostDownloadStatus = PostDownloadStatusType.Unknown)
.Build();
db.Insert(fakeSeries);
db.InsertMany(fakeEpisodes);
mocker.GetMock<SeriesProvider>().Setup(s => s.FindSeries("officeus")).Returns(fakeSeries);
//Act
mocker.Resolve<EpisodeProvider>().SetPostDownloadStatus(folderName, postDownloadStatus);
//Assert
var result = db.Fetch<Episode>();
result.Where(e => e.PostDownloadStatus == postDownloadStatus).Count().Should().Be(episodeCount);
}
}
}

View file

@ -101,7 +101,6 @@ public void Single_GetSeason_Episode_Doesnt_exists_should_add()
db.Fetch<Episode>().Should().HaveCount(1);
}
[Test]
public void Multi_GetSeason_Episode_Exists()
{
@ -235,5 +234,69 @@ public void Get_Multi_Episode_Zero_Doesnt_Exist_Should_not_add_ignored()
db.Fetch<Episode>().Should().HaveCount(2);
ep.First().Ignored.Should().BeFalse();
}
[Test]
public void Full_Season_return_all_episodes_for_season()
{
var mocker = new AutoMoqer();
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10)
.WhereAll()
.Have(e => e.SeriesId = fakeSeries.SeriesId)
.Have(e => e.SeasonNumber = 2)
.Build();
db.Insert(fakeSeries);
db.InsertMany(fakeEpisodes);
var parseResult = new EpisodeParseResult
{
Series = fakeSeries,
SeasonNumber = 2,
EpisodeNumbers = new List<int>(),
FullSeason = true
};
var ep = mocker.Resolve<EpisodeProvider>().GetEpisodesByParseResult(parseResult);
ep.Should().HaveCount(10);
db.Fetch<Episode>().Should().HaveCount(10);
}
[Test]
public void No_Episodes_Not_a_proper_full_season_release()
{
var mocker = new AutoMoqer();
var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(10)
.WhereAll()
.Have(e => e.SeriesId = fakeSeries.SeriesId)
.Have(e => e.SeasonNumber = 2)
.Build();
db.Insert(fakeSeries);
db.InsertMany(fakeEpisodes);
var parseResult = new EpisodeParseResult
{
Series = fakeSeries,
SeasonNumber = 2,
EpisodeNumbers = new List<int>(),
FullSeason = false
};
var ep = mocker.Resolve<EpisodeProvider>().GetEpisodesByParseResult(parseResult);
ep.Should().HaveCount(0);
db.Fetch<Episode>().Should().HaveCount(10);
}
}
}

View file

@ -108,5 +108,27 @@ public void low_air_date()
episode.Status.Should().Be(EpisodeStatusType.NotAired);
}
[TestCase(false, false, EpisodeStatusType.Failed, PostDownloadStatusType.Failed)]
[TestCase(false, false, EpisodeStatusType.Unpacking, PostDownloadStatusType.Unpacking)]
[TestCase(true, false, EpisodeStatusType.Ready, PostDownloadStatusType.Failed)]
[TestCase(true, true, EpisodeStatusType.Ready, PostDownloadStatusType.Unpacking)]
public void episode_downloaded_post_download_status_is_used(bool hasEpisodes, bool ignored,
EpisodeStatusType status, PostDownloadStatusType postDownloadStatus)
{
Episode episode = Builder<Episode>.CreateNew()
.With(e => e.Ignored = ignored)
.With(e => e.EpisodeFileId = 0)
.With(e => e.GrabDate = DateTime.Now.AddHours(22))
.With(e => e.PostDownloadStatus = postDownloadStatus)
.Build();
if (hasEpisodes)
{
episode.EpisodeFileId = 12;
}
Assert.AreEqual(status, episode.Status);
}
}
}

View file

@ -21,7 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

View file

@ -0,0 +1,21 @@
using System;
using System.Data;
using Migrator.Framework;
namespace NzbDrone.Core.Datastore.Migrations
{
[Migration(20111011)]
public class Migration20111011 : Migration
{
public override void Up()
{
Database.AddColumn("Episodes", "PostDownloadStatus", DbType.Int32, ColumnProperty.Null);
}
public override void Down()
{
throw new NotImplementedException();
}
}
}

View file

@ -5,7 +5,7 @@ public enum EpisodeStatusType
/// <summary>
/// Episode has not aired yet
/// </summary>
NotAired ,
NotAired,
/// <summary>
/// Episode is ignored
@ -16,12 +16,22 @@ public enum EpisodeStatusType
/// Episode has aired but no episode
/// files have avilable
/// </summary>
Missing ,
Missing,
/// <summary>
/// Episode is being downloaded
/// </summary>
Downloading ,
Downloading,
/// <summary>
/// Episode has been downloaded and is unpacking (_UNPACK_)
/// </summary>
Unpacking,
/// <summary>
/// Episode has failed to download properly (_FAILED_)
/// </summary>
Failed,
/// <summary>
/// Episode is present in disk

View file

@ -0,0 +1,25 @@
namespace NzbDrone.Core.Model
{
public enum PostDownloadStatusType
{
/// <summary>
/// Unknown (Default)
/// </summary>
Unknown = 0,
/// <summary>
/// Unpacking
/// </summary>
Unpacking = 1,
/// <summary>
/// Failed
/// </summary>
Failed = 2,
/// <summary>
/// Processed
/// </summary>
Processed = 3
}
}

View file

@ -176,6 +176,7 @@
<Compile Include="Datastore\MigrationLogger.cs" />
<Compile Include="Datastore\MigrationsHelper.cs" />
<Compile Include="Datastore\CustomeMapper.cs" />
<Compile Include="Datastore\Migrations\Migration20111011.cs" />
<Compile Include="Datastore\Migrations\Migration20110909.cs" />
<Compile Include="Datastore\Migrations\Migration20110726.cs" />
<Compile Include="Datastore\Migrations\Migration20110707.cs" />
@ -192,6 +193,7 @@
<Compile Include="Model\AtomicParsleyTitleType.cs" />
<Compile Include="Model\AuthenticationType.cs" />
<Compile Include="Model\ConnectionInfoModel.cs" />
<Compile Include="Model\PostDownloadStatusType.cs" />
<Compile Include="Model\ExternalNotificationType.cs" />
<Compile Include="Model\JobQueueItem.cs" />
<Compile Include="Model\LanguageType.cs" />

View file

@ -4,6 +4,7 @@
using System.Linq;
using Ninject;
using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using PetaPoco;
@ -146,6 +147,7 @@ public virtual EpisodeFile ImportFile(Series series, string filePath)
foreach (var ep in episodes)
{
ep.EpisodeFileId = fileId;
ep.PostDownloadStatus = PostDownloadStatusType.Processed;
_episodeProvider.UpdateEpisode(ep);
Logger.Debug("Linking [{0}] > [{1}]", filePath, ep);
}

View file

@ -125,6 +125,14 @@ public virtual IList<Episode> GetEpisodesByParseResult(EpisodeParseResult parseR
{
var result = new List<Episode>();
if (parseResult.EpisodeNumbers.Count == 0 && parseResult.FullSeason)
{
result.AddRange(GetEpisodesBySeason(parseResult.Series.SeriesId, parseResult.SeasonNumber));
//Return now as no further processing is required
return result;
}
foreach (var episodeNumber in parseResult.EpisodeNumbers)
{
var episodeInfo = GetEpisode(parseResult.Series.SeriesId, parseResult.SeasonNumber, episodeNumber);
@ -396,5 +404,20 @@ public virtual void DeleteInvalidEpisodes(Series series, TvdbSeries tvDbSeriesIn
Logger.Trace("Finished deleting invalid episodes for {0}", series.SeriesId);
}
public virtual void SetPostDownloadStatus(string folderName, PostDownloadStatusType postDownloadStatus)
{
var parseResult = Parser.ParseTitle(folderName);
parseResult.Series = _seriesProvider.FindSeries(parseResult.CleanTitle);
var episodeIds = GetEpisodesByParseResult(parseResult).Select(e => e.EpisodeId);
var episodeIdString = String.Join(", ", episodeIds);
var episodeIdQuery = String.Format(@"UPDATE Episodes SET PostDownloadStatus = {0}
WHERE EpisodeId IN ({1})", (int)postDownloadStatus, episodeIdString);
Logger.Trace("Updating PostDownloadStatus for all episodeIds in {0}", episodeIdString);
_database.Execute(episodeIdQuery);
}
}
}

View file

@ -2,6 +2,7 @@
using System.IO;
using Ninject;
using NLog;
using NzbDrone.Core.Model;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers.Core;
@ -13,16 +14,19 @@ public class PostDownloadScanJob : IJob
private readonly DiskProvider _diskProvider;
private readonly DiskScanProvider _diskScanProvider;
private readonly SeriesProvider _seriesProvider;
private readonly EpisodeProvider _episodeProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
[Inject]
public PostDownloadScanJob(ConfigProvider configProvider, DiskProvider diskProvider,
DiskScanProvider diskScanProvider, SeriesProvider seriesProvider)
DiskScanProvider diskScanProvider, SeriesProvider seriesProvider,
EpisodeProvider episodeProvider)
{
_configProvider = configProvider;
_diskProvider = diskProvider;
_diskScanProvider = diskScanProvider;
_seriesProvider = seriesProvider;
_episodeProvider = episodeProvider;
}
public PostDownloadScanJob()
@ -63,12 +67,14 @@ public virtual void Start(ProgressNotification notification, int targetId, int s
if (subfolderInfo.Name.StartsWith("_UNPACK_", StringComparison.CurrentCultureIgnoreCase))
{
_episodeProvider.SetPostDownloadStatus(subfolderInfo.Name.Substring(8), PostDownloadStatusType.Unpacking);
Logger.Debug("Folder [{0}] is still being unpacked. skipping.", subfolder);
continue;
}
if (subfolderInfo.Name.StartsWith("_FAILED_", StringComparison.CurrentCultureIgnoreCase))
{
_episodeProvider.SetPostDownloadStatus(subfolderInfo.Name.Substring(8), PostDownloadStatusType.Failed);
Logger.Debug("Folder [{0}] is marked as failed. skipping.", subfolder);
continue;
}

View file

@ -23,6 +23,8 @@ public class Episode
public Boolean Ignored { get; set; }
public PostDownloadStatusType PostDownloadStatus { get; set; }
/// <summary>
/// Gets or sets the grab date.
/// </summary>
@ -39,15 +41,23 @@ public EpisodeStatusType Status
{
if (EpisodeFileId != 0) return EpisodeStatusType.Ready;
if (GrabDate != null && GrabDate.Value.AddDays(1) >= DateTime.Now)
if (GrabDate != null)
{
return EpisodeStatusType.Downloading;
if (PostDownloadStatus == PostDownloadStatusType.Unpacking)
return EpisodeStatusType.Unpacking;
if (PostDownloadStatus == PostDownloadStatusType.Failed)
return EpisodeStatusType.Failed;
if (GrabDate.Value.AddDays(1) >= DateTime.Now)
return EpisodeStatusType.Downloading;
}
if (GrabDate != null && GrabDate.Value.AddDays(1) >= DateTime.Now)
return EpisodeStatusType.Downloading;
if (AirDate != null && AirDate.Value.Date < DateTime.Now)
{
return EpisodeStatusType.Missing;
}
return EpisodeStatusType.NotAired;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -333,6 +333,7 @@
<Content Include="Content\Images\close.png" />
<Content Include="Content\Images\Downloading.png" />
<Content Include="Content\Images\error.png" />
<Content Include="Content\Images\Failed.png" />
<Content Include="Content\Images\gritter.png" />
<Content Include="Content\Images\Missing.png" />
<Content Include="Content\Images\NotAired.png" />
@ -340,6 +341,7 @@
<Content Include="Content\Images\Rename.png" />
<Content Include="Content\Images\Search.png" />
<Content Include="Content\Images\success.png" />
<Content Include="Content\Images\Unpacking.png" />
<Content Include="Content\jquery.gritter.css" />
<Content Include="Content\Menu.css" />
<Compile Include="App_GlobalResources\EditorLocalization.bg-BG.designer.cs">