mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-11 15:56:05 -07:00
Got tv working on the popout cards !wip
This commit is contained in:
parent
f3e781d576
commit
71ec151de1
20 changed files with 674 additions and 46 deletions
|
@ -1,6 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Api.TvMaze.Models;
|
using Ombi.Api.TvMaze.Models;
|
||||||
|
using Ombi.Api.TvMaze.Models.V2;
|
||||||
|
|
||||||
namespace Ombi.Api.TvMaze
|
namespace Ombi.Api.TvMaze
|
||||||
{
|
{
|
||||||
|
@ -11,5 +12,6 @@ namespace Ombi.Api.TvMaze
|
||||||
Task<List<TvMazeSearch>> Search(string searchTerm);
|
Task<List<TvMazeSearch>> Search(string searchTerm);
|
||||||
Task<TvMazeShow> ShowLookup(int showId);
|
Task<TvMazeShow> ShowLookup(int showId);
|
||||||
Task<TvMazeShow> ShowLookupByTheTvDbId(int theTvDbId);
|
Task<TvMazeShow> ShowLookupByTheTvDbId(int theTvDbId);
|
||||||
|
Task<FullSearch> GetTvFullInformation(int id);
|
||||||
}
|
}
|
||||||
}
|
}
|
144
src/Ombi.Api.TvMaze/Models/V2/FullSearch.cs
Normal file
144
src/Ombi.Api.TvMaze/Models/V2/FullSearch.cs
Normal file
|
@ -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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Api.TvMaze.Models;
|
using Ombi.Api.TvMaze.Models;
|
||||||
|
using Ombi.Api.TvMaze.Models.V2;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
|
|
||||||
namespace Ombi.Api.TvMaze
|
namespace Ombi.Api.TvMaze
|
||||||
|
@ -15,7 +15,6 @@ namespace Ombi.Api.TvMaze
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
//Mapper = mapper;
|
|
||||||
}
|
}
|
||||||
private string Uri = "http://api.tvmaze.com";
|
private string Uri = "http://api.tvmaze.com";
|
||||||
private IApi Api { get; }
|
private IApi Api { get; }
|
||||||
|
@ -75,5 +74,17 @@ namespace Ombi.Api.TvMaze
|
||||||
return await Api.Request<List<TvMazeSeasons>>(request);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs
Normal file
10
src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs
Normal file
|
@ -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.Settings.Settings.Models;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Core.Models.Search.V2;
|
using Ombi.Core.Models.Search.V2;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine.V2
|
||||||
{
|
{
|
||||||
public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2
|
public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2
|
||||||
{
|
{
|
||||||
|
|
129
src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs
Normal file
129
src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
113
src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs
Normal file
113
src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs
Normal file
|
@ -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.Schedule.Jobs.Sonarr;
|
||||||
using Ombi.Store.Repository.Requests;
|
using Ombi.Store.Repository.Requests;
|
||||||
using Ombi.Updater;
|
using Ombi.Updater;
|
||||||
using PlexContentCacher = Ombi.Schedule.Jobs.Plex;
|
|
||||||
using Ombi.Api.Telegram;
|
using Ombi.Api.Telegram;
|
||||||
using Ombi.Core.Authentication;
|
using Ombi.Core.Authentication;
|
||||||
using Ombi.Core.Engine.V2;
|
using Ombi.Core.Engine.V2;
|
||||||
|
@ -59,7 +58,6 @@ using Ombi.Schedule.Jobs.Lidarr;
|
||||||
using Ombi.Schedule.Jobs.Plex.Interfaces;
|
using Ombi.Schedule.Jobs.Plex.Interfaces;
|
||||||
using Ombi.Schedule.Jobs.SickRage;
|
using Ombi.Schedule.Jobs.SickRage;
|
||||||
using Ombi.Schedule.Processor;
|
using Ombi.Schedule.Processor;
|
||||||
using Ombi.Store.Entities;
|
|
||||||
|
|
||||||
namespace Ombi.DependencyInjection
|
namespace Ombi.DependencyInjection
|
||||||
{
|
{
|
||||||
|
@ -100,6 +98,7 @@ namespace Ombi.DependencyInjection
|
||||||
{
|
{
|
||||||
services.AddTransient<IMultiSearchEngine, MultiSearchEngine>();
|
services.AddTransient<IMultiSearchEngine, MultiSearchEngine>();
|
||||||
services.AddTransient<IMovieEngineV2, MovieSearchEngineV2>();
|
services.AddTransient<IMovieEngineV2, MovieSearchEngineV2>();
|
||||||
|
services.AddTransient<ITVSearchEngineV2, TvSearchEngineV2>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterHttp(this IServiceCollection services)
|
public static void RegisterHttp(this IServiceCollection services)
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using AutoMapper;
|
|
||||||
using AutoMapper.Configuration;
|
using AutoMapper.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
@ -12,9 +11,9 @@ namespace Ombi.Mapping
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddOmbiMappingProfile(this IServiceCollection services)
|
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>();
|
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)))
|
if (ti.ImplementedInterfaces.Contains(typeof(IProfileConfiguration)))
|
||||||
{
|
{
|
||||||
|
|
82
src/Ombi.Mapping/Profiles/TvProfileV2.cs
Normal file
82
src/Ombi.Mapping/Profiles/TvProfileV2.cs
Normal file
|
@ -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() {
|
export function baseurlFact() {
|
||||||
|
|
||||||
console.log(window['_app_base']);
|
|
||||||
return "/" + 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="row">
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<img id="cardImage" src="{{data.posterPath}}" class="poster" alt="{{data.title}}">
|
<img id="cardImage" src="{{data.posterPath}}" class="poster" alt="{{data.title}}">
|
||||||
|
@ -19,9 +22,12 @@
|
||||||
[translate]="'Common.NotAvailable'"></span></ng-template></small>
|
[translate]="'Common.NotAvailable'"></span></ng-template></small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<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>
|
||||||
<div class="col-6">
|
<div class="col-6" *ngIf="!data.available">
|
||||||
<strong>Request Status: </strong> <small>
|
<strong>Request Status: </strong> <small>
|
||||||
<ng-template [ngIf]="data.approved && !data.available"><span class="label label-info"
|
<ng-template [ngIf]="data.approved && !data.available"><span class="label label-info"
|
||||||
id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span></ng-template>
|
id="processingRequestLabel" [translate]="'Common.ProcessingRequest'"></span></ng-template>
|
||||||
|
@ -32,13 +38,22 @@
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<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>
|
||||||
<div class="col-6">
|
<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>
|
||||||
<div class="col-6">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ import { Component, Inject, OnInit } from "@angular/core";
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material";
|
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material";
|
||||||
import { IDiscoverCardResult } from "../interfaces";
|
import { IDiscoverCardResult } from "../interfaces";
|
||||||
import { SearchV2Service } from "../../services";
|
import { SearchV2Service } from "../../services";
|
||||||
import { dataURLToBlob } from "blob-util";
|
|
||||||
import { RequestType } from "../../interfaces";
|
import { RequestType } from "../../interfaces";
|
||||||
import { ISearchMovieResultV2 } from "../../interfaces/ISearchMovieResultV2";
|
import { ISearchMovieResultV2 } from "../../interfaces/ISearchMovieResultV2";
|
||||||
|
import { ISearchTvResultV2 } from "../../interfaces/ISearchTvResultV2";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "discover-card-details",
|
selector: "discover-card-details",
|
||||||
|
@ -13,16 +13,33 @@ import { ISearchMovieResultV2 } from "../../interfaces/ISearchMovieResultV2";
|
||||||
})
|
})
|
||||||
export class DiscoverCardDetailsComponent implements OnInit {
|
export class DiscoverCardDetailsComponent implements OnInit {
|
||||||
|
|
||||||
public result: ISearchMovieResultV2;
|
public movie: ISearchMovieResultV2;
|
||||||
|
public tv: ISearchTvResultV2;
|
||||||
|
public tvCreator: string;
|
||||||
|
public tvProducer: string;
|
||||||
|
public loading: boolean;;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public dialogRef: MatDialogRef<DiscoverCardDetailsComponent>,
|
public dialogRef: MatDialogRef<DiscoverCardDetailsComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: IDiscoverCardResult, private searchService: SearchV2Service) { }
|
@Inject(MAT_DIALOG_DATA) public data: IDiscoverCardResult, private searchService: SearchV2Service) { }
|
||||||
|
|
||||||
public async ngOnInit() {
|
public async ngOnInit() {
|
||||||
|
this.loading = true;
|
||||||
if (this.data.type === RequestType.movie) {
|
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 {
|
public onNoClick(): void {
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
<div class="row justify-content-md-center top-spacing">
|
<div class="row justify-content-md-center top-spacing">
|
||||||
<div class="btn-group" role="group" aria-label="Basic example">
|
<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)="popular()" [ngClass]="popularActive ? 'active-button' : ''" 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)="trending()" [ngClass]="trendingActive ? 'active-button' : ''" 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)="upcoming()" [ngClass]="upcomingActive ? 'active-button' : ''" mat-raised-button class="btn" color="primary">Upcoming</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -15,21 +15,3 @@
|
||||||
</div>
|
</div>
|
||||||
</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 defaultTvPoster: string;
|
||||||
|
|
||||||
|
public popularActive: boolean = true;
|
||||||
|
public trendingActive: boolean;
|
||||||
|
public upcomingActive: boolean;
|
||||||
|
|
||||||
constructor(private searchService: SearchV2Service) {
|
constructor(private searchService: SearchV2Service) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,6 +40,9 @@ export class DiscoverComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async popular() {
|
public async popular() {
|
||||||
|
this.popularActive = true;
|
||||||
|
this.trendingActive = false;
|
||||||
|
this.upcomingActive = false;
|
||||||
this.movies = await this.searchService.popularMovies().toPromise();
|
this.movies = await this.searchService.popularMovies().toPromise();
|
||||||
this.tvShows = await this.searchService.popularTv().toPromise();
|
this.tvShows = await this.searchService.popularTv().toPromise();
|
||||||
|
|
||||||
|
@ -43,6 +50,9 @@ export class DiscoverComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async trending() {
|
public async trending() {
|
||||||
|
this.popularActive = false;
|
||||||
|
this.trendingActive = true;
|
||||||
|
this.upcomingActive = false;
|
||||||
this.movies = await this.searchService.nowPlayingMovies().toPromise();
|
this.movies = await this.searchService.nowPlayingMovies().toPromise();
|
||||||
this.tvShows = await this.searchService.trendingTv().toPromise();
|
this.tvShows = await this.searchService.trendingTv().toPromise();
|
||||||
|
|
||||||
|
@ -50,6 +60,9 @@ export class DiscoverComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async upcoming() {
|
public async upcoming() {
|
||||||
|
this.popularActive = false;
|
||||||
|
this.trendingActive = false;
|
||||||
|
this.upcomingActive = true;
|
||||||
this.movies = await this.searchService.upcomingMovies().toPromise();
|
this.movies = await this.searchService.upcomingMovies().toPromise();
|
||||||
this.tvShows = await this.searchService.anticipatedTv().toPromise();
|
this.tvShows = await this.searchService.anticipatedTv().toPromise();
|
||||||
|
|
||||||
|
|
86
src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts
Normal file
86
src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts
Normal file
|
@ -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 { ISearchMovieResultV2 } from "../interfaces/ISearchMovieResultV2";
|
||||||
import { promise } from "selenium-webdriver";
|
import { promise } from "selenium-webdriver";
|
||||||
|
import { ISearchTvResultV2 } from "../interfaces/ISearchTvResultV2";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SearchV2Service extends ServiceHelpers {
|
export class SearchV2Service extends ServiceHelpers {
|
||||||
|
@ -55,7 +56,12 @@ export class SearchV2Service extends ServiceHelpers {
|
||||||
public anticipatedTv(): Observable<ISearchTvResult[]> {
|
public anticipatedTv(): Observable<ISearchTvResult[]> {
|
||||||
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/anticipated`, { headers: this.headers });
|
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/anticipated`, { headers: this.headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
public trendingTv(): Observable<ISearchTvResult[]> {
|
public trendingTv(): Observable<ISearchTvResult[]> {
|
||||||
return this.http.get<ISearchTvResult[]>(`${this.url}/Tv/trending`, { headers: this.headers });
|
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 {
|
import {
|
||||||
MatButtonModule, MatNativeDateModule, MatIconModule, MatSidenavModule, MatListModule, MatToolbarModule, MatTooltipModule} from '@angular/material';
|
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({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -25,6 +25,7 @@ import {
|
||||||
TruncateModule,
|
TruncateModule,
|
||||||
MomentModule,
|
MomentModule,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
MatAutocompleteModule,
|
MatAutocompleteModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
|
@ -43,6 +44,7 @@ import {
|
||||||
CommonModule,
|
CommonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
SidebarModule,
|
SidebarModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
IssuesReportComponent,
|
IssuesReportComponent,
|
||||||
TruncateModule,
|
TruncateModule,
|
||||||
InputSwitchModule,
|
InputSwitchModule,
|
||||||
|
|
|
@ -24,4 +24,14 @@
|
||||||
|
|
||||||
.btn-orange {
|
.btn-orange {
|
||||||
background-color: #F57C00;
|
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 class SearchController : ControllerBase
|
||||||
{
|
{
|
||||||
public SearchController(IMultiSearchEngine multiSearchEngine, IMovieEngine movieEngine,
|
public SearchController(IMultiSearchEngine multiSearchEngine, IMovieEngine movieEngine,
|
||||||
ITvSearchEngine tvSearchEngine, IMovieEngineV2 v2Movie)
|
ITvSearchEngine tvSearchEngine, IMovieEngineV2 v2Movie, ITVSearchEngineV2 v2Tv)
|
||||||
{
|
{
|
||||||
_multiSearchEngine = multiSearchEngine;
|
_multiSearchEngine = multiSearchEngine;
|
||||||
_movieEngine = movieEngine;
|
_movieEngine = movieEngine;
|
||||||
|
@ -27,11 +27,13 @@ namespace Ombi.Controllers.V2
|
||||||
_tvSearchEngine = tvSearchEngine;
|
_tvSearchEngine = tvSearchEngine;
|
||||||
_tvSearchEngine.ResultLimit = 12;
|
_tvSearchEngine.ResultLimit = 12;
|
||||||
_movieEngineV2 = v2Movie;
|
_movieEngineV2 = v2Movie;
|
||||||
|
_tvEngineV2 = v2Tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IMultiSearchEngine _multiSearchEngine;
|
private readonly IMultiSearchEngine _multiSearchEngine;
|
||||||
private readonly IMovieEngine _movieEngine;
|
private readonly IMovieEngine _movieEngine;
|
||||||
private readonly IMovieEngineV2 _movieEngineV2;
|
private readonly IMovieEngineV2 _movieEngineV2;
|
||||||
|
private readonly ITVSearchEngineV2 _tvEngineV2;
|
||||||
private readonly ITvSearchEngine _tvSearchEngine;
|
private readonly ITvSearchEngine _tvSearchEngine;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -54,6 +56,17 @@ namespace Ombi.Controllers.V2
|
||||||
return await _movieEngineV2.GetFullMovieInformation(movieDbId);
|
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>
|
/// <summary>
|
||||||
/// Returns similar movies to the movie id passed in
|
/// Returns similar movies to the movie id passed in
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue