Update Music Tests, Added Cases for Should Refresh Artist, Cleanup Skyhook Resources

pull/6/head
Qstick 7 years ago
parent d10fb92a09
commit 6e4638f7b1

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
@ -7,7 +7,7 @@ using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MediaCover; using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MetadataSource.SkyHook; using NzbDrone.Core.MetadataSource.SkyHook;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv; using NzbDrone.Core.Music;
using NzbDrone.Test.Common.Categories; using NzbDrone.Test.Common.Categories;
namespace NzbDrone.Core.Test.MetadataSource.SkyHook namespace NzbDrone.Core.Test.MetadataSource.SkyHook
@ -22,88 +22,75 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
UseRealHttp(); UseRealHttp();
} }
[TestCase(75978, "Family Guy")] [TestCase("f59c5520-5f46-4d2c-b2c4-822eabf53419", "Linkin Park")]
[TestCase(83462, "Castle (2009)")] [TestCase("66c662b6-6e2f-4930-8610-912e24c63ed1", "AC/DC")]
[TestCase(266189, "The Blacklist")] public void should_be_able_to_get_artist_detail(string mbId, string name)
public void should_be_able_to_get_series_detail(int tvdbId, string title)
{ {
var details = Subject.GetSeriesInfo(tvdbId); var details = Subject.GetArtistInfo(mbId);
ValidateSeries(details.Item1); ValidateArtist(details.Item1);
ValidateEpisodes(details.Item2); ValidateAlbums(details.Item2);
details.Item1.Title.Should().Be(title); details.Item1.Name.Should().Be(name);
} }
[Test] [Test]
public void getting_details_of_invalid_series() public void getting_details_of_invalid_artist()
{ {
Assert.Throws<SeriesNotFoundException>(() => Subject.GetSeriesInfo(int.MaxValue)); Assert.Throws<ArtistNotFoundException>(() => Subject.GetArtistInfo("aaaaaa-aaa-aaaa-aaaa"));
} }
[Test] [Test]
public void should_not_have_period_at_start_of_title_slug() public void should_not_have_period_at_start_of_name_slug()
{ {
var details = Subject.GetSeriesInfo(79099); var details = Subject.GetArtistInfo("f59c5520-5f46-4d2c-b2c4-822eabf53419");
details.Item1.TitleSlug.Should().Be("dothack"); details.Item1.NameSlug.Should().Be("dothack");
} }
private void ValidateSeries(Series series) private void ValidateArtist(Artist artist)
{ {
series.Should().NotBeNull(); artist.Should().NotBeNull();
series.Title.Should().NotBeNullOrWhiteSpace(); artist.Name.Should().NotBeNullOrWhiteSpace();
series.CleanTitle.Should().Be(Parser.Parser.CleanSeriesTitle(series.Title)); artist.CleanName.Should().Be(Parser.Parser.CleanSeriesTitle(artist.Name));
series.SortTitle.Should().Be(SeriesTitleNormalizer.Normalize(series.Title, series.TvdbId)); artist.SortName.Should().Be(Parser.Parser.NormalizeTitle(artist.Name));
series.Overview.Should().NotBeNullOrWhiteSpace(); artist.Overview.Should().NotBeNullOrWhiteSpace();
series.AirTime.Should().NotBeNullOrWhiteSpace(); artist.Images.Should().NotBeEmpty();
series.FirstAired.Should().HaveValue(); artist.NameSlug.Should().NotBeNullOrWhiteSpace();
series.FirstAired.Value.Kind.Should().Be(DateTimeKind.Utc);
series.Images.Should().NotBeEmpty();
series.ImdbId.Should().NotBeNullOrWhiteSpace();
series.Network.Should().NotBeNullOrWhiteSpace();
series.Runtime.Should().BeGreaterThan(0);
series.TitleSlug.Should().NotBeNullOrWhiteSpace();
//series.TvRageId.Should().BeGreaterThan(0); //series.TvRageId.Should().BeGreaterThan(0);
series.TvdbId.Should().BeGreaterThan(0); artist.ForeignArtistId.Should().NotBeNullOrWhiteSpace();
} }
private void ValidateEpisodes(List<Episode> episodes) private void ValidateAlbums(List<Album> albums)
{ {
episodes.Should().NotBeEmpty(); albums.Should().NotBeEmpty();
var episodeGroup = episodes.GroupBy(e => e.SeasonNumber.ToString("000") + e.EpisodeNumber.ToString("000")); var episodeGroup = albums.GroupBy(e => e.AlbumType + e.Title);
episodeGroup.Should().OnlyContain(c => c.Count() == 1); episodeGroup.Should().OnlyContain(c => c.Count() == 1);
episodes.Should().Contain(c => c.SeasonNumber > 0);
episodes.Should().Contain(c => !string.IsNullOrWhiteSpace(c.Overview));
foreach (var episode in episodes) foreach (var episode in albums)
{ {
ValidateEpisode(episode); ValidateAlbum(episode);
//if atleast one episdoe has title it means parse it working. //if atleast one album has title it means parse it working.
episodes.Should().Contain(c => !string.IsNullOrWhiteSpace(c.Title)); albums.Should().Contain(c => !string.IsNullOrWhiteSpace(c.Title));
} }
} }
private void ValidateEpisode(Episode episode) private void ValidateAlbum(Album album)
{ {
episode.Should().NotBeNull(); album.Should().NotBeNull();
//TODO: Is there a better way to validate that episode number or season number is greater than zero? album.Title.Should().NotBeNullOrWhiteSpace();
(episode.EpisodeNumber + episode.SeasonNumber).Should().NotBe(0); album.AlbumType.Should().NotBeNullOrWhiteSpace();
episode.Should().NotBeNull(); album.Should().NotBeNull();
if (episode.AirDateUtc.HasValue) if (album.ReleaseDate.HasValue)
{ {
episode.AirDateUtc.Value.Kind.Should().Be(DateTimeKind.Utc); album.ReleaseDate.Value.Kind.Should().Be(DateTimeKind.Utc);
} }
episode.Images.Any(i => i.CoverType == MediaCoverTypes.Screenshot && i.Url.Contains("-940."))
.Should()
.BeFalse();
} }
} }
} }

@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Music;
using NzbDrone.Core.Music.Commands;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MusicTests
{
[TestFixture]
public class RefreshArtistServiceFixture : CoreTest<RefreshArtistService>
{
private Artist _artist;
[SetUp]
public void Setup()
{
var season1 = Builder<Album>.CreateNew()
.With(s => s.ForeignAlbumId = "1")
.Build();
_artist = Builder<Artist>.CreateNew()
.With(s => s.Albums = new List<Album>
{
season1
})
.Build();
Mocker.GetMock<IArtistService>()
.Setup(s => s.GetArtist(_artist.Id))
.Returns(_artist);
Mocker.GetMock<IProvideArtistInfo>()
.Setup(s => s.GetArtistInfo(It.IsAny<string>()))
.Callback<string>(p => { throw new ArtistNotFoundException(p); });
}
private void GivenNewArtistInfo(Artist artist)
{
Mocker.GetMock<IProvideArtistInfo>()
.Setup(s => s.GetArtistInfo(_artist.ForeignArtistId))
.Returns(new Tuple<Artist, List<Album>>(artist, new List<Album>()));
}
[Test]
public void should_monitor_new_albums_automatically()
{
var newArtistInfo = _artist.JsonClone();
newArtistInfo.Albums.Add(Builder<Album>.CreateNew()
.With(s => s.ForeignAlbumId = "2")
.Build());
GivenNewArtistInfo(newArtistInfo);
Subject.Execute(new RefreshArtistCommand(_artist.Id));
Mocker.GetMock<IArtistService>()
.Verify(v => v.UpdateArtist(It.Is<Artist>(s => s.Albums.Count == 2 && s.Albums.Single(season => season.ForeignAlbumId == "2").Monitored == true)));
}
[Test]
public void should_log_error_if_musicbrainz_id_not_found()
{
Subject.Execute(new RefreshArtistCommand(_artist.Id));
Mocker.GetMock<IArtistService>()
.Verify(v => v.UpdateArtist(It.IsAny<Artist>()), Times.Never());
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void should_update_if_musicbrainz_id_changed()
{
var newArtistInfo = _artist.JsonClone();
newArtistInfo.ForeignArtistId = _artist.ForeignArtistId + 1;
GivenNewArtistInfo(newArtistInfo);
Subject.Execute(new RefreshArtistCommand(_artist.Id));
Mocker.GetMock<IArtistService>()
.Verify(v => v.UpdateArtist(It.Is<Artist>(s => s.ForeignArtistId == newArtistInfo.ForeignArtistId)));
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_not_throw_if_duplicate_album_is_in_existing_info()
{
var newArtistInfo = _artist.JsonClone();
newArtistInfo.Albums.Add(Builder<Album>.CreateNew()
.With(s => s.ForeignAlbumId = "2")
.Build());
_artist.Albums.Add(Builder<Album>.CreateNew()
.With(s => s.ForeignAlbumId = "2")
.Build());
_artist.Albums.Add(Builder<Album>.CreateNew()
.With(s => s.ForeignAlbumId = "2")
.Build());
GivenNewArtistInfo(newArtistInfo);
Subject.Execute(new RefreshArtistCommand(_artist.Id));
Mocker.GetMock<IArtistService>()
.Verify(v => v.UpdateArtist(It.Is<Artist>(s => s.Albums.Count == 2)));
}
[Test]
public void should_filter_duplicate_albums()
{
var newArtistInfo = _artist.JsonClone();
newArtistInfo.Albums.Add(Builder<Album>.CreateNew()
.With(s => s.ForeignAlbumId = "2")
.Build());
newArtistInfo.Albums.Add(Builder<Album>.CreateNew()
.With(s => s.ForeignAlbumId = "2")
.Build());
GivenNewArtistInfo(newArtistInfo);
Subject.Execute(new RefreshArtistCommand(_artist.Id));
Mocker.GetMock<IArtistService>()
.Verify(v => v.UpdateArtist(It.Is<Artist>(s => s.Albums.Count == 2)));
}
}
}

@ -0,0 +1,135 @@
using System;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Music;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MusicTests
{
[TestFixture]
public class ShouldRefreshArtistFixture : TestBase<ShouldRefreshArtist>
{
private Artist _artist;
[SetUp]
public void Setup()
{
_artist = Builder<Artist>.CreateNew()
.With(v => v.Status == ArtistStatusType.Continuing)
.Build();
Mocker.GetMock<IAlbumService>()
.Setup(s => s.GetAlbumsByArtist(_artist.Id))
.Returns(Builder<Album>.CreateListOfSize(2)
.All()
.With(e => e.ReleaseDate = DateTime.Today.AddDays(-100))
.Build()
.ToList());
}
private void GivenArtistIsEnded()
{
_artist.Status = ArtistStatusType.Ended;
}
private void GivenArtistLastRefreshedMonthsAgo()
{
_artist.LastInfoSync = DateTime.UtcNow.AddDays(-90);
}
private void GivenArtistLastRefreshedYesterday()
{
_artist.LastInfoSync = DateTime.UtcNow.AddDays(-1);
}
private void GivenArtistLastRefreshedHalfADayAgo()
{
_artist.LastInfoSync = DateTime.UtcNow.AddHours(-12);
}
private void GivenArtistLastRefreshedRecently()
{
_artist.LastInfoSync = DateTime.UtcNow.AddHours(-1);
}
private void GivenRecentlyAired()
{
Mocker.GetMock<IAlbumService>()
.Setup(s => s.GetAlbumsByArtist(_artist.Id))
.Returns(Builder<Album>.CreateListOfSize(2)
.TheFirst(1)
.With(e => e.ReleaseDate = DateTime.Today.AddDays(-7))
.TheLast(1)
.With(e => e.ReleaseDate = DateTime.Today.AddDays(-100))
.Build()
.ToList());
}
[Test]
public void should_return_true_if_running_artist_last_refreshed_more_than_6_hours_ago()
{
GivenArtistLastRefreshedHalfADayAgo();
Subject.ShouldRefresh(_artist).Should().BeTrue();
}
[Test]
public void should_return_false_if_running_artist_last_refreshed_less_than_6_hours_ago()
{
GivenArtistLastRefreshedRecently();
Subject.ShouldRefresh(_artist).Should().BeFalse();
}
[Test]
public void should_return_false_if_ended_artist_last_refreshed_yesterday()
{
GivenArtistIsEnded();
GivenArtistLastRefreshedYesterday();
Subject.ShouldRefresh(_artist).Should().BeFalse();
}
[Test]
public void should_return_true_if_artist_last_refreshed_more_than_30_days_ago()
{
GivenArtistIsEnded();
GivenArtistLastRefreshedMonthsAgo();
Subject.ShouldRefresh(_artist).Should().BeTrue();
}
[Test]
public void should_return_true_if_album_released_in_last_30_days()
{
GivenArtistIsEnded();
GivenArtistLastRefreshedYesterday();
GivenRecentlyAired();
Subject.ShouldRefresh(_artist).Should().BeTrue();
}
[Test]
public void should_return_false_when_recently_refreshed_ended_show_has_not_aired_for_30_days()
{
GivenArtistIsEnded();
GivenArtistLastRefreshedYesterday();
Subject.ShouldRefresh(_artist).Should().BeFalse();
}
[Test]
public void should_return_false_when_recently_refreshed_ended_show_aired_in_last_30_days()
{
GivenArtistIsEnded();
GivenArtistLastRefreshedRecently();
GivenRecentlyAired();
Subject.ShouldRefresh(_artist).Should().BeFalse();
}
}
}

@ -365,13 +365,13 @@
<Compile Include="TvTests\EpisodeRepositoryTests\FindEpisodeFixture.cs" /> <Compile Include="TvTests\EpisodeRepositoryTests\FindEpisodeFixture.cs" />
<Compile Include="MusicTests\MoveArtistServiceFixture.cs" /> <Compile Include="MusicTests\MoveArtistServiceFixture.cs" />
<Compile Include="TvTests\RefreshEpisodeServiceFixture.cs" /> <Compile Include="TvTests\RefreshEpisodeServiceFixture.cs" />
<Compile Include="TvTests\RefreshSeriesServiceFixture.cs" /> <Compile Include="MusicTests\RefreshArtistServiceFixture.cs" />
<Compile Include="TvTests\EpisodeMonitoredServiceTests\SetEpisodeMontitoredFixture.cs" /> <Compile Include="TvTests\EpisodeMonitoredServiceTests\SetEpisodeMontitoredFixture.cs" />
<Compile Include="TvTests\SeriesRepositoryTests\SeriesRepositoryFixture.cs" /> <Compile Include="TvTests\SeriesRepositoryTests\SeriesRepositoryFixture.cs" />
<Compile Include="TvTests\SeriesServiceTests\UpdateMultipleSeriesFixture.cs" /> <Compile Include="TvTests\SeriesServiceTests\UpdateMultipleSeriesFixture.cs" />
<Compile Include="TvTests\SeriesServiceTests\UpdateSeriesFixture.cs" /> <Compile Include="TvTests\SeriesServiceTests\UpdateSeriesFixture.cs" />
<Compile Include="TvTests\SeriesTitleNormalizerFixture.cs" /> <Compile Include="TvTests\SeriesTitleNormalizerFixture.cs" />
<Compile Include="TvTests\ShouldRefreshSeriesFixture.cs" /> <Compile Include="MusicTests\ShouldRefreshArtistFixture.cs" />
<Compile Include="UpdateTests\UpdatePackageProviderFixture.cs" /> <Compile Include="UpdateTests\UpdatePackageProviderFixture.cs" />
<Compile Include="UpdateTests\UpdateServiceFixture.cs" /> <Compile Include="UpdateTests\UpdateServiceFixture.cs" />
<Compile Include="XbmcVersionTests.cs" /> <Compile Include="XbmcVersionTests.cs" />

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.TvTests
{ {
UseRealHttp(); UseRealHttp();
_gameOfThrones = Mocker.Resolve<SkyHookProxy>().GetSeriesInfo(121361);//Game of thrones // _gameOfThrones = Mocker.Resolve<SkyHookProxy>().GetSeriesInfo(121361);//Game of thrones
// Remove specials. // Remove specials.
_gameOfThrones.Item2.RemoveAll(v => v.SeasonNumber == 0); _gameOfThrones.Item2.RemoveAll(v => v.SeasonNumber == 0);

@ -1,184 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Tv.Commands;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.TvTests
{
[TestFixture]
public class RefreshSeriesServiceFixture : CoreTest<RefreshSeriesService>
{
private Series _series;
[SetUp]
public void Setup()
{
var season1 = Builder<Season>.CreateNew()
.With(s => s.SeasonNumber = 1)
.Build();
_series = Builder<Series>.CreateNew()
.With(s => s.Seasons = new List<Season>
{
season1
})
.Build();
Mocker.GetMock<ISeriesService>()
.Setup(s => s.GetSeries(_series.Id))
.Returns(_series);
Mocker.GetMock<IProvideSeriesInfo>()
.Setup(s => s.GetSeriesInfo(It.IsAny<int>()))
.Callback<int>(p => { throw new SeriesNotFoundException(p); });
}
private void GivenNewSeriesInfo(Series series)
{
Mocker.GetMock<IProvideSeriesInfo>()
.Setup(s => s.GetSeriesInfo(_series.TvdbId))
.Returns(new Tuple<Series, List<Episode>>(series, new List<Episode>()));
}
[Test]
public void should_monitor_new_seasons_automatically()
{
var newSeriesInfo = _series.JsonClone();
newSeriesInfo.Seasons.Add(Builder<Season>.CreateNew()
.With(s => s.SeasonNumber = 2)
.Build());
GivenNewSeriesInfo(newSeriesInfo);
Subject.Execute(new RefreshSeriesCommand(_series.Id));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.Seasons.Count == 2 && s.Seasons.Single(season => season.SeasonNumber == 2).Monitored == true)));
}
[Test]
public void should_not_monitor_new_special_season_automatically()
{
var series = _series.JsonClone();
series.Seasons.Add(Builder<Season>.CreateNew()
.With(s => s.SeasonNumber = 0)
.Build());
GivenNewSeriesInfo(series);
Subject.Execute(new RefreshSeriesCommand(_series.Id));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.Seasons.Count == 2 && s.Seasons.Single(season => season.SeasonNumber == 0).Monitored == false)));
}
[Test]
public void should_update_tvrage_id_if_changed()
{
var newSeriesInfo = _series.JsonClone();
newSeriesInfo.TvRageId = _series.TvRageId + 1;
GivenNewSeriesInfo(newSeriesInfo);
Subject.Execute(new RefreshSeriesCommand(_series.Id));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.TvRageId == newSeriesInfo.TvRageId)));
}
[Test]
public void should_update_tvmaze_id_if_changed()
{
var newSeriesInfo = _series.JsonClone();
newSeriesInfo.TvMazeId = _series.TvMazeId + 1;
GivenNewSeriesInfo(newSeriesInfo);
Subject.Execute(new RefreshSeriesCommand(_series.Id));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.TvMazeId == newSeriesInfo.TvMazeId)));
}
[Test]
public void should_log_error_if_tvdb_id_not_found()
{
Subject.Execute(new RefreshSeriesCommand(_series.Id));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.IsAny<Series>()), Times.Never());
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void should_update_if_tvdb_id_changed()
{
var newSeriesInfo = _series.JsonClone();
newSeriesInfo.TvdbId = _series.TvdbId + 1;
GivenNewSeriesInfo(newSeriesInfo);
Subject.Execute(new RefreshSeriesCommand(_series.Id));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.TvdbId == newSeriesInfo.TvdbId)));
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_not_throw_if_duplicate_season_is_in_existing_info()
{
var newSeriesInfo = _series.JsonClone();
newSeriesInfo.Seasons.Add(Builder<Season>.CreateNew()
.With(s => s.SeasonNumber = 2)
.Build());
_series.Seasons.Add(Builder<Season>.CreateNew()
.With(s => s.SeasonNumber = 2)
.Build());
_series.Seasons.Add(Builder<Season>.CreateNew()
.With(s => s.SeasonNumber = 2)
.Build());
GivenNewSeriesInfo(newSeriesInfo);
Subject.Execute(new RefreshSeriesCommand(_series.Id));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.Seasons.Count == 2)));
}
[Test]
public void should_filter_duplicate_seasons()
{
var newSeriesInfo = _series.JsonClone();
newSeriesInfo.Seasons.Add(Builder<Season>.CreateNew()
.With(s => s.SeasonNumber = 2)
.Build());
newSeriesInfo.Seasons.Add(Builder<Season>.CreateNew()
.With(s => s.SeasonNumber = 2)
.Build());
GivenNewSeriesInfo(newSeriesInfo);
Subject.Execute(new RefreshSeriesCommand(_series.Id));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.Is<Series>(s => s.Seasons.Count == 2)));
}
}
}

@ -1,135 +0,0 @@
using System;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.TvTests
{
[TestFixture]
public class ShouldRefreshSeriesFixture : TestBase<ShouldRefreshSeries>
{
private Series _series;
[SetUp]
public void Setup()
{
_series = Builder<Series>.CreateNew()
.With(v => v.Status == SeriesStatusType.Continuing)
.Build();
Mocker.GetMock<IEpisodeService>()
.Setup(s => s.GetEpisodeBySeries(_series.Id))
.Returns(Builder<Episode>.CreateListOfSize(2)
.All()
.With(e => e.AirDateUtc = DateTime.Today.AddDays(-100))
.Build()
.ToList());
}
private void GivenSeriesIsEnded()
{
_series.Status = SeriesStatusType.Ended;
}
private void GivenSeriesLastRefreshedMonthsAgo()
{
_series.LastInfoSync = DateTime.UtcNow.AddDays(-90);
}
private void GivenSeriesLastRefreshedYesterday()
{
_series.LastInfoSync = DateTime.UtcNow.AddDays(-1);
}
private void GivenSeriesLastRefreshedHalfADayAgo()
{
_series.LastInfoSync = DateTime.UtcNow.AddHours(-12);
}
private void GivenSeriesLastRefreshedRecently()
{
_series.LastInfoSync = DateTime.UtcNow.AddHours(-1);
}
private void GivenRecentlyAired()
{
Mocker.GetMock<IEpisodeService>()
.Setup(s => s.GetEpisodeBySeries(_series.Id))
.Returns(Builder<Episode>.CreateListOfSize(2)
.TheFirst(1)
.With(e => e.AirDateUtc = DateTime.Today.AddDays(-7))
.TheLast(1)
.With(e => e.AirDateUtc = DateTime.Today.AddDays(-100))
.Build()
.ToList());
}
[Test]
public void should_return_true_if_running_series_last_refreshed_more_than_6_hours_ago()
{
GivenSeriesLastRefreshedHalfADayAgo();
Subject.ShouldRefresh(_series).Should().BeTrue();
}
[Test]
public void should_return_false_if_running_series_last_refreshed_less_than_6_hours_ago()
{
GivenSeriesLastRefreshedRecently();
Subject.ShouldRefresh(_series).Should().BeFalse();
}
[Test]
public void should_return_false_if_ended_series_last_refreshed_yesterday()
{
GivenSeriesIsEnded();
GivenSeriesLastRefreshedYesterday();
Subject.ShouldRefresh(_series).Should().BeFalse();
}
[Test]
public void should_return_true_if_series_last_refreshed_more_than_30_days_ago()
{
GivenSeriesIsEnded();
GivenSeriesLastRefreshedMonthsAgo();
Subject.ShouldRefresh(_series).Should().BeTrue();
}
[Test]
public void should_return_true_if_episode_aired_in_last_30_days()
{
GivenSeriesIsEnded();
GivenSeriesLastRefreshedYesterday();
GivenRecentlyAired();
Subject.ShouldRefresh(_series).Should().BeTrue();
}
[Test]
public void should_return_false_when_recently_refreshed_ended_show_has_not_aired_for_30_days()
{
GivenSeriesIsEnded();
GivenSeriesLastRefreshedYesterday();
Subject.ShouldRefresh(_series).Should().BeFalse();
}
[Test]
public void should_return_false_when_recently_refreshed_ended_show_aired_in_last_30_days()
{
GivenSeriesIsEnded();
GivenSeriesLastRefreshedRecently();
GivenRecentlyAired();
Subject.ShouldRefresh(_series).Should().BeFalse();
}
}
}

@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.MetadataSource
{
public interface IProvideSeriesInfo
{
Tuple<Series, List<Episode>> GetSeriesInfo(int tvdbSeriesId);
}
}

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{
public class ArtistInfoResource
{
public ArtistInfoResource() { }
public List<string> Genres { get; set; }
public string AristUrl { get; set; }
public string Overview { get; set; }
public string Id { get; set; }
public List<ImageResource> Images { get; set; }
public string ArtistName { get; set; }
}
}

@ -1,17 +0,0 @@
using System;
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{
public class EpisodeResource
{
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
public int? AbsoluteEpisodeNumber { get; set; }
public string Title { get; set; }
public string AirDate { get; set; }
public DateTime? AirDateUtc { get; set; }
public RatingResource Rating { get; set; }
public string Overview { get; set; }
public string Image { get; set; }
}
}

@ -1,9 +1,9 @@
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{ {
public class ActorResource public class MemberResource
{ {
public string Name { get; set; } public string Name { get; set; }
public string Character { get; set; } public string Instrument { get; set; }
public string Image { get; set; } public string Image { get; set; }
} }
} }

@ -1,15 +0,0 @@
using System.Collections.Generic;
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{
public class SeasonResource
{
public SeasonResource()
{
Images = new List<ImageResource>();
}
public int SeasonNumber { get; set; }
public List<ImageResource> Images { get; set; }
}
}

@ -1,43 +0,0 @@
using System.Collections.Generic;
namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
{
public class ShowResource
{
public ShowResource()
{
Actors = new List<ActorResource>();
Genres = new List<string>();
Images = new List<ImageResource>();
Seasons = new List<SeasonResource>();
Episodes = new List<EpisodeResource>();
}
public int TvdbId { get; set; }
public string Title { get; set; }
public string Overview { get; set; }
//public string Language { get; set; }
public string Slug { get; set; }
public string FirstAired { get; set; }
public int? TvRageId { get; set; }
public int? TvMazeId { get; set; }
public string Status { get; set; }
public int? Runtime { get; set; }
public TimeOfDayResource TimeOfDay { get; set; }
public string Network { get; set; }
public string ImdbId { get; set; }
public List<ActorResource> Actors { get; set; }
public List<string> Genres { get; set; }
public string ContentRating { get; set; }
public RatingResource Rating { get; set; }
public List<ImageResource> Images { get; set; }
public List<SeasonResource> Seasons { get; set; }
public List<EpisodeResource> Episodes { get; set; }
}
}

@ -17,7 +17,7 @@ using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.MetadataSource.SkyHook namespace NzbDrone.Core.MetadataSource.SkyHook
{ {
public class SkyHookProxy : IProvideSeriesInfo, IProvideArtistInfo, ISearchForNewArtist public class SkyHookProxy : IProvideArtistInfo, ISearchForNewArtist
{ {
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private readonly Logger _logger; private readonly Logger _logger;
@ -37,12 +37,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
_logger = logger; _logger = logger;
} }
[Obsolete("Used for Sonarr, not Lidarr")]
public Tuple<Series, List<Episode>> GetSeriesInfo(int tvdbSeriesId)
{
throw new NotImplementedException();
}
public Tuple<Artist, List<Album>> GetArtistInfo(string foreignArtistId) public Tuple<Artist, List<Album>> GetArtistInfo(string foreignArtistId)
{ {
@ -191,23 +185,23 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return artist; return artist;
} }
private static Actor MapActors(ActorResource arg) private static Member MapMembers(MemberResource arg)
{ {
var newActor = new Actor var newMember = new Member
{ {
Name = arg.Name, Name = arg.Name,
Character = arg.Character Instrument = arg.Instrument
}; };
if (arg.Image != null) if (arg.Image != null)
{ {
newActor.Images = new List<MediaCover.MediaCover> newMember.Images = new List<MediaCover.MediaCover>
{ {
new MediaCover.MediaCover(MediaCoverTypes.Headshot, arg.Image) new MediaCover.MediaCover(MediaCoverTypes.Headshot, arg.Image)
}; };
} }
return newActor; return newMember;
} }
private static ArtistStatusType MapArtistStatus(string status) private static ArtistStatusType MapArtistStatus(string status)

@ -1,4 +1,4 @@
using NLog; using NLog;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -11,14 +11,14 @@ namespace NzbDrone.Core.Music
bool ShouldRefresh(Artist artist); bool ShouldRefresh(Artist artist);
} }
public class CheckIfArtistShouldBeRefreshed : ICheckIfArtistShouldBeRefreshed public class ShouldRefreshArtist : ICheckIfArtistShouldBeRefreshed
{ {
private readonly ITrackService _trackService; private readonly IAlbumService _albumService;
private readonly Logger _logger; private readonly Logger _logger;
public CheckIfArtistShouldBeRefreshed(ITrackService trackService, Logger logger) public ShouldRefreshArtist(IAlbumService albumService, Logger logger)
{ {
_trackService = trackService; _albumService = albumService;
_logger = logger; _logger = logger;
} }
@ -36,7 +36,21 @@ namespace NzbDrone.Core.Music
return false; return false;
} }
//_logger.Trace("Artist {0} ended long ago, should not be refreshed.", artist.Title); if (artist.Status == ArtistStatusType.Continuing)
{
_logger.Trace("Artist {0} is continuing, should refresh.", artist.Name);
return true;
}
var lastAlbum = _albumService.GetAlbumsByArtist(artist.Id).OrderByDescending(e => e.ReleaseDate).FirstOrDefault();
if (lastAlbum != null && lastAlbum.ReleaseDate > DateTime.UtcNow.AddDays(-30))
{
_logger.Trace("Last album in {0} aired less than 30 days ago, should refresh.", artist.Name);
return true;
}
_logger.Trace("Artist {0} ended long ago, should not be refreshed.", artist.Name);
return false; return false;
} }
} }

@ -828,18 +828,13 @@
<Compile Include="Messaging\Events\IHandle.cs" /> <Compile Include="Messaging\Events\IHandle.cs" />
<Compile Include="Messaging\IProcessMessage.cs" /> <Compile Include="Messaging\IProcessMessage.cs" />
<Compile Include="MetadataSource\IProvideArtistInfo.cs" /> <Compile Include="MetadataSource\IProvideArtistInfo.cs" />
<Compile Include="MetadataSource\IProvideSeriesInfo.cs" />
<Compile Include="MetadataSource\ISearchForNewArtist.cs" /> <Compile Include="MetadataSource\ISearchForNewArtist.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ActorResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\MemberResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\AlbumResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\AlbumResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ArtistInfoResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ArtistResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\ArtistResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\LinkResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\LinkResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\EpisodeResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ImageResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\ImageResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\RatingResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\RatingResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\SeasonResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\ShowResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\TimeOfDayResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\TimeOfDayResource.cs" />
<Compile Include="MetadataSource\SkyHook\Resource\TrackResource.cs" /> <Compile Include="MetadataSource\SkyHook\Resource\TrackResource.cs" />
<Compile Include="MetadataSource\SkyHook\SkyHookProxy.cs" /> <Compile Include="MetadataSource\SkyHook\SkyHookProxy.cs" />
@ -1191,7 +1186,6 @@
<Compile Include="Tv\SeriesTitleNormalizer.cs" /> <Compile Include="Tv\SeriesTitleNormalizer.cs" />
<Compile Include="Tv\SeriesTitleSlugValidator.cs" /> <Compile Include="Tv\SeriesTitleSlugValidator.cs" />
<Compile Include="Tv\SeriesTypes.cs" /> <Compile Include="Tv\SeriesTypes.cs" />
<Compile Include="Tv\ShouldRefreshSeries.cs" />
<Compile Include="Update\Commands\ApplicationUpdateCommand.cs" /> <Compile Include="Update\Commands\ApplicationUpdateCommand.cs" />
<Compile Include="Update\InstallUpdateService.cs" /> <Compile Include="Update\InstallUpdateService.cs" />
<Compile Include="Update\RecentUpdateProvider.cs" /> <Compile Include="Update\RecentUpdateProvider.cs" />

@ -16,25 +16,21 @@ namespace NzbDrone.Core.Tv
public interface IAddSeriesService public interface IAddSeriesService
{ {
Series AddSeries(Series newSeries); Series AddSeries(Series newSeries);
List<Series> AddSeries(List<Series> newSeries);
} }
public class AddSeriesService : IAddSeriesService public class AddSeriesService : IAddSeriesService
{ {
private readonly ISeriesService _seriesService; private readonly ISeriesService _seriesService;
private readonly IProvideSeriesInfo _seriesInfo;
private readonly IBuildFileNames _fileNameBuilder; private readonly IBuildFileNames _fileNameBuilder;
private readonly IAddSeriesValidator _addSeriesValidator; private readonly IAddSeriesValidator _addSeriesValidator;
private readonly Logger _logger; private readonly Logger _logger;
public AddSeriesService(ISeriesService seriesService, public AddSeriesService(ISeriesService seriesService,
IProvideSeriesInfo seriesInfo,
IBuildFileNames fileNameBuilder, IBuildFileNames fileNameBuilder,
IAddSeriesValidator addSeriesValidator, IAddSeriesValidator addSeriesValidator,
Logger logger) Logger logger)
{ {
_seriesService = seriesService; _seriesService = seriesService;
_seriesInfo = seriesInfo;
_fileNameBuilder = fileNameBuilder; _fileNameBuilder = fileNameBuilder;
_addSeriesValidator = addSeriesValidator; _addSeriesValidator = addSeriesValidator;
_logger = logger; _logger = logger;
@ -44,7 +40,6 @@ namespace NzbDrone.Core.Tv
{ {
Ensure.That(newSeries, () => newSeries).IsNotNull(); Ensure.That(newSeries, () => newSeries).IsNotNull();
newSeries = AddSkyhookData(newSeries);
newSeries = SetPropertiesAndValidate(newSeries); newSeries = SetPropertiesAndValidate(newSeries);
_logger.Info("Adding Series {0} Path: [{1}]", newSeries, newSeries.Path); _logger.Info("Adding Series {0} Path: [{1}]", newSeries, newSeries.Path);
@ -53,50 +48,6 @@ namespace NzbDrone.Core.Tv
return newSeries; return newSeries;
} }
public List<Series> AddSeries(List<Series> newSeries)
{
var added = DateTime.UtcNow;
var seriesToAdd = new List<Series>();
foreach (var s in newSeries)
{
// TODO: Verify if adding skyhook data will be slow
var series = AddSkyhookData(s);
series = SetPropertiesAndValidate(series);
series.Added = added;
seriesToAdd.Add(series);
}
return _seriesService.AddSeries(seriesToAdd);
}
private Series AddSkyhookData(Series newSeries)
{
Tuple<Series, List<Episode>> tuple;
try
{
tuple = _seriesInfo.GetSeriesInfo(newSeries.TvdbId);
}
catch (SeriesNotFoundException)
{
_logger.Error("tvdbid {1} was not found, it may have been removed from TheTVDB.", newSeries.TvdbId);
throw new ValidationException(new List<ValidationFailure>
{
new ValidationFailure("TvdbId", "A series with this ID was not found", newSeries.TvdbId)
});
}
var series = tuple.Item1;
// If seasons were passed in on the new series use them, otherwise use the seasons from Skyhook
newSeries.Seasons = newSeries.Seasons != null && newSeries.Seasons.Any() ? newSeries.Seasons : series.Seasons;
series.ApplyChanges(newSeries);
return series;
}
private Series SetPropertiesAndValidate(Series newSeries) private Series SetPropertiesAndValidate(Series newSeries)
{ {
if (string.IsNullOrWhiteSpace(newSeries.Path)) if (string.IsNullOrWhiteSpace(newSeries.Path))

@ -18,101 +18,28 @@ namespace NzbDrone.Core.Tv
{ {
public class RefreshSeriesService : IExecute<RefreshSeriesCommand> public class RefreshSeriesService : IExecute<RefreshSeriesCommand>
{ {
private readonly IProvideSeriesInfo _seriesInfo;
private readonly ISeriesService _seriesService; private readonly ISeriesService _seriesService;
private readonly IRefreshEpisodeService _refreshEpisodeService; private readonly IRefreshEpisodeService _refreshEpisodeService;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IDailySeriesService _dailySeriesService; private readonly IDailySeriesService _dailySeriesService;
private readonly IDiskScanService _diskScanService; private readonly IDiskScanService _diskScanService;
private readonly ICheckIfSeriesShouldBeRefreshed _checkIfSeriesShouldBeRefreshed;
private readonly Logger _logger; private readonly Logger _logger;
public RefreshSeriesService(IProvideSeriesInfo seriesInfo, public RefreshSeriesService(ISeriesService seriesService,
ISeriesService seriesService,
IRefreshEpisodeService refreshEpisodeService, IRefreshEpisodeService refreshEpisodeService,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IDailySeriesService dailySeriesService, IDailySeriesService dailySeriesService,
IDiskScanService diskScanService, IDiskScanService diskScanService,
ICheckIfSeriesShouldBeRefreshed checkIfSeriesShouldBeRefreshed,
Logger logger) Logger logger)
{ {
_seriesInfo = seriesInfo;
_seriesService = seriesService; _seriesService = seriesService;
_refreshEpisodeService = refreshEpisodeService; _refreshEpisodeService = refreshEpisodeService;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_dailySeriesService = dailySeriesService; _dailySeriesService = dailySeriesService;
_diskScanService = diskScanService; _diskScanService = diskScanService;
_checkIfSeriesShouldBeRefreshed = checkIfSeriesShouldBeRefreshed;
_logger = logger; _logger = logger;
} }
private void RefreshSeriesInfo(Series series)
{
_logger.ProgressInfo("Updating {0}", series.Title);
Tuple<Series, List<Episode>> tuple;
try
{
tuple = _seriesInfo.GetSeriesInfo(series.TvdbId);
}
catch (SeriesNotFoundException)
{
_logger.Error("Series '{0}' (tvdbid {1}) was not found, it may have been removed from TheTVDB.", series.Title, series.TvdbId);
return;
}
var seriesInfo = tuple.Item1;
if (series.TvdbId != seriesInfo.TvdbId)
{
_logger.Warn("Series '{0}' (tvdbid {1}) was replaced with '{2}' (tvdbid {3}), because the original was a duplicate.", series.Title, series.TvdbId, seriesInfo.Title, seriesInfo.TvdbId);
series.TvdbId = seriesInfo.TvdbId;
}
series.Title = seriesInfo.Title;
series.TitleSlug = seriesInfo.TitleSlug;
series.TvRageId = seriesInfo.TvRageId;
series.TvMazeId = seriesInfo.TvMazeId;
series.ImdbId = seriesInfo.ImdbId;
series.AirTime = seriesInfo.AirTime;
series.Overview = seriesInfo.Overview;
series.Status = seriesInfo.Status;
series.CleanTitle = seriesInfo.CleanTitle;
series.SortTitle = seriesInfo.SortTitle;
series.LastInfoSync = DateTime.UtcNow;
series.Runtime = seriesInfo.Runtime;
series.Images = seriesInfo.Images;
series.Network = seriesInfo.Network;
series.FirstAired = seriesInfo.FirstAired;
series.Ratings = seriesInfo.Ratings;
series.Actors = seriesInfo.Actors;
series.Genres = seriesInfo.Genres;
series.Certification = seriesInfo.Certification;
if (_dailySeriesService.IsDailySeries(series.TvdbId))
{
series.SeriesType = SeriesTypes.Daily;
}
try
{
series.Path = new DirectoryInfo(series.Path).FullName;
series.Path = series.Path.GetActualCasing();
}
catch (Exception e)
{
_logger.Warn(e, "Couldn't update series path for " + series.Path);
}
series.Seasons = UpdateSeasons(series, seriesInfo);
_seriesService.UpdateSeries(series);
_refreshEpisodeService.RefreshEpisodeInfo(series, tuple.Item2);
_logger.Debug("Finished series refresh for {0}", series.Title);
_eventAggregator.PublishEvent(new SeriesUpdatedEvent(series));
}
private List<Season> UpdateSeasons(Series series, Series seriesInfo) private List<Season> UpdateSeasons(Series series, Series seriesInfo)
{ {
@ -151,7 +78,6 @@ namespace NzbDrone.Core.Tv
if (message.SeriesId.HasValue) if (message.SeriesId.HasValue)
{ {
var series = _seriesService.GetSeries(message.SeriesId.Value); var series = _seriesService.GetSeries(message.SeriesId.Value);
RefreshSeriesInfo(series);
} }
else else
{ {
@ -159,11 +85,11 @@ namespace NzbDrone.Core.Tv
foreach (var series in allSeries) foreach (var series in allSeries)
{ {
if (message.Trigger == CommandTrigger.Manual || _checkIfSeriesShouldBeRefreshed.ShouldRefresh(series)) if (message.Trigger == CommandTrigger.Manual)
{ {
try try
{ {
RefreshSeriesInfo(series); //RefreshSeriesInfo(series);
} }
catch (Exception e) catch (Exception e)
{ {

@ -1,55 +0,0 @@
using System;
using System.Linq;
using NLog;
namespace NzbDrone.Core.Tv
{
public interface ICheckIfSeriesShouldBeRefreshed
{
bool ShouldRefresh(Series series);
}
public class ShouldRefreshSeries : ICheckIfSeriesShouldBeRefreshed
{
private readonly IEpisodeService _episodeService;
private readonly Logger _logger;
public ShouldRefreshSeries(IEpisodeService episodeService, Logger logger)
{
_episodeService = episodeService;
_logger = logger;
}
public bool ShouldRefresh(Series series)
{
if (series.LastInfoSync < DateTime.UtcNow.AddDays(-30))
{
_logger.Trace("Series {0} last updated more than 30 days ago, should refresh.", series.Title);
return true;
}
if (series.LastInfoSync >= DateTime.UtcNow.AddHours(-6))
{
_logger.Trace("Series {0} last updated less than 6 hours ago, should not be refreshed.", series.Title);
return false;
}
if (series.Status == SeriesStatusType.Continuing)
{
_logger.Trace("Series {0} is continuing, should refresh.", series.Title);
return true;
}
var lastEpisode = _episodeService.GetEpisodeBySeries(series.Id).OrderByDescending(e => e.AirDateUtc).FirstOrDefault();
if (lastEpisode != null && lastEpisode.AirDateUtc > DateTime.UtcNow.AddDays(-30))
{
_logger.Trace("Last episode in {0} aired less than 30 days ago, should refresh.", series.Title);
return true;
}
_logger.Trace("Series {0} ended long ago, should not be refreshed.", series.Title);
return false;
}
}
}
Loading…
Cancel
Save