mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-12 08:16:05 -07:00
!wip Made a start on adding CouchPotato, most of the UI is there but nothing is done with it yet #865
Also improved the error messages on the settings
This commit is contained in:
parent
532530a954
commit
e735df5d0a
43 changed files with 688 additions and 114 deletions
84
src/Ombi.Api.CouchPotato/CouchPotatoApi.cs
Normal file
84
src/Ombi.Api.CouchPotato/CouchPotatoApi.cs
Normal file
|
@ -0,0 +1,84 @@
|
|||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Ombi.Api.CouchPotato.Models;
|
||||
using Ombi.Helpers;
|
||||
|
||||
namespace Ombi.Api.CouchPotato
|
||||
{
|
||||
public class CouchPotatoApi : ICouchPotatoApi
|
||||
{
|
||||
public CouchPotatoApi(IApi api, ILogger<CouchPotatoApi> log)
|
||||
{
|
||||
_api = api;
|
||||
_log = log;
|
||||
}
|
||||
|
||||
private readonly IApi _api;
|
||||
private readonly ILogger<CouchPotatoApi> _log;
|
||||
|
||||
public async Task<bool> AddMovie(string imdbid, string apiKey, string title, string baseUrl, string profileId = default(string))
|
||||
{
|
||||
var request = new Request($"/api/{apiKey}/movie.add", baseUrl, HttpMethod.Get);
|
||||
|
||||
request.AddQueryString("title", title);
|
||||
request.AddQueryString("identifier", imdbid);
|
||||
if (!string.IsNullOrEmpty(profileId))
|
||||
{
|
||||
request.AddQueryString("profile_id", profileId);
|
||||
}
|
||||
|
||||
var obj = await _api.Request<JObject>(request);
|
||||
|
||||
if (obj.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = (bool)obj["success"];
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.LogError(LoggingEvents.CouchPotatoApi, e, "Error calling AddMovie");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<CouchPotatoStatus> Status(string url, string apiKey)
|
||||
{
|
||||
var request = new Request($"api/{apiKey}/app.available/", url, HttpMethod.Get);
|
||||
return await _api.Request<CouchPotatoStatus>(request);
|
||||
}
|
||||
|
||||
public async Task<CouchPotatoProfiles> GetProfiles(string url, string apiKey)
|
||||
{
|
||||
var request = new Request($"api/{apiKey}/profile.list/", url, HttpMethod.Get);
|
||||
return await _api.Request<CouchPotatoProfiles>(request);
|
||||
}
|
||||
|
||||
public async Task<CouchPotatoMovies> GetMovies(string baseUrl, string apiKey, string[] status)
|
||||
{
|
||||
var request = new Request($"/api/{apiKey}/movie.list", baseUrl, HttpMethod.Get);
|
||||
|
||||
request.AddQueryString("status",string.Join(",", status));
|
||||
request.OnBeforeDeserialization = json =>
|
||||
{
|
||||
json.Replace("[]", "{}");
|
||||
};
|
||||
return await _api.Request<CouchPotatoMovies>(request);
|
||||
}
|
||||
|
||||
public async Task<CouchPotatoApiKey> GetApiKey(string baseUrl, string username, string password)
|
||||
{
|
||||
var request = new Request("getkey/",baseUrl, HttpMethod.Get);
|
||||
request.AddQueryString("u",username.CalcuateMd5Hash());
|
||||
request.AddQueryString("p",password.CalcuateMd5Hash());
|
||||
|
||||
return await _api.Request<CouchPotatoApiKey>(request);
|
||||
}
|
||||
}
|
||||
}
|
14
src/Ombi.Api.CouchPotato/ICouchPotatoApi.cs
Normal file
14
src/Ombi.Api.CouchPotato/ICouchPotatoApi.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System.Threading.Tasks;
|
||||
using Ombi.Api.CouchPotato.Models;
|
||||
|
||||
namespace Ombi.Api.CouchPotato
|
||||
{
|
||||
public interface ICouchPotatoApi
|
||||
{
|
||||
Task<bool> AddMovie(string imdbid, string apiKey, string title, string baseUrl, string profileId = null);
|
||||
Task<CouchPotatoApiKey> GetApiKey(string baseUrl, string username, string password);
|
||||
Task<CouchPotatoMovies> GetMovies(string baseUrl, string apiKey, string[] status);
|
||||
Task<CouchPotatoProfiles> GetProfiles(string url, string apiKey);
|
||||
Task<CouchPotatoStatus> Status(string url, string apiKey);
|
||||
}
|
||||
}
|
12
src/Ombi.Api.CouchPotato/Models/CouchPotatoApiKey.cs
Normal file
12
src/Ombi.Api.CouchPotato/Models/CouchPotatoApiKey.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace Ombi.Api.CouchPotato.Models
|
||||
{
|
||||
public class CouchPotatoApiKey
|
||||
{
|
||||
[JsonProperty("success")]
|
||||
public bool success { get; set; }
|
||||
[JsonProperty("api_key")]
|
||||
public string ApiKey { get; set; }
|
||||
}
|
||||
}
|
99
src/Ombi.Api.CouchPotato/Models/CouchPotatoMovies.cs
Normal file
99
src/Ombi.Api.CouchPotato/Models/CouchPotatoMovies.cs
Normal file
|
@ -0,0 +1,99 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Api.CouchPotato.Models
|
||||
{
|
||||
public class CouchPotatoMovies
|
||||
{
|
||||
public List<Movie> movies { get; set; }
|
||||
public int total { get; set; }
|
||||
public bool success { get; set; }
|
||||
public bool empty { get; set; }
|
||||
}
|
||||
|
||||
public class Movie
|
||||
{
|
||||
public string _id { get; set; }
|
||||
public string _rev { get; set; }
|
||||
public string _t { get; set; }
|
||||
public object category_id { get; set; }
|
||||
public Files files { get; set; }
|
||||
public Identifiers identifiers { get; set; }
|
||||
public Info info { get; set; }
|
||||
public int last_edit { get; set; }
|
||||
public string profile_id { get; set; }
|
||||
public List<object> releases { get; set; }
|
||||
public string status { get; set; }
|
||||
public List<object> tags { get; set; }
|
||||
public string title { get; set; }
|
||||
public string type { get; set; }
|
||||
}
|
||||
public class CouchPotatoAdd
|
||||
{
|
||||
public Movie movie { get; set; }
|
||||
public bool success { get; set; }
|
||||
}
|
||||
|
||||
public class Rating
|
||||
{
|
||||
public List<string> imdb { get; set; }
|
||||
}
|
||||
|
||||
public class Images
|
||||
{
|
||||
public List<string> actors { get; set; }
|
||||
public List<string> backdrop { get; set; }
|
||||
public List<string> backdrop_original { get; set; }
|
||||
public List<object> banner { get; set; }
|
||||
public List<object> clear_art { get; set; }
|
||||
public List<object> disc_art { get; set; }
|
||||
public List<object> extra_fanart { get; set; }
|
||||
public List<object> extra_thumbs { get; set; }
|
||||
public List<object> landscape { get; set; }
|
||||
public List<object> logo { get; set; }
|
||||
public List<string> poster { get; set; }
|
||||
public List<string> poster_original { get; set; }
|
||||
}
|
||||
|
||||
public class Info
|
||||
{
|
||||
public List<string> actor_roles { get; set; }
|
||||
public List<string> actors { get; set; }
|
||||
public List<string> directors { get; set; }
|
||||
public List<string> genres { get; set; }
|
||||
public Images images { get; set; }
|
||||
public string imdb { get; set; }
|
||||
public string mpaa { get; set; }
|
||||
public string original_title { get; set; }
|
||||
public string plot { get; set; }
|
||||
public Rating rating { get; set; }
|
||||
public Release_Date release_date { get; set; }
|
||||
public string released { get; set; }
|
||||
public int runtime { get; set; }
|
||||
public string tagline { get; set; }
|
||||
public List<string> titles { get; set; }
|
||||
public int tmdb_id { get; set; }
|
||||
public string type { get; set; }
|
||||
public bool via_imdb { get; set; }
|
||||
public bool via_tmdb { get; set; }
|
||||
public List<string> writers { get; set; }
|
||||
public int year { get; set; }
|
||||
}
|
||||
|
||||
public class Release_Date
|
||||
{
|
||||
public bool bluray { get; set; }
|
||||
public int dvd { get; set; }
|
||||
public int expires { get; set; }
|
||||
public int theater { get; set; }
|
||||
}
|
||||
|
||||
public class Files
|
||||
{
|
||||
public List<string> image_poster { get; set; }
|
||||
}
|
||||
|
||||
public class Identifiers
|
||||
{
|
||||
public string imdb { get; set; }
|
||||
}
|
||||
}
|
29
src/Ombi.Api.CouchPotato/Models/CouchPotatoProfiles.cs
Normal file
29
src/Ombi.Api.CouchPotato/Models/CouchPotatoProfiles.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Ombi.Api.CouchPotato.Models
|
||||
{
|
||||
public class ProfileList
|
||||
{
|
||||
public bool core { get; set; }
|
||||
public bool hide { get; set; }
|
||||
public string _rev { get; set; }
|
||||
public List<bool> finish { get; set; }
|
||||
public List<string> qualities { get; set; }
|
||||
public string _id { get; set; }
|
||||
public string _t { get; set; }
|
||||
public string label { get; set; }
|
||||
public int minimum_score { get; set; }
|
||||
public List<int> stop_after { get; set; }
|
||||
public List<object> wait_for { get; set; }
|
||||
public int order { get; set; }
|
||||
[JsonProperty(PropertyName = "3d")]
|
||||
public List<object> threeD { get; set; }
|
||||
}
|
||||
|
||||
public class CouchPotatoProfiles
|
||||
{
|
||||
public List<ProfileList> list { get; set; }
|
||||
public bool success { get; set; }
|
||||
}
|
||||
}
|
7
src/Ombi.Api.CouchPotato/Models/CouchPotatoStatus.cs
Normal file
7
src/Ombi.Api.CouchPotato/Models/CouchPotatoStatus.cs
Normal file
|
@ -0,0 +1,7 @@
|
|||
namespace Ombi.Api.CouchPotato.Models
|
||||
{
|
||||
public class CouchPotatoStatus
|
||||
{
|
||||
public bool success { get; set; }
|
||||
}
|
||||
}
|
11
src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj
Normal file
11
src/Ombi.Api.CouchPotato/Ombi.Api.CouchPotato.csproj
Normal file
|
@ -0,0 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -52,6 +52,7 @@ namespace Ombi.Api
|
|||
var receivedString = await data.ReadAsStringAsync();
|
||||
if (request.ContentType == ContentType.Json)
|
||||
{
|
||||
request.OnBeforeDeserialization?.Invoke(receivedString);
|
||||
return JsonConvert.DeserializeObject<T>(receivedString, Settings);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace Ombi.Api
|
|||
public string BaseUrl { get; }
|
||||
public HttpMethod HttpMethod { get; }
|
||||
|
||||
public Action<string> OnBeforeDeserialization { get; set; }
|
||||
|
||||
private string FullUrl
|
||||
{
|
||||
get
|
||||
|
|
|
@ -8,6 +8,7 @@ using Ombi.Api.Sonarr.Models;
|
|||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Settings.Settings.Models.External;
|
||||
using Ombi.Store.Entities.Requests;
|
||||
|
||||
namespace Ombi.Core.Senders
|
||||
|
|
|
@ -31,6 +31,7 @@ using Ombi.Store.Repository;
|
|||
using Ombi.Notifications.Agents;
|
||||
using Ombi.Schedule.Jobs.Radarr;
|
||||
using Ombi.Api;
|
||||
using Ombi.Api.CouchPotato;
|
||||
using Ombi.Api.FanartTv;
|
||||
using Ombi.Api.Mattermost;
|
||||
using Ombi.Api.Pushbullet;
|
||||
|
@ -95,6 +96,7 @@ namespace Ombi.DependencyInjection
|
|||
services.AddTransient<IFanartTvApi, FanartTvApi>();
|
||||
services.AddTransient<IPushoverApi, PushoverApi>();
|
||||
services.AddTransient<IMattermostApi, MattermostApi>();
|
||||
services.AddTransient<ICouchPotatoApi, CouchPotatoApi>();
|
||||
}
|
||||
|
||||
public static void RegisterStore(this IServiceCollection services)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api.CouchPotato\Ombi.Api.CouchPotato.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Discord\Ombi.Api.Discord.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.FanartTv\Ombi.Api.FanartTv.csproj" />
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Ombi.Helpers
|
|||
|
||||
public static EventId Api => new EventId(1000);
|
||||
public static EventId RadarrApi => new EventId(1001);
|
||||
public static EventId CouchPotatoApi => new EventId(1002);
|
||||
|
||||
public static EventId Cacher => new EventId(2000);
|
||||
public static EventId RadarrCacher => new EventId(2001);
|
||||
|
|
|
@ -8,6 +8,7 @@ using Ombi.Api.Sonarr;
|
|||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Settings.Settings.Models.External;
|
||||
using Ombi.Store.Context;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
|
|
13
src/Ombi.Settings/Settings/Models/External/CouchPotatoSettings.cs
vendored
Normal file
13
src/Ombi.Settings/Settings/Models/External/CouchPotatoSettings.cs
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
using Ombi.Core.Settings.Models.External;
|
||||
|
||||
namespace Ombi.Settings.Settings.Models.External
|
||||
{
|
||||
public class CouchPotatoSettings : ExternalSettings
|
||||
{
|
||||
public bool Enabled { get; set; }
|
||||
public string ApiKey { get; set; }
|
||||
public string DefaultProfileId { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using Ombi.Settings.Settings.Models.External;
|
||||
|
||||
namespace Ombi.Core.Settings.Models.External
|
||||
{
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json;
|
||||
using Ombi.Helpers;
|
||||
|
||||
namespace Ombi.Core.Settings.Models.External
|
||||
namespace Ombi.Settings.Settings.Models.External
|
||||
{
|
||||
public abstract class ExternalSettings : Ombi.Settings.Settings.Models.Settings
|
||||
public abstract class ExternalSettings : Models.Settings
|
||||
{
|
||||
public bool Ssl { get; set; }
|
||||
public string SubDir { get; set; }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using Ombi.Settings.Settings.Models.External;
|
||||
|
||||
namespace Ombi.Core.Settings.Models.External
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace Ombi.Core.Settings.Models.External
|
||||
namespace Ombi.Settings.Settings.Models.External
|
||||
{
|
||||
public class SonarrSettings : ExternalSettings
|
||||
{
|
||||
|
|
|
@ -80,6 +80,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Pushover", "Ombi.A
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Schedule.Tests", "Ombi.Schedule.Tests\Ombi.Schedule.Tests.csproj", "{BDD8B924-016E-4CDA-9FFA-50B0A34BCD3C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.CouchPotato", "Ombi.Api.CouchPotato\Ombi.Api.CouchPotato.csproj", "{87D7897D-7C73-4856-A0AA-FF5948F4EA86}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -202,6 +204,10 @@ Global
|
|||
{BDD8B924-016E-4CDA-9FFA-50B0A34BCD3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BDD8B924-016E-4CDA-9FFA-50B0A34BCD3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BDD8B924-016E-4CDA-9FFA-50B0A34BCD3C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{87D7897D-7C73-4856-A0AA-FF5948F4EA86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{87D7897D-7C73-4856-A0AA-FF5948F4EA86}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{87D7897D-7C73-4856-A0AA-FF5948F4EA86}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{87D7897D-7C73-4856-A0AA-FF5948F4EA86}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -230,6 +236,7 @@ Global
|
|||
{737B2620-FE5A-4135-A017-79C269A7D36C} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||
{CA55DD4F-4EFF-4906-A848-35FCC7BD5654} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||
{BDD8B924-016E-4CDA-9FFA-50B0A34BCD3C} = {6F42AB98-9196-44C4-B888-D5E409F415A1}
|
||||
{87D7897D-7C73-4856-A0AA-FF5948F4EA86} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869}
|
||||
|
|
25
src/Ombi/ClientApp/app/interfaces/ICouchPotato.ts
Normal file
25
src/Ombi/ClientApp/app/interfaces/ICouchPotato.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
export interface ICouchPotatoProfiles {
|
||||
success: boolean;
|
||||
list: IProfileList[];
|
||||
}
|
||||
|
||||
export interface IProfileList {
|
||||
core: boolean;
|
||||
hide: boolean;
|
||||
_rev: string;
|
||||
finish: boolean[];
|
||||
qualities: string[];
|
||||
_id: string;
|
||||
_t: string;
|
||||
label: string;
|
||||
minimum_score: number;
|
||||
stop_after: number[];
|
||||
wait_for: object[];
|
||||
order: number;
|
||||
threeD: object[];
|
||||
}
|
||||
|
||||
export interface ICouchPotatoApiKey {
|
||||
success: boolean;
|
||||
apiKey: string;
|
||||
}
|
|
@ -119,3 +119,11 @@ export interface IAbout {
|
|||
processArchitecture: string;
|
||||
applicationBasePath: string;
|
||||
}
|
||||
|
||||
export interface ICouchPotatoSettings extends IExternalSettings {
|
||||
enabled: boolean;
|
||||
apiKey: string;
|
||||
defaultProfileId: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export * from "./ICommon";
|
||||
export * from "./ICouchPotato";
|
||||
export * from "./IImages";
|
||||
export * from "./IMediaServerStatus";
|
||||
export * from "./INotificationSettings";
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import { PlatformLocation } from "@angular/common";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { AuthHttp } from "angular2-jwt";
|
||||
import { Observable } from "rxjs/Rx";
|
||||
|
||||
import { ServiceAuthHelpers } from "../service.helpers";
|
||||
|
||||
import { ICouchPotatoApiKey, ICouchPotatoProfiles, ICouchPotatoSettings } from "../../interfaces";
|
||||
|
||||
@Injectable()
|
||||
export class CouchPotatoService extends ServiceAuthHelpers {
|
||||
constructor(http: AuthHttp, public platformLocation: PlatformLocation) {
|
||||
super(http, "/api/v1/CouchPotato/", platformLocation);
|
||||
}
|
||||
|
||||
public getProfiles(settings: ICouchPotatoSettings): Observable<ICouchPotatoProfiles> {
|
||||
return this.http.post(`${this.url}profile`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
|
||||
public getApiKey(settings: ICouchPotatoSettings): Observable<ICouchPotatoApiKey> {
|
||||
return this.http.post(`${this.url}apikey`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
export * from "./emby.service";
|
||||
export * from "./couchpotato.service";
|
||||
export * from "./emby.service";
|
||||
export * from "./plex.service";
|
||||
export * from "./radarr.service";
|
||||
export * from "./sonarr.service";
|
||||
|
|
|
@ -7,6 +7,7 @@ import { Observable } from "rxjs/Rx";
|
|||
import {
|
||||
IAbout,
|
||||
IAuthenticationSettings,
|
||||
ICouchPotatoSettings,
|
||||
ICustomizationSettings,
|
||||
IDiscordNotifcationSettings,
|
||||
IEmailNotificationSettings,
|
||||
|
@ -195,4 +196,14 @@ export class SettingsService extends ServiceAuthHelpers {
|
|||
.post(`${this.url}/UserManagement`, JSON.stringify(settings), { headers: this.headers })
|
||||
.map(this.extractData).catch(this.handleError);
|
||||
}
|
||||
|
||||
public getCouchPotatoSettings(): Observable<ICouchPotatoSettings> {
|
||||
return this.httpAuth.get(`${this.url}/UserManagement`).map(this.extractData).catch(this.handleError);
|
||||
}
|
||||
|
||||
public saveCouchPotatoSettings(settings: ICouchPotatoSettings): Observable<boolean> {
|
||||
return this.httpAuth
|
||||
.post(`${this.url}/UserManagement`, JSON.stringify(settings), { headers: this.headers })
|
||||
.map(this.extractData).catch(this.handleError);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<settings-menu>
|
||||
</settings-menu>
|
||||
<div *ngIf="form">
|
||||
<fieldset>
|
||||
<legend>CouchPotato Settings</legend>
|
||||
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)" style="padding-top:5%;">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="enable" formControlName="enabled" ng-checked="form.enabled">
|
||||
<label for="enable">Enable</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="Ip" class="control-label">Hostname or IP</label>
|
||||
<div class="">
|
||||
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('ip').hasError('required')}"
|
||||
id="Ip" name="Ip" placeholder="localhost" formControlName="ip">
|
||||
<small *ngIf="form.get('ip').hasError('required')" class="error-text">The IP/Hostname is required</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="portNumber" class="control-label">Port</label>
|
||||
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('port').hasError('required')}" formControlName="port" id="portNumber" name="Port" placeholder="Port Number">
|
||||
|
||||
<small *ngIf="form.get('port').hasError('required')" class="error-text">The Port is required</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ApiKey" class="control-label">API Key</label>
|
||||
|
||||
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('apiKey').hasError('required')}" id="ApiKey" name="ApiKey" formControlName="apiKey">
|
||||
|
||||
<small *ngIf="form.get('apiKey').hasError('required')" class="error-text">The API Key is required</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
|
||||
<input type="checkbox" id="Ssl" name="Ssl" formControlName="ssl"><label for="Ssl">SSL</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="SubDir" class="control-label">Base Url</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom" formControlName="subDir" id="SubDir" name="SubDir">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="username" class="control-label">Username</label>
|
||||
<input type="text" class="form-control form-control-custom " formControlName="username" name="username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="control-label">Password</label>
|
||||
<input type="text" class="form-control form-control-custom " formControlName="password" name="password">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary-outline" (click)="requestToken(form)">Request Api Key <i class="fa fa-key"></i></button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button type="submit" (click)="getProfiles(form)" class="btn btn-primary-outline">Get Quality Profiles <span *ngIf="profilesRunning" class="fa fa-spinner fa-spin"> </span></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="select" class="control-label">Quality Profiles</label>
|
||||
<div id="profiles">
|
||||
<select formControlName="defaultProfileId" class="form-control form-control-custom" id="select">
|
||||
<option *ngFor="let profile of profiles?.list" value="{{profile._id}}">{{profile.label}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button [disabled]="form.invalid" (click)="test(form)" class="btn btn-primary-outline">Test Connectivity <span id="spinner"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button type="submit" [disabled]="form.invalid" class="btn btn-primary-outline ">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</fieldset>
|
||||
</div>
|
|
@ -0,0 +1,90 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms";
|
||||
|
||||
import { CouchPotatoService, NotificationService, SettingsService, TesterService } from "../../services";
|
||||
|
||||
import { ICouchPotatoProfiles } from "../../interfaces";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./couchpotato.component.html",
|
||||
})
|
||||
export class CouchPotatoComponent implements OnInit {
|
||||
|
||||
public form: FormGroup;
|
||||
public profiles: ICouchPotatoProfiles;
|
||||
|
||||
public profilesRunning: boolean;
|
||||
|
||||
constructor(private readonly settingsService: SettingsService,
|
||||
private readonly fb: FormBuilder,
|
||||
private readonly notificationService: NotificationService,
|
||||
private readonly couchPotatoService: CouchPotatoService,
|
||||
private readonly testerService: TesterService) { }
|
||||
|
||||
public ngOnInit() {
|
||||
this.settingsService.getCouchPotatoSettings().subscribe(x => {
|
||||
this.form = this.fb.group({
|
||||
enabled: [x.enabled],
|
||||
username: [x.username],
|
||||
password: [x.password],
|
||||
apiKey: [x.apiKey, Validators.required],
|
||||
ip: [x.ip, Validators.required],
|
||||
port: [x.port, Validators.required],
|
||||
ssl: [x.ssl],
|
||||
subDir: [x.subDir],
|
||||
defaultProfileId: [x.defaultProfileId],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public getProfiles(form: FormGroup) {
|
||||
this.profilesRunning = true;
|
||||
this.couchPotatoService.getProfiles(form.value).subscribe(x => {
|
||||
this.profiles = x;
|
||||
this.profilesRunning = false;
|
||||
});
|
||||
}
|
||||
|
||||
public onSubmit(form: FormGroup) {
|
||||
if (form.invalid) {
|
||||
this.notificationService.error("Validation", "Please check your entered values");
|
||||
return;
|
||||
}
|
||||
|
||||
const settings = form.value;
|
||||
|
||||
this.settingsService.saveCouchPotatoSettings(settings).subscribe(x => {
|
||||
if (x) {
|
||||
this.notificationService.success("Settings Saved", "Successfully saved the CouchPotato settings");
|
||||
} else {
|
||||
this.notificationService.success("Settings Saved", "There was an error when saving the CouchPotato settings");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public test(form: FormGroup) {
|
||||
if (form.invalid) {
|
||||
this.notificationService.error("Validation", "Please check your entered values");
|
||||
return;
|
||||
}
|
||||
const settings = form.value;
|
||||
this.testerService.radarrTest(settings).subscribe(x => {
|
||||
if (x === true) {
|
||||
this.notificationService.success("Connected", "Successfully connected to Radarr!");
|
||||
} else {
|
||||
this.notificationService.error("Connected", "We could not connect to Radarr!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public requestToken(form: FormGroup) {
|
||||
this.couchPotatoService.getApiKey(form.value).subscribe(x => {
|
||||
if (x.success === true) {
|
||||
(<FormControl>this.form.controls.apiKey).setValue(x.apiKey);
|
||||
this.notificationService.success("Api Key", "Successfully got the Api Key");
|
||||
} else {
|
||||
this.notificationService.error("Api Key", "Could not get the Api Key");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -13,15 +13,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||
<div *ngIf="form.get('webhookUrl').hasError('required')">The Webhook Url is required</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="webhookUrl" class="control-label">Webhook Url</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="webhookUrl" name="webhookUrl" formControlName="webhookUrl">
|
||||
</div>
|
||||
<input type="text" class="form-control form-control-custom " id="webhookUrl" name="webhookUrl" formControlName="webhookUrl" [ngClass]="{'form-error': form.get('webhookUrl').hasError('required')}">
|
||||
<small *ngIf="form.get('webhookUrl').hasError('required')" class="error-text">The Webhook Url is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
|
|
@ -18,35 +18,27 @@
|
|||
<input type="checkbox" id="Authentication" formControlName="authentication"><label for="Authentication">Enable SMTP Authentication</label>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="emailForm.invalid && emailForm.dirty" class="alert alert-danger">
|
||||
<div *ngIf="emailForm.get('host').hasError('required')">Host is required</div>
|
||||
<div *ngIf="emailForm.get('port').hasError('required')">The Port is required</div>
|
||||
<div *ngIf="emailForm.get('senderAddress').hasError('required')">The Email Sender Address is required</div>
|
||||
<div *ngIf="emailForm.get('senderAddress').hasError('incorrectMailFormat')">The Email Sender Address needs to be a valid email address</div>
|
||||
<div *ngIf="emailForm.get('adminEmail').hasError('required')">The Email Sender is required</div>
|
||||
<div *ngIf="emailForm.get('adminEmail').hasError('email')">The Admin Email needs to be a valid email address</div>
|
||||
<div *ngIf="emailForm.get('username').hasError('required')">The Username is required</div>
|
||||
<div *ngIf="emailForm.get('password').hasError('required')">The Password is required</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="host" class="control-label">SMTP Host</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="host" name="host" placeholder="localhost" formControlName="host">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " id="host" name="host" placeholder="localhost" formControlName="host" [ngClass]="{'form-error': emailForm.get('host').hasError('required')}">
|
||||
<small *ngIf="emailForm.get('host').hasError('required')" class="error-text">The Host is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="portNumber" class="control-label">SMTP Port</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="portNumber" name="Port" placeholder="Port Number" formControlName="port">
|
||||
<input type="text" class="form-control form-control-custom " [ngClass]="{'form-error': emailForm.get('port').hasError('required')}" id="portNumber" name="Port" placeholder="Port Number" formControlName="port">
|
||||
<small *ngIf="emailForm.get('port').hasError('required')" class="error-text">The Port is required</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label style="padding-left: 0" for="senderAddress" class="control-label col-md-12">Email Sender</label>
|
||||
<div style="padding-left: 0" class="col-md-6">
|
||||
<input type="text" class="form-control form-control-custom " id="senderAddress" name="senderAddress" formControlName="senderAddress" tooltipPosition="top" placeholder="Sender Address" pTooltip="The email address that the emails will be sent from">
|
||||
<input type="text" class="form-control form-control-custom " id="senderAddress" [ngClass]="{'form-error': emailForm.get('senderAddress').hasError('required'), 'form-error': emailForm.get('senderAddress').hasError('incorrectMailFormat')}" name="senderAddress" formControlName="senderAddress" tooltipPosition="top" placeholder="Sender Address" pTooltip="The email address that the emails will be sent from">
|
||||
<small *ngIf="emailForm.get('senderAddress').hasError('required')" class="error-text">The Email Sender Address is required</small>
|
||||
<small *ngIf="emailForm.get('senderAddress').hasError('email') && !emailForm.get('senderAddress').hasError('required')" class="error-text">The Email Sender Address needs to be a valid email address</small>
|
||||
</div>
|
||||
<div style="padding-left: 0" class="col-md-6">
|
||||
<input type="text" class="form-control form-control-custom " id="senderName" name="senderName" formControlName="senderName" tooltipPosition="top" placeholder="Sender Name" pTooltip="The 'Friendly' name that will appear in the 'FROM:' part of the email">
|
||||
|
@ -58,24 +50,26 @@
|
|||
|
||||
<div class="form-group">
|
||||
<label for="adminEmail" class="control-label">Admin Email</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="adminEmail" name="adminEmail" formControlName="adminEmail" tooltipPosition="top" pTooltip="The administrator email will be used to send emails for admin only notifications (e.g. New Requests that require approvals)">
|
||||
</div>
|
||||
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': emailForm.get('adminEmail').hasError('required'), 'form-error': emailForm.get('adminEmail').hasError('email')}" id="adminEmail" name="adminEmail" formControlName="adminEmail" tooltipPosition="top" pTooltip="The administrator email will be used to send emails for admin only notifications (e.g. New Requests that require approvals)">
|
||||
<small *ngIf="emailForm.get('adminEmail').hasError('required')" class="error-text">The Admin Email Address is required</small>
|
||||
<small *ngIf="emailForm.get('adminEmail').hasError('email') && !emailForm.get('adminEmail').hasError('required')" class="error-text">The Admin Email needs to be a valid email address</small>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group" *ngIf="emailForm.controls['username'].validator">
|
||||
<label for="username" class="control-label">Username</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="username" name="username" formControlName="username" pTooltip="The username if authentication is enabled" tooltipPosition="top">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': emailForm.get('username').hasError('required')}" id="username" name="username" formControlName="username" pTooltip="The username if authentication is enabled" tooltipPosition="top">
|
||||
<small *ngIf="emailForm.get('username').hasError('required')" class="error-text">The Username is required</small>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group" *ngIf="emailForm.get('password').validator">
|
||||
<label for="password" class="control-label">Password</label>
|
||||
<div>
|
||||
<input type="password" class="form-control form-control-custom " id="password" name="password" formControlName="password" pTooltip="The password if authentication is enabled" tooltipPosition="top">
|
||||
</div>
|
||||
|
||||
<input type="password" class="form-control form-control-custom" [ngClass]="{'form-error': emailForm.get('password').hasError('required')}" id="password" name="password" formControlName="password" pTooltip="The password if authentication is enabled" tooltipPosition="top">
|
||||
<small *ngIf="emailForm.get('password').hasError('required')" class="error-text">The Password is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
|
|
@ -13,16 +13,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||
<div *ngIf="form.get('webhookUrl').hasError('required')">The Incoming Webhook Url is required</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<small class="control-label"> Mattermost > Integrations > Incoming Webhook > Add Incoming Webhook. You will then have a Webhook</small>
|
||||
<label for="webhookUrl" class="control-label">Incoming Webhook Url</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="webhookUrl" name="webhookUrl" formControlName="webhookUrl">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " id="webhookUrl" name="webhookUrl" formControlName="webhookUrl" [ngClass]="{'form-error': form.get('webhookUrl').hasError('required')}">
|
||||
<small *ngIf="form.get('webhookUrl').hasError('required')" class="error-text">The Webhook Url is required</small>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -13,15 +13,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||
<div *ngIf="form.get('accessToken').hasError('required')">The Access Token is required</div>
|
||||
</div>
|
||||
<small>You can find this here: <a href="https://www.pushbullet.com/#settings/account">https://www.pushbullet.com/#settings/account </a></small>
|
||||
<div class="form-group">
|
||||
<label for="accessToken" class="control-label">Access Token</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="accessToken" name="accessToken" formControlName="accessToken">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " id="accessToken" name="accessToken" formControlName="accessToken" [ngClass]="{'form-error': form.get('accessToken').hasError('required')}">
|
||||
<small *ngIf="form.get('accessToken').hasError('required')" class="error-text">The Access Token is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
|
|
@ -13,14 +13,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||
<div *ngIf="form.get('accessToken').hasError('required')">The Access Token is required</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="accessToken" class="control-label">Access Token</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="accessToken" name="accessToken" formControlName="accessToken" pTooltip="Enter your API Key from Pushover.">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " id="accessToken" name="accessToken" [ngClass]="{'form-error': form.get('accessToken').hasError('required')}" formControlName="accessToken" pTooltip="Enter your API Key from Pushover.">
|
||||
<small *ngIf="form.get('accessToken').hasError('required')" class="error-text">The Access Token is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||
<div *ngIf="form.get('webhookUrl').hasError('required')">The Webhook Url is required</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
|
@ -24,7 +21,8 @@
|
|||
<div>
|
||||
|
||||
<small class="control-label"> Click <a target="_blank" href="https://my.slack.com/services/new/incoming-webhook/">Here</a> and follow the guide. You will then have a Webhook Url</small>
|
||||
<input type="text" class="form-control form-control-custom " id="webhookUrl" name="webhookUrl" formControlName="webhookUrl">
|
||||
<input type="text" class="form-control form-control-custom " id="webhookUrl" name="webhookUrl" formControlName="webhookUrl" [ngClass]="{'form-error': form.get('webhookUrl').hasError('required')}">
|
||||
<small *ngIf="form.get('webhookUrl').hasError('required')" class="error-text">The Webhook Url is required</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -8,19 +8,6 @@
|
|||
<p-inputSwitch id="customInputSwitch" [(ngModel)]="advanced"></p-inputSwitch>
|
||||
</div>
|
||||
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)" style="padding-top:5%;">
|
||||
<div *ngIf="form.invalid" class="alert alert-danger">
|
||||
<div *ngIf="form.dirty">
|
||||
<div *ngIf="form.get('ip').hasError('required')">The IP/Hostname is required</div>
|
||||
<div *ngIf="form.get('port').hasError('required')">The Port is required</div>
|
||||
<div *ngIf="form.get('apiKey').hasError('required')">The Api Key is required</div>
|
||||
</div>
|
||||
<div>
|
||||
<div *ngIf="form.get('defaultQualityProfile').hasError('required')">A Default Quality Profile is required</div>
|
||||
<div *ngIf="form.get('defaultRootPath').hasError('required')">A Default Root Path is required</div>
|
||||
<div *ngIf="form.get('minimumAvailability').hasError('required')">A Default Minimum Availability is required</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
|
@ -33,25 +20,24 @@
|
|||
|
||||
<div class="form-group">
|
||||
<label for="Ip" class="control-label">Hostname or IP</label>
|
||||
<div class="">
|
||||
<input type="text" class="form-control form-control-custom " id="Ip" name="Ip" placeholder="localhost" formControlName="ip">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " id="Ip" name="Ip" placeholder="localhost" formControlName="ip" [ngClass]="{'form-error': form.get('ip').hasError('required')}">
|
||||
<small *ngIf="form.get('ip').hasError('required')" class="error-text">The IP/Hostname is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="portNumber" class="control-label">Port</label>
|
||||
|
||||
<div class="">
|
||||
<input type="text" class="form-control form-control-custom " formControlName="port" id="portNumber" name="Port" placeholder="Port Number">
|
||||
</div>
|
||||
<input type="text" class="form-control form-control-custom " formControlName="port" id="portNumber" name="Port" placeholder="Port Number" [ngClass]="{'form-error': form.get('port').hasError('required')}">
|
||||
<small *ngIf="form.get('port').hasError('required')" class="error-text">The Port is required</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ApiKey" class="control-label">API Key</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " id="ApiKey" name="ApiKey" formControlName="apiKey">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " [ngClass]="{'form-error': form.get('apiKey').hasError('required')}" id="ApiKey" name="ApiKey" formControlName="apiKey">
|
||||
<small *ngIf="form.get('apiKey').hasError('required')" class="error-text">The API Key is required</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
|
@ -76,10 +62,11 @@
|
|||
<div class="form-group">
|
||||
<label for="select" class="control-label">Quality Profiles</label>
|
||||
<div id="profiles">
|
||||
<select formControlName="defaultQualityProfile" class="form-control form-control-custom" id="select">
|
||||
<select formControlName="defaultQualityProfile" class="form-control form-control-custom" id="select" [ngClass]="{'form-error': form.get('defaultQualityProfile').hasError('required')}">
|
||||
<option *ngFor="let quality of qualities" value="{{quality.id}}">{{quality.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<small *ngIf="form.get('defaultQualityProfile').hasError('required')" class="error-text">A Default Quality Profile is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -92,19 +79,22 @@
|
|||
<div class="form-group">
|
||||
<label for="rootFolders" class="control-label">Default Root Folders</label>
|
||||
<div id="rootFolders">
|
||||
<select formControlName="defaultRootPath" class="form-control form-control-custom">
|
||||
<select formControlName="defaultRootPath" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('defaultRootPath').hasError('required')}">
|
||||
<option *ngFor="let folder of rootFolders" value="{{folder.path}}">{{folder.path}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<small *ngIf="form.get('defaultRootPath').hasError('required')" class="error-text">A Default Root Path is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="rootFolders" class="control-label">Default Minimum Availability</label>
|
||||
<div id="rootFolders">
|
||||
<select formControlName="minimumAvailability" class="form-control form-control-custom">
|
||||
<select formControlName="minimumAvailability" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('minimumAvailability').hasError('required')}">
|
||||
<option *ngFor="let min of minimumAvailabilityOptions" value="{{min.value}}">{{min.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<small *ngIf="form.get('minimumAvailability').hasError('required')" class="error-text">A Default Minimum Availability is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group" *ngIf="advanced" style="color:#ff761b">
|
||||
|
|
|
@ -8,10 +8,11 @@ import { ClipboardModule } from "ngx-clipboard/dist";
|
|||
import { AuthGuard } from "../auth/auth.guard";
|
||||
import { AuthModule } from "../auth/auth.module";
|
||||
import { AuthService } from "../auth/auth.service";
|
||||
import { JobService, RadarrService, SonarrService, TesterService, ValidationService } from "../services";
|
||||
import { CouchPotatoService, JobService, RadarrService, SonarrService, TesterService, ValidationService } from "../services";
|
||||
|
||||
import { PipeModule } from "../pipes/pipe.module";
|
||||
import { AboutComponent } from "./about/about.component";
|
||||
import { CouchPotatoComponent } from "./couchpotato/couchpotato.component";
|
||||
import { CustomizationComponent } from "./customization/customization.component";
|
||||
import { EmbyComponent } from "./emby/emby.component";
|
||||
import { LandingPageComponent } from "./landingpage/landingpage.component";
|
||||
|
@ -51,6 +52,7 @@ const routes: Routes = [
|
|||
{ path: "Settings/Mattermost", component: MattermostComponent, canActivate: [AuthGuard] },
|
||||
{ path: "Settings/UserManagement", component: UserManagementComponent, canActivate: [AuthGuard] },
|
||||
{ path: "Settings/Update", component: UpdateComponent, canActivate: [AuthGuard] },
|
||||
{ path: "Settings/CouchPotato", component: CouchPotatoComponent, canActivate: [AuthGuard] },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -91,6 +93,7 @@ const routes: Routes = [
|
|||
UpdateComponent,
|
||||
AboutComponent,
|
||||
WikiComponent,
|
||||
CouchPotatoComponent,
|
||||
],
|
||||
exports: [
|
||||
RouterModule,
|
||||
|
@ -103,6 +106,7 @@ const routes: Routes = [
|
|||
ValidationService,
|
||||
TesterService,
|
||||
JobService,
|
||||
CouchPotatoService,
|
||||
],
|
||||
|
||||
})
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<i class="fa fa-film" aria-hidden="true"></i> Movies <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<!--<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/CouchPotato']">CouchPotato</a></li>-->
|
||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/CouchPotato']">CouchPotato (NOT YET READY)</a></li>
|
||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Radarr']">Radarr</a></li>
|
||||
<!--<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Watcher']">Watcher</a></li>-->
|
||||
<li [routerLinkActive]="['active']"><a>More Coming Soon...</a></li>
|
||||
|
|
|
@ -8,17 +8,7 @@
|
|||
<p-inputSwitch id="customInputSwitch" [(ngModel)]="advanced"></p-inputSwitch>
|
||||
</div>
|
||||
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)" style="padding-top:5%;">
|
||||
<div *ngIf="form.invalid" class="alert alert-danger">
|
||||
<div *ngIf="form.dirty">
|
||||
<div *ngIf="form.get('ip').hasError('required')">The IP/Hostname is required</div>
|
||||
<div *ngIf="form.get('port').hasError('required')">The Port is required</div>
|
||||
<div *ngIf="form.get('apiKey').hasError('required')">The Api Key is required</div>
|
||||
</div>
|
||||
<div>
|
||||
<div *ngIf="form.get('qualityProfile').hasError('required')">A Default Quality Profile is required</div>
|
||||
<div *ngIf="form.get('rootPath').hasError('required')">A Default Root Path is required</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
|
@ -29,25 +19,24 @@
|
|||
|
||||
<div class="form-group">
|
||||
<label for="Ip" class="control-label">Sonarr Hostname or IP</label>
|
||||
<div class="">
|
||||
<input type="text" class="form-control form-control-custom " formControlName="ip" id="Ip" name="Ip" placeholder="localhost">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " formControlName="ip" id="Ip" name="Ip" placeholder="localhost" [ngClass]="{'form-error': form.get('ip').hasError('required')}">
|
||||
<small *ngIf="form.get('ip').hasError('required')" class="error-text">The IP/Hostname is required</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="portNumber" class="control-label">Port</label>
|
||||
|
||||
<div class="">
|
||||
<input type="text" class="form-control form-control-custom " formControlName="port" id="portNumber" name="Port" placeholder="Port Number">
|
||||
</div>
|
||||
<input type="text" class="form-control form-control-custom " [ngClass]="{'form-error': form.get('port').hasError('required')}" formControlName="port" id="portNumber" name="Port" placeholder="Port Number">
|
||||
<small *ngIf="form.get('port').hasError('required')" class="error-text">The Port is required</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ApiKey" class="control-label">Sonarr API Key</label>
|
||||
<div>
|
||||
<input type="text" class="form-control form-control-custom " formControlName="apiKey" id="ApiKey" name="ApiKey">
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control form-control-custom " [ngClass]="{'form-error': form.get('apiKey').hasError('required')}" formControlName="apiKey" id="ApiKey" name="ApiKey">
|
||||
<small *ngIf="form.get('apiKey').hasError('required')" class="error-text">The API Key is required</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
|
@ -72,10 +61,12 @@
|
|||
<div class="form-group">
|
||||
<label for="select" class="control-label">Quality Profiles</label>
|
||||
<div id="profiles">
|
||||
<select class="form-control form-control-custom" id="select" formControlName="qualityProfile">
|
||||
<select class="form-control form-control-custom" [ngClass]="{'form-error': form.get('qualityProfile').hasError('required')}" id="select" formControlName="qualityProfile">
|
||||
<option *ngFor="let quality of qualities" value="{{quality.id}}">{{quality.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<small *ngIf="form.get('qualityProfile').hasError('required')" class="error-text">A Default Quality Profile is required</small>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -88,10 +79,12 @@
|
|||
<div class="form-group">
|
||||
<label for="rootFolders" class="control-label">Default Root Folders</label>
|
||||
<div id="rootFolders">
|
||||
<select class="form-control form-control-custom" formControlName="rootPath">
|
||||
<select class="form-control form-control-custom" formControlName="rootPath" [ngClass]="{'form-error': form.get('rootPath').hasError('required')}">
|
||||
<option *ngFor="let folder of rootFolders" value="{{folder.id}}">{{folder.path}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<small *ngIf="form.get('rootPath').hasError('required')" class="error-text">A Default Root Path is required</small>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -816,3 +816,11 @@ a > h4 {
|
|||
a > h4:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
border: 1px solid #d9534f;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: #d9534f;
|
||||
}
|
||||
|
|
37
src/Ombi/Controllers/External/CouchPotatoController.cs
vendored
Normal file
37
src/Ombi/Controllers/External/CouchPotatoController.cs
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Ombi.Api.CouchPotato;
|
||||
using Ombi.Api.CouchPotato.Models;
|
||||
using Ombi.Attributes;
|
||||
using Ombi.Settings.Settings.Models.External;
|
||||
|
||||
namespace Ombi.Controllers.External
|
||||
{
|
||||
[Admin]
|
||||
[ApiV1]
|
||||
[Produces("application/json")]
|
||||
public class CouchPotatoController
|
||||
{
|
||||
public CouchPotatoController(ICouchPotatoApi api)
|
||||
{
|
||||
_api = api;
|
||||
}
|
||||
|
||||
private readonly ICouchPotatoApi _api;
|
||||
|
||||
[HttpPost("profile")]
|
||||
public async Task<CouchPotatoProfiles> GetQualityProfiles([FromBody] CouchPotatoSettings settings)
|
||||
{
|
||||
var profiles = await _api.GetProfiles(settings.FullUri, settings.ApiKey);
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
[HttpPost("apikey")]
|
||||
public async Task<CouchPotatoApiKey> GetApiKey([FromBody] CouchPotatoSettings settings)
|
||||
{
|
||||
var apiKey = await _api.GetApiKey(settings.FullUri, settings.Username, settings.Password);
|
||||
return apiKey;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,9 +13,6 @@ using Ombi.Models.External;
|
|||
|
||||
namespace Ombi.Controllers.External
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Admin]
|
||||
[ApiV1]
|
||||
[Produces("application/json")]
|
||||
|
|
|
@ -7,6 +7,7 @@ using Ombi.Api.Sonarr.Models;
|
|||
using Ombi.Attributes;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Settings.Settings.Models.External;
|
||||
|
||||
namespace Ombi.Controllers.External
|
||||
{
|
||||
|
|
|
@ -343,6 +343,26 @@ namespace Ombi.Controllers
|
|||
return await Get<UpdateSettings>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the CouchPotatoSettings Settings.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("CouchPotato")]
|
||||
public async Task<CouchPotatoSettings> CouchPotatoSettings()
|
||||
{
|
||||
return await Get<CouchPotatoSettings>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the CouchPotatoSettings settings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("CouchPotato")]
|
||||
public async Task<bool> CouchPotatoSettings([FromBody]CouchPotatoSettings settings)
|
||||
{
|
||||
return await Save(settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the email notification settings.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue