Make the movies results random once the cache expires #2837

pull/3895/head
tidusjar 6 years ago
parent c1cdb91bf1
commit fefd0c0242

@ -1,12 +1,18 @@
using Ombi.Core.Models.Search; using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Models.Search;
using Ombi.Core.Models.Search.V2; using Ombi.Core.Models.Search.V2;
namespace Ombi.Core namespace Ombi.Core.Engine.Interfaces
{ {
public interface IMovieEngineV2 public interface IMovieEngineV2
{ {
Task<MovieFullInfoViewModel> GetFullMovieInformation(int theMovieDbId, string langCode = null); Task<MovieFullInfoViewModel> GetFullMovieInformation(int theMovieDbId, string langCode = null);
Task<IEnumerable<SearchMovieViewModel>> SimilarMovies(int theMovieDbId, string langCode);
Task<IEnumerable<SearchMovieViewModel>> PopularMovies();
Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies();
Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies();
Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies();
int ResultLimit { get; set; }
} }
} }

@ -1,4 +1,7 @@
using AutoMapper; using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb;
@ -14,6 +17,7 @@ using Ombi.Store.Entities;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Models.Search.V2; using Ombi.Core.Models.Search.V2;
namespace Ombi.Core.Engine.V2 namespace Ombi.Core.Engine.V2
@ -42,6 +46,114 @@ namespace Ombi.Core.Engine.V2
return await ProcessSingleMovie(movieInfo); return await ProcessSingleMovie(movieInfo);
} }
/// <summary>
/// Get similar movies to the id passed in
/// </summary>
/// <param name="theMovieDbId"></param>
/// <returns></returns>
public async Task<IEnumerable<SearchMovieViewModel>> 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;
}
/// <summary>
/// Gets popular movies.
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<SearchMovieViewModel>> 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;
}
/// <summary>
/// Gets top rated movies.
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<SearchMovieViewModel>> 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;
}
/// <summary>
/// Gets upcoming movies.
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<SearchMovieViewModel>> 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;
}
/// <summary>
/// Gets now playing movies.
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<SearchMovieViewModel>> 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<List<SearchMovieViewModel>> TransformMovieResultsToResponse(
IEnumerable<MovieSearchResult> movies)
{
var viewMovies = new List<SearchMovieViewModel>();
foreach (var movie in movies)
{
viewMovies.Add(await ProcessSingleMovie(movie));
}
return viewMovies;
}
private async Task<SearchMovieViewModel> ProcessSingleMovie(MovieSearchResult movie)
{
var viewMovie = Mapper.Map<SearchMovieViewModel>(movie);
return await ProcessSingleMovie(viewMovie);
}
private async Task<MovieFullInfoViewModel> ProcessSingleMovie(FullMovieInfo movie) private async Task<MovieFullInfoViewModel> ProcessSingleMovie(FullMovieInfo movie)
{ {
var viewMovie = Mapper.Map<SearchMovieViewModel>(movie); var viewMovie = Mapper.Map<SearchMovieViewModel>(movie);
@ -62,6 +174,25 @@ namespace Ombi.Core.Engine.V2
return mapped; return mapped;
} }
private async Task<SearchMovieViewModel> 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) private async Task CheckForSubscription(SearchViewModel viewModel)
{ {
// Check if this user requested it // Check if this user requested it

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Ombi.Helpers namespace Ombi.Helpers
{ {
@ -21,5 +22,31 @@ namespace Ombi.Helpers
{ {
return new HashSet<T>(source, comparer); return new HashSet<T>(source, comparer);
} }
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
return source.Shuffle(new Random());
}
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> 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<T> ShuffleIterator<T>(
this IEnumerable<T> 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];
}
}
} }
} }

@ -18,20 +18,18 @@ namespace Ombi.Controllers.V2
[ApiController] [ApiController]
public class SearchController : ControllerBase public class SearchController : ControllerBase
{ {
public SearchController(IMultiSearchEngine multiSearchEngine, IMovieEngine movieEngine, public SearchController(IMultiSearchEngine multiSearchEngine,
ITvSearchEngine tvSearchEngine, IMovieEngineV2 v2Movie, ITVSearchEngineV2 v2Tv) ITvSearchEngine tvSearchEngine, IMovieEngineV2 v2Movie, ITVSearchEngineV2 v2Tv)
{ {
_multiSearchEngine = multiSearchEngine; _multiSearchEngine = multiSearchEngine;
_movieEngine = movieEngine;
_movieEngine.ResultLimit = 12;
_tvSearchEngine = tvSearchEngine; _tvSearchEngine = tvSearchEngine;
_tvSearchEngine.ResultLimit = 12; _tvSearchEngine.ResultLimit = 12;
_movieEngineV2 = v2Movie; _movieEngineV2 = v2Movie;
_movieEngineV2.ResultLimit = 12;
_tvEngineV2 = v2Tv; _tvEngineV2 = v2Tv;
} }
private readonly IMultiSearchEngine _multiSearchEngine; private readonly IMultiSearchEngine _multiSearchEngine;
private readonly IMovieEngine _movieEngine;
private readonly IMovieEngineV2 _movieEngineV2; private readonly IMovieEngineV2 _movieEngineV2;
private readonly ITVSearchEngineV2 _tvEngineV2; private readonly ITVSearchEngineV2 _tvEngineV2;
private readonly ITvSearchEngine _tvSearchEngine; private readonly ITvSearchEngine _tvSearchEngine;
@ -78,7 +76,7 @@ namespace Ombi.Controllers.V2
[ProducesDefaultResponseType] [ProducesDefaultResponseType]
public async Task<IEnumerable<SearchMovieViewModel>> SimilarMovies([FromBody] SimilarMoviesRefineModel model) public async Task<IEnumerable<SearchMovieViewModel>> 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] [ProducesDefaultResponseType]
public async Task<IEnumerable<SearchMovieViewModel>> Popular() public async Task<IEnumerable<SearchMovieViewModel>> Popular()
{ {
return await _movieEngine.PopularMovies(); return await _movieEngineV2.PopularMovies();
} }
/// <summary> /// <summary>
@ -105,7 +103,7 @@ namespace Ombi.Controllers.V2
[ProducesDefaultResponseType] [ProducesDefaultResponseType]
public async Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies() public async Task<IEnumerable<SearchMovieViewModel>> NowPlayingMovies()
{ {
return await _movieEngine.NowPlayingMovies(); return await _movieEngineV2.NowPlayingMovies();
} }
/// <summary> /// <summary>
@ -118,7 +116,7 @@ namespace Ombi.Controllers.V2
[ProducesDefaultResponseType] [ProducesDefaultResponseType]
public async Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies() public async Task<IEnumerable<SearchMovieViewModel>> TopRatedMovies()
{ {
return await _movieEngine.TopRatedMovies(); return await _movieEngineV2.TopRatedMovies();
} }
/// <summary> /// <summary>
@ -131,7 +129,7 @@ namespace Ombi.Controllers.V2
[ProducesDefaultResponseType] [ProducesDefaultResponseType]
public async Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies() public async Task<IEnumerable<SearchMovieViewModel>> UpcomingMovies()
{ {
return await _movieEngine.UpcomingMovies(); return await _movieEngineV2.UpcomingMovies();
} }
/// <summary> /// <summary>

Loading…
Cancel
Save