You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Ombi/src/Ombi.Core/Engine/TvSearchEngine.cs

317 lines
13 KiB

using AutoMapper;
using Ombi.Api.Trakt;
7 years ago
using Ombi.Api.TvMaze;
using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search;
7 years ago
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Store.Repository;
7 years ago
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.Entities.Requests;
using Ombi.Store.Repository.Requests;
using Ombi.Store.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Ombi.Core.Authentication;
using Ombi.Helpers;
7 years ago
namespace Ombi.Core.Engine
{
public class TvSearchEngine : BaseMediaEngine, ITvSearchEngine
7 years ago
{
7 years ago
public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService<PlexSettings> plexSettings,
ISettingsService<EmbySettings> embySettings, IPlexContentRepository repo, IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um,
IMemoryCache memCache)
: base(identity, service, r, um)
7 years ago
{
TvMazeApi = tvMaze;
Mapper = mapper;
PlexSettings = plexSettings;
EmbySettings = embySettings;
PlexContentRepo = repo;
7 years ago
TraktApi = trakt;
EmbyContentRepo = embyRepo;
MemCache = memCache;
7 years ago
}
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; }
7 years ago
private ITraktApi TraktApi { get; }
private IMemoryCache MemCache { get; }
7 years ago
public async Task<IEnumerable<SearchTvShowViewModel>> Search(string searchTerm)
{
var searchResult = await TvMazeApi.Search(searchTerm);
if (searchResult != null)
{
return await ProcessResults(searchResult);
}
return null;
}
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> SearchTreeNode(string searchTerm)
{
var result = await Search(searchTerm);
return result.Select(ParseIntoTreeNode).ToList();
}
public async Task<SearchTvShowViewModel> GetShowInformation(int tvdbid)
{
var show = await TvMazeApi.ShowLookupByTheTvDbId(tvdbid);
if (show == null)
{
// We don't have enough information
return null;
}
var episodes = await TvMazeApi.EpisodeLookup(show.id);
if (episodes == null || !episodes.Any())
{
// We don't have enough information
return null;
}
var mapped = Mapper.Map<SearchTvShowViewModel>(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<EpisodeRequests>()
};
newSeason.Episodes.Add(new EpisodeRequests
{
Url = e.url,
Title = e.name,
AirDate = DateTime.Parse(e.airstamp ?? DateTime.MinValue.ToString()),
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 = DateTime.Parse(e.airstamp ?? DateTime.MinValue.ToString()),
EpisodeNumber = e.number,
});
}
}
var existingRequests = await GetTvRequests();
var plexSettings = await PlexSettings.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync();
return await ProcessResult(mapped, existingRequests, plexSettings, embySettings);
}
public async Task<TreeNode<SearchTvShowViewModel>> GetShowInformationTreeNode(int tvdbid)
{
var result = await GetShowInformation(tvdbid);
return ParseIntoTreeNode(result);
}
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Popular()
7 years ago
{
var result = await MemCache.GetOrCreateAsync(CacheKeys.PopularTv, async entry =>
{
entry.AbsoluteExpiration = DateTimeOffset.Now.AddHours(12);
return await TraktApi.GetPopularShows();
});
var processed = await ProcessResults(result);
return processed.Select(ParseIntoTreeNode).ToList();
7 years ago
}
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Anticipated()
7 years ago
{
var result = await MemCache.GetOrCreateAsync(CacheKeys.AnticipatedTv, async entry =>
{
entry.AbsoluteExpiration = DateTimeOffset.Now.AddHours(12);
return await TraktApi.GetAnticipatedShows();
});
var processed= await ProcessResults(result);
return processed.Select(ParseIntoTreeNode).ToList();
7 years ago
}
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> MostWatches()
7 years ago
{
var result = await MemCache.GetOrCreateAsync(CacheKeys.MostWatchesTv, async entry =>
{
entry.AbsoluteExpiration = DateTimeOffset.Now.AddHours(12);
return await TraktApi.GetMostWatchesShows();
});
var processed = await ProcessResults(result);
return processed.Select(ParseIntoTreeNode).ToList();
7 years ago
}
public async Task<IEnumerable<TreeNode<SearchTvShowViewModel>>> Trending()
7 years ago
{
var result = await MemCache.GetOrCreateAsync(CacheKeys.TrendingTv, async entry =>
{
entry.AbsoluteExpiration = DateTimeOffset.Now.AddHours(12);
return await TraktApi.GetTrendingShows();
});
var processed = await ProcessResults(result);
return processed.Select(ParseIntoTreeNode).ToList();
7 years ago
}
private static TreeNode<SearchTvShowViewModel> ParseIntoTreeNode(SearchTvShowViewModel result)
{
return new TreeNode<SearchTvShowViewModel>
{
Data = result,
Children = new List<TreeNode<SearchTvShowViewModel>>
{
new TreeNode<SearchTvShowViewModel>
{
Data = result, Leaf = true
}
},
Leaf = false
};
}
7 years ago
private async Task<IEnumerable<SearchTvShowViewModel>> ProcessResults<T>(IEnumerable<T> items)
{
7 years ago
var existingRequests = await GetTvRequests();
var plexSettings = await PlexSettings.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync();
var retVal = new List<SearchTvShowViewModel>();
foreach (var tvMazeSearch in items)
{
7 years ago
var viewT = Mapper.Map<SearchTvShowViewModel>(tvMazeSearch);
retVal.Add(await ProcessResult(viewT, existingRequests, plexSettings, embySettings));
}
return retVal;
}
private async Task<SearchTvShowViewModel> ProcessResult(SearchTvShowViewModel item, Dictionary<int, TvRequests> existingRequests, PlexSettings plexSettings, EmbySettings embySettings)
{
if (embySettings.Enable)
{
var content = await EmbyContentRepo.Get(item.Id.ToString());
if (content != null)
{
item.Available = true;
}
// Let's go through the episodes now
if (item.SeasonRequests.Any())
{
var allEpisodes = EmbyContentRepo.GetAllEpisodes().Include(x => x.Series);
foreach (var season in item.SeasonRequests)
{
foreach (var episode in season.Episodes)
{
var epExists = await allEpisodes.FirstOrDefaultAsync(x =>
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && item.Id.ToString() == x.Series.ProviderId);
if (epExists != null)
{
episode.Available = true;
}
}
}
}
}
if (plexSettings.Enable)
{
var content = await PlexContentRepo.Get(item.Id.ToString());
if (content != null)
{
item.Available = true;
item.PlexUrl = content.Url;
}
// Let's go through the episodes now
if (item.SeasonRequests.Any())
{
var allEpisodes = PlexContentRepo.GetAllEpisodes();
foreach (var season in item.SeasonRequests)
{
foreach (var episode in season.Episodes)
{
var epExists = await allEpisodes.FirstOrDefaultAsync(x =>
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && x.Series.ProviderId == item.Id.ToString());
if (epExists != null)
{
episode.Available = true;
}
}
}
}
}
if (item.SeasonRequests.Any() && item.SeasonRequests.All(x => x.Episodes.All(e => e.Approved)))
{
item.FullyAvailable = true;
}
if (item.Id > 0)
{
7 years ago
var tvdbid = item.Id;
if (existingRequests.ContainsKey(tvdbid))
{
var existingRequest = existingRequests[tvdbid];
7 years ago
item.Requested = true;
item.Approved = existingRequest.ChildRequests.Any(x => x.Approved);
// Let's modify the seasonsrequested to reflect what we have requested...
foreach (var season in item.SeasonRequests)
{
foreach (var existingRequestChildRequest in existingRequest.ChildRequests)
{
// Find the existing request season
var existingSeason =
existingRequestChildRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == season.SeasonNumber);
if (existingSeason == null) continue;
foreach (var ep in existingSeason.Episodes)
{
// Find the episode from what we are searching
var episodeSearching = season.Episodes.FirstOrDefault(x => x.EpisodeNumber == ep.EpisodeNumber);
if (episodeSearching == null)
{
continue;
}
episodeSearching.Requested = true;
episodeSearching.Available = ep.Available;
episodeSearching.Approved = ep.Season.ChildRequest.Approved;
}
}
}
}
// TODO CHECK SONARR/RADARR
//if (sonarrCached.Select(x => x.TvdbId).Contains(tvdbid) || sickRageCache.Contains(tvdbid))
// // compare to the sonarr/sickrage db
//{
7 years ago
// item.Requested = true;
//}
}
7 years ago
return item;
}
7 years ago
}
}