diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 2d82c88aab..d7fc1cc8e3 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -37,6 +37,7 @@ namespace MediaBrowser.Controller.Entities ProductionLocations = new List(); Images = new Dictionary(); ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); + Tags = new List(); } /// @@ -566,6 +567,12 @@ namespace MediaBrowser.Controller.Entities /// The people. public List People { get; set; } + /// + /// Gets or sets the tags. + /// + /// The tags. + public List Tags { get; set; } + /// /// Override this if you need to combine/collapse person information /// diff --git a/MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs index a510449054..dbeba42d92 100644 --- a/MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs @@ -135,6 +135,22 @@ namespace MediaBrowser.Controller.Providers.Movies } } + protected override bool RefreshOnVersionChange + { + get + { + return true; + } + } + + protected override string ProviderVersion + { + get + { + return "2"; + } + } + /// /// The _TMDB settings task /// @@ -258,10 +274,9 @@ namespace MediaBrowser.Controller.Providers.Movies private const string TmdbConfigUrl = "http://api.themoviedb.org/3/configuration?api_key={0}"; private const string Search3 = @"http://api.themoviedb.org/3/search/movie?api_key={1}&query={0}&language={2}"; private const string AltTitleSearch = @"http://api.themoviedb.org/3/movie/{0}/alternative_titles?api_key={1}&country={2}"; - private const string GetInfo3 = @"http://api.themoviedb.org/3/{3}/{0}?api_key={1}&language={2}"; - private const string CastInfo = @"http://api.themoviedb.org/3/movie/{0}/casts?api_key={1}"; - private const string ReleaseInfo = @"http://api.themoviedb.org/3/movie/{0}/releases?api_key={1}"; - private const string GetImages = @"http://api.themoviedb.org/3/{2}/{0}/images?api_key={1}"; + private const string GetMovieInfo3 = @"http://api.themoviedb.org/3/movie/{0}?api_key={1}&language={2}&append_to_response=casts,releases,images,keywords"; + private const string GetBoxSetInfo3 = @"http://api.themoviedb.org/3/collection/{0}?api_key={1}&language={2}&append_to_response=images"; + internal static string ApiKey = "f6bd687ffa63cd282b6ff2c6877f2669"; internal static string AcceptHeader = "application/json,image/*"; @@ -270,9 +285,8 @@ namespace MediaBrowser.Controller.Providers.Movies new Regex(@"(?.*)") // last resort matches the whole string as the name }; - public const string LOCAL_META_FILE_NAME = "mbmovie.json"; + public const string LOCAL_META_FILE_NAME = "tmdb3.json"; public const string ALT_META_FILE_NAME = "movie.xml"; - protected string ItemType = "movie"; protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) { @@ -295,6 +309,11 @@ namespace MediaBrowser.Controller.Providers.Movies return true; } + if (RefreshOnVersionChange && !String.Equals(ProviderVersion, providerInfo.ProviderVersion)) + { + return true; + } + var downloadDate = providerInfo.LastRefreshed; if (ConfigurationManager.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue) @@ -308,7 +327,6 @@ namespace MediaBrowser.Controller.Providers.Movies if (HasAltMeta(item)) return false; //never refresh if has meta from other source - Logger.Debug("MovieDbProvider - " + item.Name + " needs refresh. Download date: " + downloadDate + " item created date: " + item.DateCreated + " Check for Update age: " + ConfigurationManager.Configuration.MetadataRefreshDays); return true; } @@ -715,7 +733,7 @@ namespace MediaBrowser.Controller.Providers.Movies string childId = await AttemptFindId(name, year, language, cancellationToken).ConfigureAwait(false); if (childId != null) { - string url = string.Format(GetInfo3, childId, ApiKey, language, ItemType); + string url = string.Format(GetMovieInfo3, childId, ApiKey, language); try { @@ -765,39 +783,16 @@ namespace MediaBrowser.Controller.Providers.Movies return; } if (item.GetProviderId(MetadataProviders.Tmdb) == null) item.SetProviderId(MetadataProviders.Tmdb, id); - var mainTask = FetchMainResult(item, id, cancellationToken); - var castTask = FetchCastInfo(item, id, cancellationToken); - var releaseTask = FetchReleaseInfo(item, id, cancellationToken); - var imageTask = FetchImageInfo(item, id, cancellationToken); - await Task.WhenAll(mainTask, castTask, releaseTask).ConfigureAwait(false); + var mainResult = await FetchMainResult(item, id, cancellationToken).ConfigureAwait(false); - cancellationToken.ThrowIfCancellationRequested(); - - var mainResult = mainTask.Result; if (mainResult == null) return; - if (castTask.Result != null) - { - mainResult.cast = castTask.Result.cast; - mainResult.crew = castTask.Result.crew; - } - - if (releaseTask.Result != null) - { - mainResult.countries = releaseTask.Result.countries; - } - ProcessMainInfo(item, mainResult); - await Task.WhenAll(imageTask).ConfigureAwait(false); - cancellationToken.ThrowIfCancellationRequested(); - if (imageTask.Result != null) - { - await ProcessImages(item, imageTask.Result, cancellationToken).ConfigureAwait(false); - } + await ProcessImages(item, mainResult.images, cancellationToken).ConfigureAwait(false); //and save locally if (ConfigurationManager.Configuration.SaveLocalMeta && item.LocationType == LocationType.FileSystem) @@ -820,8 +815,9 @@ namespace MediaBrowser.Controller.Providers.Movies /// Task{CompleteMovieData}. protected async Task FetchMainResult(BaseItem item, string id, CancellationToken cancellationToken) { - ItemType = item is BoxSet ? "collection" : "movie"; - string url = string.Format(GetInfo3, id, ApiKey, ConfigurationManager.Configuration.PreferredMetadataLanguage, ItemType); + var baseUrl = item is BoxSet ? GetBoxSetInfo3 : GetMovieInfo3; + + string url = string.Format(baseUrl, id, ApiKey, ConfigurationManager.Configuration.PreferredMetadataLanguage); CompleteMovieData mainResult; cancellationToken.ThrowIfCancellationRequested(); @@ -864,7 +860,8 @@ namespace MediaBrowser.Controller.Providers.Movies if (ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower() != "en") { Logger.Info("MovieDbProvider couldn't find meta for language " + ConfigurationManager.Configuration.PreferredMetadataLanguage + ". Trying English..."); - url = string.Format(GetInfo3, id, ApiKey, "en", ItemType); + + url = string.Format(baseUrl, id, ApiKey, "en"); try { @@ -895,114 +892,6 @@ namespace MediaBrowser.Controller.Providers.Movies return mainResult; } - /// - /// Fetches the cast info. - /// - /// The item. - /// The id. - /// The cancellation token - /// Task{TmdbCastResult}. - protected async Task FetchCastInfo(BaseItem item, string id, CancellationToken cancellationToken) - { - //get cast and crew info - var url = string.Format(CastInfo, id, ApiKey); - TmdbCastResult cast = null; - - cancellationToken.ThrowIfCancellationRequested(); - - try - { - using (Stream json = await HttpClient.Get(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - ResourcePool = Current.MovieDbResourcePool, - AcceptHeader = AcceptHeader, - EnableResponseCache = true - - }).ConfigureAwait(false)) - { - cast = JsonSerializer.DeserializeFromStream(json); - } - } - catch (HttpException) - { - } - return cast; - } - - /// - /// Fetches the release info. - /// - /// The item. - /// The id. - /// The cancellation token - /// Task{TmdbReleasesResult}. - protected async Task FetchReleaseInfo(BaseItem item, string id, CancellationToken cancellationToken) - { - var url = string.Format(ReleaseInfo, id, ApiKey); - TmdbReleasesResult releases = null; - - cancellationToken.ThrowIfCancellationRequested(); - - try - { - using (Stream json = await HttpClient.Get(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - ResourcePool = Current.MovieDbResourcePool, - AcceptHeader = AcceptHeader, - EnableResponseCache = true - - }).ConfigureAwait(false)) - { - releases = JsonSerializer.DeserializeFromStream(json); - } - } - catch (HttpException) - { - } - - return releases; - } - - /// - /// Fetches the image info. - /// - /// The item. - /// The id. - /// The cancellation token - /// Task{TmdbImages}. - protected async Task FetchImageInfo(BaseItem item, string id, CancellationToken cancellationToken) - { - //fetch images - var url = string.Format(GetImages, id, ApiKey, ItemType); - TmdbImages images = null; - - cancellationToken.ThrowIfCancellationRequested(); - - try - { - using (Stream json = await HttpClient.Get(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - ResourcePool = Current.MovieDbResourcePool, - AcceptHeader = AcceptHeader, - EnableResponseCache = true - - }).ConfigureAwait(false)) - { - images = JsonSerializer.DeserializeFromStream(json); - } - } - catch (HttpException) - { - } - return images; - } - /// /// Processes the main info. /// @@ -1035,12 +924,13 @@ namespace MediaBrowser.Controller.Providers.Movies movie.CommunityRating = rating; //release date and certification are retrieved based on configured country and we fall back on US if not there - if (movieData.countries != null) + if (movieData.releases != null && movieData.releases.countries != null) { - var ourRelease = movieData.countries.FirstOrDefault(c => c.iso_3166_1.Equals(ConfigurationManager.Configuration.MetadataCountryCode, StringComparison.OrdinalIgnoreCase)) ?? new Country(); - var usRelease = movieData.countries.FirstOrDefault(c => c.iso_3166_1.Equals("US", StringComparison.OrdinalIgnoreCase)) ?? new Country(); + var ourRelease = movieData.releases.countries.FirstOrDefault(c => c.iso_3166_1.Equals(ConfigurationManager.Configuration.MetadataCountryCode, StringComparison.OrdinalIgnoreCase)) ?? new Country(); + var usRelease = movieData.releases.countries.FirstOrDefault(c => c.iso_3166_1.Equals("US", StringComparison.OrdinalIgnoreCase)) ?? new Country(); movie.OfficialRating = ourRelease.certification ?? usRelease.certification; + if (ourRelease.release_date > new DateTime(1900, 1, 1)) { movie.PremiereDate = ourRelease.release_date.ToUniversalTime(); @@ -1096,20 +986,25 @@ namespace MediaBrowser.Controller.Providers.Movies } movie.People.Clear(); + movie.Tags.Clear(); //Actors, Directors, Writers - all in People //actors come from cast - if (movieData.cast != null) + if (movieData.casts != null && movieData.casts.cast != null) { - foreach (var actor in movieData.cast.OrderBy(a => a.order)) movie.AddPerson(new PersonInfo { Name = actor.name, Role = actor.character, Type = PersonType.Actor }); + foreach (var actor in movieData.casts.cast.OrderBy(a => a.order)) movie.AddPerson(new PersonInfo { Name = actor.name, Role = actor.character, Type = PersonType.Actor }); } + //and the rest from crew - if (movieData.crew != null) + if (movieData.casts != null && movieData.casts.crew != null) { - foreach (var person in movieData.crew) movie.AddPerson(new PersonInfo { Name = person.name, Role = person.job, Type = person.department }); + foreach (var person in movieData.casts.crew) movie.AddPerson(new PersonInfo { Name = person.name, Role = person.job, Type = person.department }); } - + if (movieData.keywords != null && movieData.keywords.keywords != null) + { + movie.Tags = movieData.keywords.keywords.Select(i => i.name).ToList(); + } } } @@ -1121,7 +1016,7 @@ namespace MediaBrowser.Controller.Providers.Movies /// The images. /// The cancellation token /// Task. - protected virtual async Task ProcessImages(BaseItem item, TmdbImages images, CancellationToken cancellationToken) + protected virtual async Task ProcessImages(BaseItem item, MovieImagesImages images, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -1329,6 +1224,40 @@ namespace MediaBrowser.Controller.Providers.Movies #region Result Objects + /// + /// Class TmdbTitle + /// + protected class TmdbTitle + { + /// + /// Gets or sets the iso_3166_1. + /// + /// The iso_3166_1. + public string iso_3166_1 { get; set; } + /// + /// Gets or sets the title. + /// + /// The title. + public string title { get; set; } + } + + /// + /// Class TmdbAltTitleResults + /// + protected class TmdbAltTitleResults + { + /// + /// Gets or sets the id. + /// + /// The id. + public int id { get; set; } + /// + /// Gets or sets the titles. + /// + /// The titles. + public List titles { get; set; } + } + /// /// Class TmdbMovieSearchResult /// @@ -1412,361 +1341,122 @@ namespace MediaBrowser.Controller.Providers.Movies /// The total_results. public int total_results { get; set; } } - - /// - /// Class BelongsToCollection - /// + protected class BelongsToCollection { - /// - /// Gets or sets the id. - /// - /// The id. public int id { get; set; } - /// - /// Gets or sets the name. - /// - /// The name. public string name { get; set; } - /// - /// Gets or sets the poster_path. - /// - /// The poster_path. public string poster_path { get; set; } - /// - /// Gets or sets the backdrop_path. - /// - /// The backdrop_path. public string backdrop_path { get; set; } } - /// - /// Class Genre - /// - protected class Genre + protected class GenreItem { - /// - /// Gets or sets the id. - /// - /// The id. public int id { get; set; } - /// - /// Gets or sets the name. - /// - /// The name. public string name { get; set; } } - /// - /// Class ProductionCompany - /// protected class ProductionCompany { - /// - /// Gets or sets the name. - /// - /// The name. public string name { get; set; } - /// - /// Gets or sets the id. - /// - /// The id. public int id { get; set; } } - /// - /// Class ProductionCountry - /// protected class ProductionCountry { - /// - /// Gets or sets the iso_3166_1. - /// - /// The iso_3166_1. public string iso_3166_1 { get; set; } - /// - /// Gets or sets the name. - /// - /// The name. public string name { get; set; } } - /// - /// Class SpokenLanguage - /// protected class SpokenLanguage { - /// - /// Gets or sets the iso_639_1. - /// - /// The iso_639_1. public string iso_639_1 { get; set; } - /// - /// Gets or sets the name. - /// - /// The name. public string name { get; set; } } - /// - /// Class Cast - /// protected class Cast { - /// - /// Gets or sets the id. - /// - /// The id. public int id { get; set; } - /// - /// Gets or sets the name. - /// - /// The name. public string name { get; set; } - /// - /// Gets or sets the character. - /// - /// The character. public string character { get; set; } - /// - /// Gets or sets the order. - /// - /// The order. public int order { get; set; } - /// - /// Gets or sets the profile_path. - /// - /// The profile_path. + public int cast_id { get; set; } public string profile_path { get; set; } } - /// - /// Class Crew - /// protected class Crew { - /// - /// Gets or sets the id. - /// - /// The id. public int id { get; set; } - /// - /// Gets or sets the name. - /// - /// The name. public string name { get; set; } - /// - /// Gets or sets the department. - /// - /// The department. public string department { get; set; } - /// - /// Gets or sets the job. - /// - /// The job. public string job { get; set; } - /// - /// Gets or sets the profile_path. - /// - /// The profile_path. - public object profile_path { get; set; } + public string profile_path { get; set; } } - /// - /// Class Country - /// - protected class Country + protected class Casts { - /// - /// Gets or sets the iso_3166_1. - /// - /// The iso_3166_1. - public string iso_3166_1 { get; set; } - /// - /// Gets or sets the certification. - /// - /// The certification. - public string certification { get; set; } - /// - /// Gets or sets the release_date. - /// - /// The release_date. - public DateTime release_date { get; set; } - } - - //protected class TmdbMovieResult - //{ - // public bool adult { get; set; } - // public string backdrop_path { get; set; } - // public int belongs_to_collection { get; set; } - // public int budget { get; set; } - // public List genres { get; set; } - // public string homepage { get; set; } - // public int id { get; set; } - // public string imdb_id { get; set; } - // public string original_title { get; set; } - // public string overview { get; set; } - // public double popularity { get; set; } - // public string poster_path { get; set; } - // public List production_companies { get; set; } - // public List production_countries { get; set; } - // public string release_date { get; set; } - // public int revenue { get; set; } - // public int runtime { get; set; } - // public List spoken_languages { get; set; } - // public string tagline { get; set; } - // public string title { get; set; } - // public double vote_average { get; set; } - // public int vote_count { get; set; } - //} - - /// - /// Class TmdbTitle - /// - protected class TmdbTitle - { - /// - /// Gets or sets the iso_3166_1. - /// - /// The iso_3166_1. - public string iso_3166_1 { get; set; } - /// - /// Gets or sets the title. - /// - /// The title. - public string title { get; set; } - } - - /// - /// Class TmdbAltTitleResults - /// - protected class TmdbAltTitleResults - { - /// - /// Gets or sets the id. - /// - /// The id. - public int id { get; set; } - /// - /// Gets or sets the titles. - /// - /// The titles. - public List titles { get; set; } - } - - /// - /// Class TmdbCastResult - /// - protected class TmdbCastResult - { - /// - /// Gets or sets the id. - /// - /// The id. - public int id { get; set; } - /// - /// Gets or sets the cast. - /// - /// The cast. public List cast { get; set; } - /// - /// Gets or sets the crew. - /// - /// The crew. public List crew { get; set; } } - /// - /// Class TmdbReleasesResult - /// - protected class TmdbReleasesResult + protected class Country + { + public string iso_3166_1 { get; set; } + public string certification { get; set; } + public DateTime release_date { get; set; } + } + + protected class Releases { - /// - /// Gets or sets the id. - /// - /// The id. - public int id { get; set; } - /// - /// Gets or sets the countries. - /// - /// The countries. public List countries { get; set; } } - /// - /// Class TmdbImage - /// - protected class TmdbImage + protected class Backdrop { - /// - /// Gets or sets the file_path. - /// - /// The file_path. public string file_path { get; set; } - /// - /// Gets or sets the width. - /// - /// The width. public int width { get; set; } - /// - /// Gets or sets the height. - /// - /// The height. public int height { get; set; } - /// - /// Gets or sets the iso_639_1. - /// - /// The iso_639_1. public string iso_639_1 { get; set; } - /// - /// Gets or sets the aspect_ratio. - /// - /// The aspect_ratio. public double aspect_ratio { get; set; } - /// - /// Gets or sets the vote_average. - /// - /// The vote_average. public double vote_average { get; set; } - /// - /// Gets or sets the vote_count. - /// - /// The vote_count. public int vote_count { get; set; } } - /// - /// Class TmdbImages - /// - protected class TmdbImages + protected class Poster { - /// - /// Gets or sets the id. - /// - /// The id. - public int id { get; set; } - /// - /// Gets or sets the backdrops. - /// - /// The backdrops. - public List backdrops { get; set; } - /// - /// Gets or sets the posters. - /// - /// The posters. - public List posters { get; set; } + public string file_path { get; set; } + public int width { get; set; } + public int height { get; set; } + public string iso_639_1 { get; set; } + public double aspect_ratio { get; set; } + public double vote_average { get; set; } + public int vote_count { get; set; } + } + + protected class MovieImagesImages + { + public List backdrops { get; set; } + public List posters { get; set; } + } + + protected class Keyword + { + public int id { get; set; } + public string name { get; set; } + } + + protected class Keywords + { + public List keywords { get; set; } } - /// - /// Class CompleteMovieData - /// protected class CompleteMovieData { public bool adult { get; set; } public string backdrop_path { get; set; } public BelongsToCollection belongs_to_collection { get; set; } public int budget { get; set; } - public List genres { get; set; } + public List genres { get; set; } public string homepage { get; set; } public int id { get; set; } public string imdb_id { get; set; } @@ -1780,13 +1470,15 @@ namespace MediaBrowser.Controller.Providers.Movies public int revenue { get; set; } public int runtime { get; set; } public List spoken_languages { get; set; } + public string status { get; set; } public string tagline { get; set; } public string title { get; set; } public double vote_average { get; set; } public int vote_count { get; set; } - public List countries { get; set; } - public List cast { get; set; } - public List crew { get; set; } + public Casts casts { get; set; } + public Releases releases { get; set; } + public MovieImagesImages images { get; set; } + public Keywords keywords { get; set; } } public class TmdbImageSettings