Rework Movie Metadata data model

This commit is contained in:
Qstick 2022-03-20 10:55:47 -05:00
parent 1576bf1f17
commit 6a03eddda9
126 changed files with 1695 additions and 1031 deletions

View File

@ -116,10 +116,11 @@ class NamingModal extends Component {
const movieTokens = [
{ token: '{Movie Title}', example: 'Movie\'s Title' },
{ token: '{Movie Title:DE}', example: 'Filetitle' },
{ token: '{Movie Title:DE}', example: 'Titel des Films' },
{ token: '{Movie CleanTitle}', example: 'Movies Title' },
{ token: '{Movie TitleThe}', example: 'Movie\'s Title, The' },
{ token: '{Movie OriginalTitle}', example: 'Τίτλος ταινίας' },
{ token: '{Movie CleanOriginalTitle}', example: 'Τίτλος ταινίας' },
{ token: '{Movie TitleFirstCharacter}', example: 'M' },
{ token: '{Movie Collection}', example: 'The Movie Collection' },
{ token: '{Movie Certification}', example: 'R' },

View File

@ -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; }
}
}

View File

@ -27,6 +27,11 @@ namespace NzbDrone.Core.Test.Datastore
return new WhereBuilderPostgres(filter, true, 0);
}
private WhereBuilderPostgres WhereMeta(Expression<Func<MovieMetadata, bool>> filter)
{
return new WhereBuilderPostgres(filter, true, 0);
}
[Test]
public void postgres_where_equal_const()
{
@ -86,36 +91,36 @@ namespace NzbDrone.Core.Test.Datastore
[Test]
public void postgres_where_string_is_null()
{
_subject = Where(x => x.CleanTitle == null);
_subject = WhereMeta(x => x.CleanTitle == null);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_string_is_null_value()
{
string cleanTitle = null;
_subject = Where(x => x.CleanTitle == cleanTitle);
_subject = WhereMeta(x => x.CleanTitle == cleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_equal_null_property()
{
var movie = new Movie { CleanTitle = null };
_subject = Where(x => x.CleanTitle == movie.CleanTitle);
var movie = new MovieMetadata { CleanTitle = null };
_subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void postgres_where_column_contains_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.Contains(test));
_subject = WhereMeta(x => x.CleanTitle.Contains(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE '%' || @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE '%' || @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@ -123,9 +128,9 @@ namespace NzbDrone.Core.Test.Datastore
public void postgres_where_string_contains_column()
{
var test = "small";
_subject = Where(x => test.Contains(x.CleanTitle));
_subject = WhereMeta(x => test.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(@Clause1_P1 ILIKE '%' || \"Movies\".\"CleanTitle\" || '%')");
_subject.ToString().Should().Be($"(@Clause1_P1 ILIKE '%' || \"MovieMetadata\".\"CleanTitle\" || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@ -133,9 +138,9 @@ namespace NzbDrone.Core.Test.Datastore
public void postgres_where_column_starts_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.StartsWith(test));
_subject = WhereMeta(x => x.CleanTitle.StartsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@ -143,9 +148,9 @@ namespace NzbDrone.Core.Test.Datastore
public void postgres_where_column_ends_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.EndsWith(test));
_subject = WhereMeta(x => x.CleanTitle.EndsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE '%' || @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE '%' || @Clause1_P1)");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@ -162,9 +167,9 @@ namespace NzbDrone.Core.Test.Datastore
public void postgres_where_in_list_2()
{
var list = new List<int> { 1, 2, 3 };
_subject = Where(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject = WhereMeta(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject.ToString().Should().Be($"((\"Movies\".\"CleanTitle\" = @Clause1_P1) AND (\"Movies\".\"Id\" = ANY (('{{1, 2, 3}}'))))");
_subject.ToString().Should().Be($"((\"MovieMetadata\".\"CleanTitle\" = @Clause1_P1) AND (\"MovieMetadata\".\"Id\" = ANY (('{{1, 2, 3}}'))))");
}
[Test]
@ -172,35 +177,35 @@ namespace NzbDrone.Core.Test.Datastore
{
var list = new List<string> { "first", "second", "third" };
_subject = Where(x => list.Contains(x.CleanTitle));
_subject = WhereMeta(x => list.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" = ANY (@Clause1_P1))");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" = ANY (@Clause1_P1))");
}
[Test]
public void enum_as_int()
{
_subject = Where(x => x.Status == MovieStatusType.Announced);
_subject = WhereMeta(x => x.Status == MovieStatusType.Announced);
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = @Clause1_P1)");
}
[Test]
public void enum_in_list()
{
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = ANY (@Clause1_P1))");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = ANY (@Clause1_P1))");
}
[Test]
public void enum_in_array()
{
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = ANY (@Clause1_P1))");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = ANY (@Clause1_P1))");
}
}
}

View File

@ -27,6 +27,11 @@ namespace NzbDrone.Core.Test.Datastore
return new WhereBuilderSqlite(filter, true, 0);
}
private WhereBuilderSqlite WhereMeta(Expression<Func<MovieMetadata, bool>> filter)
{
return new WhereBuilderSqlite(filter, true, 0);
}
[Test]
public void where_equal_const()
{
@ -86,36 +91,36 @@ namespace NzbDrone.Core.Test.Datastore
[Test]
public void where_string_is_null()
{
_subject = Where(x => x.CleanTitle == null);
_subject = WhereMeta(x => x.CleanTitle == null);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_string_is_null_value()
{
string cleanTitle = null;
_subject = Where(x => x.CleanTitle == cleanTitle);
_subject = WhereMeta(x => x.CleanTitle == cleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_equal_null_property()
{
var movie = new Movie { CleanTitle = null };
_subject = Where(x => x.CleanTitle == movie.CleanTitle);
var movie = new MovieMetadata { CleanTitle = null };
_subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
}
[Test]
public void where_column_contains_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.Contains(test));
_subject = WhereMeta(x => x.CleanTitle.Contains(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE '%' || @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE '%' || @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@ -123,9 +128,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_string_contains_column()
{
var test = "small";
_subject = Where(x => test.Contains(x.CleanTitle));
_subject = WhereMeta(x => test.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(@Clause1_P1 LIKE '%' || \"Movies\".\"CleanTitle\" || '%')");
_subject.ToString().Should().Be($"(@Clause1_P1 LIKE '%' || \"MovieMetadata\".\"CleanTitle\" || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@ -133,9 +138,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_column_starts_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.StartsWith(test));
_subject = WhereMeta(x => x.CleanTitle.StartsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE @Clause1_P1 || '%')");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE @Clause1_P1 || '%')");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@ -143,9 +148,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_column_ends_with_string()
{
var test = "small";
_subject = Where(x => x.CleanTitle.EndsWith(test));
_subject = WhereMeta(x => x.CleanTitle.EndsWith(test));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE '%' || @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE '%' || @Clause1_P1)");
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
}
@ -164,9 +169,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_in_list_2()
{
var list = new List<int> { 1, 2, 3 };
_subject = Where(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject = WhereMeta(x => x.CleanTitle == "test" && list.Contains(x.Id));
_subject.ToString().Should().Be($"((\"Movies\".\"CleanTitle\" = @Clause1_P1) AND (\"Movies\".\"Id\" IN (1, 2, 3)))");
_subject.ToString().Should().Be($"((\"MovieMetadata\".\"CleanTitle\" = @Clause1_P1) AND (\"MovieMetadata\".\"Id\" IN (1, 2, 3)))");
}
[Test]
@ -174,35 +179,35 @@ namespace NzbDrone.Core.Test.Datastore
{
var list = new List<string> { "first", "second", "third" };
_subject = Where(x => list.Contains(x.CleanTitle));
_subject = WhereMeta(x => list.Contains(x.CleanTitle));
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IN @Clause1_P1)");
}
[Test]
public void enum_as_int()
{
_subject = Where(x => x.Status == MovieStatusType.Announced);
_subject = WhereMeta(x => x.Status == MovieStatusType.Announced);
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = @Clause1_P1)");
}
[Test]
public void enum_in_list()
{
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" IN @Clause1_P1)");
}
[Test]
public void enum_in_array()
{
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas };
_subject = Where(x => allowed.Contains(x.Status));
_subject = WhereMeta(x => allowed.Contains(x.Status));
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @Clause1_P1)");
_subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" IN @Clause1_P1)");
}
}
}

View File

@ -53,7 +53,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[TestCase(60, 1000, false)]
public void single_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
{
_movie.Runtime = runtime;
_movie.MovieMetadata.Value.Runtime = runtime;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = sizeInMegaBytes.Megabytes();
@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_size_is_zero()
{
_movie.Runtime = 120;
_movie.MovieMetadata.Value.Runtime = 120;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 0;
_qualityType.MinSize = 10;
@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_unlimited_30_minute()
{
_movie.Runtime = 30;
_movie.MovieMetadata.Value.Runtime = 30;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 18457280000;
_qualityType.MaxSize = null;
@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_unlimited_60_minute()
{
_movie.Runtime = 60;
_movie.MovieMetadata.Value.Runtime = 60;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 36857280000;
_qualityType.MaxSize = null;
@ -97,7 +97,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_use_110_minutes_if_runtime_is_0()
{
_movie.Runtime = 0;
_movie.MovieMetadata.Value.Runtime = 0;
_remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 1095.Megabytes();

View File

@ -31,7 +31,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
Language = Language.English
},
OriginalLanguage = Language.French
MovieMetadata = new MovieMetadata
{
OriginalLanguage = Language.French
}
}
};
}

View File

@ -66,7 +66,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
MinFormatScore = 0
})
.With(m => m.Title = "A Movie")
.With(m => m.Runtime = runtime).Build();
.With(m => m.MovieMetadata.Value.Runtime = runtime).Build();
remoteMovie.Release = new ReleaseInfo();
remoteMovie.Release.PublishDate = DateTime.Now.AddDays(-age);

View File

@ -32,16 +32,16 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
{
movie = Builder<Movie>.CreateListOfSize(amount)
.All()
.With(v => v.Status = MovieStatusType.Released)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Released)
.BuildList();
}
else
{
movie = Builder<Movie>.CreateListOfSize(amount)
.All()
.With(v => v.Status = MovieStatusType.Released)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Released)
.Random(deleted)
.With(v => v.Status = MovieStatusType.Deleted)
.With(v => v.MovieMetadata.Value.Status = MovieStatusType.Deleted)
.BuildList();
}

View File

@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_alternative_title_items()
{
var altTitle = Builder<AlternativeTitle>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.BuildNew();
@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_alternative_title_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var altTitle = Builder<AlternativeTitle>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(altTitle);

View File

@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_credit_items()
{
var credit = Builder<Credit>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Name = "Some Credit")
.BuildNew();
@ -27,14 +27,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_credit_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var credit = Builder<Credit>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Name = "Some Credit")
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(credit);

View File

@ -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);
}
}
}

View File

@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_movie_translation_items()
{
var translation = Builder<MovieTranslation>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.BuildNew();
@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test]
public void should_not_delete_unorphaned_movie_translation_items()
{
var movie = Builder<Movie>.CreateNew().BuildNew();
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
Db.Insert(movie);
Db.Insert(movieMetadata);
var translation = Builder<MovieTranslation>.CreateNew()
.With(h => h.MovieId = default)
.With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English)
.With(b => b.MovieId = movie.Id)
.With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew();
Db.Insert(translation);

View File

@ -38,8 +38,8 @@ namespace NzbDrone.Core.Test.ImportListTests
.Build().ToList();
Mocker.GetMock<ISearchForNewMovie>()
.Setup(v => v.MapMovieToTmdbMovie(It.IsAny<Movie>()))
.Returns<Movie>(m => new Movie { TmdbId = m.TmdbId });
.Setup(v => v.MapMovieToTmdbMovie(It.IsAny<MovieMetadata>()))
.Returns<MovieMetadata>(m => new MovieMetadata { TmdbId = m.TmdbId });
}
private void GivenList(int id, bool enabled, bool enabledAuto, ImportListFetchResult fetchResult)

View File

@ -27,7 +27,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests
_movie = Builder<Movie>.CreateNew()
.With(v => v.Id = 2)
.With(v => v.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
.With(v => v.MovieMetadata.Value.Images = new List<MediaCover.MediaCover> { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") })
.Build();
Mocker.GetMock<IMovieService>().Setup(m => m.GetMovie(It.Is<int>(id => id == _movie.Id))).Returns(_movie);

View File

@ -255,7 +255,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(imported.Select(i => new ImportResult(i)).ToList());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);
@ -324,7 +324,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(imported.Select(i => new ImportResult(i)).ToList());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);
@ -431,7 +431,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(new List<ImportResult>());
Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(),
.Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>()))
.Returns(DetectSampleResult.Sample);

View File

@ -24,7 +24,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
.With(m => m.OriginalLanguage = Language.English)
.With(m => m.MovieMetadata.Value.OriginalLanguage = Language.English)
.Build();
_localMovie = Builder<LocalMovie>.CreateNew()
@ -72,7 +72,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators
{
var result = Subject.Aggregate(_localMovie, null, false);
result.Languages.Should().Contain(_movie.OriginalLanguage);
result.Languages.Should().Contain(_movie.MovieMetadata.Value.OriginalLanguage);
}
[Test]

View File

@ -16,20 +16,20 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
[TestFixture]
public class DetectSampleFixture : CoreTest<DetectSample>
{
private Movie _movie;
private MovieMetadata _movie;
private LocalMovie _localMovie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(s => s.Runtime = 30)
.Build();
_localMovie = new LocalMovie
{
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi",
Movie = _movie,
Movie = new Movie { MovieMetadata = _movie },
Quality = new QualityModel(Quality.HDTV720p)
};
}
@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
{
GivenRuntime(120);
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path);
Mocker.GetMock<IVideoFileInfoReader>().Verify(v => v.GetRunTime(It.IsAny<string>()), Times.Once());
@ -152,7 +152,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
.Setup(s => s.GetRunTime(It.IsAny<string>()))
.Returns((TimeSpan?)null);
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.Indeterminate);
ExceptionVerification.ExpectedErrors(1);
@ -160,13 +160,13 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
private void ShouldBeSample()
{
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.Sample);
}
private void ShouldBeNotSample()
{
Subject.IsSample(_localMovie.Movie,
Subject.IsSample(_localMovie.Movie.MovieMetadata,
_localMovie.Path).Should().Be(DetectSampleResult.NotSample);
}
}

View File

@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
details.Title.Should().Be(title);
}
private void ValidateMovie(Movie movie)
private void ValidateMovie(MovieMetadata movie)
{
movie.Should().NotBeNull();
movie.Title.Should().NotBeNullOrWhiteSpace();
@ -41,7 +41,6 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook
movie.ImdbId.Should().NotBeNullOrWhiteSpace();
movie.Studio.Should().NotBeNullOrWhiteSpace();
movie.Runtime.Should().BeGreaterThan(0);
movie.TitleSlug.Should().NotBeNullOrWhiteSpace();
//series.TvRageId.Should().BeGreaterThan(0);
movie.TmdbId.Should().BeGreaterThan(0);

View File

@ -20,14 +20,13 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class AddMovieFixture : CoreTest<AddMovieService>
{
private Movie _fakeMovie;
private MovieMetadata _fakeMovie;
[SetUp]
public void Setup()
{
_fakeMovie = Builder<Movie>
_fakeMovie = Builder<MovieMetadata>
.CreateNew()
.With(s => s.Path = null)
.Build();
}
@ -35,7 +34,7 @@ namespace NzbDrone.Core.Test.MovieTests
{
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(tmdbId))
.Returns(new Tuple<Movie, List<Credit>>(_fakeMovie, new List<Credit>()));
.Returns(new Tuple<MovieMetadata, List<Credit>>(_fakeMovie, new List<Credit>()));
}
private void GivenValidPath()

View File

@ -18,16 +18,17 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private AlternativeTitle _title2;
private AlternativeTitle _title3;
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
var titles = Builder<AlternativeTitle>.CreateListOfSize(3).All().With(t => t.MovieId = 0).Build();
var titles = Builder<AlternativeTitle>.CreateListOfSize(3).All().With(t => t.MovieMetadataId = 0).Build();
_title1 = titles[0];
_title2 = titles[1];
_title3 = titles[2];
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(m => m.CleanTitle = "myothertitle")
.With(m => m.Id = 1)
.Build();
@ -35,7 +36,7 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private void GivenExistingTitles(params AlternativeTitle[] titles)
{
Mocker.GetMock<IAlternativeTitleRepository>().Setup(r => r.FindByMovieId(_movie.Id))
Mocker.GetMock<IAlternativeTitleRepository>().Setup(r => r.FindByMovieMetadataId(_movie.Id))
.Returns(titles.ToList());
}
@ -72,7 +73,7 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
{
GivenExistingTitles();
var titles = new List<AlternativeTitle> { _title1 };
var movie = Builder<Movie>.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build();
var movie = Builder<MovieMetadata>.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build();
Subject.UpdateTitles(titles, movie);
@ -87,8 +88,8 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
Subject.UpdateTitles(titles, _movie);
_title1.MovieId.Should().Be(_movie.Id);
_title2.MovieId.Should().Be(_movie.Id);
_title1.MovieMetadataId.Should().Be(_movie.Id);
_title2.MovieMetadataId.Should().Be(_movie.Id);
}
[Test]

View File

@ -32,18 +32,18 @@ namespace NzbDrone.Core.Test.MovieTests.CreditTests
var credits = Builder<Credit>.CreateListOfSize(5)
.TheFirst(1)
.With(c => c.Id = 0)
.With(c => c.MovieId = _movie2.Id)
.With(c => c.MovieMetadataId = _movie2.Id)
.TheRest()
.With(c => c.Id = 0)
.With(c => c.MovieId = _movie1.Id)
.With(c => c.MovieMetadataId = _movie1.Id)
.BuildListOfNew();
Db.InsertMany(credits);
Subject.DeleteForMovies(new List<int> { _movie1.Id });
var removedMovieCredits = Subject.FindByMovieId(_movie1.Id);
var nonRemovedMovieCredits = Subject.FindByMovieId(_movie2.Id);
var removedMovieCredits = Subject.FindByMovieMetadataId(_movie1.Id);
var nonRemovedMovieCredits = Subject.FindByMovieMetadataId(_movie2.Id);
removedMovieCredits.Should().HaveCount(0);
nonRemovedMovieCredits.Should().HaveCount(1);

View File

@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
@ -18,25 +18,25 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
private Credit _credit2;
private Credit _credit3;
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
var credits = Builder<Credit>.CreateListOfSize(3)
.All()
.With(t => t.MovieId = 0).Build();
.With(t => t.MovieMetadataId = 0).Build();
_credit1 = credits[0];
_credit2 = credits[1];
_credit3 = credits[2];
_movie = Builder<Movie>.CreateNew().With(m => m.Id = 1).Build();
_movie = Builder<MovieMetadata>.CreateNew().With(m => m.Id = 1).Build();
}
private void GivenExistingCredits(params Credit[] credits)
{
Mocker.GetMock<ICreditRepository>().Setup(r => r.FindByMovieId(_movie.Id))
Mocker.GetMock<ICreditRepository>().Setup(r => r.FindByMovieMetadataId(_movie.Id))
.Returns(credits.ToList());
}
@ -77,8 +77,8 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
Subject.UpdateCredits(titles, _movie);
_credit1.MovieId.Should().Be(_movie.Id);
_credit2.MovieId.Should().Be(_movie.Id);
_credit1.MovieMetadataId.Should().Be(_movie.Id);
_credit2.MovieMetadataId.Should().Be(_movie.Id);
}
[Test]

View File

@ -21,9 +21,9 @@ namespace NzbDrone.Core.Test.MovieTests
private void SetMovieProperties(DateTime? cinema, DateTime? physical, DateTime? digital, MovieStatusType minimumAvailability)
{
_movie.InCinemas = cinema;
_movie.PhysicalRelease = physical;
_movie.DigitalRelease = digital;
_movie.MovieMetadata.Value.InCinemas = cinema;
_movie.MovieMetadata.Value.PhysicalRelease = physical;
_movie.MovieMetadata.Value.DigitalRelease = digital;
_movie.MinimumAvailability = minimumAvailability;
}

View File

@ -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);
}
}
}

View File

@ -19,15 +19,15 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
{
_candidates = Builder<Movie>.CreateListOfSize(3)
.TheFirst(1)
.With(x => x.CleanTitle = "batman")
.With(x => x.MovieMetadata.Value.CleanTitle = "batman")
.With(x => x.Year = 2000)
.TheNext(1)
.With(x => x.CleanTitle = "batman")
.With(x => x.MovieMetadata.Value.CleanTitle = "batman")
.With(x => x.Year = 1999)
.TheRest()
.With(x => x.CleanTitle = "darkknight")
.With(x => x.MovieMetadata.Value.CleanTitle = "darkknight")
.With(x => x.Year = 2008)
.With(x => x.AlternativeTitles = new List<AlternativeTitle>
.With(x => x.MovieMetadata.Value.AlternativeTitles = new List<AlternativeTitle>
{
new AlternativeTitle
{

View File

@ -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();
}
}
}

View File

@ -18,17 +18,26 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class RefreshMovieServiceFixture : CoreTest<RefreshMovieService>
{
private Movie _movie;
private MovieMetadata _movie;
private Movie _existingMovie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(s => s.Status = MovieStatusType.Released)
.Build();
_existingMovie = Builder<Movie>.CreateNew()
.With(s => s.MovieMetadata.Value.Status = MovieStatusType.Released)
.Build();
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovie(_movie.Id))
.Returns(_existingMovie);
Mocker.GetMock<IMovieMetadataService>()
.Setup(s => s.Get(_movie.Id))
.Returns(_movie);
Mocker.GetMock<IProvideMovieInfo>()
@ -36,11 +45,11 @@ namespace NzbDrone.Core.Test.MovieTests
.Callback<int>((i) => { throw new MovieNotFoundException(i); });
}
private void GivenNewMovieInfo(Movie movie)
private void GivenNewMovieInfo(MovieMetadata movie)
{
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(_movie.TmdbId))
.Returns(new Tuple<Movie, List<Credit>>(movie, new List<Credit>()));
.Returns(new Tuple<MovieMetadata, List<Credit>>(movie, new List<Credit>()));
}
[Test]
@ -53,8 +62,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.First().ImdbId == newMovieInfo.ImdbId), true));
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.ImdbId == newMovieInfo.ImdbId)));
}
[Test]
@ -62,8 +71,8 @@ namespace NzbDrone.Core.Test.MovieTests
{
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<Movie>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
ExceptionVerification.ExpectedErrors(1);
}
@ -78,8 +87,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.First().TmdbId == newMovieInfo.TmdbId), true));
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.TmdbId == newMovieInfo.TmdbId)));
ExceptionVerification.ExpectedWarns(1);
}
@ -89,8 +98,8 @@ namespace NzbDrone.Core.Test.MovieTests
{
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.Is<Movie>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
ExceptionVerification.ExpectedErrors(1);
}
@ -102,8 +111,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>()
.Verify(v => v.UpdateMovie(It.IsAny<Movie>()), Times.Never());
Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.Upsert(It.IsAny<MovieMetadata>()), Times.Never());
ExceptionVerification.ExpectedErrors(1);
}

View File

@ -10,12 +10,12 @@ namespace NzbDrone.Core.Test.MovieTests
[TestFixture]
public class ShouldRefreshMovieFixture : TestBase<ShouldRefreshMovie>
{
private Movie _movie;
private MovieMetadata _movie;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
_movie = Builder<MovieMetadata>.CreateNew()
.With(v => v.Status = MovieStatusType.InCinemas)
.With(m => m.PhysicalRelease = DateTime.Today.AddDays(-100))
.Build();

View File

@ -50,7 +50,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
_movie = Builder<Movie>
.CreateNew()
.With(s => s.Title = "South Park")
.With(s => s.OriginalTitle = "South of the Park")
.With(s => s.MovieMetadata.Value.OriginalTitle = "South of the Park")
.Build();
_namingConfig = NamingConfig.Default;
@ -206,7 +206,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_original_title()
{
_namingConfig.StandardMovieFormat = "{Movie OriginalTitle}";
_movie.OriginalTitle = "South of the Park";
_movie.MovieMetadata.Value.OriginalTitle = "South of the Park";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("South of the Park");
@ -216,7 +216,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_certification()
{
_namingConfig.StandardMovieFormat = "{Movie Certification}";
_movie.Certification = "R";
_movie.MovieMetadata.Value.Certification = "R";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("R");
@ -226,7 +226,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
public void should_replace_movie_collection()
{
_namingConfig.StandardMovieFormat = "{Movie Collection}";
_movie.Collection = new MovieCollection { Name = "South Part Collection" };
_movie.MovieMetadata.Value.Collection = new MovieCollection { Name = "South Part Collection" };
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("South Part Collection");

View File

@ -16,7 +16,10 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
var releaseInfo = new ParsedMovieInfo();
var movie = new Movies.Movie
{
OriginalLanguage = Language.English
MovieMetadata = new Movies.MovieMetadata
{
OriginalLanguage = Language.English
}
};
var result = Subject.AugmentMovieInfo(releaseInfo, movie);
result.ExtraInfo.Should().ContainKey("OriginalLanguage");

View File

@ -36,11 +36,11 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
{
_movie = Builder<Movie>.CreateNew()
.With(m => m.Title = "Fack Ju Göthe 2")
.With(m => m.CleanTitle = "fackjugoethe2")
.With(m => m.MovieMetadata.Value.CleanTitle = "fackjugoethe2")
.With(m => m.Year = 2015)
.With(m => m.AlternativeTitles = new List<AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })
.With(m => m.Translations = new List<MovieTranslation> { new MovieTranslation { Title = "Translated Title", CleanTitle = "translatedtitle" } })
.With(m => m.OriginalLanguage = Language.English)
.With(m => m.MovieMetadata.Value.AlternativeTitles = new List<AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })
.With(m => m.MovieMetadata.Value.Translations = new List<MovieTranslation> { new MovieTranslation { Title = "Translated Title", CleanTitle = "translatedtitle" } })
.With(m => m.MovieMetadata.Value.OriginalLanguage = Language.English)
.Build();
_parsedMovieInfo = new ParsedMovieInfo
@ -66,14 +66,14 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
_alternativeTitleInfo = new ParsedMovieInfo
{
MovieTitles = new List<string> { _movie.AlternativeTitles.First().Title },
MovieTitles = new List<string> { _movie.MovieMetadata.Value.AlternativeTitles.First().Title },
Languages = new List<Language> { Language.English },
Year = _movie.Year,
};
_translationTitleInfo = new ParsedMovieInfo
{
MovieTitles = new List<string> { _movie.Translations.First().Title },
MovieTitles = new List<string> { _movie.MovieMetadata.Value.Translations.First().Title },
Languages = new List<Language> { Language.English },
Year = _movie.Year,
};

View File

@ -76,20 +76,20 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movieFile.Movie.Title },
MovieTitles = new List<string>() { movieFile.Movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = sceneName.SimplifyReleaseTitle(),
Quality = movieFile.Quality,
Languages = movieFile.Languages,
ReleaseGroup = movieFile.ReleaseGroup,
Edition = movieFile.Edition,
Year = movieFile.Movie.Year,
ImdbId = movieFile.Movie.ImdbId,
Year = movieFile.Movie.MovieMetadata.Value.Year,
ImdbId = movieFile.Movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", movieFile.IndexerFlags },
{ "Size", movieFile.Size },
{ "Filename", Path.GetFileName(movieFile.RelativePath) },
{ "OriginalLanguage", movieFile.Movie.OriginalLanguage }
{ "OriginalLanguage", movieFile.Movie.MovieMetadata.Value.OriginalLanguage }
}
};
@ -114,14 +114,14 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.Title },
MovieTitles = new List<string>() { movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? blocklist.SourceTitle.SimplifyReleaseTitle(),
Quality = blocklist.Quality,
Languages = blocklist.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
Edition = parsed?.Edition,
Year = movie.Year,
ImdbId = movie.ImdbId,
Year = movie.MovieMetadata.Value.Year,
ImdbId = movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", blocklist.IndexerFlags },
@ -142,14 +142,14 @@ namespace NzbDrone.Core.CustomFormats
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.Title },
MovieTitles = new List<string>() { movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? history.SourceTitle.SimplifyReleaseTitle(),
Quality = history.Quality,
Languages = history.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
Edition = parsed?.Edition,
Year = movie.Year,
ImdbId = movie.ImdbId,
Year = movie.MovieMetadata.Value.Year,
ImdbId = movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", flags },

View File

@ -47,13 +47,6 @@ namespace NzbDrone.Core.Datastore
return builder.Where(wb.ToString(), wb.Parameters);
}
public static SqlBuilder WherePostgres<TModel>(this SqlBuilder builder, Expression<Func<TModel, bool>> filter)
{
var wb = new WhereBuilderPostgres(filter, true, builder.Sequence);
return builder.Where(wb.ToString(), wb.Parameters);
}
public static SqlBuilder OrWhere<TModel>(this SqlBuilder builder, Expression<Func<TModel, bool>> filter)
{
var wb = GetWhereBuilder(builder.DatabaseType, filter, true, builder.Sequence);

View File

@ -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");
}
}
}

View File

@ -109,9 +109,18 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<Movie>("Movies").RegisterModel()
.Ignore(s => s.RootFolderPath)
.Ignore(s => s.Translations);
.Ignore(s => s.Title)
.Ignore(s => s.Year)
.Ignore(s => s.TmdbId)
.Ignore(s => s.ImdbId)
.HasOne(a => a.MovieMetadata, a => a.MovieMetadataId);
Mapper.Entity<ImportListMovie>("ImportListMovies").RegisterModel();
Mapper.Entity<ImportListMovie>("ImportListMovies").RegisterModel()
.Ignore(s => s.Title)
.Ignore(s => s.Year)
.Ignore(s => s.TmdbId)
.Ignore(s => s.ImdbId)
.HasOne(a => a.MovieMetadata, a => a.MovieMetadataId);
Mapper.Entity<AlternativeTitle>("AlternativeTitles").RegisterModel();
@ -156,6 +165,9 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<DownloadHistory>("DownloadHistory").RegisterModel();
Mapper.Entity<UpdateHistory>("UpdateHistory").RegisterModel();
Mapper.Entity<MovieMetadata>("MovieMetadata").RegisterModel()
.Ignore(s => s.Translations);
}
private static void RegisterMappers()

View File

@ -174,9 +174,9 @@ namespace NzbDrone.Core.DecisionEngine
var preferredSize = _qualityDefinitionService.Get(remoteMovie.ParsedMovieInfo.Quality.Quality).PreferredSize;
// If no value for preferred it means unlimited so fallback to sort largest is best
if (preferredSize.HasValue && remoteMovie.Movie.Runtime > 0)
if (preferredSize.HasValue && remoteMovie.Movie.MovieMetadata.Value.Runtime > 0)
{
var preferredMovieSize = remoteMovie.Movie.Runtime * preferredSize.Value.Megabytes();
var preferredMovieSize = remoteMovie.Movie.MovieMetadata.Value.Runtime * preferredSize.Value.Megabytes();
// Calculate closest to the preferred size
return Math.Abs((remoteMovie.Release.Size - preferredMovieSize).Round(200.Megabytes())) * (-1);

View File

@ -34,10 +34,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
var qualityDefinition = _qualityDefinitionService.Get(quality);
if (subject.Movie.Runtime == 0)
if (subject.Movie.MovieMetadata.Value.Runtime == 0)
{
_logger.Warn("{0} has no runtime information using median movie runtime of 110 minutes.", subject.Movie);
subject.Movie.Runtime = 110;
subject.Movie.MovieMetadata.Value.Runtime = 110;
}
if (qualityDefinition.MinSize.HasValue)
@ -45,7 +45,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
var minSize = qualityDefinition.MinSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime
minSize = minSize * subject.Movie.Runtime;
minSize = minSize * subject.Movie.MovieMetadata.Value.Runtime;
//If the parsed size is smaller than minSize we don't want it
if (subject.Release.Size < minSize)
@ -61,7 +61,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{
_logger.Debug("Max size is unlimited, skipping check");
}
else if (subject.Movie.Runtime == 0)
else if (subject.Movie.MovieMetadata.Value.Runtime == 0)
{
_logger.Debug("Movie runtime is 0, unable to validate size until it is available, rejecting");
return Decision.Reject("Movie runtime is 0, unable to validate size until it is available");
@ -71,7 +71,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
var maxSize = qualityDefinition.MaxSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime
maxSize = maxSize * subject.Movie.Runtime;
maxSize = maxSize * subject.Movie.MovieMetadata.Value.Runtime;
//If the parsed size is greater than maxSize we don't want it
if (subject.Release.Size > maxSize)

View File

@ -27,7 +27,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
return Decision.Accept();
}
var originalLanguage = subject.Movie.OriginalLanguage;
var originalLanguage = subject.Movie.MovieMetadata.Value.OriginalLanguage;
if (wantedLanguage == Language.Original)
{

View File

@ -68,7 +68,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
_proxy.SetTorrentLabel(actualHash, Settings.MovieCategory, Settings);
}
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)DelugePriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)DelugePriority.First))
@ -95,7 +95,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
_proxy.SetTorrentLabel(actualHash, Settings.MovieCategory, Settings);
}
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)DelugePriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)DelugePriority.First))

View File

@ -52,7 +52,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
switch (additionalTag)
{
case (int)AdditionalTags.Collection:
result.Add(remoteMovie.Movie.Collection.Name);
result.Add(remoteMovie.Movie.MovieMetadata.Value.Collection.Name);
break;
case (int)AdditionalTags.Quality:
result.Add(remoteMovie.ParsedMovieInfo.Quality.Quality.ToString());
@ -70,7 +70,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
result.Add(remoteMovie.Release.Indexer);
break;
case (int)AdditionalTags.Studio:
result.Add(remoteMovie.Movie.Studio);
result.Add(remoteMovie.Movie.MovieMetadata.Value.Studio);
break;
default:
throw new DownloadClientException("Unexpected additional tag ID");

View File

@ -34,7 +34,7 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents)
{
var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var response = _proxy.DownloadNzb(fileContents, filename, priority, Settings);

View File

@ -40,7 +40,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{
var category = Settings.MovieCategory;
var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var addpaused = Settings.AddPaused;
var response = _proxy.DownloadNzb(fileContent, filename, category, priority, addpaused, Settings);

View File

@ -73,7 +73,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
var setShareLimits = remoteMovie.SeedConfiguration != null && (remoteMovie.SeedConfiguration.Ratio.HasValue || remoteMovie.SeedConfiguration.SeedTime.HasValue);
var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1);
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
var moveToTop = (isRecentMovie && Settings.RecentMoviePriority == (int)QBittorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)QBittorrentPriority.First);
var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart;
@ -132,7 +132,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
{
var setShareLimits = remoteMovie.SeedConfiguration != null && (remoteMovie.SeedConfiguration.Ratio.HasValue || remoteMovie.SeedConfiguration.SeedTime.HasValue);
var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1);
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
var moveToTop = (isRecentMovie && Settings.RecentMoviePriority == (int)QBittorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)QBittorrentPriority.First);
var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart;

View File

@ -40,7 +40,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContent)
{
var category = Settings.MovieCategory;
var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority;
var response = _proxy.DownloadNzb(fileContent, filename, category, priority, Settings);

View File

@ -194,7 +194,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteMovie.SeedConfiguration, Settings);
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)TransmissionPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)TransmissionPriority.First))
@ -210,7 +210,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteMovie.SeedConfiguration, Settings);
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)TransmissionPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)TransmissionPriority.First))

View File

@ -72,7 +72,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
var priority = (RTorrentPriority)(remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority);
var priority = (RTorrentPriority)(remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority);
_proxy.AddTorrentFromUrl(magnetLink, Settings.MovieCategory, priority, Settings.MovieDirectory, Settings);
@ -92,7 +92,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
{
var priority = (RTorrentPriority)(remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority);
var priority = (RTorrentPriority)(remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority);
_proxy.AddTorrentFromFile(filename, fileContent, Settings.MovieCategory, priority, Settings.MovieDirectory, Settings);

View File

@ -64,7 +64,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
}
var isRecentMovie = remoteMovie.Movie.IsRecentMovie;
var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentMovie && Settings.RecentMoviePriority == (int)UTorrentPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)UTorrentPriority.First))
@ -87,7 +87,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
}
var isRecentEpisode = remoteMovie.Movie.IsRecentMovie;
var isRecentEpisode = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie;
if ((isRecentEpisode && Settings.RecentMoviePriority == (int)UTorrentPriority.First) ||
(!isRecentEpisode && Settings.OlderMoviePriority == (int)UTorrentPriority.First))

View File

@ -67,19 +67,19 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.MediaBrowser
{
var movieElement = new XElement("Movie");
movieElement.Add(new XElement("id", movie.ImdbId));
movieElement.Add(new XElement("Status", movie.Status));
movieElement.Add(new XElement("id", movie.MovieMetadata.Value.ImdbId));
movieElement.Add(new XElement("Status", movie.MovieMetadata.Value.Status));
movieElement.Add(new XElement("Added", movie.Added.ToString("MM/dd/yyyy HH:mm:ss tt")));
movieElement.Add(new XElement("LockData", "false"));
movieElement.Add(new XElement("Overview", movie.Overview));
movieElement.Add(new XElement("Overview", movie.MovieMetadata.Value.Overview));
movieElement.Add(new XElement("LocalTitle", movie.Title));
movieElement.Add(new XElement("Rating", movie.Ratings.Tmdb?.Value ?? 0));
movieElement.Add(new XElement("Rating", movie.MovieMetadata.Value.Ratings.Tmdb?.Value ?? 0));
movieElement.Add(new XElement("ProductionYear", movie.Year));
movieElement.Add(new XElement("RunningTime", movie.Runtime));
movieElement.Add(new XElement("IMDB", movie.ImdbId));
movieElement.Add(new XElement("Genres", movie.Genres.Select(genre => new XElement("Genre", genre))));
movieElement.Add(new XElement("RunningTime", movie.MovieMetadata.Value.Runtime));
movieElement.Add(new XElement("IMDB", movie.MovieMetadata.Value.ImdbId));
movieElement.Add(new XElement("Genres", movie.MovieMetadata.Value.Genres.Select(genre => new XElement("Genre", genre))));
var doc = new XDocument(movieElement);
doc.Save(xw);

View File

@ -118,9 +118,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox
var details = new XElement("video");
details.Add(new XElement("title", movie.Title));
details.Add(new XElement("genre", string.Join(" / ", movie.Genres)));
details.Add(new XElement("description", movie.Overview));
details.Add(new XElement("length", movie.Runtime));
details.Add(new XElement("genre", string.Join(" / ", movie.MovieMetadata.Value.Genres)));
details.Add(new XElement("description", movie.MovieMetadata.Value.Overview));
details.Add(new XElement("length", movie.MovieMetadata.Value.Runtime));
doc.Add(details);
doc.Save(xw);
@ -139,7 +139,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox
return new List<ImageFileResult>();
}
var image = movie.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.Images.FirstOrDefault();
var image = movie.MovieMetadata.Value.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.MovieMetadata.Value.Images.FirstOrDefault();
if (image == null)
{
_logger.Trace("Failed to find suitable Movie image for movie {0}.", movie.Title);

View File

@ -113,8 +113,8 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Wdtv
var details = new XElement("details");
details.Add(new XElement("id", movie.Id));
details.Add(new XElement("title", movie.Title));
details.Add(new XElement("genre", string.Join(" / ", movie.Genres)));
details.Add(new XElement("overview", movie.Overview));
details.Add(new XElement("genre", string.Join(" / ", movie.MovieMetadata.Value.Genres)));
details.Add(new XElement("overview", movie.MovieMetadata.Value.Overview));
doc.Add(details);
doc.Save(xw);
@ -136,7 +136,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Wdtv
}
//Because we only support one image, attempt to get the Poster type, then if that fails grab the first
var image = movie.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.Images.FirstOrDefault();
var image = movie.MovieMetadata.Value.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.MovieMetadata.Value.Images.FirstOrDefault();
if (image == null)
{
_logger.Trace("Failed to find suitable Movie image for movie {0}.", movie.Title);

View File

@ -123,14 +123,14 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
_logger.Debug("Generating Movie Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath));
var movieMetadataLanguage = (Settings.MovieMetadataLanguage == (int)Language.Original) ?
(int)movie.OriginalLanguage :
(int)movie.MovieMetadata.Value.OriginalLanguage :
Settings.MovieMetadataLanguage;
var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovie(movie.Id);
var selectedSettingsLanguage = Language.FindById(movieMetadataLanguage);
var movieTranslation = movieTranslations.FirstOrDefault(mt => mt.Language == selectedSettingsLanguage);
var credits = _creditService.GetAllCreditsForMovie(movie.Id);
var credits = _creditService.GetAllCreditsForMovie(movie.MovieMetadataId);
var watched = GetExistingWatchedStatus(movie, movieFile.RelativePath);
@ -142,44 +142,44 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
using (var xw = XmlWriter.Create(sb, xws))
{
var doc = new XDocument();
var thumbnail = movie.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot);
var posters = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Poster);
var fanarts = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart);
var thumbnail = movie.MovieMetadata.Value.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot);
var posters = movie.MovieMetadata.Value.Images.Where(i => i.CoverType == MediaCoverTypes.Poster);
var fanarts = movie.MovieMetadata.Value.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart);
var details = new XElement("movie");
details.Add(new XElement("title", movieTranslation?.Title ?? movie.Title));
details.Add(new XElement("originaltitle", movie.OriginalTitle));
details.Add(new XElement("originaltitle", movie.MovieMetadata.Value.OriginalTitle));
details.Add(new XElement("sorttitle", movie.SortTitle));
details.Add(new XElement("sorttitle", movie.MovieMetadata.Value.SortTitle));
if (movie.Ratings.Tmdb?.Votes > 0 || movie.Ratings.Imdb?.Votes > 0)
if (movie.MovieMetadata.Value.Ratings.Tmdb?.Votes > 0 || movie.MovieMetadata.Value.Ratings.Imdb?.Votes > 0)
{
var setRating = new XElement("ratings");
if (movie.Ratings.Tmdb?.Votes > 0)
if (movie.MovieMetadata.Value.Ratings.Tmdb?.Votes > 0)
{
var setRatethemoviedb = new XElement("rating", new XAttribute("name", "themoviedb"), new XAttribute("max", "10"), new XAttribute("default", "true"));
setRatethemoviedb.Add(new XElement("value", movie.Ratings.Tmdb.Value));
setRatethemoviedb.Add(new XElement("votes", movie.Ratings.Tmdb.Votes));
setRatethemoviedb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Tmdb.Value));
setRatethemoviedb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Tmdb.Votes));
setRating.Add(setRatethemoviedb);
}
if (movie.Ratings.Imdb?.Votes > 0)
if (movie.MovieMetadata.Value.Ratings.Imdb?.Votes > 0)
{
var setRateImdb = new XElement("rating", new XAttribute("name", "imdb"), new XAttribute("max", "10"));
setRateImdb.Add(new XElement("value", movie.Ratings.Imdb.Value));
setRateImdb.Add(new XElement("votes", movie.Ratings.Imdb.Votes));
setRateImdb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Imdb.Value));
setRateImdb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Imdb.Votes));
setRating.Add(setRateImdb);
}
details.Add(setRating);
}
if (movie.Ratings?.Tmdb?.Votes > 0)
if (movie.MovieMetadata.Value.Ratings?.Tmdb?.Votes > 0)
{
details.Add(new XElement("rating", movie.Ratings.Tmdb.Value));
details.Add(new XElement("rating", movie.MovieMetadata.Value.Ratings.Tmdb.Value));
}
details.Add(new XElement("userrating"));
@ -188,11 +188,11 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
details.Add(new XElement("outline"));
details.Add(new XElement("plot", movieTranslation?.Overview ?? movie.Overview));
details.Add(new XElement("plot", movieTranslation?.Overview ?? movie.MovieMetadata.Value.Overview));
details.Add(new XElement("tagline"));
details.Add(new XElement("runtime", movie.Runtime));
details.Add(new XElement("runtime", movie.MovieMetadata.Value.Runtime));
if (thumbnail != null)
{
@ -221,9 +221,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
details.Add(fanartElement);
}
if (movie.Certification.IsNotNullOrWhiteSpace())
if (movie.MovieMetadata.Value.Certification.IsNotNullOrWhiteSpace())
{
details.Add(new XElement("mpaa", movie.Certification));
details.Add(new XElement("mpaa", movie.MovieMetadata.Value.Certification));
}
details.Add(new XElement("playcount"));
@ -237,25 +237,25 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
uniqueId.SetAttributeValue("default", true);
details.Add(uniqueId);
if (movie.ImdbId.IsNotNullOrWhiteSpace())
if (movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace())
{
var imdbId = new XElement("uniqueid", movie.ImdbId);
var imdbId = new XElement("uniqueid", movie.MovieMetadata.Value.ImdbId);
imdbId.SetAttributeValue("type", "imdb");
details.Add(imdbId);
}
foreach (var genre in movie.Genres)
foreach (var genre in movie.MovieMetadata.Value.Genres)
{
details.Add(new XElement("genre", genre));
}
details.Add(new XElement("country"));
if (movie.Collection?.Name != null)
if (movie.MovieMetadata.Value.Collection?.Name != null)
{
var setElement = new XElement("set");
setElement.Add(new XElement("name", movie.Collection.Name));
setElement.Add(new XElement("name", movie.MovieMetadata.Value.Collection.Name));
setElement.Add(new XElement("overview"));
details.Add(setElement);
@ -284,16 +284,16 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
}
}
if (movie.InCinemas.HasValue)
if (movie.MovieMetadata.Value.InCinemas.HasValue)
{
details.Add(new XElement("premiered", movie.InCinemas.Value.ToString("yyyy-MM-dd")));
details.Add(new XElement("premiered", movie.MovieMetadata.Value.InCinemas.Value.ToString("yyyy-MM-dd")));
}
details.Add(new XElement("year", movie.Year));
details.Add(new XElement("studio", movie.Studio));
details.Add(new XElement("studio", movie.MovieMetadata.Value.Studio));
details.Add(new XElement("trailer", "plugin://plugin.video.youtube/play/?video_id=" + movie.YouTubeTrailerId));
details.Add(new XElement("trailer", "plugin://plugin.video.youtube/play/?video_id=" + movie.MovieMetadata.Value.YouTubeTrailerId));
if (movieFile.MediaInfo != null)
{
@ -369,10 +369,10 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
if (Settings.MovieMetadataURL)
{
xmlResult += "https://www.themoviedb.org/movie/" + movie.TmdbId;
xmlResult += "https://www.themoviedb.org/movie/" + movie.MovieMetadata.Value.TmdbId;
xmlResult += Environment.NewLine;
xmlResult += "https://www.imdb.com/title/" + movie.ImdbId;
xmlResult += "https://www.imdb.com/title/" + movie.MovieMetadata.Value.ImdbId;
xmlResult += Environment.NewLine;
}
@ -393,7 +393,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
private IEnumerable<ImageFileResult> ProcessMovieImages(Movie movie)
{
foreach (var image in movie.Images)
foreach (var image in movie.MovieMetadata.Value.Images)
{
var source = _mediaCoverService.GetCoverPath(movie.Id, image.CoverType);
var destination = image.CoverType.ToString().ToLowerInvariant() + Path.GetExtension(source);

View File

@ -21,7 +21,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
public override HealthCheck Check()
{
var deletedMovie = _movieService.GetAllMovies().Where(v => v.Status == MovieStatusType.Deleted).ToList();
var deletedMovie = _movieService.GetAllMovies().Where(v => v.MovieMetadata.Value.Status == MovieStatusType.Deleted).ToList();
if (deletedMovie.Empty())
{
@ -40,12 +40,12 @@ namespace NzbDrone.Core.HealthCheck.Checks
public bool ShouldCheckOnEvent(MoviesDeletedEvent message)
{
return message.Movies.Any(m => m.Status == MovieStatusType.Deleted);
return message.Movies.Any(m => m.MovieMetadata.Value.Status == MovieStatusType.Deleted);
}
public bool ShouldCheckOnEvent(MovieUpdatedEvent message)
{
return message.Movie.Status == MovieStatusType.Deleted;
return message.Movie.MovieMetadata.Value.Status == MovieStatusType.Deleted;
}
}
}

View File

@ -1,4 +1,4 @@
using Dapper;
using Dapper;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Housekeeping.Housekeepers
@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
mapper.Execute(@"DELETE FROM ""AlternativeTitles""
WHERE ""Id"" IN (
SELECT ""AlternativeTitles"".""Id"" FROM ""AlternativeTitles""
LEFT OUTER JOIN ""Movies""
ON ""AlternativeTitles"".""MovieId"" = ""Movies"".""Id""
WHERE ""Movies"".""Id"" IS NULL)");
LEFT OUTER JOIN ""MovieMetadata""
ON ""AlternativeTitles"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""MovieMetadata"".""Id"" IS NULL)");
}
}
}

View File

@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
mapper.Execute(@"DELETE FROM ""Credits""
WHERE ""Id"" IN (
SELECT ""Credits"".""Id"" FROM ""Credits""
LEFT OUTER JOIN ""Movies""
ON ""Credits"".""MovieId"" = ""Movies"".""Id""
WHERE ""Movies"".""Id"" IS NULL)");
LEFT OUTER JOIN ""MovieMetadata""
ON ""Credits"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""MovieMetadata"".""Id"" IS NULL)");
}
}
}

View File

@ -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)");
}
}
}
}

View File

@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
mapper.Execute(@"DELETE FROM ""MovieTranslations""
WHERE ""Id"" IN (
SELECT ""MovieTranslations"".""Id"" FROM ""MovieTranslations""
LEFT OUTER JOIN ""Movies""
ON ""MovieTranslations"".""MovieId"" = ""Movies"".""Id""
WHERE ""Movies"".""Id"" IS NULL)");
LEFT OUTER JOIN ""MovieMetadata""
ON ""MovieTranslations"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""MovieMetadata"".""Id"" IS NULL)");
}
}
}

View File

@ -24,18 +24,21 @@ namespace NzbDrone.Core.ImportLists
private readonly IImportListStatusService _importListStatusService;
private readonly IImportListMovieService _listMovieService;
private readonly ISearchForNewMovie _movieSearch;
private readonly IMovieMetadataService _movieMetadataService;
private readonly Logger _logger;
public FetchAndParseImportListService(IImportListFactory importListFactory,
IImportListStatusService importListStatusService,
IImportListMovieService listMovieService,
ISearchForNewMovie movieSearch,
IMovieMetadataService movieMetadataService,
Logger logger)
{
_importListFactory = importListFactory;
_importListStatusService = importListStatusService;
_listMovieService = listMovieService;
_movieSearch = movieSearch;
_movieMetadataService = movieMetadataService;
_logger = logger;
}
@ -173,33 +176,16 @@ namespace NzbDrone.Core.ImportLists
private ImportListMovie MapMovieReport(ImportListMovie report)
{
var mappedMovie = _movieSearch.MapMovieToTmdbMovie(new Movie { Title = report.Title, TmdbId = report.TmdbId, ImdbId = report.ImdbId, Year = report.Year });
var mappedMovie = _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = report.Title, TmdbId = report.TmdbId, ImdbId = report.ImdbId, Year = report.Year });
_movieMetadataService.Upsert(mappedMovie);
var mappedListMovie = new ImportListMovie { ListId = report.ListId };
if (mappedMovie != null)
{
mappedListMovie.TmdbId = mappedMovie.TmdbId;
mappedListMovie.ImdbId = mappedMovie.ImdbId;
mappedListMovie.Title = mappedMovie.Title;
mappedListMovie.SortTitle = mappedMovie?.SortTitle;
mappedListMovie.Year = mappedMovie.Year;
mappedListMovie.Overview = mappedMovie.Overview;
mappedListMovie.Ratings = mappedMovie.Ratings;
mappedListMovie.Studio = mappedMovie.Studio;
mappedListMovie.Certification = mappedMovie.Certification;
mappedListMovie.Collection = mappedMovie.Collection;
mappedListMovie.Status = mappedMovie.Status;
mappedListMovie.Images = mappedMovie.Images;
mappedListMovie.Website = mappedMovie.Website;
mappedListMovie.YouTubeTrailerId = mappedMovie.YouTubeTrailerId;
mappedListMovie.Translations = mappedMovie.Translations;
mappedListMovie.InCinemas = mappedMovie.InCinemas;
mappedListMovie.PhysicalRelease = mappedMovie.PhysicalRelease;
mappedListMovie.DigitalRelease = mappedMovie.DigitalRelease;
mappedListMovie.Genres = mappedMovie.Genres;
mappedListMovie.Runtime = mappedMovie.Runtime;
mappedListMovie.OriginalTitle = mappedMovie.OriginalTitle;
mappedListMovie.MovieMetadata = mappedMovie;
mappedListMovie.MovieMetadataId = mappedMovie.Id;
}
return mappedListMovie;

View File

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Translations;
namespace NzbDrone.Core.ImportLists.ImportListMovies
{
@ -10,37 +7,35 @@ namespace NzbDrone.Core.ImportLists.ImportListMovies
{
public ImportListMovie()
{
Images = new List<MediaCover.MediaCover>();
Genres = new List<string>();
Translations = new List<MovieTranslation>();
Ratings = new Ratings();
MovieMetadata = new MovieMetadata();
}
public int TmdbId { get; set; }
public string ImdbId { get; set; }
public string Title { get; set; }
public string SortTitle { get; set; }
public MovieStatusType Status { get; set; }
public string Overview { get; set; }
public DateTime? LastInfoSync { get; set; }
public int Runtime { get; set; }
public List<MediaCover.MediaCover> Images { get; set; }
public string Website { get; set; }
public int Year { get; set; }
public Ratings Ratings { get; set; }
public List<string> Genres { get; set; }
public MovieCollection Collection { get; set; }
public string Certification { get; set; }
public DateTime? InCinemas { get; set; }
public DateTime? PhysicalRelease { get; set; }
public DateTime? DigitalRelease { get; set; }
public List<MovieTranslation> Translations { get; set; }
public string YouTubeTrailerId { get; set; }
public string Studio { get; set; }
public string OriginalTitle { get; set; }
public int ListId { get; set; }
public int MovieMetadataId { get; set; }
public LazyLoaded<MovieMetadata> MovieMetadata { get; set; }
public string Title
{
get { return MovieMetadata.Value.Title; }
set { MovieMetadata.Value.Title = value; }
}
public int TmdbId
{
get { return MovieMetadata.Value.TmdbId; }
set { MovieMetadata.Value.TmdbId = value; }
}
public string ImdbId
{
get { return MovieMetadata.Value.ImdbId; }
set { MovieMetadata.Value.ImdbId = value; }
}
public int Year
{
get { return MovieMetadata.Value.Year; }
set { MovieMetadata.Value.Year = value; }
}
}
}

View File

@ -48,11 +48,6 @@ namespace NzbDrone.Core.ImportLists.Radarr
{
TmdbId = remoteMovie.TmdbId,
Title = remoteMovie.Title,
SortTitle = remoteMovie.SortTitle,
Overview = remoteMovie.Overview,
Images = remoteMovie.Images.Select(x => MapImage(x, Settings.BaseUrl)).ToList(),
PhysicalRelease = remoteMovie.PhysicalRelease,
InCinemas = remoteMovie.InCinemas,
Year = remoteMovie.Year
});
}

View File

@ -36,10 +36,7 @@ namespace NzbDrone.Core.ImportLists.TMDb
var movie = new ImportListMovie
{
TmdbId = movieResult.Id,
Overview = movieResult.Overview,
Title = movieResult.Title,
SortTitle = Parser.Parser.NormalizeTitle(movieResult.Title),
Images = new List<MediaCover.MediaCover>(),
};
if (movieResult.ReleaseDate.IsNotNullOrWhiteSpace())
@ -48,8 +45,6 @@ namespace NzbDrone.Core.ImportLists.TMDb
movie.Year = releaseDate.Year;
}
movie.Images.AddIfNotNull(MapPosterImage(movieResult.PosterPath));
return movie;
}

View File

@ -49,7 +49,7 @@ namespace NzbDrone.Core.IndexerSearch
public List<DownloadDecision> MovieSearch(int movieId, bool userInvokedSearch, bool interactiveSearch)
{
var movie = _movieService.GetMovie(movieId);
movie.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
movie.MovieMetadata.Value.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
return MovieSearch(movie, userInvokedSearch, interactiveSearch);
}
@ -81,8 +81,8 @@ namespace NzbDrone.Core.IndexerSearch
var queryTranlations = new List<string>
{
movie.Title,
movie.OriginalTitle
movie.MovieMetadata.Value.Title,
movie.MovieMetadata.Value.OriginalTitle
};
//Add Translation of wanted languages to search query

View File

@ -24,9 +24,9 @@ namespace NzbDrone.Core.Indexers.FileList
{
var pageableRequests = new IndexerPageableRequestChain();
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace())
{
pageableRequests.Add(GetRequest("search-torrents", string.Format("&type=imdb&query={0}", searchCriteria.Movie.ImdbId)));
pageableRequests.Add(GetRequest("search-torrents", string.Format("&type=imdb&query={0}", searchCriteria.Movie.MovieMetadata.Value.ImdbId)));
}
else
{

View File

@ -35,12 +35,12 @@ namespace NzbDrone.Core.Indexers.HDBits
private bool TryAddSearchParameters(TorrentQuery query, SearchCriteriaBase searchCriteria)
{
if (searchCriteria.Movie.ImdbId.IsNullOrWhiteSpace())
if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNullOrWhiteSpace())
{
return false;
}
var imdbId = int.Parse(searchCriteria.Movie.ImdbId.Substring(2));
var imdbId = int.Parse(searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2));
if (imdbId != 0)
{

View File

@ -115,8 +115,8 @@ namespace NzbDrone.Core.Indexers.Newznab
private void AddMovieIdPageableRequests(IndexerPageableRequestChain chain, int maxPages, IEnumerable<int> categories, SearchCriteriaBase searchCriteria)
{
var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.TmdbId > 0;
var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace();
var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.MovieMetadata.Value.TmdbId > 0;
var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace();
if (SupportsAggregatedIdSearch && (includeTmdbSearch || includeImdbSearch))
{
@ -124,12 +124,12 @@ namespace NzbDrone.Core.Indexers.Newznab
if (includeTmdbSearch)
{
ids += "&tmdbid=" + searchCriteria.Movie.TmdbId;
ids += "&tmdbid=" + searchCriteria.Movie.MovieMetadata.Value.TmdbId;
}
if (includeImdbSearch)
{
ids += "&imdbid=" + searchCriteria.Movie.ImdbId.Substring(2);
ids += "&imdbid=" + searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2);
}
chain.Add(GetPagedRequests(maxPages, categories, "movie", ids));
@ -141,14 +141,14 @@ namespace NzbDrone.Core.Indexers.Newznab
chain.Add(GetPagedRequests(maxPages,
categories,
"movie",
string.Format("&tmdbid={0}", searchCriteria.Movie.TmdbId)));
string.Format("&tmdbid={0}", searchCriteria.Movie.MovieMetadata.Value.TmdbId)));
}
else if (includeImdbSearch)
{
chain.Add(GetPagedRequests(maxPages,
categories,
"movie",
string.Format("&imdbid={0}", searchCriteria.Movie.ImdbId.Substring(2))));
string.Format("&imdbid={0}", searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2))));
}
}

View File

@ -29,9 +29,9 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
{
var pageableRequests = new IndexerPageableRequestChain();
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace())
{
pageableRequests.Add(GetRequest(searchCriteria.Movie.ImdbId));
pageableRequests.Add(GetRequest(searchCriteria.Movie.MovieMetadata.Value.ImdbId));
}
else if (searchCriteria.Movie.Year > 0)
{

View File

@ -87,11 +87,11 @@ namespace NzbDrone.Core.Indexers.Rarbg
requestBuilder.AddQueryParam("mode", "search");
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace())
{
requestBuilder.AddQueryParam("search_imdb", searchCriteria.Movie.ImdbId);
requestBuilder.AddQueryParam("search_imdb", searchCriteria.Movie.MovieMetadata.Value.ImdbId);
}
else if (searchCriteria.Movie.TmdbId > 0)
else if (searchCriteria.Movie.MovieMetadata.Value.TmdbId > 0)
{
requestBuilder.AddQueryParam("search_themoviedb", searchCriteria.Movie.TmdbId);
}

View File

@ -1,3 +1,4 @@
using Equ;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.MediaCover
@ -12,7 +13,7 @@ namespace NzbDrone.Core.MediaCover
Headshot = 5
}
public class MediaCover : IEmbeddedDocument
public class MediaCover : MemberwiseEquatable<MediaCover>, IEmbeddedDocument
{
public MediaCoverTypes CoverType { get; set; }
public string Url { get; set; }

View File

@ -145,7 +145,7 @@ namespace NzbDrone.Core.MediaCover
bool updated = false;
var toResize = new List<Tuple<MediaCover, bool>>();
foreach (var cover in movie.Images)
foreach (var cover in movie.MovieMetadata.Value.Images)
{
var fileName = GetCoverPath(movie.Id, cover.CoverType);
var alreadyExists = false;

View File

@ -133,7 +133,7 @@ namespace NzbDrone.Core.MediaFiles
return false;
}
if (_detectSample.IsSample(movie, videoFile) != DetectSampleResult.Sample)
if (_detectSample.IsSample(movie.MovieMetadata, videoFile) != DetectSampleResult.Sample)
{
_logger.Warn("Non-sample file detected: [{0}]", videoFile);
return false;

View File

@ -22,7 +22,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators
public LocalMovie Aggregate(LocalMovie localMovie, DownloadClientItem downloadClientItem, bool otherFiles)
{
var languages = new List<Language> { localMovie.Movie?.OriginalLanguage ?? Language.Unknown };
var languages = new List<Language> { localMovie.Movie?.MovieMetadata.Value.OriginalLanguage ?? Language.Unknown };
var languagesConfidence = Confidence.Default;
foreach (var augmentLanguage in _augmentLanguages)

View File

@ -9,7 +9,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
{
public interface IDetectSample
{
DetectSampleResult IsSample(Movie movie, string path);
DetectSampleResult IsSample(MovieMetadata movie, string path);
}
public class DetectSample : IDetectSample
@ -23,7 +23,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
_logger = logger;
}
public DetectSampleResult IsSample(Movie movie, string path)
public DetectSampleResult IsSample(MovieMetadata movie, string path)
{
var extension = Path.GetExtension(path);
@ -75,7 +75,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
return DetectSampleResult.NotSample;
}
private int GetMinimumAllowedRuntime(Movie movie)
private int GetMinimumAllowedRuntime(MovieMetadata movie)
{
//Anime short - 15 seconds
if (movie.Runtime <= 3)

View File

@ -78,7 +78,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
downloadClientItemInfo = _parsingService.EnhanceMovieInfo(downloadClientItemInfo);
}
var nonSampleVideoFileCount = GetNonSampleVideoFileCount(newFiles, movie);
var nonSampleVideoFileCount = GetNonSampleVideoFileCount(newFiles, movie.MovieMetadata);
var decisions = new List<ImportDecision>();
@ -187,7 +187,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
return null;
}
private int GetNonSampleVideoFileCount(List<string> videoFiles, Movie movie)
private int GetNonSampleVideoFileCount(List<string> videoFiles, MovieMetadata movie)
{
return videoFiles.Count(file =>
{

View File

@ -104,8 +104,8 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
if (languageParse.Count <= 1 && languageParse.First() == Language.Unknown && movie != null)
{
languageParse = new List<Language> { movie.OriginalLanguage };
_logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", movie.OriginalLanguage.Name);
languageParse = new List<Language> { movie.MovieMetadata.Value.OriginalLanguage };
_logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", movie.MovieMetadata.Value.OriginalLanguage.Name);
}
var localMovie = new LocalMovie

View File

@ -25,7 +25,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications
return Decision.Accept();
}
var sample = _detectSample.IsSample(localMovie.Movie, localMovie.Path);
var sample = _detectSample.IsSample(localMovie.Movie.MovieMetadata, localMovie.Path);
if (sample == DetectSampleResult.Sample)
{

View File

@ -49,7 +49,7 @@ namespace NzbDrone.Core.MediaFiles
{
case FileDateType.Release:
{
var releaseDate = movie.PhysicalRelease ?? movie.DigitalRelease;
var releaseDate = movie.MovieMetadata.Value.PhysicalRelease ?? movie.MovieMetadata.Value.DigitalRelease;
if (releaseDate.HasValue == false)
{
@ -61,7 +61,7 @@ namespace NzbDrone.Core.MediaFiles
case FileDateType.Cinemas:
{
var airDate = movie.InCinemas;
var airDate = movie.MovieMetadata.Value.InCinemas;
if (airDate.HasValue == false)
{

View File

@ -7,9 +7,9 @@ namespace NzbDrone.Core.MetadataSource
{
public interface IProvideMovieInfo
{
Movie GetMovieByImdbId(string imdbId);
Tuple<Movie, List<Credit>> GetMovieInfo(int tmdbId);
List<Movie> GetBulkMovieInfo(List<int> tmdbIds);
MovieMetadata GetMovieByImdbId(string imdbId);
Tuple<MovieMetadata, List<Credit>> GetMovieInfo(int tmdbId);
List<MovieMetadata> GetBulkMovieInfo(List<int> tmdbIds);
HashSet<int> GetChangedMovies(DateTime startTime);
}

View File

@ -7,6 +7,6 @@ namespace NzbDrone.Core.MetadataSource
{
List<Movie> SearchForNewMovie(string title);
Movie MapMovieToTmdbMovie(Movie movie);
MovieMetadata MapMovieToTmdbMovie(MovieMetadata movie);
}
}

View File

@ -38,5 +38,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
public string OriginalLanguage { get; set; }
public string Homepage { get; set; }
public List<RecommendationResource> Recommendations { get; set; }
public float? Popularity { get; set; }
}
}

View File

@ -28,12 +28,14 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
private readonly IHttpRequestBuilderFactory _radarrMetadata;
private readonly IConfigService _configService;
private readonly IMovieService _movieService;
private readonly IMovieMetadataService _movieMetadataService;
private readonly IMovieTranslationService _movieTranslationService;
public SkyHookProxy(IHttpClient httpClient,
IRadarrCloudRequestBuilder requestBuilder,
IConfigService configService,
IMovieService movieService,
IMovieMetadataService movieMetadataService,
IMovieTranslationService movieTranslationService,
Logger logger)
{
@ -41,6 +43,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
_radarrMetadata = requestBuilder.RadarrMetadata;
_configService = configService;
_movieService = movieService;
_movieMetadataService = movieMetadataService;
_movieTranslationService = movieTranslationService;
_logger = logger;
@ -65,7 +68,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return new HashSet<int>(response.Resource);
}
public Tuple<Movie, List<Credit>> GetMovieInfo(int tmdbId)
public Tuple<MovieMetadata, List<Credit>> GetMovieInfo(int tmdbId)
{
var httpRequest = _radarrMetadata.Create()
.SetSegment("route", "movie")
@ -95,10 +98,10 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
var movie = MapMovie(httpResponse.Resource);
return new Tuple<Movie, List<Credit>>(movie, credits.ToList());
return new Tuple<MovieMetadata, List<Credit>>(movie, credits.ToList());
}
public List<Movie> GetBulkMovieInfo(List<int> tmdbIds)
public List<MovieMetadata> GetBulkMovieInfo(List<int> tmdbIds)
{
var httpRequest = _radarrMetadata.Create()
.SetSegment("route", "movie/bulk")
@ -123,7 +126,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return movies;
}
public Movie GetMovieByImdbId(string imdbId)
public MovieMetadata GetMovieByImdbId(string imdbId)
{
imdbId = Parser.Parser.NormalizeImdbId(imdbId);
@ -159,18 +162,18 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return movie;
}
public Movie MapMovie(MovieResource resource)
public MovieMetadata MapMovie(MovieResource resource)
{
var movie = new Movie();
var movie = new MovieMetadata();
var altTitles = new List<AlternativeTitle>();
movie.TmdbId = resource.TmdbId;
movie.ImdbId = resource.ImdbId;
movie.Title = resource.Title;
movie.OriginalTitle = resource.OriginalTitle;
movie.TitleSlug = resource.TitleSlug;
movie.CleanTitle = resource.Title.CleanMovieTitle();
movie.SortTitle = Parser.Parser.NormalizeTitle(resource.Title);
movie.CleanOriginalTitle = resource.OriginalTitle.CleanMovieTitle();
movie.Overview = resource.Overview;
movie.AlternativeTitles.AddRange(resource.AlternativeTitles.Select(MapAlternativeTitle));
@ -192,18 +195,26 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
movie.SecondaryYear = resource.Premier?.Year;
}
movie.Images = resource.Images.Select(MapImage).ToList();
if (resource.Runtime != null)
{
movie.Runtime = resource.Runtime.Value;
}
if (resource.Popularity != null)
{
movie.Popularity = resource.Popularity.Value;
}
var certificationCountry = _configService.CertificationCountry.ToString();
movie.Certification = resource.Certifications.FirstOrDefault(m => m.Country == certificationCountry)?.Certification;
movie.Ratings = MapRatings(resource.MovieRatings) ?? new Ratings();
movie.TmdbId = resource.TmdbId;
movie.Genres = resource.Genres;
movie.Images = resource.Images.Select(MapImage).ToList();
//movie.Genres = resource.Genres;
movie.Recommendations = resource.Recommendations?.Select(r => r.TmdbId).ToList() ?? new List<int>();
//Workaround due to metadata change until cache cleans up
@ -266,7 +277,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return title;
}
public Movie MapMovieToTmdbMovie(Movie movie)
public MovieMetadata MapMovieToTmdbMovie(MovieMetadata movie)
{
try
{
@ -274,12 +285,14 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
if (movie.TmdbId > 0)
{
newMovie = _movieService.FindByTmdbId(movie.TmdbId);
newMovie = _movieMetadataService.FindByTmdbId(movie.TmdbId);
if (newMovie == null)
if (newMovie != null)
{
newMovie = GetMovieInfo(movie.TmdbId).Item1;
return newMovie;
}
newMovie = GetMovieInfo(movie.TmdbId).Item1;
}
else if (movie.ImdbId.IsNotNullOrWhiteSpace())
{
@ -293,7 +306,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
yearStr = $" {movie.Year}";
}
newMovie = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault();
newMovie = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault().MovieMetadata;
}
if (newMovie == null)
@ -302,14 +315,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return null;
}
newMovie.Path = movie.Path;
newMovie.RootFolderPath = movie.RootFolderPath;
newMovie.ProfileId = movie.ProfileId;
newMovie.Monitored = movie.Monitored;
newMovie.MovieFile = movie.MovieFile;
newMovie.MinimumAvailability = movie.MinimumAvailability;
newMovie.Tags = movie.Tags;
return newMovie;
}
catch (Exception ex)
@ -347,7 +352,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
try
{
var movieLookup = GetMovieByImdbId(parserResult.ImdbId);
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? movieLookup };
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } };
}
catch (Exception)
{
@ -360,7 +365,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
try
{
var movieLookup = GetMovieInfo(parserResult.TmdbId).Item1;
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? movieLookup };
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } };
}
catch (Exception)
{
@ -385,7 +390,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
try
{
var movieLookup = GetMovieByImdbId(imdbid);
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? movieLookup };
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } };
}
catch (MovieNotFoundException)
{
@ -407,7 +412,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
try
{
var movieLookup = GetMovieInfo(tmdbid).Item1;
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? movieLookup };
return movieLookup == null ? new List<Movie>() : new List<Movie> { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } };
}
catch (MovieNotFoundException)
{
@ -455,11 +460,11 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
if (movie == null)
{
movie = MapMovie(result);
movie = new Movie { MovieMetadata = MapMovie(result) };
}
else
{
movie.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
movie.MovieMetadata.Value.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
}
return movie;

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FluentValidation;
using FluentValidation.Results;
using NLog;
@ -9,6 +10,7 @@ using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Parser;
using NzbDrone.Core.RootFolders;
namespace NzbDrone.Core.Movies
{
@ -21,18 +23,21 @@ namespace NzbDrone.Core.Movies
public class AddMovieService : IAddMovieService
{
private readonly IMovieService _movieService;
private readonly IMovieMetadataService _movieMetadataService;
private readonly IProvideMovieInfo _movieInfo;
private readonly IBuildFileNames _fileNameBuilder;
private readonly IAddMovieValidator _addMovieValidator;
private readonly Logger _logger;
public AddMovieService(IMovieService movieService,
IMovieMetadataService movieMetadataService,
IProvideMovieInfo movieInfo,
IBuildFileNames fileNameBuilder,
IAddMovieValidator addMovieValidator,
Logger logger)
{
_movieService = movieService;
_movieMetadataService = movieMetadataService;
_movieInfo = movieInfo;
_fileNameBuilder = fileNameBuilder;
_addMovieValidator = addMovieValidator;
@ -47,6 +52,10 @@ namespace NzbDrone.Core.Movies
newMovie = SetPropertiesAndValidate(newMovie);
_logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path);
_movieMetadataService.Upsert(newMovie.MovieMetadata.Value);
newMovie.MovieMetadataId = newMovie.MovieMetadata.Value.Id;
_movieService.AddMovie(newMovie);
return newMovie;
@ -65,6 +74,7 @@ namespace NzbDrone.Core.Movies
{
var movie = AddSkyhookData(m);
movie = SetPropertiesAndValidate(movie);
movie.Added = added;
moviesToAdd.Add(movie);
}
@ -79,16 +89,19 @@ namespace NzbDrone.Core.Movies
}
}
_movieMetadataService.UpsertMany(moviesToAdd.Select(x => x.MovieMetadata.Value).ToList());
moviesToAdd.ForEach(x => x.MovieMetadataId = x.MovieMetadata.Value.Id);
return _movieService.AddMovies(moviesToAdd);
}
private Movie AddSkyhookData(Movie newMovie)
{
Movie movie;
var movie = new Movie();
try
{
movie = _movieInfo.GetMovieInfo(newMovie.TmdbId).Item1;
movie.MovieMetadata = _movieInfo.GetMovieInfo(newMovie.TmdbId).Item1;
}
catch (MovieNotFoundException)
{
@ -113,8 +126,8 @@ namespace NzbDrone.Core.Movies
newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName);
}
newMovie.CleanTitle = newMovie.Title.CleanMovieTitle();
newMovie.SortTitle = MovieTitleNormalizer.Normalize(newMovie.Title, newMovie.TmdbId);
newMovie.MovieMetadata.Value.CleanTitle = newMovie.Title.CleanMovieTitle();
newMovie.MovieMetadata.Value.SortTitle = MovieTitleNormalizer.Normalize(newMovie.Title, newMovie.TmdbId);
newMovie.Added = DateTime.UtcNow;
var validationResult = _addMovieValidator.Validate(newMovie);

View File

@ -14,8 +14,7 @@ namespace NzbDrone.Core.Movies
public AddMovieValidator(RootFolderValidator rootFolderValidator,
RecycleBinValidator recycleBinValidator,
MoviePathValidator moviePathValidator,
MovieAncestorValidator movieAncestorValidator,
MovieTitleSlugValidator movieTitleSlugValidator)
MovieAncestorValidator movieAncestorValidator)
{
RuleFor(c => c.Path).Cascade(CascadeMode.StopOnFirstFailure)
.IsValidPath()
@ -23,8 +22,6 @@ namespace NzbDrone.Core.Movies
.SetValidator(recycleBinValidator)
.SetValidator(moviePathValidator)
.SetValidator(movieAncestorValidator);
RuleFor(c => c.TitleSlug).SetValidator(movieTitleSlugValidator);
}
}
}

View File

@ -7,7 +7,7 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
public class AlternativeTitle : ModelBase
{
public SourceType SourceType { get; set; }
public int MovieId { get; set; }
public int MovieMetadataId { get; set; }
public string Title { get; set; }
public string CleanTitle { get; set; }
public int SourceId { get; set; }

View File

@ -9,7 +9,7 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
{
AlternativeTitle FindBySourceId(int sourceId);
List<AlternativeTitle> FindBySourceIds(List<int> sourceIds);
List<AlternativeTitle> FindByMovieId(int movieId);
List<AlternativeTitle> FindByMovieMetadataId(int movieId);
void DeleteForMovies(List<int> movieIds);
}
@ -30,14 +30,14 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
return Query(x => sourceIds.Contains(x.SourceId));
}
public List<AlternativeTitle> FindByMovieId(int movieId)
public List<AlternativeTitle> FindByMovieMetadataId(int movieId)
{
return Query(x => x.MovieId == movieId);
return Query(x => x.MovieMetadataId == movieId);
}
public void DeleteForMovies(List<int> movieIds)
{
Delete(x => movieIds.Contains(x.MovieId));
Delete(x => movieIds.Contains(x.MovieMetadataId));
}
}
}

View File

@ -11,11 +11,11 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
public interface IAlternativeTitleService
{
List<AlternativeTitle> GetAllTitlesForMovie(int movieId);
AlternativeTitle AddAltTitle(AlternativeTitle title, Movie movie);
List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, Movie movie);
AlternativeTitle AddAltTitle(AlternativeTitle title, MovieMetadata movie);
List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, MovieMetadata movie);
AlternativeTitle GetById(int id);
List<AlternativeTitle> GetAllTitles();
List<AlternativeTitle> UpdateTitles(List<AlternativeTitle> titles, Movie movie);
List<AlternativeTitle> UpdateTitles(List<AlternativeTitle> titles, MovieMetadata movie);
}
public class AlternativeTitleService : IAlternativeTitleService, IHandleAsync<MoviesDeletedEvent>
@ -38,18 +38,18 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
public List<AlternativeTitle> GetAllTitlesForMovie(int movieId)
{
return _titleRepo.FindByMovieId(movieId).ToList();
return _titleRepo.FindByMovieMetadataId(movieId).ToList();
}
public AlternativeTitle AddAltTitle(AlternativeTitle title, Movie movie)
public AlternativeTitle AddAltTitle(AlternativeTitle title, MovieMetadata movie)
{
title.MovieId = movie.Id;
title.MovieMetadataId = movie.Id;
return _titleRepo.Insert(title);
}
public List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, Movie movie)
public List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, MovieMetadata movie)
{
titles.ForEach(t => t.MovieId = movie.Id);
titles.ForEach(t => t.MovieMetadataId = movie.Id);
_titleRepo.InsertMany(titles);
return titles;
}
@ -69,12 +69,12 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
_titleRepo.Delete(title);
}
public List<AlternativeTitle> UpdateTitles(List<AlternativeTitle> titles, Movie movie)
public List<AlternativeTitle> UpdateTitles(List<AlternativeTitle> titles, MovieMetadata movie)
{
int movieId = movie.Id;
// First update the movie ids so we can correlate them later.
titles.ForEach(t => t.MovieId = movieId);
titles.ForEach(t => t.MovieMetadataId = movieId);
// Then make sure none of them are the same as the main title.
titles = titles.Where(t => t.CleanTitle != movie.CleanTitle).ToList();
@ -83,10 +83,10 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
titles = titles.DistinctBy(t => t.CleanTitle).ToList();
// Make sure we are not adding titles that exist for other movies (until language PR goes in)
titles = titles.Where(t => !_titleRepo.All().Any(e => e.CleanTitle == t.CleanTitle && e.MovieId != t.MovieId)).ToList();
titles = titles.Where(t => !_titleRepo.All().Any(e => e.CleanTitle == t.CleanTitle && e.MovieMetadataId != t.MovieMetadataId)).ToList();
// Now find titles to delete, update and insert.
var existingTitles = _titleRepo.FindByMovieId(movieId);
var existingTitles = _titleRepo.FindByMovieMetadataId(movieId);
var insert = titles.Where(t => !existingTitles.Contains(t));
var update = existingTitles.Where(t => titles.Contains(t));
@ -101,7 +101,8 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
public void HandleAsync(MoviesDeletedEvent message)
{
_titleRepo.DeleteForMovies(message.Movies.Select(m => m.Id).ToList());
// TODO hanlde metadata delete instead of movie delete
_titleRepo.DeleteForMovies(message.Movies.Select(m => m.MovieMetadataId).ToList());
}
}
}

View File

@ -13,7 +13,7 @@ namespace NzbDrone.Core.Movies.Credits
public string Name { get; set; }
public string CreditTmdbId { get; set; }
public int PersonTmdbId { get; set; }
public int MovieId { get; set; }
public int MovieMetadataId { get; set; }
public List<MediaCover.MediaCover> Images { get; set; }
public string Department { get; set; }
public string Job { get; set; }

View File

@ -6,7 +6,7 @@ namespace NzbDrone.Core.Movies.Credits
{
public interface ICreditRepository : IBasicRepository<Credit>
{
List<Credit> FindByMovieId(int movieId);
List<Credit> FindByMovieMetadataId(int movieId);
void DeleteForMovies(List<int> movieIds);
}
@ -17,14 +17,14 @@ namespace NzbDrone.Core.Movies.Credits
{
}
public List<Credit> FindByMovieId(int movieId)
public List<Credit> FindByMovieMetadataId(int movieId)
{
return Query(x => x.MovieId == movieId);
return Query(x => x.MovieMetadataId == movieId);
}
public void DeleteForMovies(List<int> movieIds)
{
Delete(x => movieIds.Contains(x.MovieId));
Delete(x => movieIds.Contains(x.MovieMetadataId));
}
}
}

View File

@ -9,11 +9,11 @@ namespace NzbDrone.Core.Movies.Credits
public interface ICreditService
{
List<Credit> GetAllCreditsForMovie(int movieId);
Credit AddCredit(Credit credit, Movie movie);
List<Credit> AddCredits(List<Credit> credits, Movie movie);
Credit AddCredit(Credit credit, MovieMetadata movie);
List<Credit> AddCredits(List<Credit> credits, MovieMetadata movie);
Credit GetById(int id);
List<Credit> GetAllCredits();
List<Credit> UpdateCredits(List<Credit> credits, Movie movie);
List<Credit> UpdateCredits(List<Credit> credits, MovieMetadata movie);
}
public class CreditService : ICreditService, IHandleAsync<MoviesDeletedEvent>
@ -27,18 +27,18 @@ namespace NzbDrone.Core.Movies.Credits
public List<Credit> GetAllCreditsForMovie(int movieId)
{
return _creditRepo.FindByMovieId(movieId).ToList();
return _creditRepo.FindByMovieMetadataId(movieId).ToList();
}
public Credit AddCredit(Credit credit, Movie movie)
public Credit AddCredit(Credit credit, MovieMetadata movie)
{
credit.MovieId = movie.Id;
credit.MovieMetadataId = movie.Id;
return _creditRepo.Insert(credit);
}
public List<Credit> AddCredits(List<Credit> credits, Movie movie)
public List<Credit> AddCredits(List<Credit> credits, MovieMetadata movie)
{
credits.ForEach(t => t.MovieId = movie.Id);
credits.ForEach(t => t.MovieMetadataId = movie.Id);
_creditRepo.InsertMany(credits);
return credits;
}
@ -58,15 +58,15 @@ namespace NzbDrone.Core.Movies.Credits
_creditRepo.Delete(credit);
}
public List<Credit> UpdateCredits(List<Credit> credits, Movie movie)
public List<Credit> UpdateCredits(List<Credit> credits, MovieMetadata movie)
{
int movieId = movie.Id;
// First update the movie ids so we can correlate them later.
credits.ForEach(t => t.MovieId = movieId);
credits.ForEach(t => t.MovieMetadataId = movieId);
// Now find credits to delete, update and insert.
var existingCredits = _creditRepo.FindByMovieId(movieId);
var existingCredits = _creditRepo.FindByMovieMetadataId(movieId);
// Should never have multiple credits with same credit_id, but check to ensure incase TMDB is on fritz
var dupeFreeCredits = credits.DistinctBy(m => m.CreditTmdbId).ToList();
@ -86,7 +86,8 @@ namespace NzbDrone.Core.Movies.Credits
public void HandleAsync(MoviesDeletedEvent message)
{
_creditRepo.DeleteForMovies(message.Movies.Select(m => m.Id).ToList());
// TODO handle metadata deletions and not movie deletions
_creditRepo.DeleteForMovies(message.Movies.Select(m => m.MovieMetadataId).ToList());
}
}
}

View File

@ -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);
}
}
}

View File

@ -2,10 +2,7 @@ using System;
using System.Collections.Generic;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Languages;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Movies.AlternativeTitles;
using NzbDrone.Core.Movies.Translations;
using NzbDrone.Core.Profiles;
namespace NzbDrone.Core.Movies
@ -14,79 +11,54 @@ namespace NzbDrone.Core.Movies
{
public Movie()
{
Images = new List<MediaCover.MediaCover>();
Genres = new List<string>();
Tags = new HashSet<int>();
AlternativeTitles = new List<AlternativeTitle>();
Translations = new List<MovieTranslation>();
Recommendations = new List<int>();
OriginalLanguage = Language.English;
Ratings = new Ratings();
MovieMetadata = new MovieMetadata();
}
public int TmdbId { 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; }
public int MovieMetadataId { get; set; }
public bool Monitored { get; set; }
public MovieStatusType MinimumAvailability { get; set; }
public int ProfileId { get; set; }
public DateTime? LastInfoSync { get; set; }
public int Runtime { get; set; }
public List<MediaCover.MediaCover> Images { get; set; }
public string TitleSlug { get; set; }
public string Website { get; set; }
public string Path { get; set; }
public int Year { get; set; }
public Ratings Ratings { get; set; }
public List<string> Genres { get; set; }
public MovieCollection Collection { get; set; }
public LazyLoaded<MovieMetadata> MovieMetadata { get; set; }
public string Certification { get; set; }
public string RootFolderPath { get; set; }
public DateTime Added { get; set; }
public DateTime? InCinemas { get; set; }
public DateTime? PhysicalRelease { get; set; }
public DateTime? DigitalRelease { get; set; }
public Profile Profile { get; set; }
public HashSet<int> Tags { get; set; }
public AddMovieOptions AddOptions { get; set; }
public MovieFile MovieFile { get; set; }
public int MovieFileId { 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 Language OriginalLanguage { get; set; }
public List<int> Recommendations { get; set; }
public bool HasFile => MovieFileId > 0;
public bool IsRecentMovie
//compatibility properties
public string Title
{
get
{
if (PhysicalRelease.HasValue)
{
return PhysicalRelease.Value >= DateTime.UtcNow.AddDays(-21);
}
if (InCinemas.HasValue)
{
return InCinemas.Value >= DateTime.UtcNow.AddDays(-120);
}
return true;
}
get { return MovieMetadata.Value.Title; }
set { MovieMetadata.Value.Title = value; }
}
public bool HasFile => MovieFileId > 0;
public int TmdbId
{
get { return MovieMetadata.Value.TmdbId; }
set { MovieMetadata.Value.TmdbId = value; }
}
public string ImdbId
{
get { return MovieMetadata.Value.ImdbId; }
set { MovieMetadata.Value.ImdbId = value; }
}
public int Year
{
get { return MovieMetadata.Value.Year; }
set { MovieMetadata.Value.Year = value; }
}
public string FolderName()
{
@ -112,27 +84,27 @@ namespace NzbDrone.Core.Movies
{
minimumAvailabilityDate = DateTime.MinValue;
}
else if (MinimumAvailability == MovieStatusType.InCinemas && InCinemas.HasValue)
else if (MinimumAvailability == MovieStatusType.InCinemas && MovieMetadata.Value.InCinemas.HasValue)
{
minimumAvailabilityDate = InCinemas.Value;
minimumAvailabilityDate = MovieMetadata.Value.InCinemas.Value;
}
else
{
if (PhysicalRelease.HasValue && DigitalRelease.HasValue)
if (MovieMetadata.Value.PhysicalRelease.HasValue && MovieMetadata.Value.DigitalRelease.HasValue)
{
minimumAvailabilityDate = new DateTime(Math.Min(PhysicalRelease.Value.Ticks, DigitalRelease.Value.Ticks));
minimumAvailabilityDate = new DateTime(Math.Min(MovieMetadata.Value.PhysicalRelease.Value.Ticks, MovieMetadata.Value.DigitalRelease.Value.Ticks));
}
else if (PhysicalRelease.HasValue)
else if (MovieMetadata.Value.PhysicalRelease.HasValue)
{
minimumAvailabilityDate = PhysicalRelease.Value;
minimumAvailabilityDate = MovieMetadata.Value.PhysicalRelease.Value;
}
else if (DigitalRelease.HasValue)
else if (MovieMetadata.Value.DigitalRelease.HasValue)
{
minimumAvailabilityDate = DigitalRelease.Value;
minimumAvailabilityDate = MovieMetadata.Value.DigitalRelease.Value;
}
else
{
minimumAvailabilityDate = InCinemas.HasValue ? InCinemas.Value.AddDays(90) : DateTime.MaxValue;
minimumAvailabilityDate = MovieMetadata.Value.InCinemas.HasValue ? MovieMetadata.Value.InCinemas.Value.AddDays(90) : DateTime.MaxValue;
}
}
@ -144,20 +116,13 @@ namespace NzbDrone.Core.Movies
return DateTime.Now >= minimumAvailabilityDate.AddDays((double)delay);
}
public DateTime PhysicalReleaseDate()
{
return PhysicalRelease ?? (InCinemas?.AddDays(90) ?? DateTime.MaxValue);
}
public override string ToString()
{
return string.Format("[{1} ({2})][{0}, {3}]", ImdbId, Title.NullSafe(), Year.NullSafe(), TmdbId);
return string.Format("[{1} ({2})][{0}, {3}]", MovieMetadata.Value.ImdbId, MovieMetadata.Value.Title.NullSafe(), MovieMetadata.Value.Year.NullSafe(), MovieMetadata.Value.TmdbId);
}
public void ApplyChanges(Movie otherMovie)
{
TmdbId = otherMovie.TmdbId;
Path = otherMovie.Path;
ProfileId = otherMovie.ProfileId;

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -20,7 +20,6 @@ namespace NzbDrone.Core.Movies
Movie FindByImdbId(string imdbid);
Movie FindByTmdbId(int tmdbid);
List<Movie> FindByTmdbId(List<int> tmdbids);
Movie FindByTitleSlug(string slug);
List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec);
List<Movie> GetMoviesByFileId(int fileId);
@ -28,7 +27,6 @@ namespace NzbDrone.Core.Movies
PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff);
Movie FindByPath(string path);
Dictionary<int, string> AllMoviePaths();
Dictionary<int, string> AllMovieTitleSlugs();
List<int> AllMovieTmdbIds();
Dictionary<int, List<int>> AllMovieTags();
List<int> GetRecommendations();
@ -51,10 +49,11 @@ namespace NzbDrone.Core.Movies
protected override SqlBuilder Builder() => new SqlBuilder(_database.DatabaseType)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.LeftJoin<Movie, AlternativeTitle>((m, t) => m.Id == t.MovieId)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId);
.Join<Movie, MovieMetadata>((m, p) => m.MovieMetadataId == p.Id)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
.LeftJoin<MovieMetadata, AlternativeTitle>((mm, t) => mm.Id == t.MovieMetadataId);
private Movie Map(Dictionary<int, Movie> dict, Movie movie, Profile profile, AlternativeTitle altTitle, MovieFile movieFile, MovieTranslation translation = null)
private Movie Map(Dictionary<int, Movie> dict, Movie movie, Profile profile, MovieFile movieFile, AlternativeTitle altTitle = null, MovieTranslation translation = null)
{
Movie movieEntry;
@ -68,12 +67,12 @@ namespace NzbDrone.Core.Movies
if (altTitle != null)
{
movieEntry.AlternativeTitles.Add(altTitle);
movieEntry.MovieMetadata.Value.AlternativeTitles.Add(altTitle);
}
if (translation != null)
{
movieEntry.Translations.Add(translation);
movieEntry.MovieMetadata.Value.Translations.Add(translation);
}
return movieEntry;
@ -83,9 +82,9 @@ namespace NzbDrone.Core.Movies
{
var movieDictionary = new Dictionary<int, Movie>();
_ = _database.QueryJoined<Movie, Profile, AlternativeTitle, MovieFile>(
_ = _database.QueryJoined<Movie, Profile, MovieFile, AlternativeTitle>(
builder,
(movie, profile, altTitle, file) => Map(movieDictionary, movie, profile, altTitle, file));
(movie, profile, file, altTitle) => Map(movieDictionary, movie, profile, file, altTitle));
return movieDictionary.Values.ToList();
}
@ -95,23 +94,25 @@ namespace NzbDrone.Core.Movies
// the skips the join on profile and alternative title and populates manually
// to avoid repeatedly deserializing the same profile / movie
var builder = new SqlBuilder(_database.DatabaseType)
.LeftJoin<Movie, MovieFile>((m, f) => m.MovieFileId == f.Id);
.LeftJoin<Movie, MovieFile>((m, f) => m.MovieFileId == f.Id)
.LeftJoin<Movie, MovieMetadata>((m, f) => m.MovieMetadataId == f.Id);
var profiles = _profileRepository.All().ToDictionary(x => x.Id);
var titles = _alternativeTitleRepository.All()
.GroupBy(x => x.MovieId)
.GroupBy(x => x.MovieMetadataId)
.ToDictionary(x => x.Key, y => y.ToList());
return _database.QueryJoined<Movie, MovieFile>(
return _database.QueryJoined<Movie, MovieFile, MovieMetadata>(
builder,
(movie, file) =>
(movie, file, metadata) =>
{
movie.MovieFile = file;
movie.MovieMetadata = metadata;
movie.Profile = profiles[movie.ProfileId];
if (titles.TryGetValue(movie.Id, out var altTitles))
if (titles.TryGetValue(movie.MovieMetadataId, out var altTitles))
{
movie.AlternativeTitles = altTitles;
movie.MovieMetadata.Value.AlternativeTitles = altTitles;
}
return movie;
@ -142,30 +143,15 @@ namespace NzbDrone.Core.Movies
{
var movieDictionary = new Dictionary<int, Movie>();
SqlBuilder builder;
if (_database.DatabaseType == DatabaseType.PostgreSQL)
{
builder = new SqlBuilder(_database.DatabaseType)
.LeftJoin<Movie, AlternativeTitle>((m, t) => m.Id == t.MovieId)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
.LeftJoin<Movie, MovieTranslation>((m, tr) => m.Id == tr.MovieId)
var builder = new SqlBuilder(_database.DatabaseType)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.WherePostgres<Movie>(x => titles.Contains(x.CleanTitle));
}
else
{
builder = new SqlBuilder(_database.DatabaseType)
.LeftJoin<Movie, AlternativeTitle>((m, t) => m.Id == t.MovieId)
.Join<Movie, MovieMetadata>((m, p) => m.MovieMetadataId == p.Id)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
.LeftJoin<Movie, MovieTranslation>((m, tr) => m.Id == tr.MovieId)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.Where<Movie>(x => titles.Contains(x.CleanTitle));
}
.Where<MovieMetadata>(x => titles.Contains(x.CleanTitle) || titles.Contains(x.CleanOriginalTitle));
_ = _database.QueryJoined<Movie, Profile, AlternativeTitle, MovieFile, MovieTranslation>(
_ = _database.QueryJoined<Movie, Profile, MovieFile>(
builder,
(movie, profile, altTitle, file, trans) => Map(movieDictionary, movie, profile, altTitle, file, trans));
(movie, profile, file) => Map(movieDictionary, movie, profile, file));
return movieDictionary.Values.ToList();
}
@ -174,32 +160,18 @@ namespace NzbDrone.Core.Movies
{
var movieDictionary = new Dictionary<int, Movie>();
SqlBuilder builder;
var builder = new SqlBuilder(_database.DatabaseType)
.Join<AlternativeTitle, MovieMetadata>((t, mm) => t.MovieMetadataId == mm.Id)
.Join<MovieMetadata, Movie>((mm, m) => mm.Id == m.MovieMetadataId)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
.Where<AlternativeTitle>(x => titles.Contains(x.CleanTitle));
if (_database.DatabaseType == DatabaseType.PostgreSQL)
{
builder = new SqlBuilder(_database.DatabaseType)
.LeftJoin<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
.LeftJoin<Movie, MovieTranslation>((m, tr) => m.Id == tr.MovieId)
.Join<AlternativeTitle, Movie>((t, m) => t.MovieId == m.Id)
.WherePostgres<AlternativeTitle>(x => titles.Contains(x.CleanTitle));
}
else
{
builder = new SqlBuilder(_database.DatabaseType)
.LeftJoin<AlternativeTitle, Movie>((t, m) => t.MovieId == m.Id)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
.LeftJoin<Movie, MovieTranslation>((m, tr) => m.Id == tr.MovieId)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.Where<AlternativeTitle>(x => titles.Contains(x.CleanTitle));
}
_ = _database.QueryJoined<AlternativeTitle, Profile, Movie, MovieFile, MovieTranslation>(
_ = _database.QueryJoined<AlternativeTitle, Profile, Movie, MovieFile>(
builder,
(altTitle, profile, movie, file, trans) =>
(altTitle, profile, movie, file) =>
{
_ = Map(movieDictionary, movie, profile, altTitle, file, trans);
_ = Map(movieDictionary, movie, profile, file, altTitle);
return null;
});
@ -210,32 +182,18 @@ namespace NzbDrone.Core.Movies
{
var movieDictionary = new Dictionary<int, Movie>();
SqlBuilder builder;
if (_database.DatabaseType == DatabaseType.PostgreSQL)
{
builder = new SqlBuilder(_database.DatabaseType)
.LeftJoin<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.LeftJoin<Movie, AlternativeTitle>((m, t) => m.Id == t.MovieId)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
.Join<MovieTranslation, Movie>((tr, m) => tr.MovieId == m.Id)
.WherePostgres<MovieTranslation>(x => titles.Contains(x.CleanTitle));
}
else
{
builder = new SqlBuilder(_database.DatabaseType)
.LeftJoin<MovieTranslation, Movie>((tr, m) => tr.MovieId == m.Id)
.LeftJoin<Movie, AlternativeTitle>((m, t) => m.Id == t.MovieId)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
var builder = new SqlBuilder(_database.DatabaseType)
.Join<MovieTranslation, MovieMetadata>((t, mm) => t.MovieMetadataId == mm.Id)
.Join<MovieMetadata, Movie>((mm, m) => mm.Id == m.MovieMetadataId)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.LeftJoin<Movie, MovieFile>((m, f) => m.Id == f.MovieId)
.Where<MovieTranslation>(x => titles.Contains(x.CleanTitle));
}
_ = _database.QueryJoined<MovieTranslation, Profile, Movie, MovieFile, AlternativeTitle>(
_ = _database.QueryJoined<MovieTranslation, Profile, Movie, MovieFile>(
builder,
(trans, profile, movie, file, altTitle) =>
(trans, profile, movie, file) =>
{
_ = Map(movieDictionary, movie, profile, altTitle, file, trans);
_ = Map(movieDictionary, movie, profile, file, null, trans);
return null;
});
@ -245,12 +203,12 @@ namespace NzbDrone.Core.Movies
public Movie FindByImdbId(string imdbid)
{
var imdbIdWithPrefix = Parser.Parser.NormalizeImdbId(imdbid);
return imdbIdWithPrefix == null ? null : Query(x => x.ImdbId == imdbIdWithPrefix).FirstOrDefault();
return imdbIdWithPrefix == null ? null : Query(x => x.MovieMetadata.Value.ImdbId == imdbIdWithPrefix).FirstOrDefault();
}
public Movie FindByTmdbId(int tmdbid)
{
return Query(x => x.TmdbId == tmdbid).FirstOrDefault();
return Query(x => x.MovieMetadata.Value.TmdbId == tmdbid).FirstOrDefault();
}
public List<Movie> FindByTmdbId(List<int> tmdbids)
@ -268,18 +226,13 @@ namespace NzbDrone.Core.Movies
SetFields(new Movie { Id = movieId, MovieFileId = fileId }, movie => movie.MovieFileId);
}
public Movie FindByTitleSlug(string slug)
{
return Query(x => x.TitleSlug == slug).FirstOrDefault();
}
public List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
{
var builder = Builder()
.Where<Movie>(m =>
(m.InCinemas >= start && m.InCinemas <= end) ||
(m.PhysicalRelease >= start && m.PhysicalRelease <= end) ||
(m.DigitalRelease >= start && m.DigitalRelease <= end));
(m.MovieMetadata.Value.InCinemas >= start && m.MovieMetadata.Value.InCinemas <= end) ||
(m.MovieMetadata.Value.PhysicalRelease >= start && m.MovieMetadata.Value.PhysicalRelease <= end) ||
(m.MovieMetadata.Value.DigitalRelease >= start && m.MovieMetadata.Value.DigitalRelease <= end));
if (!includeUnmonitored)
{
@ -341,20 +294,11 @@ namespace NzbDrone.Core.Movies
}
}
public Dictionary<int, string> AllMovieTitleSlugs()
{
using (var conn = _database.OpenConnection())
{
var strSql = "SELECT \"Id\" AS \"Key\", \"TitleSlug\" AS \"Value\" FROM \"Movies\"";
return conn.Query<KeyValuePair<int, string>>(strSql).ToDictionary(x => x.Key, x => x.Value);
}
}
public List<int> AllMovieTmdbIds()
{
using (var conn = _database.OpenConnection())
{
return conn.Query<int>("SELECT \"TmdbId\" FROM \"Movies\"").ToList();
return conn.Query<int>("SELECT \"TmdbId\" FROM \"MovieMetadata\" JOIN \"Movies\" ON (\"Movies\".\"MovieMetadataId\" = \"MovieMetadata\".\"Id\")").ToList();
}
}
@ -383,14 +327,14 @@ namespace NzbDrone.Core.Movies
recommendations = conn.Query<int>(@"SELECT DISTINCT ""Rec"" FROM (
SELECT DISTINCT ""Rec"" FROM
(
SELECT DISTINCT CAST(""value"" AS INT) AS ""Rec"" FROM ""Movies"", json_array_elements_text((""Movies"".""Recommendations"")::json)
WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub1) LIMIT 10
SELECT DISTINCT CAST(""value"" AS INT) AS ""Rec"" FROM ""MovieMetadata"", json_array_elements_text((""MovieMetadata"".""Recommendations"")::json)
WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub1) LIMIT 10
) as sub2
UNION
SELECT ""Rec"" FROM
(
SELECT CAST(""value"" AS INT) AS ""Rec"" FROM ""Movies"", json_array_elements_text((""Movies"".""Recommendations"")::json)
WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub2)
SELECT CAST(""value"" AS INT) AS ""Rec"" FROM ""MovieMetadata"", json_array_elements_text((""MovieMetadata"".""Recommendations"")::json)
WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub2)
GROUP BY ""Rec"" ORDER BY count(*) DESC LIMIT 120
) as sub4
) as sub5
@ -401,14 +345,14 @@ namespace NzbDrone.Core.Movies
recommendations = conn.Query<int>(@"SELECT DISTINCT ""Rec"" FROM (
SELECT DISTINCT ""Rec"" FROM
(
SELECT DISTINCT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""Movies"" CROSS JOIN json_each(""Movies"".""Recommendations"") AS ""j""
WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"") LIMIT 10
SELECT DISTINCT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""MovieMetadata"" CROSS JOIN json_each(""MovieMetadata"".""Recommendations"") AS ""j""
WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"") LIMIT 10
)
UNION
SELECT ""Rec"" FROM
(
SELECT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""Movies"" CROSS JOIN json_each(""Movies"".""Recommendations"") AS ""j""
WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"")
SELECT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""MovieMetadata"" CROSS JOIN json_each(""MovieMetadata"".""Recommendations"") AS ""j""
WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"")
GROUP BY ""Rec"" ORDER BY count(*) DESC LIMIT 120
)
)

View File

@ -29,11 +29,9 @@ namespace NzbDrone.Core.Movies
Movie FindByTitle(string title, int year);
Movie FindByTitle(List<string> titles, int? year, List<string> otherTitles, List<Movie> candidates);
List<Movie> FindByTitleCandidates(List<string> titles, out List<string> otherTitles);
Movie FindByTitleSlug(string slug);
Movie FindByPath(string path);
Dictionary<int, string> AllMoviePaths();
List<int> AllMovieTmdbIds();
Dictionary<int, string> AllMovieTitleSlugs();
bool MovieExists(Movie movie);
List<Movie> GetMoviesByFileId(int fileId);
List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
@ -120,18 +118,18 @@ namespace NzbDrone.Core.Movies
public Movie FindByTitle(List<string> cleanTitles, int? year, List<string> otherTitles, List<Movie> candidates)
{
var result = candidates.Where(x => cleanTitles.Contains(x.CleanTitle)).FirstWithYear(year);
var result = candidates.Where(x => cleanTitles.Contains(x.MovieMetadata.Value.CleanTitle)).FirstWithYear(year);
if (result == null)
{
result =
candidates.Where(movie => otherTitles.Contains(movie.CleanTitle)).FirstWithYear(year);
candidates.Where(movie => otherTitles.Contains(movie.MovieMetadata.Value.CleanTitle)).FirstWithYear(year);
}
if (result == null)
{
result = candidates
.Where(m => m.AlternativeTitles.Any(t => cleanTitles.Contains(t.CleanTitle) ||
.Where(m => m.MovieMetadata.Value.AlternativeTitles.Any(t => cleanTitles.Contains(t.CleanTitle) ||
otherTitles.Contains(t.CleanTitle)))
.FirstWithYear(year);
}
@ -139,7 +137,7 @@ namespace NzbDrone.Core.Movies
if (result == null)
{
result = candidates
.Where(m => m.Translations.Any(t => cleanTitles.Contains(t.CleanTitle) ||
.Where(m => m.MovieMetadata.Value.Translations.Any(t => cleanTitles.Contains(t.CleanTitle) ||
otherTitles.Contains(t.CleanTitle)))
.FirstWithYear(year);
}
@ -201,11 +199,6 @@ namespace NzbDrone.Core.Movies
return _movieRepository.AllMoviePaths();
}
public Dictionary<int, string> AllMovieTitleSlugs()
{
return _movieRepository.AllMovieTitleSlugs();
}
public List<int> AllMovieTmdbIds()
{
return _movieRepository.AllMovieTmdbIds();
@ -300,11 +293,6 @@ namespace NzbDrone.Core.Movies
return _movieRepository.GetMoviesByFileId(fileId);
}
public Movie FindByTitleSlug(string slug)
{
return _movieRepository.FindByTitleSlug(slug);
}
public List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
{
var movies = _movieRepository.MoviesBetweenDates(start.ToUniversalTime(), end.ToUniversalTime(), includeUnmonitored);
@ -375,7 +363,7 @@ namespace NzbDrone.Core.Movies
var ret = withTmdbid.ExceptBy(m => m.TmdbId, allMovies, m => m.TmdbId, EqualityComparer<int>.Default)
.Union(withImdbid.ExceptBy(m => m.ImdbId, allMovies, m => m.ImdbId, EqualityComparer<string>.Default))
.Union(rest.ExceptBy(m => m.Title.CleanMovieTitle(), allMovies, m => m.CleanTitle, EqualityComparer<string>.Default)).ToList();
.Union(rest.ExceptBy(m => m.Title.CleanMovieTitle(), allMovies, m => m.MovieMetadata.Value.CleanTitle, EqualityComparer<string>.Default)).ToList();
return ret;
}

View File

@ -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;
}
}
}

View File

@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
namespace NzbDrone.Core.Movies
@ -7,7 +7,7 @@ namespace NzbDrone.Core.Movies
{
public static Movie FirstWithYear(this IEnumerable<Movie> query, int? year)
{
return year.HasValue ? query.FirstOrDefault(movie => movie.Year == year || movie.SecondaryYear == year) : query.FirstOrDefault();
return year.HasValue ? query.FirstOrDefault(movie => movie.Year == year || movie.MovieMetadata.Value.SecondaryYear == year) : query.FirstOrDefault();
}
}
}

View File

@ -1,8 +1,9 @@
using Equ;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Movies
{
public class Ratings : IEmbeddedDocument
public class Ratings : MemberwiseEquatable<Ratings>, IEmbeddedDocument
{
public RatingChild Imdb { get; set; }
public RatingChild Tmdb { get; set; }

View File

@ -23,6 +23,7 @@ namespace NzbDrone.Core.Movies
{
private readonly IProvideMovieInfo _movieInfo;
private readonly IMovieService _movieService;
private readonly IMovieMetadataService _movieMetadataService;
private readonly IMovieTranslationService _movieTranslationService;
private readonly IAlternativeTitleService _titleService;
private readonly ICreditService _creditService;
@ -35,6 +36,7 @@ namespace NzbDrone.Core.Movies
public RefreshMovieService(IProvideMovieInfo movieInfo,
IMovieService movieService,
IMovieMetadataService movieMetadataService,
IMovieTranslationService movieTranslationService,
IAlternativeTitleService titleService,
ICreditService creditService,
@ -46,6 +48,7 @@ namespace NzbDrone.Core.Movies
{
_movieInfo = movieInfo;
_movieService = movieService;
_movieMetadataService = movieMetadataService;
_movieTranslationService = movieTranslationService;
_titleService = titleService;
_creditService = creditService;
@ -61,10 +64,11 @@ namespace NzbDrone.Core.Movies
// Get the movie before updating, that way any changes made to the movie after the refresh started,
// but before this movie was refreshed won't be lost.
var movie = _movieService.GetMovie(movieId);
var movieMetadata = _movieMetadataService.Get(movie.MovieMetadataId);
_logger.ProgressInfo("Updating info for {0}", movie.Title);
Movie movieInfo;
MovieMetadata movieInfo;
List<Credit> credits;
try
@ -75,10 +79,10 @@ namespace NzbDrone.Core.Movies
}
catch (MovieNotFoundException)
{
if (movie.Status != MovieStatusType.Deleted)
if (movieMetadata.Status != MovieStatusType.Deleted)
{
movie.Status = MovieStatusType.Deleted;
_movieService.UpdateMovie(movie);
movieMetadata.Status = MovieStatusType.Deleted;
_movieMetadataService.Upsert(movieMetadata);
_logger.Debug("Movie marked as deleted on TMDb for {0}", movie.Title);
_eventAggregator.PublishEvent(new MovieUpdatedEvent(movie));
}
@ -86,56 +90,47 @@ namespace NzbDrone.Core.Movies
throw;
}
if (movie.TmdbId != movieInfo.TmdbId)
if (movieMetadata.TmdbId != movieInfo.TmdbId)
{
_logger.Warn("Movie '{0}' (TMDb: {1}) was replaced with '{2}' (TMDb: {3}), because the original was a duplicate.", movie.Title, movie.TmdbId, movieInfo.Title, movieInfo.TmdbId);
movie.TmdbId = movieInfo.TmdbId;
movieMetadata.TmdbId = movieInfo.TmdbId;
}
movie.Title = movieInfo.Title;
movie.TitleSlug = movieInfo.TitleSlug;
movie.ImdbId = movieInfo.ImdbId;
movie.Overview = movieInfo.Overview;
movie.Status = movieInfo.Status;
movie.CleanTitle = movieInfo.CleanTitle;
movie.SortTitle = movieInfo.SortTitle;
movie.LastInfoSync = DateTime.UtcNow;
movie.Runtime = movieInfo.Runtime;
movie.Images = movieInfo.Images;
movie.Ratings = movieInfo.Ratings;
movie.Collection = movieInfo.Collection;
movie.Genres = movieInfo.Genres;
movie.Certification = movieInfo.Certification;
movie.InCinemas = movieInfo.InCinemas;
movie.Website = movieInfo.Website;
movieMetadata.Title = movieInfo.Title;
movieMetadata.ImdbId = movieInfo.ImdbId;
movieMetadata.Overview = movieInfo.Overview;
movieMetadata.Status = movieInfo.Status;
movieMetadata.CleanTitle = movieInfo.CleanTitle;
movieMetadata.SortTitle = movieInfo.SortTitle;
movieMetadata.LastInfoSync = DateTime.UtcNow;
movieMetadata.Runtime = movieInfo.Runtime;
movieMetadata.Ratings = movieInfo.Ratings;
movieMetadata.Collection = movieInfo.Collection;
movie.Year = movieInfo.Year;
movie.SecondaryYear = movieInfo.SecondaryYear;
movie.PhysicalRelease = movieInfo.PhysicalRelease;
movie.DigitalRelease = movieInfo.DigitalRelease;
movie.YouTubeTrailerId = movieInfo.YouTubeTrailerId;
movie.Studio = movieInfo.Studio;
movie.OriginalTitle = movieInfo.OriginalTitle;
movie.OriginalLanguage = movieInfo.OriginalLanguage;
movie.Recommendations = movieInfo.Recommendations;
//movie.Genres = movieInfo.Genres;
movieMetadata.Certification = movieInfo.Certification;
movieMetadata.InCinemas = movieInfo.InCinemas;
movieMetadata.Website = movieInfo.Website;
try
{
movie.Path = new DirectoryInfo(movie.Path).FullName;
movie.Path = movie.Path.GetActualCasing();
}
catch (Exception e)
{
_logger.Warn(e, "Couldn't update movie path for " + movie.Path);
}
movieMetadata.Year = movieInfo.Year;
movieMetadata.SecondaryYear = movieInfo.SecondaryYear;
movieMetadata.PhysicalRelease = movieInfo.PhysicalRelease;
movieMetadata.DigitalRelease = movieInfo.DigitalRelease;
movieMetadata.YouTubeTrailerId = movieInfo.YouTubeTrailerId;
movieMetadata.Studio = movieInfo.Studio;
movieMetadata.OriginalTitle = movieInfo.OriginalTitle;
movieMetadata.CleanOriginalTitle = movieInfo.CleanOriginalTitle;
movieMetadata.OriginalLanguage = movieInfo.OriginalLanguage;
movieMetadata.Recommendations = movieInfo.Recommendations;
movieMetadata.Popularity = movieInfo.Popularity;
movie.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movie);
_movieTranslationService.UpdateTranslations(movieInfo.Translations, movie);
movieMetadata.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movieMetadata);
_movieTranslationService.UpdateTranslations(movieInfo.Translations, movieMetadata);
_movieService.UpdateMovie(new List<Movie> { movie }, true);
_creditService.UpdateCredits(credits, movie);
_movieMetadataService.Upsert(movieMetadata);
_creditService.UpdateCredits(credits, movieMetadata);
_logger.Debug("Finished movie refresh for {0}", movie.Title);
_logger.Debug("Finished movie metadata refresh for {0}", movieMetadata.Title);
_eventAggregator.PublishEvent(new MovieUpdatedEvent(movie));
return movie;
@ -208,7 +203,8 @@ namespace NzbDrone.Core.Movies
}
else
{
var allMovie = _movieService.GetAllMovies().OrderBy(c => c.SortTitle).ToList();
// TODO refresh all moviemetadata here, even if not used by a Movie
var allMovie = _movieService.GetAllMovies().OrderBy(c => c.MovieMetadata.Value.SortTitle).ToList();
var updatedTMDBMovies = new HashSet<int>();
@ -220,7 +216,7 @@ namespace NzbDrone.Core.Movies
foreach (var movie in allMovie)
{
var movieLocal = movie;
if ((updatedTMDBMovies.Count == 0 && _checkIfMovieShouldBeRefreshed.ShouldRefresh(movie)) || updatedTMDBMovies.Contains(movie.TmdbId) || message.Trigger == CommandTrigger.Manual)
if ((updatedTMDBMovies.Count == 0 && _checkIfMovieShouldBeRefreshed.ShouldRefresh(movie.MovieMetadata)) || updatedTMDBMovies.Contains(movie.TmdbId) || message.Trigger == CommandTrigger.Manual)
{
try
{

View File

@ -5,7 +5,7 @@ namespace NzbDrone.Core.Movies
{
public interface ICheckIfMovieShouldBeRefreshed
{
bool ShouldRefresh(Movie movie);
bool ShouldRefresh(MovieMetadata movie);
}
public class ShouldRefreshMovie : ICheckIfMovieShouldBeRefreshed
@ -17,7 +17,7 @@ namespace NzbDrone.Core.Movies
_logger = logger;
}
public bool ShouldRefresh(Movie movie)
public bool ShouldRefresh(MovieMetadata movie)
{
//return false;
if (movie.LastInfoSync < DateTime.UtcNow.AddDays(-180))

View File

@ -5,7 +5,7 @@ namespace NzbDrone.Core.Movies.Translations
{
public class MovieTranslation : ModelBase
{
public int MovieId { get; set; }
public int MovieMetadataId { get; set; }
public string Title { get; set; }
public string CleanTitle { get; set; }
public string Overview { get; set; }

Some files were not shown because too many files have changed in this diff Show More