mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-08 14:10:50 -07:00
Finished the main part of #844 just need testing
This commit is contained in:
parent
b3c7d83529
commit
0811a89c86
26 changed files with 820 additions and 91 deletions
|
@ -34,7 +34,7 @@ namespace Ombi.Api.Interfaces
|
||||||
public interface IWatcherApi
|
public interface IWatcherApi
|
||||||
{
|
{
|
||||||
WatcherAddMovieResult AddMovie(string imdbId, string apiKey, Uri baseUrl);
|
WatcherAddMovieResult AddMovie(string imdbId, string apiKey, Uri baseUrl);
|
||||||
List<WatcherListStatusResult> ListMovies(string apiKey, Uri baseUrl);
|
WatcherListStatusResultContainer ListMovies(string apiKey, Uri baseUrl);
|
||||||
List<WatcherListStatusResult> ListMovies(string apiKey, Uri baseUrl, string imdbId);
|
WatcherListStatusResultContainer ListMovies(string apiKey, Uri baseUrl, string imdbId);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,11 +24,19 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Ombi.Api.Models.Watcher
|
namespace Ombi.Api.Models.Watcher
|
||||||
{
|
{
|
||||||
public class WatcherAddMovieResult
|
public class WatcherAddMovieResult
|
||||||
{
|
{
|
||||||
public string status { get; set; }
|
public string status { get; set; }
|
||||||
public string message { get; set; }
|
public string message { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ErrorMessage { get; set; }
|
||||||
|
[JsonIgnore]
|
||||||
|
public bool Error { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,11 +33,11 @@ namespace Ombi.Api.Models.Watcher
|
||||||
{
|
{
|
||||||
public class Quality2
|
public class Quality2
|
||||||
{
|
{
|
||||||
[DeserializeAs(Name = "720P")]
|
[JsonProperty("720P")]
|
||||||
public List<string> Q720P { get; set; }
|
public List<string> Q720P { get; set; }
|
||||||
[DeserializeAs(Name = "1080P")]
|
[JsonProperty("1080P")]
|
||||||
public List<string> Q1080P { get; set; }
|
public List<string> Q1080P { get; set; }
|
||||||
[DeserializeAs( Name = "4K")]
|
[JsonProperty("4K")]
|
||||||
public List<string> Q4K { get; set; }
|
public List<string> Q4K { get; set; }
|
||||||
public List<string> SD { get; set; }
|
public List<string> SD { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ namespace Ombi.Api.Models.Watcher
|
||||||
|
|
||||||
public class Quality
|
public class Quality
|
||||||
{
|
{
|
||||||
[DeserializeAs(Name = "Quality")]
|
[JsonProperty("Quality")]
|
||||||
public Quality2 quality { get; set; }
|
public Quality2 quality { get; set; }
|
||||||
public Filters Filters { get; set; }
|
public Filters Filters { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -73,5 +73,15 @@ namespace Ombi.Api.Models.Watcher
|
||||||
public string tomatorating { get; set; }
|
public string tomatorating { get; set; }
|
||||||
public string imdbid { get; set; }
|
public string imdbid { get; set; }
|
||||||
public Quality quality { get; set; }
|
public Quality quality { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class WatcherListStatusResultContainer
|
||||||
|
{
|
||||||
|
public List<WatcherListStatusResult> Results { get; set; }
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ErrorMessage { get; set; }
|
||||||
|
[JsonIgnore]
|
||||||
|
public bool Error { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
#region Copyright
|
#region Copyright
|
||||||
|
|
||||||
// /************************************************************************
|
// /************************************************************************
|
||||||
// Copyright (c) 2016 Jamie Rees
|
// Copyright (c) 2016 Jamie Rees
|
||||||
// File: CouchPotatoApi.cs
|
// File: WatcherApi.cs
|
||||||
// Created By: Jamie Rees
|
// Created By: Jamie Rees
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
@ -23,16 +24,14 @@
|
||||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// ************************************************************************/
|
// ************************************************************************/
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using Ombi.Api.Interfaces;
|
using Ombi.Api.Interfaces;
|
||||||
using Ombi.Api.Models.Movie;
|
|
||||||
using Ombi.Api.Models.Watcher;
|
using Ombi.Api.Models.Watcher;
|
||||||
using Ombi.Helpers;
|
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
|
|
||||||
namespace Ombi.Api
|
namespace Ombi.Api
|
||||||
|
@ -49,21 +48,68 @@ namespace Ombi.Api
|
||||||
|
|
||||||
public WatcherAddMovieResult AddMovie(string imdbId, string apiKey, Uri baseUrl)
|
public WatcherAddMovieResult AddMovie(string imdbId, string apiKey, Uri baseUrl)
|
||||||
{
|
{
|
||||||
return Send<WatcherAddMovieResult>("addmovie", apiKey, baseUrl, imdbId);
|
var response = Send("addmovie", apiKey, baseUrl, imdbId);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject<WatcherAddMovieResult>(response.Content);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
return new WatcherAddMovieResult
|
||||||
|
{
|
||||||
|
Error = true,
|
||||||
|
ErrorMessage = e.Message
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WatcherListStatusResult> ListMovies(string apiKey, Uri baseUrl)
|
public WatcherListStatusResultContainer ListMovies(string apiKey, Uri baseUrl)
|
||||||
{
|
{
|
||||||
return Send<List<WatcherListStatusResult>>("liststatus", apiKey, baseUrl);
|
var response = Send("liststatus", apiKey, baseUrl);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (response.Content.Contains("No movies found"))
|
||||||
|
{
|
||||||
|
return new WatcherListStatusResultContainer();
|
||||||
|
}
|
||||||
|
return JsonConvert.DeserializeObject<WatcherListStatusResultContainer>(response.Content);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
return new WatcherListStatusResultContainer
|
||||||
|
{
|
||||||
|
Error = true,
|
||||||
|
ErrorMessage = e.Message
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WatcherListStatusResult> ListMovies(string apiKey, Uri baseUrl, string imdbId)
|
public WatcherListStatusResultContainer ListMovies(string apiKey, Uri baseUrl, string imdbId)
|
||||||
{
|
{
|
||||||
return Send<List<WatcherListStatusResult>>("liststatus", apiKey, baseUrl, imdbId);
|
var response = Send("liststatus", apiKey, baseUrl, imdbId);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (response.Content.Contains("No movies found"))
|
||||||
|
{
|
||||||
|
return new WatcherListStatusResultContainer();
|
||||||
|
}
|
||||||
|
return JsonConvert.DeserializeObject<WatcherListStatusResultContainer>(response.Content);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
return new WatcherListStatusResultContainer
|
||||||
|
{
|
||||||
|
Error = true,
|
||||||
|
ErrorMessage = e.Message
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private T Send<T>(string mode, string apiKey, Uri baseUrl, string imdbid = "") where T : new()
|
private IRestResponse Send(string mode, string apiKey, Uri baseUrl, string imdbid = "")
|
||||||
{
|
{
|
||||||
RestRequest request;
|
RestRequest request;
|
||||||
request = new RestRequest
|
request = new RestRequest
|
||||||
|
@ -72,11 +118,13 @@ namespace Ombi.Api
|
||||||
};
|
};
|
||||||
|
|
||||||
request.AddUrlSegment("apikey", apiKey);
|
request.AddUrlSegment("apikey", apiKey);
|
||||||
if(!string.IsNullOrEmpty(imdbid))
|
if (!string.IsNullOrEmpty(imdbid))
|
||||||
{ request.AddUrlSegment("imdbid", imdbid);}
|
{
|
||||||
|
request.AddUrlSegment("imdbid", imdbid);
|
||||||
|
}
|
||||||
request.AddUrlSegment("mode", mode);
|
request.AddUrlSegment("mode", mode);
|
||||||
|
|
||||||
return Api.Execute<T>(request, baseUrl);
|
return Api.Execute(request, baseUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace Ombi.Core
|
||||||
public const string SickRageQueued = nameof(SickRageQueued);
|
public const string SickRageQueued = nameof(SickRageQueued);
|
||||||
public const string CouchPotatoQualityProfiles = nameof(CouchPotatoQualityProfiles);
|
public const string CouchPotatoQualityProfiles = nameof(CouchPotatoQualityProfiles);
|
||||||
public const string CouchPotatoQueued = nameof(CouchPotatoQueued);
|
public const string CouchPotatoQueued = nameof(CouchPotatoQueued);
|
||||||
|
public const string WatcherQueued = nameof(WatcherQueued);
|
||||||
public const string GetPlexRequestSettings = nameof(GetPlexRequestSettings);
|
public const string GetPlexRequestSettings = nameof(GetPlexRequestSettings);
|
||||||
public const string LastestProductVersion = nameof(LastestProductVersion);
|
public const string LastestProductVersion = nameof(LastestProductVersion);
|
||||||
}
|
}
|
||||||
|
|
10
Ombi.Core/IMovieSender.cs
Normal file
10
Ombi.Core/IMovieSender.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Store;
|
||||||
|
|
||||||
|
namespace Ombi.Core
|
||||||
|
{
|
||||||
|
public interface IMovieSender
|
||||||
|
{
|
||||||
|
Task<MovieSenderResult> Send(RequestedModel model, string qualityId = "");
|
||||||
|
}
|
||||||
|
}
|
95
Ombi.Core/MovieSender.cs
Normal file
95
Ombi.Core/MovieSender.cs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: MovieSender.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.Threading.Tasks;
|
||||||
|
using NLog;
|
||||||
|
using Ombi.Api.Interfaces;
|
||||||
|
using Ombi.Core.SettingModels;
|
||||||
|
using Ombi.Store;
|
||||||
|
|
||||||
|
namespace Ombi.Core
|
||||||
|
{
|
||||||
|
public class MovieSender : IMovieSender
|
||||||
|
{
|
||||||
|
public MovieSender(ISettingsService<CouchPotatoSettings> cp, ISettingsService<WatcherSettings> watcher,
|
||||||
|
ICouchPotatoApi cpApi, IWatcherApi watcherApi)
|
||||||
|
{
|
||||||
|
CouchPotatoSettings = cp;
|
||||||
|
WatcherSettings = watcher;
|
||||||
|
CpApi = cpApi;
|
||||||
|
WatcherApi = watcherApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ISettingsService<CouchPotatoSettings> CouchPotatoSettings { get; }
|
||||||
|
private ISettingsService<WatcherSettings> WatcherSettings { get; }
|
||||||
|
private ICouchPotatoApi CpApi { get; }
|
||||||
|
private IWatcherApi WatcherApi { get; }
|
||||||
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
public async Task<MovieSenderResult> Send(RequestedModel model, string qualityId = "")
|
||||||
|
{
|
||||||
|
var cpSettings = await CouchPotatoSettings.GetSettingsAsync();
|
||||||
|
var watcherSettings = await WatcherSettings.GetSettingsAsync();
|
||||||
|
|
||||||
|
if (cpSettings.Enabled)
|
||||||
|
{
|
||||||
|
return SendToCp(model, cpSettings, string.IsNullOrEmpty(qualityId) ? cpSettings.ProfileId : qualityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (watcherSettings.Enabled)
|
||||||
|
{
|
||||||
|
return SendToWatcher(model, watcherSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MovieSenderResult { Result = false, MovieSendingEnabled = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
private MovieSenderResult SendToWatcher(RequestedModel model, WatcherSettings settings)
|
||||||
|
{
|
||||||
|
var result = WatcherApi.AddMovie(model.ImdbId, settings.ApiKey, settings.FullUri);
|
||||||
|
|
||||||
|
if (result.Error)
|
||||||
|
{
|
||||||
|
Log.Error(result.ErrorMessage);
|
||||||
|
return new MovieSenderResult { Result = false };
|
||||||
|
}
|
||||||
|
if (result.status.Equals("success", StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
return new MovieSenderResult { Result = true, MovieSendingEnabled = true };
|
||||||
|
}
|
||||||
|
Log.Error(result.message);
|
||||||
|
return new MovieSenderResult { Result = false, MovieSendingEnabled = true };
|
||||||
|
}
|
||||||
|
|
||||||
|
private MovieSenderResult SendToCp(RequestedModel model, CouchPotatoSettings settings, string qualityId)
|
||||||
|
{
|
||||||
|
var result = CpApi.AddMovie(model.ImdbId, settings.ApiKey, model.Title, settings.FullUri, qualityId);
|
||||||
|
return new MovieSenderResult { Result = result, MovieSendingEnabled = true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
Ombi.Core/MovieSenderResult.cs
Normal file
40
Ombi.Core/MovieSenderResult.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: MovieSenderResult.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 Ombi.Core
|
||||||
|
{
|
||||||
|
public class MovieSenderResult
|
||||||
|
{
|
||||||
|
public bool Result { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether we can send to either CP or Watcher.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// <c>true</c> if [movie sending enabled]; otherwise, <c>false</c>.
|
||||||
|
/// </value>
|
||||||
|
public bool MovieSendingEnabled { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -95,9 +95,12 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="CacheKeys.cs" />
|
<Compile Include="CacheKeys.cs" />
|
||||||
<Compile Include="HeadphonesSender.cs" />
|
<Compile Include="HeadphonesSender.cs" />
|
||||||
|
<Compile Include="IMovieSender.cs" />
|
||||||
<Compile Include="IPlexReadOnlyDatabase.cs" />
|
<Compile Include="IPlexReadOnlyDatabase.cs" />
|
||||||
<Compile Include="ISecurityExtensions.cs" />
|
<Compile Include="ISecurityExtensions.cs" />
|
||||||
<Compile Include="IStatusChecker.cs" />
|
<Compile Include="IStatusChecker.cs" />
|
||||||
|
<Compile Include="MovieSender.cs" />
|
||||||
|
<Compile Include="MovieSenderResult.cs" />
|
||||||
<Compile Include="Notification\NotificationMessage.cs" />
|
<Compile Include="Notification\NotificationMessage.cs" />
|
||||||
<Compile Include="Notification\NotificationMessageContent.cs" />
|
<Compile Include="Notification\NotificationMessageContent.cs" />
|
||||||
<Compile Include="Notification\NotificationMessageCurlys.cs" />
|
<Compile Include="Notification\NotificationMessageCurlys.cs" />
|
||||||
|
@ -119,6 +122,7 @@
|
||||||
<Compile Include="Queue\TransientFaultQueue.cs" />
|
<Compile Include="Queue\TransientFaultQueue.cs" />
|
||||||
<Compile Include="SecurityExtensions.cs" />
|
<Compile Include="SecurityExtensions.cs" />
|
||||||
<Compile Include="SettingModels\AuthenticationSettings.cs" />
|
<Compile Include="SettingModels\AuthenticationSettings.cs" />
|
||||||
|
<Compile Include="SettingModels\WatcherSettings.cs" />
|
||||||
<Compile Include="SettingModels\ExternalSettings.cs" />
|
<Compile Include="SettingModels\ExternalSettings.cs" />
|
||||||
<Compile Include="SettingModels\HeadphonesSettings.cs" />
|
<Compile Include="SettingModels\HeadphonesSettings.cs" />
|
||||||
<Compile Include="SettingModels\LandingPageSettings.cs" />
|
<Compile Include="SettingModels\LandingPageSettings.cs" />
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace Ombi.Core.SettingModels
|
||||||
public int SickRageCacher { get; set; }
|
public int SickRageCacher { get; set; }
|
||||||
public int SonarrCacher { get; set; }
|
public int SonarrCacher { get; set; }
|
||||||
public int CouchPotatoCacher { get; set; }
|
public int CouchPotatoCacher { get; set; }
|
||||||
|
public int WatcherCacher { get; set; }
|
||||||
public int StoreBackup { get; set; }
|
public int StoreBackup { get; set; }
|
||||||
public int StoreCleanup { get; set; }
|
public int StoreCleanup { get; set; }
|
||||||
public int UserRequestLimitResetter { get; set; }
|
public int UserRequestLimitResetter { get; set; }
|
||||||
|
|
34
Ombi.Core/SettingModels/WatcherSettings.cs
Normal file
34
Ombi.Core/SettingModels/WatcherSettings.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: WatcherSettings.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 Ombi.Core.SettingModels
|
||||||
|
{
|
||||||
|
public sealed class WatcherSettings : ExternalSettings
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public string ApiKey { get; set; }
|
||||||
|
}
|
||||||
|
}
|
8
Ombi.Services/Interfaces/IWatcherCacher.cs
Normal file
8
Ombi.Services/Interfaces/IWatcherCacher.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Ombi.Services.Interfaces
|
||||||
|
{
|
||||||
|
public interface IWatcherCacher
|
||||||
|
{
|
||||||
|
void Queued();
|
||||||
|
string[] QueuedIds();
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ namespace Ombi.Services.Jobs
|
||||||
{
|
{
|
||||||
public const string StoreBackup = "Database Backup";
|
public const string StoreBackup = "Database Backup";
|
||||||
public const string CpCacher = "CouchPotato Cacher";
|
public const string CpCacher = "CouchPotato Cacher";
|
||||||
|
public const string WatcherCacher = "Watcher Cacher";
|
||||||
public const string SonarrCacher = "Sonarr Cacher";
|
public const string SonarrCacher = "Sonarr Cacher";
|
||||||
public const string SrCacher = "SickRage Cacher";
|
public const string SrCacher = "SickRage Cacher";
|
||||||
public const string PlexChecker = "Plex Availability Cacher";
|
public const string PlexChecker = "Plex Availability Cacher";
|
||||||
|
|
132
Ombi.Services/Jobs/WatcherCacher.cs
Normal file
132
Ombi.Services/Jobs/WatcherCacher.cs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
#region Copyright
|
||||||
|
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: PlexAvailabilityChecker.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.Linq;
|
||||||
|
using NLog;
|
||||||
|
using Ombi.Api.Interfaces;
|
||||||
|
using Ombi.Api.Models.Movie;
|
||||||
|
using Ombi.Core;
|
||||||
|
using Ombi.Core.SettingModels;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Services.Interfaces;
|
||||||
|
using Quartz;
|
||||||
|
|
||||||
|
namespace Ombi.Services.Jobs
|
||||||
|
{
|
||||||
|
public class WatcherCacher : IJob, IWatcherCacher
|
||||||
|
{
|
||||||
|
public WatcherCacher(
|
||||||
|
ISettingsService<WatcherSettings> watcher,
|
||||||
|
IWatcherApi watcherApi, ICacheProvider cache, IJobRecord rec)
|
||||||
|
{
|
||||||
|
WatcherSettings = watcher;
|
||||||
|
WatcherApi = WatcherApi;
|
||||||
|
Cache = cache;
|
||||||
|
Job = rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ISettingsService<WatcherSettings> WatcherSettings { get; }
|
||||||
|
private ICacheProvider Cache { get; }
|
||||||
|
private IWatcherApi WatcherApi { get; }
|
||||||
|
private IJobRecord Job { get; }
|
||||||
|
|
||||||
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
public void Queued()
|
||||||
|
{
|
||||||
|
Log.Trace("Getting the settings");
|
||||||
|
|
||||||
|
var watcherSettings = WatcherSettings.GetSettings();
|
||||||
|
|
||||||
|
Job.SetRunning(true, JobNames.WatcherCacher);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (watcherSettings.Enabled)
|
||||||
|
{
|
||||||
|
var movies = WatcherApi.ListMovies(watcherSettings.ApiKey, watcherSettings.FullUri);
|
||||||
|
if (movies.Error)
|
||||||
|
{
|
||||||
|
Log.Error("Error when trying to get Watchers movies");
|
||||||
|
Log.Error(movies.ErrorMessage);
|
||||||
|
}
|
||||||
|
var wantedMovies =
|
||||||
|
movies?.Results?.Where(x => x.status.Equals("Wanted", StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
if (wantedMovies != null && wantedMovies.Any())
|
||||||
|
{
|
||||||
|
Cache.Set(CacheKeys.WatcherQueued, movies.Results.Select(x => x.imdbid), CacheKeys.TimeFrameMinutes.SchedulerCaching);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Job.Record(JobNames.WatcherCacher);
|
||||||
|
Job.SetRunning(false, JobNames.WatcherCacher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we do not want to set here...
|
||||||
|
public string[] QueuedIds()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
var watcherSettings = WatcherSettings.GetSettings();
|
||||||
|
|
||||||
|
if (watcherSettings.Enabled)
|
||||||
|
{
|
||||||
|
var movies = Cache.Get<string[]>(CacheKeys.WatcherQueued);
|
||||||
|
|
||||||
|
if (movies != null)
|
||||||
|
{
|
||||||
|
return movies;
|
||||||
|
}
|
||||||
|
return new string[] {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e);
|
||||||
|
return new string[] { };
|
||||||
|
}
|
||||||
|
return new string[] {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
Queued();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -86,8 +86,10 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Interfaces\IWatcherCacher.cs" />
|
||||||
<Compile Include="Interfaces\IJobRecord.cs" />
|
<Compile Include="Interfaces\IJobRecord.cs" />
|
||||||
<Compile Include="Interfaces\INotificationEngine.cs" />
|
<Compile Include="Interfaces\INotificationEngine.cs" />
|
||||||
|
<Compile Include="Jobs\WatcherCacher.cs" />
|
||||||
<Compile Include="Jobs\HtmlTemplateGenerator.cs" />
|
<Compile Include="Jobs\HtmlTemplateGenerator.cs" />
|
||||||
<Compile Include="Jobs\IPlexContentCacher.cs" />
|
<Compile Include="Jobs\IPlexContentCacher.cs" />
|
||||||
<Compile Include="Jobs\IRecentlyAdded.cs" />
|
<Compile Include="Jobs\IRecentlyAdded.cs" />
|
||||||
|
|
|
@ -33,6 +33,7 @@ using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using Ombi.Core;
|
using Ombi.Core;
|
||||||
using Ombi.Core.SettingModels;
|
using Ombi.Core.SettingModels;
|
||||||
|
using Ombi.Services.Interfaces;
|
||||||
using Ombi.Services.Jobs;
|
using Ombi.Services.Jobs;
|
||||||
using Ombi.UI.Helpers;
|
using Ombi.UI.Helpers;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
|
@ -68,6 +69,7 @@ namespace Ombi.UI.Jobs
|
||||||
JobBuilder.Create<SickRageCacher>().WithIdentity("SickRageCacher", "Cache").Build(),
|
JobBuilder.Create<SickRageCacher>().WithIdentity("SickRageCacher", "Cache").Build(),
|
||||||
JobBuilder.Create<SonarrCacher>().WithIdentity("SonarrCacher", "Cache").Build(),
|
JobBuilder.Create<SonarrCacher>().WithIdentity("SonarrCacher", "Cache").Build(),
|
||||||
JobBuilder.Create<CouchPotatoCacher>().WithIdentity("CouchPotatoCacher", "Cache").Build(),
|
JobBuilder.Create<CouchPotatoCacher>().WithIdentity("CouchPotatoCacher", "Cache").Build(),
|
||||||
|
JobBuilder.Create<WatcherCacher>().WithIdentity("WatcherCacher", "Cache").Build(),
|
||||||
JobBuilder.Create<StoreBackup>().WithIdentity("StoreBackup", "Database").Build(),
|
JobBuilder.Create<StoreBackup>().WithIdentity("StoreBackup", "Database").Build(),
|
||||||
JobBuilder.Create<StoreCleanup>().WithIdentity("StoreCleanup", "Database").Build(),
|
JobBuilder.Create<StoreCleanup>().WithIdentity("StoreCleanup", "Database").Build(),
|
||||||
JobBuilder.Create<UserRequestLimitResetter>().WithIdentity("UserRequestLimiter", "Request").Build(),
|
JobBuilder.Create<UserRequestLimitResetter>().WithIdentity("UserRequestLimiter", "Request").Build(),
|
||||||
|
@ -117,6 +119,10 @@ namespace Ombi.UI.Jobs
|
||||||
{
|
{
|
||||||
s.CouchPotatoCacher = 60;
|
s.CouchPotatoCacher = 60;
|
||||||
}
|
}
|
||||||
|
if (s.WatcherCacher == 0)
|
||||||
|
{
|
||||||
|
s.WatcherCacher = 60;
|
||||||
|
}
|
||||||
if (s.PlexAvailabilityChecker == 0)
|
if (s.PlexAvailabilityChecker == 0)
|
||||||
{
|
{
|
||||||
s.PlexAvailabilityChecker = 60;
|
s.PlexAvailabilityChecker = 60;
|
||||||
|
@ -208,6 +214,13 @@ namespace Ombi.UI.Jobs
|
||||||
.WithSimpleSchedule(x => x.WithIntervalInMinutes(s.CouchPotatoCacher).RepeatForever())
|
.WithSimpleSchedule(x => x.WithIntervalInMinutes(s.CouchPotatoCacher).RepeatForever())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
var watcherCacher =
|
||||||
|
TriggerBuilder.Create()
|
||||||
|
.WithIdentity("WatcherCacher", "Cache")
|
||||||
|
.StartAt(DateBuilder.FutureDate(4, IntervalUnit.Minute))
|
||||||
|
.WithSimpleSchedule(x => x.WithIntervalInMinutes(s.WatcherCacher).RepeatForever())
|
||||||
|
.Build();
|
||||||
|
|
||||||
var storeBackup =
|
var storeBackup =
|
||||||
TriggerBuilder.Create()
|
TriggerBuilder.Create()
|
||||||
.WithIdentity("StoreBackup", "Database")
|
.WithIdentity("StoreBackup", "Database")
|
||||||
|
@ -258,6 +271,7 @@ namespace Ombi.UI.Jobs
|
||||||
triggers.Add(srCacher);
|
triggers.Add(srCacher);
|
||||||
triggers.Add(sonarrCacher);
|
triggers.Add(sonarrCacher);
|
||||||
triggers.Add(cpCacher);
|
triggers.Add(cpCacher);
|
||||||
|
triggers.Add(watcherCacher);
|
||||||
triggers.Add(storeBackup);
|
triggers.Add(storeBackup);
|
||||||
triggers.Add(storeCleanup);
|
triggers.Add(storeCleanup);
|
||||||
triggers.Add(userRequestLimiter);
|
triggers.Add(userRequestLimiter);
|
||||||
|
|
|
@ -75,6 +75,7 @@ namespace Ombi.UI.Modules.Admin
|
||||||
private ISettingsService<PushoverNotificationSettings> PushoverService { get; }
|
private ISettingsService<PushoverNotificationSettings> PushoverService { get; }
|
||||||
private ISettingsService<HeadphonesSettings> HeadphonesService { get; }
|
private ISettingsService<HeadphonesSettings> HeadphonesService { get; }
|
||||||
private ISettingsService<NewletterSettings> NewsLetterService { get; }
|
private ISettingsService<NewletterSettings> NewsLetterService { get; }
|
||||||
|
private ISettingsService<WatcherSettings> WatcherSettings { get; }
|
||||||
private ISettingsService<LogSettings> LogService { get; }
|
private ISettingsService<LogSettings> LogService { get; }
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
private ISonarrApi SonarrApi { get; }
|
private ISonarrApi SonarrApi { get; }
|
||||||
|
@ -116,7 +117,8 @@ namespace Ombi.UI.Modules.Admin
|
||||||
ICacheProvider cache, ISettingsService<SlackNotificationSettings> slackSettings,
|
ICacheProvider cache, ISettingsService<SlackNotificationSettings> slackSettings,
|
||||||
ISlackApi slackApi, ISettingsService<LandingPageSettings> lp,
|
ISlackApi slackApi, ISettingsService<LandingPageSettings> lp,
|
||||||
ISettingsService<ScheduledJobsSettings> scheduler, IJobRecord rec, IAnalytics analytics,
|
ISettingsService<ScheduledJobsSettings> scheduler, IJobRecord rec, IAnalytics analytics,
|
||||||
ISettingsService<NotificationSettingsV2> notifyService, IRecentlyAdded recentlyAdded
|
ISettingsService<NotificationSettingsV2> notifyService, IRecentlyAdded recentlyAdded,
|
||||||
|
ISettingsService<WatcherSettings> watcherSettings
|
||||||
, ISecurityExtensions security) : base("admin", prService, security)
|
, ISecurityExtensions security) : base("admin", prService, security)
|
||||||
{
|
{
|
||||||
PrService = prService;
|
PrService = prService;
|
||||||
|
@ -147,6 +149,7 @@ namespace Ombi.UI.Modules.Admin
|
||||||
Analytics = analytics;
|
Analytics = analytics;
|
||||||
NotifySettings = notifyService;
|
NotifySettings = notifyService;
|
||||||
RecentlyAdded = recentlyAdded;
|
RecentlyAdded = recentlyAdded;
|
||||||
|
WatcherSettings = watcherSettings;
|
||||||
|
|
||||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||||
|
|
||||||
|
@ -374,6 +377,18 @@ namespace Ombi.UI.Modules.Admin
|
||||||
return Response.AsJson(valid.SendJsonError());
|
return Response.AsJson(valid.SendJsonError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var watcherSettings = WatcherSettings.GetSettings();
|
||||||
|
|
||||||
|
if (watcherSettings.Enabled)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
Response.AsJson(new JsonResponseModel
|
||||||
|
{
|
||||||
|
Result = false,
|
||||||
|
Message = "Cannot have Watcher and CouchPotato both enabled."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
couchPotatoSettings.ApiKey = couchPotatoSettings.ApiKey.Trim();
|
couchPotatoSettings.ApiKey = couchPotatoSettings.ApiKey.Trim();
|
||||||
var result = CpService.SaveSettings(couchPotatoSettings);
|
var result = CpService.SaveSettings(couchPotatoSettings);
|
||||||
return Response.AsJson(result
|
return Response.AsJson(result
|
||||||
|
|
107
Ombi.UI/Modules/Admin/IntegrationModule.cs
Normal file
107
Ombi.UI/Modules/Admin/IntegrationModule.cs
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: SystemStatusModule.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.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MarkdownSharp;
|
||||||
|
using Nancy;
|
||||||
|
using Nancy.ModelBinding;
|
||||||
|
using Nancy.Responses.Negotiation;
|
||||||
|
using Nancy.Validation;
|
||||||
|
using Ombi.Core;
|
||||||
|
using Ombi.Core.SettingModels;
|
||||||
|
using Ombi.Core.StatusChecker;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Helpers.Analytics;
|
||||||
|
using Ombi.Helpers.Permissions;
|
||||||
|
using Ombi.UI.Helpers;
|
||||||
|
using Ombi.UI.Models;
|
||||||
|
using Action = Ombi.Helpers.Analytics.Action;
|
||||||
|
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
|
||||||
|
|
||||||
|
namespace Ombi.UI.Modules.Admin
|
||||||
|
{
|
||||||
|
public class IntegrationModule : BaseModule
|
||||||
|
{
|
||||||
|
public IntegrationModule(ISettingsService<PlexRequestSettings> settingsService, ISettingsService<WatcherSettings> watcher,
|
||||||
|
ISettingsService<CouchPotatoSettings> cp,ISecurityExtensions security, IAnalytics a) : base("admin", settingsService, security)
|
||||||
|
{
|
||||||
|
|
||||||
|
WatcherSettings = watcher;
|
||||||
|
Analytics = a;
|
||||||
|
|
||||||
|
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||||
|
|
||||||
|
Get["/watcher", true] = async (x, ct) => await Watcher();
|
||||||
|
Post["/watcher", true] = async (x, ct) => await SaveWatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ISettingsService<WatcherSettings> WatcherSettings { get; }
|
||||||
|
private ISettingsService<CouchPotatoSettings> CpSettings { get; }
|
||||||
|
private IAnalytics Analytics { get; }
|
||||||
|
|
||||||
|
private async Task<Negotiator> Watcher()
|
||||||
|
{
|
||||||
|
var settings = await WatcherSettings.GetSettingsAsync();
|
||||||
|
|
||||||
|
return View["Watcher", settings];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Response> SaveWatcher()
|
||||||
|
{
|
||||||
|
var settings = this.Bind<WatcherSettings>();
|
||||||
|
var valid = this.Validate(settings);
|
||||||
|
if (!valid.IsValid)
|
||||||
|
{
|
||||||
|
return Response.AsJson(valid.SendJsonError());
|
||||||
|
}
|
||||||
|
|
||||||
|
var cpSettings = await CpSettings.GetSettingsAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (cpSettings.Enabled)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
Response.AsJson(new JsonResponseModel
|
||||||
|
{
|
||||||
|
Result = false,
|
||||||
|
Message = "Cannot have Watcher and CouchPotato both enabled."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.ApiKey = settings.ApiKey.Trim();
|
||||||
|
var result = await WatcherSettings.SaveSettingsAsync(settings);
|
||||||
|
return Response.AsJson(result
|
||||||
|
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Watcher!" }
|
||||||
|
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,7 +45,8 @@ namespace Ombi.UI.Modules
|
||||||
{
|
{
|
||||||
|
|
||||||
public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi,
|
public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi,
|
||||||
ISickRageApi srApi, IHeadphonesApi hpApi, ISettingsService<PlexRequestSettings> pr, ISecurityExtensions security) : base("test", pr, security)
|
ISickRageApi srApi, IHeadphonesApi hpApi, ISettingsService<PlexRequestSettings> pr, ISecurityExtensions security,
|
||||||
|
IWatcherApi watcherApi) : base("test", pr, security)
|
||||||
{
|
{
|
||||||
this.RequiresAuthentication();
|
this.RequiresAuthentication();
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ namespace Ombi.UI.Modules
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
SickRageApi = srApi;
|
SickRageApi = srApi;
|
||||||
HeadphonesApi = hpApi;
|
HeadphonesApi = hpApi;
|
||||||
|
WatcherApi = watcherApi;
|
||||||
|
|
||||||
Post["/cp"] = _ => CouchPotatoTest();
|
Post["/cp"] = _ => CouchPotatoTest();
|
||||||
Post["/sonarr"] = _ => SonarrTest();
|
Post["/sonarr"] = _ => SonarrTest();
|
||||||
|
@ -61,6 +63,7 @@ namespace Ombi.UI.Modules
|
||||||
Post["/sickrage"] = _ => SickRageTest();
|
Post["/sickrage"] = _ => SickRageTest();
|
||||||
Post["/headphones"] = _ => HeadphonesTest();
|
Post["/headphones"] = _ => HeadphonesTest();
|
||||||
Post["/plexdb"] = _ => TestPlexDb();
|
Post["/plexdb"] = _ => TestPlexDb();
|
||||||
|
Post["/watcher"] = _ => WatcherTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
@ -69,6 +72,7 @@ namespace Ombi.UI.Modules
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
private ISickRageApi SickRageApi { get; }
|
private ISickRageApi SickRageApi { get; }
|
||||||
private IHeadphonesApi HeadphonesApi { get; }
|
private IHeadphonesApi HeadphonesApi { get; }
|
||||||
|
private IWatcherApi WatcherApi { get; }
|
||||||
|
|
||||||
private Response CouchPotatoTest()
|
private Response CouchPotatoTest()
|
||||||
{
|
{
|
||||||
|
@ -86,7 +90,7 @@ namespace Ombi.UI.Modules
|
||||||
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to CouchPotato, please check your settings." });
|
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to CouchPotato, 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 CP's status: ");
|
Log.Warn("Exception thrown when attempting to get CP's status: ");
|
||||||
Log.Warn(e);
|
Log.Warn(e);
|
||||||
|
@ -99,6 +103,35 @@ namespace Ombi.UI.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response WatcherTest()
|
||||||
|
{
|
||||||
|
var settings = this.Bind<WatcherSettings>();
|
||||||
|
var valid = this.Validate(settings);
|
||||||
|
if (!valid.IsValid)
|
||||||
|
{
|
||||||
|
return Response.AsJson(valid.SendJsonError());
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var status = WatcherApi.ListMovies(settings.ApiKey, settings.FullUri);
|
||||||
|
return !status.Error
|
||||||
|
? Response.AsJson(new JsonResponseModel { Result = true, Message = "Connected to Watcher successfully!" })
|
||||||
|
: Response.AsJson(new JsonResponseModel { Result = false, Message = $"Could not connect to Watcher, Error: {status.ErrorMessage}" });
|
||||||
|
|
||||||
|
}
|
||||||
|
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 test Watcher ");
|
||||||
|
Log.Warn(e);
|
||||||
|
var message = $"Could not connect to Watcher, please check your settings. <strong>Exception Message:</strong> {e.Message}";
|
||||||
|
if (e.InnerException != null)
|
||||||
|
{
|
||||||
|
message = $"Could not connect to Watcher, please check your settings. <strong>Exception Message:</strong> {e.InnerException.Message}";
|
||||||
|
}
|
||||||
|
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Response SonarrTest()
|
private Response SonarrTest()
|
||||||
{
|
{
|
||||||
var sonarrSettings = this.Bind<SonarrSettings>();
|
var sonarrSettings = this.Bind<SonarrSettings>();
|
||||||
|
|
|
@ -47,17 +47,15 @@ namespace Ombi.UI.Modules
|
||||||
public class ApprovalModule : BaseAuthModule
|
public class ApprovalModule : BaseAuthModule
|
||||||
{
|
{
|
||||||
|
|
||||||
public ApprovalModule(IRequestService service, ISettingsService<CouchPotatoSettings> cpService, ICouchPotatoApi cpApi, ISonarrApi sonarrApi,
|
public ApprovalModule(IRequestService service, ISonarrApi sonarrApi,
|
||||||
ISettingsService<SonarrSettings> sonarrSettings, ISickRageApi srApi, ISettingsService<SickRageSettings> srSettings,
|
ISettingsService<SonarrSettings> sonarrSettings, ISickRageApi srApi, ISettingsService<SickRageSettings> srSettings,
|
||||||
ISettingsService<HeadphonesSettings> hpSettings, IHeadphonesApi hpApi, ISettingsService<PlexRequestSettings> pr, ITransientFaultQueue faultQueue
|
ISettingsService<HeadphonesSettings> hpSettings, IHeadphonesApi hpApi, ISettingsService<PlexRequestSettings> pr, ITransientFaultQueue faultQueue
|
||||||
, ISecurityExtensions security) : base("approval", pr, security)
|
, ISecurityExtensions security, IMovieSender movieSender) : base("approval", pr, security)
|
||||||
{
|
{
|
||||||
|
|
||||||
Before += (ctx) => Security.AdminLoginRedirect(ctx, Permissions.Administrator,Permissions.ManageRequests);
|
Before += (ctx) => Security.AdminLoginRedirect(ctx, Permissions.Administrator,Permissions.ManageRequests);
|
||||||
|
|
||||||
Service = service;
|
Service = service;
|
||||||
CpService = cpService;
|
|
||||||
CpApi = cpApi;
|
|
||||||
SonarrApi = sonarrApi;
|
SonarrApi = sonarrApi;
|
||||||
SonarrSettings = sonarrSettings;
|
SonarrSettings = sonarrSettings;
|
||||||
SickRageApi = srApi;
|
SickRageApi = srApi;
|
||||||
|
@ -65,6 +63,7 @@ namespace Ombi.UI.Modules
|
||||||
HeadphonesSettings = hpSettings;
|
HeadphonesSettings = hpSettings;
|
||||||
HeadphoneApi = hpApi;
|
HeadphoneApi = hpApi;
|
||||||
FaultQueue = faultQueue;
|
FaultQueue = faultQueue;
|
||||||
|
MovieSender = movieSender;
|
||||||
|
|
||||||
Post["/approve", true] = async (x, ct) => await Approve((int)Request.Form.requestid, (string)Request.Form.qualityId);
|
Post["/approve", true] = async (x, ct) => await Approve((int)Request.Form.requestid, (string)Request.Form.qualityId);
|
||||||
Post["/deny", true] = async (x, ct) => await DenyRequest((int)Request.Form.requestid, (string)Request.Form.reason);
|
Post["/deny", true] = async (x, ct) => await DenyRequest((int)Request.Form.requestid, (string)Request.Form.reason);
|
||||||
|
@ -77,15 +76,14 @@ namespace Ombi.UI.Modules
|
||||||
}
|
}
|
||||||
|
|
||||||
private IRequestService Service { get; }
|
private IRequestService Service { get; }
|
||||||
|
private IMovieSender MovieSender { get; }
|
||||||
|
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
private ISettingsService<SonarrSettings> SonarrSettings { get; }
|
private ISettingsService<SonarrSettings> SonarrSettings { get; }
|
||||||
private ISettingsService<SickRageSettings> SickRageSettings { get; }
|
private ISettingsService<SickRageSettings> SickRageSettings { get; }
|
||||||
private ISettingsService<CouchPotatoSettings> CpService { get; }
|
|
||||||
private ISettingsService<HeadphonesSettings> HeadphonesSettings { get; }
|
private ISettingsService<HeadphonesSettings> HeadphonesSettings { get; }
|
||||||
private ISonarrApi SonarrApi { get; }
|
private ISonarrApi SonarrApi { get; }
|
||||||
private ISickRageApi SickRageApi { get; }
|
private ISickRageApi SickRageApi { get; }
|
||||||
private ICouchPotatoApi CpApi { get; }
|
|
||||||
private IHeadphonesApi HeadphoneApi { get; }
|
private IHeadphonesApi HeadphoneApi { get; }
|
||||||
private ITransientFaultQueue FaultQueue { get; }
|
private ITransientFaultQueue FaultQueue { get; }
|
||||||
|
|
||||||
|
@ -186,19 +184,19 @@ namespace Ombi.UI.Modules
|
||||||
|
|
||||||
private async Task<Response> RequestMovieAndUpdateStatus(RequestedModel request, string qualityId)
|
private async Task<Response> RequestMovieAndUpdateStatus(RequestedModel request, string qualityId)
|
||||||
{
|
{
|
||||||
var cpSettings = await CpService.GetSettingsAsync();
|
|
||||||
|
|
||||||
Log.Info("Adding movie to CouchPotato : {0}", request.Title);
|
var result = await MovieSender.Send(request, qualityId);
|
||||||
if (!cpSettings.Enabled)
|
|
||||||
|
if (!result.MovieSendingEnabled)
|
||||||
{
|
{
|
||||||
// Approve it
|
// Approve it
|
||||||
request.Approved = true;
|
request.Approved = true;
|
||||||
Log.Warn("We approved movie: {0} but could not add it to CouchPotato because it has not been setup", request.Title);
|
Log.Warn("We approved movie: {0} but could not add it to CouchPotato/Watcher because it has not been setup", request.Title);
|
||||||
|
|
||||||
// Update the record
|
// Update the record
|
||||||
var inserted = await Service.UpdateRequestAsync(request);
|
var inserted = await Service.UpdateRequestAsync(request);
|
||||||
return Response.AsJson(inserted
|
return Response.AsJson(inserted
|
||||||
? new JsonResponseModel { Result = true, Message = "This has been approved, but It has not been sent to CouchPotato because it has not been configured." }
|
? new JsonResponseModel { Result = true, Message = "This has been approved, but It has not been sent to CouchPotato/Watcher because it has not been configured." }
|
||||||
: new JsonResponseModel
|
: new JsonResponseModel
|
||||||
{
|
{
|
||||||
Result = false,
|
Result = false,
|
||||||
|
@ -206,9 +204,7 @@ namespace Ombi.UI.Modules
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = CpApi.AddMovie(request.ImdbId, cpSettings.ApiKey, request.Title, cpSettings.FullUri, string.IsNullOrEmpty(qualityId) ? cpSettings.ProfileId : qualityId);
|
if (result.Result)
|
||||||
Log.Trace("Adding movie to CP result {0}", result);
|
|
||||||
if (result)
|
|
||||||
{
|
{
|
||||||
// Approve it
|
// Approve it
|
||||||
request.Approved = true;
|
request.Approved = true;
|
||||||
|
@ -230,7 +226,7 @@ namespace Ombi.UI.Modules
|
||||||
{
|
{
|
||||||
Result = false,
|
Result = false,
|
||||||
Message =
|
Message =
|
||||||
"Something went wrong adding the movie to CouchPotato! Please check your settings."
|
"Something went wrong adding the movie! Please check your settings."
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,26 +411,23 @@ namespace Ombi.UI.Modules
|
||||||
|
|
||||||
private async Task<Response> UpdateRequestsAsync(RequestedModel[] requestedModels)
|
private async Task<Response> UpdateRequestsAsync(RequestedModel[] requestedModels)
|
||||||
{
|
{
|
||||||
var cpSettings = await CpService.GetSettingsAsync();
|
|
||||||
var updatedRequests = new List<RequestedModel>();
|
var updatedRequests = new List<RequestedModel>();
|
||||||
foreach (var r in requestedModels)
|
foreach (var r in requestedModels)
|
||||||
{
|
{
|
||||||
if (r.Type == RequestType.Movie)
|
if (r.Type == RequestType.Movie)
|
||||||
{
|
{
|
||||||
if (cpSettings.Enabled)
|
var movieResult = await MovieSender.Send(r);
|
||||||
|
if (movieResult.Result)
|
||||||
{
|
{
|
||||||
var res = SendMovie(cpSettings, r, CpApi);
|
r.Approved = true;
|
||||||
if (res)
|
updatedRequests.Add(r);
|
||||||
{
|
|
||||||
r.Approved = true;
|
|
||||||
updatedRequests.Add(r);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Error("Could not approve and send the movie {0} to couch potato!", r.Title);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
Log.Error("Could not approve and send the movie {0} to couch potato!", r.Title);
|
||||||
|
}
|
||||||
|
if(!movieResult.MovieSendingEnabled)
|
||||||
{
|
{
|
||||||
r.Approved = true;
|
r.Approved = true;
|
||||||
updatedRequests.Add(r);
|
updatedRequests.Add(r);
|
||||||
|
@ -512,13 +505,5 @@ namespace Ombi.UI.Modules
|
||||||
: Response.AsJson(new JsonResponseModel { Result = false, Message = "An error happened, could not update the DB" });
|
: Response.AsJson(new JsonResponseModel { Result = false, Message = "An error happened, could not update the DB" });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SendMovie(CouchPotatoSettings settings, RequestedModel r, ICouchPotatoApi cp)
|
|
||||||
{
|
|
||||||
Log.Info("Adding movie to CP : {0}", r.Title);
|
|
||||||
var result = cp.AddMovie(r.ImdbId, settings.ApiKey, r.Title, settings.FullUri, settings.ProfileId);
|
|
||||||
Log.Trace("Adding movie to CP result {0}", result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -66,22 +66,22 @@ namespace Ombi.UI.Modules
|
||||||
{
|
{
|
||||||
public class SearchModule : BaseAuthModule
|
public class SearchModule : BaseAuthModule
|
||||||
{
|
{
|
||||||
public SearchModule(ICacheProvider cache, ISettingsService<CouchPotatoSettings> cpSettings,
|
public SearchModule(ICacheProvider cache,
|
||||||
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker checker,
|
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker checker,
|
||||||
IRequestService request, ISonarrApi sonarrApi, ISettingsService<SonarrSettings> sonarrSettings,
|
IRequestService request, ISonarrApi sonarrApi, ISettingsService<SonarrSettings> sonarrSettings,
|
||||||
ISettingsService<SickRageSettings> sickRageService, ICouchPotatoApi cpApi, ISickRageApi srApi,
|
ISettingsService<SickRageSettings> sickRageService, ISickRageApi srApi,
|
||||||
INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi,
|
INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi,
|
||||||
ISettingsService<HeadphonesSettings> hpService,
|
ISettingsService<HeadphonesSettings> hpService,
|
||||||
ICouchPotatoCacher cpCacher, ISonarrCacher sonarrCacher, ISickRageCacher sickRageCacher, IPlexApi plexApi,
|
ICouchPotatoCacher cpCacher, IWatcherCacher watcherCacher, ISonarrCacher sonarrCacher, ISickRageCacher sickRageCacher, IPlexApi plexApi,
|
||||||
ISettingsService<PlexSettings> plexService, ISettingsService<AuthenticationSettings> auth,
|
ISettingsService<PlexSettings> plexService, ISettingsService<AuthenticationSettings> auth,
|
||||||
IRepository<UsersToNotify> u, ISettingsService<EmailNotificationSettings> email,
|
IRepository<UsersToNotify> u, ISettingsService<EmailNotificationSettings> email,
|
||||||
IIssueService issue, IAnalytics a, IRepository<RequestLimit> rl, ITransientFaultQueue tfQueue, IRepository<PlexContent> content, ISecurityExtensions security)
|
IIssueService issue, IAnalytics a, IRepository<RequestLimit> rl, ITransientFaultQueue tfQueue, IRepository<PlexContent> content,
|
||||||
|
ISecurityExtensions security, IMovieSender movieSender)
|
||||||
: base("search", prSettings, security)
|
: base("search", prSettings, security)
|
||||||
{
|
{
|
||||||
Auth = auth;
|
Auth = auth;
|
||||||
PlexService = plexService;
|
PlexService = plexService;
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
CpService = cpSettings;
|
|
||||||
PrService = prSettings;
|
PrService = prSettings;
|
||||||
MovieApi = new TheMovieDbApi();
|
MovieApi = new TheMovieDbApi();
|
||||||
Cache = cache;
|
Cache = cache;
|
||||||
|
@ -92,7 +92,6 @@ namespace Ombi.UI.Modules
|
||||||
RequestService = request;
|
RequestService = request;
|
||||||
SonarrApi = sonarrApi;
|
SonarrApi = sonarrApi;
|
||||||
SonarrService = sonarrSettings;
|
SonarrService = sonarrSettings;
|
||||||
CouchPotatoApi = cpApi;
|
|
||||||
SickRageService = sickRageService;
|
SickRageService = sickRageService;
|
||||||
SickrageApi = srApi;
|
SickrageApi = srApi;
|
||||||
NotificationService = notify;
|
NotificationService = notify;
|
||||||
|
@ -107,7 +106,8 @@ namespace Ombi.UI.Modules
|
||||||
FaultQueue = tfQueue;
|
FaultQueue = tfQueue;
|
||||||
TvApi = new TvMazeApi();
|
TvApi = new TvMazeApi();
|
||||||
PlexContentRepository = content;
|
PlexContentRepository = content;
|
||||||
|
MovieSender = movieSender;
|
||||||
|
WatcherCacher = watcherCacher;
|
||||||
|
|
||||||
Get["SearchIndex", "/", true] = async (x, ct) => await RequestLoad();
|
Get["SearchIndex", "/", true] = async (x, ct) => await RequestLoad();
|
||||||
|
|
||||||
|
@ -128,20 +128,19 @@ namespace Ombi.UI.Modules
|
||||||
Get["/seasons"] = x => GetSeasons();
|
Get["/seasons"] = x => GetSeasons();
|
||||||
Get["/episodes", true] = async (x, ct) => await GetEpisodes();
|
Get["/episodes", true] = async (x, ct) => await GetEpisodes();
|
||||||
}
|
}
|
||||||
|
private IWatcherCacher WatcherCacher { get; }
|
||||||
|
private IMovieSender MovieSender { get; }
|
||||||
private IRepository<PlexContent> PlexContentRepository { get; }
|
private IRepository<PlexContent> PlexContentRepository { get; }
|
||||||
private TvMazeApi TvApi { get; }
|
private TvMazeApi TvApi { get; }
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
private TheMovieDbApi MovieApi { get; }
|
private TheMovieDbApi MovieApi { get; }
|
||||||
private INotificationService NotificationService { get; }
|
private INotificationService NotificationService { get; }
|
||||||
private ICouchPotatoApi CouchPotatoApi { get; }
|
|
||||||
private ISonarrApi SonarrApi { get; }
|
private ISonarrApi SonarrApi { get; }
|
||||||
private ISickRageApi SickrageApi { get; }
|
private ISickRageApi SickrageApi { get; }
|
||||||
private IRequestService RequestService { get; }
|
private IRequestService RequestService { get; }
|
||||||
private ICacheProvider Cache { get; }
|
private ICacheProvider Cache { get; }
|
||||||
private ISettingsService<AuthenticationSettings> Auth { get; }
|
private ISettingsService<AuthenticationSettings> Auth { get; }
|
||||||
private ISettingsService<PlexSettings> PlexService { get; }
|
private ISettingsService<PlexSettings> PlexService { get; }
|
||||||
private ISettingsService<CouchPotatoSettings> CpService { get; }
|
|
||||||
private ISettingsService<PlexRequestSettings> PrService { get; }
|
private ISettingsService<PlexRequestSettings> PrService { get; }
|
||||||
private ISettingsService<SonarrSettings> SonarrService { get; }
|
private ISettingsService<SonarrSettings> SonarrService { get; }
|
||||||
private ISettingsService<SickRageSettings> SickRageService { get; }
|
private ISettingsService<SickRageSettings> SickRageService { get; }
|
||||||
|
@ -236,9 +235,9 @@ namespace Ombi.UI.Modules
|
||||||
|
|
||||||
|
|
||||||
var cpCached = CpCacher.QueuedIds();
|
var cpCached = CpCacher.QueuedIds();
|
||||||
|
var watcherCached = WatcherCacher.QueuedIds();
|
||||||
var content = PlexContentRepository.GetAll();
|
var content = PlexContentRepository.GetAll();
|
||||||
var plexMovies = Checker.GetPlexMovies(content);
|
var plexMovies = Checker.GetPlexMovies(content);
|
||||||
var settings = await PrService.GetSettingsAsync();
|
|
||||||
var viewMovies = new List<SearchMovieViewModel>();
|
var viewMovies = new List<SearchMovieViewModel>();
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
foreach (var movie in apiMovies)
|
foreach (var movie in apiMovies)
|
||||||
|
@ -290,6 +289,10 @@ namespace Ombi.UI.Modules
|
||||||
{
|
{
|
||||||
viewMovie.Requested = true;
|
viewMovie.Requested = true;
|
||||||
}
|
}
|
||||||
|
else if(watcherCached.Contains(imdbId) && canSee) // compare to the watcher db
|
||||||
|
{
|
||||||
|
viewMovie.Requested = true;
|
||||||
|
}
|
||||||
|
|
||||||
viewMovies.Add(viewMovie);
|
viewMovies.Add(viewMovie);
|
||||||
}
|
}
|
||||||
|
@ -564,30 +567,25 @@ namespace Ombi.UI.Modules
|
||||||
{
|
{
|
||||||
if (ShouldAutoApprove(RequestType.Movie, settings, Username))
|
if (ShouldAutoApprove(RequestType.Movie, settings, Username))
|
||||||
{
|
{
|
||||||
var cpSettings = await CpService.GetSettingsAsync();
|
|
||||||
model.Approved = true;
|
|
||||||
if (cpSettings.Enabled)
|
|
||||||
{
|
|
||||||
Log.Info("Adding movie to CP (No approval required)");
|
|
||||||
var result = CouchPotatoApi.AddMovie(model.ImdbId, cpSettings.ApiKey, model.Title,
|
|
||||||
cpSettings.FullUri, cpSettings.ProfileId);
|
|
||||||
Log.Debug("Adding movie to CP result {0}", result);
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
await
|
|
||||||
AddRequest(model, settings,
|
|
||||||
$"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response.AsJson(new JsonResponseModel
|
var result = await MovieSender.Send(model);
|
||||||
{
|
if (result.Result)
|
||||||
Result = false,
|
{
|
||||||
Message = Resources.UI.Search_CouchPotatoError
|
return await AddRequest(model, settings,
|
||||||
});
|
$"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
||||||
}
|
}
|
||||||
model.Approved = true;
|
if (!result.MovieSendingEnabled)
|
||||||
return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
{
|
||||||
|
|
||||||
|
model.Approved = true;
|
||||||
|
return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.AsJson(new JsonResponseModel
|
||||||
|
{
|
||||||
|
Result = false,
|
||||||
|
Message = Resources.UI.Search_CouchPotatoError
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace Ombi.UI.NinjectModules
|
||||||
{
|
{
|
||||||
Bind<IAvailabilityChecker>().To<PlexAvailabilityChecker>();
|
Bind<IAvailabilityChecker>().To<PlexAvailabilityChecker>();
|
||||||
Bind<ICouchPotatoCacher>().To<CouchPotatoCacher>();
|
Bind<ICouchPotatoCacher>().To<CouchPotatoCacher>();
|
||||||
|
Bind<IWatcherCacher>().To<IWatcherCacher>();
|
||||||
Bind<ISonarrCacher>().To<SonarrCacher>();
|
Bind<ISonarrCacher>().To<SonarrCacher>();
|
||||||
Bind<ISickRageCacher>().To<SickRageCacher>();
|
Bind<ISickRageCacher>().To<SickRageCacher>();
|
||||||
Bind<IRecentlyAdded>().To<RecentlyAdded>();
|
Bind<IRecentlyAdded>().To<RecentlyAdded>();
|
||||||
|
|
|
@ -251,6 +251,7 @@
|
||||||
<Compile Include="Models\UserManagement\UserUpdateViewModel.cs" />
|
<Compile Include="Models\UserManagement\UserUpdateViewModel.cs" />
|
||||||
<Compile Include="Modules\Admin\AboutModule.cs" />
|
<Compile Include="Modules\Admin\AboutModule.cs" />
|
||||||
<Compile Include="Modules\Admin\CustomizationModule.cs" />
|
<Compile Include="Modules\Admin\CustomizationModule.cs" />
|
||||||
|
<Compile Include="Modules\Admin\IntegrationModule.cs" />
|
||||||
<Compile Include="Modules\Admin\UserManagementSettingsModule.cs" />
|
<Compile Include="Modules\Admin\UserManagementSettingsModule.cs" />
|
||||||
<Compile Include="Modules\Admin\FaultQueueModule.cs" />
|
<Compile Include="Modules\Admin\FaultQueueModule.cs" />
|
||||||
<Compile Include="Modules\Admin\SystemStatusModule.cs" />
|
<Compile Include="Modules\Admin\SystemStatusModule.cs" />
|
||||||
|
@ -282,6 +283,7 @@
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Start\StartupOptions.cs" />
|
<Compile Include="Start\StartupOptions.cs" />
|
||||||
<Compile Include="Start\UpdateValue.cs" />
|
<Compile Include="Start\UpdateValue.cs" />
|
||||||
|
<Compile Include="Validators\WatcherValidator.cs" />
|
||||||
<Compile Include="Validators\SlackSettingsValidator.cs" />
|
<Compile Include="Validators\SlackSettingsValidator.cs" />
|
||||||
<Compile Include="Validators\UserViewModelValidator.cs" />
|
<Compile Include="Validators\UserViewModelValidator.cs" />
|
||||||
<Compile Include="Validators\HeadphonesValidator.cs" />
|
<Compile Include="Validators\HeadphonesValidator.cs" />
|
||||||
|
@ -761,6 +763,9 @@
|
||||||
<Content Include="Views\About\About.cshtml">
|
<Content Include="Views\About\About.cshtml">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Views\Integration\Watcher.cshtml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<None Include="Views\Admin\NewsletterSettings.cshtml">
|
<None Include="Views\Admin\NewsletterSettings.cshtml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
|
43
Ombi.UI/Validators/WatcherValidator.cs
Normal file
43
Ombi.UI/Validators/WatcherValidator.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
#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 WatcherValidator : AbstractValidator<WatcherSettings>
|
||||||
|
{
|
||||||
|
public WatcherValidator()
|
||||||
|
{
|
||||||
|
RuleFor(request => request.Ip).NotEmpty().WithMessage("You must specify a IP/Host name.");
|
||||||
|
RuleFor(request => request.Port).NotEmpty().WithMessage("You must specify a Port.");
|
||||||
|
RuleFor(request => request.ApiKey).NotEmpty().WithMessage("You must specify a Api Key.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
133
Ombi.UI/Views/Integration/Watcher.cshtml
Normal file
133
Ombi.UI/Views/Integration/Watcher.cshtml
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
@using Ombi.UI.Helpers
|
||||||
|
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<Ombi.Core.SettingModels.WatcherSettings>
|
||||||
|
@Html.Partial("Shared/Partial/_Sidebar")
|
||||||
|
@{
|
||||||
|
int port;
|
||||||
|
if (Model.Port == 0)
|
||||||
|
{
|
||||||
|
port = 9090;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
port = Model.Port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<div class="col-sm-8 col-sm-push-1">
|
||||||
|
<form class="form-horizontal" method="POST" id="mainForm">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Watcher Settings</legend>
|
||||||
|
|
||||||
|
@Html.Checkbox(Model.Enabled, "Enabled", "Enabled")
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="Ip" class="control-label">Watcher Hostname or IP</label>
|
||||||
|
<div class="">
|
||||||
|
<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 class="">
|
||||||
|
<input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="Port Number" value="@port">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="ApiKey" class="control-label">Watcher API Key</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="ApiKey" name="ApiKey" value="@Model.ApiKey">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@Html.Checkbox(Model.Ssl, "Ssl", "SSL")
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="SubDir" class="control-label">Watcher Base Url</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="SubDir" name="SubDir" value="@Model.SubDir">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button id="testWatcher" 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 baseUrl = '@Html.GetBaseUrl()';
|
||||||
|
|
||||||
|
|
||||||
|
$('#testWatcher').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var $form = $("#mainForm");
|
||||||
|
var url = createBaseUrl(baseUrl, "/test/watcher");
|
||||||
|
$('#spinner').attr("class", "fa fa-spinner fa-spin");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: $form.prop("method"),
|
||||||
|
url: url,
|
||||||
|
data: $form.serialize(),
|
||||||
|
dataType: "json",
|
||||||
|
success: function (response) {
|
||||||
|
console.log(response);
|
||||||
|
if (response.result === true) {
|
||||||
|
$('#spinner').attr("class", "fa fa-check");
|
||||||
|
generateNotify(response.message, "success");
|
||||||
|
} else {
|
||||||
|
generateNotify(response.message, "warning");
|
||||||
|
$('#spinner').attr("class", "fa fa-times");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (e) {
|
||||||
|
console.log(e);
|
||||||
|
generateNotify("Something went wrong!", "danger");
|
||||||
|
$('#spinner').attr("class", "fa fa-times");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#save').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var $form = $("#mainForm");
|
||||||
|
var data = $form.serialize();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: $form.prop("method"),
|
||||||
|
data: data,
|
||||||
|
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>
|
|
@ -9,6 +9,7 @@
|
||||||
@Html.GetSidebarUrl(Context, "/admin/usermanagementsettings", "User Management Settings")
|
@Html.GetSidebarUrl(Context, "/admin/usermanagementsettings", "User Management Settings")
|
||||||
@Html.GetSidebarUrl(Context, "/admin/plex", "Plex")
|
@Html.GetSidebarUrl(Context, "/admin/plex", "Plex")
|
||||||
@Html.GetSidebarUrl(Context, "/admin/couchpotato", "CouchPotato")
|
@Html.GetSidebarUrl(Context, "/admin/couchpotato", "CouchPotato")
|
||||||
|
@Html.GetSidebarUrl(Context, "/admin/watcher", "Watcher")
|
||||||
@Html.GetSidebarUrl(Context, "/admin/sonarr", "Sonarr")
|
@Html.GetSidebarUrl(Context, "/admin/sonarr", "Sonarr")
|
||||||
@Html.GetSidebarUrl(Context, "/admin/sickrage", "SickRage")
|
@Html.GetSidebarUrl(Context, "/admin/sickrage", "SickRage")
|
||||||
@Html.GetSidebarUrl(Context, "/admin/headphones", "Headphones (Beta)")
|
@Html.GetSidebarUrl(Context, "/admin/headphones", "Headphones (Beta)")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue