mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-22 22:23:34 -07:00
First pass at newsletter refactoring
This commit is contained in:
parent
a309f50d15
commit
229a89f48a
19 changed files with 198 additions and 617 deletions
|
@ -46,10 +46,10 @@ namespace Ombi.Core.Rule.Rules.Search
|
|||
}
|
||||
}
|
||||
|
||||
public static async Task SingleEpisodeCheck(bool useImdb, IQueryable<PlexEpisode> allEpisodes, EpisodeRequests episode,
|
||||
SeasonRequests season, PlexServerContent item, bool useTheMovieDb, bool useTvDb, ILogger log)
|
||||
public static async Task SingleEpisodeCheck(bool useImdb, IQueryable<IMediaServerEpisode> allEpisodes, EpisodeRequests episode,
|
||||
SeasonRequests season, IMediaServerContent item, bool useTheMovieDb, bool useTvDb, ILogger log)
|
||||
{
|
||||
PlexEpisode epExists = null;
|
||||
IMediaServerEpisode epExists = null;
|
||||
try
|
||||
{
|
||||
|
||||
|
@ -79,66 +79,6 @@ namespace Ombi.Core.Rule.Rules.Search
|
|||
log.LogError(e, "Exception thrown when attempting to check if something is available");
|
||||
}
|
||||
|
||||
if (epExists != null)
|
||||
{
|
||||
episode.Available = true;
|
||||
}
|
||||
}
|
||||
public static async Task SingleEpisodeCheck(bool useImdb, IQueryable<EmbyEpisode> allEpisodes, EpisodeRequests episode,
|
||||
SeasonRequests season, EmbyContent item, bool useTheMovieDb, bool useTvDb)
|
||||
{
|
||||
EmbyEpisode epExists = null;
|
||||
if (useImdb)
|
||||
{
|
||||
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
|
||||
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
|
||||
x.Series.ImdbId == item.ImdbId);
|
||||
}
|
||||
|
||||
if (useTheMovieDb)
|
||||
{
|
||||
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
|
||||
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
|
||||
x.Series.TheMovieDbId == item.TheMovieDbId);
|
||||
}
|
||||
|
||||
if (useTvDb)
|
||||
{
|
||||
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
|
||||
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
|
||||
x.Series.TvDbId == item.TvDbId);
|
||||
}
|
||||
|
||||
if (epExists != null)
|
||||
{
|
||||
episode.Available = true;
|
||||
}
|
||||
}
|
||||
public static async Task SingleEpisodeCheck(bool useImdb, IQueryable<JellyfinEpisode> allEpisodes, EpisodeRequests episode,
|
||||
SeasonRequests season, JellyfinContent item, bool useTheMovieDb, bool useTvDb)
|
||||
{
|
||||
JellyfinEpisode epExists = null;
|
||||
if (useImdb)
|
||||
{
|
||||
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
|
||||
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
|
||||
x.Series.ImdbId == item.ImdbId);
|
||||
}
|
||||
|
||||
if (useTheMovieDb)
|
||||
{
|
||||
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
|
||||
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
|
||||
x.Series.TheMovieDbId == item.TheMovieDbId);
|
||||
}
|
||||
|
||||
if (useTvDb)
|
||||
{
|
||||
epExists = await allEpisodes.FirstOrDefaultAsync(x =>
|
||||
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber &&
|
||||
x.Series.TvDbId == item.TvDbId);
|
||||
}
|
||||
|
||||
if (epExists != null)
|
||||
{
|
||||
episode.Available = true;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Core.Rule.Interfaces;
|
||||
using Ombi.Core.Settings;
|
||||
|
@ -13,13 +14,15 @@ namespace Ombi.Core.Rule.Rules.Search
|
|||
{
|
||||
public class EmbyAvailabilityRule : BaseSearchRule, IRules<SearchViewModel>
|
||||
{
|
||||
public EmbyAvailabilityRule(IEmbyContentRepository repo, ISettingsService<EmbySettings> s)
|
||||
public EmbyAvailabilityRule(IEmbyContentRepository repo, ILogger<EmbyAvailabilityRule> log, ISettingsService<EmbySettings> s)
|
||||
{
|
||||
EmbyContentRepository = repo;
|
||||
Log = log;
|
||||
EmbySettings = s;
|
||||
}
|
||||
|
||||
private IEmbyContentRepository EmbyContentRepository { get; }
|
||||
private ILogger Log { get; }
|
||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||
|
||||
public async Task<RuleResult> Execute(SearchViewModel obj)
|
||||
|
@ -89,7 +92,7 @@ namespace Ombi.Core.Rule.Rules.Search
|
|||
{
|
||||
foreach (var episode in season.Episodes)
|
||||
{
|
||||
await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb);
|
||||
await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb, Log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ombi.Core.Models.Search;
|
||||
using Ombi.Core.Rule.Interfaces;
|
||||
using Ombi.Core.Settings;
|
||||
|
@ -13,13 +14,15 @@ namespace Ombi.Core.Rule.Rules.Search
|
|||
{
|
||||
public class JellyfinAvailabilityRule : BaseSearchRule, IRules<SearchViewModel>
|
||||
{
|
||||
public JellyfinAvailabilityRule(IJellyfinContentRepository repo, ISettingsService<JellyfinSettings> s)
|
||||
public JellyfinAvailabilityRule(IJellyfinContentRepository repo, ILogger<JellyfinAvailabilityRule> log, ISettingsService<JellyfinSettings> s)
|
||||
{
|
||||
JellyfinContentRepository = repo;
|
||||
Log = log;
|
||||
JellyfinSettings = s;
|
||||
}
|
||||
|
||||
private IJellyfinContentRepository JellyfinContentRepository { get; }
|
||||
private ILogger Log { get; }
|
||||
private ISettingsService<JellyfinSettings> JellyfinSettings { get; }
|
||||
|
||||
public async Task<RuleResult> Execute(SearchViewModel obj)
|
||||
|
@ -104,7 +107,7 @@ namespace Ombi.Core.Rule.Rules.Search
|
|||
{
|
||||
foreach (var episode in season.Episodes)
|
||||
{
|
||||
await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb);
|
||||
await AvailabilityRuleHelper.SingleEpisodeCheck(useImdb, allEpisodes, episode, season, item, useTheMovieDb, useTvDb, Log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace Ombi.Schedule.Jobs.Emby
|
|||
|
||||
var tvDbId = child.ParentRequest.TvDbId;
|
||||
var imdbId = child.ParentRequest.ImdbId;
|
||||
IQueryable<EmbyEpisode> seriesEpisodes = null;
|
||||
IQueryable<IMediaServerEpisode> seriesEpisodes = null;
|
||||
if (useImdb)
|
||||
{
|
||||
seriesEpisodes = embyEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString());
|
||||
|
|
|
@ -151,7 +151,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin
|
|||
|
||||
var tvDbId = child.ParentRequest.TvDbId;
|
||||
var imdbId = child.ParentRequest.ImdbId;
|
||||
IQueryable<JellyfinEpisode> seriesEpisodes = null;
|
||||
IQueryable<IMediaServerEpisode> seriesEpisodes = null;
|
||||
if (useImdb)
|
||||
{
|
||||
seriesEpisodes = jellyfinEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString());
|
||||
|
|
|
@ -124,18 +124,22 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
|
||||
|
||||
var customization = await _customizationSettings.GetSettingsAsync();
|
||||
// Get the Content
|
||||
var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking();
|
||||
var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking();
|
||||
var jellyfinContent = _jellyfin.GetAll().Include(x => x.Episodes).AsNoTracking();
|
||||
// MOVIES
|
||||
var plexContent = (IQueryable<IMediaServerContent>)_plex.GetAll().Include(x => x.Episodes).AsNoTracking();
|
||||
var embyContent = (IQueryable<IMediaServerContent>)_emby.GetAll().Include(x => x.Episodes).AsNoTracking();
|
||||
var jellyfinContent = (IQueryable<IMediaServerContent>)_jellyfin.GetAll().Include(x => x.Episodes).AsNoTracking();
|
||||
|
||||
var plexContentMoviesToSend = await getMoviesContent(plexContent, RecentlyAddedType.Plex);
|
||||
var embyContentMoviesToSend = await getMoviesContent(embyContent, RecentlyAddedType.Emby);
|
||||
var jellyfinContentMoviesToSend = await getMoviesContent(jellyfinContent, RecentlyAddedType.Jellyfin);
|
||||
|
||||
// MUSIC
|
||||
var lidarrContent = _lidarrAlbumRepository.GetAll().AsNoTracking().ToList().Where(x => x.FullyAvailable);
|
||||
|
||||
var addedLog = _recentlyAddedLog.GetAll().ToList();
|
||||
|
||||
HashSet<int> addedPlexMovieLogIds, addedEmbyMoviesLogIds, addedJellyfinMoviesLogIds;
|
||||
HashSet<string> addedAlbumLogIds;
|
||||
GetRecentlyAddedMoviesData(addedLog, out addedPlexMovieLogIds, out addedEmbyMoviesLogIds, out addedJellyfinMoviesLogIds, out addedAlbumLogIds);
|
||||
GetRecentlyAddedMoviesData(addedLog, out addedAlbumLogIds);
|
||||
|
||||
// EPISODES
|
||||
var addedPlexEpisodesLogIds =
|
||||
addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode);
|
||||
var addedEmbyEpisodesLogIds =
|
||||
|
@ -145,39 +149,14 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
|
||||
|
||||
// Filter out the ones that we haven't sent yet
|
||||
var plexContentLocalDataset = plexContent.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
||||
var embyContentLocalDataset = embyContent.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
||||
var jellyfinContentLocalDataset = jellyfinContent.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
||||
|
||||
var plexContentMoviesToSend = plexContentLocalDataset.Where(x => !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet();
|
||||
var embyContentMoviesToSend = embyContentLocalDataset.Where(x => !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet();
|
||||
var jellyfinContentMoviesToSend = jellyfinContentLocalDataset.Where(x => !addedJellyfinMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet();
|
||||
var lidarrContentAlbumsToSend = lidarrContent.Where(x => !addedAlbumLogIds.Contains(x.ForeignAlbumId)).ToHashSet();
|
||||
_log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count());
|
||||
_log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count());
|
||||
_log.LogInformation("Jellyfin Movies to send: {0}", jellyfinContentMoviesToSend.Count());
|
||||
_log.LogInformation("Albums to send: {0}", lidarrContentAlbumsToSend.Count());
|
||||
|
||||
// Find the movies that do not yet have MovieDbIds
|
||||
var needsMovieDbPlex = plexContent.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
||||
var needsMovieDbEmby = embyContent.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
||||
var needsMovieDbJellyfin = jellyfinContent.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
||||
var newPlexMovies = await GetMoviesWithoutId(addedPlexMovieLogIds, needsMovieDbPlex);
|
||||
var newEmbyMovies = await GetMoviesWithoutId(addedEmbyMoviesLogIds, needsMovieDbEmby);
|
||||
var newJellyfinMovies = await GetMoviesWithoutId(addedJellyfinMoviesLogIds, needsMovieDbJellyfin);
|
||||
plexContentMoviesToSend = plexContentMoviesToSend.Union(newPlexMovies).ToHashSet();
|
||||
embyContentMoviesToSend = embyContentMoviesToSend.Union(newEmbyMovies).ToHashSet();
|
||||
jellyfinContentMoviesToSend = jellyfinContentMoviesToSend.Union(newJellyfinMovies).ToHashSet();
|
||||
|
||||
plexContentMoviesToSend = plexContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet();
|
||||
embyContentMoviesToSend = embyContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet();
|
||||
jellyfinContentMoviesToSend = jellyfinContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet();
|
||||
|
||||
var plexEpisodesToSend =
|
||||
FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds);
|
||||
var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(),
|
||||
FilterEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds);
|
||||
var embyEpisodesToSend = FilterEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(),
|
||||
addedEmbyEpisodesLogIds);
|
||||
var jellyfinEpisodesToSend = FilterJellyfinEpisodes(_jellyfin.GetAllEpisodes().Include(x => x.Series).AsNoTracking(),
|
||||
var jellyfinEpisodesToSend = FilterEpisodes(_jellyfin.GetAllEpisodes().Include(x => x.Series).AsNoTracking(),
|
||||
addedJellyfinEpisodesLogIds);
|
||||
|
||||
_log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count());
|
||||
|
@ -193,14 +172,36 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
var embym = embyContent.Where(x => x.Type == MediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10);
|
||||
var jellyfinm = jellyfinContent.Where(x => x.Type == MediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10);
|
||||
var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet();
|
||||
var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet();
|
||||
var jellyfint = _jellyfin.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet();
|
||||
var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet();
|
||||
var jellyfint = _jellyfin.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet();
|
||||
var lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet();
|
||||
body = await BuildHtml(plexm, embym, jellyfinm, plext, embyt, jellyfint, lidarr, settings, embySettings, jellyfinSettings, plexSettings);
|
||||
|
||||
var moviesProviders = new List<IQueryable<IMediaServerContent>>() {
|
||||
plexm,
|
||||
embym,
|
||||
jellyfinm
|
||||
};
|
||||
var seriesProviders = new List<IEnumerable<IMediaServerEpisode>>() {
|
||||
plext,
|
||||
embyt,
|
||||
jellyfint
|
||||
};
|
||||
body = await BuildHtml(moviesProviders, seriesProviders, lidarr, settings, embySettings, jellyfinSettings, plexSettings);
|
||||
}
|
||||
else
|
||||
{
|
||||
body = await BuildHtml(plexContentMoviesToSend.AsQueryable(), embyContentMoviesToSend.AsQueryable(), jellyfinContentMoviesToSend.AsQueryable(), plexEpisodesToSend, embyEpisodesToSend, jellyfinEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, jellyfinSettings, plexSettings);
|
||||
var moviesProviders = new List<IQueryable<IMediaServerContent>>() {
|
||||
plexContentMoviesToSend.AsQueryable(),
|
||||
embyContentMoviesToSend.AsQueryable(),
|
||||
jellyfinContentMoviesToSend.AsQueryable()
|
||||
};
|
||||
var seriesProviders = new List<IEnumerable<IMediaServerEpisode>>() {
|
||||
plexEpisodesToSend,
|
||||
embyEpisodesToSend,
|
||||
jellyfinEpisodesToSend
|
||||
};
|
||||
|
||||
body = await BuildHtml(moviesProviders, seriesProviders, lidarrContentAlbumsToSend, settings, embySettings, jellyfinSettings, plexSettings);
|
||||
if (body.IsNullOrEmpty())
|
||||
{
|
||||
return;
|
||||
|
@ -224,7 +225,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
if (!users.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var messageContent = ParseTemplate(template, customization);
|
||||
var email = new NewsletterTemplate();
|
||||
|
@ -376,21 +377,32 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
.SendAsync(NotificationHub.NotificationEvent, "Newsletter Finished");
|
||||
}
|
||||
|
||||
private void GetRecentlyAddedMoviesData(List<RecentlyAddedLog> addedLog, out HashSet<int> addedPlexMovieLogIds, out HashSet<int> addedEmbyMoviesLogIds, out HashSet<int> addedJellyfinMoviesLogIds, out HashSet<string> addedAlbumLogIds)
|
||||
private void GetRecentlyAddedMoviesData(List<RecentlyAddedLog> addedLog, out HashSet<string> addedAlbumLogIds)
|
||||
{
|
||||
var plexParent = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).ToList();
|
||||
addedPlexMovieLogIds = plexParent != null && plexParent.Any() ? (plexParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet<int>()) : new HashSet<int>();
|
||||
|
||||
var embyParent = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent);
|
||||
addedEmbyMoviesLogIds = embyParent != null && embyParent.Any() ? (embyParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet<int>()) : new HashSet<int>();
|
||||
|
||||
var jellyFinParent = addedLog.Where(x => x.Type == RecentlyAddedType.Jellyfin && x.ContentType == ContentType.Parent);
|
||||
addedJellyfinMoviesLogIds = jellyFinParent != null && jellyFinParent.Any() ? (jellyFinParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet<int>()) : new HashSet<int>();
|
||||
|
||||
var lidarrParent = addedLog.Where(x => x.Type == RecentlyAddedType.Lidarr && x.ContentType == ContentType.Album);
|
||||
addedAlbumLogIds = lidarrParent != null && lidarrParent.Any() ? (lidarrParent?.Select(x => x.AlbumId)?.ToHashSet() ?? new HashSet<string>()) : new HashSet<string>();
|
||||
}
|
||||
|
||||
private async Task<HashSet<IMediaServerContent>> getMoviesContent(IQueryable<IMediaServerContent> content, RecentlyAddedType recentlyAddedType)
|
||||
{
|
||||
var localDataset = content.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
||||
// Filter out the ones that we haven't sent yet
|
||||
var addedLog = _recentlyAddedLog.GetAll().ToList();
|
||||
var plexParent = addedLog.Where(x => x.Type == recentlyAddedType
|
||||
&& x.ContentType == ContentType.Parent).ToList();
|
||||
var addedPlexMovieLogIds = plexParent != null && plexParent.Any() ? (plexParent?.Select(x => x.ContentId)?.ToHashSet() ?? new HashSet<int>()) : new HashSet<int>();
|
||||
var plexContentMoviesToSend = localDataset.Where(x => !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))).ToHashSet();
|
||||
_log.LogInformation("Movies to send: {0}", plexContentMoviesToSend.Count());
|
||||
|
||||
// Find the movies that do not yet have MovieDbIds
|
||||
var needsMovieDbPlex = content.Where(x => x.Type == MediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
||||
var newPlexMovies = await GetMoviesWithoutId(addedPlexMovieLogIds, needsMovieDbPlex);
|
||||
plexContentMoviesToSend = plexContentMoviesToSend.Union(newPlexMovies).ToHashSet();
|
||||
|
||||
return plexContentMoviesToSend.DistinctBy(x => x.Id).ToHashSet();
|
||||
|
||||
}
|
||||
|
||||
public static string GenerateUnsubscribeLink(string applicationUrl, string id)
|
||||
{
|
||||
if (!applicationUrl.HasValue() || !id.HasValue())
|
||||
|
@ -406,7 +418,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
return b.ToString();
|
||||
}
|
||||
|
||||
private async Task<HashSet<PlexServerContent>> GetMoviesWithoutId(HashSet<int> addedMovieLogIds, HashSet<PlexServerContent> needsMovieDbPlex)
|
||||
private async Task<HashSet<IMediaServerContent>> GetMoviesWithoutId(HashSet<int> addedMovieLogIds, HashSet<IMediaServerContent> needsMovieDbPlex)
|
||||
{
|
||||
foreach (var movie in needsMovieDbPlex)
|
||||
{
|
||||
|
@ -420,35 +432,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
return result.ToHashSet();
|
||||
}
|
||||
|
||||
private async Task<HashSet<EmbyContent>> GetMoviesWithoutId(HashSet<int> addedMovieLogIds, HashSet<EmbyContent> needsMovieDbPlex)
|
||||
{
|
||||
foreach (var movie in needsMovieDbPlex)
|
||||
{
|
||||
var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true);
|
||||
movie.TheMovieDbId = id.ToString();
|
||||
}
|
||||
|
||||
var result = needsMovieDbPlex.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId)));
|
||||
await UpdateTheMovieDbId(result);
|
||||
// Filter them out now
|
||||
return result.ToHashSet();
|
||||
}
|
||||
|
||||
private async Task<HashSet<JellyfinContent>> GetMoviesWithoutId(HashSet<int> addedMovieLogIds, HashSet<JellyfinContent> needsMovieDbJellyfin)
|
||||
{
|
||||
foreach (var movie in needsMovieDbJellyfin)
|
||||
{
|
||||
var id = await _refreshMetadata.GetTheMovieDbId(false, true, null, movie.ImdbId, movie.Title, true);
|
||||
movie.TheMovieDbId = id.ToString();
|
||||
}
|
||||
|
||||
var result = needsMovieDbJellyfin.Where(x => x.HasTheMovieDb && !addedMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId)));
|
||||
await UpdateTheMovieDbId(result);
|
||||
// Filter them out now
|
||||
return result.ToHashSet();
|
||||
}
|
||||
|
||||
private async Task UpdateTheMovieDbId(IEnumerable<PlexServerContent> content)
|
||||
private async Task UpdateTheMovieDbId(IEnumerable<IMediaServerContent> content)
|
||||
{
|
||||
foreach (var movie in content)
|
||||
{
|
||||
|
@ -467,79 +451,15 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
await _plex.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private async Task UpdateTheMovieDbId(IEnumerable<EmbyContent> content)
|
||||
{
|
||||
foreach (var movie in content)
|
||||
{
|
||||
if (!movie.HasTheMovieDb)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var entity = await _emby.Find(movie.Id);
|
||||
entity.TheMovieDbId = movie.TheMovieDbId;
|
||||
_emby.UpdateWithoutSave(entity);
|
||||
}
|
||||
await _plex.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private async Task UpdateTheMovieDbId(IEnumerable<JellyfinContent> content)
|
||||
{
|
||||
foreach (var movie in content)
|
||||
{
|
||||
if (!movie.HasTheMovieDb)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var entity = await _jellyfin.Find(movie.Id);
|
||||
entity.TheMovieDbId = movie.TheMovieDbId;
|
||||
_jellyfin.UpdateWithoutSave(entity);
|
||||
}
|
||||
await _plex.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task Execute(IJobExecutionContext job)
|
||||
{
|
||||
var newsletterSettings = await _newsletterSettings.GetSettingsAsync();
|
||||
await Start(newsletterSettings, false);
|
||||
}
|
||||
|
||||
private HashSet<PlexEpisode> FilterPlexEpisodes(IEnumerable<PlexEpisode> source, IEnumerable<RecentlyAddedLog> recentlyAdded)
|
||||
private HashSet<IMediaServerEpisode> FilterEpisodes(IEnumerable<IMediaServerEpisode> source, IEnumerable<RecentlyAddedLog> recentlyAdded)
|
||||
{
|
||||
var itemsToReturn = new HashSet<PlexEpisode>();
|
||||
foreach (var ep in source.Where(x => x.Series.HasTvDb))
|
||||
{
|
||||
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
|
||||
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
itemsToReturn.Add(ep);
|
||||
}
|
||||
|
||||
return itemsToReturn;
|
||||
}
|
||||
|
||||
private HashSet<EmbyEpisode> FilterEmbyEpisodes(IEnumerable<EmbyEpisode> source, IEnumerable<RecentlyAddedLog> recentlyAdded)
|
||||
{
|
||||
var itemsToReturn = new HashSet<EmbyEpisode>();
|
||||
foreach (var ep in source.Where(x => x.Series.HasTvDb))
|
||||
{
|
||||
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
|
||||
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
itemsToReturn.Add(ep);
|
||||
}
|
||||
|
||||
return itemsToReturn;
|
||||
}
|
||||
|
||||
private HashSet<JellyfinEpisode> FilterJellyfinEpisodes(IEnumerable<JellyfinEpisode> source, IEnumerable<RecentlyAddedLog> recentlyAdded)
|
||||
{
|
||||
var itemsToReturn = new HashSet<JellyfinEpisode>();
|
||||
var itemsToReturn = new HashSet<IMediaServerEpisode>();
|
||||
foreach (var ep in source.Where(x => x.Series.HasTvDb))
|
||||
{
|
||||
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
|
||||
|
@ -564,17 +484,14 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
return resolver.ParseMessage(template, curlys);
|
||||
}
|
||||
|
||||
private async Task<string> BuildHtml(IQueryable<PlexServerContent> plexContentToSend, IQueryable<EmbyContent> embyContentToSend, IQueryable<JellyfinContent> jellyfinContentToSend,
|
||||
HashSet<PlexEpisode> plexEpisodes, HashSet<EmbyEpisode> embyEp, HashSet<JellyfinEpisode> jellyfinEp, HashSet<LidarrAlbumCache> albums, NewsletterSettings settings, EmbySettings embySettings, JellyfinSettings jellyfinSettings,
|
||||
private async Task<string> BuildHtml(ICollection<IQueryable<IMediaServerContent>> contentToSend,
|
||||
ICollection<IEnumerable<IMediaServerEpisode>> episodes, HashSet<LidarrAlbumCache> albums, NewsletterSettings settings, EmbySettings embySettings, JellyfinSettings jellyfinSettings,
|
||||
PlexSettings plexSettings)
|
||||
{
|
||||
var ombiSettings = await _ombiSettings.GetSettingsAsync();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
var plexMovies = plexContentToSend.Where(x => x.Type == MediaType.Movie);
|
||||
var embyMovies = embyContentToSend.Where(x => x.Type == MediaType.Movie);
|
||||
var jellyfinMovies = jellyfinContentToSend.Where(x => x.Type == MediaType.Movie);
|
||||
if ((plexMovies.Any() || embyMovies.Any() || jellyfinMovies.Any()) && !settings.DisableMovies)
|
||||
if (!settings.DisableMovies)
|
||||
{
|
||||
sb.Append("<h1 style=\"text-align: center; max-width: 1042px;\">New Movies</h1><br /><br />");
|
||||
sb.Append(
|
||||
|
@ -583,21 +500,10 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
sb.Append("<td style=\"font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 14px; vertical-align: top; \">");
|
||||
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
|
||||
sb.Append("<tr>");
|
||||
if (plexSettings.Enable)
|
||||
foreach (var mediaServerContent in contentToSend)
|
||||
{
|
||||
await ProcessPlexMovies(plexMovies, sb, ombiSettings.DefaultLanguageCode, plexSettings.Servers.FirstOrDefault().ServerHostname ?? string.Empty);
|
||||
await ProcessMovies(mediaServerContent, sb, ombiSettings.DefaultLanguageCode, /*plexSettings.Servers?.FirstOrDefault()?.ServerHostname ?? */ string.Empty);
|
||||
}
|
||||
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty);
|
||||
}
|
||||
|
||||
if (jellyfinSettings.Enable)
|
||||
{
|
||||
await ProcessJellyfinMovies(jellyfinMovies, sb, ombiSettings.DefaultLanguageCode, jellyfinSettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty);
|
||||
}
|
||||
|
||||
sb.Append("</tr>");
|
||||
sb.Append("</table>");
|
||||
sb.Append("</td>");
|
||||
|
@ -605,7 +511,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
sb.Append("</table>");
|
||||
}
|
||||
|
||||
if ((plexEpisodes.Any() || embyEp.Any() || jellyfinEp.Any()) && !settings.DisableTv)
|
||||
if (!settings.DisableTv)
|
||||
{
|
||||
sb.Append("<br /><br /><h1 style=\"text-align: center; max-width: 1042px;\">New TV</h1><br /><br />");
|
||||
sb.Append(
|
||||
|
@ -614,21 +520,10 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
sb.Append("<td style=\"font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 14px; vertical-align: top; \">");
|
||||
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
|
||||
sb.Append("<tr>");
|
||||
if (plexSettings.Enable)
|
||||
foreach (var mediaServerContent in episodes)
|
||||
{
|
||||
await ProcessPlexTv(plexEpisodes, sb, ombiSettings.DefaultLanguageCode, plexSettings.Servers.FirstOrDefault().ServerHostname ?? string.Empty);
|
||||
await ProcessTv(mediaServerContent, sb, ombiSettings.DefaultLanguageCode, /* plexSettings.Servers.FirstOrDefault()?.ServerHostname ?? */ string.Empty);
|
||||
}
|
||||
|
||||
if (embySettings.Enable)
|
||||
{
|
||||
await ProcessEmbyTv(embyEp, sb, ombiSettings.DefaultLanguageCode, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty);
|
||||
}
|
||||
|
||||
if (jellyfinSettings.Enable)
|
||||
{
|
||||
await ProcessJellyfinTv(jellyfinEp, sb, ombiSettings.DefaultLanguageCode, jellyfinSettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty);
|
||||
}
|
||||
|
||||
sb.Append("</tr>");
|
||||
sb.Append("</table>");
|
||||
sb.Append("</td>");
|
||||
|
@ -657,7 +552,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
private async Task ProcessPlexMovies(IQueryable<PlexServerContent> plexContentToSend, StringBuilder sb, string defaultLanguageCode, string mediaServerUrl)
|
||||
private async Task ProcessMovies(IQueryable<IMediaServerContent> plexContentToSend, StringBuilder sb, string defaultLanguageCode, string mediaServerUrl)
|
||||
{
|
||||
int count = 0;
|
||||
var ordered = plexContentToSend.OrderByDescending(x => x.AddedAt);
|
||||
|
@ -681,7 +576,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.LogError(e, "Error when Processing Plex Movies {0}", info.Title);
|
||||
_log.LogError(e, "Error when Processing Movies {0}", info.Title);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -731,112 +626,6 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
}
|
||||
}
|
||||
|
||||
private async Task ProcessEmbyMovies(IQueryable<EmbyContent> embyContent, StringBuilder sb, string defaultLangaugeCode, string customUrl)
|
||||
{
|
||||
int count = 0;
|
||||
var ordered = embyContent.OrderByDescending(x => x.AddedAt);
|
||||
foreach (var content in ordered)
|
||||
{
|
||||
var theMovieDbId = content.TheMovieDbId;
|
||||
if (!content.TheMovieDbId.HasValue())
|
||||
{
|
||||
var imdbId = content.ImdbId;
|
||||
var findResult = await _movieApi.Find(imdbId, ExternalSource.imdb_id);
|
||||
var result = findResult.movie_results?.FirstOrDefault();
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
theMovieDbId = result.id.ToString();
|
||||
}
|
||||
|
||||
var mediaurl = content.Url;
|
||||
if (customUrl.HasValue())
|
||||
{
|
||||
mediaurl = customUrl;
|
||||
}
|
||||
var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId), defaultLangaugeCode);
|
||||
if (info == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
CreateMovieHtmlContent(sb, info, mediaurl);
|
||||
count += 1;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.LogError(e, "Error when processing Emby Movies {0}", info.Title);
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndLoopHtml(sb);
|
||||
}
|
||||
|
||||
if (count == 2)
|
||||
{
|
||||
count = 0;
|
||||
sb.Append("</tr>");
|
||||
sb.Append("<tr>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessJellyfinMovies(IQueryable<JellyfinContent> embyContent, StringBuilder sb, string defaultLangaugeCode, string customUrl)
|
||||
{
|
||||
int count = 0;
|
||||
var ordered = embyContent.OrderByDescending(x => x.AddedAt);
|
||||
foreach (var content in ordered)
|
||||
{
|
||||
var theMovieDbId = content.TheMovieDbId;
|
||||
if (!content.TheMovieDbId.HasValue())
|
||||
{
|
||||
var imdbId = content.ImdbId;
|
||||
var findResult = await _movieApi.Find(imdbId, ExternalSource.imdb_id);
|
||||
var result = findResult.movie_results?.FirstOrDefault();
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
theMovieDbId = result.id.ToString();
|
||||
}
|
||||
|
||||
var mediaurl = content.Url;
|
||||
if (customUrl.HasValue())
|
||||
{
|
||||
mediaurl = customUrl;
|
||||
}
|
||||
var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId), defaultLangaugeCode);
|
||||
if (info == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
CreateMovieHtmlContent(sb, info, mediaurl);
|
||||
count += 1;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.LogError(e, "Error when processing Jellyfin Movies {0}", info.Title);
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndLoopHtml(sb);
|
||||
}
|
||||
|
||||
if (count == 2)
|
||||
{
|
||||
count = 0;
|
||||
sb.Append("</tr>");
|
||||
sb.Append("<tr>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateMovieHtmlContent(StringBuilder sb, MovieResponseDto info, string mediaurl)
|
||||
{
|
||||
AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/{info.BackdropPath}");
|
||||
|
@ -909,24 +698,23 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
AddGenres(sb, $"Type: {info.albumType}");
|
||||
}
|
||||
|
||||
private async Task ProcessPlexTv(HashSet<PlexEpisode> plexContent, StringBuilder sb, string languageCode, string serverHostname)
|
||||
private async Task ProcessTv(IEnumerable<IMediaServerEpisode> episodes, StringBuilder sb, string languageCode, string serverHostname)
|
||||
{
|
||||
var series = new List<PlexServerContent>();
|
||||
foreach (var plexEpisode in plexContent)
|
||||
var series = new List<IMediaServerContent>();
|
||||
foreach (var episode in episodes)
|
||||
{
|
||||
var alreadyAdded = series.FirstOrDefault(x => x.Key == plexEpisode.PlexSeries.Key);
|
||||
if (alreadyAdded != null)
|
||||
var existingSeries = episode.SeriesIsIn(series);
|
||||
if (existingSeries != null)
|
||||
{
|
||||
var episodeExists = alreadyAdded.PlexEpisodes.Any(x => x.Key == plexEpisode.Key);
|
||||
if (!episodeExists)
|
||||
if (!episode.IsIn(existingSeries))
|
||||
{
|
||||
alreadyAdded.Episodes.Add(plexEpisode);
|
||||
existingSeries.Episodes.Add(episode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plexEpisode.Series.Episodes = new List<IMediaServerEpisode> { plexEpisode };
|
||||
series.Add(plexEpisode.PlexSeries);
|
||||
episode.Series.Episodes = new List<IMediaServerEpisode> { episode };
|
||||
series.Add(episode.Series);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1035,214 +823,6 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task ProcessEmbyTv(HashSet<EmbyEpisode> embyContent, StringBuilder sb, string languageCode, string serverUrl)
|
||||
{
|
||||
var series = new List<EmbyContent>();
|
||||
foreach (var episode in embyContent)
|
||||
{
|
||||
var alreadyAdded = series.FirstOrDefault(x => x.EmbyId == episode.EmbySeries.EmbyId);
|
||||
if (alreadyAdded != null)
|
||||
{
|
||||
alreadyAdded.Episodes.Add(episode);
|
||||
}
|
||||
else
|
||||
{
|
||||
episode.Series.Episodes = new List<IMediaServerEpisode>
|
||||
{
|
||||
episode
|
||||
};
|
||||
series.Add(episode.EmbySeries);
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
var orderedTv = series.OrderByDescending(x => x.AddedAt);
|
||||
foreach (var t in orderedTv)
|
||||
{
|
||||
if (!t.TvDbId.HasValue())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int.TryParse(t.TvDbId, out var tvdbId);
|
||||
var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId);
|
||||
if (info == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var banner = info.image?.original;
|
||||
if (!string.IsNullOrEmpty(banner))
|
||||
{
|
||||
banner = banner.ToHttpsUrl(); // Always use the Https banners
|
||||
}
|
||||
|
||||
var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode);
|
||||
if (tvInfo != null && tvInfo.backdrop_path.HasValue())
|
||||
{
|
||||
|
||||
AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/");
|
||||
}
|
||||
AddPosterInsideTable(sb, banner);
|
||||
AddMediaServerUrl(sb, serverUrl.HasValue() ? serverUrl : t.Url, banner);
|
||||
AddInfoTable(sb);
|
||||
|
||||
AddTvTitle(sb, info, tvInfo);
|
||||
|
||||
// Group by the season number
|
||||
var results = t.Episodes?.GroupBy(p => p.SeasonNumber,
|
||||
(key, g) => new
|
||||
{
|
||||
SeasonNumber = key,
|
||||
Episodes = g.ToList(),
|
||||
EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault()
|
||||
}
|
||||
);
|
||||
|
||||
// Group the episodes
|
||||
var finalsb = new StringBuilder();
|
||||
foreach (var epInformation in results.OrderBy(x => x.SeasonNumber))
|
||||
{
|
||||
var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList();
|
||||
var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber));
|
||||
var episodeAirDate = epInformation.EpisodeAirDate;
|
||||
finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}");
|
||||
finalsb.Append("<br />");
|
||||
}
|
||||
|
||||
AddTvEpisodesSummaryGenres(sb, finalsb.ToString(), tvInfo);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.LogError(e, "Error when processing Emby TV {0}", t.Title);
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndLoopHtml(sb);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
if (count == 2)
|
||||
{
|
||||
count = 0;
|
||||
sb.Append("</tr>");
|
||||
sb.Append("<tr>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessJellyfinTv(HashSet<JellyfinEpisode> jellyfinContent, StringBuilder sb, string languageCode, string serverUrl)
|
||||
{
|
||||
var series = new List<JellyfinContent>();
|
||||
foreach (var episode in jellyfinContent)
|
||||
{
|
||||
var alreadyAdded = series.FirstOrDefault(x => x.JellyfinId == episode.JellyfinSeries.JellyfinId);
|
||||
if (alreadyAdded != null)
|
||||
{
|
||||
alreadyAdded.Episodes.Add(episode);
|
||||
}
|
||||
else
|
||||
{
|
||||
episode.Series.Episodes = new List<IMediaServerEpisode>
|
||||
{
|
||||
episode
|
||||
};
|
||||
series.Add(episode.JellyfinSeries);
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
var orderedTv = series.OrderByDescending(x => x.AddedAt);
|
||||
foreach (var t in orderedTv)
|
||||
{
|
||||
if (!t.TvDbId.HasValue())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int.TryParse(t.TvDbId, out var tvdbId);
|
||||
var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId);
|
||||
if (info == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var banner = info.image?.original;
|
||||
if (!string.IsNullOrEmpty(banner))
|
||||
{
|
||||
banner = banner.ToHttpsUrl(); // Always use the Https banners
|
||||
}
|
||||
|
||||
var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId, languageCode);
|
||||
if (tvInfo != null && tvInfo.backdrop_path.HasValue())
|
||||
{
|
||||
|
||||
AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w500{tvInfo.backdrop_path}");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/");
|
||||
}
|
||||
AddPosterInsideTable(sb, banner);
|
||||
AddMediaServerUrl(sb, serverUrl.HasValue() ? serverUrl : t.Url, banner);
|
||||
AddInfoTable(sb);
|
||||
|
||||
AddTvTitle(sb, info, tvInfo);
|
||||
|
||||
// Group by the season number
|
||||
var results = t.Episodes?.GroupBy(p => p.SeasonNumber,
|
||||
(key, g) => new
|
||||
{
|
||||
SeasonNumber = key,
|
||||
Episodes = g.ToList(),
|
||||
EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault()
|
||||
}
|
||||
);
|
||||
|
||||
// Group the episodes
|
||||
var finalsb = new StringBuilder();
|
||||
foreach (var epInformation in results.OrderBy(x => x.SeasonNumber))
|
||||
{
|
||||
var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList();
|
||||
var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber));
|
||||
var episodeAirDate = epInformation.EpisodeAirDate;
|
||||
finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}");
|
||||
finalsb.Append("<br />");
|
||||
}
|
||||
|
||||
AddTvEpisodesSummaryGenres(sb, finalsb.ToString(), tvInfo);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.LogError(e, "Error when processing Jellyfin TV {0}", t.Title);
|
||||
}
|
||||
finally
|
||||
{
|
||||
EndLoopHtml(sb);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
if (count == 2)
|
||||
{
|
||||
count = 0;
|
||||
sb.Append("</tr>");
|
||||
sb.Append("<tr>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddTvTitle(StringBuilder sb, Api.TvMaze.Models.TvMazeShow info, TvInfo tvInfo)
|
||||
{
|
||||
var title = "";
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
|
||||
var tvDbId = child.ParentRequest.TvDbId;
|
||||
var imdbId = child.ParentRequest.ImdbId;
|
||||
IQueryable<PlexEpisode> seriesEpisodes = null;
|
||||
IQueryable<IMediaServerEpisode> seriesEpisodes = null;
|
||||
if (useImdb)
|
||||
{
|
||||
seriesEpisodes = plexEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString());
|
||||
|
@ -105,8 +105,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
{
|
||||
// Let's try and match the series by name
|
||||
seriesEpisodes = plexEpisodes.Where(x =>
|
||||
x.Series.Title == child.Title &&
|
||||
x.PlexSeries.ReleaseYear == child.ParentRequest.ReleaseDate.Year.ToString());
|
||||
x.Series.Title == child.Title);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
await Repo.SaveChangesAsync();
|
||||
if (content.Metadata != null)
|
||||
{
|
||||
var episodesAdded = await EpisodeSync.ProcessEpsiodes(content.Metadata, allEps);
|
||||
var episodesAdded = await EpisodeSync.ProcessEpsiodes(content.Metadata, (IQueryable<PlexEpisode>)allEps);
|
||||
episodesProcessed.AddRange(episodesAdded.Select(x => x.Id));
|
||||
}
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
Repo.DeleteWithoutSave(existingContent);
|
||||
|
||||
// Because we have changed the rating key, we need to change all children too
|
||||
var episodeToChange = Repo.GetAllEpisodes().Where(x => x.GrandparentKey == oldKey);
|
||||
var episodeToChange = Repo.GetAllEpisodes().Cast<PlexEpisode>().Where(x => x.GrandparentKey == oldKey);
|
||||
if (episodeToChange.Any())
|
||||
{
|
||||
foreach (var e in episodeToChange)
|
||||
|
|
|
@ -113,7 +113,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
|||
{
|
||||
var currentPosition = 0;
|
||||
var resultCount = settings.EpisodeBatchSize == 0 ? 150 : settings.EpisodeBatchSize;
|
||||
var currentEpisodes = _repo.GetAllEpisodes();
|
||||
var currentEpisodes = _repo.GetAllEpisodes().Cast<PlexEpisode>();
|
||||
var episodes = await _api.GetAllEpisodes(settings.PlexAuthToken, settings.FullUri, section.key, currentPosition, resultCount);
|
||||
_log.LogInformation(LoggingEvents.PlexEpisodeCacher, $"Total Epsiodes found for {episodes.MediaContainer.librarySectionTitle} = {episodes.MediaContainer.totalSize}");
|
||||
|
||||
|
|
|
@ -26,8 +26,9 @@
|
|||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ombi.Store.Entities
|
||||
{
|
||||
|
@ -50,5 +51,16 @@ namespace Ombi.Store.Entities
|
|||
get => (EmbyContent)Series;
|
||||
set => Series = value;
|
||||
}
|
||||
|
||||
public override IMediaServerContent SeriesIsIn(List<IMediaServerContent> content)
|
||||
{
|
||||
return content.Cast<EmbyContent>().FirstOrDefault(
|
||||
x => x.EmbyId == this.EmbySeries.EmbyId);
|
||||
}
|
||||
public override bool IsIn(IMediaServerContent content)
|
||||
{
|
||||
return content.Episodes.Cast<EmbyEpisode>().Any(x => x.EmbyId == this.EmbyId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Ombi.Store.Repository;
|
||||
|
||||
namespace Ombi.Store.Entities
|
||||
{
|
||||
public interface IMediaServerContent
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
public string TvDbId { get; set; }
|
||||
|
@ -42,6 +44,8 @@ namespace Ombi.Store.Entities
|
|||
|
||||
|
||||
public IMediaServerContent Series { get; set; }
|
||||
public IMediaServerContent SeriesIsIn(List<IMediaServerContent> content);
|
||||
public bool IsIn(IMediaServerContent content);
|
||||
}
|
||||
|
||||
public enum MediaType
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
|
||||
namespace Ombi.Store.Entities
|
||||
|
@ -50,5 +52,15 @@ namespace Ombi.Store.Entities
|
|||
get => (JellyfinContent)Series;
|
||||
set => Series = value;
|
||||
}
|
||||
|
||||
public override IMediaServerContent SeriesIsIn(List<IMediaServerContent> content)
|
||||
{
|
||||
return content.Cast<JellyfinContent>().FirstOrDefault(
|
||||
x => x.JellyfinId == this.JellyfinSeries.JellyfinId);
|
||||
}
|
||||
public override bool IsIn(IMediaServerContent content)
|
||||
{
|
||||
return content.Episodes.Cast<JellyfinEpisode>().Any(x => x.JellyfinId == this.JellyfinId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,5 +35,8 @@ namespace Ombi.Store.Entities
|
|||
public string Title { get; set; }
|
||||
|
||||
public IMediaServerContent Series { get; set; }
|
||||
|
||||
public abstract IMediaServerContent SeriesIsIn(List<IMediaServerContent> content);
|
||||
public abstract bool IsIn(IMediaServerContent content);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ombi.Store.Entities
|
||||
{
|
||||
|
@ -20,5 +22,17 @@ namespace Ombi.Store.Entities
|
|||
get => (PlexServerContent)Series;
|
||||
set => Series = value;
|
||||
}
|
||||
|
||||
public override IMediaServerContent SeriesIsIn(List<IMediaServerContent> content)
|
||||
{
|
||||
return content.Cast<PlexServerContent>().FirstOrDefault(
|
||||
x => x.Key == this.PlexSeries.Key);
|
||||
}
|
||||
|
||||
public override bool IsIn(IMediaServerContent content)
|
||||
{
|
||||
return content.Episodes.Cast<PlexEpisode>().Any(x => x.Key == this.Key);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -69,20 +69,20 @@ namespace Ombi.Store.Repository
|
|||
return await Db.EmbyContent./*Include(x => x.Seasons).*/FirstOrDefaultAsync(x => x.EmbyId == embyId);
|
||||
}
|
||||
|
||||
public async Task Update(EmbyContent existingContent)
|
||||
public async Task Update(IMediaServerContent existingContent)
|
||||
{
|
||||
Db.EmbyContent.Update(existingContent);
|
||||
Db.EmbyContent.Update((EmbyContent)existingContent);
|
||||
await InternalSaveChanges();
|
||||
}
|
||||
|
||||
public IQueryable<EmbyEpisode> GetAllEpisodes()
|
||||
public IQueryable<IMediaServerEpisode> GetAllEpisodes()
|
||||
{
|
||||
return Db.EmbyEpisode.AsQueryable();
|
||||
}
|
||||
|
||||
public async Task<EmbyEpisode> Add(EmbyEpisode content)
|
||||
public async Task<IMediaServerEpisode> Add(IMediaServerEpisode content)
|
||||
{
|
||||
await Db.EmbyEpisode.AddAsync(content);
|
||||
await Db.EmbyEpisode.AddAsync((EmbyEpisode)content);
|
||||
await InternalSaveChanges();
|
||||
return content;
|
||||
}
|
||||
|
@ -91,15 +91,15 @@ namespace Ombi.Store.Repository
|
|||
return await Db.EmbyEpisode.FirstOrDefaultAsync(x => x.EmbyId == key);
|
||||
}
|
||||
|
||||
public async Task AddRange(IEnumerable<EmbyEpisode> content)
|
||||
public async Task AddRange(IEnumerable<IMediaServerEpisode> content)
|
||||
{
|
||||
Db.EmbyEpisode.AddRange(content);
|
||||
Db.EmbyEpisode.AddRange((EmbyEpisode)content);
|
||||
await InternalSaveChanges();
|
||||
}
|
||||
|
||||
public void UpdateWithoutSave(EmbyContent existingContent)
|
||||
public void UpdateWithoutSave(IMediaServerContent existingContent)
|
||||
{
|
||||
Db.EmbyContent.Update(existingContent);
|
||||
Db.EmbyContent.Update((EmbyContent)existingContent);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,13 +5,8 @@ using Ombi.Store.Entities;
|
|||
|
||||
namespace Ombi.Store.Repository
|
||||
{
|
||||
public interface IMediaServerContentRepository<Content, Episode> : IExternalRepository<Content> where Content : Entity
|
||||
public interface IMediaServerContentRepository<Content, Episode> : IExternalRepository<Content>, IMediaServerContentRepositoryLight
|
||||
where Content : Entity
|
||||
{
|
||||
Task Update(Content existingContent);
|
||||
IQueryable<Episode> GetAllEpisodes();
|
||||
Task<Episode> Add(Episode content);
|
||||
Task AddRange(IEnumerable<Episode> content);
|
||||
|
||||
void UpdateWithoutSave(Content existingContent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Store.Repository
|
||||
{
|
||||
public interface IMediaServerContentRepositoryLight
|
||||
{
|
||||
Task Update(IMediaServerContent existingContent);
|
||||
IQueryable<IMediaServerEpisode> GetAllEpisodes();
|
||||
Task<IMediaServerEpisode> Add(IMediaServerEpisode content);
|
||||
Task AddRange(IEnumerable<IMediaServerEpisode> content);
|
||||
void UpdateWithoutSave(IMediaServerContent existingContent);
|
||||
}
|
||||
}
|
|
@ -69,20 +69,20 @@ namespace Ombi.Store.Repository
|
|||
return await Db.JellyfinContent./*Include(x => x.Seasons).*/FirstOrDefaultAsync(x => x.JellyfinId == jellyfinId);
|
||||
}
|
||||
|
||||
public async Task Update(JellyfinContent existingContent)
|
||||
public async Task Update(IMediaServerContent existingContent)
|
||||
{
|
||||
Db.JellyfinContent.Update(existingContent);
|
||||
Db.JellyfinContent.Update((JellyfinContent)existingContent);
|
||||
await InternalSaveChanges();
|
||||
}
|
||||
|
||||
public IQueryable<JellyfinEpisode> GetAllEpisodes()
|
||||
public IQueryable<IMediaServerEpisode> GetAllEpisodes()
|
||||
{
|
||||
return Db.JellyfinEpisode.AsQueryable();
|
||||
}
|
||||
|
||||
public async Task<JellyfinEpisode> Add(JellyfinEpisode content)
|
||||
public async Task<IMediaServerEpisode> Add(IMediaServerEpisode content)
|
||||
{
|
||||
await Db.JellyfinEpisode.AddAsync(content);
|
||||
await Db.JellyfinEpisode.AddAsync((JellyfinEpisode)content);
|
||||
await InternalSaveChanges();
|
||||
return content;
|
||||
}
|
||||
|
@ -91,15 +91,15 @@ namespace Ombi.Store.Repository
|
|||
return await Db.JellyfinEpisode.FirstOrDefaultAsync(x => x.JellyfinId == key);
|
||||
}
|
||||
|
||||
public async Task AddRange(IEnumerable<JellyfinEpisode> content)
|
||||
public async Task AddRange(IEnumerable<IMediaServerEpisode> content)
|
||||
{
|
||||
Db.JellyfinEpisode.AddRange(content);
|
||||
Db.JellyfinEpisode.AddRange((JellyfinEpisode)content);
|
||||
await InternalSaveChanges();
|
||||
}
|
||||
|
||||
public void UpdateWithoutSave(JellyfinContent existingContent)
|
||||
public void UpdateWithoutSave(IMediaServerContent existingContent)
|
||||
{
|
||||
Db.JellyfinContent.Update(existingContent);
|
||||
Db.JellyfinContent.Update((JellyfinContent)existingContent);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -114,14 +114,14 @@ namespace Ombi.Store.Repository
|
|||
.FirstOrDefaultAsync(predicate);
|
||||
}
|
||||
|
||||
public async Task Update(PlexServerContent existingContent)
|
||||
public async Task Update(IMediaServerContent existingContent)
|
||||
{
|
||||
Db.PlexServerContent.Update(existingContent);
|
||||
Db.PlexServerContent.Update((PlexServerContent)existingContent);
|
||||
await InternalSaveChanges();
|
||||
}
|
||||
public void UpdateWithoutSave(PlexServerContent existingContent)
|
||||
public void UpdateWithoutSave(IMediaServerContent existingContent)
|
||||
{
|
||||
Db.PlexServerContent.Update(existingContent);
|
||||
Db.PlexServerContent.Update((PlexServerContent)existingContent);
|
||||
}
|
||||
|
||||
public async Task UpdateRange(IEnumerable<PlexServerContent> existingContent)
|
||||
|
@ -130,7 +130,7 @@ namespace Ombi.Store.Repository
|
|||
await InternalSaveChanges();
|
||||
}
|
||||
|
||||
public IQueryable<PlexEpisode> GetAllEpisodes()
|
||||
public IQueryable<IMediaServerEpisode> GetAllEpisodes()
|
||||
{
|
||||
return Db.PlexEpisode.Include(x => x.Series).AsQueryable();
|
||||
}
|
||||
|
@ -145,9 +145,9 @@ namespace Ombi.Store.Repository
|
|||
Db.PlexEpisode.Remove(content);
|
||||
}
|
||||
|
||||
public async Task<PlexEpisode> Add(PlexEpisode content)
|
||||
public async Task<IMediaServerEpisode> Add(IMediaServerEpisode content)
|
||||
{
|
||||
await Db.PlexEpisode.AddAsync(content);
|
||||
await Db.PlexEpisode.AddAsync((PlexEpisode)content);
|
||||
await InternalSaveChanges();
|
||||
return content;
|
||||
}
|
||||
|
@ -162,9 +162,9 @@ namespace Ombi.Store.Repository
|
|||
{
|
||||
return await Db.PlexEpisode.FirstOrDefaultAsync(x => x.Key == key);
|
||||
}
|
||||
public async Task AddRange(IEnumerable<PlexEpisode> content)
|
||||
public async Task AddRange(IEnumerable<IMediaServerEpisode> content)
|
||||
{
|
||||
Db.PlexEpisode.AddRange(content);
|
||||
Db.PlexEpisode.AddRange((PlexEpisode)content);
|
||||
await InternalSaveChanges();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue