diff --git a/src/Ombi.Core/Engine/BaseMediaEngine.cs b/src/Ombi.Core/Engine/BaseMediaEngine.cs index d0bb74c91..fde13a798 100644 --- a/src/Ombi.Core/Engine/BaseMediaEngine.cs +++ b/src/Ombi.Core/Engine/BaseMediaEngine.cs @@ -32,7 +32,12 @@ namespace Ombi.Core.Engine OmbiSettings = ombiSettings; _subscriptionRepository = sub; } - + private int _resultLimit; + public int ResultLimit + { + get => _resultLimit > 0 ? _resultLimit : 10; + set => _resultLimit = value; + } protected IRequestServiceMain RequestService { get; } protected IMovieRequestRepository MovieRepository => RequestService.MovieRequestService; protected ITvRequestRepository TvRepository => RequestService.TvRequestService; diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs index 9b4cd9831..598eef046 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs @@ -20,5 +20,6 @@ namespace Ombi.Core Task> SimilarMovies(int theMovieDbId, string langCode); Task> SearchActor(string search, string langaugeCode); + int ResultLimit { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs index 0926a7f9a..1ca119862 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs @@ -12,5 +12,6 @@ namespace Ombi.Core.Engine.Interfaces Task> Anticipated(); Task> MostWatches(); Task> Trending(); + int ResultLimit { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index dda58348f..0e95e115b 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -35,7 +35,6 @@ namespace Ombi.Core.Engine private IMapper Mapper { get; } private ILogger Logger { get; } - private const int MovieLimit = 10; /// /// Lookups the imdb information. @@ -61,7 +60,7 @@ namespace Ombi.Core.Engine if (result != null) { - return await TransformMovieResultsToResponse(result.Take(MovieLimit)); // Take x to stop us overloading the API + return await TransformMovieResultsToResponse(result.Take(ResultLimit)); // Take x to stop us overloading the API } return null; } @@ -105,7 +104,7 @@ namespace Ombi.Core.Engine if (result != null) { Logger.LogDebug("Search Result: {result}", result); - return await TransformMovieResultsToResponse(result.Take(MovieLimit)); // Take x to stop us overloading the API + return await TransformMovieResultsToResponse(result.Take(ResultLimit)); // Take x to stop us overloading the API } return null; } @@ -124,7 +123,7 @@ namespace Ombi.Core.Engine }, DateTime.Now.AddHours(12)); if (result != null) { - return await TransformMovieResultsToResponse(result.Take(MovieLimit)); // Take x to stop us overloading the API + return await TransformMovieResultsToResponse(result.Take(ResultLimit)); // Take x to stop us overloading the API } return null; } @@ -142,7 +141,7 @@ namespace Ombi.Core.Engine }, DateTime.Now.AddHours(12)); if (result != null) { - return await TransformMovieResultsToResponse(result.Take(MovieLimit)); // Take x to stop us overloading the API + return await TransformMovieResultsToResponse(result.Take(ResultLimit)); // Take x to stop us overloading the API } return null; } @@ -161,7 +160,7 @@ namespace Ombi.Core.Engine if (result != null) { Logger.LogDebug("Search Result: {result}", result); - return await TransformMovieResultsToResponse(result.Take(MovieLimit)); // Take x to stop us overloading the API + return await TransformMovieResultsToResponse(result.Take(ResultLimit)); // Take x to stop us overloading the API } return null; } @@ -179,7 +178,7 @@ namespace Ombi.Core.Engine }, DateTime.Now.AddHours(12)); if (result != null) { - return await TransformMovieResultsToResponse(result.Take(MovieLimit)); // Take x to stop us overloading the API + return await TransformMovieResultsToResponse(result.Take(ResultLimit)); // Take x to stop us overloading the API } return null; } diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index c8e958002..d34a40deb 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -122,7 +122,7 @@ namespace Ombi.Core.Engine public async Task> Popular() { - var result = await Cache.GetOrAdd(CacheKeys.PopularTv, async () => await TraktApi.GetPopularShows(), DateTime.Now.AddHours(12)); + var result = await Cache.GetOrAdd(CacheKeys.PopularTv, async () => await TraktApi.GetPopularShows(null, ResultLimit), DateTime.Now.AddHours(12)); var processed = ProcessResults(result); return processed; } @@ -130,21 +130,21 @@ namespace Ombi.Core.Engine public async Task> Anticipated() { - var result = await Cache.GetOrAdd(CacheKeys.AnticipatedTv, async () => await TraktApi.GetAnticipatedShows(), DateTime.Now.AddHours(12)); + var result = await Cache.GetOrAdd(CacheKeys.AnticipatedTv, async () => await TraktApi.GetAnticipatedShows(null, ResultLimit), DateTime.Now.AddHours(12)); var processed = ProcessResults(result); return processed; } public async Task> MostWatches() { - var result = await Cache.GetOrAdd(CacheKeys.MostWatchesTv, async () => await TraktApi.GetMostWatchesShows(), DateTime.Now.AddHours(12)); + var result = await Cache.GetOrAdd(CacheKeys.MostWatchesTv, async () => await TraktApi.GetMostWatchesShows(null, ResultLimit), DateTime.Now.AddHours(12)); var processed = ProcessResults(result); return processed; } public async Task> Trending() { - var result = await Cache.GetOrAdd(CacheKeys.TrendingTv, async () => await TraktApi.GetTrendingShows(), DateTime.Now.AddHours(12)); + var result = await Cache.GetOrAdd(CacheKeys.TrendingTv, async () => await TraktApi.GetTrendingShows(null, ResultLimit), DateTime.Now.AddHours(12)); var processed = ProcessResults(result); return processed; } diff --git a/src/Ombi/ClientApp/angular.json b/src/Ombi/ClientApp/angular.json index 821a3ef78..68d9b9cd8 100644 --- a/src/Ombi/ClientApp/angular.json +++ b/src/Ombi/ClientApp/angular.json @@ -27,7 +27,7 @@ "src/styles/_imports.scss", "node_modules/bootstrap/scss/bootstrap.scss", "node_modules/angular-bootstrap-md/scss/mdb-free.scss", - "node_modules/pace/themes/orange/pace-theme-flash.css", + "node_modules/pace/themes/orange/pace-theme-flat-top.css", "node_modules/font-awesome/scss/font-awesome.scss" ], "scripts": [ diff --git a/src/Ombi/ClientApp/src/app/discover/discover.component.ts b/src/Ombi/ClientApp/src/app/discover/discover.component.ts index aa5c3273b..45f4709a1 100644 --- a/src/Ombi/ClientApp/src/app/discover/discover.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/discover.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from "@angular/core"; -import { SearchService } from "../services"; +import { SearchV2Service } from "../services"; import { ISearchMovieResult, ISearchTvResult, RequestType } from "../interfaces"; import { IDiscoverCardResult } from "./interfaces"; import { trigger, transition, style, animate } from "@angular/animations"; @@ -24,7 +24,7 @@ export class DiscoverComponent implements OnInit { public defaultTvPoster: string; - constructor(private searchService: SearchService) { + constructor(private searchService: SearchV2Service) { } public async ngOnInit() { diff --git a/src/Ombi/ClientApp/src/app/services/index.ts b/src/Ombi/ClientApp/src/app/services/index.ts index edffdd625..8a97dd900 100644 --- a/src/Ombi/ClientApp/src/app/services/index.ts +++ b/src/Ombi/ClientApp/src/app/services/index.ts @@ -16,3 +16,4 @@ export * from "./notificationMessage.service"; export * from "./recentlyAdded.service"; export * from "./vote.service"; export * from "./requestretry.service"; +export * from "./searchV2.service"; diff --git a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts index fe8d10a90..15895682e 100644 --- a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IMultiSearchResult } from "../interfaces"; +import { IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @Injectable() @@ -16,4 +16,39 @@ export class SearchV2Service extends ServiceHelpers { public multiSearch(searchTerm: string): Observable { return this.http.get(`${this.url}/multi/${searchTerm}`); } + + + public similarMovies(theMovieDbId: number, langCode: string): Observable { + return this.http.post(`${this.url}/Movie/similar`, {theMovieDbId, languageCode: langCode}); + } + + public popularMovies(): Observable { + return this.http.get(`${this.url}/Movie/Popular`); + } + + public upcomingMovies(): Observable { + return this.http.get(`${this.url}/Movie/upcoming`); + } + + public nowPlayingMovies(): Observable { + return this.http.get(`${this.url}/Movie/nowplaying`); + } + + public topRatedMovies(): Observable { + return this.http.get(`${this.url}/Movie/toprated`); + } + + + public popularTv(): Observable { + return this.http.get(`${this.url}/Tv/popular`, { headers: this.headers }); + } + public mostWatchedTv(): Observable { + return this.http.get(`${this.url}/Tv/mostwatched`, { headers: this.headers }); + } + public anticipatedTv(): Observable { + return this.http.get(`${this.url}/Tv/anticipated`, { headers: this.headers }); + } + public trendingTv(): Observable { + return this.http.get(`${this.url}/Tv/trending`, { headers: this.headers }); + } } diff --git a/src/Ombi/ClientApp/yarn.lock b/src/Ombi/ClientApp/yarn.lock index c64062879..c95fc0efd 100644 --- a/src/Ombi/ClientApp/yarn.lock +++ b/src/Ombi/ClientApp/yarn.lock @@ -3955,16 +3955,6 @@ next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" -ng-auto-complete@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/ng-auto-complete/-/ng-auto-complete-4.1.4.tgz#f7b73d1f426d4de1c236b771f984f3d2da51b5fa" - dependencies: - tslib "^1.9.0" - -ng2-completer@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/ng2-completer/-/ng2-completer-2.0.8.tgz#36101eb5a796f966897e7894fc437effd88ebdfb" - ng2-cookies@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/ng2-cookies/-/ng2-cookies-1.0.12.tgz#3f3e613e0137b0649b705c678074b4bd08149ccc" diff --git a/src/Ombi/Controllers/V1/SearchController.cs b/src/Ombi/Controllers/V1/SearchController.cs index e4df4207b..665dc5fd5 100644 --- a/src/Ombi/Controllers/V1/SearchController.cs +++ b/src/Ombi/Controllers/V1/SearchController.cs @@ -136,7 +136,6 @@ namespace Ombi.Controllers.V1 /// /// Returns similar movies to the movie id passed in /// - /// ID of the movie /// /// We use TheMovieDb as the Movie Provider /// diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index e919d2cca..b509947dc 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -4,6 +4,11 @@ using Microsoft.AspNetCore.Mvc; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Engine.V2; using System.Collections.Generic; +using Microsoft.AspNetCore.Http; +using Ombi.Core; +using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Models.Search; +using Ombi.Models; namespace Ombi.Controllers.V2 { @@ -12,21 +17,148 @@ namespace Ombi.Controllers.V2 [ApiController] public class SearchController : ControllerBase { - public SearchController(IMultiSearchEngine multiSearchEngine) + public SearchController(IMultiSearchEngine multiSearchEngine, IMovieEngine movieEngine, + ITvSearchEngine tvSearchEngine) { _multiSearchEngine = multiSearchEngine; + _movieEngine = movieEngine; + _movieEngine.ResultLimit = 12; + _tvSearchEngine = tvSearchEngine; + _tvSearchEngine.ResultLimit = 12; } private readonly IMultiSearchEngine _multiSearchEngine; + private readonly IMovieEngine _movieEngine; + private readonly ITvSearchEngine _tvSearchEngine; /// - /// Runs the update job + /// Returns search results for both TV and Movies /// /// [HttpGet("multi/{searchTerm}")] - public async Task> ForceUpdate(string searchTerm) + public async Task> MultiSearch(string searchTerm) { return await _multiSearchEngine.MultiSearch(searchTerm); } + + /// + /// Returns similar movies to the movie id passed in + /// + /// + /// We use TheMovieDb as the Movie Provider + /// + [HttpPost("movie/similar")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> SimilarMovies([FromBody] SimilarMoviesRefineModel model) + { + return await _movieEngine.SimilarMovies(model.TheMovieDbId, model.LanguageCode); + } + + + /// + /// Returns Popular Movies + /// + /// We use TheMovieDb as the Movie Provider + /// + [HttpGet("movie/popular")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> Popular() + { + return await _movieEngine.PopularMovies(); + } + + /// + /// Returns Now Playing Movies + /// + /// We use TheMovieDb as the Movie Provider + /// + [HttpGet("movie/nowplaying")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> NowPlayingMovies() + { + return await _movieEngine.NowPlayingMovies(); + } + + /// + /// Returns top rated movies. + /// + /// + /// We use TheMovieDb as the Movie Provider + [HttpGet("movie/toprated")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> TopRatedMovies() + { + return await _movieEngine.TopRatedMovies(); + } + + /// + /// Returns Upcoming movies. + /// + /// We use TheMovieDb as the Movie Provider + /// + [HttpGet("movie/upcoming")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> UpcomingMovies() + { + return await _movieEngine.UpcomingMovies(); + } + + /// + /// Returns Popular Tv Shows + /// + /// We use Trakt.tv as the Provider + /// + [HttpGet("tv/popular")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> PopularTv() + { + return await _tvSearchEngine.Popular(); + } + + /// + /// Returns most Anticiplateds tv shows. + /// + /// We use Trakt.tv as the Provider + /// + [HttpGet("tv/anticipated")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> AnticipatedTv() + { + return await _tvSearchEngine.Anticipated(); + } + + + /// + /// Returns Most watched shows. + /// + /// We use Trakt.tv as the Provider + /// + [HttpGet("tv/mostwatched")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> MostWatched() + { + return await _tvSearchEngine.MostWatches(); + } + + /// + /// Returns trending shows + /// + /// We use Trakt.tv as the Provider + /// + [HttpGet("tv/trending")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesDefaultResponseType] + public async Task> Trending() + { + return await _tvSearchEngine.Trending(); + } } } \ No newline at end of file diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index dc9efb160..de8dbdc25 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -237,7 +237,8 @@ namespace Ombi app.UseSwagger(); app.UseSwaggerUI(c => { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + c.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1"); + c.SwaggerEndpoint("/swagger/v2/swagger.json", "API V2"); }); app.UseMvc(routes => diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index d81227ff4..f0bec1383 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -43,13 +43,14 @@ namespace Ombi c.SwaggerDoc("v1", new Info { Version = "v1", - Title = "Ombi Api", + Title = "Ombi Api V1", Contact = new Contact { Name = "Jamie Rees", Url = "https://www.ombi.io/" } }); + var security = new Dictionary> { //{"Bearer", new string[] { }},