diff --git a/PlexRequests.Core/PlexReadOnlyDatabase.cs b/PlexRequests.Core/PlexReadOnlyDatabase.cs index ffb2b6616..4c41e1e63 100644 --- a/PlexRequests.Core/PlexReadOnlyDatabase.cs +++ b/PlexRequests.Core/PlexReadOnlyDatabase.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using PlexRequests.Core.SettingModels; using PlexRequests.Store; using PlexRequests.Store.Models.Plex; @@ -63,11 +64,19 @@ namespace PlexRequests.Core public IEnumerable GetItemsAddedAfterDate(DateTime dateTime) { // type 1 = Movie, type 4 = TV Episode - return Plex.QueryMetadataItems(@"SELECT * FROM metadata_items + var movies = Plex.QueryMetadataItems(@"SELECT * FROM metadata_items WHERE added_at > @AddedAt - AND metadata_type in (1,4) - AND title <> ''", - new { AddedAt = dateTime }); + AND metadata_type = 1 + AND title <> ''", new { AddedAt = dateTime }); + + // Custom query to include the series title + var tv = Plex.QueryMetadataItems(@"SELECT series.title AS SeriesTitle, mi.* FROM metadata_items mi + INNER JOIN metadata_items season ON mi.parent_id = season.id + INNER JOIN metadata_items series ON series.id = season.parent_id + WHERE mi.added_at > @AddedAt + AND mi.metadata_type = 4", new { AddedAt = dateTime }); + + return movies.Union(tv); } } } \ No newline at end of file diff --git a/PlexRequests.Services/Jobs/HtmlTemplateGenerator.cs b/PlexRequests.Services/Jobs/HtmlTemplateGenerator.cs new file mode 100644 index 000000000..d29697b67 --- /dev/null +++ b/PlexRequests.Services/Jobs/HtmlTemplateGenerator.cs @@ -0,0 +1,71 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: HtmlTemplateGenerator.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System.IO; +using System.Text; +using System.Web.UI; + +namespace PlexRequests.Services.Jobs +{ + public abstract class HtmlTemplateGenerator + { + protected virtual void AddParagraph(ref StringBuilder stringBuilder, string text, int fontSize = 14, string fontWeight = "normal") + { + stringBuilder.AppendFormat("

{0}

", text, fontSize, fontWeight); + } + + protected virtual void AddImageInsideTable(ref StringBuilder sb, string url) + { + sb.Append(""); + sb.Append(""); + sb.AppendFormat( + "", + url); + sb.Append(""); + sb.Append(""); + } + + protected virtual void Href(ref StringBuilder sb, string url) + { + sb.AppendFormat("", url); + } + + protected virtual void EndTag(ref StringBuilder sb, string tag) + { + sb.AppendFormat("", tag); + } + + protected virtual void Header(ref StringBuilder sb, int size, string text, string fontWeight = "normal") + { + sb.AppendFormat( + "{1}", + size, text, fontWeight); + } + + + } +} \ No newline at end of file diff --git a/PlexRequests.Services/Jobs/RecentlyAdded.cs b/PlexRequests.Services/Jobs/RecentlyAdded.cs index 21f592e62..869bac323 100644 --- a/PlexRequests.Services/Jobs/RecentlyAdded.cs +++ b/PlexRequests.Services/Jobs/RecentlyAdded.cs @@ -48,7 +48,7 @@ using Quartz; namespace PlexRequests.Services.Jobs { - public class RecentlyAdded : IJob, IRecentlyAdded + public class RecentlyAdded : HtmlTemplateGenerator, IJob, IRecentlyAdded { public RecentlyAdded(IPlexApi api, ISettingsService plexSettings, ISettingsService email, @@ -146,7 +146,7 @@ namespace PlexRequests.Services.Jobs var sb = new StringBuilder(); var plexSettings = PlexSettings.GetSettings(); - var recentlyAdded = PlexDb.GetItemsAddedAfterDate(DateTime.Now.AddDays(-12)).ToList(); + var recentlyAdded = PlexDb.GetItemsAddedAfterDate(DateTime.Now.AddDays(-12)).ToList(); // TODO Date configurable var movies = recentlyAdded.Where(x => x.metadata_type == MetadataTypeMovie); var tv = recentlyAdded.Where(x => x.metadata_type == MetadataTypeTv); @@ -160,12 +160,12 @@ namespace PlexRequests.Services.Jobs Send(html, plexSettings, testEmail); } - private void GenerateMovieHtml(IEnumerable movies, PlexSettings plexSettings,ref StringBuilder sb) + private void GenerateMovieHtml(IEnumerable movies, PlexSettings plexSettings, ref StringBuilder sb) { sb.Append("

New Movies:



"); sb.Append( ""); - foreach (var movie in movies) + foreach (var movie in movies.OrderByDescending(x => x.addedAt)) { var plexGUID = string.Empty; try @@ -178,36 +178,24 @@ namespace PlexRequests.Services.Jobs var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID); var info = _movieApi.GetMovieInformation(imdbId).Result; - sb.Append(""); - sb.Append(""); - sb.Append(""); + AddImageInsideTable(ref sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}"); + sb.Append(""); sb.Append( ""); + AddParagraph(ref sb, info.Overview); + + EndLoopHtml(ref sb); } catch (Exception e) { @@ -229,7 +217,7 @@ namespace PlexRequests.Services.Jobs sb.Append("

New Movies:



"); sb.Append( "
"); - sb.AppendFormat( - "", - info.BackdropPath); - sb.Append("
"); - sb.AppendFormat( - "

{1} {2}

", - info.ImdbId, info.Title, info.ReleaseDate?.ToString("yyyy") ?? string.Empty); + Href(ref sb, $"https://www.imdb.com/title/{info.ImdbId}/"); + Header(ref sb, 3, $"{info.Title} {info.ReleaseDate?.ToString("yyyy") ?? string.Empty}"); + EndTag(ref sb, "a"); if (info.Genres.Any()) { - sb.AppendFormat( - "

Genre: {0}

", - string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())); + AddParagraph(ref sb, $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); } - sb.AppendFormat( - "

{0}

", - info.Overview); - sb.Append(""); - sb.Append("
"); - sb.Append("
"); - sb.Append("

"); - foreach (var movie in items) + foreach (var movie in items.OrderByDescending(x => x.added_at)) { var plexGUID = string.Empty; try @@ -237,41 +225,35 @@ namespace PlexRequests.Services.Jobs plexGUID = movie.guid; var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID); - + var info = _movieApi.GetMovieInformation(imdbId).Result; // TODO remove this and get the image info from Plex https://github.com/jakewaldron/PlexEmail/blob/master/scripts/plexEmail.py#L391 + AddImageInsideTable(ref sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}"); + sb.Append(""); - sb.Append(""); - sb.Append(""); - sb.Append(""); - sb.Append( - ""); + EndLoopHtml(ref sb); } catch (Exception e) { @@ -283,13 +265,14 @@ namespace PlexRequests.Services.Jobs sb.Append("
"); - sb.AppendFormat( - "", - info.BackdropPath); - sb.Append("
"); + sb.Append(""); - sb.AppendFormat( - "

{1} {2:yyyy}

", - imdbId, string.IsNullOrEmpty(movie.original_title) ? movie.title : movie.original_title + $" AKA {movie.title}", movie.originally_available_at); + Href(ref sb, $"https://www.imdb.com/title/{info.ImdbId}/"); + var title = string.IsNullOrEmpty(movie.original_title) + ? $"{movie.title} {movie.originally_available_at:yyyy}" + : $"{movie.original_title} AKA {movie.title} {movie.originally_available_at:yyyy}"; + + Header(ref sb, 3, title); + EndTag(ref sb, "a"); if (!string.IsNullOrEmpty(movie.tagline)) { - sb.AppendFormat("

{0}

", movie.tagline); + AddParagraph(ref sb, movie.tagline); } if (!string.IsNullOrEmpty(movie.tags_genre)) { - sb.AppendFormat("

Genre: {0}

", PlexHelper.FormatGenres(movie.tags_genre)); + AddParagraph(ref sb, $"Genre: {PlexHelper.FormatGenres(movie.tags_genre)}"); } - sb.AppendFormat("

{0}

", movie.summary); + AddParagraph(ref sb, movie.summary); - sb.Append(""); - sb.Append("
"); - sb.Append("
"); - sb.Append("



"); } + [Obsolete("Use the new DB Version")] private void GenerateTvHtml(IEnumerable tv, PlexSettings plexSettings, ref StringBuilder sb) { // TV sb.Append("

New Episodes:



"); sb.Append( ""); - foreach (var t in tv) + foreach (var t in tv.OrderByDescending(x => x.addedAt)) { var plexGUID = string.Empty; try @@ -349,12 +332,12 @@ namespace PlexRequests.Services.Jobs sb.Append("

New Episodes:



"); sb.Append( "
"); - foreach (var t in items) + foreach (var t in items.OrderByDescending(x => x.added_at)) { var plexGUID = string.Empty; try { - + plexGUID = t.guid; var seasonInfo = PlexHelper.GetSeasonsAndEpisodesFromPlexGuid(plexGUID); @@ -373,8 +356,12 @@ namespace PlexRequests.Services.Jobs sb.Append(""); sb.Append(""); + } + } } \ No newline at end of file diff --git a/PlexRequests.Services/PlexRequests.Services.csproj b/PlexRequests.Services/PlexRequests.Services.csproj index 6c0f8392b..d53128879 100644 --- a/PlexRequests.Services/PlexRequests.Services.csproj +++ b/PlexRequests.Services/PlexRequests.Services.csproj @@ -80,6 +80,7 @@ + diff --git a/PlexRequests.Store/Models/Plex/MetadataItems.cs b/PlexRequests.Store/Models/Plex/MetadataItems.cs index 67fdefc63..8ba55fc39 100644 --- a/PlexRequests.Store/Models/Plex/MetadataItems.cs +++ b/PlexRequests.Store/Models/Plex/MetadataItems.cs @@ -63,5 +63,6 @@ namespace PlexRequests.Store.Models.Plex public DateTime expires_at { get; set; } // Skip RefreshedAt and Year public DateTime added_at { get; set; } + public string SeriesTitle { get; set; } // Only used in a custom query for the TV Shows } } \ No newline at end of file diff --git a/PlexRequests.UI/Startup.cs b/PlexRequests.UI/Startup.cs index f7484bbf2..59d26e58f 100644 --- a/PlexRequests.UI/Startup.cs +++ b/PlexRequests.UI/Startup.cs @@ -32,7 +32,7 @@ using Ninject.Planning.Bindings.Resolvers; using NLog; using Owin; - +using PlexRequests.Services.Jobs; using PlexRequests.UI.Helpers; using PlexRequests.UI.Jobs; using PlexRequests.UI.NinjectModules; @@ -67,6 +67,9 @@ namespace PlexRequests.UI Debug.WriteLine("Finished bootstrapper"); var scheduler = new Scheduler(); scheduler.StartScheduler(); + + var r = kernel.Get(); + r.Test(); } catch (Exception exception) {
"); - sb.AppendFormat("

{1} {2:yyyy}

", - info.externals.imdb, string.IsNullOrEmpty(t.original_title) ? t.title : t.original_title + $" AKA {t.title}", t.originally_available_at); // Only the year + var title = !string.IsNullOrEmpty(t.SeriesTitle) + ? $"{t.SeriesTitle} - {t.title} {t.originally_available_at:yyyy}" + : $"{t.title}"; + + sb.AppendFormat("

{1}

", + info.externals.imdb, title); sb.AppendFormat("

Season: {0}, Episode: {1}

", seasonInfo.SeasonNumber, seasonInfo.EpisodeNumber); @@ -453,5 +440,15 @@ namespace PlexRequests.Services.Jobs Log.Error(e); } } + + private void EndLoopHtml(ref StringBuilder sb) + { + sb.Append(""); + sb.Append("
"); + sb.Append("
"); + sb.Append("