diff --git a/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs new file mode 100644 index 000000000..86582fb4d --- /dev/null +++ b/src/Ombi.Core/Engine/Demo/DemoMovieSearchEngine.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; +using Ombi.Config; +using Ombi.Core.Authentication; +using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Core.Engine.Demo +{ + public class DemoMovieSearchEngine : MovieSearchEngine, IDemoMovieSearchEngine + { + public DemoMovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, + IRepository sub, IOptions lists) + : base(identity, service, movApi, mapper, logger, r, um, mem, s, sub) + { + _demoLists = lists.Value; + } + + private readonly DemoLists _demoLists; + + public async Task> Search(string search) + { + var result = await MovieApi.SearchMovie(search, null, "en"); + + for (var i = 0; i < result.Count; i++) + { + if (!_demoLists.Movies.Contains(result[i].Id)) + { + result.RemoveAt(i); + } + } + if(result.Count > 0) + return await TransformMovieResultsToResponse(result.Take(MovieLimit)); // Take x to stop us overloading the API + return null; + } + + public async Task> NowPlayingMovies() + { + var rand = new Random(); + var responses = new List(); + for (int i = 0; i < 10; i++) + { + var item = rand.Next(_demoLists.Movies.Length); + var movie = _demoLists.Movies[item]; + if (responses.Any(x => x.Id == movie)) + { + i--; + continue; + } + var movieResult = await MovieApi.GetMovieInformationWithExtraInfo(movie); + var viewMovie = Mapper.Map(movieResult); + + responses.Add(await ProcessSingleMovie(viewMovie)); + } + + return responses; + } + + public async Task> PopularMovies() + { + return await NowPlayingMovies(); + } + + + public async Task> TopRatedMovies() + { + return await NowPlayingMovies(); + } + + public async Task> UpcomingMovies() + { + + return await NowPlayingMovies(); + } + } + + public interface IDemoMovieSearchEngine + { + Task> NowPlayingMovies(); + + Task> PopularMovies(); + + Task> Search(string search); + + Task> TopRatedMovies(); + + Task> UpcomingMovies(); + + } +} diff --git a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs new file mode 100644 index 000000000..edf9c430d --- /dev/null +++ b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs @@ -0,0 +1,96 @@ +using AutoMapper; +using Microsoft.Extensions.Options; +using Ombi.Api.Trakt; +using Ombi.Api.TvMaze; +using Ombi.Config; +using Ombi.Core.Authentication; +using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace Ombi.Core.Engine.Demo +{ + public class DemoTvSearchEngine : TvSearchEngine, IDemoTvSearchEngine + { + + public DemoTvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, + ISettingsService plexSettings, ISettingsService embySettings, IPlexContentRepository repo, + IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, + ISettingsService s, IRepository sub, IOptions lists) + : base(identity, service, tvMaze, mapper, plexSettings, embySettings, repo, embyRepo, trakt, r, um, memCache, s, sub) + { + _demoLists = lists.Value; + } + + private readonly DemoLists _demoLists; + + public async Task> Search(string search) + { + var searchResult = await TvMazeApi.Search(search); + + for (var i = 0; i < searchResult.Count; i++) + { + if (!_demoLists.TvShows.Contains(searchResult[i].show?.externals?.thetvdb ?? 0)) + { + searchResult.RemoveAt(i); + } + } + + if (searchResult != null) + { + var retVal = new List(); + foreach (var tvMazeSearch in searchResult) + { + if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false)) + { + continue; + } + retVal.Add(ProcessResult(tvMazeSearch)); + } + return retVal; + } + return null; + } + + public async Task> NowPlayingMovies() + { + var rand = new Random(); + var responses = new List(); + for (int i = 0; i < 10; i++) + { + var item = rand.Next(_demoLists.TvShows.Length); + var tv = _demoLists.TvShows[item]; + if (responses.Any(x => x.Id == tv)) + { + i--; + continue; + } + + var movieResult = await TvMazeApi.ShowLookup(tv); + responses.Add(ProcessResult(movieResult)); + } + + return responses; + } + + + + } + + public interface IDemoTvSearchEngine + { + Task> Search(string search); + Task> NowPlayingMovies(); + } +} diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index dda58348f..84cb8afcf 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -31,11 +31,11 @@ namespace Ombi.Core.Engine Logger = logger; } - private IMovieDbApi MovieApi { get; } - private IMapper Mapper { get; } + protected IMovieDbApi MovieApi { get; } + protected IMapper Mapper { get; } private ILogger Logger { get; } - private const int MovieLimit = 10; + protected const int MovieLimit = 10; /// /// Lookups the imdb information. @@ -184,7 +184,7 @@ namespace Ombi.Core.Engine return null; } - private async Task> TransformMovieResultsToResponse( + protected async Task> TransformMovieResultsToResponse( IEnumerable movies) { var viewMovies = new List(); @@ -195,7 +195,7 @@ namespace Ombi.Core.Engine return viewMovies; } - private async Task ProcessSingleMovie(SearchMovieViewModel viewMovie, bool lookupExtraInfo = false) + protected async Task ProcessSingleMovie(SearchMovieViewModel viewMovie, bool lookupExtraInfo = false) { if (lookupExtraInfo && viewMovie.ImdbId.IsNullOrEmpty()) { @@ -213,7 +213,7 @@ namespace Ombi.Core.Engine // This requires the rules to be run first to populate the RequestId property await CheckForSubscription(viewMovie); - + return viewMovie; } diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index c8e958002..b2e07f05e 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -40,8 +40,8 @@ namespace Ombi.Core.Engine EmbyContentRepo = embyRepo; } - private ITvMazeApi TvMazeApi { get; } - private IMapper Mapper { get; } + protected ITvMazeApi TvMazeApi { get; } + protected IMapper Mapper { get; } private ISettingsService PlexSettings { get; } private ISettingsService EmbySettings { get; } private IPlexContentRepository PlexContentRepo { get; } @@ -149,7 +149,7 @@ namespace Ombi.Core.Engine return processed; } - private IEnumerable ProcessResults(IEnumerable items) + protected IEnumerable ProcessResults(IEnumerable items) { var retVal = new List(); foreach (var tvMazeSearch in items) @@ -159,7 +159,7 @@ namespace Ombi.Core.Engine return retVal; } - private SearchTvShowViewModel ProcessResult(T tvMazeSearch) + protected SearchTvShowViewModel ProcessResult(T tvMazeSearch) { return Mapper.Map(tvMazeSearch); } diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 09dbf4e79..68a363706 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -53,6 +53,7 @@ using Ombi.Updater; using PlexContentCacher = Ombi.Schedule.Jobs.Plex; using Ombi.Api.Telegram; using Ombi.Core.Authentication; +using Ombi.Core.Engine.Demo; using Ombi.Core.Processor; using Ombi.Schedule.Jobs.Lidarr; using Ombi.Schedule.Jobs.Plex.Interfaces; @@ -92,6 +93,8 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } public static void RegisterHttp(this IServiceCollection services) { diff --git a/src/Ombi.Helpers/DemoLists.cs b/src/Ombi.Helpers/DemoLists.cs new file mode 100644 index 000000000..42deb3845 --- /dev/null +++ b/src/Ombi.Helpers/DemoLists.cs @@ -0,0 +1,10 @@ +namespace Ombi.Config +{ + public class DemoLists + { + public int[] Movies { get; set; } + public int[] TvShows { get; set; } + } + + +} \ No newline at end of file diff --git a/src/Ombi.Helpers/DemoSingleton.cs b/src/Ombi.Helpers/DemoSingleton.cs new file mode 100644 index 000000000..22b6b2f31 --- /dev/null +++ b/src/Ombi.Helpers/DemoSingleton.cs @@ -0,0 +1,13 @@ +namespace Ombi.Helpers +{ + public class DemoSingleton + { + private static DemoSingleton instance; + + private DemoSingleton() { } + + public static DemoSingleton Instance => instance ?? (instance = new DemoSingleton()); + + public bool Demo { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index 535581447..bdeacee2a 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -10,6 +10,8 @@ using Ombi.Core.Models.Search; using Ombi.Models; using StackExchange.Profiling; using Microsoft.AspNetCore.Http; +using Ombi.Core.Engine.Demo; +using Ombi.Helpers; namespace Ombi.Controllers { @@ -19,18 +21,26 @@ namespace Ombi.Controllers [ApiController] public class SearchController : Controller { - public SearchController(IMovieEngine movie, ITvSearchEngine tvEngine, ILogger logger, IMusicSearchEngine music) + public SearchController(IMovieEngine movie, ITvSearchEngine tvEngine, ILogger logger, IMusicSearchEngine music, + IDemoMovieSearchEngine demoMovieSearch, IDemoTvSearchEngine demoTvSearchEngine) { MovieEngine = movie; TvEngine = tvEngine; Logger = logger; MusicEngine = music; + DemoMovieSearch = demoMovieSearch; + DemoTvSearch = demoTvSearchEngine; + IsDemo = DemoSingleton.Instance.Demo; } + private ILogger Logger { get; } private IMovieEngine MovieEngine { get; } private ITvSearchEngine TvEngine { get; } private IMusicSearchEngine MusicEngine { get; } + private IDemoMovieSearchEngine DemoMovieSearch { get; } + private IDemoTvSearchEngine DemoTvSearch { get; } + private readonly bool IsDemo; /// /// Searches for a movie. @@ -47,6 +57,10 @@ namespace Ombi.Controllers { Logger.LogDebug("Searching : {searchTerm}", searchTerm); + if (IsDemo) + { + return await DemoMovieSearch.Search(searchTerm); + } return await MovieEngine.Search(searchTerm, null, null); } } @@ -173,6 +187,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> Popular() { + if (IsDemo) + { + return await DemoMovieSearch.PopularMovies(); + } return await MovieEngine.PopularMovies(); } /// @@ -185,6 +203,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> NowPlayingMovies() { + if (IsDemo) + { + return await DemoMovieSearch.NowPlayingMovies(); + } return await MovieEngine.NowPlayingMovies(); } /// @@ -197,6 +219,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> TopRatedMovies() { + if (IsDemo) + { + return await DemoMovieSearch.TopRatedMovies(); + } return await MovieEngine.TopRatedMovies(); } /// @@ -209,6 +235,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> UpcomingMovies() { + if (IsDemo) + { + return await DemoMovieSearch.UpcomingMovies(); + } return await MovieEngine.UpcomingMovies(); } @@ -223,6 +253,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> SearchTv(string searchTerm) { + if (IsDemo) + { + return await DemoTvSearch.Search(searchTerm); + } return await TvEngine.Search(searchTerm); } @@ -250,6 +284,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> PopularTv() { + if (IsDemo) + { + return await DemoTvSearch.NowPlayingMovies(); + } return await TvEngine.Popular(); } @@ -263,6 +301,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> AnticipatedTv() { + if (IsDemo) + { + return await DemoTvSearch.NowPlayingMovies(); + } return await TvEngine.Anticipated(); } @@ -277,6 +319,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> MostWatched() { + if (IsDemo) + { + return await DemoTvSearch.NowPlayingMovies(); + } return await TvEngine.MostWatches(); } @@ -290,6 +336,10 @@ namespace Ombi.Controllers [ProducesDefaultResponseType] public async Task> Trending() { + if (IsDemo) + { + return await DemoTvSearch.NowPlayingMovies(); + } return await TvEngine.Trending(); } diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 62e8e4dfe..acc904875 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -3,7 +3,6 @@ using System.IO; using System.Linq; using System.Text; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; using Ombi.Store.Context; using Ombi.Store.Entities; using CommandLine; @@ -24,12 +23,14 @@ namespace Ombi var host = string.Empty; var storagePath = string.Empty; var baseUrl = string.Empty; + var demo = false; var result = Parser.Default.ParseArguments(args) .WithParsed(o => { host = o.Host; storagePath = o.StoragePath; baseUrl = o.BaseUrl; + demo = o.Demo; }).WithNotParsed(err => { foreach (var e in err) @@ -44,6 +45,8 @@ namespace Ombi var urlValue = string.Empty; var instance = StoragePathSingleton.Instance; + var demoInstance = DemoSingleton.Instance; + demoInstance.Demo = demo; instance.StoragePath = storagePath ?? string.Empty; // Check if we need to migrate the settings CheckAndMigrate(); @@ -269,5 +272,8 @@ namespace Ombi [Option("baseurl", Required = false, HelpText = "The base URL for reverse proxy scenarios")] public string BaseUrl { get; set; } + [Option("demo", Required = false, HelpText = "Demo mode, you will never need to use this, fuck that fruit company...")] + public bool Demo { get; set; } + } } diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index d81227ff4..732089cf1 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -109,6 +109,7 @@ namespace Ombi services.Configure(configuration.GetSection("UserSettings")); services.Configure(configuration.GetSection("TokenAuthentication")); services.Configure(configuration.GetSection("LandingPageBackground")); + services.Configure(configuration.GetSection("Demo")); } public static void AddJwtAuthentication(this IServiceCollection services, IConfigurationRoot configuration) diff --git a/src/Ombi/appsettings.json b/src/Ombi/appsettings.json index 4ee01911a..7379d0a27 100644 --- a/src/Ombi/appsettings.json +++ b/src/Ombi/appsettings.json @@ -47,5 +47,67 @@ 296762, 280619 ] - } + }, + // Please ignore the below + "Demo": { + "Movies": [ + //https://en.wikipedia.org/wiki/List_of_films_in_the_public_domain_in_the_United_States + 130816, + 20278, + 22657, + 29998, + 22356, + 120862, + 23325, + 22718, + 10378, + 22733, + 144613, + 156397, + 43888, + 262743, + 92341, + 75888, + 53828, + 38346, + 33468, + 72012, + 22642, + 15401, + 16093, + 4808, + 111370, + 22948, + 165009, + 43386, + 105852, + 166316, + 18449, + 28503, + 20367, + 41021 //The Devil Bat + ], + "TvShows": [ + //https://infogalactic.com/info/List_of_TV_series_with_episodes_in_the_public_domain + 26741, + 9475, + 4379, + 17434, + 12751, + 17436, + 4378, + 7792, + 10643, + 23503, + 19339, + 10632, + 12740, + 23466, + 6910, + 3327, + 2122, + 22148, + 25941 // Front Row Center + ] + } }