From fefd0c02421865aca33d2670031bfecb82fb56ab Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 21 Feb 2019 22:27:57 +0000 Subject: [PATCH] Make the movies results random once the cache expires #2837 --- .../Engine/Interfaces/IMovieEngineV2.cs | 12 +- .../Engine/V2/MovieSearchEngineV2.cs | 133 +++++++++++++++++- src/Ombi.Helpers/LinqHelpers.cs | 27 ++++ src/Ombi/Controllers/V2/SearchController.cs | 16 +-- 4 files changed, 175 insertions(+), 13 deletions(-) diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs index 8e34c4f19..03518cf6d 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs @@ -1,12 +1,18 @@ -using Ombi.Core.Models.Search; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; +using Ombi.Core.Models.Search; using Ombi.Core.Models.Search.V2; -namespace Ombi.Core +namespace Ombi.Core.Engine.Interfaces { public interface IMovieEngineV2 { Task GetFullMovieInformation(int theMovieDbId, string langCode = null); + Task> SimilarMovies(int theMovieDbId, string langCode); + Task> PopularMovies(); + Task> TopRatedMovies(); + Task> UpcomingMovies(); + Task> NowPlayingMovies(); + int ResultLimit { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index e3fe312cb..384b28646 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -1,4 +1,7 @@ -using AutoMapper; +using System; +using System.Collections.Generic; +using System.Linq; +using AutoMapper; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.TheMovieDb; @@ -14,6 +17,7 @@ using Ombi.Store.Entities; using Ombi.Store.Repository; using System.Security.Principal; using System.Threading.Tasks; +using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Search.V2; namespace Ombi.Core.Engine.V2 @@ -42,6 +46,114 @@ namespace Ombi.Core.Engine.V2 return await ProcessSingleMovie(movieInfo); } + /// + /// Get similar movies to the id passed in + /// + /// + /// + public async Task> SimilarMovies(int theMovieDbId, string langCode) + { + langCode = await DefaultLanguageCode(langCode); + var result = await MovieApi.SimilarMovies(theMovieDbId, langCode); + if (result != null) + { + Logger.LogDebug("Search Result: {result}", result); + return await TransformMovieResultsToResponse(result.Shuffle().Take(ResultLimit)); // Take x to stop us overloading the API + } + return null; + } + + /// + /// Gets popular movies. + /// + /// + public async Task> PopularMovies() + { + + var result = await Cache.GetOrAdd(CacheKeys.PopularMovies, async () => + { + var langCode = await DefaultLanguageCode(null); + return await MovieApi.PopularMovies(langCode); + }, DateTime.Now.AddHours(12)); + if (result != null) + { + return await TransformMovieResultsToResponse(result.Shuffle().Take(ResultLimit)); // Take x to stop us overloading the API + } + return null; + } + + /// + /// Gets top rated movies. + /// + /// + public async Task> TopRatedMovies() + { + var result = await Cache.GetOrAdd(CacheKeys.TopRatedMovies, async () => + { + var langCode = await DefaultLanguageCode(null); + return await MovieApi.TopRated(langCode); + }, DateTime.Now.AddHours(12)); + if (result != null) + { + return await TransformMovieResultsToResponse(result.Shuffle().Take(ResultLimit)); // Take x to stop us overloading the API + } + return null; + } + + /// + /// Gets upcoming movies. + /// + /// + public async Task> UpcomingMovies() + { + var result = await Cache.GetOrAdd(CacheKeys.UpcomingMovies, async () => + { + var langCode = await DefaultLanguageCode(null); + return await MovieApi.Upcoming(langCode); + }, DateTime.Now.AddHours(12)); + if (result != null) + { + Logger.LogDebug("Search Result: {result}", result); + return await TransformMovieResultsToResponse(result.Shuffle().Take(ResultLimit)); // Take x to stop us overloading the API + } + return null; + } + + /// + /// Gets now playing movies. + /// + /// + public async Task> NowPlayingMovies() + { + var result = await Cache.GetOrAdd(CacheKeys.NowPlayingMovies, async () => + { + var langCode = await DefaultLanguageCode(null); + return await MovieApi.NowPlaying(langCode); + }, DateTime.Now.AddHours(12)); + if (result != null) + { + return await TransformMovieResultsToResponse(result.Shuffle().Take(ResultLimit)); // Take x to stop us overloading the API + } + return null; + } + + protected async Task> TransformMovieResultsToResponse( + IEnumerable movies) + { + var viewMovies = new List(); + foreach (var movie in movies) + { + viewMovies.Add(await ProcessSingleMovie(movie)); + } + return viewMovies; + } + + private async Task ProcessSingleMovie(MovieSearchResult movie) + { + var viewMovie = Mapper.Map(movie); + return await ProcessSingleMovie(viewMovie); + } + private async Task ProcessSingleMovie(FullMovieInfo movie) { var viewMovie = Mapper.Map(movie); @@ -62,6 +174,25 @@ namespace Ombi.Core.Engine.V2 return mapped; } + private async Task ProcessSingleMovie(SearchMovieViewModel viewMovie) + { + if (viewMovie.ImdbId.IsNullOrEmpty()) + { + var showInfo = await MovieApi.GetMovieInformation(viewMovie.Id); + viewMovie.Id = showInfo.Id; // TheMovieDbId + viewMovie.ImdbId = showInfo.ImdbId; + } + + viewMovie.TheMovieDbId = viewMovie.Id.ToString(); + + await RunSearchRules(viewMovie); + + // This requires the rules to be run first to populate the RequestId property + await CheckForSubscription(viewMovie); + + return viewMovie; + } + private async Task CheckForSubscription(SearchViewModel viewModel) { // Check if this user requested it diff --git a/src/Ombi.Helpers/LinqHelpers.cs b/src/Ombi.Helpers/LinqHelpers.cs index 67fdb5c53..af8d44633 100644 --- a/src/Ombi.Helpers/LinqHelpers.cs +++ b/src/Ombi.Helpers/LinqHelpers.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Ombi.Helpers { @@ -21,5 +22,31 @@ namespace Ombi.Helpers { return new HashSet(source, comparer); } + + public static IEnumerable Shuffle(this IEnumerable source) + { + return source.Shuffle(new Random()); + } + + public static IEnumerable Shuffle(this IEnumerable source, Random rng) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (rng == null) throw new ArgumentNullException(nameof(rng)); + + return source.ShuffleIterator(rng); + } + + private static IEnumerable ShuffleIterator( + this IEnumerable source, Random rng) + { + var buffer = source.ToList(); + for (int i = 0; i < buffer.Count; i++) + { + int j = rng.Next(i, buffer.Count); + yield return buffer[j]; + + buffer[j] = buffer[i]; + } + } } } \ No newline at end of file diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index 10bc9d07d..5000b41dc 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -18,20 +18,18 @@ namespace Ombi.Controllers.V2 [ApiController] public class SearchController : ControllerBase { - public SearchController(IMultiSearchEngine multiSearchEngine, IMovieEngine movieEngine, + public SearchController(IMultiSearchEngine multiSearchEngine, ITvSearchEngine tvSearchEngine, IMovieEngineV2 v2Movie, ITVSearchEngineV2 v2Tv) { _multiSearchEngine = multiSearchEngine; - _movieEngine = movieEngine; - _movieEngine.ResultLimit = 12; _tvSearchEngine = tvSearchEngine; _tvSearchEngine.ResultLimit = 12; _movieEngineV2 = v2Movie; + _movieEngineV2.ResultLimit = 12; _tvEngineV2 = v2Tv; } private readonly IMultiSearchEngine _multiSearchEngine; - private readonly IMovieEngine _movieEngine; private readonly IMovieEngineV2 _movieEngineV2; private readonly ITVSearchEngineV2 _tvEngineV2; private readonly ITvSearchEngine _tvSearchEngine; @@ -78,7 +76,7 @@ namespace Ombi.Controllers.V2 [ProducesDefaultResponseType] public async Task> SimilarMovies([FromBody] SimilarMoviesRefineModel model) { - return await _movieEngine.SimilarMovies(model.TheMovieDbId, model.LanguageCode); + return await _movieEngineV2.SimilarMovies(model.TheMovieDbId, model.LanguageCode); } @@ -92,7 +90,7 @@ namespace Ombi.Controllers.V2 [ProducesDefaultResponseType] public async Task> Popular() { - return await _movieEngine.PopularMovies(); + return await _movieEngineV2.PopularMovies(); } /// @@ -105,7 +103,7 @@ namespace Ombi.Controllers.V2 [ProducesDefaultResponseType] public async Task> NowPlayingMovies() { - return await _movieEngine.NowPlayingMovies(); + return await _movieEngineV2.NowPlayingMovies(); } /// @@ -118,7 +116,7 @@ namespace Ombi.Controllers.V2 [ProducesDefaultResponseType] public async Task> TopRatedMovies() { - return await _movieEngine.TopRatedMovies(); + return await _movieEngineV2.TopRatedMovies(); } /// @@ -131,7 +129,7 @@ namespace Ombi.Controllers.V2 [ProducesDefaultResponseType] public async Task> UpcomingMovies() { - return await _movieEngine.UpcomingMovies(); + return await _movieEngineV2.UpcomingMovies(); } ///