From 6a03eddda96f17cb46867da8147d6ab271906fac Mon Sep 17 00:00:00 2001 From: Qstick Date: Sun, 20 Mar 2022 10:55:47 -0500 Subject: [PATCH] Rework Movie Metadata data model --- .../MediaManagement/Naming/NamingModal.js | 3 +- .../Migration/207_movie_metadataFixture.cs | 303 ++++++++++++++++++ .../Datastore/WhereBuilderPostgresFixture.cs | 55 ++-- .../Datastore/WhereBuilderSqliteFixture.cs | 55 ++-- .../AcceptableSizeSpecificationFixture.cs | 10 +- .../LanguageSpecificationFixture.cs | 5 +- .../PrioritizeDownloadDecisionFixture.cs | 2 +- .../Checks/RemovedMovieCheckFixture.cs | 6 +- ...CleanupOrphanedAlternativeTitlesFixture.cs | 10 +- .../CleanupOrphanedCreditsFixture.cs | 10 +- .../CleanupOrphanedMovieMetadataFixture.cs | 60 ++++ ...CleanupOrphanedMovieTranslationsFixture.cs | 10 +- .../FetchAndParseImportListServiceFixture.cs | 4 +- .../MediaCoverServiceFixture.cs | 2 +- .../DownloadedMoviesImportServiceFixture.cs | 6 +- .../Aggregators/AggregateLanguageFixture.cs | 4 +- .../MovieImport/DetectSampleFixture.cs | 14 +- .../SkyHook/SkyHookProxyFixture.cs | 3 +- .../MovieTests/AddMovieFixture.cs | 7 +- .../AlternativeTitleServiceFixture.cs | 15 +- .../CreditTests/CreditRepositoryFixture.cs | 8 +- .../CreditTests/CreditServiceFixture.cs | 14 +- .../MovieTests/MovieIsAvailableFixture.cs | 6 +- .../MovieMetadataRepositoryFixture.cs | 62 ++++ .../MovieServiceTests/FindByTitleFixture.cs | 8 +- .../MovieTitleSlugValidatorFixture.cs | 79 ----- .../MovieTests/RefreshMovieServiceFixture.cs | 37 ++- .../MovieTests/ShouldRefreshMovieFixture.cs | 4 +- .../FileNameBuilderFixture.cs | 8 +- .../AugmentWithOriginalLanguageFixture.cs | 5 +- .../ParsingServiceTests/MapFixture.cs | 12 +- .../CustomFormatCalculationService.cs | 20 +- .../Datastore/Extensions/BuilderExtensions.cs | 7 - .../Datastore/Migration/207_movie_metadata.cs | 150 +++++++++ src/NzbDrone.Core/Datastore/TableMapping.cs | 16 +- .../DownloadDecisionComparer.cs | 4 +- .../AcceptableSizeSpecification.cs | 10 +- .../Specifications/LanguageSpecification.cs | 2 +- .../Download/Clients/Deluge/Deluge.cs | 4 +- .../Download/Clients/Flood/Flood.cs | 4 +- .../Download/Clients/NzbVortex/NzbVortex.cs | 2 +- .../Download/Clients/Nzbget/Nzbget.cs | 2 +- .../Clients/QBittorrent/QBittorrent.cs | 4 +- .../Download/Clients/Sabnzbd/Sabnzbd.cs | 2 +- .../Clients/Transmission/TransmissionBase.cs | 4 +- .../Download/Clients/rTorrent/RTorrent.cs | 4 +- .../Download/Clients/uTorrent/UTorrent.cs | 4 +- .../MediaBrowser/MediaBrowserMetadata.cs | 14 +- .../Consumers/Roksbox/RoksboxMetadata.cs | 8 +- .../Metadata/Consumers/Wdtv/WdtvMetadata.cs | 6 +- .../Metadata/Consumers/Xbmc/XbmcMetadata.cs | 64 ++-- .../HealthCheck/Checks/RemovedMovieCheck.cs | 6 +- .../CleanupOrphanedAlternativeTitles.cs | 8 +- .../Housekeepers/CleanupOrphanedCredits.cs | 6 +- .../CleanupOrphanedMovieMetadata.cs | 28 ++ .../CleanupOrphanedMovieTranslations.cs | 6 +- .../FetchAndParseImportListService.cs | 30 +- .../ImportListMovies/ImportListMovie.cs | 59 ++-- .../ImportLists/Radarr/RadarrImport.cs | 5 - .../ImportLists/TMDb/TMDbParser.cs | 5 - .../IndexerSearch/ReleaseSearchService.cs | 6 +- .../FileList/FileListRequestGenerator.cs | 4 +- .../Indexers/HDBits/HDBitsRequestGenerator.cs | 4 +- .../Newznab/NewznabRequestGenerator.cs | 12 +- .../PassThePopcornRequestGenerator.cs | 4 +- .../Indexers/Rarbg/RarbgRequestGenerator.cs | 6 +- src/NzbDrone.Core/MediaCover/MediaCover.cs | 3 +- .../MediaCover/MediaCoverService.cs | 2 +- .../DownloadedMovieImportService.cs | 2 +- .../Aggregators/AggregateLanguage.cs | 2 +- .../MediaFiles/MovieImport/DetectSample.cs | 6 +- .../MovieImport/ImportDecisionMaker.cs | 4 +- .../MovieImport/Manual/ManualImportService.cs | 4 +- .../Specifications/NotSampleSpecification.cs | 2 +- .../MediaFiles/UpdateMovieFileService.cs | 4 +- .../MetadataSource/IProvideMovieInfo.cs | 6 +- .../MetadataSource/ISearchForNewMovie.cs | 2 +- .../SkyHook/Resource/MovieResource.cs | 1 + .../MetadataSource/SkyHook/SkyHookProxy.cs | 61 ++-- src/NzbDrone.Core/Movies/AddMovieService.cs | 21 +- src/NzbDrone.Core/Movies/AddMovieValidator.cs | 5 +- .../AlternativeTitles/AlternativeTitle.cs | 2 +- .../AlternativeTitleRepository.cs | 8 +- .../AlternativeTitleService.cs | 27 +- src/NzbDrone.Core/Movies/Credits/Credit.cs | 2 +- .../Movies/Credits/CreditRepository.cs | 8 +- .../Movies/Credits/CreditService.cs | 25 +- src/NzbDrone.Core/Movies/Entity.cs | 41 +++ src/NzbDrone.Core/Movies/Movie.cs | 109 +++---- src/NzbDrone.Core/Movies/MovieMetadata.cs | 82 +++++ .../Movies/MovieMetadataRepository.cs | 72 +++++ .../Movies/MovieMetadataService.cs | 42 +++ src/NzbDrone.Core/Movies/MovieRepository.cs | 158 +++------ src/NzbDrone.Core/Movies/MovieService.cs | 22 +- .../Movies/MovieTitleSlugValidator.cs | 47 --- src/NzbDrone.Core/Movies/QueryExtensions.cs | 4 +- src/NzbDrone.Core/Movies/Ratings.cs | 3 +- .../Movies/RefreshMovieService.cs | 90 +++--- .../Movies/ShouldRefreshMovie.cs | 4 +- .../Movies/Translations/MovieTranslation.cs | 2 +- .../MovieTranslationRepository.cs | 8 +- .../Translations/MovieTranslationService.cs | 13 +- .../CustomScript/CustomScript.cs | 48 +-- .../Notifications/Discord/Discord.cs | 50 +-- .../Notifications/Notifiarr/Notifiarr.cs | 40 +-- .../Notifications/NotificationService.cs | 2 +- .../Notifications/Trakt/TraktService.cs | 8 +- .../Notifications/Webhook/WebhookMovie.cs | 2 +- .../Webhook/WebhookRemoteMovie.cs | 18 +- .../Organizer/FileNameBuilder.cs | 15 +- .../Organizer/FileNameSampleService.cs | 11 +- .../Augmenters/AugmentWithOriginalLanguage.cs | 4 +- src/NzbDrone.Core/Parser/ParsingService.cs | 24 +- src/NzbDrone.Core/Radarr.Core.csproj | 1 + .../Calendar/CalendarController.cs | 6 +- .../Calendar/CalendarFeedController.cs | 8 +- src/Radarr.Api.V3/Credits/CreditController.cs | 15 +- src/Radarr.Api.V3/Credits/CreditResource.cs | 6 +- .../ImportLists/ImportListMoviesController.cs | 18 +- .../ImportLists/ImportListMoviesResource.cs | 60 ++-- .../Movies/AlternativeTitleController.cs | 15 +- .../Movies/AlternativeTitleResource.cs | 6 +- src/Radarr.Api.V3/Movies/MovieController.cs | 24 +- .../Movies/MovieLookupController.cs | 12 +- src/Radarr.Api.V3/Movies/MovieResource.cs | 90 +++--- src/Radarr.Api.V3/Queue/QueueController.cs | 2 +- 126 files changed, 1695 insertions(+), 1031 deletions(-) create mode 100644 src/NzbDrone.Core.Test/Datastore/Migration/207_movie_metadataFixture.cs create mode 100644 src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMovieMetadataFixture.cs create mode 100644 src/NzbDrone.Core.Test/MovieTests/MovieMetadataRepositoryTests/MovieMetadataRepositoryFixture.cs delete mode 100644 src/NzbDrone.Core.Test/MovieTests/MovieTitleSlugValidatorFixture.cs create mode 100644 src/NzbDrone.Core/Datastore/Migration/207_movie_metadata.cs create mode 100644 src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieMetadata.cs create mode 100644 src/NzbDrone.Core/Movies/Entity.cs create mode 100644 src/NzbDrone.Core/Movies/MovieMetadata.cs create mode 100644 src/NzbDrone.Core/Movies/MovieMetadataRepository.cs create mode 100644 src/NzbDrone.Core/Movies/MovieMetadataService.cs delete mode 100644 src/NzbDrone.Core/Movies/MovieTitleSlugValidator.cs diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingModal.js b/frontend/src/Settings/MediaManagement/Naming/NamingModal.js index 6fc4b068a..163cc33d1 100644 --- a/frontend/src/Settings/MediaManagement/Naming/NamingModal.js +++ b/frontend/src/Settings/MediaManagement/Naming/NamingModal.js @@ -116,10 +116,11 @@ class NamingModal extends Component { const movieTokens = [ { token: '{Movie Title}', example: 'Movie\'s Title' }, - { token: '{Movie Title:DE}', example: 'Filetitle' }, + { token: '{Movie Title:DE}', example: 'Titel des Films' }, { token: '{Movie CleanTitle}', example: 'Movies Title' }, { token: '{Movie TitleThe}', example: 'Movie\'s Title, The' }, { token: '{Movie OriginalTitle}', example: 'Τίτλος ταινίας' }, + { token: '{Movie CleanOriginalTitle}', example: 'Τίτλος ταινίας' }, { token: '{Movie TitleFirstCharacter}', example: 'M' }, { token: '{Movie Collection}', example: 'The Movie Collection' }, { token: '{Movie Certification}', example: 'R' }, diff --git a/src/NzbDrone.Core.Test/Datastore/Migration/207_movie_metadataFixture.cs b/src/NzbDrone.Core.Test/Datastore/Migration/207_movie_metadataFixture.cs new file mode 100644 index 000000000..26c229dc8 --- /dev/null +++ b/src/NzbDrone.Core.Test/Datastore/Migration/207_movie_metadataFixture.cs @@ -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 + { + [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("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("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("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("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("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("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("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("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("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("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("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("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\""); + + movies.Should().HaveCount(1); + movies.First().MovieMetadataId.Should().Be(metadata.First().Id); + + var listMovies = db.Query("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; } + } +} diff --git a/src/NzbDrone.Core.Test/Datastore/WhereBuilderPostgresFixture.cs b/src/NzbDrone.Core.Test/Datastore/WhereBuilderPostgresFixture.cs index 303862729..5780901d7 100644 --- a/src/NzbDrone.Core.Test/Datastore/WhereBuilderPostgresFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/WhereBuilderPostgresFixture.cs @@ -27,6 +27,11 @@ namespace NzbDrone.Core.Test.Datastore return new WhereBuilderPostgres(filter, true, 0); } + private WhereBuilderPostgres WhereMeta(Expression> filter) + { + return new WhereBuilderPostgres(filter, true, 0); + } + [Test] public void postgres_where_equal_const() { @@ -86,36 +91,36 @@ namespace NzbDrone.Core.Test.Datastore [Test] public void postgres_where_string_is_null() { - _subject = Where(x => x.CleanTitle == null); + _subject = WhereMeta(x => x.CleanTitle == null); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)"); } [Test] public void postgres_where_string_is_null_value() { string cleanTitle = null; - _subject = Where(x => x.CleanTitle == cleanTitle); + _subject = WhereMeta(x => x.CleanTitle == cleanTitle); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)"); } [Test] public void postgres_where_equal_null_property() { - var movie = new Movie { CleanTitle = null }; - _subject = Where(x => x.CleanTitle == movie.CleanTitle); + var movie = new MovieMetadata { CleanTitle = null }; + _subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)"); } [Test] public void postgres_where_column_contains_string() { var test = "small"; - _subject = Where(x => x.CleanTitle.Contains(test)); + _subject = WhereMeta(x => x.CleanTitle.Contains(test)); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE '%' || @Clause1_P1 || '%')"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE '%' || @Clause1_P1 || '%')"); _subject.Parameters.Get("Clause1_P1").Should().Be(test); } @@ -123,9 +128,9 @@ namespace NzbDrone.Core.Test.Datastore public void postgres_where_string_contains_column() { var test = "small"; - _subject = Where(x => test.Contains(x.CleanTitle)); + _subject = WhereMeta(x => test.Contains(x.CleanTitle)); - _subject.ToString().Should().Be($"(@Clause1_P1 ILIKE '%' || \"Movies\".\"CleanTitle\" || '%')"); + _subject.ToString().Should().Be($"(@Clause1_P1 ILIKE '%' || \"MovieMetadata\".\"CleanTitle\" || '%')"); _subject.Parameters.Get("Clause1_P1").Should().Be(test); } @@ -133,9 +138,9 @@ namespace NzbDrone.Core.Test.Datastore public void postgres_where_column_starts_with_string() { var test = "small"; - _subject = Where(x => x.CleanTitle.StartsWith(test)); + _subject = WhereMeta(x => x.CleanTitle.StartsWith(test)); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE @Clause1_P1 || '%')"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE @Clause1_P1 || '%')"); _subject.Parameters.Get("Clause1_P1").Should().Be(test); } @@ -143,9 +148,9 @@ namespace NzbDrone.Core.Test.Datastore public void postgres_where_column_ends_with_string() { var test = "small"; - _subject = Where(x => x.CleanTitle.EndsWith(test)); + _subject = WhereMeta(x => x.CleanTitle.EndsWith(test)); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE '%' || @Clause1_P1)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" ILIKE '%' || @Clause1_P1)"); _subject.Parameters.Get("Clause1_P1").Should().Be(test); } @@ -162,9 +167,9 @@ namespace NzbDrone.Core.Test.Datastore public void postgres_where_in_list_2() { var list = new List { 1, 2, 3 }; - _subject = Where(x => x.CleanTitle == "test" && list.Contains(x.Id)); + _subject = WhereMeta(x => x.CleanTitle == "test" && list.Contains(x.Id)); - _subject.ToString().Should().Be($"((\"Movies\".\"CleanTitle\" = @Clause1_P1) AND (\"Movies\".\"Id\" = ANY (('{{1, 2, 3}}'))))"); + _subject.ToString().Should().Be($"((\"MovieMetadata\".\"CleanTitle\" = @Clause1_P1) AND (\"MovieMetadata\".\"Id\" = ANY (('{{1, 2, 3}}'))))"); } [Test] @@ -172,35 +177,35 @@ namespace NzbDrone.Core.Test.Datastore { var list = new List { "first", "second", "third" }; - _subject = Where(x => list.Contains(x.CleanTitle)); + _subject = WhereMeta(x => list.Contains(x.CleanTitle)); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" = ANY (@Clause1_P1))"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" = ANY (@Clause1_P1))"); } [Test] public void enum_as_int() { - _subject = Where(x => x.Status == MovieStatusType.Announced); + _subject = WhereMeta(x => x.Status == MovieStatusType.Announced); - _subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @Clause1_P1)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = @Clause1_P1)"); } [Test] public void enum_in_list() { var allowed = new List { MovieStatusType.Announced, MovieStatusType.InCinemas }; - _subject = Where(x => allowed.Contains(x.Status)); + _subject = WhereMeta(x => allowed.Contains(x.Status)); - _subject.ToString().Should().Be($"(\"Movies\".\"Status\" = ANY (@Clause1_P1))"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = ANY (@Clause1_P1))"); } [Test] public void enum_in_array() { var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas }; - _subject = Where(x => allowed.Contains(x.Status)); + _subject = WhereMeta(x => allowed.Contains(x.Status)); - _subject.ToString().Should().Be($"(\"Movies\".\"Status\" = ANY (@Clause1_P1))"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = ANY (@Clause1_P1))"); } } } diff --git a/src/NzbDrone.Core.Test/Datastore/WhereBuilderSqliteFixture.cs b/src/NzbDrone.Core.Test/Datastore/WhereBuilderSqliteFixture.cs index 30fe38306..c44e78bad 100644 --- a/src/NzbDrone.Core.Test/Datastore/WhereBuilderSqliteFixture.cs +++ b/src/NzbDrone.Core.Test/Datastore/WhereBuilderSqliteFixture.cs @@ -27,6 +27,11 @@ namespace NzbDrone.Core.Test.Datastore return new WhereBuilderSqlite(filter, true, 0); } + private WhereBuilderSqlite WhereMeta(Expression> filter) + { + return new WhereBuilderSqlite(filter, true, 0); + } + [Test] public void where_equal_const() { @@ -86,36 +91,36 @@ namespace NzbDrone.Core.Test.Datastore [Test] public void where_string_is_null() { - _subject = Where(x => x.CleanTitle == null); + _subject = WhereMeta(x => x.CleanTitle == null); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)"); } [Test] public void where_string_is_null_value() { string cleanTitle = null; - _subject = Where(x => x.CleanTitle == cleanTitle); + _subject = WhereMeta(x => x.CleanTitle == cleanTitle); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)"); } [Test] public void where_equal_null_property() { - var movie = new Movie { CleanTitle = null }; - _subject = Where(x => x.CleanTitle == movie.CleanTitle); + var movie = new MovieMetadata { CleanTitle = null }; + _subject = WhereMeta(x => x.CleanTitle == movie.CleanTitle); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IS NULL)"); } [Test] public void where_column_contains_string() { var test = "small"; - _subject = Where(x => x.CleanTitle.Contains(test)); + _subject = WhereMeta(x => x.CleanTitle.Contains(test)); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE '%' || @Clause1_P1 || '%')"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE '%' || @Clause1_P1 || '%')"); _subject.Parameters.Get("Clause1_P1").Should().Be(test); } @@ -123,9 +128,9 @@ namespace NzbDrone.Core.Test.Datastore public void where_string_contains_column() { var test = "small"; - _subject = Where(x => test.Contains(x.CleanTitle)); + _subject = WhereMeta(x => test.Contains(x.CleanTitle)); - _subject.ToString().Should().Be($"(@Clause1_P1 LIKE '%' || \"Movies\".\"CleanTitle\" || '%')"); + _subject.ToString().Should().Be($"(@Clause1_P1 LIKE '%' || \"MovieMetadata\".\"CleanTitle\" || '%')"); _subject.Parameters.Get("Clause1_P1").Should().Be(test); } @@ -133,9 +138,9 @@ namespace NzbDrone.Core.Test.Datastore public void where_column_starts_with_string() { var test = "small"; - _subject = Where(x => x.CleanTitle.StartsWith(test)); + _subject = WhereMeta(x => x.CleanTitle.StartsWith(test)); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE @Clause1_P1 || '%')"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE @Clause1_P1 || '%')"); _subject.Parameters.Get("Clause1_P1").Should().Be(test); } @@ -143,9 +148,9 @@ namespace NzbDrone.Core.Test.Datastore public void where_column_ends_with_string() { var test = "small"; - _subject = Where(x => x.CleanTitle.EndsWith(test)); + _subject = WhereMeta(x => x.CleanTitle.EndsWith(test)); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" LIKE '%' || @Clause1_P1)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" LIKE '%' || @Clause1_P1)"); _subject.Parameters.Get("Clause1_P1").Should().Be(test); } @@ -164,9 +169,9 @@ namespace NzbDrone.Core.Test.Datastore public void where_in_list_2() { var list = new List { 1, 2, 3 }; - _subject = Where(x => x.CleanTitle == "test" && list.Contains(x.Id)); + _subject = WhereMeta(x => x.CleanTitle == "test" && list.Contains(x.Id)); - _subject.ToString().Should().Be($"((\"Movies\".\"CleanTitle\" = @Clause1_P1) AND (\"Movies\".\"Id\" IN (1, 2, 3)))"); + _subject.ToString().Should().Be($"((\"MovieMetadata\".\"CleanTitle\" = @Clause1_P1) AND (\"MovieMetadata\".\"Id\" IN (1, 2, 3)))"); } [Test] @@ -174,35 +179,35 @@ namespace NzbDrone.Core.Test.Datastore { var list = new List { "first", "second", "third" }; - _subject = Where(x => list.Contains(x.CleanTitle)); + _subject = WhereMeta(x => list.Contains(x.CleanTitle)); - _subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IN @Clause1_P1)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"CleanTitle\" IN @Clause1_P1)"); } [Test] public void enum_as_int() { - _subject = Where(x => x.Status == MovieStatusType.Announced); + _subject = WhereMeta(x => x.Status == MovieStatusType.Announced); - _subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @Clause1_P1)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" = @Clause1_P1)"); } [Test] public void enum_in_list() { var allowed = new List { MovieStatusType.Announced, MovieStatusType.InCinemas }; - _subject = Where(x => allowed.Contains(x.Status)); + _subject = WhereMeta(x => allowed.Contains(x.Status)); - _subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @Clause1_P1)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" IN @Clause1_P1)"); } [Test] public void enum_in_array() { var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas }; - _subject = Where(x => allowed.Contains(x.Status)); + _subject = WhereMeta(x => allowed.Contains(x.Status)); - _subject.ToString().Should().Be($"(\"Movies\".\"Status\" IN @Clause1_P1)"); + _subject.ToString().Should().Be($"(\"MovieMetadata\".\"Status\" IN @Clause1_P1)"); } } } diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs index c052c7b95..e69e0044c 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs @@ -53,7 +53,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests [TestCase(60, 1000, false)] public void single_episode(int runtime, int sizeInMegaBytes, bool expectedResult) { - _movie.Runtime = runtime; + _movie.MovieMetadata.Value.Runtime = runtime; _remoteMovie.Movie = _movie; _remoteMovie.Release.Size = sizeInMegaBytes.Megabytes(); @@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests [Test] public void should_return_true_if_size_is_zero() { - _movie.Runtime = 120; + _movie.MovieMetadata.Value.Runtime = 120; _remoteMovie.Movie = _movie; _remoteMovie.Release.Size = 0; _qualityType.MinSize = 10; @@ -75,7 +75,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests [Test] public void should_return_true_if_unlimited_30_minute() { - _movie.Runtime = 30; + _movie.MovieMetadata.Value.Runtime = 30; _remoteMovie.Movie = _movie; _remoteMovie.Release.Size = 18457280000; _qualityType.MaxSize = null; @@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests [Test] public void should_return_true_if_unlimited_60_minute() { - _movie.Runtime = 60; + _movie.MovieMetadata.Value.Runtime = 60; _remoteMovie.Movie = _movie; _remoteMovie.Release.Size = 36857280000; _qualityType.MaxSize = null; @@ -97,7 +97,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests [Test] public void should_use_110_minutes_if_runtime_is_0() { - _movie.Runtime = 0; + _movie.MovieMetadata.Value.Runtime = 0; _remoteMovie.Movie = _movie; _remoteMovie.Release.Size = 1095.Megabytes(); diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/LanguageSpecificationFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/LanguageSpecificationFixture.cs index a5d790b8c..688447681 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/LanguageSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/LanguageSpecificationFixture.cs @@ -31,7 +31,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests { Language = Language.English }, - OriginalLanguage = Language.French + MovieMetadata = new MovieMetadata + { + OriginalLanguage = Language.French + } } }; } diff --git a/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs b/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs index 8a04196d6..1cf77591d 100644 --- a/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs +++ b/src/NzbDrone.Core.Test/DecisionEngineTests/PrioritizeDownloadDecisionFixture.cs @@ -66,7 +66,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests MinFormatScore = 0 }) .With(m => m.Title = "A Movie") - .With(m => m.Runtime = runtime).Build(); + .With(m => m.MovieMetadata.Value.Runtime = runtime).Build(); remoteMovie.Release = new ReleaseInfo(); remoteMovie.Release.PublishDate = DateTime.Now.AddDays(-age); diff --git a/src/NzbDrone.Core.Test/HealthCheck/Checks/RemovedMovieCheckFixture.cs b/src/NzbDrone.Core.Test/HealthCheck/Checks/RemovedMovieCheckFixture.cs index 04b623a36..4e3faff6b 100644 --- a/src/NzbDrone.Core.Test/HealthCheck/Checks/RemovedMovieCheckFixture.cs +++ b/src/NzbDrone.Core.Test/HealthCheck/Checks/RemovedMovieCheckFixture.cs @@ -32,16 +32,16 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks { movie = Builder.CreateListOfSize(amount) .All() - .With(v => v.Status = MovieStatusType.Released) + .With(v => v.MovieMetadata.Value.Status = MovieStatusType.Released) .BuildList(); } else { movie = Builder.CreateListOfSize(amount) .All() - .With(v => v.Status = MovieStatusType.Released) + .With(v => v.MovieMetadata.Value.Status = MovieStatusType.Released) .Random(deleted) - .With(v => v.Status = MovieStatusType.Deleted) + .With(v => v.MovieMetadata.Value.Status = MovieStatusType.Deleted) .BuildList(); } diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitlesFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitlesFixture.cs index d8ec063ab..4b5a8aba4 100644 --- a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitlesFixture.cs +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitlesFixture.cs @@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers public void should_delete_orphaned_alternative_title_items() { var altTitle = Builder.CreateNew() - .With(h => h.MovieId = default) + .With(h => h.MovieMetadataId = default) .With(h => h.Language = Language.English) .BuildNew(); @@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers [Test] public void should_not_delete_unorphaned_alternative_title_items() { - var movie = Builder.CreateNew().BuildNew(); + var movieMetadata = Builder.CreateNew().BuildNew(); - Db.Insert(movie); + Db.Insert(movieMetadata); var altTitle = Builder.CreateNew() - .With(h => h.MovieId = default) + .With(h => h.MovieMetadataId = default) .With(h => h.Language = Language.English) - .With(b => b.MovieId = movie.Id) + .With(b => b.MovieMetadataId = movieMetadata.Id) .BuildNew(); Db.Insert(altTitle); diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedCreditsFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedCreditsFixture.cs index 219b47fb5..5b9f30ca0 100644 --- a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedCreditsFixture.cs +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedCreditsFixture.cs @@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers public void should_delete_orphaned_credit_items() { var credit = Builder.CreateNew() - .With(h => h.MovieId = default) + .With(h => h.MovieMetadataId = default) .With(h => h.Name = "Some Credit") .BuildNew(); @@ -27,14 +27,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers [Test] public void should_not_delete_unorphaned_credit_items() { - var movie = Builder.CreateNew().BuildNew(); + var movieMetadata = Builder.CreateNew().BuildNew(); - Db.Insert(movie); + Db.Insert(movieMetadata); var credit = Builder.CreateNew() - .With(h => h.MovieId = default) + .With(h => h.MovieMetadataId = default) .With(h => h.Name = "Some Credit") - .With(b => b.MovieId = movie.Id) + .With(b => b.MovieMetadataId = movieMetadata.Id) .BuildNew(); Db.Insert(credit); diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMovieMetadataFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMovieMetadataFixture.cs new file mode 100644 index 000000000..22a71af6a --- /dev/null +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMovieMetadataFixture.cs @@ -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 + { + [Test] + public void should_delete_orphaned_movie_metadata_items() + { + var metadata = Builder.CreateNew().BuildNew(); + + Db.Insert(metadata); + Subject.Clean(); + AllStoredModels.Should().BeEmpty(); + } + + [Test] + public void should_not_delete_unorphaned_movie_metadata_items() + { + var movieMetadata = Builder.CreateNew().BuildNew(); + + Db.Insert(movieMetadata); + + var movie = Builder.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.CreateNew().BuildNew(); + + Db.Insert(movieMetadata); + + var movie = Builder.CreateNew() + .With(b => b.MovieMetadataId = movieMetadata.Id) + .BuildNew(); + + Db.Insert(movie); + + Subject.Clean(); + AllStoredModels.Should().HaveCount(1); + } + } +} diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslationsFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslationsFixture.cs index b86512ac6..2d0ca5ebf 100644 --- a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslationsFixture.cs +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslationsFixture.cs @@ -16,7 +16,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers public void should_delete_orphaned_movie_translation_items() { var translation = Builder.CreateNew() - .With(h => h.MovieId = default) + .With(h => h.MovieMetadataId = default) .With(h => h.Language = Language.English) .BuildNew(); @@ -28,14 +28,14 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers [Test] public void should_not_delete_unorphaned_movie_translation_items() { - var movie = Builder.CreateNew().BuildNew(); + var movieMetadata = Builder.CreateNew().BuildNew(); - Db.Insert(movie); + Db.Insert(movieMetadata); var translation = Builder.CreateNew() - .With(h => h.MovieId = default) + .With(h => h.MovieMetadataId = default) .With(h => h.Language = Language.English) - .With(b => b.MovieId = movie.Id) + .With(b => b.MovieMetadataId = movieMetadata.Id) .BuildNew(); Db.Insert(translation); diff --git a/src/NzbDrone.Core.Test/ImportListTests/FetchAndParseImportListServiceFixture.cs b/src/NzbDrone.Core.Test/ImportListTests/FetchAndParseImportListServiceFixture.cs index 0a5c67d3f..ae1e92b57 100644 --- a/src/NzbDrone.Core.Test/ImportListTests/FetchAndParseImportListServiceFixture.cs +++ b/src/NzbDrone.Core.Test/ImportListTests/FetchAndParseImportListServiceFixture.cs @@ -38,8 +38,8 @@ namespace NzbDrone.Core.Test.ImportListTests .Build().ToList(); Mocker.GetMock() - .Setup(v => v.MapMovieToTmdbMovie(It.IsAny())) - .Returns(m => new Movie { TmdbId = m.TmdbId }); + .Setup(v => v.MapMovieToTmdbMovie(It.IsAny())) + .Returns(m => new MovieMetadata { TmdbId = m.TmdbId }); } private void GivenList(int id, bool enabled, bool enabledAuto, ImportListFetchResult fetchResult) diff --git a/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs b/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs index a27ababb7..ba11c4355 100644 --- a/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs @@ -27,7 +27,7 @@ namespace NzbDrone.Core.Test.MediaCoverTests _movie = Builder.CreateNew() .With(v => v.Id = 2) - .With(v => v.Images = new List { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") }) + .With(v => v.MovieMetadata.Value.Images = new List { new MediaCover.MediaCover(MediaCoverTypes.Poster, "") }) .Build(); Mocker.GetMock().Setup(m => m.GetMovie(It.Is(id => id == _movie.Id))).Returns(_movie); diff --git a/src/NzbDrone.Core.Test/MediaFiles/DownloadedMoviesImportServiceFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/DownloadedMoviesImportServiceFixture.cs index 92bb398da..fc2608b1a 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/DownloadedMoviesImportServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/DownloadedMoviesImportServiceFixture.cs @@ -255,7 +255,7 @@ namespace NzbDrone.Core.Test.MediaFiles .Returns(imported.Select(i => new ImportResult(i)).ToList()); Mocker.GetMock() - .Setup(s => s.IsSample(It.IsAny(), + .Setup(s => s.IsSample(It.IsAny(), It.IsAny())) .Returns(DetectSampleResult.Sample); @@ -324,7 +324,7 @@ namespace NzbDrone.Core.Test.MediaFiles .Returns(imported.Select(i => new ImportResult(i)).ToList()); Mocker.GetMock() - .Setup(s => s.IsSample(It.IsAny(), + .Setup(s => s.IsSample(It.IsAny(), It.IsAny())) .Returns(DetectSampleResult.Sample); @@ -431,7 +431,7 @@ namespace NzbDrone.Core.Test.MediaFiles .Returns(new List()); Mocker.GetMock() - .Setup(s => s.IsSample(It.IsAny(), + .Setup(s => s.IsSample(It.IsAny(), It.IsAny())) .Returns(DetectSampleResult.Sample); diff --git a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguageFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguageFixture.cs index 32adde708..08fd6d338 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguageFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguageFixture.cs @@ -24,7 +24,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators public void Setup() { _movie = Builder.CreateNew() - .With(m => m.OriginalLanguage = Language.English) + .With(m => m.MovieMetadata.Value.OriginalLanguage = Language.English) .Build(); _localMovie = Builder.CreateNew() @@ -72,7 +72,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport.Aggregation.Aggregators { var result = Subject.Aggregate(_localMovie, null, false); - result.Languages.Should().Contain(_movie.OriginalLanguage); + result.Languages.Should().Contain(_movie.MovieMetadata.Value.OriginalLanguage); } [Test] diff --git a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/DetectSampleFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/DetectSampleFixture.cs index 8975a164c..8091fbcc8 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MovieImport/DetectSampleFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MovieImport/DetectSampleFixture.cs @@ -16,20 +16,20 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport [TestFixture] public class DetectSampleFixture : CoreTest { - private Movie _movie; + private MovieMetadata _movie; private LocalMovie _localMovie; [SetUp] public void Setup() { - _movie = Builder.CreateNew() + _movie = Builder.CreateNew() .With(s => s.Runtime = 30) .Build(); _localMovie = new LocalMovie { Path = @"C:\Test\30 Rock\30.rock.s01e01.avi", - Movie = _movie, + Movie = new Movie { MovieMetadata = _movie }, Quality = new QualityModel(Quality.HDTV720p) }; } @@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport { GivenRuntime(120); - Subject.IsSample(_localMovie.Movie, + Subject.IsSample(_localMovie.Movie.MovieMetadata, _localMovie.Path); Mocker.GetMock().Verify(v => v.GetRunTime(It.IsAny()), Times.Once()); @@ -152,7 +152,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport .Setup(s => s.GetRunTime(It.IsAny())) .Returns((TimeSpan?)null); - Subject.IsSample(_localMovie.Movie, + Subject.IsSample(_localMovie.Movie.MovieMetadata, _localMovie.Path).Should().Be(DetectSampleResult.Indeterminate); ExceptionVerification.ExpectedErrors(1); @@ -160,13 +160,13 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport private void ShouldBeSample() { - Subject.IsSample(_localMovie.Movie, + Subject.IsSample(_localMovie.Movie.MovieMetadata, _localMovie.Path).Should().Be(DetectSampleResult.Sample); } private void ShouldBeNotSample() { - Subject.IsSample(_localMovie.Movie, + Subject.IsSample(_localMovie.Movie.MovieMetadata, _localMovie.Path).Should().Be(DetectSampleResult.NotSample); } } diff --git a/src/NzbDrone.Core.Test/MetadataSource/SkyHook/SkyHookProxyFixture.cs b/src/NzbDrone.Core.Test/MetadataSource/SkyHook/SkyHookProxyFixture.cs index 3b7b59cdc..d551b4295 100644 --- a/src/NzbDrone.Core.Test/MetadataSource/SkyHook/SkyHookProxyFixture.cs +++ b/src/NzbDrone.Core.Test/MetadataSource/SkyHook/SkyHookProxyFixture.cs @@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook details.Title.Should().Be(title); } - private void ValidateMovie(Movie movie) + private void ValidateMovie(MovieMetadata movie) { movie.Should().NotBeNull(); movie.Title.Should().NotBeNullOrWhiteSpace(); @@ -41,7 +41,6 @@ namespace NzbDrone.Core.Test.MetadataSource.SkyHook movie.ImdbId.Should().NotBeNullOrWhiteSpace(); movie.Studio.Should().NotBeNullOrWhiteSpace(); movie.Runtime.Should().BeGreaterThan(0); - movie.TitleSlug.Should().NotBeNullOrWhiteSpace(); //series.TvRageId.Should().BeGreaterThan(0); movie.TmdbId.Should().BeGreaterThan(0); diff --git a/src/NzbDrone.Core.Test/MovieTests/AddMovieFixture.cs b/src/NzbDrone.Core.Test/MovieTests/AddMovieFixture.cs index 676194a6f..1652da06c 100644 --- a/src/NzbDrone.Core.Test/MovieTests/AddMovieFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/AddMovieFixture.cs @@ -20,14 +20,13 @@ namespace NzbDrone.Core.Test.MovieTests [TestFixture] public class AddMovieFixture : CoreTest { - private Movie _fakeMovie; + private MovieMetadata _fakeMovie; [SetUp] public void Setup() { - _fakeMovie = Builder + _fakeMovie = Builder .CreateNew() - .With(s => s.Path = null) .Build(); } @@ -35,7 +34,7 @@ namespace NzbDrone.Core.Test.MovieTests { Mocker.GetMock() .Setup(s => s.GetMovieInfo(tmdbId)) - .Returns(new Tuple>(_fakeMovie, new List())); + .Returns(new Tuple>(_fakeMovie, new List())); } private void GivenValidPath() diff --git a/src/NzbDrone.Core.Test/MovieTests/AlternativeTitleServiceTests/AlternativeTitleServiceFixture.cs b/src/NzbDrone.Core.Test/MovieTests/AlternativeTitleServiceTests/AlternativeTitleServiceFixture.cs index 6b3159384..b6cee1767 100644 --- a/src/NzbDrone.Core.Test/MovieTests/AlternativeTitleServiceTests/AlternativeTitleServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/AlternativeTitleServiceTests/AlternativeTitleServiceFixture.cs @@ -18,16 +18,17 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests private AlternativeTitle _title2; private AlternativeTitle _title3; - private Movie _movie; + private MovieMetadata _movie; [SetUp] public void Setup() { - var titles = Builder.CreateListOfSize(3).All().With(t => t.MovieId = 0).Build(); + var titles = Builder.CreateListOfSize(3).All().With(t => t.MovieMetadataId = 0).Build(); _title1 = titles[0]; _title2 = titles[1]; _title3 = titles[2]; - _movie = Builder.CreateNew() + + _movie = Builder.CreateNew() .With(m => m.CleanTitle = "myothertitle") .With(m => m.Id = 1) .Build(); @@ -35,7 +36,7 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests private void GivenExistingTitles(params AlternativeTitle[] titles) { - Mocker.GetMock().Setup(r => r.FindByMovieId(_movie.Id)) + Mocker.GetMock().Setup(r => r.FindByMovieMetadataId(_movie.Id)) .Returns(titles.ToList()); } @@ -72,7 +73,7 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests { GivenExistingTitles(); var titles = new List { _title1 }; - var movie = Builder.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build(); + var movie = Builder.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build(); Subject.UpdateTitles(titles, movie); @@ -87,8 +88,8 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests Subject.UpdateTitles(titles, _movie); - _title1.MovieId.Should().Be(_movie.Id); - _title2.MovieId.Should().Be(_movie.Id); + _title1.MovieMetadataId.Should().Be(_movie.Id); + _title2.MovieMetadataId.Should().Be(_movie.Id); } [Test] diff --git a/src/NzbDrone.Core.Test/MovieTests/CreditTests/CreditRepositoryFixture.cs b/src/NzbDrone.Core.Test/MovieTests/CreditTests/CreditRepositoryFixture.cs index 2a9559ce7..6d8d6289d 100644 --- a/src/NzbDrone.Core.Test/MovieTests/CreditTests/CreditRepositoryFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/CreditTests/CreditRepositoryFixture.cs @@ -32,18 +32,18 @@ namespace NzbDrone.Core.Test.MovieTests.CreditTests var credits = Builder.CreateListOfSize(5) .TheFirst(1) .With(c => c.Id = 0) - .With(c => c.MovieId = _movie2.Id) + .With(c => c.MovieMetadataId = _movie2.Id) .TheRest() .With(c => c.Id = 0) - .With(c => c.MovieId = _movie1.Id) + .With(c => c.MovieMetadataId = _movie1.Id) .BuildListOfNew(); Db.InsertMany(credits); Subject.DeleteForMovies(new List { _movie1.Id }); - var removedMovieCredits = Subject.FindByMovieId(_movie1.Id); - var nonRemovedMovieCredits = Subject.FindByMovieId(_movie2.Id); + var removedMovieCredits = Subject.FindByMovieMetadataId(_movie1.Id); + var nonRemovedMovieCredits = Subject.FindByMovieMetadataId(_movie2.Id); removedMovieCredits.Should().HaveCount(0); nonRemovedMovieCredits.Should().HaveCount(1); diff --git a/src/NzbDrone.Core.Test/MovieTests/CreditTests/CreditServiceFixture.cs b/src/NzbDrone.Core.Test/MovieTests/CreditTests/CreditServiceFixture.cs index 00a276e5a..46461a46b 100644 --- a/src/NzbDrone.Core.Test/MovieTests/CreditTests/CreditServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/CreditTests/CreditServiceFixture.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; @@ -18,25 +18,25 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests private Credit _credit2; private Credit _credit3; - private Movie _movie; + private MovieMetadata _movie; [SetUp] public void Setup() { var credits = Builder.CreateListOfSize(3) .All() - .With(t => t.MovieId = 0).Build(); + .With(t => t.MovieMetadataId = 0).Build(); _credit1 = credits[0]; _credit2 = credits[1]; _credit3 = credits[2]; - _movie = Builder.CreateNew().With(m => m.Id = 1).Build(); + _movie = Builder.CreateNew().With(m => m.Id = 1).Build(); } private void GivenExistingCredits(params Credit[] credits) { - Mocker.GetMock().Setup(r => r.FindByMovieId(_movie.Id)) + Mocker.GetMock().Setup(r => r.FindByMovieMetadataId(_movie.Id)) .Returns(credits.ToList()); } @@ -77,8 +77,8 @@ namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests Subject.UpdateCredits(titles, _movie); - _credit1.MovieId.Should().Be(_movie.Id); - _credit2.MovieId.Should().Be(_movie.Id); + _credit1.MovieMetadataId.Should().Be(_movie.Id); + _credit2.MovieMetadataId.Should().Be(_movie.Id); } [Test] diff --git a/src/NzbDrone.Core.Test/MovieTests/MovieIsAvailableFixture.cs b/src/NzbDrone.Core.Test/MovieTests/MovieIsAvailableFixture.cs index 7a824d068..930089c44 100644 --- a/src/NzbDrone.Core.Test/MovieTests/MovieIsAvailableFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/MovieIsAvailableFixture.cs @@ -21,9 +21,9 @@ namespace NzbDrone.Core.Test.MovieTests private void SetMovieProperties(DateTime? cinema, DateTime? physical, DateTime? digital, MovieStatusType minimumAvailability) { - _movie.InCinemas = cinema; - _movie.PhysicalRelease = physical; - _movie.DigitalRelease = digital; + _movie.MovieMetadata.Value.InCinemas = cinema; + _movie.MovieMetadata.Value.PhysicalRelease = physical; + _movie.MovieMetadata.Value.DigitalRelease = digital; _movie.MinimumAvailability = minimumAvailability; } diff --git a/src/NzbDrone.Core.Test/MovieTests/MovieMetadataRepositoryTests/MovieMetadataRepositoryFixture.cs b/src/NzbDrone.Core.Test/MovieTests/MovieMetadataRepositoryTests/MovieMetadataRepositoryFixture.cs new file mode 100644 index 000000000..128778b19 --- /dev/null +++ b/src/NzbDrone.Core.Test/MovieTests/MovieMetadataRepositoryTests/MovieMetadataRepositoryFixture.cs @@ -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 + { + private MovieMetadataRepository _movieMetadataRepo; + private List _metadataList; + + [SetUp] + public void Setup() + { + _movieMetadataRepo = Mocker.Resolve(); + _metadataList = Builder.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); + } + } +} diff --git a/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/FindByTitleFixture.cs b/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/FindByTitleFixture.cs index dd58b79cf..fb67e73df 100644 --- a/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/FindByTitleFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/MovieServiceTests/FindByTitleFixture.cs @@ -19,15 +19,15 @@ namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests { _candidates = Builder.CreateListOfSize(3) .TheFirst(1) - .With(x => x.CleanTitle = "batman") + .With(x => x.MovieMetadata.Value.CleanTitle = "batman") .With(x => x.Year = 2000) .TheNext(1) - .With(x => x.CleanTitle = "batman") + .With(x => x.MovieMetadata.Value.CleanTitle = "batman") .With(x => x.Year = 1999) .TheRest() - .With(x => x.CleanTitle = "darkknight") + .With(x => x.MovieMetadata.Value.CleanTitle = "darkknight") .With(x => x.Year = 2008) - .With(x => x.AlternativeTitles = new List + .With(x => x.MovieMetadata.Value.AlternativeTitles = new List { new AlternativeTitle { diff --git a/src/NzbDrone.Core.Test/MovieTests/MovieTitleSlugValidatorFixture.cs b/src/NzbDrone.Core.Test/MovieTests/MovieTitleSlugValidatorFixture.cs deleted file mode 100644 index a1ad376fc..000000000 --- a/src/NzbDrone.Core.Test/MovieTests/MovieTitleSlugValidatorFixture.cs +++ /dev/null @@ -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 - { - private List _movies; - private TestValidator _validator; - - [SetUp] - public void Setup() - { - _movies = Builder.CreateListOfSize(1) - .Build() - .ToList(); - - _validator = new TestValidator - { - v => v.RuleFor(s => s.TitleSlug).SetValidator(Subject) - }; - - Mocker.GetMock() - .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() - .Setup(s => s.GetMovie(_movies.First().Id)) - .Returns(_movies.First()); - - var movie = Builder.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.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.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(); - } - } -} diff --git a/src/NzbDrone.Core.Test/MovieTests/RefreshMovieServiceFixture.cs b/src/NzbDrone.Core.Test/MovieTests/RefreshMovieServiceFixture.cs index 12a309494..8acb3706c 100644 --- a/src/NzbDrone.Core.Test/MovieTests/RefreshMovieServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/RefreshMovieServiceFixture.cs @@ -18,17 +18,26 @@ namespace NzbDrone.Core.Test.MovieTests [TestFixture] public class RefreshMovieServiceFixture : CoreTest { - private Movie _movie; + private MovieMetadata _movie; + private Movie _existingMovie; [SetUp] public void Setup() { - _movie = Builder.CreateNew() + _movie = Builder.CreateNew() .With(s => s.Status = MovieStatusType.Released) .Build(); + _existingMovie = Builder.CreateNew() + .With(s => s.MovieMetadata.Value.Status = MovieStatusType.Released) + .Build(); + Mocker.GetMock() .Setup(s => s.GetMovie(_movie.Id)) + .Returns(_existingMovie); + + Mocker.GetMock() + .Setup(s => s.Get(_movie.Id)) .Returns(_movie); Mocker.GetMock() @@ -36,11 +45,11 @@ namespace NzbDrone.Core.Test.MovieTests .Callback((i) => { throw new MovieNotFoundException(i); }); } - private void GivenNewMovieInfo(Movie movie) + private void GivenNewMovieInfo(MovieMetadata movie) { Mocker.GetMock() .Setup(s => s.GetMovieInfo(_movie.TmdbId)) - .Returns(new Tuple>(movie, new List())); + .Returns(new Tuple>(movie, new List())); } [Test] @@ -53,8 +62,8 @@ namespace NzbDrone.Core.Test.MovieTests Subject.Execute(new RefreshMovieCommand(new List { _movie.Id })); - Mocker.GetMock() - .Verify(v => v.UpdateMovie(It.Is>(s => s.First().ImdbId == newMovieInfo.ImdbId), true)); + Mocker.GetMock() + .Verify(v => v.Upsert(It.Is(s => s.ImdbId == newMovieInfo.ImdbId))); } [Test] @@ -62,8 +71,8 @@ namespace NzbDrone.Core.Test.MovieTests { Subject.Execute(new RefreshMovieCommand(new List { _movie.Id })); - Mocker.GetMock() - .Verify(v => v.UpdateMovie(It.Is(s => s.Status == MovieStatusType.Deleted)), Times.Once()); + Mocker.GetMock() + .Verify(v => v.Upsert(It.Is(s => s.Status == MovieStatusType.Deleted)), Times.Once()); ExceptionVerification.ExpectedErrors(1); } @@ -78,8 +87,8 @@ namespace NzbDrone.Core.Test.MovieTests Subject.Execute(new RefreshMovieCommand(new List { _movie.Id })); - Mocker.GetMock() - .Verify(v => v.UpdateMovie(It.Is>(s => s.First().TmdbId == newMovieInfo.TmdbId), true)); + Mocker.GetMock() + .Verify(v => v.Upsert(It.Is(s => s.TmdbId == newMovieInfo.TmdbId))); ExceptionVerification.ExpectedWarns(1); } @@ -89,8 +98,8 @@ namespace NzbDrone.Core.Test.MovieTests { Subject.Execute(new RefreshMovieCommand(new List { _movie.Id })); - Mocker.GetMock() - .Verify(v => v.UpdateMovie(It.Is(s => s.Status == MovieStatusType.Deleted)), Times.Once()); + Mocker.GetMock() + .Verify(v => v.Upsert(It.Is(s => s.Status == MovieStatusType.Deleted)), Times.Once()); ExceptionVerification.ExpectedErrors(1); } @@ -102,8 +111,8 @@ namespace NzbDrone.Core.Test.MovieTests Subject.Execute(new RefreshMovieCommand(new List { _movie.Id })); - Mocker.GetMock() - .Verify(v => v.UpdateMovie(It.IsAny()), Times.Never()); + Mocker.GetMock() + .Verify(v => v.Upsert(It.IsAny()), Times.Never()); ExceptionVerification.ExpectedErrors(1); } diff --git a/src/NzbDrone.Core.Test/MovieTests/ShouldRefreshMovieFixture.cs b/src/NzbDrone.Core.Test/MovieTests/ShouldRefreshMovieFixture.cs index 1a7ed61e8..c8c285777 100644 --- a/src/NzbDrone.Core.Test/MovieTests/ShouldRefreshMovieFixture.cs +++ b/src/NzbDrone.Core.Test/MovieTests/ShouldRefreshMovieFixture.cs @@ -10,12 +10,12 @@ namespace NzbDrone.Core.Test.MovieTests [TestFixture] public class ShouldRefreshMovieFixture : TestBase { - private Movie _movie; + private MovieMetadata _movie; [SetUp] public void Setup() { - _movie = Builder.CreateNew() + _movie = Builder.CreateNew() .With(v => v.Status = MovieStatusType.InCinemas) .With(m => m.PhysicalRelease = DateTime.Today.AddDays(-100)) .Build(); diff --git a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs index 03fc31c5d..f24756c5b 100644 --- a/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs +++ b/src/NzbDrone.Core.Test/OrganizerTests/FileNameBuilderTests/FileNameBuilderFixture.cs @@ -50,7 +50,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests _movie = Builder .CreateNew() .With(s => s.Title = "South Park") - .With(s => s.OriginalTitle = "South of the Park") + .With(s => s.MovieMetadata.Value.OriginalTitle = "South of the Park") .Build(); _namingConfig = NamingConfig.Default; @@ -206,7 +206,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests public void should_replace_movie_original_title() { _namingConfig.StandardMovieFormat = "{Movie OriginalTitle}"; - _movie.OriginalTitle = "South of the Park"; + _movie.MovieMetadata.Value.OriginalTitle = "South of the Park"; Subject.BuildFileName(_movie, _movieFile) .Should().Be("South of the Park"); @@ -216,7 +216,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests public void should_replace_movie_certification() { _namingConfig.StandardMovieFormat = "{Movie Certification}"; - _movie.Certification = "R"; + _movie.MovieMetadata.Value.Certification = "R"; Subject.BuildFileName(_movie, _movieFile) .Should().Be("R"); @@ -226,7 +226,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests public void should_replace_movie_collection() { _namingConfig.StandardMovieFormat = "{Movie Collection}"; - _movie.Collection = new MovieCollection { Name = "South Part Collection" }; + _movie.MovieMetadata.Value.Collection = new MovieCollection { Name = "South Part Collection" }; Subject.BuildFileName(_movie, _movieFile) .Should().Be("South Part Collection"); diff --git a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/AugmentersTests/AugmentWithOriginalLanguageFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/AugmentersTests/AugmentWithOriginalLanguageFixture.cs index 3c44acdbb..7a149db9a 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/AugmentersTests/AugmentWithOriginalLanguageFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/AugmentersTests/AugmentWithOriginalLanguageFixture.cs @@ -16,7 +16,10 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests var releaseInfo = new ParsedMovieInfo(); var movie = new Movies.Movie { - OriginalLanguage = Language.English + MovieMetadata = new Movies.MovieMetadata + { + OriginalLanguage = Language.English + } }; var result = Subject.AugmentMovieInfo(releaseInfo, movie); result.ExtraInfo.Should().ContainKey("OriginalLanguage"); diff --git a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs index 86ef79d54..eed7a7ab7 100644 --- a/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs +++ b/src/NzbDrone.Core.Test/ParserTests/ParsingServiceTests/MapFixture.cs @@ -36,11 +36,11 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests { _movie = Builder.CreateNew() .With(m => m.Title = "Fack Ju Göthe 2") - .With(m => m.CleanTitle = "fackjugoethe2") + .With(m => m.MovieMetadata.Value.CleanTitle = "fackjugoethe2") .With(m => m.Year = 2015) - .With(m => m.AlternativeTitles = new List { new AlternativeTitle("Fack Ju Göthe 2: Same same") }) - .With(m => m.Translations = new List { new MovieTranslation { Title = "Translated Title", CleanTitle = "translatedtitle" } }) - .With(m => m.OriginalLanguage = Language.English) + .With(m => m.MovieMetadata.Value.AlternativeTitles = new List { new AlternativeTitle("Fack Ju Göthe 2: Same same") }) + .With(m => m.MovieMetadata.Value.Translations = new List { new MovieTranslation { Title = "Translated Title", CleanTitle = "translatedtitle" } }) + .With(m => m.MovieMetadata.Value.OriginalLanguage = Language.English) .Build(); _parsedMovieInfo = new ParsedMovieInfo @@ -66,14 +66,14 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests _alternativeTitleInfo = new ParsedMovieInfo { - MovieTitles = new List { _movie.AlternativeTitles.First().Title }, + MovieTitles = new List { _movie.MovieMetadata.Value.AlternativeTitles.First().Title }, Languages = new List { Language.English }, Year = _movie.Year, }; _translationTitleInfo = new ParsedMovieInfo { - MovieTitles = new List { _movie.Translations.First().Title }, + MovieTitles = new List { _movie.MovieMetadata.Value.Translations.First().Title }, Languages = new List { Language.English }, Year = _movie.Year, }; diff --git a/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs b/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs index b7929f7a5..b4e74bc74 100644 --- a/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs +++ b/src/NzbDrone.Core/CustomFormats/CustomFormatCalculationService.cs @@ -76,20 +76,20 @@ namespace NzbDrone.Core.CustomFormats var info = new ParsedMovieInfo { - MovieTitles = new List() { movieFile.Movie.Title }, + MovieTitles = new List() { movieFile.Movie.MovieMetadata.Value.Title }, SimpleReleaseTitle = sceneName.SimplifyReleaseTitle(), Quality = movieFile.Quality, Languages = movieFile.Languages, ReleaseGroup = movieFile.ReleaseGroup, Edition = movieFile.Edition, - Year = movieFile.Movie.Year, - ImdbId = movieFile.Movie.ImdbId, + Year = movieFile.Movie.MovieMetadata.Value.Year, + ImdbId = movieFile.Movie.MovieMetadata.Value.ImdbId, ExtraInfo = new Dictionary { { "IndexerFlags", movieFile.IndexerFlags }, { "Size", movieFile.Size }, { "Filename", Path.GetFileName(movieFile.RelativePath) }, - { "OriginalLanguage", movieFile.Movie.OriginalLanguage } + { "OriginalLanguage", movieFile.Movie.MovieMetadata.Value.OriginalLanguage } } }; @@ -114,14 +114,14 @@ namespace NzbDrone.Core.CustomFormats var info = new ParsedMovieInfo { - MovieTitles = new List() { movie.Title }, + MovieTitles = new List() { movie.MovieMetadata.Value.Title }, SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? blocklist.SourceTitle.SimplifyReleaseTitle(), Quality = blocklist.Quality, Languages = blocklist.Languages, ReleaseGroup = parsed?.ReleaseGroup, Edition = parsed?.Edition, - Year = movie.Year, - ImdbId = movie.ImdbId, + Year = movie.MovieMetadata.Value.Year, + ImdbId = movie.MovieMetadata.Value.ImdbId, ExtraInfo = new Dictionary { { "IndexerFlags", blocklist.IndexerFlags }, @@ -142,14 +142,14 @@ namespace NzbDrone.Core.CustomFormats var info = new ParsedMovieInfo { - MovieTitles = new List() { movie.Title }, + MovieTitles = new List() { movie.MovieMetadata.Value.Title }, SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? history.SourceTitle.SimplifyReleaseTitle(), Quality = history.Quality, Languages = history.Languages, ReleaseGroup = parsed?.ReleaseGroup, Edition = parsed?.Edition, - Year = movie.Year, - ImdbId = movie.ImdbId, + Year = movie.MovieMetadata.Value.Year, + ImdbId = movie.MovieMetadata.Value.ImdbId, ExtraInfo = new Dictionary { { "IndexerFlags", flags }, diff --git a/src/NzbDrone.Core/Datastore/Extensions/BuilderExtensions.cs b/src/NzbDrone.Core/Datastore/Extensions/BuilderExtensions.cs index b7fc3df98..e48ef63fc 100644 --- a/src/NzbDrone.Core/Datastore/Extensions/BuilderExtensions.cs +++ b/src/NzbDrone.Core/Datastore/Extensions/BuilderExtensions.cs @@ -47,13 +47,6 @@ namespace NzbDrone.Core.Datastore return builder.Where(wb.ToString(), wb.Parameters); } - public static SqlBuilder WherePostgres(this SqlBuilder builder, Expression> filter) - { - var wb = new WhereBuilderPostgres(filter, true, builder.Sequence); - - return builder.Where(wb.ToString(), wb.Parameters); - } - public static SqlBuilder OrWhere(this SqlBuilder builder, Expression> filter) { var wb = GetWhereBuilder(builder.DatabaseType, filter, true, builder.Sequence); diff --git a/src/NzbDrone.Core/Datastore/Migration/207_movie_metadata.cs b/src/NzbDrone.Core/Datastore/Migration/207_movie_metadata.cs new file mode 100644 index 000000000..e15bb2e87 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/207_movie_metadata.cs @@ -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"); + } + } +} diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index 0e00abae0..cc609e986 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -109,9 +109,18 @@ namespace NzbDrone.Core.Datastore Mapper.Entity("Movies").RegisterModel() .Ignore(s => s.RootFolderPath) - .Ignore(s => s.Translations); + .Ignore(s => s.Title) + .Ignore(s => s.Year) + .Ignore(s => s.TmdbId) + .Ignore(s => s.ImdbId) + .HasOne(a => a.MovieMetadata, a => a.MovieMetadataId); - Mapper.Entity("ImportListMovies").RegisterModel(); + Mapper.Entity("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("AlternativeTitles").RegisterModel(); @@ -156,6 +165,9 @@ namespace NzbDrone.Core.Datastore Mapper.Entity("DownloadHistory").RegisterModel(); Mapper.Entity("UpdateHistory").RegisterModel(); + + Mapper.Entity("MovieMetadata").RegisterModel() + .Ignore(s => s.Translations); } private static void RegisterMappers() diff --git a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs index bc11d86e9..64873fb2e 100644 --- a/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs +++ b/src/NzbDrone.Core/DecisionEngine/DownloadDecisionComparer.cs @@ -174,9 +174,9 @@ namespace NzbDrone.Core.DecisionEngine var preferredSize = _qualityDefinitionService.Get(remoteMovie.ParsedMovieInfo.Quality.Quality).PreferredSize; // If no value for preferred it means unlimited so fallback to sort largest is best - if (preferredSize.HasValue && remoteMovie.Movie.Runtime > 0) + if (preferredSize.HasValue && remoteMovie.Movie.MovieMetadata.Value.Runtime > 0) { - var preferredMovieSize = remoteMovie.Movie.Runtime * preferredSize.Value.Megabytes(); + var preferredMovieSize = remoteMovie.Movie.MovieMetadata.Value.Runtime * preferredSize.Value.Megabytes(); // Calculate closest to the preferred size return Math.Abs((remoteMovie.Release.Size - preferredMovieSize).Round(200.Megabytes())) * (-1); diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs index 87b171fb3..8ca4a2c98 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs @@ -34,10 +34,10 @@ namespace NzbDrone.Core.DecisionEngine.Specifications var qualityDefinition = _qualityDefinitionService.Get(quality); - if (subject.Movie.Runtime == 0) + if (subject.Movie.MovieMetadata.Value.Runtime == 0) { _logger.Warn("{0} has no runtime information using median movie runtime of 110 minutes.", subject.Movie); - subject.Movie.Runtime = 110; + subject.Movie.MovieMetadata.Value.Runtime = 110; } if (qualityDefinition.MinSize.HasValue) @@ -45,7 +45,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications var minSize = qualityDefinition.MinSize.Value.Megabytes(); //Multiply maxSize by Series.Runtime - minSize = minSize * subject.Movie.Runtime; + minSize = minSize * subject.Movie.MovieMetadata.Value.Runtime; //If the parsed size is smaller than minSize we don't want it if (subject.Release.Size < minSize) @@ -61,7 +61,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications { _logger.Debug("Max size is unlimited, skipping check"); } - else if (subject.Movie.Runtime == 0) + else if (subject.Movie.MovieMetadata.Value.Runtime == 0) { _logger.Debug("Movie runtime is 0, unable to validate size until it is available, rejecting"); return Decision.Reject("Movie runtime is 0, unable to validate size until it is available"); @@ -71,7 +71,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications var maxSize = qualityDefinition.MaxSize.Value.Megabytes(); //Multiply maxSize by Series.Runtime - maxSize = maxSize * subject.Movie.Runtime; + maxSize = maxSize * subject.Movie.MovieMetadata.Value.Runtime; //If the parsed size is greater than maxSize we don't want it if (subject.Release.Size > maxSize) diff --git a/src/NzbDrone.Core/DecisionEngine/Specifications/LanguageSpecification.cs b/src/NzbDrone.Core/DecisionEngine/Specifications/LanguageSpecification.cs index dfeb080ad..45cf657ba 100644 --- a/src/NzbDrone.Core/DecisionEngine/Specifications/LanguageSpecification.cs +++ b/src/NzbDrone.Core/DecisionEngine/Specifications/LanguageSpecification.cs @@ -27,7 +27,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications return Decision.Accept(); } - var originalLanguage = subject.Movie.OriginalLanguage; + var originalLanguage = subject.Movie.MovieMetadata.Value.OriginalLanguage; if (wantedLanguage == Language.Original) { diff --git a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs index b04c5d632..22a7bbb38 100644 --- a/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs +++ b/src/NzbDrone.Core/Download/Clients/Deluge/Deluge.cs @@ -68,7 +68,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge _proxy.SetTorrentLabel(actualHash, Settings.MovieCategory, Settings); } - var isRecentMovie = remoteMovie.Movie.IsRecentMovie; + var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie; if ((isRecentMovie && Settings.RecentMoviePriority == (int)DelugePriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)DelugePriority.First)) @@ -95,7 +95,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge _proxy.SetTorrentLabel(actualHash, Settings.MovieCategory, Settings); } - var isRecentMovie = remoteMovie.Movie.IsRecentMovie; + var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie; if ((isRecentMovie && Settings.RecentMoviePriority == (int)DelugePriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)DelugePriority.First)) diff --git a/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs b/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs index d0642a943..3ae3fa7b1 100644 --- a/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs +++ b/src/NzbDrone.Core/Download/Clients/Flood/Flood.cs @@ -52,7 +52,7 @@ namespace NzbDrone.Core.Download.Clients.Flood switch (additionalTag) { case (int)AdditionalTags.Collection: - result.Add(remoteMovie.Movie.Collection.Name); + result.Add(remoteMovie.Movie.MovieMetadata.Value.Collection.Name); break; case (int)AdditionalTags.Quality: result.Add(remoteMovie.ParsedMovieInfo.Quality.Quality.ToString()); @@ -70,7 +70,7 @@ namespace NzbDrone.Core.Download.Clients.Flood result.Add(remoteMovie.Release.Indexer); break; case (int)AdditionalTags.Studio: - result.Add(remoteMovie.Movie.Studio); + result.Add(remoteMovie.Movie.MovieMetadata.Value.Studio); break; default: throw new DownloadClientException("Unexpected additional tag ID"); diff --git a/src/NzbDrone.Core/Download/Clients/NzbVortex/NzbVortex.cs b/src/NzbDrone.Core/Download/Clients/NzbVortex/NzbVortex.cs index 06e737aca..78095e818 100644 --- a/src/NzbDrone.Core/Download/Clients/NzbVortex/NzbVortex.cs +++ b/src/NzbDrone.Core/Download/Clients/NzbVortex/NzbVortex.cs @@ -34,7 +34,7 @@ namespace NzbDrone.Core.Download.Clients.NzbVortex protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContents) { - var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority; + var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority; var response = _proxy.DownloadNzb(fileContents, filename, priority, Settings); diff --git a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs index c9c4d1da4..e19ed88b4 100644 --- a/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs +++ b/src/NzbDrone.Core/Download/Clients/Nzbget/Nzbget.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Download.Clients.Nzbget { var category = Settings.MovieCategory; - var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority; + var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority; var addpaused = Settings.AddPaused; var response = _proxy.DownloadNzb(fileContent, filename, category, priority, addpaused, Settings); diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs index da4ddfa48..e411c4076 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs @@ -73,7 +73,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent var setShareLimits = remoteMovie.SeedConfiguration != null && (remoteMovie.SeedConfiguration.Ratio.HasValue || remoteMovie.SeedConfiguration.SeedTime.HasValue); var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1); - var isRecentMovie = remoteMovie.Movie.IsRecentMovie; + var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie; var moveToTop = (isRecentMovie && Settings.RecentMoviePriority == (int)QBittorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)QBittorrentPriority.First); var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart; @@ -132,7 +132,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent { var setShareLimits = remoteMovie.SeedConfiguration != null && (remoteMovie.SeedConfiguration.Ratio.HasValue || remoteMovie.SeedConfiguration.SeedTime.HasValue); var addHasSetShareLimits = setShareLimits && ProxyApiVersion >= new Version(2, 8, 1); - var isRecentMovie = remoteMovie.Movie.IsRecentMovie; + var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie; var moveToTop = (isRecentMovie && Settings.RecentMoviePriority == (int)QBittorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)QBittorrentPriority.First); var forceStart = (QBittorrentState)Settings.InitialState == QBittorrentState.ForceStart; diff --git a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs index 871dacb3b..caa0a581f 100644 --- a/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs +++ b/src/NzbDrone.Core/Download/Clients/Sabnzbd/Sabnzbd.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd protected override string AddFromNzbFile(RemoteMovie remoteMovie, string filename, byte[] fileContent) { var category = Settings.MovieCategory; - var priority = remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority; + var priority = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority; var response = _proxy.DownloadNzb(fileContent, filename, category, priority, Settings); diff --git a/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs b/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs index f8de7f975..0c8ff9809 100644 --- a/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs +++ b/src/NzbDrone.Core/Download/Clients/Transmission/TransmissionBase.cs @@ -194,7 +194,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission _proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings); _proxy.SetTorrentSeedingConfiguration(hash, remoteMovie.SeedConfiguration, Settings); - var isRecentMovie = remoteMovie.Movie.IsRecentMovie; + var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie; if ((isRecentMovie && Settings.RecentMoviePriority == (int)TransmissionPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)TransmissionPriority.First)) @@ -210,7 +210,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission _proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings); _proxy.SetTorrentSeedingConfiguration(hash, remoteMovie.SeedConfiguration, Settings); - var isRecentMovie = remoteMovie.Movie.IsRecentMovie; + var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie; if ((isRecentMovie && Settings.RecentMoviePriority == (int)TransmissionPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)TransmissionPriority.First)) diff --git a/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs b/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs index 360a38a3a..15ab83fb2 100644 --- a/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrent.cs @@ -72,7 +72,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink) { - var priority = (RTorrentPriority)(remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority); + var priority = (RTorrentPriority)(remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority); _proxy.AddTorrentFromUrl(magnetLink, Settings.MovieCategory, priority, Settings.MovieDirectory, Settings); @@ -92,7 +92,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent) { - var priority = (RTorrentPriority)(remoteMovie.Movie.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority); + var priority = (RTorrentPriority)(remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie ? Settings.RecentMoviePriority : Settings.OlderMoviePriority); _proxy.AddTorrentFromFile(filename, fileContent, Settings.MovieCategory, priority, Settings.MovieDirectory, Settings); diff --git a/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs b/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs index 660e03c13..3e566f95e 100644 --- a/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/uTorrent/UTorrent.cs @@ -64,7 +64,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent _proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings); } - var isRecentMovie = remoteMovie.Movie.IsRecentMovie; + var isRecentMovie = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie; if ((isRecentMovie && Settings.RecentMoviePriority == (int)UTorrentPriority.First) || (!isRecentMovie && Settings.OlderMoviePriority == (int)UTorrentPriority.First)) @@ -87,7 +87,7 @@ namespace NzbDrone.Core.Download.Clients.UTorrent _proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings); } - var isRecentEpisode = remoteMovie.Movie.IsRecentMovie; + var isRecentEpisode = remoteMovie.Movie.MovieMetadata.Value.IsRecentMovie; if ((isRecentEpisode && Settings.RecentMoviePriority == (int)UTorrentPriority.First) || (!isRecentEpisode && Settings.OlderMoviePriority == (int)UTorrentPriority.First)) diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/MediaBrowser/MediaBrowserMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/MediaBrowser/MediaBrowserMetadata.cs index 617c4da7e..451f85b5e 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/MediaBrowser/MediaBrowserMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/MediaBrowser/MediaBrowserMetadata.cs @@ -67,19 +67,19 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.MediaBrowser { var movieElement = new XElement("Movie"); - movieElement.Add(new XElement("id", movie.ImdbId)); - movieElement.Add(new XElement("Status", movie.Status)); + movieElement.Add(new XElement("id", movie.MovieMetadata.Value.ImdbId)); + movieElement.Add(new XElement("Status", movie.MovieMetadata.Value.Status)); movieElement.Add(new XElement("Added", movie.Added.ToString("MM/dd/yyyy HH:mm:ss tt"))); movieElement.Add(new XElement("LockData", "false")); - movieElement.Add(new XElement("Overview", movie.Overview)); + movieElement.Add(new XElement("Overview", movie.MovieMetadata.Value.Overview)); movieElement.Add(new XElement("LocalTitle", movie.Title)); - movieElement.Add(new XElement("Rating", movie.Ratings.Tmdb?.Value ?? 0)); + movieElement.Add(new XElement("Rating", movie.MovieMetadata.Value.Ratings.Tmdb?.Value ?? 0)); movieElement.Add(new XElement("ProductionYear", movie.Year)); - movieElement.Add(new XElement("RunningTime", movie.Runtime)); - movieElement.Add(new XElement("IMDB", movie.ImdbId)); - movieElement.Add(new XElement("Genres", movie.Genres.Select(genre => new XElement("Genre", genre)))); + movieElement.Add(new XElement("RunningTime", movie.MovieMetadata.Value.Runtime)); + movieElement.Add(new XElement("IMDB", movie.MovieMetadata.Value.ImdbId)); + movieElement.Add(new XElement("Genres", movie.MovieMetadata.Value.Genres.Select(genre => new XElement("Genre", genre)))); var doc = new XDocument(movieElement); doc.Save(xw); diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs index a708161b6..e780e6d9c 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Roksbox/RoksboxMetadata.cs @@ -118,9 +118,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox var details = new XElement("video"); details.Add(new XElement("title", movie.Title)); - details.Add(new XElement("genre", string.Join(" / ", movie.Genres))); - details.Add(new XElement("description", movie.Overview)); - details.Add(new XElement("length", movie.Runtime)); + details.Add(new XElement("genre", string.Join(" / ", movie.MovieMetadata.Value.Genres))); + details.Add(new XElement("description", movie.MovieMetadata.Value.Overview)); + details.Add(new XElement("length", movie.MovieMetadata.Value.Runtime)); doc.Add(details); doc.Save(xw); @@ -139,7 +139,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Roksbox return new List(); } - var image = movie.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.Images.FirstOrDefault(); + var image = movie.MovieMetadata.Value.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.MovieMetadata.Value.Images.FirstOrDefault(); if (image == null) { _logger.Trace("Failed to find suitable Movie image for movie {0}.", movie.Title); diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Wdtv/WdtvMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Wdtv/WdtvMetadata.cs index 2bb1a92ac..09b7b66d3 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Wdtv/WdtvMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Wdtv/WdtvMetadata.cs @@ -113,8 +113,8 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Wdtv var details = new XElement("details"); details.Add(new XElement("id", movie.Id)); details.Add(new XElement("title", movie.Title)); - details.Add(new XElement("genre", string.Join(" / ", movie.Genres))); - details.Add(new XElement("overview", movie.Overview)); + details.Add(new XElement("genre", string.Join(" / ", movie.MovieMetadata.Value.Genres))); + details.Add(new XElement("overview", movie.MovieMetadata.Value.Overview)); doc.Add(details); doc.Save(xw); @@ -136,7 +136,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Wdtv } //Because we only support one image, attempt to get the Poster type, then if that fails grab the first - var image = movie.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.Images.FirstOrDefault(); + var image = movie.MovieMetadata.Value.Images.SingleOrDefault(c => c.CoverType == MediaCoverTypes.Poster) ?? movie.MovieMetadata.Value.Images.FirstOrDefault(); if (image == null) { _logger.Trace("Failed to find suitable Movie image for movie {0}.", movie.Title); diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs index 22980ed69..61c151d0d 100644 --- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs +++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs @@ -123,14 +123,14 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc _logger.Debug("Generating Movie Metadata for: {0}", Path.Combine(movie.Path, movieFile.RelativePath)); var movieMetadataLanguage = (Settings.MovieMetadataLanguage == (int)Language.Original) ? - (int)movie.OriginalLanguage : + (int)movie.MovieMetadata.Value.OriginalLanguage : Settings.MovieMetadataLanguage; var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovie(movie.Id); var selectedSettingsLanguage = Language.FindById(movieMetadataLanguage); var movieTranslation = movieTranslations.FirstOrDefault(mt => mt.Language == selectedSettingsLanguage); - var credits = _creditService.GetAllCreditsForMovie(movie.Id); + var credits = _creditService.GetAllCreditsForMovie(movie.MovieMetadataId); var watched = GetExistingWatchedStatus(movie, movieFile.RelativePath); @@ -142,44 +142,44 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc using (var xw = XmlWriter.Create(sb, xws)) { var doc = new XDocument(); - var thumbnail = movie.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot); - var posters = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Poster); - var fanarts = movie.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart); + var thumbnail = movie.MovieMetadata.Value.Images.SingleOrDefault(i => i.CoverType == MediaCoverTypes.Screenshot); + var posters = movie.MovieMetadata.Value.Images.Where(i => i.CoverType == MediaCoverTypes.Poster); + var fanarts = movie.MovieMetadata.Value.Images.Where(i => i.CoverType == MediaCoverTypes.Fanart); var details = new XElement("movie"); details.Add(new XElement("title", movieTranslation?.Title ?? movie.Title)); - details.Add(new XElement("originaltitle", movie.OriginalTitle)); + details.Add(new XElement("originaltitle", movie.MovieMetadata.Value.OriginalTitle)); - details.Add(new XElement("sorttitle", movie.SortTitle)); + details.Add(new XElement("sorttitle", movie.MovieMetadata.Value.SortTitle)); - if (movie.Ratings.Tmdb?.Votes > 0 || movie.Ratings.Imdb?.Votes > 0) + if (movie.MovieMetadata.Value.Ratings.Tmdb?.Votes > 0 || movie.MovieMetadata.Value.Ratings.Imdb?.Votes > 0) { var setRating = new XElement("ratings"); - if (movie.Ratings.Tmdb?.Votes > 0) + if (movie.MovieMetadata.Value.Ratings.Tmdb?.Votes > 0) { var setRatethemoviedb = new XElement("rating", new XAttribute("name", "themoviedb"), new XAttribute("max", "10"), new XAttribute("default", "true")); - setRatethemoviedb.Add(new XElement("value", movie.Ratings.Tmdb.Value)); - setRatethemoviedb.Add(new XElement("votes", movie.Ratings.Tmdb.Votes)); + setRatethemoviedb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Tmdb.Value)); + setRatethemoviedb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Tmdb.Votes)); setRating.Add(setRatethemoviedb); } - if (movie.Ratings.Imdb?.Votes > 0) + if (movie.MovieMetadata.Value.Ratings.Imdb?.Votes > 0) { var setRateImdb = new XElement("rating", new XAttribute("name", "imdb"), new XAttribute("max", "10")); - setRateImdb.Add(new XElement("value", movie.Ratings.Imdb.Value)); - setRateImdb.Add(new XElement("votes", movie.Ratings.Imdb.Votes)); + setRateImdb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Imdb.Value)); + setRateImdb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Imdb.Votes)); setRating.Add(setRateImdb); } details.Add(setRating); } - if (movie.Ratings?.Tmdb?.Votes > 0) + if (movie.MovieMetadata.Value.Ratings?.Tmdb?.Votes > 0) { - details.Add(new XElement("rating", movie.Ratings.Tmdb.Value)); + details.Add(new XElement("rating", movie.MovieMetadata.Value.Ratings.Tmdb.Value)); } details.Add(new XElement("userrating")); @@ -188,11 +188,11 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc details.Add(new XElement("outline")); - details.Add(new XElement("plot", movieTranslation?.Overview ?? movie.Overview)); + details.Add(new XElement("plot", movieTranslation?.Overview ?? movie.MovieMetadata.Value.Overview)); details.Add(new XElement("tagline")); - details.Add(new XElement("runtime", movie.Runtime)); + details.Add(new XElement("runtime", movie.MovieMetadata.Value.Runtime)); if (thumbnail != null) { @@ -221,9 +221,9 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc details.Add(fanartElement); } - if (movie.Certification.IsNotNullOrWhiteSpace()) + if (movie.MovieMetadata.Value.Certification.IsNotNullOrWhiteSpace()) { - details.Add(new XElement("mpaa", movie.Certification)); + details.Add(new XElement("mpaa", movie.MovieMetadata.Value.Certification)); } details.Add(new XElement("playcount")); @@ -237,25 +237,25 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc uniqueId.SetAttributeValue("default", true); details.Add(uniqueId); - if (movie.ImdbId.IsNotNullOrWhiteSpace()) + if (movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace()) { - var imdbId = new XElement("uniqueid", movie.ImdbId); + var imdbId = new XElement("uniqueid", movie.MovieMetadata.Value.ImdbId); imdbId.SetAttributeValue("type", "imdb"); details.Add(imdbId); } - foreach (var genre in movie.Genres) + foreach (var genre in movie.MovieMetadata.Value.Genres) { details.Add(new XElement("genre", genre)); } details.Add(new XElement("country")); - if (movie.Collection?.Name != null) + if (movie.MovieMetadata.Value.Collection?.Name != null) { var setElement = new XElement("set"); - setElement.Add(new XElement("name", movie.Collection.Name)); + setElement.Add(new XElement("name", movie.MovieMetadata.Value.Collection.Name)); setElement.Add(new XElement("overview")); details.Add(setElement); @@ -284,16 +284,16 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc } } - if (movie.InCinemas.HasValue) + if (movie.MovieMetadata.Value.InCinemas.HasValue) { - details.Add(new XElement("premiered", movie.InCinemas.Value.ToString("yyyy-MM-dd"))); + details.Add(new XElement("premiered", movie.MovieMetadata.Value.InCinemas.Value.ToString("yyyy-MM-dd"))); } details.Add(new XElement("year", movie.Year)); - details.Add(new XElement("studio", movie.Studio)); + details.Add(new XElement("studio", movie.MovieMetadata.Value.Studio)); - details.Add(new XElement("trailer", "plugin://plugin.video.youtube/play/?video_id=" + movie.YouTubeTrailerId)); + details.Add(new XElement("trailer", "plugin://plugin.video.youtube/play/?video_id=" + movie.MovieMetadata.Value.YouTubeTrailerId)); if (movieFile.MediaInfo != null) { @@ -369,10 +369,10 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc if (Settings.MovieMetadataURL) { - xmlResult += "https://www.themoviedb.org/movie/" + movie.TmdbId; + xmlResult += "https://www.themoviedb.org/movie/" + movie.MovieMetadata.Value.TmdbId; xmlResult += Environment.NewLine; - xmlResult += "https://www.imdb.com/title/" + movie.ImdbId; + xmlResult += "https://www.imdb.com/title/" + movie.MovieMetadata.Value.ImdbId; xmlResult += Environment.NewLine; } @@ -393,7 +393,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc private IEnumerable ProcessMovieImages(Movie movie) { - foreach (var image in movie.Images) + foreach (var image in movie.MovieMetadata.Value.Images) { var source = _mediaCoverService.GetCoverPath(movie.Id, image.CoverType); var destination = image.CoverType.ToString().ToLowerInvariant() + Path.GetExtension(source); diff --git a/src/NzbDrone.Core/HealthCheck/Checks/RemovedMovieCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/RemovedMovieCheck.cs index 29a214e78..ae756cc52 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/RemovedMovieCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/RemovedMovieCheck.cs @@ -21,7 +21,7 @@ namespace NzbDrone.Core.HealthCheck.Checks public override HealthCheck Check() { - var deletedMovie = _movieService.GetAllMovies().Where(v => v.Status == MovieStatusType.Deleted).ToList(); + var deletedMovie = _movieService.GetAllMovies().Where(v => v.MovieMetadata.Value.Status == MovieStatusType.Deleted).ToList(); if (deletedMovie.Empty()) { @@ -40,12 +40,12 @@ namespace NzbDrone.Core.HealthCheck.Checks public bool ShouldCheckOnEvent(MoviesDeletedEvent message) { - return message.Movies.Any(m => m.Status == MovieStatusType.Deleted); + return message.Movies.Any(m => m.MovieMetadata.Value.Status == MovieStatusType.Deleted); } public bool ShouldCheckOnEvent(MovieUpdatedEvent message) { - return message.Movie.Status == MovieStatusType.Deleted; + return message.Movie.MovieMetadata.Value.Status == MovieStatusType.Deleted; } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitles.cs index 2f26a28c8..050008a07 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitles.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedAlternativeTitles.cs @@ -1,4 +1,4 @@ -using Dapper; +using Dapper; using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Housekeeping.Housekeepers @@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers mapper.Execute(@"DELETE FROM ""AlternativeTitles"" WHERE ""Id"" IN ( SELECT ""AlternativeTitles"".""Id"" FROM ""AlternativeTitles"" - LEFT OUTER JOIN ""Movies"" - ON ""AlternativeTitles"".""MovieId"" = ""Movies"".""Id"" - WHERE ""Movies"".""Id"" IS NULL)"); + LEFT OUTER JOIN ""MovieMetadata"" + ON ""AlternativeTitles"".""MovieMetadataId"" = ""MovieMetadata"".""Id"" + WHERE ""MovieMetadata"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedCredits.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedCredits.cs index 57eef9ad0..88024b3fb 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedCredits.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedCredits.cs @@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers mapper.Execute(@"DELETE FROM ""Credits"" WHERE ""Id"" IN ( SELECT ""Credits"".""Id"" FROM ""Credits"" - LEFT OUTER JOIN ""Movies"" - ON ""Credits"".""MovieId"" = ""Movies"".""Id"" - WHERE ""Movies"".""Id"" IS NULL)"); + LEFT OUTER JOIN ""MovieMetadata"" + ON ""Credits"".""MovieMetadataId"" = ""MovieMetadata"".""Id"" + WHERE ""MovieMetadata"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieMetadata.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieMetadata.cs new file mode 100644 index 000000000..e7e10bc40 --- /dev/null +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieMetadata.cs @@ -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)"); + } + } + } +} diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslations.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslations.cs index 35500d034..9db5013d6 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslations.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedMovieTranslations.cs @@ -19,9 +19,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers mapper.Execute(@"DELETE FROM ""MovieTranslations"" WHERE ""Id"" IN ( SELECT ""MovieTranslations"".""Id"" FROM ""MovieTranslations"" - LEFT OUTER JOIN ""Movies"" - ON ""MovieTranslations"".""MovieId"" = ""Movies"".""Id"" - WHERE ""Movies"".""Id"" IS NULL)"); + LEFT OUTER JOIN ""MovieMetadata"" + ON ""MovieTranslations"".""MovieMetadataId"" = ""MovieMetadata"".""Id"" + WHERE ""MovieMetadata"".""Id"" IS NULL)"); } } } diff --git a/src/NzbDrone.Core/ImportLists/FetchAndParseImportListService.cs b/src/NzbDrone.Core/ImportLists/FetchAndParseImportListService.cs index 1836d5f5f..9a5125b08 100644 --- a/src/NzbDrone.Core/ImportLists/FetchAndParseImportListService.cs +++ b/src/NzbDrone.Core/ImportLists/FetchAndParseImportListService.cs @@ -24,18 +24,21 @@ namespace NzbDrone.Core.ImportLists private readonly IImportListStatusService _importListStatusService; private readonly IImportListMovieService _listMovieService; private readonly ISearchForNewMovie _movieSearch; + private readonly IMovieMetadataService _movieMetadataService; private readonly Logger _logger; public FetchAndParseImportListService(IImportListFactory importListFactory, IImportListStatusService importListStatusService, IImportListMovieService listMovieService, ISearchForNewMovie movieSearch, + IMovieMetadataService movieMetadataService, Logger logger) { _importListFactory = importListFactory; _importListStatusService = importListStatusService; _listMovieService = listMovieService; _movieSearch = movieSearch; + _movieMetadataService = movieMetadataService; _logger = logger; } @@ -173,33 +176,16 @@ namespace NzbDrone.Core.ImportLists private ImportListMovie MapMovieReport(ImportListMovie report) { - var mappedMovie = _movieSearch.MapMovieToTmdbMovie(new Movie { Title = report.Title, TmdbId = report.TmdbId, ImdbId = report.ImdbId, Year = report.Year }); + var mappedMovie = _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = report.Title, TmdbId = report.TmdbId, ImdbId = report.ImdbId, Year = report.Year }); + + _movieMetadataService.Upsert(mappedMovie); var mappedListMovie = new ImportListMovie { ListId = report.ListId }; if (mappedMovie != null) { - mappedListMovie.TmdbId = mappedMovie.TmdbId; - mappedListMovie.ImdbId = mappedMovie.ImdbId; - mappedListMovie.Title = mappedMovie.Title; - mappedListMovie.SortTitle = mappedMovie?.SortTitle; - mappedListMovie.Year = mappedMovie.Year; - mappedListMovie.Overview = mappedMovie.Overview; - mappedListMovie.Ratings = mappedMovie.Ratings; - mappedListMovie.Studio = mappedMovie.Studio; - mappedListMovie.Certification = mappedMovie.Certification; - mappedListMovie.Collection = mappedMovie.Collection; - mappedListMovie.Status = mappedMovie.Status; - mappedListMovie.Images = mappedMovie.Images; - mappedListMovie.Website = mappedMovie.Website; - mappedListMovie.YouTubeTrailerId = mappedMovie.YouTubeTrailerId; - mappedListMovie.Translations = mappedMovie.Translations; - mappedListMovie.InCinemas = mappedMovie.InCinemas; - mappedListMovie.PhysicalRelease = mappedMovie.PhysicalRelease; - mappedListMovie.DigitalRelease = mappedMovie.DigitalRelease; - mappedListMovie.Genres = mappedMovie.Genres; - mappedListMovie.Runtime = mappedMovie.Runtime; - mappedListMovie.OriginalTitle = mappedMovie.OriginalTitle; + mappedListMovie.MovieMetadata = mappedMovie; + mappedListMovie.MovieMetadataId = mappedMovie.Id; } return mappedListMovie; diff --git a/src/NzbDrone.Core/ImportLists/ImportListMovies/ImportListMovie.cs b/src/NzbDrone.Core/ImportLists/ImportListMovies/ImportListMovie.cs index 288f6ba40..1c8efdc0b 100644 --- a/src/NzbDrone.Core/ImportLists/ImportListMovies/ImportListMovie.cs +++ b/src/NzbDrone.Core/ImportLists/ImportListMovies/ImportListMovie.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; using NzbDrone.Core.Datastore; using NzbDrone.Core.Movies; -using NzbDrone.Core.Movies.Translations; namespace NzbDrone.Core.ImportLists.ImportListMovies { @@ -10,37 +7,35 @@ namespace NzbDrone.Core.ImportLists.ImportListMovies { public ImportListMovie() { - Images = new List(); - Genres = new List(); - Translations = new List(); - Ratings = new Ratings(); + MovieMetadata = new MovieMetadata(); } - public int TmdbId { get; set; } - public string ImdbId { get; set; } - public string Title { get; set; } - public string SortTitle { get; set; } - public MovieStatusType Status { get; set; } - public string Overview { get; set; } - public DateTime? LastInfoSync { get; set; } - public int Runtime { get; set; } - public List Images { get; set; } - public string Website { get; set; } - public int Year { get; set; } - public Ratings Ratings { get; set; } - public List 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 Translations { get; set; } - public string YouTubeTrailerId { get; set; } - public string Studio { get; set; } - public string OriginalTitle { get; set; } public int ListId { get; set; } + public int MovieMetadataId { get; set; } + public LazyLoaded MovieMetadata { 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; } + } } } diff --git a/src/NzbDrone.Core/ImportLists/Radarr/RadarrImport.cs b/src/NzbDrone.Core/ImportLists/Radarr/RadarrImport.cs index 92162c46b..eb0da5c9e 100644 --- a/src/NzbDrone.Core/ImportLists/Radarr/RadarrImport.cs +++ b/src/NzbDrone.Core/ImportLists/Radarr/RadarrImport.cs @@ -48,11 +48,6 @@ namespace NzbDrone.Core.ImportLists.Radarr { TmdbId = remoteMovie.TmdbId, Title = remoteMovie.Title, - SortTitle = remoteMovie.SortTitle, - Overview = remoteMovie.Overview, - Images = remoteMovie.Images.Select(x => MapImage(x, Settings.BaseUrl)).ToList(), - PhysicalRelease = remoteMovie.PhysicalRelease, - InCinemas = remoteMovie.InCinemas, Year = remoteMovie.Year }); } diff --git a/src/NzbDrone.Core/ImportLists/TMDb/TMDbParser.cs b/src/NzbDrone.Core/ImportLists/TMDb/TMDbParser.cs index 3164013db..75cb14e8c 100644 --- a/src/NzbDrone.Core/ImportLists/TMDb/TMDbParser.cs +++ b/src/NzbDrone.Core/ImportLists/TMDb/TMDbParser.cs @@ -36,10 +36,7 @@ namespace NzbDrone.Core.ImportLists.TMDb var movie = new ImportListMovie { TmdbId = movieResult.Id, - Overview = movieResult.Overview, Title = movieResult.Title, - SortTitle = Parser.Parser.NormalizeTitle(movieResult.Title), - Images = new List(), }; if (movieResult.ReleaseDate.IsNotNullOrWhiteSpace()) @@ -48,8 +45,6 @@ namespace NzbDrone.Core.ImportLists.TMDb movie.Year = releaseDate.Year; } - movie.Images.AddIfNotNull(MapPosterImage(movieResult.PosterPath)); - return movie; } diff --git a/src/NzbDrone.Core/IndexerSearch/ReleaseSearchService.cs b/src/NzbDrone.Core/IndexerSearch/ReleaseSearchService.cs index 7ce8ddc66..b22f66389 100644 --- a/src/NzbDrone.Core/IndexerSearch/ReleaseSearchService.cs +++ b/src/NzbDrone.Core/IndexerSearch/ReleaseSearchService.cs @@ -49,7 +49,7 @@ namespace NzbDrone.Core.IndexerSearch public List MovieSearch(int movieId, bool userInvokedSearch, bool interactiveSearch) { var movie = _movieService.GetMovie(movieId); - movie.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id); + movie.MovieMetadata.Value.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id); return MovieSearch(movie, userInvokedSearch, interactiveSearch); } @@ -81,8 +81,8 @@ namespace NzbDrone.Core.IndexerSearch var queryTranlations = new List { - movie.Title, - movie.OriginalTitle + movie.MovieMetadata.Value.Title, + movie.MovieMetadata.Value.OriginalTitle }; //Add Translation of wanted languages to search query diff --git a/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs b/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs index ca47a146a..0f802d168 100644 --- a/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/FileList/FileListRequestGenerator.cs @@ -24,9 +24,9 @@ namespace NzbDrone.Core.Indexers.FileList { var pageableRequests = new IndexerPageableRequestChain(); - if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace()) + if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace()) { - pageableRequests.Add(GetRequest("search-torrents", string.Format("&type=imdb&query={0}", searchCriteria.Movie.ImdbId))); + pageableRequests.Add(GetRequest("search-torrents", string.Format("&type=imdb&query={0}", searchCriteria.Movie.MovieMetadata.Value.ImdbId))); } else { diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs b/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs index c502e4a83..e53084f2c 100644 --- a/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/HDBits/HDBitsRequestGenerator.cs @@ -35,12 +35,12 @@ namespace NzbDrone.Core.Indexers.HDBits private bool TryAddSearchParameters(TorrentQuery query, SearchCriteriaBase searchCriteria) { - if (searchCriteria.Movie.ImdbId.IsNullOrWhiteSpace()) + if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNullOrWhiteSpace()) { return false; } - var imdbId = int.Parse(searchCriteria.Movie.ImdbId.Substring(2)); + var imdbId = int.Parse(searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2)); if (imdbId != 0) { diff --git a/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs index a20f0dbab..6b5aa742d 100644 --- a/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Newznab/NewznabRequestGenerator.cs @@ -115,8 +115,8 @@ namespace NzbDrone.Core.Indexers.Newznab private void AddMovieIdPageableRequests(IndexerPageableRequestChain chain, int maxPages, IEnumerable categories, SearchCriteriaBase searchCriteria) { - var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.TmdbId > 0; - var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace(); + var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.MovieMetadata.Value.TmdbId > 0; + var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace(); if (SupportsAggregatedIdSearch && (includeTmdbSearch || includeImdbSearch)) { @@ -124,12 +124,12 @@ namespace NzbDrone.Core.Indexers.Newznab if (includeTmdbSearch) { - ids += "&tmdbid=" + searchCriteria.Movie.TmdbId; + ids += "&tmdbid=" + searchCriteria.Movie.MovieMetadata.Value.TmdbId; } if (includeImdbSearch) { - ids += "&imdbid=" + searchCriteria.Movie.ImdbId.Substring(2); + ids += "&imdbid=" + searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2); } chain.Add(GetPagedRequests(maxPages, categories, "movie", ids)); @@ -141,14 +141,14 @@ namespace NzbDrone.Core.Indexers.Newznab chain.Add(GetPagedRequests(maxPages, categories, "movie", - string.Format("&tmdbid={0}", searchCriteria.Movie.TmdbId))); + string.Format("&tmdbid={0}", searchCriteria.Movie.MovieMetadata.Value.TmdbId))); } else if (includeImdbSearch) { chain.Add(GetPagedRequests(maxPages, categories, "movie", - string.Format("&imdbid={0}", searchCriteria.Movie.ImdbId.Substring(2)))); + string.Format("&imdbid={0}", searchCriteria.Movie.MovieMetadata.Value.ImdbId.Substring(2)))); } } diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs b/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs index f5d62c4fd..aa3f59327 100644 --- a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcornRequestGenerator.cs @@ -29,9 +29,9 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn { var pageableRequests = new IndexerPageableRequestChain(); - if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace()) + if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace()) { - pageableRequests.Add(GetRequest(searchCriteria.Movie.ImdbId)); + pageableRequests.Add(GetRequest(searchCriteria.Movie.MovieMetadata.Value.ImdbId)); } else if (searchCriteria.Movie.Year > 0) { diff --git a/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs index 1e824c14e..12f6111fc 100644 --- a/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Rarbg/RarbgRequestGenerator.cs @@ -87,11 +87,11 @@ namespace NzbDrone.Core.Indexers.Rarbg requestBuilder.AddQueryParam("mode", "search"); - if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace()) + if (searchCriteria.Movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace()) { - requestBuilder.AddQueryParam("search_imdb", searchCriteria.Movie.ImdbId); + requestBuilder.AddQueryParam("search_imdb", searchCriteria.Movie.MovieMetadata.Value.ImdbId); } - else if (searchCriteria.Movie.TmdbId > 0) + else if (searchCriteria.Movie.MovieMetadata.Value.TmdbId > 0) { requestBuilder.AddQueryParam("search_themoviedb", searchCriteria.Movie.TmdbId); } diff --git a/src/NzbDrone.Core/MediaCover/MediaCover.cs b/src/NzbDrone.Core/MediaCover/MediaCover.cs index acea3ab42..b546264e2 100644 --- a/src/NzbDrone.Core/MediaCover/MediaCover.cs +++ b/src/NzbDrone.Core/MediaCover/MediaCover.cs @@ -1,3 +1,4 @@ +using Equ; using NzbDrone.Core.Datastore; namespace NzbDrone.Core.MediaCover @@ -12,7 +13,7 @@ namespace NzbDrone.Core.MediaCover Headshot = 5 } - public class MediaCover : IEmbeddedDocument + public class MediaCover : MemberwiseEquatable, IEmbeddedDocument { public MediaCoverTypes CoverType { get; set; } public string Url { get; set; } diff --git a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs index 44453eb36..eaccc9ae6 100644 --- a/src/NzbDrone.Core/MediaCover/MediaCoverService.cs +++ b/src/NzbDrone.Core/MediaCover/MediaCoverService.cs @@ -145,7 +145,7 @@ namespace NzbDrone.Core.MediaCover bool updated = false; var toResize = new List>(); - foreach (var cover in movie.Images) + foreach (var cover in movie.MovieMetadata.Value.Images) { var fileName = GetCoverPath(movie.Id, cover.CoverType); var alreadyExists = false; diff --git a/src/NzbDrone.Core/MediaFiles/DownloadedMovieImportService.cs b/src/NzbDrone.Core/MediaFiles/DownloadedMovieImportService.cs index 9635a5c12..882e258c0 100644 --- a/src/NzbDrone.Core/MediaFiles/DownloadedMovieImportService.cs +++ b/src/NzbDrone.Core/MediaFiles/DownloadedMovieImportService.cs @@ -133,7 +133,7 @@ namespace NzbDrone.Core.MediaFiles return false; } - if (_detectSample.IsSample(movie, videoFile) != DetectSampleResult.Sample) + if (_detectSample.IsSample(movie.MovieMetadata, videoFile) != DetectSampleResult.Sample) { _logger.Warn("Non-sample file detected: [{0}]", videoFile); return false; diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguage.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguage.cs index 60cadfcfe..c44b6a23c 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguage.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguage.cs @@ -22,7 +22,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators public LocalMovie Aggregate(LocalMovie localMovie, DownloadClientItem downloadClientItem, bool otherFiles) { - var languages = new List { localMovie.Movie?.OriginalLanguage ?? Language.Unknown }; + var languages = new List { localMovie.Movie?.MovieMetadata.Value.OriginalLanguage ?? Language.Unknown }; var languagesConfidence = Confidence.Default; foreach (var augmentLanguage in _augmentLanguages) diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/DetectSample.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/DetectSample.cs index 1caf7da6b..5b1005918 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/DetectSample.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/DetectSample.cs @@ -9,7 +9,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport { public interface IDetectSample { - DetectSampleResult IsSample(Movie movie, string path); + DetectSampleResult IsSample(MovieMetadata movie, string path); } public class DetectSample : IDetectSample @@ -23,7 +23,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport _logger = logger; } - public DetectSampleResult IsSample(Movie movie, string path) + public DetectSampleResult IsSample(MovieMetadata movie, string path) { var extension = Path.GetExtension(path); @@ -75,7 +75,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport return DetectSampleResult.NotSample; } - private int GetMinimumAllowedRuntime(Movie movie) + private int GetMinimumAllowedRuntime(MovieMetadata movie) { //Anime short - 15 seconds if (movie.Runtime <= 3) diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/ImportDecisionMaker.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/ImportDecisionMaker.cs index bd256ab10..eed2912e1 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/ImportDecisionMaker.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/ImportDecisionMaker.cs @@ -78,7 +78,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport downloadClientItemInfo = _parsingService.EnhanceMovieInfo(downloadClientItemInfo); } - var nonSampleVideoFileCount = GetNonSampleVideoFileCount(newFiles, movie); + var nonSampleVideoFileCount = GetNonSampleVideoFileCount(newFiles, movie.MovieMetadata); var decisions = new List(); @@ -187,7 +187,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport return null; } - private int GetNonSampleVideoFileCount(List videoFiles, Movie movie) + private int GetNonSampleVideoFileCount(List videoFiles, MovieMetadata movie) { return videoFiles.Count(file => { diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs index 90b962f6f..6632ab971 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs @@ -104,8 +104,8 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual if (languageParse.Count <= 1 && languageParse.First() == Language.Unknown && movie != null) { - languageParse = new List { movie.OriginalLanguage }; - _logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", movie.OriginalLanguage.Name); + languageParse = new List { movie.MovieMetadata.Value.OriginalLanguage }; + _logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", movie.MovieMetadata.Value.OriginalLanguage.Name); } var localMovie = new LocalMovie diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Specifications/NotSampleSpecification.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Specifications/NotSampleSpecification.cs index 2cddda5fd..73c19e53b 100644 --- a/src/NzbDrone.Core/MediaFiles/MovieImport/Specifications/NotSampleSpecification.cs +++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Specifications/NotSampleSpecification.cs @@ -25,7 +25,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Specifications return Decision.Accept(); } - var sample = _detectSample.IsSample(localMovie.Movie, localMovie.Path); + var sample = _detectSample.IsSample(localMovie.Movie.MovieMetadata, localMovie.Path); if (sample == DetectSampleResult.Sample) { diff --git a/src/NzbDrone.Core/MediaFiles/UpdateMovieFileService.cs b/src/NzbDrone.Core/MediaFiles/UpdateMovieFileService.cs index ce9c9f5e7..b7a297394 100644 --- a/src/NzbDrone.Core/MediaFiles/UpdateMovieFileService.cs +++ b/src/NzbDrone.Core/MediaFiles/UpdateMovieFileService.cs @@ -49,7 +49,7 @@ namespace NzbDrone.Core.MediaFiles { case FileDateType.Release: { - var releaseDate = movie.PhysicalRelease ?? movie.DigitalRelease; + var releaseDate = movie.MovieMetadata.Value.PhysicalRelease ?? movie.MovieMetadata.Value.DigitalRelease; if (releaseDate.HasValue == false) { @@ -61,7 +61,7 @@ namespace NzbDrone.Core.MediaFiles case FileDateType.Cinemas: { - var airDate = movie.InCinemas; + var airDate = movie.MovieMetadata.Value.InCinemas; if (airDate.HasValue == false) { diff --git a/src/NzbDrone.Core/MetadataSource/IProvideMovieInfo.cs b/src/NzbDrone.Core/MetadataSource/IProvideMovieInfo.cs index 923fda3a4..55c470b82 100644 --- a/src/NzbDrone.Core/MetadataSource/IProvideMovieInfo.cs +++ b/src/NzbDrone.Core/MetadataSource/IProvideMovieInfo.cs @@ -7,9 +7,9 @@ namespace NzbDrone.Core.MetadataSource { public interface IProvideMovieInfo { - Movie GetMovieByImdbId(string imdbId); - Tuple> GetMovieInfo(int tmdbId); - List GetBulkMovieInfo(List tmdbIds); + MovieMetadata GetMovieByImdbId(string imdbId); + Tuple> GetMovieInfo(int tmdbId); + List GetBulkMovieInfo(List tmdbIds); HashSet GetChangedMovies(DateTime startTime); } diff --git a/src/NzbDrone.Core/MetadataSource/ISearchForNewMovie.cs b/src/NzbDrone.Core/MetadataSource/ISearchForNewMovie.cs index 637bdaae4..2907fc117 100644 --- a/src/NzbDrone.Core/MetadataSource/ISearchForNewMovie.cs +++ b/src/NzbDrone.Core/MetadataSource/ISearchForNewMovie.cs @@ -7,6 +7,6 @@ namespace NzbDrone.Core.MetadataSource { List SearchForNewMovie(string title); - Movie MapMovieToTmdbMovie(Movie movie); + MovieMetadata MapMovieToTmdbMovie(MovieMetadata movie); } } diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/MovieResource.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/MovieResource.cs index 15bc72ef4..c3a0abe62 100644 --- a/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/MovieResource.cs +++ b/src/NzbDrone.Core/MetadataSource/SkyHook/Resource/MovieResource.cs @@ -38,5 +38,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource public string OriginalLanguage { get; set; } public string Homepage { get; set; } public List Recommendations { get; set; } + public float? Popularity { get; set; } } } diff --git a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs index 996e3635b..eac68b37e 100644 --- a/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs +++ b/src/NzbDrone.Core/MetadataSource/SkyHook/SkyHookProxy.cs @@ -28,12 +28,14 @@ namespace NzbDrone.Core.MetadataSource.SkyHook private readonly IHttpRequestBuilderFactory _radarrMetadata; private readonly IConfigService _configService; private readonly IMovieService _movieService; + private readonly IMovieMetadataService _movieMetadataService; private readonly IMovieTranslationService _movieTranslationService; public SkyHookProxy(IHttpClient httpClient, IRadarrCloudRequestBuilder requestBuilder, IConfigService configService, IMovieService movieService, + IMovieMetadataService movieMetadataService, IMovieTranslationService movieTranslationService, Logger logger) { @@ -41,6 +43,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook _radarrMetadata = requestBuilder.RadarrMetadata; _configService = configService; _movieService = movieService; + _movieMetadataService = movieMetadataService; _movieTranslationService = movieTranslationService; _logger = logger; @@ -65,7 +68,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook return new HashSet(response.Resource); } - public Tuple> GetMovieInfo(int tmdbId) + public Tuple> GetMovieInfo(int tmdbId) { var httpRequest = _radarrMetadata.Create() .SetSegment("route", "movie") @@ -95,10 +98,10 @@ namespace NzbDrone.Core.MetadataSource.SkyHook var movie = MapMovie(httpResponse.Resource); - return new Tuple>(movie, credits.ToList()); + return new Tuple>(movie, credits.ToList()); } - public List GetBulkMovieInfo(List tmdbIds) + public List GetBulkMovieInfo(List tmdbIds) { var httpRequest = _radarrMetadata.Create() .SetSegment("route", "movie/bulk") @@ -123,7 +126,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook return movies; } - public Movie GetMovieByImdbId(string imdbId) + public MovieMetadata GetMovieByImdbId(string imdbId) { imdbId = Parser.Parser.NormalizeImdbId(imdbId); @@ -159,18 +162,18 @@ namespace NzbDrone.Core.MetadataSource.SkyHook return movie; } - public Movie MapMovie(MovieResource resource) + public MovieMetadata MapMovie(MovieResource resource) { - var movie = new Movie(); + var movie = new MovieMetadata(); var altTitles = new List(); movie.TmdbId = resource.TmdbId; movie.ImdbId = resource.ImdbId; movie.Title = resource.Title; movie.OriginalTitle = resource.OriginalTitle; - movie.TitleSlug = resource.TitleSlug; movie.CleanTitle = resource.Title.CleanMovieTitle(); movie.SortTitle = Parser.Parser.NormalizeTitle(resource.Title); + movie.CleanOriginalTitle = resource.OriginalTitle.CleanMovieTitle(); movie.Overview = resource.Overview; movie.AlternativeTitles.AddRange(resource.AlternativeTitles.Select(MapAlternativeTitle)); @@ -192,18 +195,26 @@ namespace NzbDrone.Core.MetadataSource.SkyHook movie.SecondaryYear = resource.Premier?.Year; } - movie.Images = resource.Images.Select(MapImage).ToList(); - if (resource.Runtime != null) { movie.Runtime = resource.Runtime.Value; } + if (resource.Popularity != null) + { + movie.Popularity = resource.Popularity.Value; + } + var certificationCountry = _configService.CertificationCountry.ToString(); movie.Certification = resource.Certifications.FirstOrDefault(m => m.Country == certificationCountry)?.Certification; movie.Ratings = MapRatings(resource.MovieRatings) ?? new Ratings(); + + movie.TmdbId = resource.TmdbId; movie.Genres = resource.Genres; + movie.Images = resource.Images.Select(MapImage).ToList(); + + //movie.Genres = resource.Genres; movie.Recommendations = resource.Recommendations?.Select(r => r.TmdbId).ToList() ?? new List(); //Workaround due to metadata change until cache cleans up @@ -266,7 +277,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook return title; } - public Movie MapMovieToTmdbMovie(Movie movie) + public MovieMetadata MapMovieToTmdbMovie(MovieMetadata movie) { try { @@ -274,12 +285,14 @@ namespace NzbDrone.Core.MetadataSource.SkyHook if (movie.TmdbId > 0) { - newMovie = _movieService.FindByTmdbId(movie.TmdbId); + newMovie = _movieMetadataService.FindByTmdbId(movie.TmdbId); - if (newMovie == null) + if (newMovie != null) { - newMovie = GetMovieInfo(movie.TmdbId).Item1; + return newMovie; } + + newMovie = GetMovieInfo(movie.TmdbId).Item1; } else if (movie.ImdbId.IsNotNullOrWhiteSpace()) { @@ -293,7 +306,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook yearStr = $" {movie.Year}"; } - newMovie = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault(); + newMovie = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault().MovieMetadata; } if (newMovie == null) @@ -302,14 +315,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook return null; } - newMovie.Path = movie.Path; - newMovie.RootFolderPath = movie.RootFolderPath; - newMovie.ProfileId = movie.ProfileId; - newMovie.Monitored = movie.Monitored; - newMovie.MovieFile = movie.MovieFile; - newMovie.MinimumAvailability = movie.MinimumAvailability; - newMovie.Tags = movie.Tags; - return newMovie; } catch (Exception ex) @@ -347,7 +352,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook try { var movieLookup = GetMovieByImdbId(parserResult.ImdbId); - return movieLookup == null ? new List() : new List { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? movieLookup }; + return movieLookup == null ? new List() : new List { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } }; } catch (Exception) { @@ -360,7 +365,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook try { var movieLookup = GetMovieInfo(parserResult.TmdbId).Item1; - return movieLookup == null ? new List() : new List { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? movieLookup }; + return movieLookup == null ? new List() : new List { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } }; } catch (Exception) { @@ -385,7 +390,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook try { var movieLookup = GetMovieByImdbId(imdbid); - return movieLookup == null ? new List() : new List { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? movieLookup }; + return movieLookup == null ? new List() : new List { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } }; } catch (MovieNotFoundException) { @@ -407,7 +412,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook try { var movieLookup = GetMovieInfo(tmdbid).Item1; - return movieLookup == null ? new List() : new List { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? movieLookup }; + return movieLookup == null ? new List() : new List { _movieService.FindByTmdbId(movieLookup.TmdbId) ?? new Movie { MovieMetadata = movieLookup } }; } catch (MovieNotFoundException) { @@ -455,11 +460,11 @@ namespace NzbDrone.Core.MetadataSource.SkyHook if (movie == null) { - movie = MapMovie(result); + movie = new Movie { MovieMetadata = MapMovie(result) }; } else { - movie.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id); + movie.MovieMetadata.Value.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id); } return movie; diff --git a/src/NzbDrone.Core/Movies/AddMovieService.cs b/src/NzbDrone.Core/Movies/AddMovieService.cs index 364183374..b2a123532 100644 --- a/src/NzbDrone.Core/Movies/AddMovieService.cs +++ b/src/NzbDrone.Core/Movies/AddMovieService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using FluentValidation; using FluentValidation.Results; using NLog; @@ -9,6 +10,7 @@ using NzbDrone.Core.Exceptions; using NzbDrone.Core.MetadataSource; using NzbDrone.Core.Organizer; using NzbDrone.Core.Parser; +using NzbDrone.Core.RootFolders; namespace NzbDrone.Core.Movies { @@ -21,18 +23,21 @@ namespace NzbDrone.Core.Movies public class AddMovieService : IAddMovieService { private readonly IMovieService _movieService; + private readonly IMovieMetadataService _movieMetadataService; private readonly IProvideMovieInfo _movieInfo; private readonly IBuildFileNames _fileNameBuilder; private readonly IAddMovieValidator _addMovieValidator; private readonly Logger _logger; public AddMovieService(IMovieService movieService, + IMovieMetadataService movieMetadataService, IProvideMovieInfo movieInfo, IBuildFileNames fileNameBuilder, IAddMovieValidator addMovieValidator, Logger logger) { _movieService = movieService; + _movieMetadataService = movieMetadataService; _movieInfo = movieInfo; _fileNameBuilder = fileNameBuilder; _addMovieValidator = addMovieValidator; @@ -47,6 +52,10 @@ namespace NzbDrone.Core.Movies newMovie = SetPropertiesAndValidate(newMovie); _logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path); + + _movieMetadataService.Upsert(newMovie.MovieMetadata.Value); + newMovie.MovieMetadataId = newMovie.MovieMetadata.Value.Id; + _movieService.AddMovie(newMovie); return newMovie; @@ -65,6 +74,7 @@ namespace NzbDrone.Core.Movies { var movie = AddSkyhookData(m); movie = SetPropertiesAndValidate(movie); + movie.Added = added; moviesToAdd.Add(movie); } @@ -79,16 +89,19 @@ namespace NzbDrone.Core.Movies } } + _movieMetadataService.UpsertMany(moviesToAdd.Select(x => x.MovieMetadata.Value).ToList()); + moviesToAdd.ForEach(x => x.MovieMetadataId = x.MovieMetadata.Value.Id); + return _movieService.AddMovies(moviesToAdd); } private Movie AddSkyhookData(Movie newMovie) { - Movie movie; + var movie = new Movie(); try { - movie = _movieInfo.GetMovieInfo(newMovie.TmdbId).Item1; + movie.MovieMetadata = _movieInfo.GetMovieInfo(newMovie.TmdbId).Item1; } catch (MovieNotFoundException) { @@ -113,8 +126,8 @@ namespace NzbDrone.Core.Movies newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName); } - newMovie.CleanTitle = newMovie.Title.CleanMovieTitle(); - newMovie.SortTitle = MovieTitleNormalizer.Normalize(newMovie.Title, newMovie.TmdbId); + newMovie.MovieMetadata.Value.CleanTitle = newMovie.Title.CleanMovieTitle(); + newMovie.MovieMetadata.Value.SortTitle = MovieTitleNormalizer.Normalize(newMovie.Title, newMovie.TmdbId); newMovie.Added = DateTime.UtcNow; var validationResult = _addMovieValidator.Validate(newMovie); diff --git a/src/NzbDrone.Core/Movies/AddMovieValidator.cs b/src/NzbDrone.Core/Movies/AddMovieValidator.cs index 57da73e8d..00fdee689 100644 --- a/src/NzbDrone.Core/Movies/AddMovieValidator.cs +++ b/src/NzbDrone.Core/Movies/AddMovieValidator.cs @@ -14,8 +14,7 @@ namespace NzbDrone.Core.Movies public AddMovieValidator(RootFolderValidator rootFolderValidator, RecycleBinValidator recycleBinValidator, MoviePathValidator moviePathValidator, - MovieAncestorValidator movieAncestorValidator, - MovieTitleSlugValidator movieTitleSlugValidator) + MovieAncestorValidator movieAncestorValidator) { RuleFor(c => c.Path).Cascade(CascadeMode.StopOnFirstFailure) .IsValidPath() @@ -23,8 +22,6 @@ namespace NzbDrone.Core.Movies .SetValidator(recycleBinValidator) .SetValidator(moviePathValidator) .SetValidator(movieAncestorValidator); - - RuleFor(c => c.TitleSlug).SetValidator(movieTitleSlugValidator); } } } diff --git a/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitle.cs b/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitle.cs index 6645e265f..c3c5e2cd7 100644 --- a/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitle.cs +++ b/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitle.cs @@ -7,7 +7,7 @@ namespace NzbDrone.Core.Movies.AlternativeTitles public class AlternativeTitle : ModelBase { public SourceType SourceType { get; set; } - public int MovieId { get; set; } + public int MovieMetadataId { get; set; } public string Title { get; set; } public string CleanTitle { get; set; } public int SourceId { get; set; } diff --git a/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitleRepository.cs b/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitleRepository.cs index e3c7d5f6a..413d058db 100644 --- a/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitleRepository.cs +++ b/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitleRepository.cs @@ -9,7 +9,7 @@ namespace NzbDrone.Core.Movies.AlternativeTitles { AlternativeTitle FindBySourceId(int sourceId); List FindBySourceIds(List sourceIds); - List FindByMovieId(int movieId); + List FindByMovieMetadataId(int movieId); void DeleteForMovies(List movieIds); } @@ -30,14 +30,14 @@ namespace NzbDrone.Core.Movies.AlternativeTitles return Query(x => sourceIds.Contains(x.SourceId)); } - public List FindByMovieId(int movieId) + public List FindByMovieMetadataId(int movieId) { - return Query(x => x.MovieId == movieId); + return Query(x => x.MovieMetadataId == movieId); } public void DeleteForMovies(List movieIds) { - Delete(x => movieIds.Contains(x.MovieId)); + Delete(x => movieIds.Contains(x.MovieMetadataId)); } } } diff --git a/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitleService.cs b/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitleService.cs index 729149921..b25711a9c 100644 --- a/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitleService.cs +++ b/src/NzbDrone.Core/Movies/AlternativeTitles/AlternativeTitleService.cs @@ -11,11 +11,11 @@ namespace NzbDrone.Core.Movies.AlternativeTitles public interface IAlternativeTitleService { List GetAllTitlesForMovie(int movieId); - AlternativeTitle AddAltTitle(AlternativeTitle title, Movie movie); - List AddAltTitles(List titles, Movie movie); + AlternativeTitle AddAltTitle(AlternativeTitle title, MovieMetadata movie); + List AddAltTitles(List titles, MovieMetadata movie); AlternativeTitle GetById(int id); List GetAllTitles(); - List UpdateTitles(List titles, Movie movie); + List UpdateTitles(List titles, MovieMetadata movie); } public class AlternativeTitleService : IAlternativeTitleService, IHandleAsync @@ -38,18 +38,18 @@ namespace NzbDrone.Core.Movies.AlternativeTitles public List GetAllTitlesForMovie(int movieId) { - return _titleRepo.FindByMovieId(movieId).ToList(); + return _titleRepo.FindByMovieMetadataId(movieId).ToList(); } - public AlternativeTitle AddAltTitle(AlternativeTitle title, Movie movie) + public AlternativeTitle AddAltTitle(AlternativeTitle title, MovieMetadata movie) { - title.MovieId = movie.Id; + title.MovieMetadataId = movie.Id; return _titleRepo.Insert(title); } - public List AddAltTitles(List titles, Movie movie) + public List AddAltTitles(List titles, MovieMetadata movie) { - titles.ForEach(t => t.MovieId = movie.Id); + titles.ForEach(t => t.MovieMetadataId = movie.Id); _titleRepo.InsertMany(titles); return titles; } @@ -69,12 +69,12 @@ namespace NzbDrone.Core.Movies.AlternativeTitles _titleRepo.Delete(title); } - public List UpdateTitles(List titles, Movie movie) + public List UpdateTitles(List titles, MovieMetadata movie) { int movieId = movie.Id; // First update the movie ids so we can correlate them later. - titles.ForEach(t => t.MovieId = movieId); + titles.ForEach(t => t.MovieMetadataId = movieId); // Then make sure none of them are the same as the main title. titles = titles.Where(t => t.CleanTitle != movie.CleanTitle).ToList(); @@ -83,10 +83,10 @@ namespace NzbDrone.Core.Movies.AlternativeTitles titles = titles.DistinctBy(t => t.CleanTitle).ToList(); // Make sure we are not adding titles that exist for other movies (until language PR goes in) - titles = titles.Where(t => !_titleRepo.All().Any(e => e.CleanTitle == t.CleanTitle && e.MovieId != t.MovieId)).ToList(); + titles = titles.Where(t => !_titleRepo.All().Any(e => e.CleanTitle == t.CleanTitle && e.MovieMetadataId != t.MovieMetadataId)).ToList(); // Now find titles to delete, update and insert. - var existingTitles = _titleRepo.FindByMovieId(movieId); + var existingTitles = _titleRepo.FindByMovieMetadataId(movieId); var insert = titles.Where(t => !existingTitles.Contains(t)); var update = existingTitles.Where(t => titles.Contains(t)); @@ -101,7 +101,8 @@ namespace NzbDrone.Core.Movies.AlternativeTitles public void HandleAsync(MoviesDeletedEvent message) { - _titleRepo.DeleteForMovies(message.Movies.Select(m => m.Id).ToList()); + // TODO hanlde metadata delete instead of movie delete + _titleRepo.DeleteForMovies(message.Movies.Select(m => m.MovieMetadataId).ToList()); } } } diff --git a/src/NzbDrone.Core/Movies/Credits/Credit.cs b/src/NzbDrone.Core/Movies/Credits/Credit.cs index 690e4d2a8..b7d4cbabf 100644 --- a/src/NzbDrone.Core/Movies/Credits/Credit.cs +++ b/src/NzbDrone.Core/Movies/Credits/Credit.cs @@ -13,7 +13,7 @@ namespace NzbDrone.Core.Movies.Credits public string Name { get; set; } public string CreditTmdbId { get; set; } public int PersonTmdbId { get; set; } - public int MovieId { get; set; } + public int MovieMetadataId { get; set; } public List Images { get; set; } public string Department { get; set; } public string Job { get; set; } diff --git a/src/NzbDrone.Core/Movies/Credits/CreditRepository.cs b/src/NzbDrone.Core/Movies/Credits/CreditRepository.cs index 330fef6ff..92d684721 100644 --- a/src/NzbDrone.Core/Movies/Credits/CreditRepository.cs +++ b/src/NzbDrone.Core/Movies/Credits/CreditRepository.cs @@ -6,7 +6,7 @@ namespace NzbDrone.Core.Movies.Credits { public interface ICreditRepository : IBasicRepository { - List FindByMovieId(int movieId); + List FindByMovieMetadataId(int movieId); void DeleteForMovies(List movieIds); } @@ -17,14 +17,14 @@ namespace NzbDrone.Core.Movies.Credits { } - public List FindByMovieId(int movieId) + public List FindByMovieMetadataId(int movieId) { - return Query(x => x.MovieId == movieId); + return Query(x => x.MovieMetadataId == movieId); } public void DeleteForMovies(List movieIds) { - Delete(x => movieIds.Contains(x.MovieId)); + Delete(x => movieIds.Contains(x.MovieMetadataId)); } } } diff --git a/src/NzbDrone.Core/Movies/Credits/CreditService.cs b/src/NzbDrone.Core/Movies/Credits/CreditService.cs index da885b549..a094886bb 100644 --- a/src/NzbDrone.Core/Movies/Credits/CreditService.cs +++ b/src/NzbDrone.Core/Movies/Credits/CreditService.cs @@ -9,11 +9,11 @@ namespace NzbDrone.Core.Movies.Credits public interface ICreditService { List GetAllCreditsForMovie(int movieId); - Credit AddCredit(Credit credit, Movie movie); - List AddCredits(List credits, Movie movie); + Credit AddCredit(Credit credit, MovieMetadata movie); + List AddCredits(List credits, MovieMetadata movie); Credit GetById(int id); List GetAllCredits(); - List UpdateCredits(List credits, Movie movie); + List UpdateCredits(List credits, MovieMetadata movie); } public class CreditService : ICreditService, IHandleAsync @@ -27,18 +27,18 @@ namespace NzbDrone.Core.Movies.Credits public List GetAllCreditsForMovie(int movieId) { - return _creditRepo.FindByMovieId(movieId).ToList(); + return _creditRepo.FindByMovieMetadataId(movieId).ToList(); } - public Credit AddCredit(Credit credit, Movie movie) + public Credit AddCredit(Credit credit, MovieMetadata movie) { - credit.MovieId = movie.Id; + credit.MovieMetadataId = movie.Id; return _creditRepo.Insert(credit); } - public List AddCredits(List credits, Movie movie) + public List AddCredits(List credits, MovieMetadata movie) { - credits.ForEach(t => t.MovieId = movie.Id); + credits.ForEach(t => t.MovieMetadataId = movie.Id); _creditRepo.InsertMany(credits); return credits; } @@ -58,15 +58,15 @@ namespace NzbDrone.Core.Movies.Credits _creditRepo.Delete(credit); } - public List UpdateCredits(List credits, Movie movie) + public List UpdateCredits(List credits, MovieMetadata movie) { int movieId = movie.Id; // First update the movie ids so we can correlate them later. - credits.ForEach(t => t.MovieId = movieId); + credits.ForEach(t => t.MovieMetadataId = movieId); // Now find credits to delete, update and insert. - var existingCredits = _creditRepo.FindByMovieId(movieId); + var existingCredits = _creditRepo.FindByMovieMetadataId(movieId); // Should never have multiple credits with same credit_id, but check to ensure incase TMDB is on fritz var dupeFreeCredits = credits.DistinctBy(m => m.CreditTmdbId).ToList(); @@ -86,7 +86,8 @@ namespace NzbDrone.Core.Movies.Credits public void HandleAsync(MoviesDeletedEvent message) { - _creditRepo.DeleteForMovies(message.Movies.Select(m => m.Id).ToList()); + // TODO handle metadata deletions and not movie deletions + _creditRepo.DeleteForMovies(message.Movies.Select(m => m.MovieMetadataId).ToList()); } } } diff --git a/src/NzbDrone.Core/Movies/Entity.cs b/src/NzbDrone.Core/Movies/Entity.cs new file mode 100644 index 000000000..263fab774 --- /dev/null +++ b/src/NzbDrone.Core/Movies/Entity.cs @@ -0,0 +1,41 @@ +using System; +using Equ; +using NzbDrone.Core.Datastore; + +namespace NzbDrone.Core.Movies +{ + public abstract class Entity : ModelBase, IEquatable + where T : Entity + { + private static readonly MemberwiseEqualityComparer _comparer = + MemberwiseEqualityComparer.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); + } + } +} diff --git a/src/NzbDrone.Core/Movies/Movie.cs b/src/NzbDrone.Core/Movies/Movie.cs index 6af4387bf..cb02a39a1 100644 --- a/src/NzbDrone.Core/Movies/Movie.cs +++ b/src/NzbDrone.Core/Movies/Movie.cs @@ -2,10 +2,7 @@ using System; using System.Collections.Generic; using NzbDrone.Common.Extensions; using NzbDrone.Core.Datastore; -using NzbDrone.Core.Languages; using NzbDrone.Core.MediaFiles; -using NzbDrone.Core.Movies.AlternativeTitles; -using NzbDrone.Core.Movies.Translations; using NzbDrone.Core.Profiles; namespace NzbDrone.Core.Movies @@ -14,79 +11,54 @@ namespace NzbDrone.Core.Movies { public Movie() { - Images = new List(); - Genres = new List(); Tags = new HashSet(); - AlternativeTitles = new List(); - Translations = new List(); - Recommendations = new List(); - OriginalLanguage = Language.English; - Ratings = new Ratings(); + MovieMetadata = new MovieMetadata(); } - public int TmdbId { get; set; } - public string ImdbId { get; set; } - public string Title { get; set; } - public string CleanTitle { get; set; } - public string SortTitle { get; set; } - public MovieStatusType Status { get; set; } - public string Overview { get; set; } + public int MovieMetadataId { get; set; } + public bool Monitored { get; set; } public MovieStatusType MinimumAvailability { get; set; } public int ProfileId { get; set; } - public DateTime? LastInfoSync { get; set; } - public int Runtime { get; set; } - public List Images { get; set; } - public string TitleSlug { get; set; } - public string Website { get; set; } + public string Path { get; set; } - public int Year { get; set; } - public Ratings Ratings { get; set; } - public List Genres { get; set; } - public MovieCollection Collection { get; set; } + public LazyLoaded MovieMetadata { get; set; } - public string Certification { get; set; } public string RootFolderPath { get; set; } public DateTime Added { get; set; } - public DateTime? InCinemas { get; set; } - public DateTime? PhysicalRelease { get; set; } - public DateTime? DigitalRelease { get; set; } public Profile Profile { get; set; } public HashSet Tags { get; set; } public AddMovieOptions AddOptions { get; set; } public MovieFile MovieFile { get; set; } public int MovieFileId { get; set; } - //Get Loaded via a Join Query - public List AlternativeTitles { get; set; } - public List 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 Recommendations { get; set; } + public bool HasFile => MovieFileId > 0; - public bool IsRecentMovie + //compatibility properties + public string Title { - get - { - if (PhysicalRelease.HasValue) - { - return PhysicalRelease.Value >= DateTime.UtcNow.AddDays(-21); - } - - if (InCinemas.HasValue) - { - return InCinemas.Value >= DateTime.UtcNow.AddDays(-120); - } - - return true; - } + get { return MovieMetadata.Value.Title; } + set { MovieMetadata.Value.Title = value; } } - public bool HasFile => MovieFileId > 0; + public int TmdbId + { + get { return MovieMetadata.Value.TmdbId; } + set { MovieMetadata.Value.TmdbId = value; } + } + + public string ImdbId + { + get { return MovieMetadata.Value.ImdbId; } + set { MovieMetadata.Value.ImdbId = value; } + } + + public int Year + { + get { return MovieMetadata.Value.Year; } + set { MovieMetadata.Value.Year = value; } + } public string FolderName() { @@ -112,27 +84,27 @@ namespace NzbDrone.Core.Movies { minimumAvailabilityDate = DateTime.MinValue; } - else if (MinimumAvailability == MovieStatusType.InCinemas && InCinemas.HasValue) + else if (MinimumAvailability == MovieStatusType.InCinemas && MovieMetadata.Value.InCinemas.HasValue) { - minimumAvailabilityDate = InCinemas.Value; + minimumAvailabilityDate = MovieMetadata.Value.InCinemas.Value; } else { - if (PhysicalRelease.HasValue && DigitalRelease.HasValue) + if (MovieMetadata.Value.PhysicalRelease.HasValue && MovieMetadata.Value.DigitalRelease.HasValue) { - minimumAvailabilityDate = new DateTime(Math.Min(PhysicalRelease.Value.Ticks, DigitalRelease.Value.Ticks)); + minimumAvailabilityDate = new DateTime(Math.Min(MovieMetadata.Value.PhysicalRelease.Value.Ticks, MovieMetadata.Value.DigitalRelease.Value.Ticks)); } - else if (PhysicalRelease.HasValue) + else if (MovieMetadata.Value.PhysicalRelease.HasValue) { - minimumAvailabilityDate = PhysicalRelease.Value; + minimumAvailabilityDate = MovieMetadata.Value.PhysicalRelease.Value; } - else if (DigitalRelease.HasValue) + else if (MovieMetadata.Value.DigitalRelease.HasValue) { - minimumAvailabilityDate = DigitalRelease.Value; + minimumAvailabilityDate = MovieMetadata.Value.DigitalRelease.Value; } else { - minimumAvailabilityDate = InCinemas.HasValue ? InCinemas.Value.AddDays(90) : DateTime.MaxValue; + minimumAvailabilityDate = MovieMetadata.Value.InCinemas.HasValue ? MovieMetadata.Value.InCinemas.Value.AddDays(90) : DateTime.MaxValue; } } @@ -144,20 +116,13 @@ namespace NzbDrone.Core.Movies return DateTime.Now >= minimumAvailabilityDate.AddDays((double)delay); } - public DateTime PhysicalReleaseDate() - { - return PhysicalRelease ?? (InCinemas?.AddDays(90) ?? DateTime.MaxValue); - } - public override string ToString() { - return string.Format("[{1} ({2})][{0}, {3}]", ImdbId, Title.NullSafe(), Year.NullSafe(), TmdbId); + return string.Format("[{1} ({2})][{0}, {3}]", MovieMetadata.Value.ImdbId, MovieMetadata.Value.Title.NullSafe(), MovieMetadata.Value.Year.NullSafe(), MovieMetadata.Value.TmdbId); } public void ApplyChanges(Movie otherMovie) { - TmdbId = otherMovie.TmdbId; - Path = otherMovie.Path; ProfileId = otherMovie.ProfileId; diff --git a/src/NzbDrone.Core/Movies/MovieMetadata.cs b/src/NzbDrone.Core/Movies/MovieMetadata.cs new file mode 100644 index 000000000..b1082b198 --- /dev/null +++ b/src/NzbDrone.Core/Movies/MovieMetadata.cs @@ -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 + { + public MovieMetadata() + { + AlternativeTitles = new List(); + Translations = new List(); + Images = new List(); + Genres = new List(); + OriginalLanguage = Language.English; + Recommendations = new List(); + Ratings = new Ratings(); + } + + public int TmdbId { get; set; } + + public List Images { get; set; } + public List 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 AlternativeTitles { get; set; } + public List 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 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); + } + } +} diff --git a/src/NzbDrone.Core/Movies/MovieMetadataRepository.cs b/src/NzbDrone.Core/Movies/MovieMetadataRepository.cs new file mode 100644 index 000000000..78f9b7a29 --- /dev/null +++ b/src/NzbDrone.Core/Movies/MovieMetadataRepository.cs @@ -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 FindByTmdbId(int tmdbId); + List FindById(List tmdbIds); + bool UpsertMany(List data); + } + + public class MovieMetadataRepository : BasicRepository, 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 FindById(List tmdbIds) + { + return Query(x => Enumerable.Contains(tmdbIds, x.TmdbId)); + } + + public bool UpsertMany(List data) + { + var existingMetadata = FindById(data.Select(x => x.TmdbId).ToList()); + var updateMetadataList = new List(); + var addMetadataList = new List(); + 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; + } + } +} diff --git a/src/NzbDrone.Core/Movies/MovieMetadataService.cs b/src/NzbDrone.Core/Movies/MovieMetadataService.cs new file mode 100644 index 000000000..172296e32 --- /dev/null +++ b/src/NzbDrone.Core/Movies/MovieMetadataService.cs @@ -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 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 { movie }); + } + + public bool UpsertMany(List movies) + { + return _movieMetadataRepository.UpsertMany(movies); + } + } +} diff --git a/src/NzbDrone.Core/Movies/MovieRepository.cs b/src/NzbDrone.Core/Movies/MovieRepository.cs index 8844f0539..13a983bc3 100644 --- a/src/NzbDrone.Core/Movies/MovieRepository.cs +++ b/src/NzbDrone.Core/Movies/MovieRepository.cs @@ -20,7 +20,6 @@ namespace NzbDrone.Core.Movies Movie FindByImdbId(string imdbid); Movie FindByTmdbId(int tmdbid); List FindByTmdbId(List tmdbids); - Movie FindByTitleSlug(string slug); List MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored); PagingSpec MoviesWithoutFiles(PagingSpec pagingSpec); List GetMoviesByFileId(int fileId); @@ -28,7 +27,6 @@ namespace NzbDrone.Core.Movies PagingSpec MoviesWhereCutoffUnmet(PagingSpec pagingSpec, List qualitiesBelowCutoff); Movie FindByPath(string path); Dictionary AllMoviePaths(); - Dictionary AllMovieTitleSlugs(); List AllMovieTmdbIds(); Dictionary> AllMovieTags(); List GetRecommendations(); @@ -51,10 +49,11 @@ namespace NzbDrone.Core.Movies protected override SqlBuilder Builder() => new SqlBuilder(_database.DatabaseType) .Join((m, p) => m.ProfileId == p.Id) - .LeftJoin((m, t) => m.Id == t.MovieId) - .LeftJoin((m, f) => m.Id == f.MovieId); + .Join((m, p) => m.MovieMetadataId == p.Id) + .LeftJoin((m, f) => m.Id == f.MovieId) + .LeftJoin((mm, t) => mm.Id == t.MovieMetadataId); - private Movie Map(Dictionary dict, Movie movie, Profile profile, AlternativeTitle altTitle, MovieFile movieFile, MovieTranslation translation = null) + private Movie Map(Dictionary dict, Movie movie, Profile profile, MovieFile movieFile, AlternativeTitle altTitle = null, MovieTranslation translation = null) { Movie movieEntry; @@ -68,12 +67,12 @@ namespace NzbDrone.Core.Movies if (altTitle != null) { - movieEntry.AlternativeTitles.Add(altTitle); + movieEntry.MovieMetadata.Value.AlternativeTitles.Add(altTitle); } if (translation != null) { - movieEntry.Translations.Add(translation); + movieEntry.MovieMetadata.Value.Translations.Add(translation); } return movieEntry; @@ -83,9 +82,9 @@ namespace NzbDrone.Core.Movies { var movieDictionary = new Dictionary(); - _ = _database.QueryJoined( + _ = _database.QueryJoined( builder, - (movie, profile, altTitle, file) => Map(movieDictionary, movie, profile, altTitle, file)); + (movie, profile, file, altTitle) => Map(movieDictionary, movie, profile, file, altTitle)); return movieDictionary.Values.ToList(); } @@ -95,23 +94,25 @@ namespace NzbDrone.Core.Movies // the skips the join on profile and alternative title and populates manually // to avoid repeatedly deserializing the same profile / movie var builder = new SqlBuilder(_database.DatabaseType) - .LeftJoin((m, f) => m.MovieFileId == f.Id); + .LeftJoin((m, f) => m.MovieFileId == f.Id) + .LeftJoin((m, f) => m.MovieMetadataId == f.Id); var profiles = _profileRepository.All().ToDictionary(x => x.Id); var titles = _alternativeTitleRepository.All() - .GroupBy(x => x.MovieId) + .GroupBy(x => x.MovieMetadataId) .ToDictionary(x => x.Key, y => y.ToList()); - return _database.QueryJoined( + return _database.QueryJoined( builder, - (movie, file) => + (movie, file, metadata) => { movie.MovieFile = file; + movie.MovieMetadata = metadata; movie.Profile = profiles[movie.ProfileId]; - if (titles.TryGetValue(movie.Id, out var altTitles)) + if (titles.TryGetValue(movie.MovieMetadataId, out var altTitles)) { - movie.AlternativeTitles = altTitles; + movie.MovieMetadata.Value.AlternativeTitles = altTitles; } return movie; @@ -142,30 +143,15 @@ namespace NzbDrone.Core.Movies { var movieDictionary = new Dictionary(); - SqlBuilder builder; - - if (_database.DatabaseType == DatabaseType.PostgreSQL) - { - builder = new SqlBuilder(_database.DatabaseType) - .LeftJoin((m, t) => m.Id == t.MovieId) - .LeftJoin((m, f) => m.Id == f.MovieId) - .LeftJoin((m, tr) => m.Id == tr.MovieId) + var builder = new SqlBuilder(_database.DatabaseType) .Join((m, p) => m.ProfileId == p.Id) - .WherePostgres(x => titles.Contains(x.CleanTitle)); - } - else - { - builder = new SqlBuilder(_database.DatabaseType) - .LeftJoin((m, t) => m.Id == t.MovieId) + .Join((m, p) => m.MovieMetadataId == p.Id) .LeftJoin((m, f) => m.Id == f.MovieId) - .LeftJoin((m, tr) => m.Id == tr.MovieId) - .Join((m, p) => m.ProfileId == p.Id) - .Where(x => titles.Contains(x.CleanTitle)); - } + .Where(x => titles.Contains(x.CleanTitle) || titles.Contains(x.CleanOriginalTitle)); - _ = _database.QueryJoined( + _ = _database.QueryJoined( builder, - (movie, profile, altTitle, file, trans) => Map(movieDictionary, movie, profile, altTitle, file, trans)); + (movie, profile, file) => Map(movieDictionary, movie, profile, file)); return movieDictionary.Values.ToList(); } @@ -174,32 +160,18 @@ namespace NzbDrone.Core.Movies { var movieDictionary = new Dictionary(); - SqlBuilder builder; + var builder = new SqlBuilder(_database.DatabaseType) + .Join((t, mm) => t.MovieMetadataId == mm.Id) + .Join((mm, m) => mm.Id == m.MovieMetadataId) + .Join((m, p) => m.ProfileId == p.Id) + .LeftJoin((m, f) => m.Id == f.MovieId) + .Where(x => titles.Contains(x.CleanTitle)); - if (_database.DatabaseType == DatabaseType.PostgreSQL) - { - builder = new SqlBuilder(_database.DatabaseType) - .LeftJoin((m, p) => m.ProfileId == p.Id) - .LeftJoin((m, f) => m.Id == f.MovieId) - .LeftJoin((m, tr) => m.Id == tr.MovieId) - .Join((t, m) => t.MovieId == m.Id) - .WherePostgres(x => titles.Contains(x.CleanTitle)); - } - else - { - builder = new SqlBuilder(_database.DatabaseType) - .LeftJoin((t, m) => t.MovieId == m.Id) - .LeftJoin((m, f) => m.Id == f.MovieId) - .LeftJoin((m, tr) => m.Id == tr.MovieId) - .Join((m, p) => m.ProfileId == p.Id) - .Where(x => titles.Contains(x.CleanTitle)); - } - - _ = _database.QueryJoined( + _ = _database.QueryJoined( builder, - (altTitle, profile, movie, file, trans) => + (altTitle, profile, movie, file) => { - _ = Map(movieDictionary, movie, profile, altTitle, file, trans); + _ = Map(movieDictionary, movie, profile, file, altTitle); return null; }); @@ -210,32 +182,18 @@ namespace NzbDrone.Core.Movies { var movieDictionary = new Dictionary(); - SqlBuilder builder; - - if (_database.DatabaseType == DatabaseType.PostgreSQL) - { - builder = new SqlBuilder(_database.DatabaseType) - .LeftJoin((m, p) => m.ProfileId == p.Id) - .LeftJoin((m, t) => m.Id == t.MovieId) - .LeftJoin((m, f) => m.Id == f.MovieId) - .Join((tr, m) => tr.MovieId == m.Id) - .WherePostgres(x => titles.Contains(x.CleanTitle)); - } - else - { - builder = new SqlBuilder(_database.DatabaseType) - .LeftJoin((tr, m) => tr.MovieId == m.Id) - .LeftJoin((m, t) => m.Id == t.MovieId) - .LeftJoin((m, f) => m.Id == f.MovieId) + var builder = new SqlBuilder(_database.DatabaseType) + .Join((t, mm) => t.MovieMetadataId == mm.Id) + .Join((mm, m) => mm.Id == m.MovieMetadataId) .Join((m, p) => m.ProfileId == p.Id) + .LeftJoin((m, f) => m.Id == f.MovieId) .Where(x => titles.Contains(x.CleanTitle)); - } - _ = _database.QueryJoined( + _ = _database.QueryJoined( builder, - (trans, profile, movie, file, altTitle) => + (trans, profile, movie, file) => { - _ = Map(movieDictionary, movie, profile, altTitle, file, trans); + _ = Map(movieDictionary, movie, profile, file, null, trans); return null; }); @@ -245,12 +203,12 @@ namespace NzbDrone.Core.Movies public Movie FindByImdbId(string imdbid) { var imdbIdWithPrefix = Parser.Parser.NormalizeImdbId(imdbid); - return imdbIdWithPrefix == null ? null : Query(x => x.ImdbId == imdbIdWithPrefix).FirstOrDefault(); + return imdbIdWithPrefix == null ? null : Query(x => x.MovieMetadata.Value.ImdbId == imdbIdWithPrefix).FirstOrDefault(); } public Movie FindByTmdbId(int tmdbid) { - return Query(x => x.TmdbId == tmdbid).FirstOrDefault(); + return Query(x => x.MovieMetadata.Value.TmdbId == tmdbid).FirstOrDefault(); } public List FindByTmdbId(List tmdbids) @@ -268,18 +226,13 @@ namespace NzbDrone.Core.Movies SetFields(new Movie { Id = movieId, MovieFileId = fileId }, movie => movie.MovieFileId); } - public Movie FindByTitleSlug(string slug) - { - return Query(x => x.TitleSlug == slug).FirstOrDefault(); - } - public List MoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored) { var builder = Builder() .Where(m => - (m.InCinemas >= start && m.InCinemas <= end) || - (m.PhysicalRelease >= start && m.PhysicalRelease <= end) || - (m.DigitalRelease >= start && m.DigitalRelease <= end)); + (m.MovieMetadata.Value.InCinemas >= start && m.MovieMetadata.Value.InCinemas <= end) || + (m.MovieMetadata.Value.PhysicalRelease >= start && m.MovieMetadata.Value.PhysicalRelease <= end) || + (m.MovieMetadata.Value.DigitalRelease >= start && m.MovieMetadata.Value.DigitalRelease <= end)); if (!includeUnmonitored) { @@ -341,20 +294,11 @@ namespace NzbDrone.Core.Movies } } - public Dictionary AllMovieTitleSlugs() - { - using (var conn = _database.OpenConnection()) - { - var strSql = "SELECT \"Id\" AS \"Key\", \"TitleSlug\" AS \"Value\" FROM \"Movies\""; - return conn.Query>(strSql).ToDictionary(x => x.Key, x => x.Value); - } - } - public List AllMovieTmdbIds() { using (var conn = _database.OpenConnection()) { - return conn.Query("SELECT \"TmdbId\" FROM \"Movies\"").ToList(); + return conn.Query("SELECT \"TmdbId\" FROM \"MovieMetadata\" JOIN \"Movies\" ON (\"Movies\".\"MovieMetadataId\" = \"MovieMetadata\".\"Id\")").ToList(); } } @@ -383,14 +327,14 @@ namespace NzbDrone.Core.Movies recommendations = conn.Query(@"SELECT DISTINCT ""Rec"" FROM ( SELECT DISTINCT ""Rec"" FROM ( - SELECT DISTINCT CAST(""value"" AS INT) AS ""Rec"" FROM ""Movies"", json_array_elements_text((""Movies"".""Recommendations"")::json) - WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub1) LIMIT 10 + SELECT DISTINCT CAST(""value"" AS INT) AS ""Rec"" FROM ""MovieMetadata"", json_array_elements_text((""MovieMetadata"".""Recommendations"")::json) + WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub1) LIMIT 10 ) as sub2 UNION SELECT ""Rec"" FROM ( - SELECT CAST(""value"" AS INT) AS ""Rec"" FROM ""Movies"", json_array_elements_text((""Movies"".""Recommendations"")::json) - WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub2) + SELECT CAST(""value"" AS INT) AS ""Rec"" FROM ""MovieMetadata"", json_array_elements_text((""MovieMetadata"".""Recommendations"")::json) + WHERE CAST(""value"" AS INT) NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"" as sub2) GROUP BY ""Rec"" ORDER BY count(*) DESC LIMIT 120 ) as sub4 ) as sub5 @@ -401,14 +345,14 @@ namespace NzbDrone.Core.Movies recommendations = conn.Query(@"SELECT DISTINCT ""Rec"" FROM ( SELECT DISTINCT ""Rec"" FROM ( - SELECT DISTINCT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""Movies"" CROSS JOIN json_each(""Movies"".""Recommendations"") AS ""j"" - WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"") LIMIT 10 + SELECT DISTINCT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""MovieMetadata"" CROSS JOIN json_each(""MovieMetadata"".""Recommendations"") AS ""j"" + WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"") LIMIT 10 ) UNION SELECT ""Rec"" FROM ( - SELECT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""Movies"" CROSS JOIN json_each(""Movies"".""Recommendations"") AS ""j"" - WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""Movies"" union SELECT ""TmdbId"" from ""ImportExclusions"") + SELECT CAST(""j"".""value"" AS INT) AS ""Rec"" FROM ""MovieMetadata"" CROSS JOIN json_each(""MovieMetadata"".""Recommendations"") AS ""j"" + WHERE ""Rec"" NOT IN (SELECT ""TmdbId"" FROM ""MovieMetadata"" union SELECT ""TmdbId"" from ""ImportExclusions"") GROUP BY ""Rec"" ORDER BY count(*) DESC LIMIT 120 ) ) diff --git a/src/NzbDrone.Core/Movies/MovieService.cs b/src/NzbDrone.Core/Movies/MovieService.cs index a2688328d..4373cb364 100644 --- a/src/NzbDrone.Core/Movies/MovieService.cs +++ b/src/NzbDrone.Core/Movies/MovieService.cs @@ -29,11 +29,9 @@ namespace NzbDrone.Core.Movies Movie FindByTitle(string title, int year); Movie FindByTitle(List titles, int? year, List otherTitles, List candidates); List FindByTitleCandidates(List titles, out List otherTitles); - Movie FindByTitleSlug(string slug); Movie FindByPath(string path); Dictionary AllMoviePaths(); List AllMovieTmdbIds(); - Dictionary AllMovieTitleSlugs(); bool MovieExists(Movie movie); List GetMoviesByFileId(int fileId); List GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored); @@ -120,18 +118,18 @@ namespace NzbDrone.Core.Movies public Movie FindByTitle(List cleanTitles, int? year, List otherTitles, List candidates) { - var result = candidates.Where(x => cleanTitles.Contains(x.CleanTitle)).FirstWithYear(year); + var result = candidates.Where(x => cleanTitles.Contains(x.MovieMetadata.Value.CleanTitle)).FirstWithYear(year); if (result == null) { result = - candidates.Where(movie => otherTitles.Contains(movie.CleanTitle)).FirstWithYear(year); + candidates.Where(movie => otherTitles.Contains(movie.MovieMetadata.Value.CleanTitle)).FirstWithYear(year); } if (result == null) { result = candidates - .Where(m => m.AlternativeTitles.Any(t => cleanTitles.Contains(t.CleanTitle) || + .Where(m => m.MovieMetadata.Value.AlternativeTitles.Any(t => cleanTitles.Contains(t.CleanTitle) || otherTitles.Contains(t.CleanTitle))) .FirstWithYear(year); } @@ -139,7 +137,7 @@ namespace NzbDrone.Core.Movies if (result == null) { result = candidates - .Where(m => m.Translations.Any(t => cleanTitles.Contains(t.CleanTitle) || + .Where(m => m.MovieMetadata.Value.Translations.Any(t => cleanTitles.Contains(t.CleanTitle) || otherTitles.Contains(t.CleanTitle))) .FirstWithYear(year); } @@ -201,11 +199,6 @@ namespace NzbDrone.Core.Movies return _movieRepository.AllMoviePaths(); } - public Dictionary AllMovieTitleSlugs() - { - return _movieRepository.AllMovieTitleSlugs(); - } - public List AllMovieTmdbIds() { return _movieRepository.AllMovieTmdbIds(); @@ -300,11 +293,6 @@ namespace NzbDrone.Core.Movies return _movieRepository.GetMoviesByFileId(fileId); } - public Movie FindByTitleSlug(string slug) - { - return _movieRepository.FindByTitleSlug(slug); - } - public List GetMoviesBetweenDates(DateTime start, DateTime end, bool includeUnmonitored) { var movies = _movieRepository.MoviesBetweenDates(start.ToUniversalTime(), end.ToUniversalTime(), includeUnmonitored); @@ -375,7 +363,7 @@ namespace NzbDrone.Core.Movies var ret = withTmdbid.ExceptBy(m => m.TmdbId, allMovies, m => m.TmdbId, EqualityComparer.Default) .Union(withImdbid.ExceptBy(m => m.ImdbId, allMovies, m => m.ImdbId, EqualityComparer.Default)) - .Union(rest.ExceptBy(m => m.Title.CleanMovieTitle(), allMovies, m => m.CleanTitle, EqualityComparer.Default)).ToList(); + .Union(rest.ExceptBy(m => m.Title.CleanMovieTitle(), allMovies, m => m.MovieMetadata.Value.CleanTitle, EqualityComparer.Default)).ToList(); return ret; } diff --git a/src/NzbDrone.Core/Movies/MovieTitleSlugValidator.cs b/src/NzbDrone.Core/Movies/MovieTitleSlugValidator.cs deleted file mode 100644 index 07ef8b33e..000000000 --- a/src/NzbDrone.Core/Movies/MovieTitleSlugValidator.cs +++ /dev/null @@ -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))) - { - return true; - } - - var conflictingMovie = _movieService.GetMovie(conflictingId.Key); - - context.MessageFormatter.AppendArgument("slug", slug); - context.MessageFormatter.AppendArgument("movieTitle", conflictingMovie.Title); - - return false; - } - } -} diff --git a/src/NzbDrone.Core/Movies/QueryExtensions.cs b/src/NzbDrone.Core/Movies/QueryExtensions.cs index c2876631a..ac900eff4 100644 --- a/src/NzbDrone.Core/Movies/QueryExtensions.cs +++ b/src/NzbDrone.Core/Movies/QueryExtensions.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; namespace NzbDrone.Core.Movies @@ -7,7 +7,7 @@ namespace NzbDrone.Core.Movies { public static Movie FirstWithYear(this IEnumerable 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(); } } } diff --git a/src/NzbDrone.Core/Movies/Ratings.cs b/src/NzbDrone.Core/Movies/Ratings.cs index 3cf61fdea..e2103938d 100644 --- a/src/NzbDrone.Core/Movies/Ratings.cs +++ b/src/NzbDrone.Core/Movies/Ratings.cs @@ -1,8 +1,9 @@ +using Equ; using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Movies { - public class Ratings : IEmbeddedDocument + public class Ratings : MemberwiseEquatable, IEmbeddedDocument { public RatingChild Imdb { get; set; } public RatingChild Tmdb { get; set; } diff --git a/src/NzbDrone.Core/Movies/RefreshMovieService.cs b/src/NzbDrone.Core/Movies/RefreshMovieService.cs index bd00c2bd1..40a08bafe 100644 --- a/src/NzbDrone.Core/Movies/RefreshMovieService.cs +++ b/src/NzbDrone.Core/Movies/RefreshMovieService.cs @@ -23,6 +23,7 @@ namespace NzbDrone.Core.Movies { private readonly IProvideMovieInfo _movieInfo; private readonly IMovieService _movieService; + private readonly IMovieMetadataService _movieMetadataService; private readonly IMovieTranslationService _movieTranslationService; private readonly IAlternativeTitleService _titleService; private readonly ICreditService _creditService; @@ -35,6 +36,7 @@ namespace NzbDrone.Core.Movies public RefreshMovieService(IProvideMovieInfo movieInfo, IMovieService movieService, + IMovieMetadataService movieMetadataService, IMovieTranslationService movieTranslationService, IAlternativeTitleService titleService, ICreditService creditService, @@ -46,6 +48,7 @@ namespace NzbDrone.Core.Movies { _movieInfo = movieInfo; _movieService = movieService; + _movieMetadataService = movieMetadataService; _movieTranslationService = movieTranslationService; _titleService = titleService; _creditService = creditService; @@ -61,10 +64,11 @@ namespace NzbDrone.Core.Movies // Get the movie before updating, that way any changes made to the movie after the refresh started, // but before this movie was refreshed won't be lost. var movie = _movieService.GetMovie(movieId); + var movieMetadata = _movieMetadataService.Get(movie.MovieMetadataId); _logger.ProgressInfo("Updating info for {0}", movie.Title); - Movie movieInfo; + MovieMetadata movieInfo; List credits; try @@ -75,10 +79,10 @@ namespace NzbDrone.Core.Movies } catch (MovieNotFoundException) { - if (movie.Status != MovieStatusType.Deleted) + if (movieMetadata.Status != MovieStatusType.Deleted) { - movie.Status = MovieStatusType.Deleted; - _movieService.UpdateMovie(movie); + movieMetadata.Status = MovieStatusType.Deleted; + _movieMetadataService.Upsert(movieMetadata); _logger.Debug("Movie marked as deleted on TMDb for {0}", movie.Title); _eventAggregator.PublishEvent(new MovieUpdatedEvent(movie)); } @@ -86,56 +90,47 @@ namespace NzbDrone.Core.Movies throw; } - if (movie.TmdbId != movieInfo.TmdbId) + if (movieMetadata.TmdbId != movieInfo.TmdbId) { _logger.Warn("Movie '{0}' (TMDb: {1}) was replaced with '{2}' (TMDb: {3}), because the original was a duplicate.", movie.Title, movie.TmdbId, movieInfo.Title, movieInfo.TmdbId); - movie.TmdbId = movieInfo.TmdbId; + movieMetadata.TmdbId = movieInfo.TmdbId; } - movie.Title = movieInfo.Title; - movie.TitleSlug = movieInfo.TitleSlug; - movie.ImdbId = movieInfo.ImdbId; - movie.Overview = movieInfo.Overview; - movie.Status = movieInfo.Status; - movie.CleanTitle = movieInfo.CleanTitle; - movie.SortTitle = movieInfo.SortTitle; - movie.LastInfoSync = DateTime.UtcNow; - movie.Runtime = movieInfo.Runtime; - movie.Images = movieInfo.Images; - movie.Ratings = movieInfo.Ratings; - movie.Collection = movieInfo.Collection; - movie.Genres = movieInfo.Genres; - movie.Certification = movieInfo.Certification; - movie.InCinemas = movieInfo.InCinemas; - movie.Website = movieInfo.Website; + movieMetadata.Title = movieInfo.Title; + movieMetadata.ImdbId = movieInfo.ImdbId; + movieMetadata.Overview = movieInfo.Overview; + movieMetadata.Status = movieInfo.Status; + movieMetadata.CleanTitle = movieInfo.CleanTitle; + movieMetadata.SortTitle = movieInfo.SortTitle; + movieMetadata.LastInfoSync = DateTime.UtcNow; + movieMetadata.Runtime = movieInfo.Runtime; + movieMetadata.Ratings = movieInfo.Ratings; + movieMetadata.Collection = movieInfo.Collection; - movie.Year = movieInfo.Year; - movie.SecondaryYear = movieInfo.SecondaryYear; - movie.PhysicalRelease = movieInfo.PhysicalRelease; - movie.DigitalRelease = movieInfo.DigitalRelease; - movie.YouTubeTrailerId = movieInfo.YouTubeTrailerId; - movie.Studio = movieInfo.Studio; - movie.OriginalTitle = movieInfo.OriginalTitle; - movie.OriginalLanguage = movieInfo.OriginalLanguage; - movie.Recommendations = movieInfo.Recommendations; + //movie.Genres = movieInfo.Genres; + movieMetadata.Certification = movieInfo.Certification; + movieMetadata.InCinemas = movieInfo.InCinemas; + movieMetadata.Website = movieInfo.Website; - try - { - movie.Path = new DirectoryInfo(movie.Path).FullName; - movie.Path = movie.Path.GetActualCasing(); - } - catch (Exception e) - { - _logger.Warn(e, "Couldn't update movie path for " + movie.Path); - } + movieMetadata.Year = movieInfo.Year; + movieMetadata.SecondaryYear = movieInfo.SecondaryYear; + movieMetadata.PhysicalRelease = movieInfo.PhysicalRelease; + movieMetadata.DigitalRelease = movieInfo.DigitalRelease; + movieMetadata.YouTubeTrailerId = movieInfo.YouTubeTrailerId; + movieMetadata.Studio = movieInfo.Studio; + movieMetadata.OriginalTitle = movieInfo.OriginalTitle; + movieMetadata.CleanOriginalTitle = movieInfo.CleanOriginalTitle; + movieMetadata.OriginalLanguage = movieInfo.OriginalLanguage; + movieMetadata.Recommendations = movieInfo.Recommendations; + movieMetadata.Popularity = movieInfo.Popularity; - movie.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movie); - _movieTranslationService.UpdateTranslations(movieInfo.Translations, movie); + movieMetadata.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movieMetadata); + _movieTranslationService.UpdateTranslations(movieInfo.Translations, movieMetadata); - _movieService.UpdateMovie(new List { movie }, true); - _creditService.UpdateCredits(credits, movie); + _movieMetadataService.Upsert(movieMetadata); + _creditService.UpdateCredits(credits, movieMetadata); - _logger.Debug("Finished movie refresh for {0}", movie.Title); + _logger.Debug("Finished movie metadata refresh for {0}", movieMetadata.Title); _eventAggregator.PublishEvent(new MovieUpdatedEvent(movie)); return movie; @@ -208,7 +203,8 @@ namespace NzbDrone.Core.Movies } else { - var allMovie = _movieService.GetAllMovies().OrderBy(c => c.SortTitle).ToList(); + // TODO refresh all moviemetadata here, even if not used by a Movie + var allMovie = _movieService.GetAllMovies().OrderBy(c => c.MovieMetadata.Value.SortTitle).ToList(); var updatedTMDBMovies = new HashSet(); @@ -220,7 +216,7 @@ namespace NzbDrone.Core.Movies foreach (var movie in allMovie) { var movieLocal = movie; - if ((updatedTMDBMovies.Count == 0 && _checkIfMovieShouldBeRefreshed.ShouldRefresh(movie)) || updatedTMDBMovies.Contains(movie.TmdbId) || message.Trigger == CommandTrigger.Manual) + if ((updatedTMDBMovies.Count == 0 && _checkIfMovieShouldBeRefreshed.ShouldRefresh(movie.MovieMetadata)) || updatedTMDBMovies.Contains(movie.TmdbId) || message.Trigger == CommandTrigger.Manual) { try { diff --git a/src/NzbDrone.Core/Movies/ShouldRefreshMovie.cs b/src/NzbDrone.Core/Movies/ShouldRefreshMovie.cs index 18d005470..c81b6e3bb 100644 --- a/src/NzbDrone.Core/Movies/ShouldRefreshMovie.cs +++ b/src/NzbDrone.Core/Movies/ShouldRefreshMovie.cs @@ -5,7 +5,7 @@ namespace NzbDrone.Core.Movies { public interface ICheckIfMovieShouldBeRefreshed { - bool ShouldRefresh(Movie movie); + bool ShouldRefresh(MovieMetadata movie); } public class ShouldRefreshMovie : ICheckIfMovieShouldBeRefreshed @@ -17,7 +17,7 @@ namespace NzbDrone.Core.Movies _logger = logger; } - public bool ShouldRefresh(Movie movie) + public bool ShouldRefresh(MovieMetadata movie) { //return false; if (movie.LastInfoSync < DateTime.UtcNow.AddDays(-180)) diff --git a/src/NzbDrone.Core/Movies/Translations/MovieTranslation.cs b/src/NzbDrone.Core/Movies/Translations/MovieTranslation.cs index b02d1add9..8d514832d 100644 --- a/src/NzbDrone.Core/Movies/Translations/MovieTranslation.cs +++ b/src/NzbDrone.Core/Movies/Translations/MovieTranslation.cs @@ -5,7 +5,7 @@ namespace NzbDrone.Core.Movies.Translations { public class MovieTranslation : ModelBase { - public int MovieId { get; set; } + public int MovieMetadataId { get; set; } public string Title { get; set; } public string CleanTitle { get; set; } public string Overview { get; set; } diff --git a/src/NzbDrone.Core/Movies/Translations/MovieTranslationRepository.cs b/src/NzbDrone.Core/Movies/Translations/MovieTranslationRepository.cs index a9e2023f2..aae9b818e 100644 --- a/src/NzbDrone.Core/Movies/Translations/MovieTranslationRepository.cs +++ b/src/NzbDrone.Core/Movies/Translations/MovieTranslationRepository.cs @@ -7,7 +7,7 @@ namespace NzbDrone.Core.Movies.Translations { public interface IMovieTranslationRepository : IBasicRepository { - List FindByMovieId(int movieId); + List FindByMovieMetadataId(int movieId); List FindByLanguage(Language language); void DeleteForMovies(List movieIds); } @@ -19,9 +19,9 @@ namespace NzbDrone.Core.Movies.Translations { } - public List FindByMovieId(int movieId) + public List FindByMovieMetadataId(int movieId) { - return Query(x => x.MovieId == movieId); + return Query(x => x.MovieMetadataId == movieId); } public List FindByLanguage(Language language) @@ -31,7 +31,7 @@ namespace NzbDrone.Core.Movies.Translations public void DeleteForMovies(List movieIds) { - Delete(x => movieIds.Contains(x.MovieId)); + Delete(x => movieIds.Contains(x.MovieMetadataId)); } } } diff --git a/src/NzbDrone.Core/Movies/Translations/MovieTranslationService.cs b/src/NzbDrone.Core/Movies/Translations/MovieTranslationService.cs index bbe9d65d3..af170566c 100644 --- a/src/NzbDrone.Core/Movies/Translations/MovieTranslationService.cs +++ b/src/NzbDrone.Core/Movies/Translations/MovieTranslationService.cs @@ -12,7 +12,7 @@ namespace NzbDrone.Core.Movies.Translations { List GetAllTranslationsForMovie(int movieId); List GetAllTranslationsForLanguage(Language language); - List UpdateTranslations(List titles, Movie movie); + List UpdateTranslations(List titles, MovieMetadata movie); } public class MovieTranslationService : IMovieTranslationService, IHandleAsync @@ -29,7 +29,7 @@ namespace NzbDrone.Core.Movies.Translations public List GetAllTranslationsForMovie(int movieId) { - return _translationRepo.FindByMovieId(movieId).ToList(); + return _translationRepo.FindByMovieMetadataId(movieId).ToList(); } public List GetAllTranslationsForLanguage(Language language) @@ -42,12 +42,12 @@ namespace NzbDrone.Core.Movies.Translations _translationRepo.Delete(title); } - public List UpdateTranslations(List translations, Movie movie) + public List UpdateTranslations(List translations, MovieMetadata movie) { int movieId = movie.Id; // First update the movie ids so we can correlate them later - translations.ForEach(t => t.MovieId = movieId); + translations.ForEach(t => t.MovieMetadataId = movieId); // Then throw out any we don't have languages for translations = translations.Where(t => t.Language != null).ToList(); @@ -56,7 +56,7 @@ namespace NzbDrone.Core.Movies.Translations translations = translations.DistinctBy(t => t.Language).ToList(); // Now find translations to delete, update and insert - var existingTranslations = _translationRepo.FindByMovieId(movieId); + var existingTranslations = _translationRepo.FindByMovieMetadataId(movieId); translations.ForEach(c => c.Id = existingTranslations.FirstOrDefault(t => t.Language == c.Language)?.Id ?? 0); @@ -73,7 +73,8 @@ namespace NzbDrone.Core.Movies.Translations public void HandleAsync(MoviesDeletedEvent message) { - _translationRepo.DeleteForMovies(message.Movies.Select(m => m.Id).ToList()); + // TODO hanlde metadata delete instead of movie delete + _translationRepo.DeleteForMovies(message.Movies.Select(m => m.MovieMetadataId).ToList()); } } } diff --git a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs index 7a15f5281..a83f0ffae 100755 --- a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs +++ b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs @@ -44,12 +44,12 @@ namespace NzbDrone.Core.Notifications.CustomScript environmentVariables.Add("Radarr_EventType", "Grab"); environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString()); - environmentVariables.Add("Radarr_Movie_Title", movie.Title); - environmentVariables.Add("Radarr_Movie_Year", movie.Year.ToString()); - environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - environmentVariables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); - environmentVariables.Add("Radarr_Movie_In_Cinemas_Date", movie.InCinemas.ToString() ?? string.Empty); - environmentVariables.Add("Radarr_Movie_Physical_Release_Date", movie.PhysicalRelease.ToString() ?? string.Empty); + environmentVariables.Add("Radarr_Movie_Title", movie.MovieMetadata.Value.Title); + environmentVariables.Add("Radarr_Movie_Year", movie.MovieMetadata.Value.Year.ToString()); + environmentVariables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + environmentVariables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); + environmentVariables.Add("Radarr_Movie_In_Cinemas_Date", movie.MovieMetadata.Value.InCinemas.ToString() ?? string.Empty); + environmentVariables.Add("Radarr_Movie_Physical_Release_Date", movie.MovieMetadata.Value.PhysicalRelease.ToString() ?? string.Empty); environmentVariables.Add("Radarr_Release_Title", remoteMovie.Release.Title); environmentVariables.Add("Radarr_Release_Indexer", remoteMovie.Release.Indexer ?? string.Empty); environmentVariables.Add("Radarr_Release_Size", remoteMovie.Release.Size.ToString()); @@ -74,13 +74,13 @@ namespace NzbDrone.Core.Notifications.CustomScript environmentVariables.Add("Radarr_EventType", "Download"); environmentVariables.Add("Radarr_IsUpgrade", message.OldMovieFiles.Any().ToString()); environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString()); - environmentVariables.Add("Radarr_Movie_Title", movie.Title); - environmentVariables.Add("Radarr_Movie_Year", movie.Year.ToString()); + environmentVariables.Add("Radarr_Movie_Title", movie.MovieMetadata.Value.Title); + environmentVariables.Add("Radarr_Movie_Year", movie.MovieMetadata.Value.Year.ToString()); environmentVariables.Add("Radarr_Movie_Path", movie.Path); - environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - environmentVariables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); - environmentVariables.Add("Radarr_Movie_In_Cinemas_Date", movie.InCinemas.ToString() ?? string.Empty); - environmentVariables.Add("Radarr_Movie_Physical_Release_Date", movie.PhysicalRelease.ToString() ?? string.Empty); + environmentVariables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + environmentVariables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); + environmentVariables.Add("Radarr_Movie_In_Cinemas_Date", movie.MovieMetadata.Value.InCinemas.ToString() ?? string.Empty); + environmentVariables.Add("Radarr_Movie_Physical_Release_Date", movie.MovieMetadata.Value.PhysicalRelease.ToString() ?? string.Empty); environmentVariables.Add("Radarr_MovieFile_Id", movieFile.Id.ToString()); environmentVariables.Add("Radarr_MovieFile_RelativePath", movieFile.RelativePath); environmentVariables.Add("Radarr_MovieFile_Path", Path.Combine(movie.Path, movieFile.RelativePath)); @@ -109,13 +109,13 @@ namespace NzbDrone.Core.Notifications.CustomScript environmentVariables.Add("Radarr_EventType", "Rename"); environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString()); - environmentVariables.Add("Radarr_Movie_Title", movie.Title); - environmentVariables.Add("Radarr_Movie_Year", movie.Year.ToString()); + environmentVariables.Add("Radarr_Movie_Title", movie.MovieMetadata.Value.Title); + environmentVariables.Add("Radarr_Movie_Year", movie.MovieMetadata.Value.Year.ToString()); environmentVariables.Add("Radarr_Movie_Path", movie.Path); - environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - environmentVariables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); - environmentVariables.Add("Radarr_Movie_In_Cinemas_Date", movie.InCinemas.ToString() ?? string.Empty); - environmentVariables.Add("Radarr_Movie_Physical_Release_Date", movie.PhysicalRelease.ToString() ?? string.Empty); + environmentVariables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + environmentVariables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); + environmentVariables.Add("Radarr_Movie_In_Cinemas_Date", movie.MovieMetadata.Value.InCinemas.ToString() ?? string.Empty); + environmentVariables.Add("Radarr_Movie_Physical_Release_Date", movie.MovieMetadata.Value.PhysicalRelease.ToString() ?? string.Empty); environmentVariables.Add("Radarr_MovieFile_Ids", string.Join(",", renamedFiles.Select(e => e.MovieFile.Id))); environmentVariables.Add("Radarr_MovieFile_RelativePaths", string.Join("|", renamedFiles.Select(e => e.MovieFile.RelativePath))); environmentVariables.Add("Radarr_MovieFile_Paths", string.Join("|", renamedFiles.Select(e => e.MovieFile.Path))); @@ -138,8 +138,8 @@ namespace NzbDrone.Core.Notifications.CustomScript environmentVariables.Add("Radarr_Movie_Title", movie.Title); environmentVariables.Add("Radarr_Movie_Year", movie.Year.ToString()); environmentVariables.Add("Radarr_Movie_Path", movie.Path); - environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - environmentVariables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); + environmentVariables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + environmentVariables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); environmentVariables.Add("Radarr_MovieFile_Id", movieFile.Id.ToString()); environmentVariables.Add("Radarr_MovieFile_RelativePath", movieFile.RelativePath); environmentVariables.Add("Radarr_MovieFile_Path", Path.Combine(movie.Path, movieFile.RelativePath)); @@ -159,11 +159,11 @@ namespace NzbDrone.Core.Notifications.CustomScript environmentVariables.Add("Radarr_EventType", "MovieDelete"); environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString()); - environmentVariables.Add("Radarr_Movie_Title", movie.Title); - environmentVariables.Add("Radarr_Movie_Year", movie.Year.ToString()); + environmentVariables.Add("Radarr_Movie_Title", movie.MovieMetadata.Value.Title); + environmentVariables.Add("Radarr_Movie_Year", movie.MovieMetadata.Value.Year.ToString()); environmentVariables.Add("Radarr_Movie_Path", movie.Path); - environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - environmentVariables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); + environmentVariables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + environmentVariables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); environmentVariables.Add("Radarr_Movie_DeletedFiles", deleteMessage.DeletedFiles.ToString()); if (deleteMessage.DeletedFiles && movie.MovieFile != null) diff --git a/src/NzbDrone.Core/Notifications/Discord/Discord.cs b/src/NzbDrone.Core/Notifications/Discord/Discord.cs index c7a0934e7..e7f8ef5a0 100644 --- a/src/NzbDrone.Core/Notifications/Discord/Discord.cs +++ b/src/NzbDrone.Core/Notifications/Discord/Discord.cs @@ -34,9 +34,9 @@ namespace NzbDrone.Core.Notifications.Discord Name = Settings.Author.IsNullOrWhiteSpace() ? Environment.MachineName : Settings.Author, IconUrl = "https://raw.githubusercontent.com/Radarr/Radarr/develop/Logo/256.png" }, - Url = $"https://www.themoviedb.org/movie/{message.Movie.TmdbId}", + Url = $"https://www.themoviedb.org/movie/{message.Movie.MovieMetadata.Value.TmdbId}", Description = "Movie Grabbed", - Title = message.Movie.Year > 0 ? $"{message.Movie.Title} ({message.Movie.Year})" : message.Movie.Title, + Title = message.Movie.MovieMetadata.Value.Year > 0 ? $"{message.Movie.MovieMetadata.Value.Title} ({message.Movie.MovieMetadata.Value.Year})" : message.Movie.MovieMetadata.Value.Title, Color = (int)DiscordColors.Standard, Fields = new List(), Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") @@ -46,7 +46,7 @@ namespace NzbDrone.Core.Notifications.Discord { embed.Thumbnail = new DiscordImage { - Url = message.Movie.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.Url + Url = message.Movie.MovieMetadata.Value.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.Url }; } @@ -54,7 +54,7 @@ namespace NzbDrone.Core.Notifications.Discord { embed.Image = new DiscordImage { - Url = message.Movie.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Fanart)?.Url + Url = message.Movie.MovieMetadata.Value.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Fanart)?.Url }; } @@ -66,15 +66,15 @@ namespace NzbDrone.Core.Notifications.Discord { case DiscordGrabFieldType.Overview: discordField.Name = "Overview"; - discordField.Value = message.Movie.Overview.Length <= 300 ? message.Movie.Overview : message.Movie.Overview.Substring(0, 300) + "..."; + discordField.Value = message.Movie.MovieMetadata.Value.Overview.Length <= 300 ? message.Movie.MovieMetadata.Value.Overview : message.Movie.MovieMetadata.Value.Overview.Substring(0, 300) + "..."; break; case DiscordGrabFieldType.Rating: discordField.Name = "Rating"; - discordField.Value = message.Movie.Ratings.Tmdb?.Value.ToString() ?? string.Empty; + discordField.Value = message.Movie.MovieMetadata.Value.Ratings.Tmdb?.Value.ToString() ?? string.Empty; break; case DiscordGrabFieldType.Genres: discordField.Name = "Genres"; - discordField.Value = message.Movie.Genres.Take(5).Join(", "); + discordField.Value = message.Movie.MovieMetadata.Value.Genres.Take(5).Join(", "); break; case DiscordGrabFieldType.Quality: discordField.Name = "Quality"; @@ -121,9 +121,9 @@ namespace NzbDrone.Core.Notifications.Discord Name = Settings.Author.IsNullOrWhiteSpace() ? Environment.MachineName : Settings.Author, IconUrl = "https://raw.githubusercontent.com/Radarr/Radarr/develop/Logo/256.png" }, - Url = $"https://www.themoviedb.org/movie/{message.Movie.TmdbId}", + Url = $"https://www.themoviedb.org/movie/{message.Movie.MovieMetadata.Value.TmdbId}", Description = isUpgrade ? "Movie Upgraded" : "Movie Imported", - Title = message.Movie.Year > 0 ? $"{message.Movie.Title} ({message.Movie.Year})" : message.Movie.Title, + Title = message.Movie.MovieMetadata.Value.Year > 0 ? $"{message.Movie.MovieMetadata.Value.Title} ({message.Movie.MovieMetadata.Value.Year})" : message.Movie.MovieMetadata.Value.Title, Color = isUpgrade ? (int)DiscordColors.Upgrade : (int)DiscordColors.Success, Fields = new List(), Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") @@ -133,7 +133,7 @@ namespace NzbDrone.Core.Notifications.Discord { embed.Thumbnail = new DiscordImage { - Url = message.Movie.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.Url + Url = message.Movie.MovieMetadata.Value.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.Url }; } @@ -141,7 +141,7 @@ namespace NzbDrone.Core.Notifications.Discord { embed.Image = new DiscordImage { - Url = message.Movie.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Fanart)?.Url + Url = message.Movie.MovieMetadata.Value.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Fanart)?.Url }; } @@ -153,15 +153,15 @@ namespace NzbDrone.Core.Notifications.Discord { case DiscordImportFieldType.Overview: discordField.Name = "Overview"; - discordField.Value = message.Movie.Overview.Length <= 300 ? message.Movie.Overview : message.Movie.Overview.Substring(0, 300) + "..."; + discordField.Value = message.Movie.MovieMetadata.Value.Overview.Length <= 300 ? message.Movie.MovieMetadata.Value.Overview : message.Movie.MovieMetadata.Value.Overview.Substring(0, 300) + "..."; break; case DiscordImportFieldType.Rating: discordField.Name = "Rating"; - discordField.Value = message.Movie.Ratings.Tmdb?.Value.ToString() ?? string.Empty; + discordField.Value = message.Movie.MovieMetadata.Value.Ratings.Tmdb?.Value.ToString() ?? string.Empty; break; case DiscordImportFieldType.Genres: discordField.Name = "Genres"; - discordField.Value = message.Movie.Genres.Take(5).Join(", "); + discordField.Value = message.Movie.MovieMetadata.Value.Genres.Take(5).Join(", "); break; case DiscordImportFieldType.Quality: discordField.Name = "Quality"; @@ -222,7 +222,7 @@ namespace NzbDrone.Core.Notifications.Discord { attachments.Add(new Embed { - Title = movie.Title, + Title = movie.MovieMetadata.Value.Title, Description = renamedFile.PreviousRelativePath + " renamed to " + renamedFile.MovieFile.RelativePath, }); } @@ -240,7 +240,7 @@ namespace NzbDrone.Core.Notifications.Discord { new Embed { - Title = movie.Title, + Title = movie.MovieMetadata.Value.Title, Description = deleteMessage.DeletedFilesMessage } }; @@ -259,7 +259,7 @@ namespace NzbDrone.Core.Notifications.Discord { new Embed { - Title = movie.Title, + Title = movie.MovieMetadata.Value.Title, Description = deleteMessage.MovieFile.Path } }; @@ -393,21 +393,21 @@ namespace NzbDrone.Core.Notifications.Discord private static string GetLinksString(Movie movie) { - var links = string.Format("[{0}]({1})", "TMDb", $"https://themoviedb.org/movie/{movie.TmdbId}"); - links += string.Format(" / [{0}]({1})", "Trakt", $"https://trakt.tv/search/tmdb/{movie.TmdbId}?id_type=movie"); - if (movie.ImdbId.IsNotNullOrWhiteSpace()) + var links = string.Format("[{0}]({1})", "TMDb", $"https://themoviedb.org/movie/{movie.MovieMetadata.Value.TmdbId}"); + links += string.Format(" / [{0}]({1})", "Trakt", $"https://trakt.tv/search/tmdb/{movie.MovieMetadata.Value.TmdbId}?id_type=movie"); + if (movie.MovieMetadata.Value.ImdbId.IsNotNullOrWhiteSpace()) { - links += string.Format(" / [{0}]({1})", "IMDb", $"https://imdb.com/title/{movie.ImdbId}/"); + links += string.Format(" / [{0}]({1})", "IMDb", $"https://imdb.com/title/{movie.MovieMetadata.Value.ImdbId}/"); } - if (movie.YouTubeTrailerId.IsNotNullOrWhiteSpace()) + if (movie.MovieMetadata.Value.YouTubeTrailerId.IsNotNullOrWhiteSpace()) { - links += string.Format(" / [{0}]({1})", "YouTube", $"https://www.youtube.com/watch?v={movie.YouTubeTrailerId}"); + links += string.Format(" / [{0}]({1})", "YouTube", $"https://www.youtube.com/watch?v={movie.MovieMetadata.Value.YouTubeTrailerId}"); } - if (movie.Website.IsNotNullOrWhiteSpace()) + if (movie.MovieMetadata.Value.Website.IsNotNullOrWhiteSpace()) { - links += string.Format(" / [{0}]({1})", "Website", movie.Website); + links += string.Format(" / [{0}]({1})", "Website", movie.MovieMetadata.Value.Website); } return links; diff --git a/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs b/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs index 97893d3a2..005158fdc 100644 --- a/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs +++ b/src/NzbDrone.Core/Notifications/Notifiarr/Notifiarr.cs @@ -30,12 +30,12 @@ namespace NzbDrone.Core.Notifications.Notifiarr variables.Add("Radarr_EventType", "Grab"); variables.Add("Radarr_Movie_Id", movie.Id.ToString()); - variables.Add("Radarr_Movie_Title", movie.Title); - variables.Add("Radarr_Movie_Year", movie.Year.ToString()); - variables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - variables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); - variables.Add("Radarr_Movie_In_Cinemas_Date", movie.InCinemas.ToString() ?? string.Empty); - variables.Add("Radarr_Movie_Physical_Release_Date", movie.PhysicalRelease.ToString() ?? string.Empty); + variables.Add("Radarr_Movie_Title", movie.MovieMetadata.Value.Title); + variables.Add("Radarr_Movie_Year", movie.MovieMetadata.Value.Year.ToString()); + variables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + variables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); + variables.Add("Radarr_Movie_In_Cinemas_Date", movie.MovieMetadata.Value.InCinemas.ToString() ?? string.Empty); + variables.Add("Radarr_Movie_Physical_Release_Date", movie.MovieMetadata.Value.PhysicalRelease.ToString() ?? string.Empty); variables.Add("Radarr_Release_Title", remoteMovie.Release.Title); variables.Add("Radarr_Release_Indexer", remoteMovie.Release.Indexer ?? string.Empty); variables.Add("Radarr_Release_Size", remoteMovie.Release.Size.ToString()); @@ -60,13 +60,13 @@ namespace NzbDrone.Core.Notifications.Notifiarr variables.Add("Radarr_EventType", "Download"); variables.Add("Radarr_IsUpgrade", message.OldMovieFiles.Any().ToString()); variables.Add("Radarr_Movie_Id", movie.Id.ToString()); - variables.Add("Radarr_Movie_Title", movie.Title); - variables.Add("Radarr_Movie_Year", movie.Year.ToString()); + variables.Add("Radarr_Movie_Title", movie.MovieMetadata.Value.Title); + variables.Add("Radarr_Movie_Year", movie.MovieMetadata.Value.Year.ToString()); variables.Add("Radarr_Movie_Path", movie.Path); - variables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - variables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); - variables.Add("Radarr_Movie_In_Cinemas_Date", movie.InCinemas.ToString() ?? string.Empty); - variables.Add("Radarr_Movie_Physical_Release_Date", movie.PhysicalRelease.ToString() ?? string.Empty); + variables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + variables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); + variables.Add("Radarr_Movie_In_Cinemas_Date", movie.MovieMetadata.Value.InCinemas.ToString() ?? string.Empty); + variables.Add("Radarr_Movie_Physical_Release_Date", movie.MovieMetadata.Value.PhysicalRelease.ToString() ?? string.Empty); variables.Add("Radarr_MovieFile_Id", movieFile.Id.ToString()); variables.Add("Radarr_MovieFile_RelativePath", movieFile.RelativePath); variables.Add("Radarr_MovieFile_Path", Path.Combine(movie.Path, movieFile.RelativePath)); @@ -99,11 +99,11 @@ namespace NzbDrone.Core.Notifications.Notifiarr variables.Add("Radarr_EventType", "MovieFileDelete"); variables.Add("Radarr_MovieFile_DeleteReason", deleteMessage.Reason.ToString()); variables.Add("Radarr_Movie_Id", movie.Id.ToString()); - variables.Add("Radarr_Movie_Title", movie.Title); - variables.Add("Radarr_Movie_Year", movie.Year.ToString()); + variables.Add("Radarr_Movie_Title", movie.MovieMetadata.Value.Title); + variables.Add("Radarr_Movie_Year", movie.MovieMetadata.Value.Year.ToString()); variables.Add("Radarr_Movie_Path", movie.Path); - variables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - variables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); + variables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + variables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); variables.Add("Radarr_MovieFile_Id", movieFile.Id.ToString()); variables.Add("Radarr_MovieFile_RelativePath", movieFile.RelativePath); variables.Add("Radarr_MovieFile_Path", Path.Combine(movie.Path, movieFile.RelativePath)); @@ -123,11 +123,11 @@ namespace NzbDrone.Core.Notifications.Notifiarr variables.Add("Radarr_EventType", "MovieDelete"); variables.Add("Radarr_Movie_Id", movie.Id.ToString()); - variables.Add("Radarr_Movie_Title", movie.Title); - variables.Add("Radarr_Movie_Year", movie.Year.ToString()); + variables.Add("Radarr_Movie_Title", movie.MovieMetadata.Value.Title); + variables.Add("Radarr_Movie_Year", movie.MovieMetadata.Value.Year.ToString()); variables.Add("Radarr_Movie_Path", movie.Path); - variables.Add("Radarr_Movie_ImdbId", movie.ImdbId ?? string.Empty); - variables.Add("Radarr_Movie_TmdbId", movie.TmdbId.ToString()); + variables.Add("Radarr_Movie_ImdbId", movie.MovieMetadata.Value.ImdbId ?? string.Empty); + variables.Add("Radarr_Movie_TmdbId", movie.MovieMetadata.Value.TmdbId.ToString()); variables.Add("Radarr_Movie_DeletedFiles", deleteMessage.DeletedFiles.ToString()); if (deleteMessage.DeletedFiles && movie.MovieFile != null) { diff --git a/src/NzbDrone.Core/Notifications/NotificationService.cs b/src/NzbDrone.Core/Notifications/NotificationService.cs index 621590c5b..62b799742 100644 --- a/src/NzbDrone.Core/Notifications/NotificationService.cs +++ b/src/NzbDrone.Core/Notifications/NotificationService.cs @@ -39,7 +39,7 @@ namespace NzbDrone.Core.Notifications private string GetMessage(Movie movie, QualityModel quality) { var qualityString = quality.Quality.ToString(); - var imdbUrl = "https://www.imdb.com/title/" + movie.ImdbId + "/"; + var imdbUrl = "https://www.imdb.com/title/" + movie.MovieMetadata.Value.ImdbId + "/"; if (quality.Revision.Version > 1) { diff --git a/src/NzbDrone.Core/Notifications/Trakt/TraktService.cs b/src/NzbDrone.Core/Notifications/Trakt/TraktService.cs index 15a8f8765..339d0cf92 100644 --- a/src/NzbDrone.Core/Notifications/Trakt/TraktService.cs +++ b/src/NzbDrone.Core/Notifications/Trakt/TraktService.cs @@ -89,8 +89,8 @@ namespace NzbDrone.Core.Notifications.Trakt Year = movie.Year, Ids = new TraktMovieIdsResource { - Tmdb = movie.TmdbId, - Imdb = movie.ImdbId ?? "", + Tmdb = movie.MovieMetadata.Value.TmdbId, + Imdb = movie.MovieMetadata.Value.ImdbId ?? "", } }); @@ -120,8 +120,8 @@ namespace NzbDrone.Core.Notifications.Trakt Audio = audio, Ids = new TraktMovieIdsResource { - Tmdb = movie.TmdbId, - Imdb = movie.ImdbId ?? "", + Tmdb = movie.MovieMetadata.Value.TmdbId, + Imdb = movie.MovieMetadata.Value.ImdbId ?? "", } }); diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookMovie.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookMovie.cs index 4a9fa3d7e..d80ac0478 100755 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookMovie.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookMovie.cs @@ -24,7 +24,7 @@ namespace NzbDrone.Core.Notifications.Webhook Id = movie.Id; Title = movie.Title; Year = movie.Year; - ReleaseDate = movie.PhysicalReleaseDate().ToString("yyyy-MM-dd"); + ReleaseDate = movie.MovieMetadata.Value.PhysicalReleaseDate().ToString("yyyy-MM-dd"); FolderPath = movie.Path; TmdbId = movie.TmdbId; ImdbId = movie.ImdbId; diff --git a/src/NzbDrone.Core/Notifications/Webhook/WebhookRemoteMovie.cs b/src/NzbDrone.Core/Notifications/Webhook/WebhookRemoteMovie.cs index d14af047f..db82d58fe 100644 --- a/src/NzbDrone.Core/Notifications/Webhook/WebhookRemoteMovie.cs +++ b/src/NzbDrone.Core/Notifications/Webhook/WebhookRemoteMovie.cs @@ -1,4 +1,4 @@ -using NzbDrone.Core.Movies; +using NzbDrone.Core.Movies; using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.Notifications.Webhook @@ -16,18 +16,18 @@ namespace NzbDrone.Core.Notifications.Webhook public WebhookRemoteMovie(RemoteMovie remoteMovie) { - TmdbId = remoteMovie.Movie.TmdbId; - ImdbId = remoteMovie.Movie.ImdbId; - Title = remoteMovie.Movie.Title; - Year = remoteMovie.Movie.Year; + TmdbId = remoteMovie.Movie.MovieMetadata.Value.TmdbId; + ImdbId = remoteMovie.Movie.MovieMetadata.Value.ImdbId; + Title = remoteMovie.Movie.MovieMetadata.Value.Title; + Year = remoteMovie.Movie.MovieMetadata.Value.Year; } public WebhookRemoteMovie(Movie movie) { - TmdbId = movie.TmdbId; - ImdbId = movie.ImdbId; - Title = movie.Title; - Year = movie.Year; + TmdbId = movie.MovieMetadata.Value.TmdbId; + ImdbId = movie.MovieMetadata.Value.ImdbId; + Title = movie.MovieMetadata.Value.Title; + Year = movie.MovieMetadata.Value.Year; } } } diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs index 67d6cac72..4d98e174e 100644 --- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs +++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs @@ -264,10 +264,11 @@ namespace NzbDrone.Core.Organizer tokenHandlers["{Movie CleanTitle}"] = m => CleanTitle(GetLanguageTitle(movie, m.CustomFormat)); tokenHandlers["{Movie Title The}"] = m => TitleThe(movie.Title); tokenHandlers["{Movie TitleFirstCharacter}"] = m => TitleThe(movie.Title).Substring(0, 1).FirstCharToUpper(); - tokenHandlers["{Movie OriginalTitle}"] = m => movie.OriginalTitle ?? string.Empty; + tokenHandlers["{Movie OriginalTitle}"] = m => movie.MovieMetadata.Value.OriginalTitle ?? string.Empty; + tokenHandlers["{Movie CleanOriginalTitle}"] = m => CleanTitle(movie.MovieMetadata.Value.OriginalTitle) ?? string.Empty; - tokenHandlers["{Movie Certification}"] = m => movie.Certification ?? string.Empty; - tokenHandlers["{Movie Collection}"] = m => movie.Collection?.Name ?? string.Empty; + tokenHandlers["{Movie Certification}"] = m => movie.MovieMetadata.Value.Certification ?? string.Empty; + tokenHandlers["{Movie Collection}"] = m => movie.MovieMetadata.Value.Collection?.Name ?? string.Empty; } private string GetLanguageTitle(Movie movie, string isoCodes) @@ -283,9 +284,9 @@ namespace NzbDrone.Core.Organizer continue; } - var titles = movie.Translations.Where(t => t.Language == language).ToList(); + var titles = movie.MovieMetadata.Value.Translations.Where(t => t.Language == language).ToList(); - if (!movie.Translations.Any()) + if (!movie.MovieMetadata.Value.Translations.Any()) { titles = _movieTranslationService.GetAllTranslationsForMovie(movie.Id).Where(t => t.Language == language).ToList(); } @@ -318,8 +319,8 @@ namespace NzbDrone.Core.Organizer private void AddIdTokens(Dictionary> tokenHandlers, Movie movie) { - tokenHandlers["{ImdbId}"] = m => movie.ImdbId ?? string.Empty; - tokenHandlers["{TmdbId}"] = m => movie.TmdbId.ToString(); + tokenHandlers["{ImdbId}"] = m => movie.MovieMetadata.Value.ImdbId ?? string.Empty; + tokenHandlers["{TmdbId}"] = m => movie.MovieMetadata.Value.TmdbId.ToString(); } private void AddMovieFileTokens(Dictionary> tokenHandlers, MovieFile movieFile) diff --git a/src/NzbDrone.Core/Organizer/FileNameSampleService.cs b/src/NzbDrone.Core/Organizer/FileNameSampleService.cs index 1c2d942e0..70e4aeecb 100644 --- a/src/NzbDrone.Core/Organizer/FileNameSampleService.cs +++ b/src/NzbDrone.Core/Organizer/FileNameSampleService.cs @@ -19,6 +19,7 @@ namespace NzbDrone.Core.Organizer private static MovieFile _movieFile; private static Movie _movie; + private static MovieMetadata _movieMetadata; private static List _customFormats; public FileNameSampleService(IBuildFileNames buildFileNames) @@ -49,7 +50,7 @@ namespace NzbDrone.Core.Organizer Edition = "Ultimate extended edition", }; - _movie = new Movie + _movieMetadata = new MovieMetadata { Title = "The Movie: Title", OriginalTitle = "The Original Movie Title", @@ -57,9 +58,15 @@ namespace NzbDrone.Core.Organizer Certification = "R", Year = 2010, ImdbId = "tt0066921", - TmdbId = 345691, + TmdbId = 345691 + }; + + _movie = new Movie + { MovieFile = _movieFile, MovieFileId = 1, + MovieMetadata = _movieMetadata, + MovieMetadataId = 1 }; _customFormats = new List diff --git a/src/NzbDrone.Core/Parser/Augmenters/AugmentWithOriginalLanguage.cs b/src/NzbDrone.Core/Parser/Augmenters/AugmentWithOriginalLanguage.cs index a1b7b6671..2573e6adf 100644 --- a/src/NzbDrone.Core/Parser/Augmenters/AugmentWithOriginalLanguage.cs +++ b/src/NzbDrone.Core/Parser/Augmenters/AugmentWithOriginalLanguage.cs @@ -16,9 +16,9 @@ namespace NzbDrone.Core.Parser.Augmenters public ParsedMovieInfo AugmentMovieInfo(ParsedMovieInfo movieInfo, object helper) { - if (helper is Movie movie && movie?.OriginalLanguage != null && movieInfo != null) + if (helper is Movie movie && movie?.MovieMetadata.Value.OriginalLanguage != null && movieInfo != null) { - movieInfo.ExtraInfo["OriginalLanguage"] = movie.OriginalLanguage; + movieInfo.ExtraInfo["OriginalLanguage"] = movie.MovieMetadata.Value.OriginalLanguage; } return movieInfo; diff --git a/src/NzbDrone.Core/Parser/ParsingService.cs b/src/NzbDrone.Core/Parser/ParsingService.cs index 6b97c504d..3747feadc 100644 --- a/src/NzbDrone.Core/Parser/ParsingService.cs +++ b/src/NzbDrone.Core/Parser/ParsingService.cs @@ -130,17 +130,17 @@ namespace NzbDrone.Core.Parser //Use movie language as fallback if we could't parse a language (more accurate than just using English) if (parsedMovieInfo.Languages.Count <= 1 && parsedMovieInfo.Languages.First() == Language.Unknown && result.Movie != null) { - parsedMovieInfo.Languages = new List { result.Movie.OriginalLanguage }; - _logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", result.Movie.OriginalLanguage.Name); + parsedMovieInfo.Languages = new List { result.Movie.MovieMetadata.Value.OriginalLanguage }; + _logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", result.Movie.MovieMetadata.Value.OriginalLanguage.Name); } if (parsedMovieInfo.Languages.Contains(Language.Original)) { parsedMovieInfo.Languages.Remove(Language.Original); - if (result.Movie != null && !parsedMovieInfo.Languages.Contains(result.Movie.OriginalLanguage)) + if (result.Movie != null && !parsedMovieInfo.Languages.Contains(result.Movie.MovieMetadata.Value.OriginalLanguage)) { - parsedMovieInfo.Languages.Add(result.Movie.OriginalLanguage); + parsedMovieInfo.Languages.Add(result.Movie.MovieMetadata.Value.OriginalLanguage); } else { @@ -190,7 +190,7 @@ namespace NzbDrone.Core.Parser var movie = _movieService.FindByImdbId(imdbId); //Should fix practically all problems, where indexer is shite at adding correct imdbids to movies. - if (movie != null && parsedMovieInfo.Year > 1800 && (parsedMovieInfo.Year != movie.Year && movie.SecondaryYear != parsedMovieInfo.Year)) + if (movie != null && parsedMovieInfo.Year > 1800 && (parsedMovieInfo.Year != movie.MovieMetadata.Value.Year && movie.MovieMetadata.Value.SecondaryYear != parsedMovieInfo.Year)) { result = new MappingResult { Movie = movie, MappingResultType = MappingResultType.WrongYear }; return false; @@ -254,9 +254,9 @@ namespace NzbDrone.Core.Parser var possibleTitles = new List(); - possibleTitles.Add(searchCriteria.Movie.CleanTitle); - possibleTitles.AddRange(searchCriteria.Movie.AlternativeTitles.Select(t => t.CleanTitle)); - possibleTitles.AddRange(searchCriteria.Movie.Translations.Select(t => t.CleanTitle)); + possibleTitles.Add(searchCriteria.Movie.MovieMetadata.Value.CleanTitle); + possibleTitles.AddRange(searchCriteria.Movie.MovieMetadata.Value.AlternativeTitles.Select(t => t.CleanTitle)); + possibleTitles.AddRange(searchCriteria.Movie.MovieMetadata.Value.Translations.Select(t => t.CleanTitle)); var cleanTitle = parsedMovieInfo.PrimaryMovieTitle.CleanMovieTitle(); @@ -287,7 +287,7 @@ namespace NzbDrone.Core.Parser if (possibleMovie != null) { - if (parsedMovieInfo.Year < 1800 || possibleMovie.Year == parsedMovieInfo.Year || possibleMovie.SecondaryYear == parsedMovieInfo.Year) + if (parsedMovieInfo.Year < 1800 || possibleMovie.MovieMetadata.Value.Year == parsedMovieInfo.Year || possibleMovie.MovieMetadata.Value.SecondaryYear == parsedMovieInfo.Year) { result = new MappingResult { Movie = possibleMovie, MappingResultType = MappingResultType.Success }; return true; @@ -318,11 +318,11 @@ namespace NzbDrone.Core.Parser case MappingResultType.TitleNotFound: return $"Could not find {RemoteMovie.ParsedMovieInfo.PrimaryMovieTitle}"; case MappingResultType.WrongYear: - return $"Failed to map movie, expected year {RemoteMovie.Movie.Year}, but found {RemoteMovie.ParsedMovieInfo.Year}"; + return $"Failed to map movie, expected year {RemoteMovie.Movie.MovieMetadata.Value.Year}, but found {RemoteMovie.ParsedMovieInfo.Year}"; case MappingResultType.WrongTitle: - var comma = RemoteMovie.Movie.AlternativeTitles.Count > 0 ? ", " : ""; + var comma = RemoteMovie.Movie.MovieMetadata.Value.AlternativeTitles.Count > 0 ? ", " : ""; return - $"Failed to map movie, found title(s) {string.Join(", ", RemoteMovie.ParsedMovieInfo.MovieTitles)}, expected one of: {RemoteMovie.Movie.Title}{comma}{string.Join(", ", RemoteMovie.Movie.AlternativeTitles)}"; + $"Failed to map movie, found title(s) {string.Join(", ", RemoteMovie.ParsedMovieInfo.MovieTitles)}, expected one of: {RemoteMovie.Movie.MovieMetadata.Value.Title}{comma}{string.Join(", ", RemoteMovie.Movie.MovieMetadata.Value.AlternativeTitles)}"; default: return $"Failed to map movie for unknown reasons"; } diff --git a/src/NzbDrone.Core/Radarr.Core.csproj b/src/NzbDrone.Core/Radarr.Core.csproj index b9458975e..baead3218 100644 --- a/src/NzbDrone.Core/Radarr.Core.csproj +++ b/src/NzbDrone.Core/Radarr.Core.csproj @@ -4,6 +4,7 @@ + diff --git a/src/Radarr.Api.V3/Calendar/CalendarController.cs b/src/Radarr.Api.V3/Calendar/CalendarController.cs index 8d983463c..c15a01892 100644 --- a/src/Radarr.Api.V3/Calendar/CalendarController.cs +++ b/src/Radarr.Api.V3/Calendar/CalendarController.cs @@ -60,13 +60,13 @@ namespace Radarr.Api.V3.Calendar var availDelay = _configService.AvailabilityDelay; var translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id); - var translation = GetMovieTranslation(translations, movie); + var translation = GetMovieTranslation(translations, movie.MovieMetadata); var resource = movie.ToResource(availDelay, translation, _qualityUpgradableSpecification); return resource; } - private MovieTranslation GetMovieTranslation(List translations, Movie movie) + private MovieTranslation GetMovieTranslation(List translations, MovieMetadata movie) { if ((Language)_configService.MovieInfoLanguage == Language.Original) { @@ -77,7 +77,7 @@ namespace Radarr.Api.V3.Calendar }; } - return translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage && t.MovieId == movie.Id); + return translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage && t.MovieMetadataId == movie.Id); } } } diff --git a/src/Radarr.Api.V3/Calendar/CalendarFeedController.cs b/src/Radarr.Api.V3/Calendar/CalendarFeedController.cs index 0d9edb126..1df33a24b 100644 --- a/src/Radarr.Api.V3/Calendar/CalendarFeedController.cs +++ b/src/Radarr.Api.V3/Calendar/CalendarFeedController.cs @@ -54,9 +54,9 @@ namespace Radarr.Api.V3.Calendar continue; } - CreateEvent(calendar, movie, "cinematic"); - CreateEvent(calendar, movie, "digital"); - CreateEvent(calendar, movie, "physical"); + CreateEvent(calendar, movie.MovieMetadata, "cinematic"); + CreateEvent(calendar, movie.MovieMetadata, "digital"); + CreateEvent(calendar, movie.MovieMetadata, "physical"); } var serializer = (IStringSerializer)new SerializerFactory().Build(calendar.GetType(), new SerializationContext()); @@ -65,7 +65,7 @@ namespace Radarr.Api.V3.Calendar return Content(icalendar, "text/calendar"); } - private void CreateEvent(Ical.Net.Calendar calendar, Movie movie, string releaseType) + private void CreateEvent(Ical.Net.Calendar calendar, MovieMetadata movie, string releaseType) { var date = movie.InCinemas; string eventType = "_cinemas"; diff --git a/src/Radarr.Api.V3/Credits/CreditController.cs b/src/Radarr.Api.V3/Credits/CreditController.cs index 10e4be516..e4641d6a5 100644 --- a/src/Radarr.Api.V3/Credits/CreditController.cs +++ b/src/Radarr.Api.V3/Credits/CreditController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using NzbDrone.Core.Movies; using NzbDrone.Core.Movies.Credits; using Radarr.Http; using Radarr.Http.REST; @@ -10,10 +11,12 @@ namespace Radarr.Api.V3.Credits public class CreditController : RestController { private readonly ICreditService _creditService; + private readonly IMovieService _movieService; - public CreditController(ICreditService creditService) + public CreditController(ICreditService creditService, IMovieService movieService) { _creditService = creditService; + _movieService = movieService; } protected override CreditResource GetResourceById(int id) @@ -22,11 +25,17 @@ namespace Radarr.Api.V3.Credits } [HttpGet] - public List GetCredits(int? movieId) + public List GetCredits(int? movieId, int? movieMetadataId) { + if (movieMetadataId.HasValue) + { + return _creditService.GetAllCreditsForMovie(movieMetadataId.Value).ToResource(); + } + if (movieId.HasValue) { - return _creditService.GetAllCreditsForMovie(movieId.Value).ToResource(); + var movie = _movieService.GetMovie(movieId.Value); + return _creditService.GetAllCreditsForMovie(movie.MovieMetadataId).ToResource(); } return _creditService.GetAllCredits().ToResource(); diff --git a/src/Radarr.Api.V3/Credits/CreditResource.cs b/src/Radarr.Api.V3/Credits/CreditResource.cs index cd7ddb4a1..7ade5d148 100644 --- a/src/Radarr.Api.V3/Credits/CreditResource.cs +++ b/src/Radarr.Api.V3/Credits/CreditResource.cs @@ -15,7 +15,7 @@ namespace Radarr.Api.V3.Credits public string PersonName { get; set; } public string CreditTmdbId { get; set; } public int PersonTmdbId { get; set; } - public int MovieId { get; set; } + public int MovieMetadataId { get; set; } public List Images { get; set; } public string Department { get; set; } public string Job { get; set; } @@ -36,7 +36,7 @@ namespace Radarr.Api.V3.Credits return new CreditResource { Id = model.Id, - MovieId = model.MovieId, + MovieMetadataId = model.MovieMetadataId, CreditTmdbId = model.CreditTmdbId, PersonTmdbId = model.PersonTmdbId, PersonName = model.Name, @@ -64,7 +64,7 @@ namespace Radarr.Api.V3.Credits return new Credit { Id = resource.Id, - MovieId = resource.MovieId, + MovieMetadataId = resource.MovieMetadataId, Name = resource.PersonName, Order = resource.Order, Character = resource.Character, diff --git a/src/Radarr.Api.V3/ImportLists/ImportListMoviesController.cs b/src/Radarr.Api.V3/ImportLists/ImportListMoviesController.cs index aa17fb890..f5a646f3c 100644 --- a/src/Radarr.Api.V3/ImportLists/ImportListMoviesController.cs +++ b/src/Radarr.Api.V3/ImportLists/ImportListMoviesController.cs @@ -60,7 +60,7 @@ namespace Radarr.Api.V3.ImportLists if (results.Count > 0) { - mapped = _movieInfo.GetBulkMovieInfo(results); + mapped = _movieInfo.GetBulkMovieInfo(results).Select(m => new Movie { MovieMetadata = m }).ToList(); } realResults.AddRange(MapToResource(mapped.Where(x => x != null), movieLanguge)); @@ -94,13 +94,13 @@ namespace Radarr.Api.V3.ImportLists foreach (var currentMovie in movies) { var resource = DiscoverMoviesResourceMapper.ToResource(currentMovie); - var poster = currentMovie.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster); + var poster = currentMovie.MovieMetadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster); if (poster != null) { resource.RemotePoster = poster.Url; } - var translation = currentMovie.Translations.FirstOrDefault(t => t.Language == language); + var translation = currentMovie.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == language); resource.Title = translation?.Title ?? resource.Title; resource.Overview = translation?.Overview ?? resource.Overview; @@ -115,17 +115,23 @@ namespace Radarr.Api.V3.ImportLists foreach (var currentMovie in movies) { var resource = DiscoverMoviesResourceMapper.ToResource(currentMovie); - var poster = currentMovie.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster); + var poster = currentMovie.MovieMetadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster); if (poster != null) { resource.RemotePoster = poster.Url; } - var translation = currentMovie.Translations.FirstOrDefault(t => t.Language == language); + var translation = currentMovie.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == language); resource.Title = translation?.Title ?? resource.Title; resource.Overview = translation?.Overview ?? resource.Overview; - resource.Folder = _fileNameBuilder.GetMovieFolder(new Movie { Title = currentMovie.Title, Year = currentMovie.Year, ImdbId = currentMovie.ImdbId, TmdbId = currentMovie.TmdbId }); + resource.Folder = _fileNameBuilder.GetMovieFolder(new Movie + { + Title = currentMovie.Title, + Year = currentMovie.Year, + ImdbId = currentMovie.ImdbId, + TmdbId = currentMovie.TmdbId + }); yield return resource; } diff --git a/src/Radarr.Api.V3/ImportLists/ImportListMoviesResource.cs b/src/Radarr.Api.V3/ImportLists/ImportListMoviesResource.cs index 2f8bdf2c2..c4c71bb42 100644 --- a/src/Radarr.Api.V3/ImportLists/ImportListMoviesResource.cs +++ b/src/Radarr.Api.V3/ImportLists/ImportListMoviesResource.cs @@ -56,27 +56,27 @@ namespace Radarr.Api.V3.ImportLists { TmdbId = model.TmdbId, Title = model.Title, - SortTitle = model.SortTitle, - InCinemas = model.InCinemas, - PhysicalRelease = model.PhysicalRelease, - DigitalRelease = model.DigitalRelease, + SortTitle = model.MovieMetadata.Value.SortTitle, + InCinemas = model.MovieMetadata.Value.InCinemas, + PhysicalRelease = model.MovieMetadata.Value.PhysicalRelease, + DigitalRelease = model.MovieMetadata.Value.DigitalRelease, - Status = model.Status, - Overview = model.Overview, + Status = model.MovieMetadata.Value.Status, + Overview = model.MovieMetadata.Value.Overview, - Images = model.Images, + Images = model.MovieMetadata.Value.Images, Year = model.Year, - Runtime = model.Runtime, + Runtime = model.MovieMetadata.Value.Runtime, ImdbId = model.ImdbId, - Certification = model.Certification, - Website = model.Website, - Genres = model.Genres, - Ratings = model.Ratings, - YouTubeTrailerId = model.YouTubeTrailerId, - Studio = model.Studio, - Collection = model.Collection + Certification = model.MovieMetadata.Value.Certification, + Website = model.MovieMetadata.Value.Website, + Genres = model.MovieMetadata.Value.Genres, + Ratings = model.MovieMetadata.Value.Ratings, + YouTubeTrailerId = model.MovieMetadata.Value.YouTubeTrailerId, + Studio = model.MovieMetadata.Value.Studio, + Collection = model.MovieMetadata.Value.Collection }; } @@ -91,27 +91,27 @@ namespace Radarr.Api.V3.ImportLists { TmdbId = model.TmdbId, Title = model.Title, - SortTitle = model.SortTitle, - InCinemas = model.InCinemas, - PhysicalRelease = model.PhysicalRelease, - DigitalRelease = model.DigitalRelease, + SortTitle = model.MovieMetadata.Value.SortTitle, + InCinemas = model.MovieMetadata.Value.InCinemas, + PhysicalRelease = model.MovieMetadata.Value.PhysicalRelease, + DigitalRelease = model.MovieMetadata.Value.DigitalRelease, - Status = model.Status, - Overview = model.Overview, + Status = model.MovieMetadata.Value.Status, + Overview = model.MovieMetadata.Value.Overview, - Images = model.Images, + Images = model.MovieMetadata.Value.Images, Year = model.Year, - Runtime = model.Runtime, + Runtime = model.MovieMetadata.Value.Runtime, ImdbId = model.ImdbId, - Certification = model.Certification, - Website = model.Website, - Genres = model.Genres, - Ratings = model.Ratings, - YouTubeTrailerId = model.YouTubeTrailerId, - Studio = model.Studio, - Collection = model.Collection, + Certification = model.MovieMetadata.Value.Certification, + Website = model.MovieMetadata.Value.Website, + Genres = model.MovieMetadata.Value.Genres, + Ratings = model.MovieMetadata.Value.Ratings, + YouTubeTrailerId = model.MovieMetadata.Value.YouTubeTrailerId, + Studio = model.MovieMetadata.Value.Studio, + Collection = model.MovieMetadata.Value.Collection, Lists = new HashSet { model.ListId } }; } diff --git a/src/Radarr.Api.V3/Movies/AlternativeTitleController.cs b/src/Radarr.Api.V3/Movies/AlternativeTitleController.cs index 00c9b23c0..19f3faf93 100644 --- a/src/Radarr.Api.V3/Movies/AlternativeTitleController.cs +++ b/src/Radarr.Api.V3/Movies/AlternativeTitleController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; +using NzbDrone.Core.Movies; using NzbDrone.Core.Movies.AlternativeTitles; using Radarr.Http; using Radarr.Http.REST; @@ -11,10 +12,12 @@ namespace Radarr.Api.V3.Movies public class AlternativeTitleController : RestController { private readonly IAlternativeTitleService _altTitleService; + private readonly IMovieService _movieService; - public AlternativeTitleController(IAlternativeTitleService altTitleService) + public AlternativeTitleController(IAlternativeTitleService altTitleService, IMovieService movieService) { _altTitleService = altTitleService; + _movieService = movieService; } protected override AlternativeTitleResource GetResourceById(int id) @@ -23,11 +26,17 @@ namespace Radarr.Api.V3.Movies } [HttpGet] - public List GetAltTitles(int? movieId) + public List GetAltTitles(int? movieId, int? movieMetadataId) { + if (movieMetadataId.HasValue) + { + return _altTitleService.GetAllTitlesForMovie(movieMetadataId.Value).ToResource(); + } + if (movieId.HasValue) { - return _altTitleService.GetAllTitlesForMovie(movieId.Value).ToResource(); + var movie = _movieService.GetMovie(movieId.Value); + return _altTitleService.GetAllTitlesForMovie(movie.MovieMetadataId).ToResource(); } return _altTitleService.GetAllTitles().ToResource(); diff --git a/src/Radarr.Api.V3/Movies/AlternativeTitleResource.cs b/src/Radarr.Api.V3/Movies/AlternativeTitleResource.cs index a85b40a42..fee73c35d 100644 --- a/src/Radarr.Api.V3/Movies/AlternativeTitleResource.cs +++ b/src/Radarr.Api.V3/Movies/AlternativeTitleResource.cs @@ -16,7 +16,7 @@ namespace Radarr.Api.V3.Movies //Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing? //Todo: We should get the entire Profile instead of ID and Name separately public SourceType SourceType { get; set; } - public int MovieId { get; set; } + public int MovieMetadataId { get; set; } public string Title { get; set; } public string CleanTitle { get; set; } public int SourceId { get; set; } @@ -40,7 +40,7 @@ namespace Radarr.Api.V3.Movies { Id = model.Id, SourceType = model.SourceType, - MovieId = model.MovieId, + MovieMetadataId = model.MovieMetadataId, Title = model.Title, SourceId = model.SourceId, Votes = model.Votes, @@ -60,7 +60,7 @@ namespace Radarr.Api.V3.Movies { Id = resource.Id, SourceType = resource.SourceType, - MovieId = resource.MovieId, + MovieMetadataId = resource.MovieMetadataId, Title = resource.Title, SourceId = resource.SourceId, Votes = resource.Votes, diff --git a/src/Radarr.Api.V3/Movies/MovieController.cs b/src/Radarr.Api.V3/Movies/MovieController.cs index 23cc585fe..98bb2bda7 100644 --- a/src/Radarr.Api.V3/Movies/MovieController.cs +++ b/src/Radarr.Api.V3/Movies/MovieController.cs @@ -130,7 +130,7 @@ namespace Radarr.Api.V3.Movies var translations = _movieTranslationService .GetAllTranslationsForLanguage(configLanguage); - var tdict = translations.ToDictionary(x => x.MovieId); + var tdict = translations.ToDictionary(x => x.MovieMetadataId); coverFileInfos = _coverMapper.GetCoverFileInfos(); @@ -140,7 +140,7 @@ namespace Radarr.Api.V3.Movies foreach (var movie in movies) { - var translation = GetTranslationFromDict(tdict, movie, configLanguage); + var translation = GetTranslationFromDict(tdict, movie.MovieMetadata, configLanguage); moviesResources.Add(movie.ToResource(availDelay, translation, _qualityUpgradableSpecification)); } @@ -165,8 +165,8 @@ namespace Radarr.Api.V3.Movies var availDelay = _configService.AvailabilityDelay; - var translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id); - var translation = GetMovieTranslation(translations, movie, (Language)_configService.MovieInfoLanguage); + var translations = _movieTranslationService.GetAllTranslationsForMovie(movie.MovieMetadataId); + var translation = GetMovieTranslation(translations, movie.MovieMetadata, (Language)_configService.MovieInfoLanguage); var resource = movie.ToResource(availDelay, translation, _qualityUpgradableSpecification); MapCoversToLocal(resource); @@ -174,7 +174,7 @@ namespace Radarr.Api.V3.Movies return resource; } - private MovieTranslation GetMovieTranslation(List translations, Movie movie, Language configLanguage) + private MovieTranslation GetMovieTranslation(List translations, MovieMetadata movie, Language configLanguage) { if (configLanguage == Language.Original) { @@ -185,10 +185,10 @@ namespace Radarr.Api.V3.Movies }; } - return translations.FirstOrDefault(t => t.Language == configLanguage && t.MovieId == movie.Id); + return translations.FirstOrDefault(t => t.Language == configLanguage && t.MovieMetadataId == movie.Id); } - private MovieTranslation GetTranslationFromDict(Dictionary translations, Movie movie, Language configLanguage) + private MovieTranslation GetTranslationFromDict(Dictionary translations, MovieMetadata movie, Language configLanguage) { if (configLanguage == Language.Original) { @@ -237,7 +237,7 @@ namespace Radarr.Api.V3.Movies var availDelay = _configService.AvailabilityDelay; var translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id); - var translation = GetMovieTranslation(translations, movie, (Language)_configService.MovieInfoLanguage); + var translation = GetMovieTranslation(translations, movie.MovieMetadata, (Language)_configService.MovieInfoLanguage); BroadcastResourceChange(ModelAction.Updated, updatedMovie.ToResource(availDelay, translation, _qualityUpgradableSpecification)); @@ -268,7 +268,7 @@ namespace Radarr.Api.V3.Movies { var availDelay = _configService.AvailabilityDelay; var translations = _movieTranslationService.GetAllTranslationsForMovie(message.ImportedMovie.Movie.Id); - var translation = GetMovieTranslation(translations, message.ImportedMovie.Movie, (Language)_configService.MovieInfoLanguage); + var translation = GetMovieTranslation(translations, message.ImportedMovie.Movie.MovieMetadata, (Language)_configService.MovieInfoLanguage); BroadcastResourceChange(ModelAction.Updated, message.ImportedMovie.Movie.ToResource(availDelay, translation, _qualityUpgradableSpecification)); } @@ -288,7 +288,7 @@ namespace Radarr.Api.V3.Movies { var availDelay = _configService.AvailabilityDelay; var translations = _movieTranslationService.GetAllTranslationsForMovie(message.Movie.Id); - var translation = GetMovieTranslation(translations, message.Movie, (Language)_configService.MovieInfoLanguage); + var translation = GetMovieTranslation(translations, message.Movie.MovieMetadata, (Language)_configService.MovieInfoLanguage); BroadcastResourceChange(ModelAction.Updated, message.Movie.ToResource(availDelay, translation, _qualityUpgradableSpecification)); } @@ -297,7 +297,7 @@ namespace Radarr.Api.V3.Movies { var availDelay = _configService.AvailabilityDelay; var translations = _movieTranslationService.GetAllTranslationsForMovie(message.Movie.Id); - var translation = GetMovieTranslation(translations, message.Movie, (Language)_configService.MovieInfoLanguage); + var translation = GetMovieTranslation(translations, message.Movie.MovieMetadata, (Language)_configService.MovieInfoLanguage); BroadcastResourceChange(ModelAction.Updated, message.Movie.ToResource(availDelay, translation, _qualityUpgradableSpecification)); } @@ -315,7 +315,7 @@ namespace Radarr.Api.V3.Movies { var availDelay = _configService.AvailabilityDelay; var translations = _movieTranslationService.GetAllTranslationsForMovie(message.Movie.Id); - var translation = GetMovieTranslation(translations, message.Movie, (Language)_configService.MovieInfoLanguage); + var translation = GetMovieTranslation(translations, message.Movie.MovieMetadata, (Language)_configService.MovieInfoLanguage); BroadcastResourceChange(ModelAction.Updated, message.Movie.ToResource(availDelay, translation, _qualityUpgradableSpecification)); } diff --git a/src/Radarr.Api.V3/Movies/MovieLookupController.cs b/src/Radarr.Api.V3/Movies/MovieLookupController.cs index 3e2dde5e6..ebc52c748 100644 --- a/src/Radarr.Api.V3/Movies/MovieLookupController.cs +++ b/src/Radarr.Api.V3/Movies/MovieLookupController.cs @@ -44,18 +44,18 @@ namespace Radarr.Api.V3.Movies public object SearchByTmdbId(int tmdbId) { var availDelay = _configService.AvailabilityDelay; - var result = _movieInfo.GetMovieInfo(tmdbId).Item1; - var translation = result.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage); + var result = new Movie { MovieMetadata = _movieInfo.GetMovieInfo(tmdbId).Item1 }; + var translation = result.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage); return result.ToResource(availDelay, translation); } [HttpGet("imdb")] public object SearchByImdbId(string imdbId) { - var result = _movieInfo.GetMovieByImdbId(imdbId); + var result = new Movie { MovieMetadata = _movieInfo.GetMovieByImdbId(imdbId) }; var availDelay = _configService.AvailabilityDelay; - var translation = result.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage); + var translation = result.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage); return result.ToResource(availDelay, translation); } @@ -72,12 +72,12 @@ namespace Radarr.Api.V3.Movies foreach (var currentMovie in movies) { var availDelay = _configService.AvailabilityDelay; - var translation = currentMovie.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage); + var translation = currentMovie.MovieMetadata.Value.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage); var resource = currentMovie.ToResource(availDelay, translation); _coverMapper.ConvertToLocalUrls(resource.Id, resource.Images); - var poster = currentMovie.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster); + var poster = currentMovie.MovieMetadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster); if (poster != null) { resource.RemotePoster = poster.RemoteUrl; diff --git a/src/Radarr.Api.V3/Movies/MovieResource.cs b/src/Radarr.Api.V3/Movies/MovieResource.cs index b0b1eeb83..605c265c9 100644 --- a/src/Radarr.Api.V3/Movies/MovieResource.cs +++ b/src/Radarr.Api.V3/Movies/MovieResource.cs @@ -74,6 +74,7 @@ namespace Radarr.Api.V3.Movies public Ratings Ratings { get; set; } public MovieFileResource MovieFile { get; set; } public MovieCollection Collection { get; set; } + public float Popularity { get; set; } } public static class MovieResourceMapper @@ -90,29 +91,29 @@ namespace Radarr.Api.V3.Movies MovieFileResource movieFile = model.MovieFile?.ToResource(model, upgradableSpecification); var translatedTitle = movieTranslation?.Title ?? model.Title; - var translatedOverview = movieTranslation?.Overview ?? model.Overview; + var translatedOverview = movieTranslation?.Overview ?? model.MovieMetadata.Value.Overview; return new MovieResource { Id = model.Id, TmdbId = model.TmdbId, Title = translatedTitle, - OriginalTitle = model.OriginalTitle, - OriginalLanguage = model.OriginalLanguage, + OriginalTitle = model.MovieMetadata.Value.OriginalTitle, + OriginalLanguage = model.MovieMetadata.Value.OriginalLanguage, SortTitle = translatedTitle.NormalizeTitle(), - InCinemas = model.InCinemas, - PhysicalRelease = model.PhysicalRelease, - DigitalRelease = model.DigitalRelease, + InCinemas = model.MovieMetadata.Value.InCinemas, + PhysicalRelease = model.MovieMetadata.Value.PhysicalRelease, + DigitalRelease = model.MovieMetadata.Value.DigitalRelease, HasFile = model.HasFile, SizeOnDisk = size, - Status = model.Status, + Status = model.MovieMetadata.Value.Status, Overview = translatedOverview, - Images = model.Images, + Images = model.MovieMetadata.Value.Images, Year = model.Year, - SecondaryYear = model.SecondaryYear, + SecondaryYear = model.MovieMetadata.Value.SecondaryYear, Path = model.Path, QualityProfileId = model.ProfileId, @@ -123,23 +124,24 @@ namespace Radarr.Api.V3.Movies IsAvailable = model.IsAvailable(availDelay), FolderName = model.FolderName(), - Runtime = model.Runtime, - CleanTitle = model.CleanTitle, + Runtime = model.MovieMetadata.Value.Runtime, + CleanTitle = model.MovieMetadata.Value.CleanTitle, ImdbId = model.ImdbId, - TitleSlug = model.TitleSlug, + TitleSlug = model.MovieMetadata.Value.TmdbId.ToString(), RootFolderPath = model.RootFolderPath, - Certification = model.Certification, - Website = model.Website, - Genres = model.Genres, + Certification = model.MovieMetadata.Value.Certification, + Website = model.MovieMetadata.Value.Website, + Genres = model.MovieMetadata.Value.Genres, Tags = model.Tags, Added = model.Added, AddOptions = model.AddOptions, - AlternateTitles = model.AlternativeTitles.ToResource(), - Ratings = model.Ratings, + AlternateTitles = model.MovieMetadata.Value.AlternativeTitles.ToResource(), + Ratings = model.MovieMetadata.Value.Ratings, MovieFile = movieFile, - YouTubeTrailerId = model.YouTubeTrailerId, - Studio = model.Studio, - Collection = model.Collection + YouTubeTrailerId = model.MovieMetadata.Value.YouTubeTrailerId, + Studio = model.MovieMetadata.Value.Studio, + Collection = model.MovieMetadata.Value.Collection, + Popularity = model.MovieMetadata.Value.Popularity }; } @@ -153,20 +155,29 @@ namespace Radarr.Api.V3.Movies return new Movie { Id = resource.Id, - TmdbId = resource.TmdbId, - Title = resource.Title, - OriginalTitle = resource.OriginalTitle, - SortTitle = resource.SortTitle, - InCinemas = resource.InCinemas, - PhysicalRelease = resource.PhysicalRelease, - - Overview = resource.Overview, - - Images = resource.Images, - - Year = resource.Year, - SecondaryYear = resource.SecondaryYear, + MovieMetadata = new MovieMetadata + { + TmdbId = resource.TmdbId, + Title = resource.Title, + Genres = resource.Genres, + Images = resource.Images, + OriginalTitle = resource.OriginalTitle, + SortTitle = resource.SortTitle, + InCinemas = resource.InCinemas, + PhysicalRelease = resource.PhysicalRelease, + Year = resource.Year, + SecondaryYear = resource.SecondaryYear, + Overview = resource.Overview, + Certification = resource.Certification, + Website = resource.Website, + Ratings = resource.Ratings, + YouTubeTrailerId = resource.YouTubeTrailerId, + Studio = resource.Studio, + Runtime = resource.Runtime, + CleanTitle = resource.CleanTitle, + ImdbId = resource.ImdbId, + }, Path = resource.Path, ProfileId = resource.QualityProfileId, @@ -174,20 +185,11 @@ namespace Radarr.Api.V3.Movies Monitored = resource.Monitored, MinimumAvailability = resource.MinimumAvailability, - Runtime = resource.Runtime, - CleanTitle = resource.CleanTitle, - ImdbId = resource.ImdbId, - TitleSlug = resource.TitleSlug, RootFolderPath = resource.RootFolderPath, - Certification = resource.Certification, - Website = resource.Website, - Genres = resource.Genres, + Tags = resource.Tags, Added = resource.Added, - AddOptions = resource.AddOptions, - Ratings = resource.Ratings, - YouTubeTrailerId = resource.YouTubeTrailerId, - Studio = resource.Studio + AddOptions = resource.AddOptions }; } diff --git a/src/Radarr.Api.V3/Queue/QueueController.cs b/src/Radarr.Api.V3/Queue/QueueController.cs index 9c558009d..a23c46039 100644 --- a/src/Radarr.Api.V3/Queue/QueueController.cs +++ b/src/Radarr.Api.V3/Queue/QueueController.cs @@ -183,7 +183,7 @@ namespace Radarr.Api.V3.Queue case "status": return q => q.Status; case "movies.sortTitle": - return q => q.Movie?.SortTitle ?? string.Empty; + return q => q.Movie?.MovieMetadata.Value.SortTitle ?? string.Empty; case "title": return q => q.Title; case "languages":