diff --git a/PlexRequests.Core/PlexReadOnlyDatabase.cs b/PlexRequests.Core/PlexReadOnlyDatabase.cs index ff4291756..ffb2b6616 100644 --- a/PlexRequests.Core/PlexReadOnlyDatabase.cs +++ b/PlexRequests.Core/PlexReadOnlyDatabase.cs @@ -44,7 +44,8 @@ namespace PlexRequests.Core if (!string.IsNullOrEmpty(settings.PlexDatabaseLocationOverride)) { - Plex.DbLocation = settings.PlexDatabaseLocationOverride; + //Overriden setting + Plex.DbLocation = Path.Combine(settings.PlexDatabaseLocationOverride, "Plug-in Support", "Databases", "com.plexapp.plugins.library.db"); } else if (Type.GetType("Mono.Runtime") != null) { @@ -61,7 +62,11 @@ namespace PlexRequests.Core public IEnumerable GetItemsAddedAfterDate(DateTime dateTime) { - return Plex.QueryMetadataItems("select * from metadata_items where added_at > @AddedAt", + // type 1 = Movie, type 4 = TV Episode + return Plex.QueryMetadataItems(@"SELECT * FROM metadata_items + WHERE added_at > @AddedAt + AND metadata_type in (1,4) + AND title <> ''", new { AddedAt = dateTime }); } } diff --git a/PlexRequests.Services/Jobs/RecentlyAdded.cs b/PlexRequests.Services/Jobs/RecentlyAdded.cs index 162e154be..c2cfdd1d3 100644 --- a/PlexRequests.Services/Jobs/RecentlyAdded.cs +++ b/PlexRequests.Services/Jobs/RecentlyAdded.cs @@ -42,6 +42,7 @@ using PlexRequests.Core.SettingModels; using PlexRequests.Helpers; using PlexRequests.Services.Interfaces; using PlexRequests.Services.Jobs.Templates; +using PlexRequests.Store.Models.Plex; using Quartz; @@ -52,7 +53,8 @@ namespace PlexRequests.Services.Jobs public RecentlyAdded(IPlexApi api, ISettingsService plexSettings, ISettingsService email, ISettingsService scheduledService, IJobRecord rec, - ISettingsService plexRequest) + ISettingsService plexRequest, + IPlexReadOnlyDatabase db) { JobRecord = rec; Api = api; @@ -60,6 +62,7 @@ namespace PlexRequests.Services.Jobs EmailSettings = email; ScheduledJobsSettings = scheduledService; PlexRequestSettings = plexRequest; + PlexDb = db; } private IPlexApi Api { get; } @@ -70,6 +73,7 @@ namespace PlexRequests.Services.Jobs private ISettingsService PlexRequestSettings { get; } private ISettingsService ScheduledJobsSettings { get; } private IJobRecord JobRecord { get; } + private IPlexReadOnlyDatabase PlexDb { get; } private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -108,7 +112,7 @@ namespace PlexRequests.Services.Jobs public void Test() { - Start(true); + StartDb(true); } private void Start(bool testEmail = false) @@ -135,8 +139,26 @@ namespace PlexRequests.Services.Jobs Send(html, plexSettings, testEmail); } - private void GenerateMovieHtml(IEnumerable movies, PlexSettings plexSettings, - ref StringBuilder sb) + private void StartDb(bool testEmail = false) + { + var sb = new StringBuilder(); + var plexSettings = PlexSettings.GetSettings(); + + var recentlyAdded = PlexDb.GetItemsAddedAfterDate(DateTime.Now.AddDays(-7)); + + var movies = recentlyAdded.Where(x => x.MetadataType == 1); + var tv = recentlyAdded.Where(x => x.MetadataType == 4); + + GenerateMovieHtmlDb(movies, ref sb); + GenerateTvHtml(tv, ref sb); + + var template = new RecentlyAddedTemplate(); + var html = template.LoadTemplate(sb.ToString()); + + Send(html, plexSettings, testEmail); + } + + private void GenerateMovieHtml(IEnumerable movies, PlexSettings plexSettings,ref StringBuilder sb) { sb.Append("

New Movies:



"); sb.Append( @@ -195,6 +217,65 @@ namespace PlexRequests.Services.Jobs sb.Append("

"); } + private void GenerateMovieHtmlDb(IEnumerable movies, ref StringBuilder sb) + { + sb.Append("

New Movies:



"); + sb.Append( + ""); + foreach (var movie in movies) + { + var plexGUID = string.Empty; + try + { + plexGUID = movie.Guid; + + var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID); + + var info = _movieApi.GetMovieInformation(imdbId).Result; + + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append( + ""); + } + catch (Exception e) + { + Log.Error(e); + Log.Error("Exception when trying to process a Movie, either in getting the metadata from Plex OR getting the information from TheMovieDB, Plex GUID = {0}", plexGUID); + } + + } + sb.Append("
"); + sb.AppendFormat( + "", + info.BackdropPath); + sb.Append("
"); + + sb.AppendFormat( + "

{1} {2}

", + info.ImdbId, info.Title, info.ReleaseDate?.ToString("yyyy") ?? string.Empty); + + + + if (info.Genres.Any()) + { + sb.AppendFormat( + "

Genre: {0}

", + string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())); + } + sb.AppendFormat( + "

{0}

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



"); + } + private void GenerateTvHtml(IEnumerable tv, PlexSettings plexSettings, ref StringBuilder sb) { // TV @@ -249,6 +330,65 @@ namespace PlexRequests.Services.Jobs sb.Append("

"); } + private void GenerateTvHtml(IEnumerable tv, ref StringBuilder sb) + { + // TV + sb.Append("

New Episodes:



"); + sb.Append( + ""); + foreach (var t in tv) + { + var plexGUID = string.Empty; + try + { + + plexGUID = t.Guid; + var seasonInfo = PlexHelper.GetSeasonsAndEpisodesFromPlexGuid(plexGUID); + + var info = TvApi.ShowLookupByTheTvDbId(int.Parse(PlexHelper.GetProviderIdFromPlexGuid(plexGUID))); + + var banner = info.image?.original; + if (!string.IsNullOrEmpty(banner)) + { + banner = banner.Replace("http", "https"); // Always use the Https banners + } + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + } + catch (Exception e) + { + Log.Error(e); + Log.Error("Exception when trying to process a TV Show, either in getting the metadata from Plex OR getting the information from TVMaze, Plex GUID = {0}", plexGUID); + } + } + sb.Append("
"); + sb.AppendFormat("", banner); + sb.Append("
"); + + sb.AppendFormat("

{1} {2}

", + info.externals.imdb, info.name, info.premiered.Substring(0, 4)); // Only the year + + sb.AppendFormat("

Season: {0}, Episode: {1}

", seasonInfo.SeasonNumber, seasonInfo.EpisodeNumber); + + if (info.genres.Any()) + { + sb.AppendFormat( + "

Genre: {0}

", + string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())); + } + sb.AppendFormat("

{0}

", + string.IsNullOrEmpty(t.Summary) ? info.summary : t.Summary); // Episode Summary + + sb.Append(""); + sb.Append("
"); + sb.Append("
"); + sb.Append("



"); + } + private void Send(string html, PlexSettings plexSettings, bool testEmail = false) { var settings = EmailSettings.GetSettings(); diff --git a/PlexRequests.Store/PlexDatabase.cs b/PlexRequests.Store/PlexDatabase.cs index edfc6cf22..4f274a96d 100644 --- a/PlexRequests.Store/PlexDatabase.cs +++ b/PlexRequests.Store/PlexDatabase.cs @@ -84,7 +84,7 @@ namespace PlexRequests.Store { using (var con = DbConnection()) { - return con.Query(query, param); + return (IEnumerable)con.Query(query, param); } } } diff --git a/PlexRequests.UI/Helpers/BaseUrlHelper.cs b/PlexRequests.UI/Helpers/BaseUrlHelper.cs index d76d37c39..803f612c6 100644 --- a/PlexRequests.UI/Helpers/BaseUrlHelper.cs +++ b/PlexRequests.UI/Helpers/BaseUrlHelper.cs @@ -122,8 +122,8 @@ namespace PlexRequests.UI.Helpers var sb = new StringBuilder(); var startUrl = $"{content}/Content"; - sb.AppendLine($""); - sb.AppendLine($""); + sb.AppendLine($""); + sb.AppendLine($""); return helper.Raw(sb.ToString()); } diff --git a/PlexRequests.UI/Modules/ApplicationTesterModule.cs b/PlexRequests.UI/Modules/ApplicationTesterModule.cs index 8c3ab2a8c..6963fec9a 100644 --- a/PlexRequests.UI/Modules/ApplicationTesterModule.cs +++ b/PlexRequests.UI/Modules/ApplicationTesterModule.cs @@ -25,7 +25,8 @@ // ************************************************************************/ #endregion using System; - +using System.IO; +using Mono.Data.Sqlite; using Nancy; using Nancy.ModelBinding; using Nancy.Security; @@ -35,6 +36,8 @@ using NLog; using PlexRequests.Api.Interfaces; using PlexRequests.Core; using PlexRequests.Core.SettingModels; +using PlexRequests.Store; +using PlexRequests.Store.Repository; using PlexRequests.UI.Helpers; using PlexRequests.UI.Models; @@ -59,7 +62,7 @@ namespace PlexRequests.UI.Modules Post["/plex"] = _ => PlexTest(); Post["/sickrage"] = _ => SickRageTest(); Post["/headphones"] = _ => HeadphonesTest(); - + Post["/plexdb"] = _ => TestPlexDb(); } private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -223,5 +226,65 @@ namespace PlexRequests.UI.Modules return Response.AsJson(new JsonResponseModel { Result = false, Message = message }); ; } } + + private Response TestPlexDb() + { + var settings = this.Bind(); + var valid = this.Validate(settings); + if (!valid.IsValid) + { + return Response.AsJson(valid.SendJsonError()); + } + try + { + var location = string.Empty; + + if (string.IsNullOrEmpty(settings.PlexDatabaseLocationOverride)) + { + if (Type.GetType("Mono.Runtime") != null) + { + // Mono + location = Path.Combine("/var/lib/plexmediaserver/Library/Application Support/", + "Plex Media Server", "Plug-in Support", "Databases", "com.plexapp.plugins.library.db"); + } + else + { + // Default Windows + location = Path.Combine(Environment.ExpandEnvironmentVariables("%LOCALAPPDATA%"), + "Plex Media Server", "Plug-in Support", "Databases", "com.plexapp.plugins.library.db"); + } + } + else + { + location = Path.Combine(settings.PlexDatabaseLocationOverride, "Plug-in Support", "Databases", "com.plexapp.plugins.library.db"); + } + + if (File.Exists(location)) + { + return Response.AsJson(new JsonResponseModel + { + Result = true, + Message = "Found the database!" + }); + } + + return Response.AsJson(new JsonResponseModel + { + Result = false, + Message = $"Could not find the database at the following full location : {location}" + }); + } + catch (Exception e) + { + Log.Warn("Exception thrown when attempting to find the plex database: "); + Log.Warn(e); + var message = $"Could not find Plex's DB, please check your settings. Exception Message: {e.Message}"; + if (e.InnerException != null) + { + message = $"Could not find Plex's DB, please check your settings. Exception Message: {e.InnerException.Message}"; + } + return Response.AsJson(new JsonResponseModel { Result = false, Message = message }); ; + } + } } } \ No newline at end of file diff --git a/PlexRequests.UI/NinjectModules/ConfigurationModule.cs b/PlexRequests.UI/NinjectModules/ConfigurationModule.cs index 34cfef01d..1382fd9c1 100644 --- a/PlexRequests.UI/NinjectModules/ConfigurationModule.cs +++ b/PlexRequests.UI/NinjectModules/ConfigurationModule.cs @@ -46,6 +46,7 @@ namespace PlexRequests.UI.NinjectModules Bind().To().InSingletonScope(); Bind().To().WithConstructorArgument("provider", new SqliteFactory()); Bind().To().WithConstructorArgument("provider", new SqliteFactory()); + Bind().To(); Bind().To(); diff --git a/PlexRequests.UI/Views/Admin/LandingPage.cshtml b/PlexRequests.UI/Views/Admin/LandingPage.cshtml index e7ddb4417..b33e55991 100644 --- a/PlexRequests.UI/Views/Admin/LandingPage.cshtml +++ b/PlexRequests.UI/Views/Admin/LandingPage.cshtml @@ -121,6 +121,8 @@ }); $('#save').click(function (e) { + e.preventDefault(); + var start = ''; var end = ''; if ($startDate.data("DateTimePicker").date()) { @@ -130,8 +132,6 @@ end = $endDate.data("DateTimePicker").date().toISOString(); } - e.preventDefault(); - var $form = $("#mainForm"); var data = $form.serialize(); diff --git a/PlexRequests.UI/Views/Admin/Plex.cshtml b/PlexRequests.UI/Views/Admin/Plex.cshtml index 2c0da24fd..40a7d9d37 100644 --- a/PlexRequests.UI/Views/Admin/Plex.cshtml +++ b/PlexRequests.UI/Views/Admin/Plex.cshtml @@ -91,7 +91,15 @@
- + +
+ + This is your Plex data directory location, if we cannot manually find it then you need to specify the location! See Here. + +
+
+
+
@@ -101,6 +109,8 @@ + +
@@ -173,6 +183,38 @@ }); }); + $('#dbTest').click(function (e) { + e.preventDefault(); + var url = createBaseUrl(base, '/test/plexdb'); + var $form = $("#mainForm"); + + $('#dbSpinner').attr("class", "fa fa-spinner fa-spin"); + $.ajax({ + type: $form.prop("method"), + url: url, + data: $form.serialize(), + dataType: "json", + success: function (response) { + $('#dbSpinner').attr("class", ""); + console.log(response); + if (response.result === true) { + generateNotify(response.message, "success"); + + $('#dbSpinner').attr("class", "fa fa-check"); + } else { + generateNotify(response.message, "warning"); + $('#dbSpinner').attr("class", "fa fa-times"); + } + }, + error: function (e) { + + $('#spinner').attr("class", "fa fa-times"); + console.log(e); + generateNotify("Something went wrong!", "danger"); + } + }); + }); + $('#requestToken').click(function (e) { e.preventDefault(); var $form = $("#mainForm");