using AutoMapper; using Ombi.Api.Trakt; using Ombi.Api.TvMaze; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Settings; using Ombi.Store.Repository; using System; 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; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using System.Threading; using TraktSharp.Entities; using Ombi.Core.Helpers; namespace Ombi.Core.Engine { public class TvSearchEngine : BaseMediaEngine, ITvSearchEngine { private readonly ISettingsService _customizationSettings; private readonly IImageService _imageService; private readonly IMovieDbApi _theMovieDbApi; public TvSearchEngine(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ISettingsService customizationSettings, ICacheService memCache, ISettingsService s, IRepository sub, IImageService imageService, IMovieDbApi theMovieDbApi) : base(identity, service, r, um, memCache, s, sub) { _imageService = imageService; _theMovieDbApi = theMovieDbApi; TvMazeApi = tvMaze; Mapper = mapper; TraktApi = trakt; _customizationSettings = customizationSettings; } protected ITvMazeApi TvMazeApi { get; } protected IMapper Mapper { get; } private ITraktApi TraktApi { get; } public async Task> Search(string searchTerm) { var searchResult = await TvMazeApi.Search(searchTerm); if (searchResult != null) { var retVal = new List(); foreach (var tvMazeSearch in searchResult) { if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false)) { continue; } var mappedResult = await ProcessResult(tvMazeSearch, false); if (mappedResult == null) { continue; } retVal.Add(mappedResult); } return retVal; } return null; } public async Task GetShowInformation(string tvdbid, CancellationToken token) { var show = await Cache.GetOrAddAsync(nameof(GetShowInformation) + tvdbid, () => TvMazeApi.ShowLookupByTheTvDbId(int.Parse(tvdbid)), DateTimeOffset.Now.AddHours(12)); if (show == null) { // We don't have enough information return null; } var episodes = await Cache.GetOrAddAsync("TvMazeEpisodeLookup" + show.id, () => TvMazeApi.EpisodeLookup(show.id), DateTimeOffset.Now.AddHours(12)); if (episodes == null || !episodes.Any()) { // We don't have enough information return null; } var mapped = Mapper.Map(show); foreach (var e in episodes) { var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season); if (season == null) { var newSeason = new SeasonRequests { SeasonNumber = e.season, Episodes = new List() }; var hasAirDate = e.airstamp.HasValue(); var airDate = DateTime.MinValue; if (hasAirDate) { hasAirDate = DateTime.TryParse(e.airdate, out airDate); } newSeason.Episodes.Add(new EpisodeRequests { Url = e.url.ToHttpsUrl(), Title = e.name, AirDate = airDate, EpisodeNumber = e.number, }); mapped.SeasonRequests.Add(newSeason); } else { var hasAirDate = e.airstamp.HasValue(); var airDate = DateTime.MinValue; if (hasAirDate) { hasAirDate = DateTime.TryParse(e.airdate, out airDate); } // We already have the season, so just add the episode season.Episodes.Add(new EpisodeRequests { Url = e.url.ToHttpsUrl(), Title = e.name, AirDate = airDate, EpisodeNumber = e.number, }); } } return await ProcessResult(mapped, false); } public async Task> Popular() { var result = await Cache.GetOrAddAsync(CacheKeys.PopularTv, () => TraktApi.GetPopularShows(null, ResultLimit), DateTimeOffset.Now.AddHours(12)); var processed = ProcessResults(result); return await processed; } public async Task> Popular(int currentlyLoaded, int amountToLoad, bool includeImages = false) { var langCode = await DefaultLanguageCode(null); var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAddAsync(nameof(Popular) + langCode + pagesToLoad.Page, () => TraktApi.GetPopularShows(pagesToLoad.Page, ResultLimit), DateTimeOffset.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } var processed = ProcessResults(results, includeImages); return await processed; } public async Task> Anticipated() { var result = await Cache.GetOrAddAsync(CacheKeys.AnticipatedTv, () => TraktApi.GetAnticipatedShows(null, ResultLimit), DateTimeOffset.Now.AddHours(12)); var processed = ProcessResults(result); return await processed; } public async Task> Anticipated(int currentlyLoaded, int amountToLoad) { var langCode = await DefaultLanguageCode(null); var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAddAsync(nameof(Anticipated) + langCode + pagesToLoad.Page, () => TraktApi.GetAnticipatedShows(pagesToLoad.Page, ResultLimit), DateTimeOffset.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } var processed = ProcessResults(results); return await processed; } public async Task> Trending() { var result = await Cache.GetOrAddAsync(CacheKeys.TrendingTv, () => TraktApi.GetTrendingShows(null, ResultLimit), DateTimeOffset.Now.AddHours(12)); var processed = ProcessResults(result); return await processed; } public async Task> Trending(int currentlyLoaded, int amountToLoad) { var langCode = await DefaultLanguageCode(null); var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAddAsync(nameof(Trending) + langCode + pagesToLoad.Page, () => TraktApi.GetTrendingShows(pagesToLoad.Page, ResultLimit), DateTimeOffset.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } var processed = ProcessResults(results); return await processed; } protected async Task> ProcessResults(IEnumerable items, bool includeImages = false) { var retVal = new List(); var settings = await _customizationSettings.GetSettingsAsync(); foreach (var tvMazeSearch in items) { var result = await ProcessResult(tvMazeSearch, includeImages); if (result == null || settings.HideAvailableFromDiscover && result.Available) { continue; } retVal.Add(result); } return retVal; } protected async Task ProcessResult(T tvMazeSearch, bool includeImages) { var mapped = Mapper.Map(tvMazeSearch); return await ProcessResult(mapped, includeImages); } private async Task ProcessResult(SearchTvShowViewModel item, bool includeImages) { if (item.Id == 0) { return null; } item.TheMovieDbId = item.Id.ToString(); //item.TheTvDbId = item.Id.ToString(); //if (includeImages) //{ // if (item.TheTvDbId.HasValue()) // { // item.BackdropPath = await _imageService.GetTvBackground(item.TheTvDbId); // } //} await RunSearchRules(item); return item; } } }