From 67b124148c3f2da0e16885108e6b251a08188c42 Mon Sep 17 00:00:00 2001 From: "Jamie.Rees" Date: Mon, 17 Oct 2016 17:31:38 +0100 Subject: [PATCH] Plex DB --- PlexRequests.Core/IPlexReadOnlyDatabase.cs | 11 +++ PlexRequests.Core/PlexReadOnlyDatabase.cs | 68 +++++++++++++ PlexRequests.Core/PlexRequests.Core.csproj | 2 + .../SettingModels/PlexSettings.cs | 1 + PlexRequests.Store/IPlexDatabase.cs | 15 +++ .../Models/Plex/MetadataItems.cs | 95 +++++++++++++++++++ PlexRequests.Store/PlexDatabase.cs | 91 ++++++++++++++++++ PlexRequests.Store/PlexRequests.Store.csproj | 4 + .../Content/bootstrap-switch.min.css | 22 +++++ .../Content/bootstrap-switch.min.js | 22 +++++ PlexRequests.UI/Helpers/BaseUrlHelper.cs | 22 +++-- .../NinjectModules/ConfigurationModule.cs | 2 + PlexRequests.UI/PlexRequests.UI.csproj | 6 ++ PlexRequests.UI/Views/Admin/Plex.cshtml | 12 ++- PlexRequests.UI/Views/Admin/_Sidebar.cshtml | 1 + .../Views/Shared/Partial/_Navbar.cshtml | 1 - 16 files changed, 365 insertions(+), 10 deletions(-) create mode 100644 PlexRequests.Core/IPlexReadOnlyDatabase.cs create mode 100644 PlexRequests.Core/PlexReadOnlyDatabase.cs create mode 100644 PlexRequests.Store/IPlexDatabase.cs create mode 100644 PlexRequests.Store/Models/Plex/MetadataItems.cs create mode 100644 PlexRequests.Store/PlexDatabase.cs create mode 100644 PlexRequests.UI/Content/bootstrap-switch.min.css create mode 100644 PlexRequests.UI/Content/bootstrap-switch.min.js diff --git a/PlexRequests.Core/IPlexReadOnlyDatabase.cs b/PlexRequests.Core/IPlexReadOnlyDatabase.cs new file mode 100644 index 000000000..93a4dc98f --- /dev/null +++ b/PlexRequests.Core/IPlexReadOnlyDatabase.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using PlexRequests.Store.Models.Plex; + +namespace PlexRequests.Core +{ + public interface IPlexReadOnlyDatabase + { + IEnumerable GetItemsAddedAfterDate(DateTime dateTime); + } +} \ No newline at end of file diff --git a/PlexRequests.Core/PlexReadOnlyDatabase.cs b/PlexRequests.Core/PlexReadOnlyDatabase.cs new file mode 100644 index 000000000..ff4291756 --- /dev/null +++ b/PlexRequests.Core/PlexReadOnlyDatabase.cs @@ -0,0 +1,68 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexReadOnlyDatabase.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; +using System.Collections.Generic; +using System.IO; +using PlexRequests.Core.SettingModels; +using PlexRequests.Store; +using PlexRequests.Store.Models.Plex; + +namespace PlexRequests.Core +{ + public class PlexReadOnlyDatabase : IPlexReadOnlyDatabase + { + public PlexReadOnlyDatabase(IPlexDatabase plexDatabase, ISettingsService plexSettings) + { + Plex = plexDatabase; + + var settings = plexSettings.GetSettings(); + + if (!string.IsNullOrEmpty(settings.PlexDatabaseLocationOverride)) + { + Plex.DbLocation = settings.PlexDatabaseLocationOverride; + } + else if (Type.GetType("Mono.Runtime") != null) + { + // Mono + Plex.DbLocation = Path.Combine("/var/lib/plexmediaserver/Library/Application Support/", "Plex Media Server", "Plug-in Support", "Databases", "com.plexapp.plugins.library.db"); + } + else + { + // Default Windows + Plex.DbLocation = Path.Combine(Environment.ExpandEnvironmentVariables("%LOCALAPPDATA%"), "Plex Media Server", "Plug-in Support", "Databases", "com.plexapp.plugins.library.db"); + } + } + private IPlexDatabase Plex { get; } + + public IEnumerable GetItemsAddedAfterDate(DateTime dateTime) + { + return Plex.QueryMetadataItems("select * from metadata_items where added_at > @AddedAt", + new { AddedAt = dateTime }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.Core/PlexRequests.Core.csproj b/PlexRequests.Core/PlexRequests.Core.csproj index d3cd82a7b..055061291 100644 --- a/PlexRequests.Core/PlexRequests.Core.csproj +++ b/PlexRequests.Core/PlexRequests.Core.csproj @@ -69,6 +69,7 @@ + @@ -85,6 +86,7 @@ + diff --git a/PlexRequests.Core/SettingModels/PlexSettings.cs b/PlexRequests.Core/SettingModels/PlexSettings.cs index 09be5fb15..108edee19 100644 --- a/PlexRequests.Core/SettingModels/PlexSettings.cs +++ b/PlexRequests.Core/SettingModels/PlexSettings.cs @@ -40,5 +40,6 @@ namespace PlexRequests.Core.SettingModels public string PlexAuthToken { get; set; } public string MachineIdentifier { get; set; } + public string PlexDatabaseLocationOverride { get; set; } } } \ No newline at end of file diff --git a/PlexRequests.Store/IPlexDatabase.cs b/PlexRequests.Store/IPlexDatabase.cs new file mode 100644 index 000000000..ac8b6fbea --- /dev/null +++ b/PlexRequests.Store/IPlexDatabase.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Data; +using System.Threading.Tasks; +using PlexRequests.Store.Models.Plex; + +namespace PlexRequests.Store +{ + public interface IPlexDatabase + { + IEnumerable GetMetadata(); + string DbLocation { get; set; } + Task> GetMetadataAsync(); + IEnumerable QueryMetadataItems(string query, object param); + } +} \ No newline at end of file diff --git a/PlexRequests.Store/Models/Plex/MetadataItems.cs b/PlexRequests.Store/Models/Plex/MetadataItems.cs new file mode 100644 index 000000000..179026c03 --- /dev/null +++ b/PlexRequests.Store/Models/Plex/MetadataItems.cs @@ -0,0 +1,95 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: MetadataItems.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; +using System.Data.Linq.Mapping; + +namespace PlexRequests.Store.Models.Plex +{ + [Table(Name = "metadata_items")] + public class MetadataItems + { + [Column(IsPrimaryKey = true)] + public int Id { get; set; } + + [Column(Name = "library_section_id")] + public int LibrarySectionId { get; set; } + + [Column(Name = "parent_id")] + public int ParentId { get; set; } + + [Column(Name = "metadata_type")] + public int MetadataType { get; set; } + + [Column(Name = "guid")] + public string Guid { get; set; } + + [Column(Name = "media_item_count")] + public int MediaItemCount { get; set; } + + [Column(Name = "title")] + public string Title { get; set; } + + [Column(Name = "title_sort")] + public string TitleSort { get; set; } + + [Column(Name = "OriginalTitle")] + public string OriginalTitle { get; set; } + + [Column(Name = "studio")] + public string Studio { get; set; } + [Column(Name = "rating")] + public float Rating { get; set; } + [Column(Name = "rating_count")] + public int RatingCount { get; set; } + [Column(Name = "tagline")] + public string Tagline { get; set; } + [Column(Name = "summary")] + public string Summary { get; set; } + [Column(Name = "trivia")] + public string Trivia { get; set; } + [Column(Name = "quotes")] + public string Quotes { get; set; } + [Column(Name = "content_rating")] + public string ContentRating { get; set; } + [Column(Name = "content_rating_age")] + public int ContentRatingAge { get; set; } + [Column(Name = "Index")] + public int Index { get; set; } + // SKIP Until Date Times + + [Column(Name = "originally_available_at")] + public DateTime OriginallyAvailableAt { get; set; } + [Column(Name = "available_at")] + public DateTime AvailableAt { get; set; } + [Column(Name = "expires_at")] + public DateTime ExpiresAt { get; set; } + // Skip RefreshedAt and Year + [Column(Name = "added_at")] + public DateTime AddedAt { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.Store/PlexDatabase.cs b/PlexRequests.Store/PlexDatabase.cs new file mode 100644 index 000000000..edfc6cf22 --- /dev/null +++ b/PlexRequests.Store/PlexDatabase.cs @@ -0,0 +1,91 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexDatabase.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; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Threading.Tasks; +using Dapper; +using Dapper.Contrib.Extensions; +using Mono.Data.Sqlite; +using PlexRequests.Store.Models.Plex; + +namespace PlexRequests.Store +{ + /// + /// We should only ever READ, NEVER WRITE! + /// + public class PlexDatabase : IPlexDatabase + { + public PlexDatabase(SqliteFactory provider) + { + Factory = provider; + } + + private SqliteFactory Factory { get; } + /// + /// https://support.plex.tv/hc/en-us/articles/202915258-Where-is-the-Plex-Media-Server-data-directory-located- + /// + public string DbLocation { get; set; } + + private IDbConnection DbConnection() + { + var fact = Factory.CreateConnection(); + if (fact == null) + { + throw new SqliteException("Factory returned null"); + } + fact.ConnectionString = "Data Source=" + "Plex Path"; + return fact; + } + + public IEnumerable GetMetadata() + { + using (var con = DbConnection()) + { + return con.GetAll(); + } + } + + public async Task> GetMetadataAsync() + { + using (var con = DbConnection()) + { + return await con.GetAllAsync(); + } + } + + public IEnumerable QueryMetadataItems(string query, object param) + { + using (var con = DbConnection()) + { + return con.Query(query, param); + } + } + } +} \ No newline at end of file diff --git a/PlexRequests.Store/PlexRequests.Store.csproj b/PlexRequests.Store/PlexRequests.Store.csproj index 1e6a22cb6..78f777dbc 100644 --- a/PlexRequests.Store/PlexRequests.Store.csproj +++ b/PlexRequests.Store/PlexRequests.Store.csproj @@ -64,12 +64,15 @@ + + + @@ -120,6 +123,7 @@ PlexRequests.Helpers +