Started adding Emby, Lots of backend work done. Need a few more services done and login and user management. #435

This commit is contained in:
tidusjar 2017-01-28 16:54:48 +00:00
commit 868301f552
43 changed files with 1495 additions and 18 deletions

View file

@ -97,6 +97,8 @@ namespace Ombi.UI.Modules.Admin
private IDiscordApi DiscordApi { get; }
private ISettingsService<RadarrSettings> RadarrSettings { get; }
private IRadarrApi RadarrApi { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private IEmbyApi EmbyApi { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
public AdminModule(ISettingsService<PlexRequestSettings> prService,
@ -124,7 +126,8 @@ namespace Ombi.UI.Modules.Admin
ISettingsService<NotificationSettingsV2> notifyService, IRecentlyAdded recentlyAdded,
ISettingsService<WatcherSettings> watcherSettings ,
ISettingsService<DiscordNotificationSettings> discord,
IDiscordApi discordapi, ISettingsService<RadarrSettings> settings, IRadarrApi radarrApi
IDiscordApi discordapi, ISettingsService<RadarrSettings> settings, IRadarrApi radarrApi,
ISettingsService<EmbySettings> embySettings, IEmbyApi emby
, ISecurityExtensions security) : base("admin", prService, security)
{
PrService = prService;
@ -160,7 +163,9 @@ namespace Ombi.UI.Modules.Admin
DiscordApi = discordapi;
RadarrSettings = settings;
RadarrApi = radarrApi;
EmbyApi = emby;
EmbySettings = embySettings;
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Get["/"] = _ => Admin();
@ -180,6 +185,10 @@ namespace Ombi.UI.Modules.Admin
Get["/plex"] = _ => Plex();
Post["/plex", true] = async (x, ct) => await SavePlex();
Get["/emby", true] = async (x, ct) => await Emby();
Post["/emby", true] = async (x, ct) => await SaveEmby();
Get["/sonarr"] = _ => Sonarr();
Post["/sonarr"] = _ => SaveSonarr();
Post["/sonarrprofiles"] = _ => GetSonarrQualityProfiles();
@ -438,6 +447,13 @@ namespace Ombi.UI.Modules.Admin
return Response.AsJson(valid.SendJsonError());
}
var embySettings = await EmbySettings.GetSettingsAsync();
if (embySettings.Enable)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Emby is enabled, we cannot enable Plex and Emby" });
}
if (string.IsNullOrEmpty(plexSettings.MachineIdentifier))
{
//Lookup identifier
@ -453,6 +469,41 @@ namespace Ombi.UI.Modules.Admin
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
private async Task<Negotiator> Emby()
{
var settings = await EmbySettings.GetSettingsAsync();
return View["Emby", settings];
}
private async Task<Response> SaveEmby()
{
var emby = this.Bind<EmbySettings>();
var valid = this.Validate(emby);
if (!valid.IsValid)
{
return Response.AsJson(valid.SendJsonError());
}
var plexSettings = await PlexService.GetSettingsAsync();
if (plexSettings.Enable)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Plex is enabled, we cannot enable Plex and Emby" });
}
// Get the users
var users = EmbyApi.GetUsers(emby.FullUri, emby.ApiKey);
// Find admin
var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator);
emby.AdministratorId = admin?.Id;
var result = await EmbySettings.SaveSettingsAsync(emby);
return Response.AsJson(result
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Emby!" }
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
private Negotiator Sonarr()
{
var settings = SonarrService.GetSettings();

View file

@ -46,7 +46,7 @@ namespace Ombi.UI.Modules
public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi,
ISickRageApi srApi, IHeadphonesApi hpApi, ISettingsService<PlexRequestSettings> pr, ISecurityExtensions security,
IWatcherApi watcherApi, IRadarrApi radarrApi) : base("test", pr, security)
IWatcherApi watcherApi, IRadarrApi radarrApi, IEmbyApi emby) : base("test", pr, security)
{
this.RequiresAuthentication();
@ -57,6 +57,7 @@ namespace Ombi.UI.Modules
HeadphonesApi = hpApi;
WatcherApi = watcherApi;
RadarrApi = radarrApi;
Emby = emby;
Post["/cp"] = _ => CouchPotatoTest();
Post["/sonarr"] = _ => SonarrTest();
@ -66,6 +67,7 @@ namespace Ombi.UI.Modules
Post["/headphones"] = _ => HeadphonesTest();
Post["/plexdb"] = _ => TestPlexDb();
Post["/watcher"] = _ => WatcherTest();
Post["/emby"] = _ => EmbyTest();
}
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
@ -76,6 +78,7 @@ namespace Ombi.UI.Modules
private IHeadphonesApi HeadphonesApi { get; }
private IWatcherApi WatcherApi { get; }
private IRadarrApi RadarrApi { get; }
private IEmbyApi Emby { get; set; }
private Response CouchPotatoTest()
{
@ -213,7 +216,7 @@ namespace Ombi.UI.Modules
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Plex, please check your settings." });
}
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
{
Log.Warn("Exception thrown when attempting to get Plex's status: ");
Log.Warn(e);
@ -225,6 +228,35 @@ namespace Ombi.UI.Modules
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
}
}
private Response EmbyTest()
{
var emby = this.Bind<EmbySettings>();
var valid = this.Validate(emby);
if (!valid.IsValid)
{
return Response.AsJson(valid.SendJsonError());
}
try
{
var status = Emby.GetUsers(emby?.FullUri, emby?.ApiKey);
return status != null
? Response.AsJson(new JsonResponseModel { Result = true, Message = "Connected to Emby successfully!" })
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Emby, please check your settings." });
}
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
{
Log.Warn("Exception thrown when attempting to get Emby's users: ");
Log.Warn(e);
var message = $"Could not connect to Emby, please check your settings. <strong>Exception Message:</strong> {e.Message}";
if (e.InnerException != null)
{
message = $"Could not connect to Emby, please check your settings. <strong>Exception Message:</strong> {e.InnerException.Message}";
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
}
}
private Response SickRageTest()
{

View file

@ -34,6 +34,7 @@ using Nancy;
using Nancy.Extensions;
using Nancy.Linker;
using NLog;
using Ombi.Api;
using Ombi.Api.Interfaces;
using Ombi.Api.Models.Plex;
using Ombi.Core;

View file

@ -50,6 +50,7 @@ namespace Ombi.UI.NinjectModules
Bind<IDiscordApi>().To<DiscordApi>();
Bind<IRadarrApi>().To<RadarrApi>();
Bind<ITraktApi>().To<TraktApi>();
Bind<IEmbyApi>().To<EmbyApi>();
}
}
}

View file

@ -58,6 +58,9 @@ namespace Ombi.UI.NinjectModules
Bind<IPlexEpisodeCacher>().To<PlexEpisodeCacher>();
Bind<IFaultQueueHandler>().To<FaultQueueHandler>();
Bind<IPlexUserChecker>().To<PlexUserChecker>();
Bind<IEmbyAvailabilityChecker>().To<EmbyAvailabilityChecker>();
Bind<IAnalytics>().To<Analytics>();
Bind<ISchedulerFactory>().To<StdSchedulerFactory>();

View file

@ -295,6 +295,7 @@
</Compile>
<Compile Include="Start\StartupOptions.cs" />
<Compile Include="Start\UpdateValue.cs" />
<Compile Include="Validators\EmbyValidator.cs" />
<Compile Include="Validators\RadarrValidator.cs" />
<Compile Include="Validators\WatcherValidator.cs" />
<Compile Include="Validators\SlackSettingsValidator.cs" />
@ -803,6 +804,9 @@
<Content Include="Views\Integration\Radarr.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Views\Admin\Emby.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="Web.Debug.config">
<DependentUpon>web.config</DependentUpon>
</None>

View file

@ -31,6 +31,7 @@ using Ninject;
using Ninject.Planning.Bindings.Resolvers;
using Ninject.Syntax;
using NLog;
using Ombi.Api;
using Ombi.Api.Interfaces;
using Ombi.Core;
using Ombi.Core.Migration;
@ -83,6 +84,7 @@ namespace Ombi.UI
var scheduler = new Scheduler();
// Reset any jobs running
var jobSettings = kernel.Get<IRepository<ScheduledJobs>>();
var all = jobSettings.GetAll();

View file

@ -0,0 +1,42 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: SonarrValidator.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 FluentValidation;
using Ombi.Core.SettingModels;
namespace Ombi.UI.Validators
{
public class EmbyValidator : AbstractValidator<EmbySettings>
{
public EmbyValidator()
{
RuleFor(request => request.Ip).NotNull().WithMessage("You must specify a IP/Host name.");
RuleFor(request => request.Port).NotNull().WithMessage("You must specify a Port.");
RuleFor(request => request.ApiKey).NotNull().WithMessage("You must specify a Api Key.");
}
}
}

View file

@ -0,0 +1,146 @@
@using Ombi.UI.Helpers
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<Ombi.Core.SettingModels.EmbySettings>
@Html.Partial("Shared/Partial/_Sidebar")
@{
int port;
if (Model.Port == 0)
{
port = 8096;
}
else
{
port = Model.Port;
}
}
<div class="col-sm-8 col-sm-push-1">
<form class="form-horizontal" method="POST" id="mainForm">
<fieldset>
<legend>Emby Settings</legend>
@Html.Checkbox(Model.Enable, "Enable", "Enabled")
<div class="form-group">
<label for="Ip" class="control-label">Emby Hostname or IP</label>
<div>
<input type="text" class="form-control form-control-custom " id="Ip" name="Ip" placeholder="localhost" value="@Model.Ip">
</div>
</div>
<div class="form-group">
<label for="portNumber" class="control-label">Port</label>
<div>
<input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="Port Number" value="@port">
</div>
</div>
<div class="form-group">
<div class="checkbox">
@if (Model.Ssl)
{
<input type="checkbox" id="Ssl" name="Ssl" checked="checked"><label for="Ssl">SSL</label>
}
else
{
<input type="checkbox" id="Ssl" name="Ssl"><label for="Ssl">SSL</label>
}
</div>
</div>
<div class="form-group">
<label for="SubDir" class="control-label">Emby Base Url</label>
<div>
<input type="text" class="form-control form-control-custom " id="SubDir" name="SubDir" value="@Model.SubDir">
</div>
</div>
<div class="form-group">
<label for="ApiKey" class="control-label">Emby Api Key</label>
<div class="">
<input type="text" class="form-control-custom form-control" id="ApiKey" name="ApiKey" placeholder="Api Key" value="@Model.ApiKey">
</div>
</div>
<div class="form-group">
<div>
<button id="testEmby" type="submit" class="btn btn-primary-outline">Test Connectivity <div id="spinner"></div></button>
</div>
</div>
<div class="form-group">
<div>
<button id="save" type="submit" class="btn btn-primary-outline">Submit</button>
</div>
</div>
</fieldset>
</form>
</div>
<script>
$(function () {
var base = '@Html.GetBaseUrl()';
$('#testEmby').click(function (e) {
e.preventDefault();
var url = createBaseUrl(base, '/test/emby');
var $form = $("#mainForm");
$('#spinner').attr("class", "fa fa-spinner fa-spin");
$.ajax({
type: $form.prop("method"),
url: url,
data: $form.serialize(),
dataType: "json",
success: function (response) {
$('#spinner').attr("class", "");
console.log(response);
if (response.result === true) {
generateNotify(response.message, "success");
$('#spinner').attr("class", "fa fa-check");
} else {
generateNotify(response.message, "warning");
$('#spinner').attr("class", "fa fa-times");
}
},
error: function (e) {
$('#spinner').attr("class", "fa fa-times");
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
$('#save').click(function (e) {
e.preventDefault();
var port = $('#portNumber').val();
if (isNaN(port)) {
generateNotify("You must specify a Port.", "warning");
return;
}
var $form = $("#mainForm");
$.ajax({
type: $form.prop("method"),
data: $form.serialize(),
url: $form.prop("action"),
dataType: "json",
success: function (response) {
if (response.result === true) {
generateNotify(response.message, "success");
} else {
generateNotify(response.message, "warning");
}
},
error: function (e) {
console.log(e);
generateNotify("Something went wrong!", "danger");
}
});
});
});
</script>

View file

@ -17,6 +17,8 @@
<fieldset>
<legend>Plex Settings</legend>
@*<input id="advancedToggle" type="checkbox"/>*@ @*TODO*@
@Html.Checkbox(Model.Enable, "Enable", "Enable")
<div class="form-group">
<label for="Ip" class="control-label">Plex Hostname or IP</label>
<div>