parent
1576bf1f17
commit
6a03eddda9
@ -0,0 +1,303 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Datastore.Migration;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore.Migration
|
||||
{
|
||||
[TestFixture]
|
||||
public class movie_metadataFixture : MigrationTest<movie_metadata>
|
||||
{
|
||||
[Test]
|
||||
public void should_add_metadata_from_movie_and_link_back_to_movie()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Movies").Row(new
|
||||
{
|
||||
Monitored = true,
|
||||
Title = "Title",
|
||||
CleanTitle = "CleanTitle",
|
||||
Status = 3,
|
||||
MinimumAvailability = 4,
|
||||
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
|
||||
Recommendations = new[] { 1 }.ToJson(),
|
||||
Runtime = 90,
|
||||
OriginalLanguage = 1,
|
||||
ProfileId = 1,
|
||||
MovieFileId = 0,
|
||||
Path = string.Format("/Movies/{0}", "Title"),
|
||||
TitleSlug = 123456,
|
||||
TmdbId = 132456,
|
||||
Added = DateTime.UtcNow,
|
||||
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
|
||||
LastInfoSync = DateTime.UtcNow,
|
||||
});
|
||||
});
|
||||
|
||||
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
|
||||
|
||||
metadata.Should().HaveCount(1);
|
||||
metadata.First().TmdbId.Should().Be(132456);
|
||||
metadata.First().Title.Should().Be("Title");
|
||||
|
||||
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\"");
|
||||
|
||||
movies.Should().HaveCount(1);
|
||||
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_link_metadata_to_credits()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Movies").Row(new
|
||||
{
|
||||
Id = 5,
|
||||
Monitored = true,
|
||||
Title = "Title",
|
||||
CleanTitle = "CleanTitle",
|
||||
Status = 3,
|
||||
MinimumAvailability = 4,
|
||||
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
|
||||
Recommendations = new[] { 1 }.ToJson(),
|
||||
Runtime = 90,
|
||||
OriginalLanguage = 1,
|
||||
ProfileId = 1,
|
||||
MovieFileId = 0,
|
||||
Path = string.Format("/Movies/{0}", "Title"),
|
||||
TitleSlug = 123456,
|
||||
TmdbId = 132456,
|
||||
Added = DateTime.UtcNow,
|
||||
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
|
||||
LastInfoSync = DateTime.UtcNow,
|
||||
});
|
||||
|
||||
c.Insert.IntoTable("Credits").Row(new
|
||||
{
|
||||
MovieId = 5,
|
||||
CreditTmdbId = 123,
|
||||
PersonTmdbId = 456,
|
||||
Order = 1,
|
||||
Type = 1,
|
||||
Name = "Some Person",
|
||||
Images = new[] { new { CoverType = "Poster" } }.ToJson()
|
||||
});
|
||||
});
|
||||
|
||||
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
|
||||
|
||||
metadata.Should().HaveCount(1);
|
||||
metadata.First().TmdbId.Should().Be(132456);
|
||||
metadata.First().Title.Should().Be("Title");
|
||||
|
||||
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Credits\"");
|
||||
|
||||
movies.Should().HaveCount(1);
|
||||
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_link_metadata_to_alt_title()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Movies").Row(new
|
||||
{
|
||||
Id = 5,
|
||||
Monitored = true,
|
||||
Title = "Title",
|
||||
CleanTitle = "CleanTitle",
|
||||
Status = 3,
|
||||
MinimumAvailability = 4,
|
||||
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
|
||||
Recommendations = new[] { 1 }.ToJson(),
|
||||
Runtime = 90,
|
||||
OriginalLanguage = 1,
|
||||
ProfileId = 1,
|
||||
MovieFileId = 0,
|
||||
Path = string.Format("/Movies/{0}", "Title"),
|
||||
TitleSlug = 123456,
|
||||
TmdbId = 132456,
|
||||
Added = DateTime.UtcNow,
|
||||
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
|
||||
LastInfoSync = DateTime.UtcNow,
|
||||
});
|
||||
|
||||
c.Insert.IntoTable("AlternativeTitles").Row(new
|
||||
{
|
||||
MovieId = 5,
|
||||
Title = "Some Alt",
|
||||
CleanTitle = "somealt",
|
||||
SourceType = 1,
|
||||
SourceId = 1,
|
||||
Votes = 0,
|
||||
VoteCount = 0,
|
||||
Language = 1
|
||||
});
|
||||
});
|
||||
|
||||
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
|
||||
|
||||
metadata.Should().HaveCount(1);
|
||||
metadata.First().TmdbId.Should().Be(132456);
|
||||
metadata.First().Title.Should().Be("Title");
|
||||
|
||||
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"AlternativeTitles\"");
|
||||
|
||||
movies.Should().HaveCount(1);
|
||||
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_link_metadata_to_translation()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Movies").Row(new
|
||||
{
|
||||
Id = 5,
|
||||
Monitored = true,
|
||||
Title = "Title",
|
||||
CleanTitle = "CleanTitle",
|
||||
Status = 3,
|
||||
MinimumAvailability = 4,
|
||||
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
|
||||
Recommendations = new[] { 1 }.ToJson(),
|
||||
Runtime = 90,
|
||||
OriginalLanguage = 1,
|
||||
ProfileId = 1,
|
||||
MovieFileId = 0,
|
||||
Path = string.Format("/Movies/{0}", "Title"),
|
||||
TitleSlug = 123456,
|
||||
TmdbId = 132456,
|
||||
Added = DateTime.UtcNow,
|
||||
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
|
||||
LastInfoSync = DateTime.UtcNow,
|
||||
});
|
||||
|
||||
c.Insert.IntoTable("MovieTranslations").Row(new
|
||||
{
|
||||
MovieId = 5,
|
||||
Title = "Some Trans",
|
||||
Language = 1
|
||||
});
|
||||
});
|
||||
|
||||
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
|
||||
|
||||
metadata.Should().HaveCount(1);
|
||||
metadata.First().TmdbId.Should().Be(132456);
|
||||
metadata.First().Title.Should().Be("Title");
|
||||
|
||||
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"MovieTranslations\"");
|
||||
|
||||
movies.Should().HaveCount(1);
|
||||
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_metadata_from_list_and_link_back()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("ImportListMovies").Row(new
|
||||
{
|
||||
Title = "Title",
|
||||
Status = 3,
|
||||
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
|
||||
Runtime = 90,
|
||||
TmdbId = 123456,
|
||||
ListId = 4,
|
||||
Translations = new[] { new { } }.ToJson(),
|
||||
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
|
||||
});
|
||||
});
|
||||
|
||||
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
|
||||
|
||||
metadata.Should().HaveCount(1);
|
||||
metadata.First().TmdbId.Should().Be(123456);
|
||||
metadata.First().Title.Should().Be("Title");
|
||||
|
||||
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
|
||||
|
||||
movies.Should().HaveCount(1);
|
||||
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_duplicate_metadata()
|
||||
{
|
||||
var db = WithMigrationTestDb(c =>
|
||||
{
|
||||
c.Insert.IntoTable("Movies").Row(new
|
||||
{
|
||||
Monitored = true,
|
||||
Title = "Title",
|
||||
CleanTitle = "CleanTitle",
|
||||
Status = 3,
|
||||
MinimumAvailability = 4,
|
||||
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
|
||||
Recommendations = new[] { 1 }.ToJson(),
|
||||
Runtime = 90,
|
||||
OriginalLanguage = 1,
|
||||
ProfileId = 1,
|
||||
MovieFileId = 0,
|
||||
Path = string.Format("/Movies/{0}", "Title"),
|
||||
TitleSlug = 123456,
|
||||
TmdbId = 123456,
|
||||
Added = DateTime.UtcNow,
|
||||
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
|
||||
LastInfoSync = DateTime.UtcNow,
|
||||
});
|
||||
|
||||
c.Insert.IntoTable("ImportListMovies").Row(new
|
||||
{
|
||||
Title = "Title",
|
||||
Status = 3,
|
||||
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
|
||||
Runtime = 90,
|
||||
TmdbId = 123456,
|
||||
ListId = 4,
|
||||
Translations = new[] { new { } }.ToJson(),
|
||||
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
|
||||
});
|
||||
});
|
||||
|
||||
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
|
||||
|
||||
metadata.Should().HaveCount(1);
|
||||
metadata.First().TmdbId.Should().Be(123456);
|
||||
metadata.First().Title.Should().Be("Title");
|
||||
|
||||
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\"");
|
||||
|
||||
movies.Should().HaveCount(1);
|
||||
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
|
||||
|
||||
var listMovies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
|
||||
|
||||
listMovies.Should().HaveCount(1);
|
||||
listMovies.First().MovieMetadataId.Should().Be(metadata.First().Id);
|
||||
}
|
||||
}
|
||||
|
||||
public class MovieMetadata207
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int TmdbId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public bool Monitored { get; set; }
|
||||
}
|
||||
|
||||
public class Movie207
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int MovieMetadataId { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Housekeeping.Housekeepers;
|
||||
using NzbDrone.Core.ImportLists.ImportListMovies;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Movies.Translations;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||
{
|
||||
[TestFixture]
|
||||
public class CleanupOrphanedMovieMetadataFixture : DbTest<CleanupOrphanedMovieMetadata, MovieMetadata>
|
||||
{
|
||||
[Test]
|
||||
public void should_delete_orphaned_movie_metadata_items()
|
||||
{
|
||||
var metadata = Builder<MovieMetadata>.CreateNew().BuildNew();
|
||||
|
||||
Db.Insert(metadata);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_delete_unorphaned_movie_metadata_items()
|
||||
{
|
||||
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
|
||||
|
||||
Db.Insert(movieMetadata);
|
||||
|
||||
var movie = Builder<Movie>.CreateNew()
|
||||
.With(b => b.MovieMetadataId = movieMetadata.Id)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(movie);
|
||||
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_delete_unorphaned_movie_metadata_items_for_lists()
|
||||
{
|
||||
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
|
||||
|
||||
Db.Insert(movieMetadata);
|
||||
|
||||
var movie = Builder<ImportListMovie>.CreateNew()
|
||||
.With(b => b.MovieMetadataId = movieMetadata.Id)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(movie);
|
||||
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.MovieTests.MovieMetadataRepositoryTests
|
||||
{
|
||||
[TestFixture]
|
||||
|
||||
public class MovieMetadataRepositoryFixture : DbTest<MovieMetadataRepository, MovieMetadata>
|
||||
{
|
||||
private MovieMetadataRepository _movieMetadataRepo;
|
||||
private List<MovieMetadata> _metadataList;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_movieMetadataRepo = Mocker.Resolve<MovieMetadataRepository>();
|
||||
_metadataList = Builder<MovieMetadata>.CreateListOfSize(10).All().With(x => x.Id = 0).BuildList();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void upsert_many_should_insert_list_of_new()
|
||||
{
|
||||
var updated = _movieMetadataRepo.UpsertMany(_metadataList);
|
||||
AllStoredModels.Should().HaveCount(_metadataList.Count);
|
||||
updated.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void upsert_many_should_upsert_existing_with_id_0()
|
||||
{
|
||||
var clone = _metadataList.JsonClone();
|
||||
var updated = _movieMetadataRepo.UpsertMany(clone);
|
||||
|
||||
updated.Should().BeTrue();
|
||||
AllStoredModels.Should().HaveCount(_metadataList.Count);
|
||||
|
||||
updated = _movieMetadataRepo.UpsertMany(_metadataList);
|
||||
updated.Should().BeFalse();
|
||||
AllStoredModels.Should().HaveCount(_metadataList.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void upsert_many_should_upsert_mixed_list_of_old_and_new()
|
||||
{
|
||||
var clone = _metadataList.Take(5).ToList().JsonClone();
|
||||
var updated = _movieMetadataRepo.UpsertMany(clone);
|
||||
|
||||
updated.Should().BeTrue();
|
||||
AllStoredModels.Should().HaveCount(clone.Count);
|
||||
|
||||
updated = _movieMetadataRepo.UpsertMany(_metadataList);
|
||||
updated.Should().BeTrue();
|
||||
AllStoredModels.Should().HaveCount(_metadataList.Count);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Core.Test.MovieTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class MovieTitleSlugValidatorFixture : CoreTest<MovieTitleSlugValidator>
|
||||
{
|
||||
private List<Movie> _movies;
|
||||
private TestValidator<Movie> _validator;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_movies = Builder<Movie>.CreateListOfSize(1)
|
||||
.Build()
|
||||
.ToList();
|
||||
|
||||
_validator = new TestValidator<Movie>
|
||||
{
|
||||
v => v.RuleFor(s => s.TitleSlug).SetValidator(Subject)
|
||||
};
|
||||
|
||||
Mocker.GetMock<IMovieService>()
|
||||
.Setup(s => s.AllMovieTitleSlugs())
|
||||
.Returns(_movies.ToDictionary(m => m.Id, m => m.TitleSlug));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_be_valid_if_there_is_an_existing_movie_with_the_same_title_slug()
|
||||
{
|
||||
Mocker.GetMock<IMovieService>()
|
||||
.Setup(s => s.GetMovie(_movies.First().Id))
|
||||
.Returns(_movies.First());
|
||||
|
||||
var movie = Builder<Movie>.CreateNew()
|
||||
.With(s => s.Id = 100)
|
||||
.With(s => s.TitleSlug = _movies.First().TitleSlug)
|
||||
.Build();
|
||||
|
||||
_validator.Validate(movie).IsValid.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_valid_if_there_is_not_an_existing_movie_with_the_same_title_slug()
|
||||
{
|
||||
var movie = Builder<Movie>.CreateNew()
|
||||
.With(s => s.TitleSlug = "MyTitleSlug")
|
||||
.Build();
|
||||
|
||||
_validator.Validate(movie).IsValid.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_valid_if_there_is_an_existing_movie_with_a_null_title_slug()
|
||||
{
|
||||
_movies.First().TitleSlug = null;
|
||||
|
||||
var movie = Builder<Movie>.CreateNew()
|
||||
.With(s => s.TitleSlug = "MyTitleSlug")
|
||||
.Build();
|
||||
|
||||
_validator.Validate(movie).IsValid.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_valid_when_updating_an_existing_movie()
|
||||
{
|
||||
_validator.Validate(_movies.First().JsonClone()).IsValid.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(207)]
|
||||
public class movie_metadata : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Create.TableForModel("MovieMetadata")
|
||||
.WithColumn("TmdbId").AsInt32().Unique()
|
||||
.WithColumn("ImdbId").AsString().Nullable()
|
||||
.WithColumn("Images").AsString()
|
||||
.WithColumn("Genres").AsString().Nullable()
|
||||
.WithColumn("Title").AsString()
|
||||
.WithColumn("SortTitle").AsString().Nullable()
|
||||
.WithColumn("CleanTitle").AsString().Nullable().Indexed()
|
||||
.WithColumn("OriginalTitle").AsString().Nullable()
|
||||
.WithColumn("CleanOriginalTitle").AsString().Nullable().Indexed()
|
||||
.WithColumn("OriginalLanguage").AsInt32()
|
||||
.WithColumn("Status").AsInt32()
|
||||
.WithColumn("LastInfoSync").AsDateTime().Nullable()
|
||||
.WithColumn("Runtime").AsInt32()
|
||||
.WithColumn("InCinemas").AsDateTime().Nullable()
|
||||
.WithColumn("PhysicalRelease").AsDateTime().Nullable()
|
||||
.WithColumn("DigitalRelease").AsDateTime().Nullable()
|
||||
.WithColumn("Year").AsInt32().Nullable()
|
||||
.WithColumn("SecondaryYear").AsInt32().Nullable()
|
||||
.WithColumn("Ratings").AsString().Nullable()
|
||||
.WithColumn("Recommendations").AsString()
|
||||
.WithColumn("Certification").AsString().Nullable()
|
||||
.WithColumn("YouTubeTrailerId").AsString().Nullable()
|
||||
.WithColumn("Collection").AsString().Nullable()
|
||||
.WithColumn("Studio").AsString().Nullable()
|
||||
.WithColumn("Overview").AsString().Nullable()
|
||||
.WithColumn("Website").AsString().Nullable()
|
||||
.WithColumn("Popularity").AsFloat().Nullable();
|
||||
|
||||
// Transfer metadata from Movies to MovieMetadata
|
||||
Execute.Sql(@"INSERT INTO ""MovieMetadata"" (""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""CleanTitle"", ""OriginalTitle"", ""CleanOriginalTitle"", ""OriginalLanguage"", ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""SecondaryYear"", ""Recommendations"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website"")
|
||||
SELECT ""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""CleanTitle"", ""OriginalTitle"", ""CleanTitle"", ""OriginalLanguage"", ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""SecondaryYear"", ""Recommendations"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website""
|
||||
FROM ""Movies""");
|
||||
|
||||
// Transfer metadata from ImportListMovies to MovieMetadata if not already in
|
||||
Execute.Sql(@"INSERT INTO ""MovieMetadata"" (""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""CleanTitle"", ""OriginalTitle"", ""CleanOriginalTitle"", ""OriginalLanguage"", ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""Recommendations"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website"")
|
||||
SELECT ""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""Title"", ""OriginalTitle"", ""OriginalTitle"", 1, ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", '[]', ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website""
|
||||
FROM ""ImportListMovies""
|
||||
WHERE ""ImportListMovies"".""TmdbId"" NOT IN ( SELECT ""MovieMetadata"".""TmdbId"" FROM ""MovieMetadata"" )");
|
||||
|
||||
// Add an MovieMetadataId column to Movies
|
||||
Alter.Table("Movies").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);
|
||||
Alter.Table("AlternativeTitles").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);
|
||||
Alter.Table("Credits").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);
|
||||
Alter.Table("MovieTranslations").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);
|
||||
Alter.Table("ImportListMovies").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0).Indexed();
|
||||
|
||||
// Update MovieMetadataId
|
||||
Execute.Sql(@"UPDATE ""Movies""
|
||||
SET ""MovieMetadataId"" = (SELECT ""MovieMetadata"".""Id""
|
||||
FROM ""MovieMetadata""
|
||||
WHERE ""MovieMetadata"".""TmdbId"" = ""Movies"".""TmdbId"")");
|
||||
|
||||
Execute.Sql(@"UPDATE ""AlternativeTitles""
|
||||
SET ""MovieMetadataId"" = (SELECT ""Movies"".""MovieMetadataId""
|
||||
FROM ""Movies""
|
||||
WHERE ""Movies"".""Id"" = ""AlternativeTitles"".""MovieId"")");
|
||||
|
||||
Execute.Sql(@"UPDATE ""Credits""
|
||||
SET ""MovieMetadataId"" = (SELECT ""Movies"".""MovieMetadataId""
|
||||
FROM ""Movies""
|
||||
WHERE ""Movies"".""Id"" = ""Credits"".""MovieId"")");
|
||||
|
||||
Execute.Sql(@"UPDATE ""MovieTranslations""
|
||||
SET ""MovieMetadataId"" = (SELECT ""Movies"".""MovieMetadataId""
|
||||
FROM ""Movies""
|
||||
WHERE ""Movies"".""Id"" = ""MovieTranslations"".""MovieId"")");
|
||||
|
||||
Execute.Sql(@"UPDATE ""ImportListMovies""
|
||||
SET ""MovieMetadataId"" = (SELECT ""MovieMetadata"".""Id""
|
||||
FROM ""MovieMetadata""
|
||||
WHERE ""MovieMetadata"".""TmdbId"" = ""ImportListMovies"".""TmdbId"")");
|
||||
|
||||
// Alter MovieMetadataId column to be unique on Movies
|
||||
Alter.Table("Movies").AlterColumn("MovieMetadataId").AsInt32().Unique();
|
||||
|
||||
// Remove Movie Link from Metadata Tables
|
||||
Delete.Column("MovieId").FromTable("AlternativeTitles");
|
||||
Delete.Column("MovieId").FromTable("Credits");
|
||||
Delete.Column("MovieId").FromTable("MovieTranslations");
|
||||
|
||||
// Remove the columns in Movies now in MovieMetadata
|
||||
Delete.Column("TmdbId")
|
||||
.Column("ImdbId")
|
||||
.Column("Title")
|
||||
.Column("SortTitle")
|
||||
.Column("CleanTitle")
|
||||
.Column("OriginalTitle")
|
||||
.Column("OriginalLanguage")
|
||||
.Column("Overview")
|
||||
.Column("Status")
|
||||
.Column("LastInfoSync")
|
||||
.Column("Images")
|
||||
.Column("Genres")
|
||||
.Column("Ratings")
|
||||
.Column("Runtime")
|
||||
.Column("InCinemas")
|
||||
.Column("PhysicalRelease")
|
||||
.Column("DigitalRelease")
|
||||
.Column("Year")
|
||||
.Column("SecondaryYear")
|
||||
.Column("Recommendations")
|
||||
.Column("Certification")
|
||||
.Column("YouTubeTrailerId")
|
||||
.Column("Studio")
|
||||
.Column("Collection")
|
||||
.Column("Website")
|
||||
|
||||
// as well as the ones no longer used
|
||||
.Column("LastDiskSync")
|
||||
.Column("TitleSlug")
|
||||
.FromTable("Movies");
|
||||
|
||||
// Remove the columns in ImportListMovies now in MovieMetadata
|
||||
Delete.Column("TmdbId")
|
||||
.Column("ImdbId")
|
||||
.Column("Title")
|
||||
.Column("SortTitle")
|
||||
.Column("Overview")
|
||||
.Column("Status")
|
||||
.Column("LastInfoSync")
|
||||
.Column("OriginalTitle")
|
||||
.Column("Translations")
|
||||
.Column("Images")
|
||||
.Column("Genres")
|
||||
.Column("Ratings")
|
||||
.Column("Runtime")
|
||||
.Column("InCinemas")
|
||||
.Column("PhysicalRelease")
|
||||
.Column("DigitalRelease")
|
||||
.Column("Year")
|
||||
.Column("Certification")
|
||||
.Column("YouTubeTrailerId")
|
||||
.Column("Studio")
|
||||
.Column("Collection")
|
||||
.Column("Website")
|
||||
.FromTable("ImportListMovies");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
using Dapper;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class CleanupOrphanedMovieMetadata : IHousekeepingTask
|
||||
{
|
||||
private readonly IMainDatabase _database;
|
||||
|
||||
public CleanupOrphanedMovieMetadata(IMainDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
using (var mapper = _database.OpenConnection())
|
||||
{
|
||||
mapper.Execute(@"DELETE FROM ""MovieMetadata""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""MovieMetadata"".""Id"" FROM ""MovieMetadata""
|
||||
LEFT OUTER JOIN ""Movies"" ON ""Movies"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
|
||||
LEFT OUTER JOIN ""ImportListMovies"" ON ""ImportListMovies"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
|
||||
WHERE ""Movies"".""Id"" IS NULL AND ""ImportListMovies"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using Equ;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Movies
|
||||
{
|
||||
public abstract class Entity<T> : ModelBase, IEquatable<T>
|
||||
where T : Entity<T>
|
||||
{
|
||||
private static readonly MemberwiseEqualityComparer<T> _comparer =
|
||||
MemberwiseEqualityComparer<T>.ByProperties;
|
||||
|
||||
public virtual void UseDbFieldsFrom(T other)
|
||||
{
|
||||
Id = other.Id;
|
||||
}
|
||||
|
||||
public virtual void UseMetadataFrom(T other)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void ApplyChanges(T other)
|
||||
{
|
||||
}
|
||||
|
||||
public bool Equals(T other)
|
||||
{
|
||||
return _comparer.Equals(this as T, other);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as T);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _comparer.GetHashCode(this as T);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Equ;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Movies.AlternativeTitles;
|
||||
using NzbDrone.Core.Movies.Translations;
|
||||
|
||||
namespace NzbDrone.Core.Movies
|
||||
{
|
||||
public class MovieMetadata : Entity<MovieMetadata>
|
||||
{
|
||||
public MovieMetadata()
|
||||
{
|
||||
AlternativeTitles = new List<AlternativeTitle>();
|
||||
Translations = new List<MovieTranslation>();
|
||||
Images = new List<MediaCover.MediaCover>();
|
||||
Genres = new List<string>();
|
||||
OriginalLanguage = Language.English;
|
||||
Recommendations = new List<int>();
|
||||
Ratings = new Ratings();
|
||||
}
|
||||
|
||||
public int TmdbId { get; set; }
|
||||
|
||||
public List<MediaCover.MediaCover> Images { get; set; }
|
||||
public List<string> Genres { get; set; }
|
||||
public DateTime? InCinemas { get; set; }
|
||||
public DateTime? PhysicalRelease { get; set; }
|
||||
public DateTime? DigitalRelease { get; set; }
|
||||
public string Certification { get; set; }
|
||||
public int Year { get; set; }
|
||||
public Ratings Ratings { get; set; }
|
||||
|
||||
public MovieCollection Collection { get; set; }
|
||||
public DateTime? LastInfoSync { get; set; }
|
||||
public int Runtime { get; set; }
|
||||
public string Website { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string CleanTitle { get; set; }
|
||||
public string SortTitle { get; set; }
|
||||
public MovieStatusType Status { get; set; }
|
||||
public string Overview { get; set; }
|
||||
|
||||
//Get Loaded via a Join Query
|
||||
public List<AlternativeTitle> AlternativeTitles { get; set; }
|
||||
public List<MovieTranslation> Translations { get; set; }
|
||||
|
||||
public int? SecondaryYear { get; set; }
|
||||
public string YouTubeTrailerId { get; set; }
|
||||
public string Studio { get; set; }
|
||||
public string OriginalTitle { get; set; }
|
||||
public string CleanOriginalTitle { get; set; }
|
||||
public Language OriginalLanguage { get; set; }
|
||||
public List<int> Recommendations { get; set; }
|
||||
public float Popularity { get; set; }
|
||||
|
||||
[MemberwiseEqualityIgnore]
|
||||
public bool IsRecentMovie
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PhysicalRelease.HasValue)
|
||||
{
|
||||
return PhysicalRelease.Value >= DateTime.UtcNow.AddDays(-21);
|
||||
}
|
||||
|
||||
if (InCinemas.HasValue)
|
||||
{
|
||||
return InCinemas.Value >= DateTime.UtcNow.AddDays(-120);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime PhysicalReleaseDate()
|
||||
{
|
||||
return PhysicalRelease ?? (InCinemas?.AddDays(90) ?? DateTime.MaxValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.Movies
|
||||
{
|
||||
public interface IMovieMetadataRepository : IBasicRepository<MovieMetadata>
|
||||
{
|
||||
MovieMetadata FindByTmdbId(int tmdbId);
|
||||
List<MovieMetadata> FindById(List<int> tmdbIds);
|
||||
bool UpsertMany(List<MovieMetadata> data);
|
||||
}
|
||||
|
||||
public class MovieMetadataRepository : BasicRepository<MovieMetadata>, IMovieMetadataRepository
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MovieMetadataRepository(IMainDatabase database, IEventAggregator eventAggregator, Logger logger)
|
||||
: base(database, eventAggregator)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public MovieMetadata FindByTmdbId(int tmdbid)
|
||||
{
|
||||
return Query(x => x.TmdbId == tmdbid).FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<MovieMetadata> FindById(List<int> tmdbIds)
|
||||
{
|
||||
return Query(x => Enumerable.Contains(tmdbIds, x.TmdbId));
|
||||
}
|
||||
|
||||
public bool UpsertMany(List<MovieMetadata> data)
|
||||
{
|
||||
var existingMetadata = FindById(data.Select(x => x.TmdbId).ToList());
|
||||
var updateMetadataList = new List<MovieMetadata>();
|
||||
var addMetadataList = new List<MovieMetadata>();
|
||||
int upToDateMetadataCount = 0;
|
||||
|
||||
foreach (var meta in data)
|
||||
{
|
||||
var existing = existingMetadata.SingleOrDefault(x => x.TmdbId == meta.TmdbId);
|
||||
if (existing != null)
|
||||
{
|
||||
meta.UseDbFieldsFrom(existing);
|
||||
if (!meta.Equals(existing))
|
||||
{
|
||||
updateMetadataList.Add(meta);
|
||||
}
|
||||
else
|
||||
{
|
||||
upToDateMetadataCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addMetadataList.Add(meta);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateMany(updateMetadataList);
|
||||
InsertMany(addMetadataList);
|
||||
|
||||
_logger.Debug($"{upToDateMetadataCount} movie metadata up to date; Updating {updateMetadataList.Count}, Adding {addMetadataList.Count} movie metadata entries.");
|
||||
|
||||
return updateMetadataList.Count > 0 || addMetadataList.Count > 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Movies
|
||||
{
|
||||
public interface IMovieMetadataService
|
||||
{
|
||||
MovieMetadata Get(int id);
|
||||
MovieMetadata FindByTmdbId(int tmdbid);
|
||||
bool Upsert(MovieMetadata movie);
|
||||
bool UpsertMany(List<MovieMetadata> movies);
|
||||
}
|
||||
|
||||
public class MovieMetadataService : IMovieMetadataService
|
||||
{
|
||||
private readonly IMovieMetadataRepository _movieMetadataRepository;
|
||||
|
||||
public MovieMetadataService(IMovieMetadataRepository movieMetadataRepository)
|
||||
{
|
||||
_movieMetadataRepository = movieMetadataRepository;
|
||||
}
|
||||
|
||||
public MovieMetadata FindByTmdbId(int tmdbid)
|
||||
{
|
||||
return _movieMetadataRepository.FindByTmdbId(tmdbid);
|
||||
}
|
||||
|
||||
public MovieMetadata Get(int id)
|
||||
{
|
||||
return _movieMetadataRepository.Get(id);
|
||||
}
|
||||
|
||||
public bool Upsert(MovieMetadata movie)
|
||||
{
|
||||
return _movieMetadataRepository.UpsertMany(new List<MovieMetadata> { movie });
|
||||
}
|
||||
|
||||
public bool UpsertMany(List<MovieMetadata> movies)
|
||||
{
|
||||
return _movieMetadataRepository.UpsertMany(movies);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation.Validators;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.Movies
|
||||
{
|
||||
public class MovieTitleSlugValidator : PropertyValidator
|
||||
{
|
||||
private readonly IMovieService _movieService;
|
||||
|
||||
public MovieTitleSlugValidator(IMovieService movieService)
|
||||
: base("Title slug '{slug}' is in use by movie '{movieTitle}'")
|
||||
{
|
||||
_movieService = movieService;
|
||||
}
|
||||
|
||||
protected override bool IsValid(PropertyValidatorContext context)
|
||||
{
|
||||
if (context.PropertyValue == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
dynamic instance = context.ParentContext.InstanceToValidate;
|
||||
var instanceId = (int)instance.Id;
|
||||
var slug = context.PropertyValue.ToString();
|
||||
|
||||
var conflictingId = _movieService.AllMovieTitleSlugs()
|
||||
.FirstOrDefault(s => s.Value.IsNotNullOrWhiteSpace() &&
|
||||
s.Value.Equals(context.PropertyValue.ToString()) &&
|
||||
s.Key != instanceId);
|
||||
|
||||
if (conflictingId.Equals(default(KeyValuePair<int, string>)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var conflictingMovie = _movieService.GetMovie(conflictingId.Key);
|
||||
|
||||
context.MessageFormatter.AppendArgument("slug", slug);
|
||||
context.MessageFormatter.AppendArgument("movieTitle", conflictingMovie.Title);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue