This commit is contained in:
tidusjar 2016-08-25 22:53:05 +01:00
commit 7db336e202
19 changed files with 229 additions and 89 deletions

View file

@ -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;

View file

@ -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; }
}
}

View file

@ -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);
}
}

View file

@ -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<Response> SavePlex()
{
var plexSettings = this.Bind<PlexSettings>();
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<CouchPotatoSettings>();
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 });
}
}
}

View file

@ -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<Response> SearchMusic(string searchTerm)
private async Task<Response> SearchAlbum(string searchTerm)
{
Analytics.TrackEventAsync(Category.Search, Action.Album, searchTerm, Username, CookieHelper.GetAnalyticClientId(Cookies));
var apiAlbums = new List<Release>();
@ -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))
{

View file

@ -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<PlexAuth>();
@ -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)
{

View file

@ -440,4 +440,7 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>There is no information available for the release date</value>
</data>
<data name="Search_ViewInPlex" xml:space="preserve">
<value>View In Plex</value>
</data>
</root>

View file

@ -987,6 +987,15 @@ namespace PlexRequests.UI.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to View In Plex.
/// </summary>
public static string Search_ViewInPlex {
get {
return ResourceManager.GetString("Search_ViewInPlex", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You have reached your weekly request limit for Albums! Please contact your admin..
/// </summary>

View file

@ -175,6 +175,8 @@
{{#if_eq type "movie"}}
{{#if_eq available true}}
<button style="text-align: right" class="btn btn-success-outline disabled" disabled><i class="fa fa-check"></i> @UI.Search_Available</button>
<br />
<a style="text-align: right" class="btn btn-sm btn-primary-outline" href="{{url}}" target="_blank"><i class="fa fa-eye"></i> @UI.Search_ViewInPlex</a>
{{else}}
{{#if_eq requested true}}
<button style="text-align: right" class="btn btn-primary-outline disabled" disabled><i class="fa fa-check"></i> @UI.Search_Requested</button>
@ -186,7 +188,8 @@
{{#if_eq type "tv"}}
{{#if_eq tvFullyAvailable true}}
@*//TODO Not used yet*@
<button style="text-align: right" class="btn btn-success-outline disabled" disabled><i class="fa fa-check"></i> @UI.Search_Available</button>
<button style="text-align: right" class="btn btn-success-outline disabled" disabled><i class="fa fa-check"></i> @UI.Search_Available</button><br />
<a style="text-align: right" class="btn btn-sm btn-primary-outline" href="{{url}}" target="_blank"><i class="fa fa-eye"></i> @UI.Search_ViewInPlex</a>
{{else}}
<div class="dropdown">
<button id="{{id}}" class="btn btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
@ -259,7 +262,8 @@
<form method="POST" action="@url/search/request/{{type}}" id="form{{id}}">
<input name="{{type}}Id" type="text" value="{{id}}" hidden="hidden" />
{{#if_eq available true}}
<button style="text-align: right" class="btn btn-success-outline disabled" disabled><i class="fa fa-check"></i> @UI.Search_Available</button>
<button style="text-align: right" class="btn btn-success-outline disabled" disabled><i class="fa fa-check"></i> @UI.Search_Available</button><br />
<a style="text-align: right" class="btn btn-sm btn-primary-outline" href="{{url}}" target="_blank"><i class="fa fa-eye"></i> @UI.Search_ViewInPlex</a>
{{else}}
{{#if_eq requested true}}
<button style="text-align: right" class="btn btn-success-outline disabled" disabled><i class="fa fa-check"></i> @UI.Search_Requested</button>