diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 9f02fdc905..a0dba1aab4 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -30,7 +30,6 @@ namespace MediaBrowser.Controller.Entities TrailerUrls = new List(); Studios = new List(); People = new List(); - CriticReviews = new List(); Taglines = new List(); ScreenshotImagePaths = new List(); BackdropImagePaths = new List(); @@ -671,12 +670,6 @@ namespace MediaBrowser.Controller.Entities /// The parent index number. public int? ParentIndexNumber { get; set; } - /// - /// Gets or sets the critic reviews. - /// - /// The critic reviews. - public List CriticReviews { get; set; } - public List ThemeSongIds { get; set; } public List ThemeVideoIds { get; set; } public List LocalTrailerIds { get; set; } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 378011e34f..2ffa8333a8 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -119,7 +119,6 @@ - diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index c91aeb9a5e..6f71ee9be8 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Persistence { @@ -48,5 +49,20 @@ namespace MediaBrowser.Controller.Persistence /// The cancellation token. /// Task. Task SaveChildren(Guid parentId, IEnumerable children, CancellationToken cancellationToken); + + /// + /// Gets the critic reviews. + /// + /// The item id. + /// Task{IEnumerable{ItemReview}}. + Task> GetCriticReviews(Guid itemId); + + /// + /// Saves the critic reviews. + /// + /// The item id. + /// The critic reviews. + /// Task. + Task SaveCriticReviews(Guid itemId, IEnumerable criticReviews); } } diff --git a/MediaBrowser.Controller/Providers/Movies/RottenTomatoesMovieProvider.cs b/MediaBrowser.Controller/Providers/Movies/RottenTomatoesMovieProvider.cs deleted file mode 100644 index 1ddc8d72c8..0000000000 --- a/MediaBrowser.Controller/Providers/Movies/RottenTomatoesMovieProvider.cs +++ /dev/null @@ -1,322 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Serialization; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Providers.Movies -{ - /// - /// Class RottenTomatoesMovieProvider - /// - public class RottenTomatoesProvider : BaseMetadataProvider - { - // http://developer.rottentomatoes.com/iodocs - - private const string MoviesReviews = @"movies/{1}/reviews.json?review_type=top_critic&page_limit=10&page=1&country=us&apikey={0}"; - - private const string ApiKey = "x9wjnvv39ntjmt9zs95nm7bg"; - - private const string BasicUrl = @"http://api.rottentomatoes.com/api/public/v1.0/"; - private const string MovieImdb = @"movie_alias.json?id={1}&type=imdb&apikey={0}"; - - private readonly SemaphoreSlim _rottenTomatoesResourcePool = new SemaphoreSlim(1, 1); - - /// - /// Gets the json serializer. - /// - /// The json serializer. - protected IJsonSerializer JsonSerializer { get; private set; } - - /// - /// Gets the HTTP client. - /// - /// The HTTP client. - protected IHttpClient HttpClient { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log manager. - /// The configuration manager. - /// The json serializer. - /// The HTTP client. - public RottenTomatoesProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient) - : base(logManager, configurationManager) - { - JsonSerializer = jsonSerializer; - HttpClient = httpClient; - } - - /// - /// Gets the provider version. - /// - /// The provider version. - protected override string ProviderVersion - { - get - { - return "5"; - } - } - - /// - /// Gets a value indicating whether [requires internet]. - /// - /// true if [requires internet]; otherwise, false. - public override bool RequiresInternet - { - get - { - return true; - } - } - - /// - /// Gets a value indicating whether [refresh on version change]. - /// - /// true if [refresh on version change]; otherwise, false. - protected override bool RefreshOnVersionChange - { - get - { - return true; - } - } - - /// - /// Supports the specified item. - /// - /// The item. - /// true if XXXX, false otherwise - public override bool Supports(BaseItem item) - { - return false; - var trailer = item as Trailer; - - if (trailer != null) - { - return !trailer.IsLocalTrailer; - } - - // Don't support local trailers - return item is Movie; - } - - /// - /// Gets the comparison data. - /// - /// The imdb id. - /// Guid. - private Guid GetComparisonData(string imdbId) - { - return string.IsNullOrEmpty(imdbId) ? Guid.Empty : imdbId.GetMD5(); - } - - /// - /// Gets the priority. - /// - /// The priority. - public override MetadataProviderPriority Priority - { - get - { - // Run after moviedb and xml providers - return MetadataProviderPriority.Last; - } - } - - /// - /// Needses the refresh internal. - /// - /// The item. - /// The provider info. - /// true if XXXX, false otherwise - protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) - { - // Refresh if rt id has changed - if (providerInfo.Data != GetComparisonData(item.GetProviderId(MetadataProviders.Imdb))) - { - return true; - } - - return base.NeedsRefreshInternal(item, providerInfo); - } - - /// - /// Fetches metadata and returns true or false indicating if any work that requires persistence was done - /// - /// The item. - /// if set to true [force]. - /// The cancellation token. - /// Task{System.Boolean}. - public override async Task FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) - { - BaseProviderInfo data; - - if (!item.ProviderData.TryGetValue(Id, out data)) - { - data = new BaseProviderInfo(); - item.ProviderData[Id] = data; - } - - var imdbId = item.GetProviderId(MetadataProviders.Imdb); - - if (string.IsNullOrEmpty(imdbId)) - { - data.Data = GetComparisonData(imdbId); - data.LastRefreshStatus = ProviderRefreshStatus.Success; - return true; - } - - await FetchRottenTomatoesId(item, cancellationToken).ConfigureAwait(false); - - using (var stream = await HttpClient.Get(new HttpRequestOptions - { - Url = GetMovieReviewsUrl(item.GetProviderId(MetadataProviders.RottenTomatoes)), - ResourcePool = _rottenTomatoesResourcePool, - CancellationToken = cancellationToken, - EnableResponseCache = true - - }).ConfigureAwait(false)) - { - - var result = JsonSerializer.DeserializeFromStream(stream); - - item.CriticReviews = result.reviews.Select(rtReview => new ItemReview - { - ReviewerName = rtReview.critic, - Publisher = rtReview.publication, - Date = DateTime.Parse(rtReview.date).ToUniversalTime(), - Caption = rtReview.quote, - Url = rtReview.links.review, - Likes = string.Equals(rtReview.freshness, "fresh", StringComparison.OrdinalIgnoreCase) - - }).ToList(); - } - - data.Data = GetComparisonData(item.GetProviderId(MetadataProviders.Imdb)); - data.LastRefreshStatus = ProviderRefreshStatus.Success; - SetLastRefreshed(item, DateTime.UtcNow); - - return true; - } - - /// - /// Fetches the rotten tomatoes id. - /// - /// The item. - /// The cancellation token. - /// Task. - private async Task FetchRottenTomatoesId(BaseItem item, CancellationToken cancellationToken) - { - var imdbId = item.GetProviderId(MetadataProviders.Imdb); - - // Have IMDB Id - using (var stream = await HttpClient.Get(new HttpRequestOptions - { - Url = GetMovieImdbUrl(imdbId), - ResourcePool = _rottenTomatoesResourcePool, - CancellationToken = cancellationToken, - EnableResponseCache = true - - }).ConfigureAwait(false)) - { - var hit = JsonSerializer.DeserializeFromStream(stream); - - if (!string.IsNullOrEmpty(hit.id)) - { - // Got a result - item.CriticRatingSummary = hit.critics_consensus; - item.CriticRating = float.Parse(hit.ratings.critics_score); - - item.SetProviderId(MetadataProviders.RottenTomatoes, hit.id); - } - } - } - - - // Utility functions to get the URL of the API calls - - private string GetMovieReviewsUrl(string rtId) - { - return BasicUrl + string.Format(MoviesReviews, ApiKey, rtId); - } - private string GetMovieImdbUrl(string imdbId) - { - return BasicUrl + string.Format(MovieImdb, ApiKey, imdbId.TrimStart('t')); - } - - // Data contract classes for use with the Rotten Tomatoes API - - protected class RTReviewList - { - public int total { get; set; } - public List reviews { get; set; } - } - - protected class RTReview - { - public string critic { get; set; } - public string date { get; set; } - public string freshness { get; set; } - public string publication { get; set; } - public string quote { get; set; } - public RTReviewLink links { get; set; } - public string original_score { get; set; } - } - - protected class RTReviewLink - { - public string review { get; set; } - } - - protected class RTSearchResults - { - public int total { get; set; } - public List movies { get; set; } - public RTSearchLinks links { get; set; } - public string link_template { get; set; } - } - - protected class RTSearchLinks - { - public string self { get; set; } - public string next { get; set; } - public string previous { get; set; } - } - - protected class RTMovieSearchResult - { - public string title { get; set; } - public int year { get; set; } - public string runtime { get; set; } - public string synopsis { get; set; } - public string critics_consensus { get; set; } - public string mpaa_rating { get; set; } - public string id { get; set; } - public RTRatings ratings { get; set; } - public RTAlternateIds alternate_ids { get; set; } - } - - protected class RTRatings - { - public string critics_rating { get; set; } - public string critics_score { get; set; } - } - - protected class RTAlternateIds - { - public string imdb { get; set; } - } - - } -} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs b/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs index 52dfeb9f2d..72e3a3a6e8 100644 --- a/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs +++ b/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Providers.Music } } - artist.PremiereDate = yearFormed > 0 ? new DateTime(yearFormed, 1,1) : DateTime.MinValue; + artist.PremiereDate = yearFormed > 0 ? new DateTime(yearFormed, 1, 1, 0, 0, 0, DateTimeKind.Utc) : (DateTime?)null; artist.ProductionYear = yearFormed; if (data.tags != null) { diff --git a/MediaBrowser.Server.Implementations/Sqlite/SQLiteItemRepository.cs b/MediaBrowser.Server.Implementations/Sqlite/SQLiteItemRepository.cs index 9138baad05..a8108f56e5 100644 --- a/MediaBrowser.Server.Implementations/Sqlite/SQLiteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Sqlite/SQLiteItemRepository.cs @@ -2,6 +2,7 @@ using System.Linq; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Server.Implementations.Reflection; @@ -321,5 +322,64 @@ namespace MediaBrowser.Server.Implementations.Sqlite } }); } + + /// + /// Gets the critic reviews path. + /// + /// The critic reviews path. + private string CriticReviewsPath + { + get + { + var path = Path.Combine(_appPaths.DataPath, "critic-reviews"); + + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + return path; + } + } + + /// + /// Gets the critic reviews. + /// + /// The item id. + /// Task{IEnumerable{ItemReview}}. + public Task> GetCriticReviews(Guid itemId) + { + return Task.Run>(() => + { + + try + { + var path = Path.Combine(CriticReviewsPath, itemId + ".json"); + + return _jsonSerializer.DeserializeFromFile>(path); + } + catch (FileNotFoundException) + { + return new List(); + } + + }); + } + + /// + /// Saves the critic reviews. + /// + /// The item id. + /// The critic reviews. + /// Task. + public Task SaveCriticReviews(Guid itemId, IEnumerable criticReviews) + { + return Task.Run(() => + { + var path = Path.Combine(CriticReviewsPath, itemId + ".json"); + + _jsonSerializer.SerializeToFile(criticReviews.ToList(), path); + }); + } } } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 1feb828482..dd40546c91 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.98 + 3.0.100 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,9 +12,9 @@ Contains common components shared by Media Browser Theatre and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 85d2ca3c5e..5524946a85 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.98 + 3.0.100 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 5670f8a6ce..e7f1a628a4 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.98 + 3.0.100 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - +