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 = [ const movieTokens = [
{ token: '{Movie Title}', example: 'Movie\'s Title' }, { 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 CleanTitle}', example: 'Movies Title' },
{ token: '{Movie TitleThe}', example: 'Movie\'s Title, The' }, { token: '{Movie TitleThe}', example: 'Movie\'s Title, The' },
{ token: '{Movie OriginalTitle}', example: 'Τίτλος ταινίας' }, { token: '{Movie OriginalTitle}', example: 'Τίτλος ταινίας' },
{ token: '{Movie CleanOriginalTitle}', example: 'Τίτλος ταινίας' },
{ token: '{Movie TitleFirstCharacter}', example: 'M' }, { token: '{Movie TitleFirstCharacter}', example: 'M' },
{ token: '{Movie Collection}', example: 'The Movie Collection' }, { token: '{Movie Collection}', example: 'The Movie Collection' },
{ token: '{Movie Certification}', example: 'R' }, { 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); return new WhereBuilderPostgres(filter, true, 0);
} }
private WhereBuilderPostgres WhereMeta(Expression<Func<MovieMetadata, bool>> filter)
{
return new WhereBuilderPostgres(filter, true, 0);
}
[Test] [Test]
public void postgres_where_equal_const() public void postgres_where_equal_const()
{ {
@ -86,36 +91,36 @@ namespace NzbDrone.Core.Test.Datastore
[Test] [Test]
public void postgres_where_string_is_null() 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] [Test]
public void postgres_where_string_is_null_value() public void postgres_where_string_is_null_value()
{ {
string cleanTitle = null; 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] [Test]
public void postgres_where_equal_null_property() public void postgres_where_equal_null_property()
{ {
var movie = new Movie { CleanTitle = null }; var movie = new MovieMetadata { CleanTitle = null };
_subject = Where(x => x.CleanTitle == movie.CleanTitle); _subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)"); _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
} }
[Test] [Test]
public void postgres_where_column_contains_string() public void postgres_where_column_contains_string()
{ {
var test = "small"; 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); _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() public void postgres_where_string_contains_column()
{ {
var test = "small"; 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); _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() public void postgres_where_column_starts_with_string()
{ {
var test = "small"; 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); _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() public void postgres_where_column_ends_with_string()
{ {
var test = "small"; 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); _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() public void postgres_where_in_list_2()
{ {
var list = new List<int> { 1, 2, 3 }; 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] [Test]
@ -172,35 +177,35 @@ namespace NzbDrone.Core.Test.Datastore
{ {
var list = new List<string> { "first", "second", "third" }; 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] [Test]
public void enum_as_int() 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] [Test]
public void enum_in_list() public void enum_in_list()
{ {
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas }; 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] [Test]
public void enum_in_array() public void enum_in_array()
{ {
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas }; 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); return new WhereBuilderSqlite(filter, true, 0);
} }
private WhereBuilderSqlite WhereMeta(Expression<Func<MovieMetadata, bool>> filter)
{
return new WhereBuilderSqlite(filter, true, 0);
}
[Test] [Test]
public void where_equal_const() public void where_equal_const()
{ {
@ -86,36 +91,36 @@ namespace NzbDrone.Core.Test.Datastore
[Test] [Test]
public void where_string_is_null() 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] [Test]
public void where_string_is_null_value() public void where_string_is_null_value()
{ {
string cleanTitle = null; 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] [Test]
public void where_equal_null_property() public void where_equal_null_property()
{ {
var movie = new Movie { CleanTitle = null }; var movie = new MovieMetadata { CleanTitle = null };
_subject = Where(x => x.CleanTitle == movie.CleanTitle); _subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle);
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)"); _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)");
} }
[Test] [Test]
public void where_column_contains_string() public void where_column_contains_string()
{ {
var test = "small"; 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); _subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
} }
@ -123,9 +128,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_string_contains_column() public void where_string_contains_column()
{ {
var test = "small"; 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); _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() public void where_column_starts_with_string()
{ {
var test = "small"; 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); _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() public void where_column_ends_with_string()
{ {
var test = "small"; 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); _subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
} }
@ -164,9 +169,9 @@ namespace NzbDrone.Core.Test.Datastore
public void where_in_list_2() public void where_in_list_2()
{ {
var list = new List<int> { 1, 2, 3 }; 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] [Test]
@ -174,35 +179,35 @@ namespace NzbDrone.Core.Test.Datastore
{ {
var list = new List<string> { "first", "second", "third" }; 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] [Test]
public void enum_as_int() 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] [Test]
public void enum_in_list() public void enum_in_list()
{ {
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas }; 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] [Test]
public void enum_in_array() public void enum_in_array()
{ {
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas }; 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)] [TestCase(60, 1000, false)]
public void single_episode(int runtime, int sizeInMegaBytes, bool expectedResult) public void single_episode(int runtime, int sizeInMegaBytes, bool expectedResult)
{ {
_movie.Runtime = runtime; _movie.MovieMetadata.Value.Runtime = runtime;
_remoteMovie.Movie = _movie; _remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = sizeInMegaBytes.Megabytes(); _remoteMovie.Release.Size = sizeInMegaBytes.Megabytes();
@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test] [Test]
public void should_return_true_if_size_is_zero() public void should_return_true_if_size_is_zero()
{ {
_movie.Runtime = 120; _movie.MovieMetadata.Value.Runtime = 120;
_remoteMovie.Movie = _movie; _remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 0; _remoteMovie.Release.Size = 0;
_qualityType.MinSize = 10; _qualityType.MinSize = 10;
@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test] [Test]
public void should_return_true_if_unlimited_30_minute() public void should_return_true_if_unlimited_30_minute()
{ {
_movie.Runtime = 30; _movie.MovieMetadata.Value.Runtime = 30;
_remoteMovie.Movie = _movie; _remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 18457280000; _remoteMovie.Release.Size = 18457280000;
_qualityType.MaxSize = null; _qualityType.MaxSize = null;
@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test] [Test]
public void should_return_true_if_unlimited_60_minute() public void should_return_true_if_unlimited_60_minute()
{ {
_movie.Runtime = 60; _movie.MovieMetadata.Value.Runtime = 60;
_remoteMovie.Movie = _movie; _remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 36857280000; _remoteMovie.Release.Size = 36857280000;
_qualityType.MaxSize = null; _qualityType.MaxSize = null;
@ -97,7 +97,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test] [Test]
public void should_use_110_minutes_if_runtime_is_0() public void should_use_110_minutes_if_runtime_is_0()
{ {
_movie.Runtime = 0; _movie.MovieMetadata.Value.Runtime = 0;
_remoteMovie.Movie = _movie; _remoteMovie.Movie = _movie;
_remoteMovie.Release.Size = 1095.Megabytes(); _remoteMovie.Release.Size = 1095.Megabytes();

View File

@ -31,7 +31,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{ {
Language = Language.English 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 MinFormatScore = 0
}) })
.With(m => m.Title = "A Movie") .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 = new ReleaseInfo();
remoteMovie.Release.PublishDate = DateTime.Now.AddDays(-age); remoteMovie.Release.PublishDate = DateTime.Now.AddDays(-age);

View File

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

View File

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

View File

@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
public void should_delete_orphaned_credit_items() public void should_delete_orphaned_credit_items()
{ {
var credit = Builder<Credit>.CreateNew() var credit = Builder<Credit>.CreateNew()
.With(h => h.MovieId = default) .With(h => h.MovieMetadataId = default)
.With(h => h.Name = "Some Credit") .With(h => h.Name = "Some Credit")
.BuildNew(); .BuildNew();
@ -27,14 +27,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test] [Test]
public void should_not_delete_unorphaned_credit_items() 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() var credit = Builder<Credit>.CreateNew()
.With(h => h.MovieId = default) .With(h => h.MovieMetadataId = default)
.With(h => h.Name = "Some Credit") .With(h => h.Name = "Some Credit")
.With(b => b.MovieId = movie.Id) .With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew(); .BuildNew();
Db.Insert(credit); 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() public void should_delete_orphaned_movie_translation_items()
{ {
var translation = Builder<MovieTranslation>.CreateNew() var translation = Builder<MovieTranslation>.CreateNew()
.With(h => h.MovieId = default) .With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English) .With(h => h.Language = Language.English)
.BuildNew(); .BuildNew();
@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
[Test] [Test]
public void should_not_delete_unorphaned_movie_translation_items() 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() var translation = Builder<MovieTranslation>.CreateNew()
.With(h => h.MovieId = default) .With(h => h.MovieMetadataId = default)
.With(h => h.Language = Language.English) .With(h => h.Language = Language.English)
.With(b => b.MovieId = movie.Id) .With(b => b.MovieMetadataId = movieMetadata.Id)
.BuildNew(); .BuildNew();
Db.Insert(translation); Db.Insert(translation);

View File

@ -38,8 +38,8 @@ namespace NzbDrone.Core.Test.ImportListTests
.Build().ToList(); .Build().ToList();
Mocker.GetMock<ISearchForNewMovie>() Mocker.GetMock<ISearchForNewMovie>()
.Setup(v => v.MapMovieToTmdbMovie(It.IsAny<Movie>())) .Setup(v => v.MapMovieToTmdbMovie(It.IsAny<MovieMetadata>()))
.Returns<Movie>(m => new Movie { TmdbId = m.TmdbId }); .Returns<MovieMetadata>(m => new MovieMetadata { TmdbId = m.TmdbId });
} }
private void GivenList(int id, bool enabled, bool enabledAuto, ImportListFetchResult fetchResult) 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() _movie = Builder<Movie>.CreateNew()
.With(v => v.Id = 2) .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(); .Build();
Mocker.GetMock<IMovieService>().Setup(m => m.GetMovie(It.Is<int>(id => id == _movie.Id))).Returns(_movie); 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()); .Returns(imported.Select(i => new ImportResult(i)).ToList());
Mocker.GetMock<IDetectSample>() Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(), .Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>())) It.IsAny<string>()))
.Returns(DetectSampleResult.Sample); .Returns(DetectSampleResult.Sample);
@ -324,7 +324,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(imported.Select(i => new ImportResult(i)).ToList()); .Returns(imported.Select(i => new ImportResult(i)).ToList());
Mocker.GetMock<IDetectSample>() Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(), .Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>())) It.IsAny<string>()))
.Returns(DetectSampleResult.Sample); .Returns(DetectSampleResult.Sample);
@ -431,7 +431,7 @@ namespace NzbDrone.Core.Test.MediaFiles
.Returns(new List<ImportResult>()); .Returns(new List<ImportResult>());
Mocker.GetMock<IDetectSample>() Mocker.GetMock<IDetectSample>()
.Setup(s => s.IsSample(It.IsAny<Movie>(), .Setup(s => s.IsSample(It.IsAny<MovieMetadata>(),
It.IsAny<string>())) It.IsAny<string>()))
.Returns(DetectSampleResult.Sample); .Returns(DetectSampleResult.Sample);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,9 +21,9 @@ namespace NzbDrone.Core.Test.MovieTests
private void SetMovieProperties(DateTime? cinema, DateTime? physical, DateTime? digital, MovieStatusType minimumAvailability) private void SetMovieProperties(DateTime? cinema, DateTime? physical, DateTime? digital, MovieStatusType minimumAvailability)
{ {
_movie.InCinemas = cinema; _movie.MovieMetadata.Value.InCinemas = cinema;
_movie.PhysicalRelease = physical; _movie.MovieMetadata.Value.PhysicalRelease = physical;
_movie.DigitalRelease = digital; _movie.MovieMetadata.Value.DigitalRelease = digital;
_movie.MinimumAvailability = minimumAvailability; _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) _candidates = Builder<Movie>.CreateListOfSize(3)
.TheFirst(1) .TheFirst(1)
.With(x => x.CleanTitle = "batman") .With(x => x.MovieMetadata.Value.CleanTitle = "batman")
.With(x => x.Year = 2000) .With(x => x.Year = 2000)
.TheNext(1) .TheNext(1)
.With(x => x.CleanTitle = "batman") .With(x => x.MovieMetadata.Value.CleanTitle = "batman")
.With(x => x.Year = 1999) .With(x => x.Year = 1999)
.TheRest() .TheRest()
.With(x => x.CleanTitle = "darkknight") .With(x => x.MovieMetadata.Value.CleanTitle = "darkknight")
.With(x => x.Year = 2008) .With(x => x.Year = 2008)
.With(x => x.AlternativeTitles = new List<AlternativeTitle> .With(x => x.MovieMetadata.Value.AlternativeTitles = new List<AlternativeTitle>
{ {
new 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] [TestFixture]
public class RefreshMovieServiceFixture : CoreTest<RefreshMovieService> public class RefreshMovieServiceFixture : CoreTest<RefreshMovieService>
{ {
private Movie _movie; private MovieMetadata _movie;
private Movie _existingMovie;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_movie = Builder<Movie>.CreateNew() _movie = Builder<MovieMetadata>.CreateNew()
.With(s => s.Status = MovieStatusType.Released) .With(s => s.Status = MovieStatusType.Released)
.Build(); .Build();
_existingMovie = Builder<Movie>.CreateNew()
.With(s => s.MovieMetadata.Value.Status = MovieStatusType.Released)
.Build();
Mocker.GetMock<IMovieService>() Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovie(_movie.Id)) .Setup(s => s.GetMovie(_movie.Id))
.Returns(_existingMovie);
Mocker.GetMock<IMovieMetadataService>()
.Setup(s => s.Get(_movie.Id))
.Returns(_movie); .Returns(_movie);
Mocker.GetMock<IProvideMovieInfo>() Mocker.GetMock<IProvideMovieInfo>()
@ -36,11 +45,11 @@ namespace NzbDrone.Core.Test.MovieTests
.Callback<int>((i) => { throw new MovieNotFoundException(i); }); .Callback<int>((i) => { throw new MovieNotFoundException(i); });
} }
private void GivenNewMovieInfo(Movie movie) private void GivenNewMovieInfo(MovieMetadata movie)
{ {
Mocker.GetMock<IProvideMovieInfo>() Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(_movie.TmdbId)) .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] [Test]
@ -53,8 +62,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id })); Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>() Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.First().ImdbId == newMovieInfo.ImdbId), true)); .Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.ImdbId == newMovieInfo.ImdbId)));
} }
[Test] [Test]
@ -62,8 +71,8 @@ namespace NzbDrone.Core.Test.MovieTests
{ {
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id })); Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>() Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.UpdateMovie(It.Is<Movie>(s => s.Status == MovieStatusType.Deleted)), Times.Once()); .Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
ExceptionVerification.ExpectedErrors(1); ExceptionVerification.ExpectedErrors(1);
} }
@ -78,8 +87,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id })); Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>() Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.UpdateMovie(It.Is<List<Movie>>(s => s.First().TmdbId == newMovieInfo.TmdbId), true)); .Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.TmdbId == newMovieInfo.TmdbId)));
ExceptionVerification.ExpectedWarns(1); ExceptionVerification.ExpectedWarns(1);
} }
@ -89,8 +98,8 @@ namespace NzbDrone.Core.Test.MovieTests
{ {
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id })); Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>() Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.UpdateMovie(It.Is<Movie>(s => s.Status == MovieStatusType.Deleted)), Times.Once()); .Verify(v => v.Upsert(It.Is<MovieMetadata>(s => s.Status == MovieStatusType.Deleted)), Times.Once());
ExceptionVerification.ExpectedErrors(1); ExceptionVerification.ExpectedErrors(1);
} }
@ -102,8 +111,8 @@ namespace NzbDrone.Core.Test.MovieTests
Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id })); Subject.Execute(new RefreshMovieCommand(new List<int> { _movie.Id }));
Mocker.GetMock<IMovieService>() Mocker.GetMock<IMovieMetadataService>()
.Verify(v => v.UpdateMovie(It.IsAny<Movie>()), Times.Never()); .Verify(v => v.Upsert(It.IsAny<MovieMetadata>()), Times.Never());
ExceptionVerification.ExpectedErrors(1); ExceptionVerification.ExpectedErrors(1);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -47,13 +47,6 @@ namespace NzbDrone.Core.Datastore
return builder.Where(wb.ToString(), wb.Parameters); 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) public static SqlBuilder OrWhere<TModel>(this SqlBuilder builder, Expression<Func<TModel, bool>> filter)
{ {
var wb = GetWhereBuilder(builder.DatabaseType, filter, true, builder.Sequence); 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() Mapper.Entity<Movie>("Movies").RegisterModel()
.Ignore(s => s.RootFolderPath) .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(); Mapper.Entity<AlternativeTitle>("AlternativeTitles").RegisterModel();
@ -156,6 +165,9 @@ namespace NzbDrone.Core.Datastore
Mapper.Entity<DownloadHistory>("DownloadHistory").RegisterModel(); Mapper.Entity<DownloadHistory>("DownloadHistory").RegisterModel();
Mapper.Entity<UpdateHistory>("UpdateHistory").RegisterModel(); Mapper.Entity<UpdateHistory>("UpdateHistory").RegisterModel();
Mapper.Entity<MovieMetadata>("MovieMetadata").RegisterModel()
.Ignore(s => s.Translations);
} }
private static void RegisterMappers() private static void RegisterMappers()

View File

@ -174,9 +174,9 @@ namespace NzbDrone.Core.DecisionEngine
var preferredSize = _qualityDefinitionService.Get(remoteMovie.ParsedMovieInfo.Quality.Quality).PreferredSize; 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 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 // Calculate closest to the preferred size
return Math.Abs((remoteMovie.Release.Size - preferredMovieSize).Round(200.Megabytes())) * (-1); 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); 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); _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) if (qualityDefinition.MinSize.HasValue)
@ -45,7 +45,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
var minSize = qualityDefinition.MinSize.Value.Megabytes(); var minSize = qualityDefinition.MinSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime //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 the parsed size is smaller than minSize we don't want it
if (subject.Release.Size < minSize) if (subject.Release.Size < minSize)
@ -61,7 +61,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{ {
_logger.Debug("Max size is unlimited, skipping check"); _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"); _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"); 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(); var maxSize = qualityDefinition.MaxSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime //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 the parsed size is greater than maxSize we don't want it
if (subject.Release.Size > maxSize) if (subject.Release.Size > maxSize)

View File

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

View File

@ -68,7 +68,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
_proxy.SetTorrentLabel(actualHash, Settings.MovieCategory, Settings); _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) || if ((isRecentMovie && Settings.RecentMoviePriority == (int)DelugePriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (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); _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) || if ((isRecentMovie && Settings.RecentMoviePriority == (int)DelugePriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (int)DelugePriority.First)) (!isRecentMovie && Settings.OlderMoviePriority == (int)DelugePriority.First))

View File

@ -52,7 +52,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
switch (additionalTag) switch (additionalTag)
{ {
case (int)AdditionalTags.Collection: case (int)AdditionalTags.Collection:
result.Add(remoteMovie.Movie.Collection.Name); result.Add(remoteMovie.Movie.MovieMetadata.Value.Collection.Name);
break; break;
case (int)AdditionalTags.Quality: case (int)AdditionalTags.Quality:
result.Add(remoteMovie.ParsedMovieInfo.Quality.Quality.ToString()); result.Add(remoteMovie.ParsedMovieInfo.Quality.Quality.ToString());
@ -70,7 +70,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
result.Add(remoteMovie.Release.Indexer); result.Add(remoteMovie.Release.Indexer);
break; break;
case (int)AdditionalTags.Studio: case (int)AdditionalTags.Studio:
result.Add(remoteMovie.Movie.Studio); result.Add(remoteMovie.Movie.MovieMetadata.Value.Studio);
break; break;
default: default:
throw new DownloadClientException("Unexpected additional tag ID"); 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) 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); 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 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 addpaused = Settings.AddPaused;
var response = _proxy.DownloadNzb(fileContent, filename, category, priority, addpaused, Settings); 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 setShareLimits = remoteMovie.SeedConfiguration != null && (remoteMovie.SeedConfiguration.Ratio.HasValue || remoteMovie.SeedConfiguration.SeedTime.HasValue);
var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1); 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 moveToTop = (isRecentMovie && Settings.RecentMoviePriority == (int)QBittorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)QBittorrentPriority.First);
var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart; 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 setShareLimits = remoteMovie.SeedConfiguration != null && (remoteMovie.SeedConfiguration.Ratio.HasValue || remoteMovie.SeedConfiguration.SeedTime.HasValue);
var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1); 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 moveToTop = (isRecentMovie && Settings.RecentMoviePriority == (int)QBittorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)QBittorrentPriority.First);
var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart; 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) protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContent)
{ {
var category = Settings.MovieCategory; 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); 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.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteMovie.SeedConfiguration, 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) || if ((isRecentMovie && Settings.RecentMoviePriority == (int)TransmissionPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (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.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
_proxy.SetTorrentSeedingConfiguration(hash, remoteMovie.SeedConfiguration, 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) || if ((isRecentMovie && Settings.RecentMoviePriority == (int)TransmissionPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (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) 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); _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) 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); _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); _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) || if ((isRecentMovie && Settings.RecentMoviePriority == (int)UTorrentPriority.First) ||
(!isRecentMovie && Settings.OlderMoviePriority == (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); _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) || if ((isRecentEpisode && Settings.RecentMoviePriority == (int)UTorrentPriority.First) ||
(!isRecentEpisode && Settings.OlderMoviePriority == (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"); var movieElement = new XElement("Movie");
movieElement.Add(new XElement("id", movie.ImdbId)); movieElement.Add(new XElement("id", movie.MovieMetadata.Value.ImdbId));
movieElement.Add(new XElement("Status", movie.Status)); 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("Added", movie.Added.ToString("MM/dd/yyyy HH:mm:ss tt")));
movieElement.Add(new XElement("LockData", "false")); 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("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("ProductionYear", movie.Year));
movieElement.Add(new XElement("RunningTime", movie.Runtime)); movieElement.Add(new XElement("RunningTime", movie.MovieMetadata.Value.Runtime));
movieElement.Add(new XElement("IMDB", movie.ImdbId)); movieElement.Add(new XElement("IMDB", movie.MovieMetadata.Value.ImdbId));
movieElement.Add(new XElement("Genres", movie.Genres.Select(genre => new XElement("Genre", genre)))); movieElement.Add(new XElement("Genres", movie.MovieMetadata.Value.Genres.Select(genre => new XElement("Genre", genre))));
var doc = new XDocument(movieElement); var doc = new XDocument(movieElement);
doc.Save(xw); doc.Save(xw);

View File

@ -118,9 +118,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox
var details = new XElement("video"); var details = new XElement("video");
details.Add(new XElement("title", movie.Title)); details.Add(new XElement("title", movie.Title));
details.Add(new XElement("genre", string.Join(" / ", movie.Genres))); details.Add(new XElement("genre", string.Join(" / ", movie.MovieMetadata.Value.Genres)));
details.Add(new XElement("description", movie.Overview)); details.Add(new XElement("description", movie.MovieMetadata.Value.Overview));
details.Add(new XElement("length", movie.Runtime)); details.Add(new XElement("length", movie.MovieMetadata.Value.Runtime));
doc.Add(details); doc.Add(details);
doc.Save(xw); doc.Save(xw);
@ -139,7 +139,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox
return new List<ImageFileResult>(); 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) if (image == null)
{ {
_logger.Trace("Failed to find suitable Movie image for movie {0}.", movie.Title); _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"); var details = new XElement("details");
details.Add(new XElement("id", movie.Id)); details.Add(new XElement("id", movie.Id));
details.Add(new XElement("title", movie.Title)); details.Add(new XElement("title", movie.Title));
details.Add(new XElement("genre", string.Join(" / ", movie.Genres))); details.Add(new XElement("genre", string.Join(" / ", movie.MovieMetadata.Value.Genres)));
details.Add(new XElement("overview", movie.Overview)); details.Add(new XElement("overview", movie.MovieMetadata.Value.Overview));
doc.Add(details); doc.Add(details);
doc.Save(xw); 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 //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) if (image == null)
{ {
_logger.Trace("Failed to find suitable Movie image for movie {0}.", movie.Title); _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)); _logger.Debug("Generating Movie Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath));
var movieMetadataLanguage = (Settings.MovieMetadataLanguage == (int)Language.Original) ? var movieMetadataLanguage = (Settings.MovieMetadataLanguage == (int)Language.Original) ?
(int)movie.OriginalLanguage : (int)movie.MovieMetadata.Value.OriginalLanguage :
Settings.MovieMetadataLanguage; Settings.MovieMetadataLanguage;
var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovie(movie.Id); var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovie(movie.Id);
var selectedSettingsLanguage = Language.FindById(movieMetadataLanguage); var selectedSettingsLanguage = Language.FindById(movieMetadataLanguage);
var movieTranslation = movieTranslations.FirstOrDefault(mt => mt.Language == selectedSettingsLanguage); 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); var watched = GetExistingWatchedStatus(movie, movieFile.RelativePath);
@ -142,44 +142,44 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
using (var xw = XmlWriter.Create(sb, xws)) using (var xw = XmlWriter.Create(sb, xws))
{ {
var doc = new XDocument(); var doc = new XDocument();
var thumbnail = movie.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot); var thumbnail = movie.MovieMetadata.Value.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot);
var posters = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Poster); var posters = movie.MovieMetadata.Value.Images.Where(i => i.CoverType == MediaCoverTypes.Poster);
var fanarts = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart); var fanarts = movie.MovieMetadata.Value.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart);
var details = new XElement("movie"); var details = new XElement("movie");
details.Add(new XElement("title", movieTranslation?.Title ?? movie.Title)); 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"); 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")); 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("value", movie.MovieMetadata.Value.Ratings.Tmdb.Value));
setRatethemoviedb.Add(new XElement("votes", movie.Ratings.Tmdb.Votes)); setRatethemoviedb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Tmdb.Votes));
setRating.Add(setRatethemoviedb); 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")); 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("value", movie.MovieMetadata.Value.Ratings.Imdb.Value));
setRateImdb.Add(new XElement("votes", movie.Ratings.Imdb.Votes)); setRateImdb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Imdb.Votes));
setRating.Add(setRateImdb); setRating.Add(setRateImdb);
} }
details.Add(setRating); 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")); 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("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("tagline"));
details.Add(new XElement("runtime", movie.Runtime)); details.Add(new XElement("runtime", movie.MovieMetadata.Value.Runtime));
if (thumbnail != null) if (thumbnail != null)
{ {
@ -221,9 +221,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
details.Add(fanartElement); 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")); details.Add(new XElement("playcount"));
@ -237,25 +237,25 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
uniqueId.SetAttributeValue("default", true); uniqueId.SetAttributeValue("default", true);
details.Add(uniqueId); 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"); imdbId.SetAttributeValue("type", "imdb");
details.Add(imdbId); 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("genre", genre));
} }
details.Add(new XElement("country")); details.Add(new XElement("country"));
if (movie.Collection?.Name != null) if (movie.MovieMetadata.Value.Collection?.Name != null)
{ {
var setElement = new XElement("set"); 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")); setElement.Add(new XElement("overview"));
details.Add(setElement); 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("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) if (movieFile.MediaInfo != null)
{ {
@ -369,10 +369,10 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
if (Settings.MovieMetadataURL) 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 += Environment.NewLine;
xmlResult += "https://www.imdb.com/title/" + movie.ImdbId; xmlResult += "https://www.imdb.com/title/" + movie.MovieMetadata.Value.ImdbId;
xmlResult += Environment.NewLine; xmlResult += Environment.NewLine;
} }
@ -393,7 +393,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
private IEnumerable<ImageFileResult> ProcessMovieImages(Movie movie) 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 source = _mediaCoverService.GetCoverPath(movie.Id, image.CoverType);
var destination = image.CoverType.ToString().ToLowerInvariant() + Path.GetExtension(source); var destination = image.CoverType.ToString().ToLowerInvariant() + Path.GetExtension(source);

View File

@ -21,7 +21,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
public override HealthCheck Check() 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()) if (deletedMovie.Empty())
{ {
@ -40,12 +40,12 @@ namespace NzbDrone.Core.HealthCheck.Checks
public bool ShouldCheckOnEvent(MoviesDeletedEvent message) 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) 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; using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Housekeeping.Housekeepers namespace NzbDrone.Core.Housekeeping.Housekeepers
@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
mapper.Execute(@"DELETE FROM ""AlternativeTitles"" mapper.Execute(@"DELETE FROM ""AlternativeTitles""
WHERE ""Id"" IN ( WHERE ""Id"" IN (
SELECT ""AlternativeTitles"".""Id"" FROM ""AlternativeTitles"" SELECT ""AlternativeTitles"".""Id"" FROM ""AlternativeTitles""
LEFT OUTER JOIN ""Movies"" LEFT OUTER JOIN ""MovieMetadata""
ON ""AlternativeTitles"".""MovieId"" = ""Movies"".""Id"" ON ""AlternativeTitles"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""Movies"".""Id"" IS NULL)"); WHERE ""MovieMetadata"".""Id"" IS NULL)");
} }
} }
} }

View File

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

View File

@ -24,18 +24,21 @@ namespace NzbDrone.Core.ImportLists
private readonly IImportListStatusService _importListStatusService; private readonly IImportListStatusService _importListStatusService;
private readonly IImportListMovieService _listMovieService; private readonly IImportListMovieService _listMovieService;
private readonly ISearchForNewMovie _movieSearch; private readonly ISearchForNewMovie _movieSearch;
private readonly IMovieMetadataService _movieMetadataService;
private readonly Logger _logger; private readonly Logger _logger;
public FetchAndParseImportListService(IImportListFactory importListFactory, public FetchAndParseImportListService(IImportListFactory importListFactory,
IImportListStatusService importListStatusService, IImportListStatusService importListStatusService,
IImportListMovieService listMovieService, IImportListMovieService listMovieService,
ISearchForNewMovie movieSearch, ISearchForNewMovie movieSearch,
IMovieMetadataService movieMetadataService,
Logger logger) Logger logger)
{ {
_importListFactory = importListFactory; _importListFactory = importListFactory;
_importListStatusService = importListStatusService; _importListStatusService = importListStatusService;
_listMovieService = listMovieService; _listMovieService = listMovieService;
_movieSearch = movieSearch; _movieSearch = movieSearch;
_movieMetadataService = movieMetadataService;
_logger = logger; _logger = logger;
} }
@ -173,33 +176,16 @@ namespace NzbDrone.Core.ImportLists
private ImportListMovie MapMovieReport(ImportListMovie report) 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 }; var mappedListMovie = new ImportListMovie { ListId = report.ListId };
if (mappedMovie != null) if (mappedMovie != null)
{ {
mappedListMovie.TmdbId = mappedMovie.TmdbId; mappedListMovie.MovieMetadata = mappedMovie;
mappedListMovie.ImdbId = mappedMovie.ImdbId; mappedListMovie.MovieMetadataId = mappedMovie.Id;
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;
} }
return mappedListMovie; return mappedListMovie;

View File

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Translations;
namespace NzbDrone.Core.ImportLists.ImportListMovies namespace NzbDrone.Core.ImportLists.ImportListMovies
{ {
@ -10,37 +7,35 @@ namespace NzbDrone.Core.ImportLists.ImportListMovies
{ {
public ImportListMovie() public ImportListMovie()
{ {
Images = new List<MediaCover.MediaCover>(); MovieMetadata = new MovieMetadata();
Genres = new List<string>();
Translations = new List<MovieTranslation>();
Ratings = new Ratings();
} }
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 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, TmdbId = remoteMovie.TmdbId,
Title = remoteMovie.Title, 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 Year = remoteMovie.Year
}); });
} }

View File

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

View File

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

View File

@ -24,9 +24,9 @@ namespace NzbDrone.Core.Indexers.FileList
{ {
var pageableRequests = new IndexerPageableRequestChain(); 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 else
{ {

View File

@ -35,12 +35,12 @@ namespace NzbDrone.Core.Indexers.HDBits
private bool TryAddSearchParameters(TorrentQuery query, SearchCriteriaBase searchCriteria) private bool TryAddSearchParameters(TorrentQuery query, SearchCriteriaBase searchCriteria)
{ {
if (searchCriteria.Movie.ImdbId.IsNullOrWhiteSpace()) if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNullOrWhiteSpace())
{ {
return false; 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) 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) private void AddMovieIdPageableRequests(IndexerPageableRequestChain chain, int maxPages, IEnumerable<int> categories, SearchCriteriaBase searchCriteria)
{ {
var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.TmdbId > 0; var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.MovieMetadata.Value.TmdbId > 0;
var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace(); var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace();
if (SupportsAggregatedIdSearch && (includeTmdbSearch || includeImdbSearch)) if (SupportsAggregatedIdSearch && (includeTmdbSearch || includeImdbSearch))
{ {
@ -124,12 +124,12 @@ namespace NzbDrone.Core.Indexers.Newznab
if (includeTmdbSearch) if (includeTmdbSearch)
{ {
ids += "&tmdbid=" + searchCriteria.Movie.TmdbId; ids += "&tmdbid=" + searchCriteria.Movie.MovieMetadata.Value.TmdbId;
} }
if (includeImdbSearch) 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)); chain.Add(GetPagedRequests(maxPages, categories, "movie", ids));
@ -141,14 +141,14 @@ namespace NzbDrone.Core.Indexers.Newznab
chain.Add(GetPagedRequests(maxPages, chain.Add(GetPagedRequests(maxPages,
categories, categories,
"movie", "movie",
string.Format("&tmdbid={0}", searchCriteria.Movie.TmdbId))); string.Format("&tmdbid={0}", searchCriteria.Movie.MovieMetadata.Value.TmdbId)));
} }
else if (includeImdbSearch) else if (includeImdbSearch)
{ {
chain.Add(GetPagedRequests(maxPages, chain.Add(GetPagedRequests(maxPages,
categories, categories,
"movie", "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(); 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) else if (searchCriteria.Movie.Year > 0)
{ {

View File

@ -87,11 +87,11 @@ namespace NzbDrone.Core.Indexers.Rarbg
requestBuilder.AddQueryParam("mode", "search"); 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); requestBuilder.AddQueryParam("search_themoviedb", searchCriteria.Movie.TmdbId);
} }

View File

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

View File

@ -145,7 +145,7 @@ namespace NzbDrone.Core.MediaCover
bool updated = false; bool updated = false;
var toResize = new List<Tuple<MediaCover, bool>>(); 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 fileName = GetCoverPath(movie.Id, cover.CoverType);
var alreadyExists = false; var alreadyExists = false;

View File

@ -133,7 +133,7 @@ namespace NzbDrone.Core.MediaFiles
return false; 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); _logger.Warn("Non-sample file detected: [{0}]", videoFile);
return false; return false;

View File

@ -22,7 +22,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators
public LocalMovie Aggregate(LocalMovie localMovie, DownloadClientItem downloadClientItem, bool otherFiles) 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; var languagesConfidence = Confidence.Default;
foreach (var augmentLanguage in _augmentLanguages) foreach (var augmentLanguage in _augmentLanguages)

View File

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

View File

@ -78,7 +78,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
downloadClientItemInfo = _parsingService.EnhanceMovieInfo(downloadClientItemInfo); downloadClientItemInfo = _parsingService.EnhanceMovieInfo(downloadClientItemInfo);
} }
var nonSampleVideoFileCount = GetNonSampleVideoFileCount(newFiles, movie); var nonSampleVideoFileCount = GetNonSampleVideoFileCount(newFiles, movie.MovieMetadata);
var decisions = new List<ImportDecision>(); var decisions = new List<ImportDecision>();
@ -187,7 +187,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
return null; return null;
} }
private int GetNonSampleVideoFileCount(List<string> videoFiles, Movie movie) private int GetNonSampleVideoFileCount(List<string> videoFiles, MovieMetadata movie)
{ {
return videoFiles.Count(file => 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) if (languageParse.Count <= 1 && languageParse.First() == Language.Unknown && movie != null)
{ {
languageParse = new List<Language> { movie.OriginalLanguage }; languageParse = new List<Language> { movie.MovieMetadata.Value.OriginalLanguage };
_logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", movie.OriginalLanguage.Name); _logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", movie.MovieMetadata.Value.OriginalLanguage.Name);
} }
var localMovie = new LocalMovie var localMovie = new LocalMovie

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
{ {
AlternativeTitle FindBySourceId(int sourceId); AlternativeTitle FindBySourceId(int sourceId);
List<AlternativeTitle> FindBySourceIds(List<int> sourceIds); List<AlternativeTitle> FindBySourceIds(List<int> sourceIds);
List<AlternativeTitle> FindByMovieId(int movieId); List<AlternativeTitle> FindByMovieMetadataId(int movieId);
void DeleteForMovies(List<int> movieIds); void DeleteForMovies(List<int> movieIds);
} }
@ -30,14 +30,14 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
return Query(x => sourceIds.Contains(x.SourceId)); 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) 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 public interface IAlternativeTitleService
{ {
List<AlternativeTitle> GetAllTitlesForMovie(int movieId); List<AlternativeTitle> GetAllTitlesForMovie(int movieId);
AlternativeTitle AddAltTitle(AlternativeTitle title, Movie movie); AlternativeTitle AddAltTitle(AlternativeTitle title, MovieMetadata movie);
List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, Movie movie); List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, MovieMetadata movie);
AlternativeTitle GetById(int id); AlternativeTitle GetById(int id);
List<AlternativeTitle> GetAllTitles(); 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> public class AlternativeTitleService : IAlternativeTitleService, IHandleAsync<MoviesDeletedEvent>
@ -38,18 +38,18 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
public List<AlternativeTitle> GetAllTitlesForMovie(int movieId) 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); 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); _titleRepo.InsertMany(titles);
return titles; return titles;
} }
@ -69,12 +69,12 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
_titleRepo.Delete(title); _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; int movieId = movie.Id;
// First update the movie ids so we can correlate them later. // 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. // Then make sure none of them are the same as the main title.
titles = titles.Where(t => t.CleanTitle != movie.CleanTitle).ToList(); 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(); titles = titles.DistinctBy(t => t.CleanTitle).ToList();
// Make sure we are not adding titles that exist for other movies (until language PR goes in) // 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. // 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 insert = titles.Where(t => !existingTitles.Contains(t));
var update = existingTitles.Where(t => titles.Contains(t)); var update = existingTitles.Where(t => titles.Contains(t));
@ -101,7 +101,8 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
public void HandleAsync(MoviesDeletedEvent message) 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 Name { get; set; }
public string CreditTmdbId { get; set; } public string CreditTmdbId { get; set; }
public int PersonTmdbId { 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 List<MediaCover.MediaCover> Images { get; set; }
public string Department { get; set; } public string Department { get; set; }
public string Job { get; set; } public string Job { get; set; }

View File

@ -6,7 +6,7 @@ namespace NzbDrone.Core.Movies.Credits
{ {
public interface ICreditRepository : IBasicRepository<Credit> public interface ICreditRepository : IBasicRepository<Credit>
{ {
List<Credit> FindByMovieId(int movieId); List<Credit> FindByMovieMetadataId(int movieId);
void DeleteForMovies(List<int> movieIds); 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) 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 public interface ICreditService
{ {
List<Credit> GetAllCreditsForMovie(int movieId); List<Credit> GetAllCreditsForMovie(int movieId);
Credit AddCredit(Credit credit, Movie movie); Credit AddCredit(Credit credit, MovieMetadata movie);
List<Credit> AddCredits(List<Credit> credits, Movie movie); List<Credit> AddCredits(List<Credit> credits, MovieMetadata movie);
Credit GetById(int id); Credit GetById(int id);
List<Credit> GetAllCredits(); 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> public class CreditService : ICreditService, IHandleAsync<MoviesDeletedEvent>
@ -27,18 +27,18 @@ namespace NzbDrone.Core.Movies.Credits
public List<Credit> GetAllCreditsForMovie(int movieId) 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); 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); _creditRepo.InsertMany(credits);
return credits; return credits;
} }
@ -58,15 +58,15 @@ namespace NzbDrone.Core.Movies.Credits
_creditRepo.Delete(credit); _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; int movieId = movie.Id;
// First update the movie ids so we can correlate them later. // 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. // 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 // 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(); var dupeFreeCredits = credits.DistinctBy(m => m.CreditTmdbId).ToList();
@ -86,7 +86,8 @@ namespace NzbDrone.Core.Movies.Credits
public void HandleAsync(MoviesDeletedEvent message) 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 System.Collections.Generic;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Languages;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Movies.AlternativeTitles;
using NzbDrone.Core.Movies.Translations;
using NzbDrone.Core.Profiles; using NzbDrone.Core.Profiles;
namespace NzbDrone.Core.Movies namespace NzbDrone.Core.Movies
@ -14,79 +11,54 @@ namespace NzbDrone.Core.Movies
{ {
public Movie() public Movie()
{ {
Images = new List<MediaCover.MediaCover>();
Genres = new List<string>();
Tags = new HashSet<int>(); Tags = new HashSet<int>();
AlternativeTitles = new List<AlternativeTitle>(); MovieMetadata = new MovieMetadata();
Translations = new List<MovieTranslation>();
Recommendations = new List<int>();
OriginalLanguage = Language.English;
Ratings = new Ratings();
} }
public int TmdbId { get; set; } public int MovieMetadataId { 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 bool Monitored { get; set; } public bool Monitored { get; set; }
public MovieStatusType MinimumAvailability { get; set; } public MovieStatusType MinimumAvailability { get; set; }
public int ProfileId { 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 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 string RootFolderPath { get; set; }
public DateTime Added { 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 Profile Profile { get; set; }
public HashSet<int> Tags { get; set; } public HashSet<int> Tags { get; set; }
public AddMovieOptions AddOptions { get; set; } public AddMovieOptions AddOptions { get; set; }
public MovieFile MovieFile { get; set; } public MovieFile MovieFile { get; set; }
public int MovieFileId { get; set; } public int MovieFileId { get; set; }
//Get Loaded via a Join Query public bool HasFile => MovieFileId > 0;
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 IsRecentMovie //compatibility properties
public string Title
{ {
get get { return MovieMetadata.Value.Title; }
{ set { MovieMetadata.Value.Title = value; }
if (PhysicalRelease.HasValue)
{
return PhysicalRelease.Value >= DateTime.UtcNow.AddDays(-21);
}
if (InCinemas.HasValue)
{
return InCinemas.Value >= DateTime.UtcNow.AddDays(-120);
}
return true;
}
} }
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() public string FolderName()
{ {
@ -112,27 +84,27 @@ namespace NzbDrone.Core.Movies
{ {
minimumAvailabilityDate = DateTime.MinValue; 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 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 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); return DateTime.Now >= minimumAvailabilityDate.AddDays((double)delay);
} }
public DateTime PhysicalReleaseDate()
{
return PhysicalRelease ?? (InCinemas?.AddDays(90) ?? DateTime.MaxValue);
}
public override string ToString() 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) public void ApplyChanges(Movie otherMovie)
{ {
TmdbId = otherMovie.TmdbId;
Path = otherMovie.Path; Path = otherMovie.Path;
ProfileId = otherMovie.ProfileId; 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 FindByImdbId(string imdbid);
Movie FindByTmdbId(int tmdbid); Movie FindByTmdbId(int tmdbid);
List<Movie> FindByTmdbId(List<int> tmdbids); List<Movie> FindByTmdbId(List<int> tmdbids);
Movie FindByTitleSlug(string slug);
List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored); List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored);
PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec); PagingSpec<Movie> MoviesWithoutFiles(PagingSpec<Movie> pagingSpec);
List<Movie> GetMoviesByFileId(int fileId); List<Movie> GetMoviesByFileId(int fileId);
@ -28,7 +27,6 @@ namespace NzbDrone.Core.Movies
PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff); PagingSpec<Movie> MoviesWhereCutoffUnmet(PagingSpec<Movie> pagingSpec, List<QualitiesBelowCutoff> qualitiesBelowCutoff);
Movie FindByPath(string path); Movie FindByPath(string path);
Dictionary<int, string> AllMoviePaths(); Dictionary<int, string> AllMoviePaths();
Dictionary<int, string> AllMovieTitleSlugs();
List<int> AllMovieTmdbIds(); List<int> AllMovieTmdbIds();
Dictionary<int, List<int>> AllMovieTags(); Dictionary<int, List<int>> AllMovieTags();
List<int> GetRecommendations(); List<int> GetRecommendations();
@ -51,10 +49,11 @@ namespace NzbDrone.Core.Movies
protected override SqlBuilder Builder() => new SqlBuilder(_database.DatabaseType) protected override SqlBuilder Builder() => new SqlBuilder(_database.DatabaseType)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id) .Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.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, 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; Movie movieEntry;
@ -68,12 +67,12 @@ namespace NzbDrone.Core.Movies
if (altTitle != null) if (altTitle != null)
{ {
movieEntry.AlternativeTitles.Add(altTitle); movieEntry.MovieMetadata.Value.AlternativeTitles.Add(altTitle);
} }
if (translation != null) if (translation != null)
{ {
movieEntry.Translations.Add(translation); movieEntry.MovieMetadata.Value.Translations.Add(translation);
} }
return movieEntry; return movieEntry;
@ -83,9 +82,9 @@ namespace NzbDrone.Core.Movies
{ {
var movieDictionary = new Dictionary<int, Movie>(); var movieDictionary = new Dictionary<int, Movie>();
_ = _database.QueryJoined<Movie, Profile, AlternativeTitle, MovieFile>( _ = _database.QueryJoined<Movie, Profile, MovieFile, AlternativeTitle>(
builder, 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(); return movieDictionary.Values.ToList();
} }
@ -95,23 +94,25 @@ namespace NzbDrone.Core.Movies
// the skips the join on profile and alternative title and populates manually // the skips the join on profile and alternative title and populates manually
// to avoid repeatedly deserializing the same profile / movie // to avoid repeatedly deserializing the same profile / movie
var builder = new SqlBuilder(_database.DatabaseType) 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 profiles = _profileRepository.All().ToDictionary(x => x.Id);
var titles = _alternativeTitleRepository.All() var titles = _alternativeTitleRepository.All()
.GroupBy(x => x.MovieId) .GroupBy(x => x.MovieMetadataId)
.ToDictionary(x => x.Key, y => y.ToList()); .ToDictionary(x => x.Key, y => y.ToList());
return _database.QueryJoined<Movie, MovieFile>( return _database.QueryJoined<Movie, MovieFile, MovieMetadata>(
builder, builder,
(movie, file) => (movie, file, metadata) =>
{ {
movie.MovieFile = file; movie.MovieFile = file;
movie.MovieMetadata = metadata;
movie.Profile = profiles[movie.ProfileId]; 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; return movie;
@ -142,30 +143,15 @@ namespace NzbDrone.Core.Movies
{ {
var movieDictionary = new Dictionary<int, Movie>(); var movieDictionary = new Dictionary<int, Movie>();
SqlBuilder builder; var builder = new SqlBuilder(_database.DatabaseType)
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)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id) .Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.WherePostgres<Movie>(x => titles.Contains(x.CleanTitle)); .Join<Movie, MovieMetadata>((m, p) => m.MovieMetadataId == p.Id)
}
else
{
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, MovieFile>((m, f) => m.Id == f.MovieId)
.LeftJoin<Movie, MovieTranslation>((m, tr) => m.Id == tr.MovieId) .Where<MovieMetadata>(x => titles.Contains(x.CleanTitle) || titles.Contains(x.CleanOriginalTitle));
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id)
.Where<Movie>(x => titles.Contains(x.CleanTitle));
}
_ = _database.QueryJoined<Movie, Profile, AlternativeTitle, MovieFile, MovieTranslation>( _ = _database.QueryJoined<Movie, Profile, MovieFile>(
builder, 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(); return movieDictionary.Values.ToList();
} }
@ -174,32 +160,18 @@ namespace NzbDrone.Core.Movies
{ {
var movieDictionary = new Dictionary<int, Movie>(); 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) _ = _database.QueryJoined<AlternativeTitle, Profile, Movie, MovieFile>(
{
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>(
builder, 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; return null;
}); });
@ -210,32 +182,18 @@ namespace NzbDrone.Core.Movies
{ {
var movieDictionary = new Dictionary<int, Movie>(); var movieDictionary = new Dictionary<int, Movie>();
SqlBuilder builder; var builder = new SqlBuilder(_database.DatabaseType)
.Join<MovieTranslation, MovieMetadata>((t, mm) => t.MovieMetadataId == mm.Id)
if (_database.DatabaseType == DatabaseType.PostgreSQL) .Join<MovieMetadata, Movie>((mm, m) => mm.Id == m.MovieMetadataId)
{
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)
.Join<Movie, Profile>((m, p) => m.ProfileId == p.Id) .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)); .Where<MovieTranslation>(x => titles.Contains(x.CleanTitle));
}
_ = _database.QueryJoined<MovieTranslation, Profile, Movie, MovieFile, AlternativeTitle>( _ = _database.QueryJoined<MovieTranslation, Profile, Movie, MovieFile>(
builder, 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; return null;
}); });
@ -245,12 +203,12 @@ namespace NzbDrone.Core.Movies
public Movie FindByImdbId(string imdbid) public Movie FindByImdbId(string imdbid)
{ {
var imdbIdWithPrefix = Parser.Parser.NormalizeImdbId(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) 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) 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); 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) public List<Movie> MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
{ {
var builder = Builder() var builder = Builder()
.Where<Movie>(m => .Where<Movie>(m =>
(m.InCinemas >= start && m.InCinemas <= end) || (m.MovieMetadata.Value.InCinemas >= start && m.MovieMetadata.Value.InCinemas <= end) ||
(m.PhysicalRelease >= start && m.PhysicalRelease <= end) || (m.MovieMetadata.Value.PhysicalRelease >= start && m.MovieMetadata.Value.PhysicalRelease <= end) ||
(m.DigitalRelease >= start && m.DigitalRelease <= end)); (m.MovieMetadata.Value.DigitalRelease >= start && m.MovieMetadata.Value.DigitalRelease <= end));
if (!includeUnmonitored) 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() public List<int> AllMovieTmdbIds()
{ {
using (var conn = _database.OpenConnection()) 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 ( recommendations = conn.Query<int>(@"SELECT DISTINCT ""Rec"" FROM (
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) 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 ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub1) LIMIT 10 WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub1) LIMIT 10
) as sub2 ) as sub2
UNION UNION
SELECT ""Rec"" FROM SELECT ""Rec"" FROM
( (
SELECT CAST(""value"" AS INT) AS ""Rec"" FROM ""Movies"", json_array_elements_text((""Movies"".""Recommendations"")::json) 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 ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub2) 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 GROUP BY ""Rec"" ORDER BY count(*) DESC LIMIT 120
) as sub4 ) as sub4
) as sub5 ) as sub5
@ -401,14 +345,14 @@ namespace NzbDrone.Core.Movies
recommendations = conn.Query<int>(@"SELECT DISTINCT ""Rec"" FROM ( recommendations = conn.Query<int>(@"SELECT DISTINCT ""Rec"" FROM (
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"" 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 ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"") LIMIT 10 WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"") LIMIT 10
) )
UNION UNION
SELECT ""Rec"" FROM SELECT ""Rec"" FROM
( (
SELECT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""Movies"" CROSS JOIN json_each(""Movies"".""Recommendations"") AS ""j"" 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 ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"") WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"")
GROUP BY ""Rec"" ORDER BY count(*) DESC LIMIT 120 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(string title, int year);
Movie FindByTitle(List<string> titles, int? year, List<string> otherTitles, List<Movie> candidates); Movie FindByTitle(List<string> titles, int? year, List<string> otherTitles, List<Movie> candidates);
List<Movie> FindByTitleCandidates(List<string> titles, out List<string> otherTitles); List<Movie> FindByTitleCandidates(List<string> titles, out List<string> otherTitles);
Movie FindByTitleSlug(string slug);
Movie FindByPath(string path); Movie FindByPath(string path);
Dictionary<int, string> AllMoviePaths(); Dictionary<int, string> AllMoviePaths();
List<int> AllMovieTmdbIds(); List<int> AllMovieTmdbIds();
Dictionary<int, string> AllMovieTitleSlugs();
bool MovieExists(Movie movie); bool MovieExists(Movie movie);
List<Movie> GetMoviesByFileId(int fileId); List<Movie> GetMoviesByFileId(int fileId);
List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored); 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) 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) if (result == null)
{ {
result = result =
candidates.Where(movie => otherTitles.Contains(movie.CleanTitle)).FirstWithYear(year); candidates.Where(movie => otherTitles.Contains(movie.MovieMetadata.Value.CleanTitle)).FirstWithYear(year);
} }
if (result == null) if (result == null)
{ {
result = candidates 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))) otherTitles.Contains(t.CleanTitle)))
.FirstWithYear(year); .FirstWithYear(year);
} }
@ -139,7 +137,7 @@ namespace NzbDrone.Core.Movies
if (result == null) if (result == null)
{ {
result = candidates 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))) otherTitles.Contains(t.CleanTitle)))
.FirstWithYear(year); .FirstWithYear(year);
} }
@ -201,11 +199,6 @@ namespace NzbDrone.Core.Movies
return _movieRepository.AllMoviePaths(); return _movieRepository.AllMoviePaths();
} }
public Dictionary<int, string> AllMovieTitleSlugs()
{
return _movieRepository.AllMovieTitleSlugs();
}
public List<int> AllMovieTmdbIds() public List<int> AllMovieTmdbIds()
{ {
return _movieRepository.AllMovieTmdbIds(); return _movieRepository.AllMovieTmdbIds();
@ -300,11 +293,6 @@ namespace NzbDrone.Core.Movies
return _movieRepository.GetMoviesByFileId(fileId); return _movieRepository.GetMoviesByFileId(fileId);
} }
public Movie FindByTitleSlug(string slug)
{
return _movieRepository.FindByTitleSlug(slug);
}
public List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored) public List<Movie> GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored)
{ {
var movies = _movieRepository.MoviesBetweenDates(start.ToUniversalTime(), end.ToUniversalTime(), 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) 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(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; 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; using System.Linq;
namespace NzbDrone.Core.Movies namespace NzbDrone.Core.Movies
@ -7,7 +7,7 @@ namespace NzbDrone.Core.Movies
{ {
public static Movie FirstWithYear(this IEnumerable<Movie> query, int? year) 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; using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Movies namespace NzbDrone.Core.Movies
{ {
public class Ratings : IEmbeddedDocument public class Ratings : MemberwiseEquatable<Ratings>, IEmbeddedDocument
{ {
public RatingChild Imdb { get; set; } public RatingChild Imdb { get; set; }
public RatingChild Tmdb { get; set; } public RatingChild Tmdb { get; set; }

View File

@ -23,6 +23,7 @@ namespace NzbDrone.Core.Movies
{ {
private readonly IProvideMovieInfo _movieInfo; private readonly IProvideMovieInfo _movieInfo;
private readonly IMovieService _movieService; private readonly IMovieService _movieService;
private readonly IMovieMetadataService _movieMetadataService;
private readonly IMovieTranslationService _movieTranslationService; private readonly IMovieTranslationService _movieTranslationService;
private readonly IAlternativeTitleService _titleService; private readonly IAlternativeTitleService _titleService;
private readonly ICreditService _creditService; private readonly ICreditService _creditService;
@ -35,6 +36,7 @@ namespace NzbDrone.Core.Movies
public RefreshMovieService(IProvideMovieInfo movieInfo, public RefreshMovieService(IProvideMovieInfo movieInfo,
IMovieService movieService, IMovieService movieService,
IMovieMetadataService movieMetadataService,
IMovieTranslationService movieTranslationService, IMovieTranslationService movieTranslationService,
IAlternativeTitleService titleService, IAlternativeTitleService titleService,
ICreditService creditService, ICreditService creditService,
@ -46,6 +48,7 @@ namespace NzbDrone.Core.Movies
{ {
_movieInfo = movieInfo; _movieInfo = movieInfo;
_movieService = movieService; _movieService = movieService;
_movieMetadataService = movieMetadataService;
_movieTranslationService = movieTranslationService; _movieTranslationService = movieTranslationService;
_titleService = titleService; _titleService = titleService;
_creditService = creditService; _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, // 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. // but before this movie was refreshed won't be lost.
var movie = _movieService.GetMovie(movieId); var movie = _movieService.GetMovie(movieId);
var movieMetadata = _movieMetadataService.Get(movie.MovieMetadataId);
_logger.ProgressInfo("Updating info for {0}", movie.Title); _logger.ProgressInfo("Updating info for {0}", movie.Title);
Movie movieInfo; MovieMetadata movieInfo;
List<Credit> credits; List<Credit> credits;
try try
@ -75,10 +79,10 @@ namespace NzbDrone.Core.Movies
} }
catch (MovieNotFoundException) catch (MovieNotFoundException)
{ {
if (movie.Status != MovieStatusType.Deleted) if (movieMetadata.Status != MovieStatusType.Deleted)
{ {
movie.Status = MovieStatusType.Deleted; movieMetadata.Status = MovieStatusType.Deleted;
_movieService.UpdateMovie(movie); _movieMetadataService.Upsert(movieMetadata);
_logger.Debug("Movie marked as deleted on TMDb for {0}", movie.Title); _logger.Debug("Movie marked as deleted on TMDb for {0}", movie.Title);
_eventAggregator.PublishEvent(new MovieUpdatedEvent(movie)); _eventAggregator.PublishEvent(new MovieUpdatedEvent(movie));
} }
@ -86,56 +90,47 @@ namespace NzbDrone.Core.Movies
throw; 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); _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; movieMetadata.Title = movieInfo.Title;
movie.TitleSlug = movieInfo.TitleSlug; movieMetadata.ImdbId = movieInfo.ImdbId;
movie.ImdbId = movieInfo.ImdbId; movieMetadata.Overview = movieInfo.Overview;
movie.Overview = movieInfo.Overview; movieMetadata.Status = movieInfo.Status;
movie.Status = movieInfo.Status; movieMetadata.CleanTitle = movieInfo.CleanTitle;
movie.CleanTitle = movieInfo.CleanTitle; movieMetadata.SortTitle = movieInfo.SortTitle;
movie.SortTitle = movieInfo.SortTitle; movieMetadata.LastInfoSync = DateTime.UtcNow;
movie.LastInfoSync = DateTime.UtcNow; movieMetadata.Runtime = movieInfo.Runtime;
movie.Runtime = movieInfo.Runtime; movieMetadata.Ratings = movieInfo.Ratings;
movie.Images = movieInfo.Images; movieMetadata.Collection = movieInfo.Collection;
movie.Ratings = movieInfo.Ratings;
movie.Collection = movieInfo.Collection;
movie.Genres = movieInfo.Genres;
movie.Certification = movieInfo.Certification;
movie.InCinemas = movieInfo.InCinemas;
movie.Website = movieInfo.Website;
movie.Year = movieInfo.Year; //movie.Genres = movieInfo.Genres;
movie.SecondaryYear = movieInfo.SecondaryYear; movieMetadata.Certification = movieInfo.Certification;
movie.PhysicalRelease = movieInfo.PhysicalRelease; movieMetadata.InCinemas = movieInfo.InCinemas;
movie.DigitalRelease = movieInfo.DigitalRelease; movieMetadata.Website = movieInfo.Website;
movie.YouTubeTrailerId = movieInfo.YouTubeTrailerId;
movie.Studio = movieInfo.Studio;
movie.OriginalTitle = movieInfo.OriginalTitle;
movie.OriginalLanguage = movieInfo.OriginalLanguage;
movie.Recommendations = movieInfo.Recommendations;
try movieMetadata.Year = movieInfo.Year;
{ movieMetadata.SecondaryYear = movieInfo.SecondaryYear;
movie.Path = new DirectoryInfo(movie.Path).FullName; movieMetadata.PhysicalRelease = movieInfo.PhysicalRelease;
movie.Path = movie.Path.GetActualCasing(); movieMetadata.DigitalRelease = movieInfo.DigitalRelease;
} movieMetadata.YouTubeTrailerId = movieInfo.YouTubeTrailerId;
catch (Exception e) movieMetadata.Studio = movieInfo.Studio;
{ movieMetadata.OriginalTitle = movieInfo.OriginalTitle;
_logger.Warn(e, "Couldn't update movie path for " + movie.Path); movieMetadata.CleanOriginalTitle = movieInfo.CleanOriginalTitle;
} movieMetadata.OriginalLanguage = movieInfo.OriginalLanguage;
movieMetadata.Recommendations = movieInfo.Recommendations;
movieMetadata.Popularity = movieInfo.Popularity;
movie.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movie); movieMetadata.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movieMetadata);
_movieTranslationService.UpdateTranslations(movieInfo.Translations, movie); _movieTranslationService.UpdateTranslations(movieInfo.Translations, movieMetadata);
_movieService.UpdateMovie(new List<Movie> { movie }, true); _movieMetadataService.Upsert(movieMetadata);
_creditService.UpdateCredits(credits, movie); _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)); _eventAggregator.PublishEvent(new MovieUpdatedEvent(movie));
return movie; return movie;
@ -208,7 +203,8 @@ namespace NzbDrone.Core.Movies
} }
else 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>(); var updatedTMDBMovies = new HashSet<int>();
@ -220,7 +216,7 @@ namespace NzbDrone.Core.Movies
foreach (var movie in allMovie) foreach (var movie in allMovie)
{ {
var movieLocal = movie; 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 try
{ {

View File

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

View File

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

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