From cdec1f4f27fe2f99e62c3d296ae14662ae0af572 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 30 Jan 2019 19:35:04 +0000 Subject: [PATCH] more !wip --- .../Engine/Interfaces/IMovieEngineV2.cs | 12 ++ src/Ombi.Core/Engine/MovieSearchEngine.cs | 2 + .../Engine/V2/MovieSearchEngineV2.cs | 102 ++++++++++ .../Search/V2/MovieFullInfoViewModel.cs | 95 ++++++++++ src/Ombi.Mapping/Profiles/MovieProfile.cs | 8 + src/Ombi.TheMovieDbApi/IMovieDbApi.cs | 1 + .../Models/FullMovieInfo.cs | 179 ++++++++++++++++++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 12 ++ .../app/interfaces/ISearchMovieResultV2.ts | 138 ++++++++++++++ .../media-details/movie-details.component.ts | 10 +- .../src/app/services/searchV2.service.ts | 7 +- src/Ombi/Controllers/V2/SearchController.cs | 15 +- 12 files changed, 573 insertions(+), 8 deletions(-) create mode 100644 src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs create mode 100644 src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs create mode 100644 src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs create mode 100644 src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs create mode 100644 src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs new file mode 100644 index 000000000..8e34c4f19 --- /dev/null +++ b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs @@ -0,0 +1,12 @@ +using Ombi.Core.Models.Search; +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Core.Models.Search.V2; + +namespace Ombi.Core +{ + public interface IMovieEngineV2 + { + Task GetFullMovieInformation(int theMovieDbId, string langCode = null); + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index 0e95e115b..692776f72 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -50,6 +50,8 @@ namespace Ombi.Core.Engine return await ProcessSingleMovie(viewMovie, true); } + + /// /// Searches the specified movie. /// diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs new file mode 100644 index 000000000..ffdeef769 --- /dev/null +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -0,0 +1,102 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; +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; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; +using Ombi.Core.Models.Search.V2; + +namespace Ombi.Core.Engine +{ + public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2 + { + public MovieSearchEngineV2(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub) + : base(identity, service, r, um, mem, s, sub) + { + MovieApi = movApi; + Mapper = mapper; + Logger = logger; + } + + private IMovieDbApi MovieApi { get; } + private IMapper Mapper { get; } + private ILogger Logger { get; } + + + public async Task GetFullMovieInformation(int theMovieDbId, string langCode = null) + { + langCode = await DefaultLanguageCode(langCode); + var movieInfo = await MovieApi.GetFullMovieInfo(theMovieDbId, langCode); + + return await ProcessSingleMovie(movieInfo); + } + + private async Task ProcessSingleMovie(FullMovieInfo movie) + { + var retVal = new MovieFullInfoViewModel(); + + retVal.Id = movie.Id; // TheMovieDbId + retVal.ImdbId = movie.ImdbId; + retVal.ReleaseDates = new ReleaseDatesDto + { + Results = new List() + }; + + retVal.TheMovieDbId = movie.Id.ToString(); + + var viewMovie = Mapper.Map(movie); + await RunSearchRules(viewMovie); + + // This requires the rules to be run first to populate the RequestId property + await CheckForSubscription(viewMovie); + var mapped = Mapper.Map(movie); + + mapped.Available = viewMovie.Available; + mapped.RequestId = viewMovie.RequestId; + mapped.Requested = viewMovie.Requested; + mapped.PlexUrl = viewMovie.PlexUrl; + mapped.EmbyUrl = viewMovie.EmbyUrl; + mapped.Subscribed = viewMovie.Subscribed; + mapped.ShowSubscribe = viewMovie.ShowSubscribe; + + return mapped; + } + + private async Task CheckForSubscription(SearchMovieViewModel viewModel) + { + // Check if this user requested it + var user = await GetUser(); + if (user == null) + { + return; + } + var request = await RequestService.MovieRequestService.GetAll() + .AnyAsync(x => x.RequestedUserId.Equals(user.Id) && x.TheMovieDbId == viewModel.Id); + if (request) + { + viewModel.ShowSubscribe = false; + } + else + { + viewModel.ShowSubscribe = true; + var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => s.UserId == user.Id + && s.RequestId == viewModel.RequestId && s.RequestType == RequestType.Movie); + viewModel.Subscribed = sub != null; + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs b/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs new file mode 100644 index 000000000..5f3c674f5 --- /dev/null +++ b/src/Ombi.Core/Models/Search/V2/MovieFullInfoViewModel.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using Ombi.Api.TheMovieDb.Models; +using Ombi.Store.Entities; + +namespace Ombi.Core.Models.Search.V2 +{ + public class MovieFullInfoViewModel : SearchViewModel + { + public bool Adult { get; set; } + public string BackdropPath { get; set; } + public string OriginalLanguage { get; set; } + public int Budget { get; set; } + public GenreViewModel[] Genres { get; set; } + public string OriginalTitle { get; set; } + public string Overview { get; set; } + public List ProductionCompanies { get; set; } + public double Popularity { get; set; } + public int Revenue { get; set; } + public long Runtime { get; set; } + public string PosterPath { get; set; } + public DateTime? ReleaseDate { get; set; } + public string Title { get; set; } + public bool Video { get; set; } + public string Tagline { get; set; } + public double VoteAverage { get; set; } + public int VoteCount { get; set; } + public bool AlreadyInCp { get; set; } + public string Trailer { get; set; } + public string Homepage { get; set; } + public int RootPathOverride { get; set; } + public string Status { get; set; } + public List Videos { get; set; } + public CreditsViewModel Credits { get; set; } + public int QualityOverride { get; set; } + public override RequestType Type => RequestType.Movie; + public ReleaseDatesDto ReleaseDates { get; set; } + public DateTime? DigitalReleaseDate { get; set; } + public Similar Similar { get; set; } + public Recommendations Recommendations { get; set; } + } + + public class GenreViewModel + { + public int id { get; set; } + public string name { get; set; } + } + + public class ProductionCompaniesViewModel + { + public int id { get; set; } + public string logo_path { get; set; } + public string name { get; set; } + public string origin_country { get; set; } + } + + public class VideoResults + { + public string id { get; set; } + public string iso_639_1 { get; set; } + public string iso_3166_1 { get; set; } + public string key { get; set; } + public string name { get; set; } + public string site { get; set; } + public int size { get; set; } + public string type { get; set; } + } + public class CreditsViewModel + { + public FullMovieCastViewModel[] cast { get; set; } + public FullMovieCrewViewModel[] crew { get; set; } + } + public class FullMovieCastViewModel + { + public int cast_id { get; set; } + public string character { get; set; } + public string credit_id { get; set; } + public int gender { get; set; } + public int id { get; set; } + public string name { get; set; } + public int order { get; set; } + public string profile_path { get; set; } + } + + public class FullMovieCrewViewModel + { + public string credit_id { get; set; } + public string department { get; set; } + public int gender { get; set; } + public int id { get; set; } + public string job { get; set; } + public string name { get; set; } + public string profile_path { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Mapping/Profiles/MovieProfile.cs b/src/Ombi.Mapping/Profiles/MovieProfile.cs index 39961b785..b11a9e1f7 100644 --- a/src/Ombi.Mapping/Profiles/MovieProfile.cs +++ b/src/Ombi.Mapping/Profiles/MovieProfile.cs @@ -1,6 +1,7 @@ using AutoMapper; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Search; +using Ombi.Core.Models.Search.V2; using Ombi.TheMovieDbApi.Models; namespace Ombi.Mapping.Profiles @@ -72,6 +73,13 @@ namespace Ombi.Mapping.Profiles CreateMap().ReverseMap(); CreateMap().ReverseMap(); + + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap() + .ForMember(x => x.) } } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index 78faab5dc..379636929 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -22,5 +22,6 @@ namespace Ombi.Api.TheMovieDb Task> SearchByActor(string searchTerm, string langCode); Task GetActorMovieCredits(int actorId, string langCode); Task> MultiSearch(string searchTerm, string languageCode); + Task GetFullMovieInfo(int movieId, string langCode); } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs b/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs new file mode 100644 index 000000000..654aa3c12 --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs @@ -0,0 +1,179 @@ +using System; +using Newtonsoft.Json; +using Ombi.TheMovieDbApi.Models; + +namespace Ombi.Api.TheMovieDb.Models +{ + public class FullMovieInfo + { + [JsonProperty("adult")] + public bool Adult { get; set; } + [JsonProperty("backdrop_path")] + public string BackdropPath { get; set; } + [JsonProperty("budget")] + public int Budget { get; set; } + [JsonProperty("genres")] + public Genre[] Genres { get; set; } + [JsonProperty("homepage")] + public string Homepage { get; set; } + [JsonProperty("id")] + public int Id { get; set; } + [JsonProperty("imdb_id")] + public string ImdbId { get; set; } + [JsonProperty("original_language")] + public string OriginalLanguage { get; set; } + [JsonProperty("original_title")] + public string OriginalTitle { get; set; } + [JsonProperty("overview")] + public string Overview { get; set; } + [JsonProperty("popularity")] + public float Popularity { get; set; } + [JsonProperty("poster_path")] + public string PosterPath { get; set; } + [JsonProperty("production_companies")] + public Production_Companies[] ProductionCompanies { get; set; } + [JsonProperty("production_countries")] + public Production_Countries[] ProductionCountries { get; set; } + [JsonProperty("release_date")] + public string ReleaseDate { get; set; } + [JsonProperty("revenue")] + public int Revenue { get; set; } + [JsonProperty("runtime")] + public long Runtime { get; set; } + [JsonProperty("spoken_languages")] + public Spoken_Languages[] SpokenLanguages { get; set; } + [JsonProperty("status")] + public string Status { get; set; } + [JsonProperty("tagline")] + public string Tagline { get; set; } + [JsonProperty("title")] + public string Title { get; set; } + [JsonProperty("video")] + public bool Video { get; set; } + [JsonProperty("vote_average")] + public float VoteAverage { get; set; } + [JsonProperty("vote_count")] + public int VoteCount { get; set; } + [JsonProperty("videos")] + public Videos Videos { get; set; } + [JsonProperty("credits")] + public Credits Credits { get; set; } + [JsonProperty("similar")] + public Similar Similar { get; set; } + [JsonProperty("recommendations")] + public Recommendations Recommendations { get; set; } + [JsonProperty("release_dates")] + public ReleaseDates ReleaseDates { get; set; } + } + + public class Videos + { + public Result[] results { get; set; } + } + + public class Result + { + public string id { get; set; } + public string iso_639_1 { get; set; } + public string iso_3166_1 { get; set; } + public string key { get; set; } + public string name { get; set; } + public string site { get; set; } + public int size { get; set; } + public string type { get; set; } + } + + public class Credits + { + public FullMovieCast[] cast { get; set; } + public FullMovieCrew[] crew { get; set; } + } + + public class FullMovieCast + { + public int cast_id { get; set; } + public string character { get; set; } + public string credit_id { get; set; } + public int gender { get; set; } + public int id { get; set; } + public string name { get; set; } + public int order { get; set; } + public string profile_path { get; set; } + } + + public class FullMovieCrew + { + public string credit_id { get; set; } + public string department { get; set; } + public int gender { get; set; } + public int id { get; set; } + public string job { get; set; } + public string name { get; set; } + public string profile_path { get; set; } + } + + public class Similar + { + public int page { get; set; } + public SimilarResults[] results { get; set; } + public int total_pages { get; set; } + public int total_results { get; set; } + } + + public class SimilarResults + { + public bool adult { get; set; } + public string backdrop_path { get; set; } + public int[] genre_ids { get; set; } + public int id { get; set; } + public string original_language { get; set; } + public string original_title { get; set; } + public string overview { get; set; } + public string poster_path { get; set; } + public string release_date { get; set; } + public string title { get; set; } + public bool video { get; set; } + public float vote_average { get; set; } + public int vote_count { get; set; } + public float popularity { get; set; } + } + + public class Recommendations + { + public int page { get; set; } + public RecommendationResults[] results { get; set; } + public int total_pages { get; set; } + public int total_results { get; set; } + } + + public class RecommendationResults + { + public bool adult { get; set; } + public string backdrop_path { get; set; } + public int[] genre_ids { get; set; } + public int id { get; set; } + public string original_language { get; set; } + public string original_title { get; set; } + public string overview { get; set; } + public string poster_path { get; set; } + public string release_date { get; set; } + public string title { get; set; } + public bool video { get; set; } + public float vote_average { get; set; } + public int vote_count { get; set; } + public float popularity { get; set; } + } + + public class Production_Countries + { + public string iso_3166_1 { get; set; } + public string name { get; set; } + } + + public class Spoken_Languages + { + public string iso_639_1 { get; set; } + public string name { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 32142507b..47652b26b 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -32,6 +32,18 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map(result); } + + public async Task GetFullMovieInfo(int movieId, string langCode) + { + var request = new Request($"movie/{movieId}", BaseUri, HttpMethod.Get); + request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.FullUri = request.FullUri.AddQueryParameter("append_to_response", "videos,credits,similar,recommendations,release_dates"); + AddRetry(request); + + return await Api.Request(request); + } + public async Task Find(string externalId, ExternalSource source) { var request = new Request($"find/{externalId}", BaseUri, HttpMethod.Get); diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts new file mode 100644 index 000000000..edfb55877 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResultV2.ts @@ -0,0 +1,138 @@ +export interface ISearchMovieResultV2 { + backdropPath: string; + adult: boolean; + overview: string; + budget: number; + genres: IGenresViewModel[], + releaseDate: Date; + revenue: number; + runtime: number; + tagline: string; + productionCompanies: IProductionCompanies[], + id: number; + originalTitle: string; + originalLanguage: string; + title: string; + posterPath: string; + popularity: number; + voteCount: number; + video: boolean; + voteAverage: number; + alreadyInCp: boolean; + trailer: string; + homepage: string; + imdbId: string; + approved: boolean; + requested: boolean; + requestId: number; + available: boolean; + status: string; + videos: IVideoResult[]; + credits: ICreditsViewModel; + releaseDates: IReleaseDatesDto; + similar: IOtherMovies; + recommendations: IOtherMovies; + plexUrl: string; + embyUrl: string; + quality: string; + digitalReleaseDate: Date; + subscribed: boolean; + showSubscribe: boolean; + + // for the UI + requestProcessing: boolean; + processed: boolean; + background: any; +} + +export interface IGenresViewModel { + id: number; + name: string; +} + +export interface IProductionCompanies { + id: number; + logo_path: string; + name: string; + origin_country: string; +} + +export interface IVideoResult { + id: number; + iso_639_1: string; + iso_3166_1: string; + key: string; + name: string; + site: string; + size: number; + type: string; +} + +export interface ICreditsViewModel { + cast: ICastViewModel[]; + crew: ICrewViewModel[]; +} + +export interface ICastViewModel { + cast_id: number; + character: string; + credit_id: string; + gender: number; + id: number; + name: string; + order: number; + profile_path: string; +} + +export interface ICrewViewModel { + credit_id: string; + department: string; + gender: number; + id: number; + job: string; + name: string; + profile_path: string; +} + +export interface IReleaseDatesDto { + results: IReleaseResultsDto[]; +} + +export interface IReleaseResultsDto { + isoCode: string; + releaseDate: IReleaseDateDto[]; +} + +export interface IReleaseDateDto { + releaseDate: Date; + type: ReleaseDateType; +} + +export enum ReleaseDateType { + Premiere = 1, + TheatricalLimited = 2, + Theatrical = 3, + Digital = 4, + Physical = 5, + Tv = 6 +} + +export interface IOtherMovies { + results: IOtherMoviesViewModel[]; +} + +export interface IOtherMoviesViewModel { + adult: boolean; + backdrop_path: string; + id: number; + original_language: string; + original_title: string; + overview : string; + poster_path: string; + release_date : string; + title : string; + video: boolean; + vote_average: number; + vote_count: number; + popularity: number; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/movie-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/movie-details.component.ts index 341a0639c..af33b4cd3 100644 --- a/src/Ombi/ClientApp/src/app/media-details/movie-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/movie-details.component.ts @@ -1,18 +1,18 @@ import { Component } from "@angular/core"; -import { SearchService, ImageService } from "../services"; +import { ImageService, SearchV2Service } from "../services"; import { ActivatedRoute } from "@angular/router"; -import { ISearchMovieResult } from "../interfaces"; import { DomSanitizer } from "@angular/platform-browser"; +import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2"; @Component({ templateUrl: "./movie-details.component.html", styleUrls: ["./movie-details.component.scss"], }) export class MovieDetailsComponent { - public movie: ISearchMovieResult; + public movie: ISearchMovieResultV2; private theMovidDbId: number; - constructor(private searchService: SearchService, private route: ActivatedRoute, + constructor(private searchService: SearchV2Service, private route: ActivatedRoute, private sanitizer: DomSanitizer, private imageService: ImageService) { this.route.params.subscribe((params: any) => { this.theMovidDbId = params.movieDbId; @@ -21,7 +21,7 @@ export class MovieDetailsComponent { } public load() { - this.searchService.getMovieInformation(this.theMovidDbId).subscribe(x => { + this.searchService.getFullMovieDetails(this.theMovidDbId).subscribe(x => { this.movie = x; this.imageService.getMovieBanner(this.theMovidDbId.toString()).subscribe(x => { diff --git a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts index 15895682e..e8558f060 100644 --- a/src/Ombi/ClientApp/src/app/services/searchV2.service.ts +++ b/src/Ombi/ClientApp/src/app/services/searchV2.service.ts @@ -6,6 +6,8 @@ import { Observable } from "rxjs"; import { IMultiSearchResult, ISearchMovieResult, ISearchTvResult } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; ++ +import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2"; @Injectable() export class SearchV2Service extends ServiceHelpers { @@ -16,7 +18,9 @@ export class SearchV2Service extends ServiceHelpers { public multiSearch(searchTerm: string): Observable { return this.http.get(`${this.url}/multi/${searchTerm}`); } - + public getFullMovieDetails(theMovieDbId: number): Observable { + return this.http.get(`${this.url}/Movie/${theMovieDbId}`); + } public similarMovies(theMovieDbId: number, langCode: string): Observable { return this.http.post(`${this.url}/Movie/similar`, {theMovieDbId, languageCode: langCode}); @@ -37,7 +41,6 @@ export class SearchV2Service extends ServiceHelpers { 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 }); diff --git a/src/Ombi/Controllers/V2/SearchController.cs b/src/Ombi/Controllers/V2/SearchController.cs index b509947dc..5e6ba52de 100644 --- a/src/Ombi/Controllers/V2/SearchController.cs +++ b/src/Ombi/Controllers/V2/SearchController.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Http; using Ombi.Core; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Search; +using Ombi.Core.Models.Search.V2; using Ombi.Models; namespace Ombi.Controllers.V2 @@ -18,17 +19,19 @@ namespace Ombi.Controllers.V2 public class SearchController : ControllerBase { public SearchController(IMultiSearchEngine multiSearchEngine, IMovieEngine movieEngine, - ITvSearchEngine tvSearchEngine) + ITvSearchEngine tvSearchEngine, IMovieEngineV2 v2Movie) { _multiSearchEngine = multiSearchEngine; _movieEngine = movieEngine; _movieEngine.ResultLimit = 12; _tvSearchEngine = tvSearchEngine; _tvSearchEngine.ResultLimit = 12; + _movieEngineV2 = v2Movie; } private readonly IMultiSearchEngine _multiSearchEngine; private readonly IMovieEngine _movieEngine; + private readonly IMovieEngineV2 _movieEngineV2; private readonly ITvSearchEngine _tvSearchEngine; /// @@ -41,6 +44,16 @@ namespace Ombi.Controllers.V2 return await _multiSearchEngine.MultiSearch(searchTerm); } + // + /// Returns details for a single movie + /// + /// + [HttpGet("movie/{movieDbId}")] + public async Task GetMovieInfo(int movieDbId) + { + return await _movieEngineV2.GetFullMovieInformation(movieDbId); + } + /// /// Returns similar movies to the movie id passed in ///