pull/3895/head
TidusJar 6 years ago
parent 0ce93071f1
commit cdec1f4f27

@ -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<MovieFullInfoViewModel> GetFullMovieInformation(int theMovieDbId, string langCode = null);
}
}

@ -50,6 +50,8 @@ namespace Ombi.Core.Engine
return await ProcessSingleMovie(viewMovie, true);
}
/// <summary>
/// Searches the specified movie.
/// </summary>

@ -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<MovieSearchEngineV2> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> 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<MovieFullInfoViewModel> GetFullMovieInformation(int theMovieDbId, string langCode = null)
{
langCode = await DefaultLanguageCode(langCode);
var movieInfo = await MovieApi.GetFullMovieInfo(theMovieDbId, langCode);
return await ProcessSingleMovie(movieInfo);
}
private async Task<MovieFullInfoViewModel> ProcessSingleMovie(FullMovieInfo movie)
{
var retVal = new MovieFullInfoViewModel();
retVal.Id = movie.Id; // TheMovieDbId
retVal.ImdbId = movie.ImdbId;
retVal.ReleaseDates = new ReleaseDatesDto
{
Results = new List<ReleaseResultsDto>()
};
retVal.TheMovieDbId = movie.Id.ToString();
var viewMovie = Mapper.Map<SearchMovieViewModel>(movie);
await RunSearchRules(viewMovie);
// This requires the rules to be run first to populate the RequestId property
await CheckForSubscription(viewMovie);
var mapped = Mapper.Map<MovieFullInfoViewModel>(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;
}
}
}
}

@ -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<ProductionCompaniesViewModel> 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<VideoResults> 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; }
}
}

@ -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<MovieSearchResult, SearchMovieViewModel>().ReverseMap();
CreateMap<MovieResponseDto, SearchMovieViewModel>().ReverseMap();
CreateMap<FullMovieInfo, SearchMovieViewModel>().ReverseMap();
CreateMap<ProductionCompanies, Production_Companies>().ReverseMap();
CreateMap<VideoResults, Videos>().ReverseMap();
CreateMap<CreditsViewModel, Credits>().ReverseMap();
CreateMap<MovieFullInfoViewModel, FullMovieInfo>()
.ForMember(x => x.)
}
}
}

@ -22,5 +22,6 @@ namespace Ombi.Api.TheMovieDb
Task<TheMovieDbContainer<ActorResult>> SearchByActor(string searchTerm, string langCode);
Task<ActorCredits> GetActorMovieCredits(int actorId, string langCode);
Task<TheMovieDbContainer<MultiSearch>> MultiSearch(string searchTerm, string languageCode);
Task<FullMovieInfo> GetFullMovieInfo(int movieId, string langCode);
}
}

@ -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; }
}
}

@ -32,6 +32,18 @@ namespace Ombi.Api.TheMovieDb
return Mapper.Map<MovieResponseDto>(result);
}
public async Task<FullMovieInfo> 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<FullMovieInfo>(request);
}
public async Task<FindResult> Find(string externalId, ExternalSource source)
{
var request = new Request($"find/{externalId}", BaseUri, HttpMethod.Get);

@ -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;
}

@ -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 => {

@ -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<IMultiSearchResult[]> {
return this.http.get<IMultiSearchResult[]>(`${this.url}/multi/${searchTerm}`);
}
public getFullMovieDetails(theMovieDbId: number): Observable<ISearchMovieResultV2> {
return this.http.get<ISearchMovieResultV2>(`${this.url}/Movie/${theMovieDbId}`);
}
public similarMovies(theMovieDbId: number, langCode: string): Observable<ISearchMovieResult[]> {
return this.http.post<ISearchMovieResult[]>(`${this.url}/Movie/similar`, {theMovieDbId, languageCode: langCode});
@ -38,7 +42,6 @@ export class SearchV2Service extends ServiceHelpers {
return this.http.get<ISearchMovieResult[]>(`${this.url}/Movie/toprated`);
}
public popularTv(): Observable<ISearchTvResult[]> {
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/popular`, { headers: this.headers });
}

@ -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;
/// <summary>
@ -41,6 +44,16 @@ namespace Ombi.Controllers.V2
return await _multiSearchEngine.MultiSearch(searchTerm);
}
// <summary>
/// Returns details for a single movie
/// </summary>
/// <returns></returns>
[HttpGet("movie/{movieDbId}")]
public async Task<MovieFullInfoViewModel> GetMovieInfo(int movieDbId)
{
return await _movieEngineV2.GetFullMovieInformation(movieDbId);
}
/// <summary>
/// Returns similar movies to the movie id passed in
/// </summary>

Loading…
Cancel
Save