Got tv working on the popout cards !wip

pull/3895/head
tidusjar 5 years ago
parent f3e781d576
commit 71ec151de1

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Api.TvMaze.Models;
using Ombi.Api.TvMaze.Models.V2;
namespace Ombi.Api.TvMaze
{
@ -11,5 +12,6 @@ namespace Ombi.Api.TvMaze
Task<List<TvMazeSearch>> Search(string searchTerm);
Task<TvMazeShow> ShowLookup(int showId);
Task<TvMazeShow> ShowLookupByTheTvDbId(int theTvDbId);
Task<FullSearch> GetTvFullInformation(int id);
}
}

@ -0,0 +1,144 @@
using System;
namespace Ombi.Api.TvMaze.Models.V2
{
public class FullSearch
{
public int id { get; set; }
public string url { get; set; }
public string name { get; set; }
public string type { get; set; }
public string language { get; set; }
public string[] genres { get; set; }
public string status { get; set; }
public int runtime { get; set; }
public string premiered { get; set; }
public string officialSite { get; set; }
public Schedule schedule { get; set; }
public Rating rating { get; set; }
public int weight { get; set; }
public Network network { get; set; }
public object webChannel { get; set; }
public Externals externals { get; set; }
public Image image { get; set; }
public string summary { get; set; }
public int updated { get; set; }
public _Links _links { get; set; }
public _Embedded _embedded { get; set; }
}
public class Schedule
{
public string time { get; set; }
public string[] days { get; set; }
}
public class Rating
{
public float average { get; set; }
}
public class Network
{
public int id { get; set; }
public string name { get; set; }
public Country country { get; set; }
}
public class Country
{
public string name { get; set; }
public string code { get; set; }
public string timezone { get; set; }
}
public class Externals
{
public int tvrage { get; set; }
public int thetvdb { get; set; }
public string imdb { get; set; }
}
public class Image
{
public string medium { get; set; }
public string original { get; set; }
}
public class _Links
{
public Self self { get; set; }
public Previousepisode previousepisode { get; set; }
}
public class Self
{
public string href { get; set; }
}
public class Previousepisode
{
public string href { get; set; }
}
public class _Embedded
{
public Cast[] cast { get; set; }
public Crew[] crew { get; set; }
public Episode[] episodes { get; set; }
}
public class Cast
{
public Person person { get; set; }
public Character character { get; set; }
public bool self { get; set; }
public bool voice { get; set; }
}
public class Person
{
public int id { get; set; }
public string url { get; set; }
public string name { get; set; }
public Country country { get; set; }
public string birthday { get; set; }
public object deathday { get; set; }
public string gender { get; set; }
public Image image { get; set; }
public _Links _links { get; set; }
}
public class Character
{
public int id { get; set; }
public string url { get; set; }
public string name { get; set; }
public Image image { get; set; }
public _Links _links { get; set; }
}
public class Crew
{
public string type { get; set; }
public Person person { get; set; }
}
public class Episode
{
public int id { get; set; }
public string url { get; set; }
public string name { get; set; }
public int season { get; set; }
public int number { get; set; }
public string airdate { get; set; }
public string airtime { get; set; }
public DateTime airstamp { get; set; }
public int runtime { get; set; }
public Image image { get; set; }
public string summary { get; set; }
public _Links _links { get; set; }
}
}

@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Ombi.Api.TvMaze.Models;
using Ombi.Api.TvMaze.Models.V2;
using Ombi.Helpers;
namespace Ombi.Api.TvMaze
@ -15,7 +15,6 @@ namespace Ombi.Api.TvMaze
{
Api = api;
Logger = logger;
//Mapper = mapper;
}
private string Uri = "http://api.tvmaze.com";
private IApi Api { get; }
@ -75,5 +74,17 @@ namespace Ombi.Api.TvMaze
return await Api.Request<List<TvMazeSeasons>>(request);
}
public async Task<FullSearch> GetTvFullInformation(int id)
{
var request = new Request($"shows/{id}", Uri, HttpMethod.Get);
request.AddQueryString("embed[]", "cast");
request.AddQueryString("embed[]", "crew");
request.AddQueryString("embed[]", "episodes");
request.AddContentHeader("Content-Type", "application/json");
return await Api.Request<FullSearch>(request);
}
}
}

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Ombi.Core.Models.Search.V2;
namespace Ombi.Core
{
public interface ITVSearchEngineV2
{
Task<SearchFullInfoTvShowViewModel> GetShowInformation(int tvdbid);
}
}

@ -12,14 +12,11 @@ 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
namespace Ombi.Core.Engine.V2
{
public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2
{

@ -0,0 +1,129 @@
using AutoMapper;
using Ombi.Api.Trakt;
using Ombi.Api.TvMaze;
using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search;
using Ombi.Core.Models.Search.V2;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Store.Repository;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Repository.Requests;
using Ombi.Core.Authentication;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities;
namespace Ombi.Core.Engine.V2
{
public class TvSearchEngineV2 : BaseMediaEngine, ITVSearchEngineV2
{
public TvSearchEngineV2(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService<PlexSettings> plexSettings,
ISettingsService<EmbySettings> embySettings, IPlexContentRepository repo, IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um,
ICacheService memCache, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub)
: base(identity, service, r, um, memCache, s, sub)
{
TvMazeApi = tvMaze;
Mapper = mapper;
PlexSettings = plexSettings;
EmbySettings = embySettings;
PlexContentRepo = repo;
TraktApi = trakt;
EmbyContentRepo = embyRepo;
}
private ITvMazeApi TvMazeApi { get; }
private IMapper Mapper { get; }
private ISettingsService<PlexSettings> PlexSettings { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private IPlexContentRepository PlexContentRepo { get; }
private IEmbyContentRepository EmbyContentRepo { get; }
private ITraktApi TraktApi { get; }
public async Task<SearchFullInfoTvShowViewModel> GetShowInformation(int tvdbid)
{
var tvdbshow = await TvMazeApi.ShowLookupByTheTvDbId(tvdbid);
var show = await TvMazeApi.GetTvFullInformation(tvdbshow.id);
if (show == null)
{
// We don't have enough information
return null;
}
var mapped = Mapper.Map<SearchFullInfoTvShowViewModel>(show);
foreach (var e in show._embedded.episodes)
{
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season);
if (season == null)
{
var newSeason = new SeasonRequests
{
SeasonNumber = e.season,
Episodes = new List<EpisodeRequests>()
};
newSeason.Episodes.Add(new EpisodeRequests
{
Url = e.url,
Title = e.name,
AirDate = e.airstamp,
EpisodeNumber = e.number,
});
mapped.SeasonRequests.Add(newSeason);
}
else
{
// We already have the season, so just add the episode
season.Episodes.Add(new EpisodeRequests
{
Url = e.url,
Title = e.name,
AirDate = e.airstamp,
EpisodeNumber = e.number,
});
}
}
return await ProcessResult(mapped);
}
private IEnumerable<SearchTvShowViewModel> ProcessResults<T>(IEnumerable<T> items)
{
var retVal = new List<SearchTvShowViewModel>();
foreach (var tvMazeSearch in items)
{
retVal.Add(ProcessResult(tvMazeSearch));
}
return retVal;
}
private SearchTvShowViewModel ProcessResult<T>(T tvMazeSearch)
{
return Mapper.Map<SearchTvShowViewModel>(tvMazeSearch);
}
private async Task<SearchFullInfoTvShowViewModel> ProcessResult(SearchFullInfoTvShowViewModel item)
{
item.TheTvDbId = item.Id.ToString();
var oldModel = Mapper.Map<SearchTvShowViewModel>(item);
await RunSearchRules(oldModel);
item.Available = oldModel.Available;
item.FullyAvailable = oldModel.FullyAvailable;
item.PartlyAvailable = oldModel.PartlyAvailable;
item.Requested = oldModel.Requested;
item.Available = oldModel.Available;
item.Approved = oldModel.Approved;
return item;
}
}
}

@ -0,0 +1,113 @@
using Ombi.Store.Repository.Requests;
using System.Collections.Generic;
using Ombi.Store.Entities;
namespace Ombi.Core.Models.Search.V2
{
public class SearchFullInfoTvShowViewModel : SearchViewModel
{
public string Title { get; set; }
public List<string> Aliases { get; set; }
public string Banner { get; set; }
public int SeriesId { get; set; }
public string Status { get; set; }
public string FirstAired { get; set; }
public string NetworkId { get; set; }
public string Runtime { get; set; }
public List<string> Genre { get; set; }
public string Overview { get; set; }
public int LastUpdated { get; set; }
public string AirsDayOfWeek { get; set; }
public string AirsTime { get; set; }
public string Rating { get; set; }
public int SiteRating { get; set; }
public NetworkViewModel Network { get; set; }
public Images Images { get; set; }
public List<CastViewModel> Cast { get; set; }
public List<CrewViewModel> Crew { get; set; }
/// <summary>
/// This is used from the Trakt API
/// </summary>
/// <value>
/// The trailer.
/// </value>
public string Trailer { get; set; }
/// <summary>
/// This is used from the Trakt API
/// </summary>
/// <value>
/// The trailer.
/// </value>
public string Homepage { get; set; }
public List<SeasonRequests> SeasonRequests { get; set; } = new List<SeasonRequests>();
/// <summary>
/// If we are requesting the entire series
/// </summary>
public bool RequestAll { get; set; }
public bool FirstSeason { get; set; }
public bool LatestSeason { get; set; }
/// <summary>
/// This is where we have EVERY Episode for that series
/// </summary>
public bool FullyAvailable { get; set; }
// We only have some episodes
public bool PartlyAvailable { get; set; }
public override RequestType Type => RequestType.TvShow;
}
public class NetworkViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public Country Country { get; set; }
}
public class Country
{
public string Name { get; set; }
public string Code { get; set; }
public string Timezone { get; set; }
}
public class Images
{
public string Medium { get; set; }
public string Original { get; set; }
}
public class CastViewModel
{
public PersonViewModel Person { get; set; }
public CharacterViewModel Character { get; set; }
public bool Self { get; set; }
public bool Voice { get; set; }
}
public class PersonViewModel
{
public int Id { get; set; }
public string Url { get; set; }
public string Name { get; set; }
public Images Image { get; set; }
}
public class CharacterViewModel
{
public int Id { get; set; }
public string Url { get; set; }
public string Name { get; set; }
public Images Image { get; set; }
}
public class CrewViewModel
{
public string Type { get; set; }
public PersonViewModel Person { get; set; }
}
}

@ -50,7 +50,6 @@ using Ombi.Schedule.Jobs.Plex;
using Ombi.Schedule.Jobs.Sonarr;
using Ombi.Store.Repository.Requests;
using Ombi.Updater;
using PlexContentCacher = Ombi.Schedule.Jobs.Plex;
using Ombi.Api.Telegram;
using Ombi.Core.Authentication;
using Ombi.Core.Engine.V2;
@ -59,7 +58,6 @@ using Ombi.Schedule.Jobs.Lidarr;
using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Schedule.Jobs.SickRage;
using Ombi.Schedule.Processor;
using Ombi.Store.Entities;
namespace Ombi.DependencyInjection
{
@ -100,6 +98,7 @@ namespace Ombi.DependencyInjection
{
services.AddTransient<IMultiSearchEngine, MultiSearchEngine>();
services.AddTransient<IMovieEngineV2, MovieSearchEngineV2>();
services.AddTransient<ITVSearchEngineV2, TvSearchEngineV2>();
}
public static void RegisterHttp(this IServiceCollection services)

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AutoMapper;
using AutoMapper.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -12,9 +11,9 @@ namespace Ombi.Mapping
{
public static IServiceCollection AddOmbiMappingProfile(this IServiceCollection services)
{
System.Reflection.Assembly ass = typeof(AutoMapperProfile).GetTypeInfo().Assembly;
Assembly ass = typeof(AutoMapperProfile).GetTypeInfo().Assembly;
var assemblies = new List<Type>();
foreach (System.Reflection.TypeInfo ti in ass.DefinedTypes)
foreach (TypeInfo ti in ass.DefinedTypes)
{
if (ti.ImplementedInterfaces.Contains(typeof(IProfileConfiguration)))
{

@ -0,0 +1,82 @@
using System.Globalization;
using AutoMapper;
using Ombi.Api.TvMaze.Models.V2;
using Ombi.Core.Models.Search;
using Ombi.Core.Models.Search.V2;
using Ombi.Helpers;
namespace Ombi.Mapping.Profiles
{
public class TvProfileV2 : Profile
{
public TvProfileV2()
{
CreateMap<FullSearch, SearchFullInfoTvShowViewModel>()
.ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.externals.thetvdb))
.ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.premiered))
.ForMember(dest => dest.ImdbId, opts => opts.MapFrom(src => src.externals.imdb))
.ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.network.name))
.ForMember(dest => dest.NetworkId, opts => opts.MapFrom(src => src.network.id.ToString()))
.ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.summary.RemoveHtml()))
.ForMember(dest => dest.Rating,
opts => opts.MapFrom(src => src.rating.average.ToString(CultureInfo.CurrentUICulture)))
.ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.runtime.ToString()))
.ForMember(dest => dest.SeriesId, opts => opts.MapFrom(src => src.id))
.ForMember(dest => dest.Title, opts => opts.MapFrom(src => src.name))
.ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.network))
.ForMember(dest => dest.Images, opts => opts.MapFrom(src => src.image))
.ForMember(dest => dest.Cast, opts => opts.MapFrom(src => src._embedded.cast))
.ForMember(dest => dest.Crew, opts => opts.MapFrom(src => src._embedded.crew))
.ForMember(dest => dest.Banner,
opts => opts.MapFrom(src =>
!string.IsNullOrEmpty(src.image.medium)
? src.image.medium.Replace("http", "https")
: string.Empty))
.ForMember(dest => dest.Status, opts => opts.MapFrom(src => src.status));
CreateMap<Network, NetworkViewModel>()
.ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id))
.ForMember(dest => dest.Country, opts => opts.MapFrom(src => src.country))
.ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name));
CreateMap<Api.TvMaze.Models.V2.Country, Core.Models.Search.V2.Country>()
.ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name))
.ForMember(dest => dest.Code, opts => opts.MapFrom(src => src.code))
.ForMember(dest => dest.Timezone, opts => opts.MapFrom(src => src.timezone));
CreateMap<Api.TvMaze.Models.V2.Image, Images>()
.ForMember(dest => dest.Medium, opts => opts.MapFrom(src => src.medium))
.ForMember(dest => dest.Original, opts => opts.MapFrom(src => src.original));
CreateMap<Api.TvMaze.Models.V2.Cast, CastViewModel>()
.ForMember(dest => dest.Character, opts => opts.MapFrom(src => src.character))
.ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person))
.ForMember(dest => dest.Voice, opts => opts.MapFrom(src => src.voice))
.ForMember(dest => dest.Self, opts => opts.MapFrom(src => src.self));
CreateMap<Api.TvMaze.Models.V2.Person, PersonViewModel>()
.ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id))
.ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name))
.ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.image))
.ForMember(dest => dest.Url, opts => opts.MapFrom(src => src.url));
CreateMap<Api.TvMaze.Models.V2.Crew, CrewViewModel>()
.ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person))
.ForMember(dest => dest.Type, opts => opts.MapFrom(src => src.type));
CreateMap<Api.TvMaze.Models.V2.Cast, CastViewModel>()
.ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person))
.ForMember(dest => dest.Self, opts => opts.MapFrom(src => src.self))
.ForMember(dest => dest.Voice, opts => opts.MapFrom(src => src.voice))
.ForMember(dest => dest.Character, opts => opts.MapFrom(src => src.character));
CreateMap<Api.TvMaze.Models.V2.Character, CharacterViewModel>()
.ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name))
.ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id))
.ForMember(dest => dest.Url, opts => opts.MapFrom(src => src.url))
.ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.image));
CreateMap<SearchTvShowViewModel, SearchFullInfoTvShowViewModel>().ReverseMap();
}
}
}

@ -85,8 +85,6 @@ export function HttpLoaderFactory(http: HttpClient, platformLocation: PlatformLo
}
export function baseurlFact() {
console.log(window['_app_base']);
return "/" + window['_app_base'];
}

@ -1,4 +1,7 @@
<div *ngIf="result" mat-dialog-content class="background">
<div class="spinner-container">
<mat-spinner *ngIf="loading" [color]="'accent'"></mat-spinner>
</div>
<div *ngIf="!loading" mat-dialog-content class="background">
<div class="row">
<div class="col-4">
<img id="cardImage" src="{{data.posterPath}}" class="poster" alt="{{data.title}}">
@ -19,9 +22,12 @@
[translate]="'Common.NotAvailable'"></span></ng-template></small>
</div>
<div class="col-6">
<strong>Studio: </strong> <small>{{result.productionCompanies[0].name}}</small>
<strong *ngIf="movie">Studio: </strong>
<small *ngIf="movie">{{movie.productionCompanies[0].name}}</small>
<strong *ngIf="tv">Network: </strong>
<small *ngIf="tv">{{tv.network.name}}</small>
</div>
<div class="col-6">
<div class="col-6" *ngIf="!data.available">
<strong>Request Status: </strong> <small>
<ng-template [ngIf]="data.approved && !data.available"><span class="label label-info"
id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span></ng-template>
@ -32,13 +38,22 @@
</small>
</div>
<div class="col-6">
<strong>Director: </strong> <small>{{result.credits.crew[0].name}}</small>
<strong *ngIf="movie">Director: </strong>
<small *ngIf="movie">{{movie.credits.crew[0].name}}</small>
<strong *ngIf="tvCreator">Director: </strong>
<small *ngIf="tvCreator">{{tvCreator}}</small>
</div>
<div class="col-6">
<strong>In Cinemas: </strong> <small>{{result.releaseDate}}</small>
<strong *ngIf="movie">In Cinemas: </strong>
<small *ngIf="movie">{{movie.releaseDate | amLocal | amDateFormat: 'LL'}}</small>
<strong *ngIf="tv">First Aired: </strong>
<small *ngIf="tv">{{tv.firstAired | amLocal | amDateFormat: 'LL'}}</small>
</div>
<div class="col-6">
<strong>Writer: </strong> <small>{{result.credits.crew[1].name}}</small>
<strong *ngIf="movie">Writer: </strong>
<small *ngIf="movie">{{movie.credits.crew[1].name}}</small>
<strong *ngIf="tv">Exec Producer: </strong>
<small *ngIf="tv">{{tvProducer}}</small>
</div>
</div>

@ -2,9 +2,9 @@ import { Component, Inject, OnInit } from "@angular/core";
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material";
import { IDiscoverCardResult } from "../interfaces";
import { SearchV2Service } from "../../services";
import { dataURLToBlob } from "blob-util";
import { RequestType } from "../../interfaces";
import { ISearchMovieResultV2 } from "../../interfaces/ISearchMovieResultV2";
import { ISearchTvResultV2 } from "../../interfaces/ISearchTvResultV2";
@Component({
selector: "discover-card-details",
@ -13,16 +13,33 @@ import { ISearchMovieResultV2 } from "../../interfaces/ISearchMovieResultV2";
})
export class DiscoverCardDetailsComponent implements OnInit {
public result: ISearchMovieResultV2;
public movie: ISearchMovieResultV2;
public tv: ISearchTvResultV2;
public tvCreator: string;
public tvProducer: string;
public loading: boolean;;
constructor(
public dialogRef: MatDialogRef<DiscoverCardDetailsComponent>,
@Inject(MAT_DIALOG_DATA) public data: IDiscoverCardResult, private searchService: SearchV2Service) { }
public async ngOnInit() {
this.loading = true;
if (this.data.type === RequestType.movie) {
this.result = await this.searchService.getFullMovieDetailsPromise(this.data.id);
this.movie = await this.searchService.getFullMovieDetailsPromise(this.data.id);
} else if (this.data.type === RequestType.tvShow) {
this.tv = await this.searchService.getTvInfo(this.data.id);
const creator = this.tv.crew.filter(tv => {
return tv.type === "Creator";
})[0];
if(creator) {
this.tvCreator = creator.person.name;
}
this.tvProducer = this.tv.crew.filter(tv => {
return tv.type === "Executive Producer";
})[0].person.name;
}
this.loading = false;
}
public onNoClick(): void {

@ -2,9 +2,9 @@
<div class="row justify-content-md-center top-spacing">
<div class="btn-group" role="group" aria-label="Basic example">
<button type="button" (click)="popular()" mat-raised-button class="btn" color="primary">Popular</button>
<button type="button" (click)="trending()" mat-raised-button class="btn" color="primary">Trending</button>
<button type="button" (click)="upcoming()" mat-raised-button class="btn" color="primary">Upcoming</button>
<button type="button" (click)="popular()" [ngClass]="popularActive ? 'active-button' : ''" mat-raised-button class="btn" color="primary">Popular</button>
<button type="button" (click)="trending()" [ngClass]="trendingActive ? 'active-button' : ''" mat-raised-button class="btn" color="primary">Trending</button>
<button type="button" (click)="upcoming()" [ngClass]="upcomingActive ? 'active-button' : ''" mat-raised-button class="btn" color="primary">Upcoming</button>
</div>
</div>
@ -15,21 +15,3 @@
</div>
</div>
<!-- <div class="small-middle-container">
<div class="row">
<div class="col-lg-5">
<div class="row">
<div class="col-lg-4 small-padding" *ngFor="let result of discoverResults" [@slideIn]>
<discover-card [result]="result"></discover-card>
</div>
</div>
</div>
<div class="col-lg-5">
<div class="row">
<div class="col-lg-4 small-padding" *ngFor="let result of discoverResults" [@slideIn]>
<discover-card [result]="result"></discover-card>
</div>
</div>
</div>
</div>
</div> -->

@ -24,6 +24,10 @@ export class DiscoverComponent implements OnInit {
public defaultTvPoster: string;
public popularActive: boolean = true;
public trendingActive: boolean;
public upcomingActive: boolean;
constructor(private searchService: SearchV2Service) {
}
@ -36,6 +40,9 @@ export class DiscoverComponent implements OnInit {
}
public async popular() {
this.popularActive = true;
this.trendingActive = false;
this.upcomingActive = false;
this.movies = await this.searchService.popularMovies().toPromise();
this.tvShows = await this.searchService.popularTv().toPromise();
@ -43,6 +50,9 @@ export class DiscoverComponent implements OnInit {
}
public async trending() {
this.popularActive = false;
this.trendingActive = true;
this.upcomingActive = false;
this.movies = await this.searchService.nowPlayingMovies().toPromise();
this.tvShows = await this.searchService.trendingTv().toPromise();
@ -50,6 +60,9 @@ export class DiscoverComponent implements OnInit {
}
public async upcoming() {
this.popularActive = false;
this.trendingActive = false;
this.upcomingActive = true;
this.movies = await this.searchService.upcomingMovies().toPromise();
this.tvShows = await this.searchService.anticipatedTv().toPromise();

@ -0,0 +1,86 @@
import { INewSeasonRequests } from "./IRequestModel";
export interface ISearchTvResultV2 {
id: number;
title: string; // used in the request
aliases: string[];
banner: string;
seriesId: number;
status: string;
firstAired: string;
networkId: string;
runtime: string;
genre: string[];
overview: string;
lastUpdated: number;
airsDayOfWeek: string;
airsTime: string;
rating: string;
imdbId: string;
siteRating: number;
trailer: string;
homepage: string;
seasonRequests: INewSeasonRequests[];
requestAll: boolean;
approved: boolean;
requested: boolean;
available: boolean;
plexUrl: string;
embyUrl: string;
quality: string;
firstSeason: boolean;
latestSeason: boolean;
theTvDbId: string;
subscribed: boolean;
showSubscribe: boolean;
fullyAvailable: boolean;
partlyAvailable: boolean;
network: INetwork;
images: IImagesV2;
cast: ICast[];
crew: ICrew[];
}
export interface INetwork {
id: number;
name: string;
country: ICountry;
}
export interface ICountry {
name: string;
code: string;
timezone: string;
}
export interface IImagesV2 {
medium: string;
original: string;
}
export interface ICast {
self: boolean;
voide: boolean;
person: IPersonViewModel;
character: ICharacterViewModel;
}
export interface IPersonViewModel {
id: number;
url: string;
name: string;
image: IImagesV2;
}
export interface ICharacterViewModel {
id: number;
url: string;
name: string;
image: IImagesV2;
}
export interface ICrew {
type: string;
person: IPersonViewModel;
}

@ -9,6 +9,7 @@ import { ServiceHelpers } from "./service.helpers";
import { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2";
import { promise } from "selenium-webdriver";
import { ISearchTvResultV2 } from "../interfaces/ISearchTvResultV2";
@Injectable()
export class SearchV2Service extends ServiceHelpers {
@ -55,7 +56,12 @@ export class SearchV2Service extends ServiceHelpers {
public anticipatedTv(): Observable<ISearchTvResult[]> {
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/anticipated`, { headers: this.headers });
}
public trendingTv(): Observable<ISearchTvResult[]> {
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/trending`, { headers: this.headers });
}
public getTvInfo(tvdbid: number): Promise<ISearchTvResultV2> {
return this.http.get<ISearchTvResultV2>(`${this.url}/Tv/${tvdbid}`, { headers: this.headers }).toPromise();
}
}

@ -11,7 +11,7 @@ import { InputSwitchModule, SidebarModule } from "primeng/primeng";
import {
MatButtonModule, MatNativeDateModule, MatIconModule, MatSidenavModule, MatListModule, MatToolbarModule, MatTooltipModule} from '@angular/material';
import { MatCardModule, MatInputModule, MatTabsModule, MatAutocompleteModule, MatCheckboxModule, MatExpansionModule, MatDialogModule } from "@angular/material";
import { MatCardModule, MatInputModule, MatTabsModule, MatAutocompleteModule, MatCheckboxModule, MatExpansionModule, MatDialogModule, MatProgressSpinnerModule } from "@angular/material";
@NgModule({
declarations: [
@ -25,6 +25,7 @@ import {
TruncateModule,
MomentModule,
MatCardModule,
MatProgressSpinnerModule,
MatAutocompleteModule,
MatInputModule,
MatTabsModule,
@ -43,6 +44,7 @@ import {
CommonModule,
FormsModule,
SidebarModule,
MatProgressSpinnerModule,
IssuesReportComponent,
TruncateModule,
InputSwitchModule,

@ -24,4 +24,14 @@
.btn-orange {
background-color: #F57C00;
}
}
.spinner-container {
position: relative;
margin-left: 50%;
}
.active-button {
background-color: #5dffbd !important;
color:white;
}

@ -19,7 +19,7 @@ namespace Ombi.Controllers.V2
public class SearchController : ControllerBase
{
public SearchController(IMultiSearchEngine multiSearchEngine, IMovieEngine movieEngine,
ITvSearchEngine tvSearchEngine, IMovieEngineV2 v2Movie)
ITvSearchEngine tvSearchEngine, IMovieEngineV2 v2Movie, ITVSearchEngineV2 v2Tv)
{
_multiSearchEngine = multiSearchEngine;
_movieEngine = movieEngine;
@ -27,11 +27,13 @@ namespace Ombi.Controllers.V2
_tvSearchEngine = tvSearchEngine;
_tvSearchEngine.ResultLimit = 12;
_movieEngineV2 = v2Movie;
_tvEngineV2 = v2Tv;
}
private readonly IMultiSearchEngine _multiSearchEngine;
private readonly IMovieEngine _movieEngine;
private readonly IMovieEngineV2 _movieEngineV2;
private readonly ITVSearchEngineV2 _tvEngineV2;
private readonly ITvSearchEngine _tvSearchEngine;
/// <summary>
@ -54,6 +56,17 @@ namespace Ombi.Controllers.V2
return await _movieEngineV2.GetFullMovieInformation(movieDbId);
}
/// <summary>
/// Returns details for a single show
/// </summary>
/// <returns></returns>
[HttpGet("tv/{tvdbId}")]
public async Task<SearchFullInfoTvShowViewModel> GetTvInfo(int tvdbid)
{
return await _tvEngineV2.GetShowInformation(tvdbid);
}
/// <summary>
/// Returns similar movies to the movie id passed in
/// </summary>

Loading…
Cancel
Save