|
|
|
@ -38,16 +38,17 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
{
|
|
|
|
|
public class NewsletterJob : HtmlTemplateGenerator, INewsletterJob
|
|
|
|
|
{
|
|
|
|
|
public NewsletterJob(IPlexContentRepository plex, IEmbyContentRepository emby, IRepository<RecentlyAddedLog> addedLog,
|
|
|
|
|
public NewsletterJob(IPlexContentRepository plex, IEmbyContentRepository emby, IJellyfinContentRepository jellyfin, IRepository<RecentlyAddedLog> addedLog,
|
|
|
|
|
IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService<CustomizationSettings> custom,
|
|
|
|
|
ISettingsService<EmailNotificationSettings> emailSettings, INotificationTemplatesRepository templateRepo,
|
|
|
|
|
UserManager<OmbiUser> um, ISettingsService<NewsletterSettings> newsletter, ILogger<NewsletterJob> log,
|
|
|
|
|
ILidarrApi lidarrApi, IExternalRepository<LidarrAlbumCache> albumCache, ISettingsService<LidarrSettings> lidarrSettings,
|
|
|
|
|
ISettingsService<OmbiSettings> ombiSettings, ISettingsService<PlexSettings> plexSettings, ISettingsService<EmbySettings> embySettings
|
|
|
|
|
, IHubContext<NotificationHub> notification, IRefreshMetadata refreshMetadata)
|
|
|
|
|
ISettingsService<OmbiSettings> ombiSettings, ISettingsService<PlexSettings> plexSettings, ISettingsService<EmbySettings> embySettings, ISettingsService<JellyfinSettings> jellyfinSettings,
|
|
|
|
|
IHubContext<NotificationHub> notification, IRefreshMetadata refreshMetadata)
|
|
|
|
|
{
|
|
|
|
|
_plex = plex;
|
|
|
|
|
_emby = emby;
|
|
|
|
|
_jellyfin = jellyfin;
|
|
|
|
|
_recentlyAddedLog = addedLog;
|
|
|
|
|
_movieApi = movieApi;
|
|
|
|
|
_tvApi = tvApi;
|
|
|
|
@ -64,6 +65,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
_ombiSettings = ombiSettings;
|
|
|
|
|
_plexSettings = plexSettings;
|
|
|
|
|
_embySettings = embySettings;
|
|
|
|
|
_jellyfinSettings = jellyfinSettings;
|
|
|
|
|
_notification = notification;
|
|
|
|
|
_ombiSettings.ClearCache();
|
|
|
|
|
_plexSettings.ClearCache();
|
|
|
|
@ -74,6 +76,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
|
|
|
|
|
private readonly IPlexContentRepository _plex;
|
|
|
|
|
private readonly IEmbyContentRepository _emby;
|
|
|
|
|
private readonly IJellyfinContentRepository _jellyfin;
|
|
|
|
|
private readonly IRepository<RecentlyAddedLog> _recentlyAddedLog;
|
|
|
|
|
private readonly IMovieDbApi _movieApi;
|
|
|
|
|
private readonly ITvMazeApi _tvApi;
|
|
|
|
@ -90,6 +93,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
private readonly ISettingsService<LidarrSettings> _lidarrSettings;
|
|
|
|
|
private readonly ISettingsService<PlexSettings> _plexSettings;
|
|
|
|
|
private readonly ISettingsService<EmbySettings> _embySettings;
|
|
|
|
|
private readonly ISettingsService<JellyfinSettings> _jellyfinSettings;
|
|
|
|
|
private readonly IHubContext<NotificationHub> _notification;
|
|
|
|
|
private readonly IRefreshMetadata _refreshMetadata;
|
|
|
|
|
|
|
|
|
@ -123,36 +127,46 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
// 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();
|
|
|
|
|
var lidarrContent = _lidarrAlbumRepository.GetAll().AsNoTracking().ToList().Where(x => x.FullyAvailable);
|
|
|
|
|
|
|
|
|
|
var addedLog = _recentlyAddedLog.GetAll();
|
|
|
|
|
var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId).ToHashSet();
|
|
|
|
|
var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId).ToHashSet();
|
|
|
|
|
var addedJellyfinMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Jellyfin && x.ContentType == ContentType.Parent).Select(x => x.ContentId).ToHashSet();
|
|
|
|
|
var addedAlbumLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Lidarr && x.ContentType == ContentType.Album).Select(x => x.AlbumId).ToHashSet();
|
|
|
|
|
|
|
|
|
|
var addedPlexEpisodesLogIds =
|
|
|
|
|
addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode);
|
|
|
|
|
var addedEmbyEpisodesLogIds =
|
|
|
|
|
addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode);
|
|
|
|
|
var addedJellyfinEpisodesLogIds =
|
|
|
|
|
addedLog.Where(x => x.Type == RecentlyAddedType.Jellyfin && x.ContentType == ContentType.Episode);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Filter out the ones that we haven't sent yet
|
|
|
|
|
var plexContentLocalDataset = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
|
|
|
|
var embyContentLocalDataset = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
|
|
|
|
var jellyfinContentLocalDataset = jellyfinContent.Where(x => x.Type == JellyfinMediaType.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 == PlexMediaTypeEntity.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
|
|
|
|
var needsMovieDbEmby = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !string.IsNullOrEmpty(x.TheMovieDbId)).ToHashSet();
|
|
|
|
|
var needsMovieDbJellyfin = jellyfinContent.Where(x => x.Type == JellyfinMediaType.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();
|
|
|
|
@ -161,24 +175,30 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds);
|
|
|
|
|
var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(),
|
|
|
|
|
addedEmbyEpisodesLogIds);
|
|
|
|
|
var jellyfinEpisodesToSend = FilterJellyfinEpisodes(_jellyfin.GetAllEpisodes().Include(x => x.Series).AsNoTracking(),
|
|
|
|
|
addedJellyfinEpisodesLogIds);
|
|
|
|
|
|
|
|
|
|
_log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count());
|
|
|
|
|
_log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count());
|
|
|
|
|
_log.LogInformation("Jellyfin Episodes to send: {0}", jellyfinEpisodesToSend.Count());
|
|
|
|
|
var plexSettings = await _plexSettings.GetSettingsAsync();
|
|
|
|
|
var embySettings = await _embySettings.GetSettingsAsync();
|
|
|
|
|
var jellyfinSettings = await _jellyfinSettings.GetSettingsAsync();
|
|
|
|
|
var body = string.Empty;
|
|
|
|
|
if (test)
|
|
|
|
|
{
|
|
|
|
|
var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10);
|
|
|
|
|
var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10);
|
|
|
|
|
var jellyfinm = jellyfinContent.Where(x => x.Type == JellyfinMediaType.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 lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet();
|
|
|
|
|
body = await BuildHtml(plexm, embym, plext, embyt, lidarr, settings, embySettings, plexSettings);
|
|
|
|
|
body = await BuildHtml(plexm, embym, jellyfinm, plext, embyt, jellyfint, lidarr, settings, embySettings, jellyfinSettings, plexSettings);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
body = await BuildHtml(plexContentMoviesToSend.AsQueryable(), embyContentMoviesToSend.AsQueryable(), plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, plexSettings);
|
|
|
|
|
body = await BuildHtml(plexContentMoviesToSend.AsQueryable(), embyContentMoviesToSend.AsQueryable(), jellyfinContentMoviesToSend.AsQueryable(), plexEpisodesToSend, embyEpisodesToSend, jellyfinEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, jellyfinSettings, plexSettings);
|
|
|
|
|
if (body.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
@ -285,6 +305,34 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
SeasonNumber = p.SeasonNumber
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var e in jellyfinContentMoviesToSend)
|
|
|
|
|
{
|
|
|
|
|
if (e.Type == JellyfinMediaType.Movie)
|
|
|
|
|
{
|
|
|
|
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
|
|
|
|
{
|
|
|
|
|
AddedAt = DateTime.Now,
|
|
|
|
|
Type = RecentlyAddedType.Jellyfin,
|
|
|
|
|
ContentType = ContentType.Parent,
|
|
|
|
|
ContentId = StringHelper.IntParseLinq(e.TheMovieDbId),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var p in jellyfinEpisodesToSend)
|
|
|
|
|
{
|
|
|
|
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
|
|
|
|
{
|
|
|
|
|
AddedAt = DateTime.Now,
|
|
|
|
|
Type = RecentlyAddedType.Jellyfin,
|
|
|
|
|
ContentType = ContentType.Episode,
|
|
|
|
|
ContentId = StringHelper.IntParseLinq(p.Series.TvDbId),
|
|
|
|
|
EpisodeNumber = p.EpisodeNumber,
|
|
|
|
|
SeasonNumber = p.SeasonNumber
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await _recentlyAddedLog.AddRange(recentlyAddedLog);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
@ -349,6 +397,20 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
foreach (var movie in content)
|
|
|
|
@ -358,6 +420,10 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
var entity = await _plex.Find(movie.Id);
|
|
|
|
|
if (entity == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
entity.TheMovieDbId = movie.TheMovieDbId;
|
|
|
|
|
_plex.UpdateWithoutSave(entity);
|
|
|
|
|
}
|
|
|
|
@ -379,6 +445,21 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
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();
|
|
|
|
@ -419,6 +500,23 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
return itemsToReturn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private HashSet<JellyfinEpisode> FilterJellyfinEpisodes(IEnumerable<JellyfinEpisode> source, IQueryable<RecentlyAddedLog> recentlyAdded)
|
|
|
|
|
{
|
|
|
|
|
var itemsToReturn = new HashSet<JellyfinEpisode>();
|
|
|
|
|
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 NotificationMessageContent ParseTemplate(NotificationTemplates template, CustomizationSettings settings)
|
|
|
|
|
{
|
|
|
|
|
var resolver = new NotificationMessageResolver();
|
|
|
|
@ -429,8 +527,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
return resolver.ParseMessage(template, curlys);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<string> BuildHtml(IQueryable<PlexServerContent> plexContentToSend, IQueryable<EmbyContent> embyContentToSend,
|
|
|
|
|
HashSet<PlexEpisode> plexEpisodes, HashSet<EmbyEpisode> embyEp, HashSet<LidarrAlbumCache> albums, NewsletterSettings settings, EmbySettings embySettings,
|
|
|
|
|
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,
|
|
|
|
|
PlexSettings plexSettings)
|
|
|
|
|
{
|
|
|
|
|
var ombiSettings = await _ombiSettings.GetSettingsAsync();
|
|
|
|
@ -438,6 +536,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
|
|
|
|
|
var plexMovies = plexContentToSend.Where(x => x.Type == PlexMediaTypeEntity.Movie);
|
|
|
|
|
var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie);
|
|
|
|
|
var jellyfinMovies = jellyfinContentToSend.Where(x => x.Type == JellyfinMediaType.Movie);
|
|
|
|
|
if ((plexMovies.Any() || embyMovies.Any()) && !settings.DisableMovies)
|
|
|
|
|
{
|
|
|
|
|
sb.Append("<h1 style=\"text-align: center; max-width: 1042px;\">New Movies</h1><br /><br />");
|
|
|
|
@ -457,6 +556,11 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
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>");
|
|
|
|
@ -464,7 +568,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
sb.Append("</table>");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((plexEpisodes.Any() || embyEp.Any()) && !settings.DisableTv)
|
|
|
|
|
if ((plexEpisodes.Any() || embyEp.Any()) || jellyfinEp.Any() && !settings.DisableTv)
|
|
|
|
|
{
|
|
|
|
|
sb.Append("<br /><br /><h1 style=\"text-align: center; max-width: 1042px;\">New TV</h1><br /><br />");
|
|
|
|
|
sb.Append(
|
|
|
|
@ -483,6 +587,11 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
await ProcessEmbyTv(embyEp, sb, embySettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (jellyfinSettings.Enable)
|
|
|
|
|
{
|
|
|
|
|
await ProcessJellyfinTv(jellyfinEp, sb, jellyfinSettings.Servers.FirstOrDefault()?.ServerHostname ?? string.Empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sb.Append("</tr>");
|
|
|
|
|
sb.Append("</table>");
|
|
|
|
|
sb.Append("</td>");
|
|
|
|
@ -638,6 +747,59 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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}");
|
|
|
|
@ -981,6 +1143,129 @@ namespace Ombi.Schedule.Jobs.Ombi
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task ProcessJellyfinTv(HashSet<JellyfinEpisode> embyContent, StringBuilder sb, string serverUrl)
|
|
|
|
|
{
|
|
|
|
|
var series = new List<JellyfinContent>();
|
|
|
|
|
foreach (var episode in embyContent)
|
|
|
|
|
{
|
|
|
|
|
var alreadyAdded = series.FirstOrDefault(x => x.JellyfinId == episode.Series.JellyfinId);
|
|
|
|
|
if (alreadyAdded != null)
|
|
|
|
|
{
|
|
|
|
|
alreadyAdded.Episodes.Add(episode);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
episode.Series.Episodes = new List<JellyfinEpisode>
|
|
|
|
|
{
|
|
|
|
|
episode
|
|
|
|
|
};
|
|
|
|
|
series.Add(episode.Series);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
var title = "";
|
|
|
|
|
if (!String.IsNullOrEmpty(info.premiered) && info.premiered.Length > 4)
|
|
|
|
|
{
|
|
|
|
|
title = $"{t.Title} ({info.premiered.Remove(4)})";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
title = $"{t.Title}";
|
|
|
|
|
}
|
|
|
|
|
AddTitle(sb, $"https://www.imdb.com/title/{info.externals.imdb}/", title);
|
|
|
|
|
|
|
|
|
|
// 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 />");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var summary = info.summary;
|
|
|
|
|
if (summary.Length > 280)
|
|
|
|
|
{
|
|
|
|
|
summary = summary.Remove(280);
|
|
|
|
|
summary = summary + "...</p>";
|
|
|
|
|
}
|
|
|
|
|
AddTvParagraph(sb, finalsb.ToString(), summary);
|
|
|
|
|
|
|
|
|
|
if (info.genres.Any())
|
|
|
|
|
{
|
|
|
|
|
AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
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 EndLoopHtml(StringBuilder sb)
|
|
|
|
|
{
|
|
|
|
|
//NOTE: BR have to be in TD's as per html spec or it will be put outside of the table...
|
|
|
|
|