diff --git a/PlexRequests.Core/SettingModels/PlexSettings.cs b/PlexRequests.Core/SettingModels/PlexSettings.cs index e83e61f4d..09be5fb15 100644 --- a/PlexRequests.Core/SettingModels/PlexSettings.cs +++ b/PlexRequests.Core/SettingModels/PlexSettings.cs @@ -24,6 +24,9 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ #endregion + +using Newtonsoft.Json; + namespace PlexRequests.Core.SettingModels { public sealed class PlexSettings : ExternalSettings @@ -36,5 +39,6 @@ namespace PlexRequests.Core.SettingModels public bool EnableTvEpisodeSearching { get; set; } public string PlexAuthToken { get; set; } + public string MachineIdentifier { get; set; } } } \ No newline at end of file diff --git a/PlexRequests.Core/Setup.cs b/PlexRequests.Core/Setup.cs index 50b27dd2d..dac15a731 100644 --- a/PlexRequests.Core/Setup.cs +++ b/PlexRequests.Core/Setup.cs @@ -26,6 +26,7 @@ #endregion using System; +using System.Linq; using System.Text.RegularExpressions; using Mono.Data.Sqlite; @@ -66,6 +67,11 @@ namespace PlexRequests.Core { MigrateToVersion1900(); } + + if(version > 1899 && version <= 1910) + { + MigrateToVersion1910(); + } } return Db.DbConnection().ConnectionString; @@ -244,5 +250,30 @@ namespace PlexRequests.Core Log.Error(e); } } + + /// + /// Migrates to version1910. + /// + public void MigrateToVersion1910() + { + try + { + // Get the new machine Identifier + var settings = new SettingsServiceV2(new SettingsJsonRepository(Db, new MemoryCacheProvider())); + var plex = settings.GetSettings(); + if (!string.IsNullOrEmpty(plex.PlexAuthToken)) + { + var api = new PlexApi(new ApiRequest()); + var server = api.GetServer(plex.PlexAuthToken); // Get the server info + plex.MachineIdentifier = server.Server.FirstOrDefault(x => x.AccessToken == plex.PlexAuthToken)?.MachineIdentifier; + + settings.SaveSettings(plex); // Save the new settings + } + } + catch (Exception e) + { + Log.Error(e); + } + } } } diff --git a/PlexRequests.Helpers.Tests/PlexHelperTests.cs b/PlexRequests.Helpers.Tests/PlexHelperTests.cs index 6f09d6c39..33a1bf1a3 100644 --- a/PlexRequests.Helpers.Tests/PlexHelperTests.cs +++ b/PlexRequests.Helpers.Tests/PlexHelperTests.cs @@ -61,6 +61,12 @@ namespace PlexRequests.Helpers.Tests return PlexHelper.GetSeasonNumberFromTitle(title); } + [TestCaseSource(nameof(MediaUrls))] + public string GetPlexMediaUrlTest(string machineId, string mediaId) + { + return PlexHelper.GetPlexMediaUrl(machineId, mediaId); + } + private static IEnumerable PlexGuids { get @@ -75,6 +81,15 @@ namespace PlexRequests.Helpers.Tests } } + private static IEnumerable MediaUrls + { + get + { + yield return new TestCaseData("abcd","99").Returns("https://app.plex.tv/web/app#!/server/abcd/details/%2Flibrary%2Fmetadata%2F99").SetName("Test 1"); + yield return new TestCaseData("a54d1db669799308cd704b791f331eca6648b952", "51").Returns("https://app.plex.tv/web/app#!/server/a54d1db669799308cd704b791f331eca6648b952/details/%2Flibrary%2Fmetadata%2F51").SetName("Test 2"); + } + } + private static IEnumerable SeasonNumbers { get diff --git a/PlexRequests.Helpers/PlexHelper.cs b/PlexRequests.Helpers/PlexHelper.cs index baafcd451..1e186ddba 100644 --- a/PlexRequests.Helpers/PlexHelper.cs +++ b/PlexRequests.Helpers/PlexHelper.cs @@ -95,6 +95,13 @@ namespace PlexRequests.Helpers return 0; } + + public static string GetPlexMediaUrl(string machineId, string mediaId) + { + var url = + $"https://app.plex.tv/web/app#!/server/{machineId}/details/%2Flibrary%2Fmetadata%2F{mediaId}"; + return url; + } } public class EpisodeModelHelper diff --git a/PlexRequests.Services.Tests/PlexAvailabilityCheckerTests.cs b/PlexRequests.Services.Tests/PlexAvailabilityCheckerTests.cs index 5b8ba361f..3b152d7ee 100644 --- a/PlexRequests.Services.Tests/PlexAvailabilityCheckerTests.cs +++ b/PlexRequests.Services.Tests/PlexAvailabilityCheckerTests.cs @@ -242,6 +242,7 @@ namespace PlexRequests.Services.Tests } }); CacheMock.Setup(x => x.Get>(CacheKeys.PlexLibaries)).Returns(cachedMovies); + SettingsMock.Setup(x => x.GetSettings()).Returns(F.Create()); var movies = Checker.GetPlexMovies(); Assert.That(movies.Any(x => x.ProviderId == "1212")); @@ -258,6 +259,7 @@ namespace PlexRequests.Services.Tests new Directory1 {Type = "show", Title = "title1", Year = "2016", ProviderId = "1212", Seasons = new List()} } }); + SettingsMock.Setup(x => x.GetSettings()).Returns(F.Create()); CacheMock.Setup(x => x.Get>(CacheKeys.PlexLibaries)).Returns(cachedTv); var movies = Checker.GetPlexTvShows(); diff --git a/PlexRequests.Services/Interfaces/IAvailabilityChecker.cs b/PlexRequests.Services/Interfaces/IAvailabilityChecker.cs index 8992e6545..d966e2b5f 100644 --- a/PlexRequests.Services/Interfaces/IAvailabilityChecker.cs +++ b/PlexRequests.Services/Interfaces/IAvailabilityChecker.cs @@ -42,6 +42,9 @@ namespace PlexRequests.Services.Interfaces List GetPlexAlbums(); bool IsAlbumAvailable(PlexAlbum[] plexAlbums, string title, string year, string artist); bool IsEpisodeAvailable(string theTvDbId, int season, int episode); + PlexAlbum GetAlbum(PlexAlbum[] plexAlbums, string title, string year, string artist); + PlexMovie GetMovie(PlexMovie[] plexMovies, string title, string year, string providerId = null); + PlexTvShow GetTvShow(PlexTvShow[] plexShows, string title, string year, string providerId = null, int[] seasons = null); /// /// Gets the episode's stored in the cache. /// diff --git a/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs b/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs index e58a18c17..b5c284756 100644 --- a/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs +++ b/PlexRequests.Services/Jobs/PlexAvailabilityChecker.cs @@ -158,6 +158,7 @@ namespace PlexRequests.Services.Jobs public List GetPlexMovies() { + var settings = Plex.GetSettings(); var movies = new List(); var libs = Cache.Get>(CacheKeys.PlexLibaries); if (libs != null) @@ -175,6 +176,7 @@ namespace PlexRequests.Services.Jobs ReleaseYear = video.Year, Title = video.Title, ProviderId = video.ProviderId, + Url = PlexHelper.GetPlexMediaUrl(settings.MachineIdentifier, video.RatingKey) })); } } @@ -182,6 +184,12 @@ namespace PlexRequests.Services.Jobs } public bool IsMovieAvailable(PlexMovie[] plexMovies, string title, string year, string providerId = null) + { + var movie = GetMovie(plexMovies, title, year, providerId); + return movie != null; + } + + public PlexMovie GetMovie(PlexMovie[] plexMovies, string title, string year, string providerId = null) { var advanced = !string.IsNullOrEmpty(providerId); foreach (var movie in plexMovies) @@ -191,20 +199,21 @@ namespace PlexRequests.Services.Jobs if (!string.IsNullOrEmpty(movie.ProviderId) && movie.ProviderId.Equals(providerId, StringComparison.InvariantCultureIgnoreCase)) { - return true; + return movie; } } if (movie.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) && movie.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase)) { - return true; + return movie; } } - return false; + return null; } public List GetPlexTvShows() { + var settings = Plex.GetSettings(); var shows = new List(); var libs = Cache.Get>(CacheKeys.PlexLibaries); if (libs != null) @@ -224,7 +233,9 @@ namespace PlexRequests.Services.Jobs Title = x.Title, ReleaseYear = x.Year, ProviderId = x.ProviderId, - Seasons = x.Seasons?.Select(d => PlexHelper.GetSeasonNumberFromTitle(d.Title)).ToArray() + Seasons = x.Seasons?.Select(d => PlexHelper.GetSeasonNumberFromTitle(d.Title)).ToArray(), + Url = PlexHelper.GetPlexMediaUrl(settings.MachineIdentifier, x.RatingKey) + })); } } @@ -232,6 +243,14 @@ namespace PlexRequests.Services.Jobs } public bool IsTvShowAvailable(PlexTvShow[] plexShows, string title, string year, string providerId = null, int[] seasons = null) + { + var show = GetTvShow(plexShows, title, year, providerId, seasons); + return show != null; + } + + + public PlexTvShow GetTvShow(PlexTvShow[] plexShows, string title, string year, string providerId = null, + int[] seasons = null) { var advanced = !string.IsNullOrEmpty(providerId); foreach (var show in plexShows) @@ -242,23 +261,23 @@ namespace PlexRequests.Services.Jobs { if (seasons.Any(season => show.Seasons.Contains(season))) { - return true; + return show; } - return false; + return null; } if (!string.IsNullOrEmpty(show.ProviderId) && show.ProviderId.Equals(providerId, StringComparison.InvariantCultureIgnoreCase)) { - return true; + return show; } } if (show.Title.Equals(title, StringComparison.CurrentCultureIgnoreCase) && show.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase)) { - return true; + return show; } } - return false; + return null; } public bool IsEpisodeAvailable(string theTvDbId, int season, int episode) @@ -328,6 +347,7 @@ namespace PlexRequests.Services.Jobs public List GetPlexAlbums() { + var settings = Plex.GetSettings(); var albums = new List(); var libs = Cache.Get>(CacheKeys.PlexLibaries); if (libs != null) @@ -344,7 +364,8 @@ namespace PlexRequests.Services.Jobs { Title = x.Title, ReleaseYear = x.Year, - Artist = x.ParentTitle + Artist = x.ParentTitle, + Url = PlexHelper.GetPlexMediaUrl(settings.MachineIdentifier, x.RatingKey) })); } } @@ -355,7 +376,13 @@ namespace PlexRequests.Services.Jobs { return plexAlbums.Any(x => x.Title.Contains(title) && - //x.ReleaseYear.Equals(year, StringComparison.CurrentCultureIgnoreCase) && + x.Artist.Equals(artist, StringComparison.CurrentCultureIgnoreCase)); + } + + public PlexAlbum GetAlbum(PlexAlbum[] plexAlbums, string title, string year, string artist) + { + return plexAlbums.FirstOrDefault(x => + x.Title.Contains(title) && x.Artist.Equals(artist, StringComparison.CurrentCultureIgnoreCase)); } diff --git a/PlexRequests.Services/Models/PlexAlbum.cs b/PlexRequests.Services/Models/PlexAlbum.cs index 5d2bd7254..09d4b2638 100644 --- a/PlexRequests.Services/Models/PlexAlbum.cs +++ b/PlexRequests.Services/Models/PlexAlbum.cs @@ -1,9 +1,10 @@ -namespace PlexRequests.Services.Models -{ - public class PlexAlbum - { - public string Title { get; set; } - public string Artist { get; set; } - public string ReleaseYear { get; set; } - } -} +namespace PlexRequests.Services.Models +{ + public class PlexAlbum + { + public string Title { get; set; } + public string Artist { get; set; } + public string ReleaseYear { get; set; } + public string Url { get; set; } + } +} diff --git a/PlexRequests.Services/Models/PlexMovie.cs b/PlexRequests.Services/Models/PlexMovie.cs index 0149698ba..27eca9948 100644 --- a/PlexRequests.Services/Models/PlexMovie.cs +++ b/PlexRequests.Services/Models/PlexMovie.cs @@ -1,9 +1,10 @@ -namespace PlexRequests.Services.Models -{ - public class PlexMovie - { - public string Title { get; set; } - public string ReleaseYear { get; set; } - public string ProviderId { get; set; } - } -} +namespace PlexRequests.Services.Models +{ + public class PlexMovie + { + public string Title { get; set; } + public string ReleaseYear { get; set; } + public string ProviderId { get; set; } + public string Url { get; set; } + } +} diff --git a/PlexRequests.Services/Models/PlexTvShow.cs b/PlexRequests.Services/Models/PlexTvShow.cs index 5ac629132..aecf6f088 100644 --- a/PlexRequests.Services/Models/PlexTvShow.cs +++ b/PlexRequests.Services/Models/PlexTvShow.cs @@ -6,5 +6,6 @@ public string ReleaseYear { get; set; } public string ProviderId { get; set; } public int[] Seasons { get; set; } + public string Url { get; set; } } } diff --git a/PlexRequests.UI/Content/search.js b/PlexRequests.UI/Content/search.js index bf5eea9db..f720ae6ba 100644 --- a/PlexRequests.UI/Content/search.js +++ b/PlexRequests.UI/Content/search.js @@ -429,7 +429,8 @@ $(function () { imdb: result.imdbId, requested: result.requested, approved: result.approved, - available: result.available + available: result.available, + url: result.plexUrl }; return context; @@ -450,7 +451,8 @@ $(function () { approved: result.approved, available: result.available, episodes: result.episodes, - tvFullyAvailable: result.tvFullyAvailable + tvFullyAvailable: result.tvFullyAvailable, + url: result.plexUrl }; return context; } @@ -470,7 +472,8 @@ $(function () { country: result.country, requested: result.requested, approved: result.approved, - available: result.available + available: result.available, + url: result.plexUrl }; return context; diff --git a/PlexRequests.UI/Models/SearchViewModel.cs b/PlexRequests.UI/Models/SearchViewModel.cs index 776b9d2b1..9c11d32ef 100644 --- a/PlexRequests.UI/Models/SearchViewModel.cs +++ b/PlexRequests.UI/Models/SearchViewModel.cs @@ -1,37 +1,38 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: SearchTvShowViewModel.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 - - -namespace PlexRequests.UI.Models -{ - public class SearchViewModel - { - public bool Approved { get; set; } - public bool Requested { get; set; } - public bool Available { get; set; } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SearchTvShowViewModel.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 + + +namespace PlexRequests.UI.Models +{ + public class SearchViewModel + { + public bool Approved { get; set; } + public bool Requested { get; set; } + public bool Available { get; set; } + public string PlexUrl { get; set; } + } } \ No newline at end of file diff --git a/PlexRequests.UI/Models/SessionKeys.cs b/PlexRequests.UI/Models/SessionKeys.cs index fefc7d8bd..766a84bf6 100644 --- a/PlexRequests.UI/Models/SessionKeys.cs +++ b/PlexRequests.UI/Models/SessionKeys.cs @@ -31,5 +31,6 @@ namespace PlexRequests.UI.Models public const string UsernameKey = "Username"; public const string ClientDateTimeOffsetKey = "ClientDateTimeOffset"; public const string UserWizardPlexAuth = nameof(UserWizardPlexAuth); + public const string UserWizardMachineId = nameof(UserWizardMachineId); } } diff --git a/PlexRequests.UI/Modules/AdminModule.cs b/PlexRequests.UI/Modules/AdminModule.cs index 4d6ca7e43..a04edca3c 100644 --- a/PlexRequests.UI/Modules/AdminModule.cs +++ b/PlexRequests.UI/Modules/AdminModule.cs @@ -161,7 +161,7 @@ namespace PlexRequests.UI.Modules Post["/couchpotato"] = _ => SaveCouchPotato(); Get["/plex"] = _ => Plex(); - Post["/plex"] = _ => SavePlex(); + Post["/plex", true] = async (x, ct) => await SavePlex(); Get["/sonarr"] = _ => Sonarr(); Post["/sonarr"] = _ => SaveSonarr(); @@ -170,13 +170,13 @@ namespace PlexRequests.UI.Modules Post["/sickrage"] = _ => SaveSickrage(); Post["/sonarrprofiles"] = _ => GetSonarrQualityProfiles(); - Post["/cpprofiles", true] = async (x,ct) => await GetCpProfiles(); + Post["/cpprofiles", true] = async (x, ct) => await GetCpProfiles(); Post["/cpapikey"] = x => GetCpApiKey(); Get["/emailnotification"] = _ => EmailNotifications(); Post["/emailnotification"] = _ => SaveEmailNotifications(); Post["/testemailnotification"] = _ => TestEmailNotifications(); - Get["/status", true] = async (x,ct) => await Status(); + Get["/status", true] = async (x, ct) => await Status(); Get["/pushbulletnotification"] = _ => PushbulletNotifications(); Post["/pushbulletnotification"] = _ => SavePushbulletNotifications(); @@ -268,7 +268,7 @@ namespace PlexRequests.UI.Modules Analytics.TrackEventAsync(Category.Admin, Action.Save, "CollectAnalyticData turned off", Username, CookieHelper.GetAnalyticClientId(Cookies)); } var result = PrService.SaveSettings(model); - + Analytics.TrackEventAsync(Category.Admin, Action.Save, "PlexRequestSettings", Username, CookieHelper.GetAnalyticClientId(Cookies)); return Response.AsJson(result ? new JsonResponseModel { Result = true } @@ -377,7 +377,7 @@ namespace PlexRequests.UI.Modules return View["Plex", settings]; } - private Response SavePlex() + private async Task SavePlex() { var plexSettings = this.Bind(); var valid = this.Validate(plexSettings); @@ -386,8 +386,11 @@ namespace PlexRequests.UI.Modules return Response.AsJson(valid.SendJsonError()); } + //Lookup identifier + var server = PlexApi.GetServer(plexSettings.PlexAuthToken); + plexSettings.MachineIdentifier = server.Server.FirstOrDefault(x => x.AccessToken == plexSettings.PlexAuthToken)?.MachineIdentifier; - var result = PlexService.SaveSettings(plexSettings); + var result = await PlexService.SaveSettingsAsync(plexSettings); return Response.AsJson(result ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Plex!" } @@ -517,7 +520,7 @@ namespace PlexRequests.UI.Modules { if (string.IsNullOrEmpty(settings.EmailUsername) || string.IsNullOrEmpty(settings.EmailPassword)) { - return Response.AsJson(new JsonResponseModel {Result = false, Message = "SMTP Authentication is enabled, please specify a username and password"}); + return Response.AsJson(new JsonResponseModel { Result = false, Message = "SMTP Authentication is enabled, please specify a username and password" }); } } @@ -542,7 +545,7 @@ namespace PlexRequests.UI.Modules { var checker = new StatusChecker(); var status = await Cache.GetOrSetAsync(CacheKeys.LastestProductVersion, async () => await checker.GetStatus(), 30); - var md = new Markdown(new MarkdownOptions { AutoNewLines = true, AutoHyperlink = true}); + var md = new Markdown(new MarkdownOptions { AutoNewLines = true, AutoHyperlink = true }); status.ReleaseNotes = md.Transform(status.ReleaseNotes); return View["Status", status]; } @@ -711,7 +714,7 @@ namespace PlexRequests.UI.Modules private Response GetCpApiKey() { var settings = this.Bind(); - + if (string.IsNullOrEmpty(settings.Username) || string.IsNullOrEmpty(settings.Password)) { return Response.AsJson(new { Message = "Please enter a username and password to request the Api Key", Result = false }); @@ -938,12 +941,12 @@ namespace PlexRequests.UI.Modules { await LogsRepo.DeleteAsync(logEntity); } - return Response.AsJson(new JsonResponseModel { Result = true, Message = "Logs cleared successfully."}); + return Response.AsJson(new JsonResponseModel { Result = true, Message = "Logs cleared successfully." }); } catch (Exception e) { Log.Error(e); - return Response.AsJson(new JsonResponseModel { Result = false, Message = e.Message }); + return Response.AsJson(new JsonResponseModel { Result = false, Message = e.Message }); } } } diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs index 5f0fa4ed1..73f016f24 100644 --- a/PlexRequests.UI/Modules/SearchModule.cs +++ b/PlexRequests.UI/Modules/SearchModule.cs @@ -110,7 +110,7 @@ namespace PlexRequests.UI.Modules Get["movie/{searchTerm}", true] = async (x, ct) => await SearchMovie((string)x.searchTerm); Get["tv/{searchTerm}", true] = async (x, ct) => await SearchTvShow((string)x.searchTerm); - Get["music/{searchTerm}", true] = async (x, ct) => await SearchMusic((string)x.searchTerm); + Get["music/{searchTerm}", true] = async (x, ct) => await SearchAlbum((string)x.searchTerm); Get["music/coverArt/{id}"] = p => GetMusicBrainzCoverArt((string)p.id); Get["movie/upcoming", true] = async (x, ct) => await UpcomingMovies(); @@ -252,9 +252,11 @@ namespace PlexRequests.UI.Modules VoteCount = movie.VoteCount }; var canSee = CanUserSeeThisRequest(viewMovie.Id, settings.UsersCanViewOnlyOwnRequests, dbMovies); - if (Checker.IsMovieAvailable(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString())) + var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString()); + if (plexMovie != null) { viewMovie.Available = true; + viewMovie.PlexUrl = plexMovie.Url; } else if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db { @@ -343,9 +345,12 @@ namespace PlexRequests.UI.Modules providerId = viewT.Id.ToString(); } - if (Checker.IsTvShowAvailable(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), providerId)) + var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), + providerId); + if (plexShow != null) { viewT.Available = true; + viewT.PlexUrl = plexShow.Url; } else if (t.show?.externals?.thetvdb != null) { @@ -371,7 +376,7 @@ namespace PlexRequests.UI.Modules return Response.AsJson(viewTv); } - private async Task SearchMusic(string searchTerm) + private async Task SearchAlbum(string searchTerm) { Analytics.TrackEventAsync(Category.Search, Action.Album, searchTerm, Username, CookieHelper.GetAnalyticClientId(Cookies)); var apiAlbums = new List(); @@ -405,9 +410,11 @@ namespace PlexRequests.UI.Modules DateTime release; DateTimeHelper.CustomParse(a.ReleaseEvents?.FirstOrDefault()?.date, out release); var artist = a.ArtistCredit?.FirstOrDefault()?.artist; - if (Checker.IsAlbumAvailable(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist?.name)) + var plexAlbum = Checker.GetAlbum(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist?.name); + if (plexAlbum != null) { viewA.Available = true; + viewA.PlexUrl = plexAlbum.Url; } if (!string.IsNullOrEmpty(a.id) && dbAlbum.ContainsKey(a.id)) { diff --git a/PlexRequests.UI/Modules/UserWizardModule.cs b/PlexRequests.UI/Modules/UserWizardModule.cs index 253288929..1bfbbd679 100644 --- a/PlexRequests.UI/Modules/UserWizardModule.cs +++ b/PlexRequests.UI/Modules/UserWizardModule.cs @@ -34,7 +34,7 @@ using Nancy.Extensions; using Nancy.ModelBinding; using Nancy.Responses.Negotiation; using Nancy.Validation; - +using NLog; using PlexRequests.Api.Interfaces; using PlexRequests.Core; using PlexRequests.Core.SettingModels; @@ -84,7 +84,9 @@ namespace PlexRequests.UI.Modules private ICustomUserMapper Mapper { get; } private IAnalytics Analytics { get; } - + private static Logger Log = LogManager.GetCurrentClassLogger(); + + private Response PlexAuth() { var user = this.Bind(); @@ -103,9 +105,10 @@ namespace PlexRequests.UI.Modules // Set the auth token in the session so we can use it in the next form Session[SessionKeys.UserWizardPlexAuth] = model.user.authentication_token; - + var servers = PlexApi.GetServer(model.user.authentication_token); var firstServer = servers.Server.FirstOrDefault(); + return Response.AsJson(new { Result = true, firstServer?.Port, Ip = firstServer?.LocalAddresses, firstServer?.Scheme }); } @@ -119,6 +122,20 @@ namespace PlexRequests.UI.Modules } form.PlexAuthToken = Session[SessionKeys.UserWizardPlexAuth].ToString(); // Set the auth token from the previous form + // Get the machine ID from the settings (This could have changed) + try + { + var servers = PlexApi.GetServer(form.PlexAuthToken); + var firstServer = servers.Server.FirstOrDefault(x => x.AccessToken == form.PlexAuthToken); + + Session[SessionKeys.UserWizardMachineId] = firstServer?.MachineIdentifier; + } + catch (Exception e) + { + // Probably bad settings, just continue + Log.Error(e); + } + var result = await PlexSettings.SaveSettingsAsync(form); if (result) { diff --git a/PlexRequests.UI/Resources/UI.resx b/PlexRequests.UI/Resources/UI.resx index 58e8f71c8..4f23fce97 100644 --- a/PlexRequests.UI/Resources/UI.resx +++ b/PlexRequests.UI/Resources/UI.resx @@ -440,4 +440,7 @@ There is no information available for the release date + + View In Plex + \ No newline at end of file diff --git a/PlexRequests.UI/Resources/UI1.Designer.cs b/PlexRequests.UI/Resources/UI1.Designer.cs index 20ab447d7..6cd282c32 100644 --- a/PlexRequests.UI/Resources/UI1.Designer.cs +++ b/PlexRequests.UI/Resources/UI1.Designer.cs @@ -987,6 +987,15 @@ namespace PlexRequests.UI.Resources { } } + /// + /// Looks up a localized string similar to View In Plex. + /// + public static string Search_ViewInPlex { + get { + return ResourceManager.GetString("Search_ViewInPlex", resourceCulture); + } + } + /// /// Looks up a localized string similar to You have reached your weekly request limit for Albums! Please contact your admin.. /// diff --git a/PlexRequests.UI/Views/Search/Index.cshtml b/PlexRequests.UI/Views/Search/Index.cshtml index 17204abb1..950a7f06d 100644 --- a/PlexRequests.UI/Views/Search/Index.cshtml +++ b/PlexRequests.UI/Views/Search/Index.cshtml @@ -175,6 +175,8 @@ {{#if_eq type "movie"}} {{#if_eq available true}} +
+ @UI.Search_ViewInPlex {{else}} {{#if_eq requested true}} @@ -186,7 +188,8 @@ {{#if_eq type "tv"}} {{#if_eq tvFullyAvailable true}} @*//TODO Not used yet*@ - +
+ @UI.Search_ViewInPlex {{else}}