public void RecentlyAddedAdminTest() { Log.Debug("Starting Recently Added Newsletter Test"); var settings = NewsletterSettings.GetSettings(); StartNewsLetter(settings, true); }
public void Test() { Log.Debug("Starting Test Newsletter"); var settings = NewsletterSettings.GetSettings(); Start(settings, true); }
private void UpdateApplicationSettings() { var plex = PlexRequestSettings.GetSettings(); var jobSettings = Jobs.GetSettings(); var newsLetter = NewsletterSettings.GetSettings(); newsLetter.SendToPlexUsers = true; UpdateScheduledSettings(jobSettings); if (plex.SendRecentlyAddedEmail) { newsLetter.SendRecentlyAddedEmail = plex.SendRecentlyAddedEmail; plex.SendRecentlyAddedEmail = false; PlexRequestSettings.SaveSettings(plex); } NewsletterSettings.SaveSettings(newsLetter); Jobs.SaveSettings(jobSettings); }
public void Execute(IJobExecutionContext context) { try { var settings = NewsletterSettings.GetSettings(); if (!settings.SendRecentlyAddedEmail) { return; } Start(settings); } catch (Exception e) { Log.Error(e); } finally { JobRecord.Record(JobNames.RecentlyAddedEmail); } }
public void StartNewsLetter() { try { var settings = NewsletterSettings.GetSettings(); if (!settings.SendRecentlyAddedEmail) { return; } JobRecord.SetRunning(true, JobNames.RecentlyAddedEmail); StartNewsLetter(settings); } catch (Exception e) { Log.Error(e); } finally { JobRecord.Record(JobNames.RecentlyAddedEmail); JobRecord.SetRunning(false, JobNames.RecentlyAddedEmail); } }
public async Task Start(NewsletterSettings settings, bool test) { if (!settings.Enabled) { return; } var template = await _templateRepo.GetTemplate(NotificationAgent.Email, NotificationType.Newsletter); if (!template.Enabled) { return; } var emailSettings = await _emailSettings.GetSettingsAsync(); if (!ValidateConfiguration(emailSettings)) { return; } 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 addedLog = _recentlyAddedLog.GetAll(); var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId); var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId); var addedPlexEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode).Select(x => x.ContentId); var addedEmbyEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode).Select(x => x.ContentId); // Filter out the ones that we haven't sent yet var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(x.Id)); var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(x.Id)); var plexEpisodesToSend = _plex.GetAllEpisodes().Include(x => x.Series).Where(x => !addedPlexEpisodesLogIds.Contains(x.Id)).AsNoTracking(); var embyEpisodesToSend = _emby.GetAllEpisodes().Include(x => x.Series).Where(x => !addedEmbyEpisodesLogIds.Contains(x.Id)).AsNoTracking(); 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 plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10); var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10); body = await BuildHtml(plexm, embym, plext, embyt); } else { body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend); if (body.IsNullOrEmpty()) { return; } } if (!test) { // Get the users to send it to var users = await _userManager.GetUsersInRoleAsync(OmbiRoles.RecievesNewsletter); if (!users.Any()) { return; } var emailTasks = new List <Task>(); foreach (var user in users) { if (user.Email.IsNullOrEmpty()) { continue; } var messageContent = ParseTemplate(template, customization, user); var email = new NewsletterTemplate(); var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo); emailTasks.Add(_email.Send( new NotificationMessage { Message = html, Subject = messageContent.Subject, To = user.Email }, emailSettings)); } // Now add all of this to the Recently Added log var recentlyAddedLog = new HashSet <RecentlyAddedLog>(); foreach (var p in plexContentMoviesToSend) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, ContentType = ContentType.Parent, ContentId = p.Id }); } foreach (var p in plexEpisodesToSend) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, ContentType = ContentType.Episode, ContentId = p.Id }); } foreach (var e in embyContentMoviesToSend) { if (e.Type == EmbyMediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, ContentType = ContentType.Parent, ContentId = e.Id }); } } foreach (var p in embyEpisodesToSend) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, ContentType = ContentType.Episode, ContentId = p.Id }); } await _recentlyAddedLog.AddRange(recentlyAddedLog); await Task.WhenAll(emailTasks.ToArray()); } else { var admins = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin); foreach (var a in admins) { if (a.Email.IsNullOrEmpty()) { continue; } var messageContent = ParseTemplate(template, customization, a); var email = new NewsletterTemplate(); var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo); await _email.Send( new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email }, emailSettings); } } }
private async Task <string> BuildHtml(IQueryable <PlexServerContent> plexContentToSend, IQueryable <EmbyContent> embyContentToSend, IQueryable <PlexEpisode> plexEpisodes, IQueryable <EmbyEpisode> embyEp, NewsletterSettings settings) { var sb = new StringBuilder(); var plexMovies = plexContentToSend.Where(x => x.Type == PlexMediaTypeEntity.Movie); var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie); if ((plexMovies.Any() || embyMovies.Any()) && !settings.DisableMovies) { sb.Append("<h1>New Movies:</h1><br /><br />"); await ProcessPlexMovies(plexMovies, sb); await ProcessEmbyMovies(embyMovies, sb); } if ((plexEpisodes.Any() || embyEp.Any()) && !settings.DisableTv) { sb.Append("<h1>New Episodes:</h1><br /><br />"); await ProcessPlexTv(plexEpisodes, sb); await ProcessEmbyTv(embyEp, sb); } return(sb.ToString()); }
public async Task Start(NewsletterSettings settings, bool test) { if (!settings.Enabled) { return; } var template = await _templateRepo.GetTemplate(NotificationAgent.Email, NotificationType.Newsletter); if (!template.Enabled) { return; } var emailSettings = await _emailSettings.GetSettingsAsync(); if (!ValidateConfiguration(emailSettings)) { return; } try { 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 lidarrContent = _lidarrAlbumRepository.GetAll().Where(x => x.FullyAvailable).AsNoTracking(); 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 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); // Filter out the ones that we haven't sent yet var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && x.HasTheMovieDb && !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && x.HasTheMovieDb && !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); 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("Albums to send: {0}", lidarrContentAlbumsToSend.Count()); var plexEpisodesToSend = FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).Where(x => x.Series.HasTvDb).AsNoTracking(), addedPlexEpisodesLogIds); var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).Where(x => x.Series.HasTvDb).AsNoTracking(), addedEmbyEpisodesLogIds); _log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count()); _log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count()); var plexSettings = await _plexSettings.GetSettingsAsync(); var embySettings = await _embySettings.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 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 lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); body = await BuildHtml(plexm, embym, plext, embyt, lidarr, settings, embySettings, plexSettings); } else { body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, plexSettings); if (body.IsNullOrEmpty()) { return; } } if (!test) { // Get the users to send it to var users = await _userManager.GetUsersInRoleAsync(OmbiRoles.ReceivesNewsletter); if (!users.Any()) { return; } foreach (var emails in settings.ExternalEmails) { users.Add(new OmbiUser { UserName = emails, Email = emails }); } var messageContent = ParseTemplate(template, customization); var email = new NewsletterTemplate(); var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo); var bodyBuilder = new BodyBuilder { HtmlBody = html, }; var message = new MimeMessage { Body = bodyBuilder.ToMessageBody(), Subject = messageContent.Subject }; foreach (var user in users) { // Get the users to send it to if (user.Email.IsNullOrEmpty()) { continue; } // BCC the messages message.Bcc.Add(new MailboxAddress(user.Email, user.Email)); } // Send the email await _email.Send(message, emailSettings); // Now add all of this to the Recently Added log var recentlyAddedLog = new HashSet <RecentlyAddedLog>(); foreach (var p in plexContentMoviesToSend) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, ContentType = ContentType.Parent, ContentId = StringHelper.IntParseLinq(p.TheMovieDbId), }); } foreach (var p in plexEpisodesToSend) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, ContentType = ContentType.Episode, ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), EpisodeNumber = p.EpisodeNumber, SeasonNumber = p.SeasonNumber }); } foreach (var e in embyContentMoviesToSend) { if (e.Type == EmbyMediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, ContentType = ContentType.Parent, ContentId = StringHelper.IntParseLinq(e.TheMovieDbId), }); } } foreach (var p in embyEpisodesToSend) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, ContentType = ContentType.Episode, ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), EpisodeNumber = p.EpisodeNumber, SeasonNumber = p.SeasonNumber }); } await _recentlyAddedLog.AddRange(recentlyAddedLog); } else { var admins = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin); foreach (var a in admins) { if (a.Email.IsNullOrEmpty()) { continue; } var messageContent = ParseTemplate(template, customization); var email = new NewsletterTemplate(); var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo); await _email.Send( new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email }, emailSettings); } } } catch (Exception e) { _log.LogError(e, "Error when attempting to create newsletter"); throw; } }
private async Task <string> BuildHtml(IQueryable <PlexServerContent> plexContentToSend, IQueryable <EmbyContent> embyContentToSend, HashSet <PlexEpisode> plexEpisodes, HashSet <EmbyEpisode> embyEp, HashSet <LidarrAlbumCache> albums, NewsletterSettings settings, EmbySettings embySettings, PlexSettings plexSettings) { var ombiSettings = await _ombiSettings.GetSettingsAsync(); var sb = new StringBuilder(); var plexMovies = plexContentToSend.Where(x => x.Type == PlexMediaTypeEntity.Movie); var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie); if ((plexMovies.Any() || embyMovies.Any()) && !settings.DisableMovies) { sb.Append("<h1 style=\"text-align: center; max-width: 1042px;\">New Movies</h1><br /><br />"); sb.Append( "<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); sb.Append("<tr>"); 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) { await ProcessPlexMovies(plexMovies, sb, ombiSettings.DefaultLanguageCode); } if (embySettings.Enable) { await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode); } sb.Append("</tr>"); sb.Append("</table>"); sb.Append("</td>"); sb.Append("</tr>"); sb.Append("</table>"); } if ((plexEpisodes.Any() || embyEp.Any()) && !settings.DisableTv) { sb.Append("<br /><br /><h1 style=\"text-align: center; max-width: 1042px;\">New TV</h1><br /><br />"); sb.Append( "<table class=\"tv-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); sb.Append("<tr>"); 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) { await ProcessPlexTv(plexEpisodes, sb); } if (embySettings.Enable) { await ProcessEmbyTv(embyEp, sb); } sb.Append("</tr>"); sb.Append("</table>"); sb.Append("</td>"); sb.Append("</tr>"); sb.Append("</table>"); } if (albums.Any() && !settings.DisableMusic) { sb.Append("<h1 style=\"text-align: center; max-width: 1042px;\">New Albums</h1><br /><br />"); sb.Append( "<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); sb.Append("<tr>"); 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>"); await ProcessAlbums(albums, sb); sb.Append("</tr>"); sb.Append("</table>"); sb.Append("</td>"); sb.Append("</tr>"); sb.Append("</table>"); } return(sb.ToString()); }
public void Test() { var settings = NewsletterSettings.GetSettings(); Start(settings, true); }
public async Task Start(NewsletterSettings settings, bool test) { if (!settings.Enabled) { return; } var template = await _templateRepo.GetTemplate(NotificationAgent.Email, NotificationType.Newsletter); if (!template.Enabled) { return; } await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Newsletter Started"); var emailSettings = await _emailSettings.GetSettingsAsync(); if (!ValidateConfiguration(emailSettings)) { await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Newsletter Email Settings Not Configured"); return; } try { var plexSettings = await _plexSettings.GetSettingsAsync(); var embySettings = await _embySettings.GetSettingsAsync(); var jellyfinSettings = await _jellyfinSettings.GetSettingsAsync(); var customization = await _customizationSettings.GetSettingsAsync(); var moviesContents = new List <IMediaServerContent>(); var seriesContents = new List <IMediaServerEpisode>(); if (plexSettings.Enable) { moviesContents.AddRange(await GetMoviesContent(_plex, test)); seriesContents.AddRange(GetSeriesContent(_plex, test)); } if (embySettings.Enable) { moviesContents.AddRange(await GetMoviesContent(_emby, test)); seriesContents.AddRange(GetSeriesContent(_emby, test)); } if (jellyfinSettings.Enable) { moviesContents.AddRange(await GetMoviesContent(_jellyfin, test)); seriesContents.AddRange(GetSeriesContent(_jellyfin, test)); } var albumsContents = GetMusicContent(_lidarrAlbumRepository, test); var body = await BuildHtml(moviesContents, seriesContents, albumsContents, settings); if (body.IsNullOrEmpty()) { return; } if (!test) { var users = new List <OmbiUser>(); foreach (var emails in settings.ExternalEmails) { users.Add(new OmbiUser { UserName = emails, Email = emails }); } // Get the users to send it to users.AddRange(await _userManager.GetUsersInRoleAsync(OmbiRoles.ReceivesNewsletter)); if (!users.Any()) { return; } var messageContent = ParseTemplate(template, customization); var email = new NewsletterTemplate(); foreach (var user in users.DistinctBy(x => x.Email)) { // Get the users to send it to if (user.Email.IsNullOrEmpty()) { continue; } var url = GenerateUnsubscribeLink(customization.ApplicationUrl, user.Id); var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo, url); var bodyBuilder = new BodyBuilder { HtmlBody = html, }; var message = new MimeMessage { Body = bodyBuilder.ToMessageBody(), Subject = messageContent.Subject }; // Send the message to the user message.To.Add(new MailboxAddress(user.Email.Trim(), user.Email.Trim())); // Send the email await _email.Send(message, emailSettings); } // Now add all of this to the Recently Added log var recentlyAddedLog = new HashSet <RecentlyAddedLog>(); AddToRecentlyAddedLog(moviesContents, recentlyAddedLog); AddToRecentlyAddedLog(seriesContents, recentlyAddedLog); await _recentlyAddedLog.AddRange(recentlyAddedLog); } else { var admins = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin); foreach (var a in admins) { if (a.Email.IsNullOrEmpty()) { continue; } var unsubscribeLink = GenerateUnsubscribeLink(customization.ApplicationUrl, a.Id); var messageContent = ParseTemplate(template, customization); var email = new NewsletterTemplate(); var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo, unsubscribeLink); await _email.Send( new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email }, emailSettings); } } } catch (Exception e) { await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Newsletter Failed"); _log.LogError(e, "Error when attempting to create newsletter"); throw; } await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Newsletter Finished"); }
private async Task <string> BuildHtml(ICollection <IMediaServerContent> movies, IEnumerable <IMediaServerEpisode> episodes, HashSet <LidarrAlbumCache> albums, NewsletterSettings settings) { var ombiSettings = await _ombiSettings.GetSettingsAsync(); sb = new StringBuilder(); if (movies.Any() && !settings.DisableMovies) { sb.Append($"<h1 style=\"text-align: center; max-width: 1042px;\">{Texts.NewMovies}</h1><br /><br />"); sb.Append( "<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); sb.Append("<tr>"); 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>"); await ProcessMovies(movies, ombiSettings.DefaultLanguageCode); sb.Append("</tr>"); sb.Append("</table>"); sb.Append("</td>"); sb.Append("</tr>"); sb.Append("</table>"); } if (episodes.Any() && !settings.DisableTv) { sb.Append($"<br /><br /><h1 style=\"text-align: center; max-width: 1042px;\">{Texts.NewTV}</h1><br /><br />"); sb.Append( "<table class=\"tv-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); sb.Append("<tr>"); 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>"); await ProcessTv(episodes, ombiSettings.DefaultLanguageCode); sb.Append("</tr>"); sb.Append("</table>"); sb.Append("</td>"); sb.Append("</tr>"); sb.Append("</table>"); } if (albums.Any() && !settings.DisableMusic) { sb.Append($"<h1 style=\"text-align: center; max-width: 1042px;\">{Texts.NewAlbums}</h1><br /><br />"); sb.Append( "<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); sb.Append("<tr>"); 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>"); await ProcessAlbums(albums); sb.Append("</tr>"); sb.Append("</table>"); sb.Append("</td>"); sb.Append("</tr>"); sb.Append("</table>"); } return(sb.ToString()); }