From 6ea39079238be99fb0b78e940cae3090d6280f90 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 9 Dec 2016 23:38:01 +0000 Subject: [PATCH] Fixed #749 Fixed an issue where we were adding the read only permission when creating the admin --- PlexRequests.Api.Interfaces/IPlexApi.cs | 3 +- ...AddedModel.cs => RecentlyAddedModelOld.cs} | 112 ++++++++++- .../PlexRequests.Api.Models.csproj | 2 +- PlexRequests.Api/PlexApi.cs | 36 +++- PlexRequests.Services/Jobs/RecentlyAdded.cs | 187 ++++++++++++++++-- PlexRequests.UI/Modules/UserWizardModule.cs | 2 +- 6 files changed, 314 insertions(+), 28 deletions(-) rename PlexRequests.Api.Models/Plex/{RecentlyAddedModel.cs => RecentlyAddedModelOld.cs} (58%) diff --git a/PlexRequests.Api.Interfaces/IPlexApi.cs b/PlexRequests.Api.Interfaces/IPlexApi.cs index 3588b0ecd..bfd42ae50 100644 --- a/PlexRequests.Api.Interfaces/IPlexApi.cs +++ b/PlexRequests.Api.Interfaces/IPlexApi.cs @@ -44,6 +44,7 @@ namespace PlexRequests.Api.Interfaces PlexSearch GetAllEpisodes(string authToken, Uri host, string section, int startPage, int returnCount); PlexServer GetServer(string authToken); PlexSeasonMetadata GetSeasons(string authToken, Uri plexFullHost, string ratingKey); - RecentlyAddedModel RecentlyAdded(string authToken, Uri plexFullHost, string sectionId); + RecentlyAddedModelOld RecentlyAddedOld(string authToken, Uri plexFullHost, string sectionId); + PlexRecentlyAddedModel RecentlyAdded(string authToken, Uri plexFullHost, string sectionId); } } \ No newline at end of file diff --git a/PlexRequests.Api.Models/Plex/RecentlyAddedModel.cs b/PlexRequests.Api.Models/Plex/RecentlyAddedModelOld.cs similarity index 58% rename from PlexRequests.Api.Models/Plex/RecentlyAddedModel.cs rename to PlexRequests.Api.Models/Plex/RecentlyAddedModelOld.cs index 136f48a81..01b64a4f0 100644 --- a/PlexRequests.Api.Models/Plex/RecentlyAddedModel.cs +++ b/PlexRequests.Api.Models/Plex/RecentlyAddedModelOld.cs @@ -1,7 +1,7 @@ #region Copyright // /************************************************************************ // Copyright (c) 2016 Jamie Rees -// File: RecentlyAddedModel.cs +// File: RecentlyAddedModelOld.cs // Created By: Jamie Rees // // Permission is hereby granted, free of charge, to any person obtaining @@ -110,7 +110,7 @@ namespace PlexRequests.Api.Models.Plex public string tag { get; set; } } - public class RecentlyAddedModel + public class RecentlyAddedModelOld { public string _elementType { get; set; } public string allowSync { get; set; } @@ -130,4 +130,112 @@ namespace PlexRequests.Api.Models.Plex public string viewMode { get; set; } public List _children { get; set; } } + + + // 1.3 and forward! + public class PartRecentlyAdded + { + public int id { get; set; } + public string key { get; set; } + public int duration { get; set; } + public string file { get; set; } + public double size { get; set; } + public string audioProfile { get; set; } + public string container { get; set; } + public string videoProfile { get; set; } + public string deepAnalysisVersion { get; set; } + public string requiredBandwidths { get; set; } + } + + public class Medium + { + public string videoResolution { get; set; } + public int id { get; set; } + public int duration { get; set; } + public int bitrate { get; set; } + public int width { get; set; } + public int height { get; set; } + public double aspectRatio { get; set; } + public int audioChannels { get; set; } + public string audioCodec { get; set; } + public string videoCodec { get; set; } + public string container { get; set; } + public string videoFrameRate { get; set; } + public string audioProfile { get; set; } + public string videoProfile { get; set; } + public List Part { get; set; } + } + + public class DirectorRecentlyAdded + { + public string tag { get; set; } + } + + public class WriterRecentlyAdded + { + public string tag { get; set; } + } + + public class Metadata + { + public string ratingKey { get; set; } + public string key { get; set; } + public string parentRatingKey { get; set; } + public string grandparentRatingKey { get; set; } + public string type { get; set; } + public string title { get; set; } + public string titleSort { get; set; } + public string grandparentKey { get; set; } + public string parentKey { get; set; } + public string grandparentTitle { get; set; } + public string contentRating { get; set; } + public string summary { get; set; } + public int index { get; set; } + public int parentIndex { get; set; } + public int year { get; set; } + public string thumb { get; set; } + public string art { get; set; } + public string parentThumb { get; set; } + public string grandparentThumb { get; set; } + public string grandparentArt { get; set; } + public string grandparentTheme { get; set; } + public int duration { get; set; } + public string originallyAvailableAt { get; set; } + public int addedAt { get; set; } + public int updatedAt { get; set; } + public List Media { get; set; } + public List Director { get; set; } + public List Writer { get; set; } + public int? viewCount { get; set; } + public int? lastViewedAt { get; set; } + public double? rating { get; set; } + } + + public class MediaContainer + { + public double size { get; set; } + public double totalSize { get; set; } + public bool allowSync { get; set; } + public string art { get; set; } + public string identifier { get; set; } + public int librarySectionID { get; set; } + public string librarySectionTitle { get; set; } + public string librarySectionUUID { get; set; } + public string mediaTagPrefix { get; set; } + public int mediaTagVersion { get; set; } + public bool mixedParents { get; set; } + public bool nocache { get; set; } + public int offset { get; set; } + public string thumb { get; set; } + public string title1 { get; set; } + public string title2 { get; set; } + public string viewGroup { get; set; } + public int viewMode { get; set; } + public List Metadata { get; set; } + } + + public class PlexRecentlyAddedModel + { + public MediaContainer MediaContainer { get; set; } + } } \ No newline at end of file diff --git a/PlexRequests.Api.Models/PlexRequests.Api.Models.csproj b/PlexRequests.Api.Models/PlexRequests.Api.Models.csproj index a1638df6f..1d29ec759 100644 --- a/PlexRequests.Api.Models/PlexRequests.Api.Models.csproj +++ b/PlexRequests.Api.Models/PlexRequests.Api.Models.csproj @@ -73,7 +73,7 @@ - + diff --git a/PlexRequests.Api/PlexApi.cs b/PlexRequests.Api/PlexApi.cs index 2e03ad274..b20971910 100644 --- a/PlexRequests.Api/PlexApi.cs +++ b/PlexRequests.Api/PlexApi.cs @@ -346,7 +346,7 @@ namespace PlexRequests.Api return servers; } - public RecentlyAddedModel RecentlyAdded(string authToken, Uri plexFullHost, string sectionId) + public RecentlyAddedModelOld RecentlyAddedOld(string authToken, Uri plexFullHost, string sectionId) { var request = new RestRequest { @@ -360,7 +360,7 @@ namespace PlexRequests.Api try { - var lib = RetryHandler.Execute(() => Api.ExecuteJson(request, plexFullHost), + var lib = RetryHandler.Execute(() => Api.ExecuteJson(request, plexFullHost), (exception, timespan) => Log.Error(exception, "Exception when calling RecentlyAddedModel for Plex, Retrying {0}", timespan), new[] { TimeSpan.FromSeconds (5), TimeSpan.FromSeconds(10), @@ -372,7 +372,37 @@ namespace PlexRequests.Api catch (Exception e) { Log.Error(e, "There has been a API Exception when attempting to get the Plex RecentlyAddedModel"); - return new RecentlyAddedModel(); + return new RecentlyAddedModelOld(); + } + } + + public PlexRecentlyAddedModel RecentlyAdded(string authToken, Uri plexFullHost, string sectionId) + { + var request = new RestRequest + { + Method = Method.GET, + Resource = "library/sections/{sectionId}/recentlyAdded" + }; + + request.AddUrlSegment("sectionId", sectionId); + AddHeaders(ref request, authToken, true); + AddLimitHeaders(ref request, 0, 25); + + try + { + var lib = RetryHandler.Execute(() => Api.ExecuteJson(request, plexFullHost), + (exception, timespan) => Log.Error(exception, "Exception when calling PlexRecentlyAddedModel for Plex, Retrying {0}", timespan), new[] { + TimeSpan.FromSeconds (5), + TimeSpan.FromSeconds(10), + TimeSpan.FromSeconds(30) + }); + + return lib; + } + catch (Exception e) + { + Log.Error(e, "There has been a API Exception when attempting to get the Plex RecentlyAddedModel"); + return new PlexRecentlyAddedModel(); } } diff --git a/PlexRequests.Services/Jobs/RecentlyAdded.cs b/PlexRequests.Services/Jobs/RecentlyAdded.cs index bc4c2c308..5172e2980 100644 --- a/PlexRequests.Services/Jobs/RecentlyAdded.cs +++ b/PlexRequests.Services/Jobs/RecentlyAdded.cs @@ -119,32 +119,58 @@ namespace PlexRequests.Services.Jobs var libs = Api.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri); Log.Debug("Getting Plex Library Sections"); - var tvSection = libs.Directories.FirstOrDefault(x => x.type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase)); + var tvSection = libs.Directories.FirstOrDefault(x => x.type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase)); // We could have more than 1 lib Log.Debug("Filtered sections for TV"); - var movieSection = libs.Directories.FirstOrDefault(x => x.type.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase)); + var movieSection = libs.Directories.FirstOrDefault(x => x.type.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase)); // We could have more than 1 lib Log.Debug("Filtered sections for Movies"); + + var plexVersion = Api.GetStatus(plexSettings.PlexAuthToken, plexSettings.FullUri).Version; + + var html = string.Empty; + if (plexVersion.StartsWith("1.3")) + { + var recentlyAddedTv = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, tvSection?.Key); + Log.Debug("Got RecentlyAdded TV Shows"); + var recentlyAddedMovies = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, movieSection?.Key); + Log.Debug("Got RecentlyAdded Movies"); + + Log.Debug("Started Generating Movie HTML"); + GenerateMovieHtml(recentlyAddedMovies, plexSettings, sb); + Log.Debug("Finished Generating Movie HTML"); + Log.Debug("Started Generating TV HTML"); + GenerateTvHtml(recentlyAddedTv, plexSettings, sb); + Log.Debug("Finished Generating TV HTML"); + + var template = new RecentlyAddedTemplate(); + html = template.LoadTemplate(sb.ToString()); + Log.Debug("Loaded the template"); + } + else + { + // Old API + var recentlyAddedTv = Api.RecentlyAddedOld(plexSettings.PlexAuthToken, plexSettings.FullUri, tvSection?.Key); + Log.Debug("Got RecentlyAdded TV Shows"); + var recentlyAddedMovies = Api.RecentlyAddedOld(plexSettings.PlexAuthToken, plexSettings.FullUri, movieSection?.Key); + Log.Debug("Got RecentlyAdded Movies"); + + Log.Debug("Started Generating Movie HTML"); + GenerateMovieHtml(recentlyAddedMovies, plexSettings, sb); + Log.Debug("Finished Generating Movie HTML"); + Log.Debug("Started Generating TV HTML"); + GenerateTvHtml(recentlyAddedTv, plexSettings, sb); + Log.Debug("Finished Generating TV HTML"); + + var template = new RecentlyAddedTemplate(); + html = template.LoadTemplate(sb.ToString()); + Log.Debug("Loaded the template"); + } - - var recentlyAddedTv = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, tvSection.Key); - Log.Debug("Got RecentlyAdded TV Shows"); - var recentlyAddedMovies = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, movieSection.Key); - Log.Debug("Got RecentlyAdded Movies"); - - Log.Debug("Started Generating Movie HTML"); - GenerateMovieHtml(recentlyAddedMovies, plexSettings, sb); - Log.Debug("Finished Generating Movie HTML"); - Log.Debug("Started Generating TV HTML"); - GenerateTvHtml(recentlyAddedTv, plexSettings, sb); - Log.Debug("Finished Generating TV HTML"); - - var template = new RecentlyAddedTemplate(); - var html = template.LoadTemplate(sb.ToString()); - Log.Debug("Loaded the template"); + Send(newletterSettings, html, plexSettings, testEmail); } - private void GenerateMovieHtml(RecentlyAddedModel movies, PlexSettings plexSettings, StringBuilder sb) + private void GenerateMovieHtml(RecentlyAddedModelOld movies, PlexSettings plexSettings, StringBuilder sb) { var orderedMovies = movies?._children?.OrderByDescending(x => x?.addedAt.UnixTimeStampToDateTime()).ToList() ?? new List(); sb.Append("

New Movies:



"); @@ -200,7 +226,63 @@ namespace PlexRequests.Services.Jobs sb.Append("

"); } - private void GenerateTvHtml(RecentlyAddedModel tv, PlexSettings plexSettings, StringBuilder sb) + private void GenerateMovieHtml(PlexRecentlyAddedModel movies, PlexSettings plexSettings, StringBuilder sb) + { + var orderedMovies = movies?.MediaContainer?.Metadata?.OrderByDescending(x => x?.addedAt.UnixTimeStampToDateTime()).ToList() ?? new List(); + sb.Append("

New Movies:



"); + sb.Append( + ""); + foreach (var movie in orderedMovies) + { + var plexGUID = string.Empty; + try + { + var metaData = Api.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, + movie.ratingKey.ToString()); + + plexGUID = metaData.Video.Guid; + + var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID); + var info = _movieApi.GetMovieInformation(imdbId).Result; + if (info == null) + { + throw new Exception($"Movie with Imdb id {imdbId} returned null from the MovieApi"); + } + AddImageInsideTable(sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}"); + + sb.Append(""); + sb.Append( + "
"); + + Href(sb, $"https://www.imdb.com/title/{info.ImdbId}/"); + Header(sb, 3, $"{info.Title} {info.ReleaseDate?.ToString("yyyy") ?? string.Empty}"); + EndTag(sb, "a"); + + if (info.Genres.Any()) + { + AddParagraph(sb, + $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); + } + + AddParagraph(sb, info.Overview); + } + 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); + } + finally + { + EndLoopHtml(sb); + } + + } + sb.Append("


"); + } + + private void GenerateTvHtml(RecentlyAddedModelOld tv, PlexSettings plexSettings, StringBuilder sb) { var orderedTv = tv?._children; if (orderedTv == null) @@ -265,6 +347,71 @@ namespace PlexRequests.Services.Jobs sb.Append("

"); } + private void GenerateTvHtml(PlexRecentlyAddedModel tv, PlexSettings plexSettings, StringBuilder sb) + { + var orderedTv = tv?.MediaContainer?.Metadata; + if (orderedTv == null) + { + return; + } + orderedTv = orderedTv.OrderByDescending(x => x?.addedAt.UnixTimeStampToDateTime()).ToList(); + // TV + sb.Append("

New Episodes:



"); + sb.Append( + ""); + foreach (var t in orderedTv) + { + var plexGUID = string.Empty; + try + { + + var parentMetaData = Api.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri, + t.parentRatingKey.ToString()); + + plexGUID = parentMetaData.Directory.Guid; + + 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 + } + AddImageInsideTable(sb, banner); + + sb.Append(""); + sb.Append( + "
"); + + var title = $"{t.grandparentTitle} - {t.title} {t.originallyAvailableAt?.Substring(0, 4)}"; + + Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/"); + Header(sb, 3, title); + EndTag(sb, "a"); + + AddParagraph(sb, $"Season: {t.parentIndex}, Episode: {t.index}"); + if (info.genres.Any()) + { + AddParagraph(sb, $"Genre: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}"); + } + + AddParagraph(sb, string.IsNullOrEmpty(t.summary) ? info.summary : t.summary); + } + 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); + } + finally + { + EndLoopHtml(sb); + } + } + sb.Append("


"); + } + private void Send(NewletterSettings newletterSettings, string html, PlexSettings plexSettings, bool testEmail = false) { Log.Debug("Entering Send"); diff --git a/PlexRequests.UI/Modules/UserWizardModule.cs b/PlexRequests.UI/Modules/UserWizardModule.cs index b475294b9..c4a90027d 100644 --- a/PlexRequests.UI/Modules/UserWizardModule.cs +++ b/PlexRequests.UI/Modules/UserWizardModule.cs @@ -183,7 +183,7 @@ namespace PlexRequests.UI.Modules private async Task CreateUser() { var username = (string)Request.Form.Username; - var userId = Mapper.CreateUser(username, Request.Form.Password, EnumHelper.All(), 0); + var userId = Mapper.CreateUser(username, Request.Form.Password, EnumHelper.All() - (int)Permissions.ReadOnlyUser, 0); Analytics.TrackEventAsync(Category.Wizard, Action.Finish, "Finished the wizard", username, CookieHelper.GetAnalyticClientId(Cookies)); Session[SessionKeys.UsernameKey] = username;