mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-14 01:02:57 -07:00
Got the TV Page working nicely, requests are up next!
This commit is contained in:
parent
db4123b4ea
commit
be50b1eff1
37 changed files with 2924 additions and 195 deletions
|
@ -1,5 +1,6 @@
|
|||
using Ombi.Core.Models.Search;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.Core.Engine.Interfaces
|
||||
|
@ -7,7 +8,7 @@ namespace Ombi.Core.Engine.Interfaces
|
|||
public interface ITvSearchEngine
|
||||
{
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Search(string searchTerm);
|
||||
Task<SearchTvShowViewModel> GetShowInformation(int tvdbid);
|
||||
Task<SearchTvShowViewModel> GetShowInformation(string movieDbId, CancellationToken token);
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Popular();
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Popular(int currentlyLoaded, int amountToLoad, bool includeImages = false);
|
||||
Task<IEnumerable<SearchTvShowViewModel>> Anticipated();
|
||||
|
|
|
@ -7,8 +7,8 @@ namespace Ombi.Core
|
|||
{
|
||||
public interface ITVSearchEngineV2
|
||||
{
|
||||
Task<SearchFullInfoTvShowViewModel> GetShowInformation(int tvdbid);
|
||||
Task<SearchFullInfoTvShowViewModel> GetShowByRequest(int requestId);
|
||||
Task<IEnumerable<StreamingData>> GetStreamInformation(int tvDbId, int tvMazeId, CancellationToken cancellationToken);
|
||||
Task<SearchFullInfoTvShowViewModel> GetShowInformation(string tvdbid, CancellationToken token);
|
||||
Task<SearchFullInfoTvShowViewModel> GetShowByRequest(int requestId, CancellationToken token);
|
||||
Task<IEnumerable<StreamingData>> GetStreamInformation(int movieDbId, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ using Ombi.Core.Engine.Interfaces;
|
|||
using Ombi.Core.Models.Requests;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Store.Repository;
|
||||
|
||||
using System;
|
||||
|
@ -16,14 +15,13 @@ using System.Security.Principal;
|
|||
using System.Threading.Tasks;
|
||||
using Ombi.Core.Rule.Interfaces;
|
||||
using Ombi.Store.Repository.Requests;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Ombi.Core.Authentication;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Settings.Settings.Models;
|
||||
using Ombi.Store.Entities;
|
||||
using TraktSharp.Entities;
|
||||
using Ombi.Api.TheMovieDb;
|
||||
using Ombi.Api.TheMovieDb.Models;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ombi.Core.Engine
|
||||
{
|
||||
|
@ -76,7 +74,7 @@ namespace Ombi.Core.Engine
|
|||
return null;
|
||||
}
|
||||
|
||||
public async Task<SearchTvShowViewModel> GetShowInformation(string theMovieDbId)
|
||||
public async Task<SearchTvShowViewModel> GetShowInformation(string theMovieDbId, CancellationToken token)
|
||||
{
|
||||
var show = await Cache.GetOrAdd(nameof(GetShowInformation) + theMovieDbId,
|
||||
async () => await _theMovieDbApi.GetTVInfo(theMovieDbId), DateTime.Now.AddHours(12));
|
||||
|
@ -96,22 +94,26 @@ namespace Ombi.Core.Engine
|
|||
|
||||
var mapped = Mapper.Map<SearchTvShowViewModel>(show);
|
||||
|
||||
foreach (var e in show.seasons)
|
||||
foreach(var tvSeason in show.seasons)
|
||||
{
|
||||
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season_number);
|
||||
var seasonEpisodes = (await _theMovieDbApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token));
|
||||
|
||||
foreach (var episode in seasonEpisodes.episodes)
|
||||
{
|
||||
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == episode.season_number);
|
||||
if (season == null)
|
||||
{
|
||||
var newSeason = new SeasonRequests
|
||||
{
|
||||
SeasonNumber = e.season_number,
|
||||
SeasonNumber = episode.season_number,
|
||||
Episodes = new List<EpisodeRequests>()
|
||||
};
|
||||
newSeason.Episodes.Add(new EpisodeRequests
|
||||
{
|
||||
//Url = e..ToHttpsUrl(),
|
||||
Title = e.name,
|
||||
AirDate = e.air_date.HasValue() ? DateTime.Parse(e.air_date) : DateTime.MinValue,
|
||||
EpisodeNumber = e,
|
||||
//Url = episode...ToHttpsUrl(),
|
||||
Title = episode.name,
|
||||
AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue,
|
||||
EpisodeNumber = episode.episode_number,
|
||||
|
||||
});
|
||||
mapped.SeasonRequests.Add(newSeason);
|
||||
|
@ -121,13 +123,15 @@ namespace Ombi.Core.Engine
|
|||
// We already have the season, so just add the episode
|
||||
season.Episodes.Add(new EpisodeRequests
|
||||
{
|
||||
Url = e.url.ToHttpsUrl(),
|
||||
Title = e.name,
|
||||
AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue,
|
||||
EpisodeNumber = e.number,
|
||||
//Url = e.url.ToHttpsUrl(),
|
||||
Title = episode.name,
|
||||
AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue,
|
||||
EpisodeNumber = episode.episode_number,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await ProcessResult(mapped, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,54 +43,46 @@ namespace Ombi.Core.Engine.V2
|
|||
}
|
||||
|
||||
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetShowByRequest(int requestId)
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetShowByRequest(int requestId, CancellationToken token)
|
||||
{
|
||||
var request = await RequestService.TvRequestService.Get().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||
return await GetShowInformation(request.TvDbId);
|
||||
return await GetShowInformation(request.TvDbId.ToString(), token); // TODO
|
||||
}
|
||||
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetShowInformation(int tvdbid)
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetShowInformation(string tvdbid, CancellationToken token)
|
||||
{
|
||||
var tvdbshow = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid,
|
||||
async () => await _tvMaze.ShowLookupByTheTvDbId(tvdbid), DateTime.Now.AddHours(12));
|
||||
if (tvdbshow == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var show = await Cache.GetOrAdd("GetTvFullInformation" + tvdbshow.id,
|
||||
async () => await _tvMaze.GetTvFullInformation(tvdbshow.id), DateTime.Now.AddHours(12));
|
||||
var show = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid,
|
||||
async () => await _movieApi.GetTVInfo(tvdbid), DateTime.Now.AddHours(12));
|
||||
if (show == null)
|
||||
{
|
||||
// We don't have enough information
|
||||
return null;
|
||||
}
|
||||
|
||||
// Setup the task so we can get the data later on if we have a IMDBID
|
||||
Task<TraktShow> traktInfoTask = null;
|
||||
if (show.externals?.imdb.HasValue() ?? false)
|
||||
{
|
||||
traktInfoTask = Cache.GetOrAdd("GetExtendedTvInfoTrakt" + show.externals?.imdb,
|
||||
() => _traktApi.GetTvExtendedInfo(show.externals?.imdb), DateTime.Now.AddHours(12));
|
||||
}
|
||||
|
||||
var mapped = _mapper.Map<SearchFullInfoTvShowViewModel>(show);
|
||||
|
||||
foreach (var e in show._embedded?.episodes ?? new Api.TvMaze.Models.V2.Episode[0])
|
||||
|
||||
foreach (var tvSeason in show.seasons.Where(x => x.season_number != 0)) // skip the first season
|
||||
{
|
||||
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season);
|
||||
var seasonEpisodes = (await _movieApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token));
|
||||
|
||||
foreach (var episode in seasonEpisodes.episodes)
|
||||
{
|
||||
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == episode.season_number);
|
||||
if (season == null)
|
||||
{
|
||||
var newSeason = new SeasonRequests
|
||||
{
|
||||
SeasonNumber = e.season,
|
||||
SeasonNumber = episode.season_number,
|
||||
Overview = tvSeason.overview,
|
||||
Episodes = new List<EpisodeRequests>()
|
||||
};
|
||||
newSeason.Episodes.Add(new EpisodeRequests
|
||||
{
|
||||
Url = e.url.ToHttpsUrl(),
|
||||
Title = e.name,
|
||||
AirDate = e.airstamp,
|
||||
EpisodeNumber = e.number,
|
||||
//Url = episode...ToHttpsUrl(),
|
||||
Title = episode.name,
|
||||
AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue,
|
||||
EpisodeNumber = episode.episode_number,
|
||||
|
||||
});
|
||||
mapped.SeasonRequests.Add(newSeason);
|
||||
|
@ -100,32 +92,21 @@ namespace Ombi.Core.Engine.V2
|
|||
// We already have the season, so just add the episode
|
||||
season.Episodes.Add(new EpisodeRequests
|
||||
{
|
||||
Url = e.url.ToHttpsUrl(),
|
||||
Title = e.name,
|
||||
AirDate = e.airstamp,
|
||||
EpisodeNumber = e.number,
|
||||
//Url = e.url.ToHttpsUrl(),
|
||||
Title = episode.name,
|
||||
AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue,
|
||||
EpisodeNumber = episode.episode_number,
|
||||
});
|
||||
}
|
||||
}
|
||||
return await ProcessResult(mapped, traktInfoTask);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<StreamingData>> GetStreamInformation(int tvDbId, int tvMazeId, CancellationToken cancellationToken)
|
||||
{
|
||||
var tvdbshow = await Cache.GetOrAdd(nameof(GetShowInformation) + tvMazeId,
|
||||
async () => await _tvMaze.ShowLookupByTheTvDbId(tvMazeId), DateTime.Now.AddHours(12));
|
||||
if (tvdbshow == null)
|
||||
{
|
||||
return null;
|
||||
return await ProcessResult(mapped);
|
||||
}
|
||||
|
||||
/// this is a best effort guess since TV maze do not provide the TheMovieDbId
|
||||
var movieDbResults = await _movieApi.SearchTv(tvdbshow.name, tvdbshow.premiered.Substring(0, 4));
|
||||
var potential = movieDbResults.FirstOrDefault();
|
||||
tvDbId = potential.Id;
|
||||
// end guess
|
||||
|
||||
var providers = await _movieApi.GetTvWatchProviders(tvDbId, cancellationToken);
|
||||
public async Task<IEnumerable<StreamingData>> GetStreamInformation(int movieDbId, CancellationToken cancellationToken)
|
||||
{
|
||||
var providers = await _movieApi.GetTvWatchProviders(movieDbId, cancellationToken);
|
||||
var results = await GetUserWatchProvider(providers);
|
||||
|
||||
var data = new List<StreamingData>();
|
||||
|
@ -158,9 +139,9 @@ namespace Ombi.Core.Engine.V2
|
|||
return _mapper.Map<SearchTvShowViewModel>(tvMazeSearch);
|
||||
}
|
||||
|
||||
private async Task<SearchFullInfoTvShowViewModel> ProcessResult(SearchFullInfoTvShowViewModel item, Task<TraktShow> showInfoTask)
|
||||
private async Task<SearchFullInfoTvShowViewModel> ProcessResult(SearchFullInfoTvShowViewModel item)
|
||||
{
|
||||
item.TheTvDbId = item.Id.ToString();
|
||||
item.TheMovieDbId = item.Id.ToString();
|
||||
|
||||
var oldModel = _mapper.Map<SearchTvShowViewModel>(item);
|
||||
await RunSearchRules(oldModel);
|
||||
|
@ -179,18 +160,9 @@ namespace Ombi.Core.Engine.V2
|
|||
item.Images.Medium = item.Images.Medium.ToHttpsUrl();
|
||||
}
|
||||
|
||||
if (item.Cast?.Any() ?? false)
|
||||
{
|
||||
foreach (var cast in item.Cast)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(cast.Character?.Image?.Medium))
|
||||
{
|
||||
cast.Character.Image.Medium = cast.Character?.Image?.Medium.ToHttpsUrl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await GetExtraInfo(showInfoTask, item);
|
||||
return item;
|
||||
//return await GetExtraInfo(showInfoTask, item);
|
||||
}
|
||||
|
||||
private async Task<SearchFullInfoTvShowViewModel> GetExtraInfo(Task<TraktShow> showInfoTask, SearchFullInfoTvShowViewModel model)
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace Ombi.Core.Helpers
|
|||
public TvRequests NewRequest { get; protected set; }
|
||||
protected TvMazeShow ShowInfo { get; set; }
|
||||
protected List<TvSearchResult> Results { get; set; }
|
||||
protected TvSearchResult TheMovieDbRecord { get; set; }
|
||||
|
||||
public async Task<TvShowRequestBuilder> GetShowInfo(int id)
|
||||
{
|
||||
|
@ -43,6 +44,7 @@ namespace Ombi.Core.Helpers
|
|||
foreach (TvSearchResult result in Results) {
|
||||
if (result.Name.Equals(ShowInfo.name, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
TheMovieDbRecord = result;
|
||||
var showIds = await MovieDbApi.GetTvExternals(result.Id);
|
||||
ShowInfo.externals.imdb = showIds.imdb_id;
|
||||
BackdropPath = result.BackdropPath;
|
||||
|
@ -240,6 +242,7 @@ namespace Ombi.Core.Helpers
|
|||
PosterPath = PosterPath,
|
||||
Title = ShowInfo.name,
|
||||
ReleaseDate = FirstAir,
|
||||
ExternalProviderId = TheMovieDbRecord.Id,
|
||||
Status = ShowInfo.status,
|
||||
ImdbId = ShowInfo.externals?.imdb ?? string.Empty,
|
||||
TvDbId = tv.TvDbId,
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Ombi.Core.Models.Search.V2
|
|||
public string FirstAired { get; set; }
|
||||
public string NetworkId { get; set; }
|
||||
public string Runtime { get; set; }
|
||||
public List<string> Genre { get; set; }
|
||||
public GenreViewModel[] Genres { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public int LastUpdated { get; set; }
|
||||
public string AirsDayOfWeek { get; set; }
|
||||
|
@ -24,23 +24,12 @@ namespace Ombi.Core.Models.Search.V2
|
|||
public NetworkViewModel Network { get; set; }
|
||||
public Images Images { get; set; }
|
||||
public List<CastViewModel> Cast { get; set; }
|
||||
public List<CrewViewModel> Crew { get; set; }
|
||||
public List<PersonViewModel> Crew { get; set; }
|
||||
public string Certification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is used from the Trakt API
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The trailer.
|
||||
/// </value>
|
||||
public string Tagline { get; set; }
|
||||
public Keywords Keywords { get; set; }
|
||||
public ExternalIds ExternalIds { get; set; }
|
||||
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>();
|
||||
|
@ -66,7 +55,7 @@ namespace Ombi.Core.Models.Search.V2
|
|||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public Country Country { get; set; }
|
||||
public string Country { get; set; }
|
||||
}
|
||||
|
||||
public class Country
|
||||
|
@ -84,8 +73,9 @@ namespace Ombi.Core.Models.Search.V2
|
|||
|
||||
public class CastViewModel
|
||||
{
|
||||
public PersonViewModel Person { get; set; }
|
||||
public CharacterViewModel Character { get; set; }
|
||||
public string Person { get; set; }
|
||||
public string Character { get; set; }
|
||||
public string Image { get; set; }
|
||||
public bool Self { get; set; }
|
||||
public bool Voice { get; set; }
|
||||
}
|
||||
|
@ -95,7 +85,7 @@ namespace Ombi.Core.Models.Search.V2
|
|||
public int Id { get; set; }
|
||||
public string Url { get; set; }
|
||||
public string Name { get; set; }
|
||||
public Images Image { get; set; }
|
||||
public string Image { get; set; }
|
||||
}
|
||||
|
||||
public class CharacterViewModel
|
||||
|
@ -106,9 +96,4 @@ namespace Ombi.Core.Models.Search.V2
|
|||
public Images Image { get; set; }
|
||||
}
|
||||
|
||||
public class CrewViewModel
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public PersonViewModel Person { get; set; }
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ namespace Ombi.Core.Rule.Rules
|
|||
{
|
||||
var vm = (SearchTvShowViewModel) obj;
|
||||
// Check if it's in Radarr
|
||||
var result = await _ctx.SonarrCache.FirstOrDefaultAsync(x => x.TvDbId == vm.Id);
|
||||
var result = await _ctx.SonarrCache.FirstOrDefaultAsync(x => x.TvDbId.ToString() == vm.TheTvDbId);
|
||||
if (result != null)
|
||||
{
|
||||
vm.Approved = true;
|
||||
|
@ -69,7 +69,7 @@ namespace Ombi.Core.Rule.Rules
|
|||
// Check if we have it
|
||||
var monitoredInSonarr = await sonarrEpisodes.FirstOrDefaultAsync(x =>
|
||||
x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == season.SeasonNumber
|
||||
&& x.TvDbId == vm.Id);
|
||||
&& x.TvDbId.ToString() == vm.TheTvDbId);
|
||||
if (monitoredInSonarr != null)
|
||||
{
|
||||
ep.Approved = true;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System.Globalization;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using Ombi.Api.TheMovieDb.Models;
|
||||
using Ombi.Api.TvMaze.Models.V2;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Core.Models.Search.V2;
|
||||
|
@ -24,7 +27,7 @@ namespace Ombi.Mapping.Profiles
|
|||
.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.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,
|
||||
|
@ -34,9 +37,55 @@ namespace Ombi.Mapping.Profiles
|
|||
: string.Empty))
|
||||
.ForMember(dest => dest.Status, opts => opts.MapFrom(src => src.status));
|
||||
|
||||
CreateMap<Network, NetworkViewModel>()
|
||||
|
||||
|
||||
CreateMap<TvInfo, SearchFullInfoTvShowViewModel>()
|
||||
.ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id))
|
||||
.ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.first_air_date))
|
||||
.ForMember(dest => dest.ImdbId, opts => opts.MapFrom(src => src.ExternalIds.ImdbId))
|
||||
.ForMember(dest => dest.TheTvDbId, opts => opts.MapFrom(src => src.ExternalIds.TvDbId))
|
||||
.ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.networks.FirstOrDefault()))
|
||||
.ForMember(dest => dest.NetworkId, opts => opts.MapFrom(src => src.networks.FirstOrDefault().id))
|
||||
.ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.overview))
|
||||
.ForMember(dest => dest.Rating,
|
||||
opts => opts.MapFrom(src => src.vote_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.Images))
|
||||
.ForMember(dest => dest.Cast, opts => opts.MapFrom(src => src.Credits.cast))
|
||||
.ForMember(dest => dest.Crew, opts => opts.MapFrom(src => src.Credits.crew))
|
||||
.ForMember(dest => dest.Banner, opts => opts.MapFrom(src => GetBanner(src.Images)))
|
||||
.ForMember(dest => dest.Genres, opts => opts.MapFrom(src => src.genres))
|
||||
.ForMember(dest => dest.Keywords, opts => opts.MapFrom(src => src.Keywords))
|
||||
.ForMember(dest => dest.Tagline, opts => opts.MapFrom(src => src.tagline))
|
||||
.ForMember(dest => dest.ExternalIds, opts => opts.MapFrom(src => src.ExternalIds))
|
||||
.ForMember(dest => dest.Trailer, opts => opts.MapFrom(src => GetTrailer(src.Videos)))
|
||||
.ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.episode_run_time.FirstOrDefault()))
|
||||
.ForMember(dest => dest.Status, opts => opts.MapFrom(src => src.status));
|
||||
|
||||
CreateMap<Ombi.Api.TheMovieDb.Models.ExternalIds, Ombi.Core.Models.Search.V2.ExternalIds>().ReverseMap();
|
||||
CreateMap<Ombi.Api.TheMovieDb.Models.Images, Ombi.Core.Models.Search.V2.Images>()
|
||||
.ForMember(dest => dest.Original, opts => opts.MapFrom(src => src.Posters.OrderBy(x => x.VoteCount).ThenBy(x => x.VoteAverage).FirstOrDefault().FilePath));
|
||||
|
||||
|
||||
CreateMap<Api.TheMovieDb.Models.Keywords, Ombi.Core.Models.Search.V2.Keywords>().ReverseMap();
|
||||
CreateMap<Ombi.Api.TheMovieDb.Models.KeywordsValue, Ombi.Core.Models.Search.V2.KeywordsValue>().ReverseMap();
|
||||
|
||||
|
||||
CreateMap<GenreViewModel, Genre>()
|
||||
.ForMember(dest => dest.id, opts => opts.MapFrom(src => src.id))
|
||||
.ForMember(dest => dest.name, opts => opts.MapFrom(src => src.name));
|
||||
|
||||
CreateMap<Api.TvMaze.Models.V2.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.TheMovieDb.Models.Network, NetworkViewModel>()
|
||||
.ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id))
|
||||
.ForMember(dest => dest.Country, opts => opts.MapFrom(src => src.origin_country))
|
||||
.ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name));
|
||||
|
||||
CreateMap<Api.TvMaze.Models.V2.Country, Core.Models.Search.V2.Country>()
|
||||
|
@ -44,9 +93,9 @@ namespace Ombi.Mapping.Profiles
|
|||
.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.ToHttpsUrl()))
|
||||
.ForMember(dest => dest.Original, opts => opts.MapFrom(src => src.original.ToHttpsUrl()));
|
||||
//CreateMap<Api.TvMaze.Models.V2.Image, Images>()
|
||||
// .ForMember(dest => dest.Medium, opts => opts.MapFrom(src => src.medium.ToHttpsUrl()))
|
||||
// .ForMember(dest => dest.Original, opts => opts.MapFrom(src => src.original.ToHttpsUrl()));
|
||||
|
||||
CreateMap<Api.TvMaze.Models.V2.Cast, CastViewModel>()
|
||||
.ForMember(dest => dest.Character, opts => opts.MapFrom(src => src.character))
|
||||
|
@ -54,15 +103,25 @@ namespace Ombi.Mapping.Profiles
|
|||
.ForMember(dest => dest.Voice, opts => opts.MapFrom(src => src.voice))
|
||||
.ForMember(dest => dest.Self, opts => opts.MapFrom(src => src.self));
|
||||
|
||||
CreateMap<FullMovieCast, CastViewModel>()
|
||||
.ForMember(dest => dest.Character, opts => opts.MapFrom(src => src.character))
|
||||
.ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.name))
|
||||
.ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.profile_path));
|
||||
|
||||
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.ToHttpsUrl()));
|
||||
|
||||
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.Crew, CrewViewModel>()
|
||||
// .ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person))
|
||||
// .ForMember(dest => dest.Type, opts => opts.MapFrom(src => src.type));
|
||||
|
||||
CreateMap<FullMovieCrew, PersonViewModel>()
|
||||
.ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id))
|
||||
.ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.profile_path))
|
||||
.ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name));
|
||||
|
||||
CreateMap<Api.TvMaze.Models.V2.Cast, CastViewModel>()
|
||||
.ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person))
|
||||
|
@ -78,5 +137,27 @@ namespace Ombi.Mapping.Profiles
|
|||
|
||||
CreateMap<SearchTvShowViewModel, SearchFullInfoTvShowViewModel>().ReverseMap();
|
||||
}
|
||||
|
||||
private string GetBanner(Api.TheMovieDb.Models.Images images)
|
||||
{
|
||||
var hasBackdrop = images?.Backdrops?.Any();
|
||||
if (hasBackdrop ?? false)
|
||||
{
|
||||
return images.Backdrops?.OrderBy(x => x.VoteCount).ThenBy(x => x.VoteAverage).Select(x => x.FilePath).FirstOrDefault();
|
||||
}
|
||||
else if (images != null)
|
||||
{
|
||||
return images.Posters?.OrderBy(x => x.VoteCount).ThenBy(x => x.VoteAverage).Select(x => x.FilePath).FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTrailer(Api.TheMovieDb.Models.Videos trailer)
|
||||
{
|
||||
return trailer?.results?.FirstOrDefault(x => x.type.Equals("trailer", StringComparison.InvariantCultureIgnoreCase))?.key ?? null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ namespace Ombi.Store.Repository.Requests
|
|||
public class SeasonRequests : Entity
|
||||
{
|
||||
public int SeasonNumber { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public List<EpisodeRequests> Episodes { get; set; } = new List<EpisodeRequests>();
|
||||
|
||||
public int ChildRequestId { get; set; }
|
||||
|
|
|
@ -6,8 +6,13 @@ namespace Ombi.Store.Entities.Requests
|
|||
{
|
||||
public class TvRequests : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// No longer used since moved away from TvMaze
|
||||
/// </summary>
|
||||
public int TvDbId { get; set; }
|
||||
//public int ExternalProviderId { get; set; }
|
||||
|
||||
// TheMovieDbId
|
||||
public int ExternalProviderId { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
public int? QualityOverride { get; set; }
|
||||
public int? RootFolder { get; set; }
|
||||
|
|
1232
src/Ombi.Store/Migrations/OmbiMySql/20210305151743_TvRequestProviderId.Designer.cs
generated
Normal file
1232
src/Ombi.Store/Migrations/OmbiMySql/20210305151743_TvRequestProviderId.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,52 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Ombi.Store.Migrations.OmbiMySql
|
||||
{
|
||||
public partial class TvRequestProviderId : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "ExternalProviderId",
|
||||
table: "TvRequests",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Overview",
|
||||
table: "SeasonRequests",
|
||||
type: "longtext",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "StreamingCountry",
|
||||
table: "AspNetUsers",
|
||||
type: "longtext",
|
||||
nullable: false,
|
||||
defaultValue: "",
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext",
|
||||
oldNullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ExternalProviderId",
|
||||
table: "TvRequests");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Overview",
|
||||
table: "SeasonRequests");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "StreamingCountry",
|
||||
table: "AspNetUsers",
|
||||
type: "longtext",
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldType: "longtext");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -308,6 +308,7 @@ namespace Ombi.Store.Migrations.OmbiMySql
|
|||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("StreamingCountry")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
|
@ -764,6 +765,9 @@ namespace Ombi.Store.Migrations.OmbiMySql
|
|||
b.Property<string>("Background")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("ExternalProviderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
|
@ -954,6 +958,9 @@ namespace Ombi.Store.Migrations.OmbiMySql
|
|||
b.Property<int>("ChildRequestId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Overview")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("int");
|
||||
|
||||
|
|
1231
src/Ombi.Store/Migrations/OmbiSqlite/20210305151854_TvRequestProviderId.Designer.cs
generated
Normal file
1231
src/Ombi.Store/Migrations/OmbiSqlite/20210305151854_TvRequestProviderId.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,34 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Ombi.Store.Migrations.OmbiSqlite
|
||||
{
|
||||
public partial class TvRequestProviderId : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "ExternalProviderId",
|
||||
table: "TvRequests",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Overview",
|
||||
table: "SeasonRequests",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ExternalProviderId",
|
||||
table: "TvRequests");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Overview",
|
||||
table: "SeasonRequests");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -764,6 +764,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite
|
|||
b.Property<string>("Background")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("ExternalProviderId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ImdbId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
@ -954,6 +957,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite
|
|||
b.Property<int>("ChildRequestId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Overview")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SeasonNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace Ombi.Api.TheMovieDb
|
|||
Task<List<MovieDbSearchResult>> SimilarMovies(int movieId, string langCode);
|
||||
Task<FindResult> Find(string externalId, ExternalSource source);
|
||||
Task<TvExternals> GetTvExternals(int theMovieDbId);
|
||||
Task<TvInfo> GetTVInfo(string themoviedbid);
|
||||
Task<SeasonDetails> GetSeasonEpisodes(int theMovieDbId, int seasonNumber, CancellationToken token, string langCode = "en");
|
||||
Task<TvInfo> GetTVInfo(string themoviedbid, string langCode = "en");
|
||||
Task<TheMovieDbContainer<ActorResult>> SearchByActor(string searchTerm, string langCode);
|
||||
Task<ActorCredits> GetActorMovieCredits(int actorId, string langCode);
|
||||
Task<TheMovieDbContainer<MultiSearch>> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken);
|
||||
|
|
|
@ -87,6 +87,10 @@ namespace Ombi.Api.TheMovieDb.Models
|
|||
{
|
||||
[JsonProperty("file_path")]
|
||||
public string FilePath { get; set; }
|
||||
[JsonProperty("vote_count")]
|
||||
public int VoteCount { get; set; }
|
||||
[JsonProperty("vote_average")]
|
||||
public double VoteAverage { get; set; }
|
||||
}
|
||||
|
||||
public class Keywords
|
||||
|
@ -128,6 +132,8 @@ namespace Ombi.Api.TheMovieDb.Models
|
|||
public string InstagramId { get; set; }
|
||||
[JsonProperty("twitter_id")]
|
||||
public string TwitterId { get; set; }
|
||||
[JsonProperty("tvdb_id")]
|
||||
public string TvDbId { get; set; }
|
||||
}
|
||||
|
||||
public class Credits
|
||||
|
|
54
src/Ombi.TheMovieDbApi/Models/SeasonDetails.cs
Normal file
54
src/Ombi.TheMovieDbApi/Models/SeasonDetails.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.Api.TheMovieDb.Models
|
||||
{
|
||||
public class SeasonDetails
|
||||
{
|
||||
public string _id { get; set; }
|
||||
public string air_date { get; set; }
|
||||
public Episode[] episodes { get; set; }
|
||||
public string name { get; set; }
|
||||
public string overview { get; set; }
|
||||
public int id { get; set; }
|
||||
public string poster_path { get; set; }
|
||||
public int season_number { get; set; }
|
||||
}
|
||||
|
||||
public class Episode
|
||||
{
|
||||
public string air_date { get; set; }
|
||||
public int episode_number { get; set; }
|
||||
public Crew[] crew { get; set; }
|
||||
public Guest_Stars[] guest_stars { get; set; }
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
public string overview { get; set; }
|
||||
public string production_code { get; set; }
|
||||
public int season_number { get; set; }
|
||||
public string still_path { get; set; }
|
||||
public float vote_average { get; set; }
|
||||
public int vote_count { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class Guest_Stars
|
||||
{
|
||||
public string character { get; set; }
|
||||
public string credit_id { get; set; }
|
||||
public int order { get; set; }
|
||||
public bool adult { get; set; }
|
||||
public int gender { get; set; }
|
||||
public int id { get; set; }
|
||||
public string known_for_department { get; set; }
|
||||
public string name { get; set; }
|
||||
public string original_name { get; set; }
|
||||
public float popularity { get; set; }
|
||||
public string profile_path { get; set; }
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@ namespace Ombi.Api.TheMovieDb.Models
|
|||
public Network[] networks { get; set; }
|
||||
public int number_of_episodes { get; set; }
|
||||
public int number_of_seasons { get; set; }
|
||||
public string tagline { get; set; }
|
||||
public string[] origin_country { get; set; }
|
||||
public string original_language { get; set; }
|
||||
public string original_name { get; set; }
|
||||
|
@ -30,7 +31,21 @@ namespace Ombi.Api.TheMovieDb.Models
|
|||
public string type { get; set; }
|
||||
public float vote_average { get; set; }
|
||||
public int vote_count { get; set; }
|
||||
[JsonProperty("external_ids")] public TvExternalIds TvExternalIds { 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("external_ids")]
|
||||
public ExternalIds ExternalIds { get; set; }
|
||||
[JsonProperty("keywords")]
|
||||
public Keywords Keywords { get; set; }
|
||||
[JsonProperty("images")]
|
||||
public Images Images { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class Created_By
|
||||
|
|
|
@ -302,16 +302,27 @@ namespace Ombi.Api.TheMovieDb
|
|||
return Mapper.Map<List<MovieDbSearchResult>>(result.results);
|
||||
}
|
||||
|
||||
public async Task<TvInfo> GetTVInfo(string themoviedbid)
|
||||
public async Task<TvInfo> GetTVInfo(string themoviedbid, string langCode = "en")
|
||||
{
|
||||
var request = new Request($"/tv/{themoviedbid}", BaseUri, HttpMethod.Get);
|
||||
request.AddQueryString("api_key", ApiToken);
|
||||
request.AddQueryString("append_to_response", "external_ids");
|
||||
request.AddQueryString("language", langCode);
|
||||
request.AddQueryString("append_to_response", "videos,credits,similar,recommendations,external_ids,keywords,images");
|
||||
AddRetry(request);
|
||||
|
||||
return await Api.Request<TvInfo>(request);
|
||||
}
|
||||
|
||||
public async Task<SeasonDetails> GetSeasonEpisodes(int theMovieDbId, int seasonNumber, CancellationToken token, string langCode = "en")
|
||||
{
|
||||
var request = new Request($"/tv/{theMovieDbId}/season/{seasonNumber}", BaseUri, HttpMethod.Get);
|
||||
request.AddQueryString("api_key", ApiToken);
|
||||
request.AddQueryString("language", langCode);
|
||||
AddRetry(request);
|
||||
|
||||
return await Api.Request<SeasonDetails>(request, token);
|
||||
}
|
||||
|
||||
public async Task<List<Keyword>> SearchKeyword(string searchTerm)
|
||||
{
|
||||
var request = new Request("search/keyword", BaseUri, HttpMethod.Get);
|
||||
|
|
|
@ -100,6 +100,7 @@ export interface IBaseRequest {
|
|||
export interface ITvRequests {
|
||||
id: number;
|
||||
imdbId: string;
|
||||
externalProviderId: number;
|
||||
rootFolder: number;
|
||||
overview: string;
|
||||
title: string;
|
||||
|
@ -111,7 +112,8 @@ export interface ITvRequests {
|
|||
qualityOverride: number;
|
||||
background: any;
|
||||
totalSeasons: number;
|
||||
tvDbId: number;
|
||||
tvDbId: number; // NO LONGER USED
|
||||
|
||||
open: boolean; // THIS IS FOR THE UI
|
||||
|
||||
// For UI display
|
||||
|
@ -146,6 +148,7 @@ export enum OrderType {
|
|||
|
||||
export interface INewSeasonRequests {
|
||||
id: number;
|
||||
overview: string;
|
||||
seasonNumber: number;
|
||||
episodes: IEpisodesRequests[];
|
||||
seasonAvailable: boolean;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { INewSeasonRequests, RequestType } from "./IRequestModel";
|
||||
import { IExternalIds, IGenresViewModel, IKeywords } from "./ISearchMovieResultV2";
|
||||
|
||||
export interface ISearchTvResultV2 {
|
||||
id: number;
|
||||
|
@ -11,7 +12,7 @@ export interface ISearchTvResultV2 {
|
|||
firstAired: string;
|
||||
networkId: string;
|
||||
runtime: string;
|
||||
genre: string[];
|
||||
genres: IGenresViewModel[],
|
||||
overview: string;
|
||||
lastUpdated: number;
|
||||
airsDayOfWeek: string;
|
||||
|
@ -21,7 +22,6 @@ export interface ISearchTvResultV2 {
|
|||
siteRating: number;
|
||||
trailer: string;
|
||||
homepage: string;
|
||||
certification: string;
|
||||
seasonRequests: INewSeasonRequests[];
|
||||
requestAll: boolean;
|
||||
approved: boolean;
|
||||
|
@ -30,6 +30,7 @@ export interface ISearchTvResultV2 {
|
|||
plexUrl: string;
|
||||
embyUrl: string;
|
||||
jellyfinUrl: string;
|
||||
tagline: string;
|
||||
quality: string;
|
||||
firstSeason: boolean;
|
||||
latestSeason: boolean;
|
||||
|
@ -38,8 +39,10 @@ export interface ISearchTvResultV2 {
|
|||
showSubscribe: boolean;
|
||||
fullyAvailable: boolean;
|
||||
partlyAvailable: boolean;
|
||||
externalIds: IExternalIds;
|
||||
network: INetwork;
|
||||
images: IImagesV2;
|
||||
keywords: IKeywords;
|
||||
cast: ICast[];
|
||||
crew: ICrew[];
|
||||
requestId: number;
|
||||
|
|
|
@ -8,19 +8,18 @@
|
|||
<a *ngIf="item.profile_path" [routerLink]="'/discover/actor/' + item.id">
|
||||
<img class="cast-profile-img" src="https://image.tmdb.org/t/p/w300/{{item.profile_path}}">
|
||||
</a>
|
||||
<a *ngIf="item.character?.image?.medium" [routerLink]="'/discover/actor/' + item.person.id">
|
||||
<img class="cast-profile-img" [src]="item.character.image.medium">
|
||||
<a *ngIf="item.image" [routerLink]="'/discover/actor/' + item.person.id">
|
||||
<img class="cast-profile-img" src="https://image.tmdb.org/t/p/w300/{{item.image}}">
|
||||
</a>
|
||||
<!-- TODO get profile image default -->
|
||||
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<span *ngIf="item.name"><strong>{{item.name}}</strong></span>
|
||||
<span *ngIf="item.person?.name"><strong>{{item.person.name}}</strong></span>
|
||||
<span *ngIf="item.person"><strong>{{item.person}}</strong></span>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<span *ngIf="!item.character?.name"><small>{{item.character}}</small></span>
|
||||
<span *ngIf="item.character.name"><small>{{item.character.name}}</small></span>
|
||||
<span *ngIf="item.character"><small>{{item.character}}</small></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<a *ngIf="homepage" class="media-icons" href="{{homepage}}" target="_blank">
|
||||
<i matTooltip="Homepage" class="sfa-home fa-2x grow-social"></i>
|
||||
</a>
|
||||
<a *ngIf="theMoviedbId" href="https://www.themoviedb.org/movie/{{theMoviedbId}}" class="media-icons"
|
||||
<a *ngIf="theMoviedbId" href="https://www.themoviedb.org/{{type === RequestType.movie ? 'movie' : 'tv'}}/{{theMoviedbId}}" class="media-icons"
|
||||
target="_blank">
|
||||
<i matTooltip="The Movie DB" class="fas fa-film fa-2x grow-social"></i>
|
||||
</a>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, Inject, Input } from "@angular/core";
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { DomSanitizer, SafeStyle } from "@angular/platform-browser";
|
||||
|
||||
@Component({
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div>
|
||||
<div class="rating medium-font">
|
||||
<span *ngIf="tv.rating">
|
||||
<img class="rating-small" src="{{baseUrl}}/images/tvm-logo.png"> {{tv.rating}}/10
|
||||
<img class="rating-small" src="{{baseUrl}}/images/tmdb-logo.svg"> {{tv.rating * 10}}%
|
||||
</span>
|
||||
<span *ngIf="ratings?.score && ratings?.class">
|
||||
<img class="rating-small" src="{{baseUrl}}/images/{{ratings.class === 'rotten' ? 'rotten-rotten.svg' : 'rotten-fresh.svg'}}"> {{ratings.score}}%
|
||||
|
@ -56,13 +56,27 @@
|
|||
{{tv.network.name}}
|
||||
</div>
|
||||
|
||||
<div *ngIf="tv.genre">
|
||||
|
||||
<div class="genre-button-container" *ngIf="tv.genres">
|
||||
<span class="label">{{'MediaDetails.Genres' | translate }}:</span>
|
||||
<div>
|
||||
<span *ngFor="let genre of tv.genre">
|
||||
{{genre}} |
|
||||
</span>
|
||||
</div>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let genre of tv.genres">
|
||||
{{genre.name}}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div class="keyword-button-container" *ngIf="tv?.keywords?.keywordsValue?.length > 0">
|
||||
<span class="label">{{'MediaDetails.Keywords' | translate }}:</span>
|
||||
<mat-chip-list>
|
||||
<mat-chip selected *ngFor="let keyword of tv.keywords.keywordsValue">
|
||||
{{keyword.name}}
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ export class TvInformationPanelComponent implements OnInit {
|
|||
this.searchService.getRottenTvRatings(this.tv.title, +this.tv.firstAired.toString().substring(0,4))
|
||||
.subscribe(x => this.ratings = x);
|
||||
|
||||
this.searchService.getTvStreams(+this.tv.theTvDbId, this.tv.id).subscribe(x => this.streams = x);
|
||||
this.searchService.getTvStreams(+this.tv.id ).subscribe(x => this.streams = x);
|
||||
this.tv.seasonRequests.forEach(season => {
|
||||
this.totalEpisodes = this.totalEpisodes + season.episodes.length;
|
||||
});
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
</div>
|
||||
</ng-template>
|
||||
|
||||
<mat-card class="mat-elevation-z8">
|
||||
<mat-card-content>
|
||||
<p>{{season.overview}}</p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
|
||||
<table mat-table [dataSource]="season.episodes" class="mat-elevation-z8">
|
||||
|
||||
<ng-container matColumnDef="select">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<mat-accordion class="mat-elevation-z8">
|
||||
|
||||
<mat-expansion-panel *ngFor="let request of tvRequest">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
|
|
|
@ -15,12 +15,15 @@
|
|||
<div>
|
||||
|
||||
<top-banner [background]="tv.background" [available]="tv.available" [title]="tv.title"
|
||||
[releaseDate]="tv.firstAired" [tagline]="tv.certification"></top-banner>
|
||||
[releaseDate]="tv.firstAired" [tagline]="tv.tagline"></top-banner>
|
||||
<div class="social-icons-container">
|
||||
<social-icons
|
||||
[homepage]="tv.homepage"
|
||||
[tvdbId]="tv.id"
|
||||
[theMoviedbId]="tv.id"
|
||||
[hasTrailer]="tv.trailer"
|
||||
[twitter]="tv.externalIds.twitterId"
|
||||
[facebook]="tv.externalIds.facebookId"
|
||||
[instagram]="tv.externalIds.instagramId"
|
||||
(openTrailer)="openDialog()"
|
||||
[imdbId]="tv.imdbId"
|
||||
[available]="tv.available || tv.partlyAvailable"
|
||||
|
@ -41,7 +44,7 @@
|
|||
<div class="small-middle-container">
|
||||
<div class="row justify-content-center justify-content-sm-start header-container">
|
||||
<div class="details-poster-container">
|
||||
<media-poster [posterPath]="tv.images?.medium"></media-poster>
|
||||
<media-poster [posterPath]="'https://image.tmdb.org/t/p/w300/' + tv.images.original"></media-poster>
|
||||
</div>
|
||||
<!--Next to poster-->
|
||||
<div class="details-button-container">
|
||||
|
|
|
@ -13,6 +13,7 @@ import { TvAdvancedOptionsComponent } from "./panels/tv-advanced-options/tv-adva
|
|||
import { RequestServiceV2 } from "../../../services/requestV2.service";
|
||||
import { RequestBehalfComponent } from "../shared/request-behalf/request-behalf.component";
|
||||
import { forkJoin } from "rxjs";
|
||||
import { TopBannerComponent } from "../shared/top-banner/top-banner.component";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./tv-details.component.html",
|
||||
|
@ -57,12 +58,12 @@ export class TvDetailsComponent implements OnInit {
|
|||
this.showAdvanced = await this.sonarrService.isEnabled();
|
||||
}
|
||||
|
||||
if (this.fromSearch) {
|
||||
this.tv = await this.searchService.getTvInfoWithMovieDbId(this.tvdbId);
|
||||
this.tvdbId = this.tv.id;
|
||||
} else {
|
||||
// if (this.fromSearch) {
|
||||
// this.tv = await this.searchService.getTvInfoWithMovieDbId(this.tvdbId);
|
||||
// this.tvdbId = this.tv.id;
|
||||
// } else {
|
||||
this.tv = await this.searchService.getTvInfo(this.tvdbId);
|
||||
}
|
||||
// }
|
||||
|
||||
if (this.tv.requestId) {
|
||||
this.tvRequest = await this.requestService.getChildRequests(this.tv.requestId).toPromise();
|
||||
|
@ -70,8 +71,8 @@ export class TvDetailsComponent implements OnInit {
|
|||
this.loadAdvancedInfo();
|
||||
}
|
||||
|
||||
const tvBanner = await this.imageService.getTvBanner(this.tvdbId).toPromise();
|
||||
this.tv.background = this.sanitizer.bypassSecurityTrustStyle("url(" + tvBanner + ")");
|
||||
// const tvBanner = await this.imageService.getTvBanner(this.tvdbId).toPromise();
|
||||
this.tv.background = this.sanitizer.bypassSecurityTrustStyle("url(https://image.tmdb.org/t/p/original" + this.tv.banner + ")");
|
||||
}
|
||||
|
||||
public async request(userId: string) {
|
||||
|
@ -87,7 +88,6 @@ export class TvDetailsComponent implements OnInit {
|
|||
|
||||
public openDialog() {
|
||||
let trailerLink = this.tv.trailer;
|
||||
trailerLink = trailerLink.split('?v=')[1];
|
||||
|
||||
this.dialog.open(YoutubeTrailerComponent, {
|
||||
width: '560px',
|
||||
|
|
|
@ -210,7 +210,7 @@
|
|||
}
|
||||
|
||||
.rating-small {
|
||||
width: 1.3em;
|
||||
width: 1.4em;
|
||||
}
|
||||
.stream-small {
|
||||
width: 3em;
|
||||
|
|
|
@ -140,8 +140,8 @@ export class SearchV2Service extends ServiceHelpers {
|
|||
return this.http.get<IStreamingData[]>(`${this.url}/stream/movie/${theMovieDbId}`);
|
||||
}
|
||||
|
||||
public getTvStreams(theTvDbId: number, tvMaze: number): Observable<IStreamingData[]> {
|
||||
return this.http.get<IStreamingData[]>(`${this.url}/stream/tv/${theTvDbId}/${tvMaze}`);
|
||||
public getTvStreams(movieDbId: number): Observable<IStreamingData[]> {
|
||||
return this.http.get<IStreamingData[]>(`${this.url}/stream/tv/${movieDbId}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
background-color: white !important;
|
||||
}
|
||||
</style>
|
||||
<base href="/" />
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
|
||||
<link href="styles/please-wait.css" rel="stylesheet">
|
||||
|
|
|
@ -263,9 +263,9 @@ namespace Ombi.Controllers.V1
|
|||
[HttpGet("tv/info/{tvdbId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<SearchTvShowViewModel> GetShowInfo(int tvdbId)
|
||||
public async Task<SearchTvShowViewModel> GetShowInfo(string tvdbId)
|
||||
{
|
||||
return await TvEngine.GetShowInformation(tvdbId);
|
||||
return await TvEngine.GetShowInformation(tvdbId, HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -99,9 +99,9 @@ namespace Ombi.Controllers.V2
|
|||
/// <remarks>TVMaze is the TV Show Provider</remarks>
|
||||
/// <param name="tvdbid">The TVDB Id</param>
|
||||
[HttpGet("tv/{tvdbId}")]
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetTvInfo(int tvdbid)
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetTvInfo(string tvdbid)
|
||||
{
|
||||
return await _tvEngineV2.GetShowInformation(tvdbid);
|
||||
return await _tvEngineV2.GetShowInformation(tvdbid, HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -112,7 +112,7 @@ namespace Ombi.Controllers.V2
|
|||
[HttpGet("tv/request/{requestId}")]
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetTvInfoByRequest(int requestId)
|
||||
{
|
||||
return await _tvEngineV2.GetShowByRequest(requestId);
|
||||
return await _tvEngineV2.GetShowByRequest(requestId, HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -120,10 +120,9 @@ namespace Ombi.Controllers.V2
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("tv/moviedb/{moviedbid}")]
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetTvInfoByMovieId(int moviedbid)
|
||||
public async Task<SearchFullInfoTvShowViewModel> GetTvInfoByMovieId(string moviedbid)
|
||||
{
|
||||
var tvDbId = await _movieEngineV2.GetTvDbId(moviedbid);
|
||||
return await _tvEngineV2.GetShowInformation(tvDbId);
|
||||
return await _tvEngineV2.GetShowInformation(moviedbid, HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -437,12 +436,12 @@ namespace Ombi.Controllers.V2
|
|||
return _movieEngineV2.GetStreamInformation(movieDBId, HttpContext.RequestAborted);
|
||||
}
|
||||
|
||||
[HttpGet("stream/tv/{tvdbId}/{tvMaze}")]
|
||||
[HttpGet("stream/tv/{movieDbId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesDefaultResponseType]
|
||||
public Task<IEnumerable<StreamingData>> GetTvStreams(int tvdbId, int tvMaze)
|
||||
public Task<IEnumerable<StreamingData>> GetTvStreams(int movieDbId)
|
||||
{
|
||||
return _tvEngineV2.GetStreamInformation(tvdbId, tvMaze, HttpContext.RequestAborted);
|
||||
return _tvEngineV2.GetStreamInformation(movieDbId, HttpContext.RequestAborted);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue