diff --git a/src/Ombi.Mapping/Profiles/MovieProfile.cs b/src/Ombi.Mapping/Profiles/MovieProfile.cs index dd7e03379..39961b785 100644 --- a/src/Ombi.Mapping/Profiles/MovieProfile.cs +++ b/src/Ombi.Mapping/Profiles/MovieProfile.cs @@ -68,7 +68,7 @@ namespace Ombi.Mapping.Profiles .ForMember(x => x.ReleaseDate, o => o.MapFrom(s => s.release_date)) .ForMember(x => x.Type, o => o.MapFrom(s => s.Type)); - CreateMap(); + CreateMap(); CreateMap().ReverseMap(); CreateMap().ReverseMap(); diff --git a/src/Ombi.Notifications.Templates/TemplateBase.cs b/src/Ombi.Notifications.Templates/TemplateBase.cs index 9b9207c9a..ccabfa65c 100644 --- a/src/Ombi.Notifications.Templates/TemplateBase.cs +++ b/src/Ombi.Notifications.Templates/TemplateBase.cs @@ -3,6 +3,6 @@ public abstract class TemplateBase { public abstract string TemplateLocation { get; } - public virtual string OmbiLogo => "http://i.imgur.com/qQsN78U.png"; + public virtual string OmbiLogo => "http://i.imgur.com/7pqVq7W.png"; } } \ No newline at end of file diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 464e3463b..e9a2b7f29 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -4,57 +4,125 @@ Ombi - - - + +
- - + +
  -
+
+
- +
@@ -144,23 +165,24 @@
- +


-

{@INTRO}

+

{@INTRO}

- {@RECENTLYADDED} -
+ {@RECENTLYADDED}
diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 61f4bd7c8..3f9a182a4 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -4,43 +4,79 @@ namespace Ombi.Schedule.Jobs.Ombi { public abstract class HtmlTemplateGenerator { - protected virtual void AddParagraph(StringBuilder stringBuilder, string text, int fontSize = 14, string fontWeight = "normal") + protected virtual void AddBackgroundInsideTable(StringBuilder sb, string url) { - stringBuilder.AppendFormat("

{0}

", text, fontSize, fontWeight); + sb.Append(""); + sb.AppendFormat("", url); + sb.Append(""); + sb.Append("
"); + sb.Append(""); } - protected virtual void AddImageInsideTable(StringBuilder sb, string url, int size = 400) + protected virtual void AddPosterInsideTable(StringBuilder sb, string url) { sb.Append(""); - sb.Append(""); + } + + protected virtual void AddInfoTable(StringBuilder sb) + { + sb.Append( + ""); + sb.Append(""); + } + } } private async Task ProcessEmbyTv(HashSet embyContent, StringBuilder sb) @@ -570,9 +627,9 @@ namespace Ombi.Schedule.Jobs.Ombi series.Add(episode.Series); } } + + int count = 0; var orderedTv = series.OrderByDescending(x => x.AddedAt); - sb.Append( - "
"); - sb.Append($""); + sb.Append(""); + sb.AppendFormat("", url); + } + + protected virtual void AddMediaServerUrl(StringBuilder sb, string mediaurl, string url) + { + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append("
"); + sb.AppendFormat("", mediaurl); + sb.AppendFormat("", url); + sb.Append(""); + sb.Append("
"); + sb.Append("
"); + sb.Append(""); + } + + protected virtual void AddTitle(StringBuilder sb, string url, string title) + { + sb.Append(""); + sb.Append(""); sb.Append(""); } - protected virtual void Href(StringBuilder sb, string url) + protected virtual void AddParagraph(StringBuilder sb, string text) { - sb.AppendFormat("", url); + sb.Append(""); + sb.Append(""); + sb.Append(""); } - protected virtual void TableData(StringBuilder sb) + protected virtual void AddTvParagraph(StringBuilder sb, string episodes, string summary) { - sb.Append( - ""); + sb.Append(""); + sb.Append(""); } - protected virtual void EndTag(StringBuilder sb, string tag) + protected virtual void AddGenres(StringBuilder sb, string text) { - sb.AppendFormat("", tag); + sb.Append(""); + sb.Append(""); + sb.Append(""); } - - protected virtual void Header(StringBuilder sb, int size, string text, string fontWeight = "normal") - { - sb.AppendFormat( - "{1}", - size, text, fontWeight); - } - - } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 8b246e97e..20f5a3619 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -306,16 +306,38 @@ namespace Ombi.Schedule.Jobs.Ombi var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie); if ((plexMovies.Any() || embyMovies.Any()) && !settings.DisableMovies) { - sb.Append("

New Movies:



"); + sb.Append("

New Movies



"); + sb.Append( + "
"); + sb.AppendFormat("", url); + sb.AppendFormat("

{0}

", title); + sb.Append("
"); sb.Append("
"); + sb.AppendFormat("

{0}

", text); + sb.Append("
"); + sb.Append("
"); + sb.AppendFormat("

{0}

", episodes); + sb.AppendFormat("
{0}
", summary); + sb.Append("
"); + sb.AppendFormat("{0}", text); + sb.Append("
"); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append("
"); + sb.Append(""); + sb.Append(""); await ProcessPlexMovies(plexMovies, sb); await ProcessEmbyMovies(embyMovies, sb); + sb.Append(""); + sb.Append("
"); + sb.Append("
"); } if ((plexEpisodes.Any() || embyEp.Any()) && !settings.DisableTv) { - sb.Append("

New Episodes:



"); + sb.Append("

New TV



"); + sb.Append( + ""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append("
"); + sb.Append(""); + sb.Append(""); await ProcessPlexTv(plexEpisodes, sb); await ProcessEmbyTv(embyEp, sb); + sb.Append(""); + sb.Append("
"); + sb.Append("
"); } return sb.ToString(); @@ -323,8 +345,7 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task ProcessPlexMovies(IQueryable plexContentToSend, StringBuilder sb) { - sb.Append( - ""); + int count = 0; var ordered = plexContentToSend.OrderByDescending(x => x.AddedAt); foreach (var content in ordered) { @@ -334,13 +355,15 @@ namespace Ombi.Schedule.Jobs.Ombi continue; } var info = await _movieApi.GetMovieInformationWithExtraInfo(movieDbId); + var mediaurl = content.Url; if (info == null) { continue; } try { - CreateMovieHtmlContent(sb, info); + CreateMovieHtmlContent(sb, info, mediaurl); + count += 1; } catch (Exception e) { @@ -350,13 +373,19 @@ namespace Ombi.Schedule.Jobs.Ombi { EndLoopHtml(sb); } + + if (count == 2) + { + count = 0; + sb.Append(""); + sb.Append(""); + } } } private async Task ProcessEmbyMovies(IQueryable embyContent, StringBuilder sb) { - sb.Append( - "
"); + int count = 0; var ordered = embyContent.OrderByDescending(x => x.AddedAt); foreach (var content in ordered) { @@ -374,6 +403,7 @@ namespace Ombi.Schedule.Jobs.Ombi theMovieDbId = result.id.ToString(); } + var mediaurl = content.Url; var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId)); if (info == null) { @@ -381,7 +411,8 @@ namespace Ombi.Schedule.Jobs.Ombi } try { - CreateMovieHtmlContent(sb, info); + CreateMovieHtmlContent(sb, info, mediaurl); + count += 1; } catch (Exception e) { @@ -391,17 +422,24 @@ namespace Ombi.Schedule.Jobs.Ombi { EndLoopHtml(sb); } + + if (count == 2) + { + count = 0; + sb.Append(""); + sb.Append(""); + } } } - private void CreateMovieHtmlContent(StringBuilder sb, MovieResponseDto info) + private void CreateMovieHtmlContent(StringBuilder sb, MovieResponseDto info, string mediaurl) { - AddImageInsideTable(sb, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); + AddBackgroundInsideTable(sb, $"https://image.tmdb.org/t/p/w1280/{info.BackdropPath}"); + AddPosterInsideTable(sb, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); - sb.Append(""); - TableData(sb); + AddMediaServerUrl(sb, mediaurl, $"https://image.tmdb.org/t/p/original{info.PosterPath}"); + AddInfoTable(sb); - Href(sb, $"https://www.imdb.com/title/{info.ImdbId}/"); var releaseDate = string.Empty; try { @@ -411,16 +449,15 @@ namespace Ombi.Schedule.Jobs.Ombi { // Swallow, couldn't parse the date } - Header(sb, 3, $"{info.Title} {releaseDate}"); - EndTag(sb, "a"); + + AddTitle(sb, $"https://www.imdb.com/title/{info.ImdbId}/", $"{info.Title} {releaseDate}"); + AddParagraph(sb, info.Overview); if (info.Genres.Any()) { - AddParagraph(sb, - $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); + AddGenres(sb, + $"Genres: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); } - - AddParagraph(sb, info.Overview); } private async Task ProcessPlexTv(HashSet plexContent, StringBuilder sb) @@ -444,9 +481,8 @@ namespace Ombi.Schedule.Jobs.Ombi } } + int count = 0; var orderedTv = series.OrderByDescending(x => x.AddedAt); - sb.Append( - "
"); foreach (var t in orderedTv) { try @@ -489,17 +525,23 @@ namespace Ombi.Schedule.Jobs.Ombi { banner = banner.Replace("http", "https"); // Always use the Https banners } - AddImageInsideTable(sb, banner); + + var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId); + if (tvInfo != null && tvInfo.backdrop_path.HasValue()) + { - sb.Append(""); - sb.Append( - "
"); + 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, t.Url, banner); + AddInfoTable(sb); var title = $"{t.Title} ({t.ReleaseYear})"; - - Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/"); - Header(sb, 3, title); - EndTag(sb, "a"); + AddTitle(sb, $"https://www.imdb.com/title/{info.externals.imdb}/", title); // Group by the season number var results = t.Episodes.GroupBy(p => p.SeasonNumber, @@ -511,6 +553,7 @@ namespace Ombi.Schedule.Jobs.Ombi ); // 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(); @@ -528,15 +571,24 @@ namespace Ombi.Schedule.Jobs.Ombi } } - AddParagraph(sb, $"Season: {epInformation.SeasonNumber}, Episode: {epSb}"); + finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {epSb}"); + finalsb.Append("
"); } + var summary = info.summary; + if (summary.Length > 280) + { + summary = summary.Remove(280); + summary = summary + "...

"; + } + AddTvParagraph(sb, finalsb.ToString(), summary); + if (info.genres.Any()) { - AddParagraph(sb, $"Genre: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); + AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); } + count += 1; - AddParagraph(sb, info.summary); } catch (Exception e) { @@ -546,9 +598,14 @@ namespace Ombi.Schedule.Jobs.Ombi { EndLoopHtml(sb); } - } - sb.Append("


"); + if (count == 2) + { + count = 0; + sb.Append("
"); foreach (var t in orderedTv) { try @@ -581,26 +638,34 @@ namespace Ombi.Schedule.Jobs.Ombi { continue; } + int.TryParse(t.TvDbId, out var tvdbId); var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId); if (info == null) { continue; } + var banner = info.image?.original; if (!string.IsNullOrEmpty(banner)) { banner = banner.Replace("http", "https"); // Always use the Https banners } - AddImageInsideTable(sb, banner); - sb.Append(""); - sb.Append( - ""); + sb.Append(""); + } } - sb.Append("
"); + var tvInfo = await _movieApi.GetTVInfo(t.TheMovieDbId); + if (tvInfo != null && tvInfo.backdrop_path.HasValue()) + { - Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/"); - Header(sb, 3, t.Title); - EndTag(sb, "a"); + 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, t.Url, banner); + AddInfoTable(sb); + AddTitle(sb, $"https://www.imdb.com/title/{info.externals.imdb}/", $"{t.Title} ({info.premiered.Remove(4)})"); // Group by the season number var results = t.Episodes?.GroupBy(p => p.SeasonNumber, @@ -612,6 +677,7 @@ namespace Ombi.Schedule.Jobs.Ombi ); // 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(); @@ -629,15 +695,24 @@ namespace Ombi.Schedule.Jobs.Ombi } } - AddParagraph(sb, $"Season: {epInformation.SeasonNumber}, Episode: {epSb}"); + finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {epSb}"); + finalsb.Append("
"); } + var summary = info.summary; + if (summary.Length > 280) + { + summary = summary.Remove(280); + summary = summary + "...

"; + } + AddTvParagraph(sb, finalsb.ToString(), summary); + if (info.genres.Any()) { - AddParagraph(sb, $"Genre: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); + AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); } + count += 1; - AddParagraph(sb, info.summary); } catch (Exception e) { @@ -647,19 +722,28 @@ namespace Ombi.Schedule.Jobs.Ombi { EndLoopHtml(sb); } + + if (count == 2) + { + count = 0; + sb.Append("


"); } 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... //Source: http://stackoverflow.com/questions/6588638/phantom-br-tag-rendered-by-browsers-prior-to-table-tag - sb.Append("
"); - sb.Append("
"); - sb.Append("
"); + sb.Append("
"); sb.Append(""); sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); } protected bool ValidateConfiguration(EmailNotificationSettings settings) diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index 5d0a89992..0b24bd55c 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -18,5 +18,6 @@ namespace Ombi.Api.TheMovieDb Task> SimilarMovies(int movieId); Task Find(string externalId, ExternalSource source); Task GetTvExternals(int theMovieDbId); + Task GetTVInfo(string themoviedbid); } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/Models/TvInfo.cs b/src/Ombi.TheMovieDbApi/Models/TvInfo.cs new file mode 100644 index 000000000..5692fcc17 --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/TvInfo.cs @@ -0,0 +1,74 @@ +namespace Ombi.Api.TheMovieDb.Models +{ + public class TvInfo + { + public string backdrop_path { get; set; } + public Created_By[] created_by { get; set; } + public int[] episode_run_time { get; set; } + public string first_air_date { get; set; } + public Genre[] genres { get; set; } + public string homepage { get; set; } + public int id { get; set; } + public bool in_production { get; set; } + public string[] languages { get; set; } + public string last_air_date { get; set; } + public string name { get; set; } + public Network[] networks { get; set; } + public int number_of_episodes { get; set; } + public int number_of_seasons { get; set; } + public string[] origin_country { get; set; } + public string original_language { get; set; } + public string original_name { get; set; } + public string overview { get; set; } + public float popularity { get; set; } + public string poster_path { get; set; } + public Production_Companies[] production_companies { get; set; } + public Season[] seasons { get; set; } + public string status { get; set; } + public string type { get; set; } + public float vote_average { get; set; } + public int vote_count { get; set; } + } + + public class Created_By + { + public int id { get; set; } + public string name { get; set; } + public int gender { get; set; } + public string profile_path { get; set; } + } + + public class Genre + { + public int id { get; set; } + public string name { get; set; } + } + + public class Network + { + public string name { get; set; } + public int id { get; set; } + public string logo_path { get; set; } + public string origin_country { get; set; } + } + + public class Production_Companies + { + public int id { get; set; } + public string logo_path { get; set; } + public string name { get; set; } + public string origin_country { get; set; } + } + + public class Season + { + public string air_date { get; set; } + public int episode_count { get; set; } + public int id { get; set; } + public string name { get; set; } + public string overview { get; set; } + public string poster_path { get; set; } + public int season_number { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index ccd0e52e6..af9423f5d 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -129,6 +129,15 @@ namespace Ombi.Api.TheMovieDb var result = await Api.Request>(request); return Mapper.Map>(result.results); } + + public async Task GetTVInfo(string themoviedbid) + { + var request = new Request($"/tv/{themoviedbid}", BaseUri, HttpMethod.Get); + request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + AddRetry(request); + + return await Api.Request(request); + } private static void AddRetry(Request request) { request.Retry = true;