using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Ombi.Api.TvMaze; using Ombi.Api.TheMovieDb; using Ombi.Api.TvMaze.Models; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository.Requests; using Microsoft.Extensions.Logging; namespace Ombi.Core.Helpers { public class TvShowRequestBuilder { private readonly ILogger _logger; public TvShowRequestBuilder(ITvMazeApi tvApi, IMovieDbApi movApi, ILogger logger) { TvApi = tvApi; MovieDbApi = movApi; _logger = logger; } private ITvMazeApi TvApi { get; } private IMovieDbApi MovieDbApi { get; } public ChildRequests ChildRequest { get; set; } public List TvRequests { get; protected set; } public string PosterPath { get; protected set; } public string BackdropPath { get; protected set; } public DateTime FirstAir { get; protected set; } public TvRequests NewRequest { get; protected set; } protected TvMazeShow ShowInfo { get; set; } protected List Results { get; set; } protected TvSearchResult TheMovieDbRecord { get; set; } public async Task GetShowInfo(int id) { ShowInfo = await TvApi.ShowLookupByTheTvDbId(id); Results = await MovieDbApi.SearchTv(ShowInfo.name); foreach (TvSearchResult result in Results) { if (result.Name.Equals(ShowInfo.name, StringComparison.InvariantCultureIgnoreCase)) { _logger.LogInformation($"Found matching MovieDb entry for show name {ShowInfo.name}"); TheMovieDbRecord = result; var showIds = await MovieDbApi.GetTvExternals(result.Id); ShowInfo.externals.imdb = showIds.imdb_id; BackdropPath = result.BackdropPath; break; } } DateTime.TryParse(ShowInfo.premiered, out var dt); FirstAir = dt; // For some reason the poster path is always http PosterPath = ShowInfo.image?.medium.ToHttpsUrl(); return this; } public TvShowRequestBuilder CreateChild(TvRequestViewModel model, string userId) { ChildRequest = new ChildRequests { Id = model.TvDbId, // This is set to 0 after the request rules have run, the request rules needs it to identify the request RequestType = RequestType.TvShow, RequestedDate = DateTime.UtcNow, Approved = false, RequestedUserId = userId, SeasonRequests = new List(), Title = ShowInfo.name, ReleaseYear = FirstAir, RequestedByAlias = model.RequestedByAlias, SeriesType = ShowInfo.genres.Any( s => s.Equals("Anime", StringComparison.InvariantCultureIgnoreCase)) ? SeriesType.Anime : SeriesType.Standard }; return this; } public TvShowRequestBuilder CreateTvList(TvRequestViewModel tv) { TvRequests = new List(); // Only have the TV requests we actually requested and not everything foreach (var season in tv.Seasons) { if (season.Episodes.Any()) { TvRequests.Add(season); } } return this; } public async Task BuildEpisodes(TvRequestViewModel tv) { if (tv.RequestAll) { var episodes = await TvApi.EpisodeLookup(ShowInfo.id); foreach (var ep in episodes) { var season = ChildRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == ep.season); if (season == null) { ChildRequest.SeasonRequests.Add(new SeasonRequests { Episodes = new List{ new EpisodeRequests { EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, Url = ep.url.ToHttpsUrl() } }, SeasonNumber = ep.season, }); } else { season.Episodes.Add(new EpisodeRequests { EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, Url = ep.url.ToHttpsUrl() }); } } } else if (tv.LatestSeason) { var episodes = await TvApi.EpisodeLookup(ShowInfo.id); var latest = episodes.OrderByDescending(x => x.season).FirstOrDefault(); var episodesRequests = new List(); foreach (var ep in episodes) { if (ep.season == latest.season) { episodesRequests.Add(new EpisodeRequests { EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, Url = ep.url.ToHttpsUrl() }); } } ChildRequest.SeasonRequests.Add(new SeasonRequests { Episodes = episodesRequests, SeasonNumber = latest.season, }); } else if (tv.FirstSeason) { var episodes = await TvApi.EpisodeLookup(ShowInfo.id); var first = episodes.OrderBy(x => x.season).FirstOrDefault(); var episodesRequests = new List(); foreach (var ep in episodes) { if (ep.season == first.season) { episodesRequests.Add(new EpisodeRequests { EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, Url = ep.url.ToHttpsUrl() }); } } ChildRequest.SeasonRequests.Add(new SeasonRequests { Episodes = episodesRequests, SeasonNumber = first.season, }); } else { // It's a custom request var seasonRequests = new List(); var episodes = await TvApi.EpisodeLookup(ShowInfo.id); foreach (var ep in episodes) { var existingSeasonRequest = seasonRequests.FirstOrDefault(x => x.SeasonNumber == ep.season); if (existingSeasonRequest != null) { var requestedSeason = tv.Seasons.FirstOrDefault(x => x.SeasonNumber == ep.season); var requestedEpisode = requestedSeason?.Episodes?.Any(x => x.EpisodeNumber == ep.number) ?? false; if (requestedSeason != null && requestedEpisode) { // We already have this, let's just add the episodes to it existingSeasonRequest.Episodes.Add(new EpisodeRequests { EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, Url = ep.url.ToHttpsUrl() }); } } else { var newRequest = new SeasonRequests {SeasonNumber = ep.season}; var requestedSeason = tv.Seasons.FirstOrDefault(x => x.SeasonNumber == ep.season); var requestedEpisode = requestedSeason?.Episodes?.Any(x => x.EpisodeNumber == ep.number) ?? false; if (requestedSeason != null && requestedEpisode) { newRequest.Episodes.Add(new EpisodeRequests { EpisodeNumber = ep.number, AirDate = FormatDate(ep.airdate), Title = ep.name, Url = ep.url.ToHttpsUrl() }); seasonRequests.Add(newRequest); } } } foreach (var s in seasonRequests) { ChildRequest.SeasonRequests.Add(s); } } return this; } public TvShowRequestBuilder CreateNewRequest(TvRequestViewModel tv) { _logger.LogInformation($"Building Request for {ShowInfo.name} with Provider ID {TheMovieDbRecord?.Id ?? 0}"); NewRequest = new TvRequests { Overview = ShowInfo.summary.RemoveHtml(), PosterPath = PosterPath, Title = ShowInfo.name, ReleaseDate = FirstAir, ExternalProviderId = TheMovieDbRecord?.Id ?? 0, Status = ShowInfo.status, ImdbId = ShowInfo.externals?.imdb ?? string.Empty, TvDbId = tv.TvDbId, ChildRequests = new List(), TotalSeasons = tv.Seasons?.Count ?? 0, Background = BackdropPath }; NewRequest.ChildRequests.Add(ChildRequest); return this; } private static DateTime FormatDate(string date) { if (date.HasValue()) { if (DateTime.TryParse(date, out var d)) { return d; } } return DateTime.MinValue; } } }