Added the ability to customize job scheudles

pull/1741/head
Jamie 7 years ago
parent e090800cd7
commit a89585b85a

@ -1,4 +1,5 @@
using Hangfire;
using Ombi.Core.Settings;
using Ombi.Schedule.Jobs;
using Ombi.Schedule.Jobs.Couchpotato;
using Ombi.Schedule.Jobs.Emby;
@ -6,6 +7,7 @@ using Ombi.Schedule.Jobs.Ombi;
using Ombi.Schedule.Jobs.Plex;
using Ombi.Schedule.Jobs.Radarr;
using Ombi.Schedule.Jobs.Sonarr;
using Ombi.Settings.Settings.Models;
namespace Ombi.Schedule
{
@ -13,7 +15,8 @@ namespace Ombi.Schedule
{
public JobSetup(IPlexContentSync plexContentSync, IRadarrSync radarrSync,
IOmbiAutomaticUpdater updater, IEmbyContentSync embySync, IPlexUserImporter userImporter,
IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache)
IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache,
ISettingsService<JobSettings> jobsettings)
{
PlexContentSync = plexContentSync;
RadarrSync = radarrSync;
@ -23,6 +26,7 @@ namespace Ombi.Schedule
EmbyUserImporter = embyUserImporter;
SonarrSync = cache;
CpCache = cpCache;
JobSettings = jobsettings;
}
private IPlexContentSync PlexContentSync { get; }
@ -33,19 +37,22 @@ namespace Ombi.Schedule
private IEmbyUserImporter EmbyUserImporter { get; }
private ISonarrSync SonarrSync { get; }
private ICouchPotatoSync CpCache { get; }
private ISettingsService<JobSettings> JobSettings { get; set; }
public void Setup()
{
RecurringJob.AddOrUpdate(() => EmbyContentSync.Start(), Cron.Hourly(5));
RecurringJob.AddOrUpdate(() => SonarrSync.Start(), Cron.Hourly(10));
RecurringJob.AddOrUpdate(() => RadarrSync.CacheContent(), Cron.Hourly(15));
RecurringJob.AddOrUpdate(() => PlexContentSync.CacheContent(), Cron.Hourly(20));
RecurringJob.AddOrUpdate(() => CpCache.Start(), Cron.Hourly(30));
var s = JobSettings.GetSettings();
RecurringJob.AddOrUpdate(() => Updater.Update(null), Cron.HourInterval(6));
RecurringJob.AddOrUpdate(() => EmbyContentSync.Start(), JobSettingsHelper.EmbyContent(s));
RecurringJob.AddOrUpdate(() => SonarrSync.Start(), JobSettingsHelper.Sonarr(s));
RecurringJob.AddOrUpdate(() => RadarrSync.CacheContent(), JobSettingsHelper.Radarr(s));
RecurringJob.AddOrUpdate(() => PlexContentSync.CacheContent(), JobSettingsHelper.PlexContent(s));
RecurringJob.AddOrUpdate(() => CpCache.Start(), JobSettingsHelper.CouchPotato(s));
RecurringJob.AddOrUpdate(() => EmbyUserImporter.Start(), Cron.Daily);
RecurringJob.AddOrUpdate(() => PlexUserImporter.Start(), Cron.Daily(5));
RecurringJob.AddOrUpdate(() => Updater.Update(null), JobSettingsHelper.Updater(s));
RecurringJob.AddOrUpdate(() => EmbyUserImporter.Start(), JobSettingsHelper.UserImporter(s));
RecurringJob.AddOrUpdate(() => PlexUserImporter.Start(), JobSettingsHelper.UserImporter(s));
}
}
}

@ -5,5 +5,9 @@
public string EmbyContentSync { get; set; }
public string SonarrSync { get; set; }
public string RadarrSync { get; set; }
public string PlexContentSync { get; set; }
public string CouchPotatoSync { get; set; }
public string AutomaticUpdater { get; set; }
public string UserImporter { get; set; }
}
}

@ -0,0 +1,46 @@
using Hangfire;
using Ombi.Helpers;
namespace Ombi.Settings.Settings.Models
{
public static class JobSettingsHelper
{
public static string Radarr(JobSettings s)
{
return Get(s.RadarrSync, Cron.Hourly(15));
}
public static string Sonarr(JobSettings s)
{
return Get(s.SonarrSync, Cron.Hourly(10));
}
public static string EmbyContent(JobSettings s)
{
return Get(s.EmbyContentSync, Cron.Hourly(5));
}
public static string PlexContent(JobSettings s)
{
return Get(s.PlexContentSync, Cron.Hourly(20));
}
public static string CouchPotato(JobSettings s)
{
return Get(s.CouchPotatoSync, Cron.Hourly(30));
}
public static string Updater(JobSettings s)
{
return Get(s.AutomaticUpdater, Cron.HourInterval(6));
}
public static string UserImporter(JobSettings s)
{
return Get(s.UserImporter, Cron.Daily());
}
private static string Get(string settings, string defaultCron)
{
return settings.HasValue() ? settings : defaultCron;
}
}
}

@ -0,0 +1,782 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.Internal;
using Ombi.Helpers;
using Ombi.Store.Context;
using Ombi.Store.Entities;
using System;
namespace Ombi.Store.Migrations
{
[DbContext(typeof(OmbiContext))]
[Migration("JobSettingsMigration")]
partial class JobSettingsMigration
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.0.0-rtm-26452");
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider");
b.Property<string>("ProviderKey");
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider");
b.Property<string>("Name");
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("Type");
b.Property<string>("Value");
b.HasKey("Id");
b.ToTable("ApplicationConfiguration");
});
modelBuilder.Entity("Ombi.Store.Entities.Audit", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AuditArea");
b.Property<int>("AuditType");
b.Property<DateTime>("DateTime");
b.Property<string>("Description");
b.Property<string>("User");
b.HasKey("Id");
b.ToTable("Audit");
});
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("TheMovieDbId");
b.HasKey("Id");
b.ToTable("CouchPotatoCache");
});
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedAt");
b.Property<string>("EmbyId")
.IsRequired();
b.Property<string>("ProviderId");
b.Property<string>("Title");
b.Property<int>("Type");
b.HasKey("Id");
b.ToTable("EmbyContent");
});
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedAt");
b.Property<string>("EmbyId");
b.Property<int>("EpisodeNumber");
b.Property<string>("ParentId");
b.Property<string>("ProviderId");
b.Property<int>("SeasonNumber");
b.Property<string>("Title");
b.HasKey("Id");
b.HasIndex("ParentId");
b.ToTable("EmbyEpisode");
});
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Content");
b.Property<string>("SettingsName");
b.HasKey("Id");
b.ToTable("GlobalSettings");
});
modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("Agent");
b.Property<bool>("Enabled");
b.Property<string>("Message");
b.Property<int>("NotificationType");
b.Property<string>("Subject");
b.HasKey("Id");
b.ToTable("NotificationTemplates");
});
modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("Alias");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<DateTime?>("LastLoggedIn");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("ProviderUserId");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.Property<int>("UserType");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("EpisodeNumber");
b.Property<int>("GrandparentKey");
b.Property<int>("Key");
b.Property<int>("ParentKey");
b.Property<int>("SeasonNumber");
b.Property<string>("Title");
b.HasKey("Id");
b.HasIndex("GrandparentKey");
b.ToTable("PlexEpisode");
});
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("ParentKey");
b.Property<int>("PlexContentId");
b.Property<int?>("PlexServerContentId");
b.Property<int>("SeasonKey");
b.Property<int>("SeasonNumber");
b.HasKey("Id");
b.HasIndex("PlexServerContentId");
b.ToTable("PlexSeasonsContent");
});
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedAt");
b.Property<string>("ImdbId");
b.Property<int>("Key");
b.Property<string>("Quality");
b.Property<string>("ReleaseYear");
b.Property<string>("TheMovieDbId");
b.Property<string>("Title");
b.Property<string>("TvDbId");
b.Property<int>("Type");
b.Property<string>("Url");
b.HasKey("Id");
b.ToTable("PlexServerContent");
});
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("TheMovieDbId");
b.HasKey("Id");
b.ToTable("RadarrCache");
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("Approved");
b.Property<bool>("Available");
b.Property<bool?>("Denied");
b.Property<string>("DeniedReason");
b.Property<int?>("IssueId");
b.Property<int>("ParentRequestId");
b.Property<int>("RequestType");
b.Property<DateTime>("RequestedDate");
b.Property<string>("RequestedUserId");
b.Property<string>("Title");
b.HasKey("Id");
b.HasIndex("ParentRequestId");
b.HasIndex("RequestedUserId");
b.ToTable("ChildRequests");
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieIssues", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Description");
b.Property<int?>("IssueId");
b.Property<int>("MovieId");
b.Property<string>("Subect");
b.HasKey("Id");
b.HasIndex("IssueId");
b.HasIndex("MovieId");
b.ToTable("MovieIssues");
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("Approved");
b.Property<bool>("Available");
b.Property<string>("Background");
b.Property<bool?>("Denied");
b.Property<string>("DeniedReason");
b.Property<string>("ImdbId");
b.Property<int?>("IssueId");
b.Property<string>("Overview");
b.Property<string>("PosterPath");
b.Property<int>("QualityOverride");
b.Property<DateTime>("ReleaseDate");
b.Property<int>("RequestType");
b.Property<DateTime>("RequestedDate");
b.Property<string>("RequestedUserId");
b.Property<int>("RootPathOverride");
b.Property<string>("Status");
b.Property<int>("TheMovieDbId");
b.Property<string>("Title");
b.HasKey("Id");
b.HasIndex("RequestedUserId");
b.ToTable("MovieRequests");
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.TvIssues", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Description");
b.Property<int?>("IssueId");
b.Property<string>("Subect");
b.Property<int>("TvId");
b.HasKey("Id");
b.HasIndex("IssueId");
b.HasIndex("TvId");
b.ToTable("TvIssues");
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ImdbId");
b.Property<string>("Overview");
b.Property<string>("PosterPath");
b.Property<DateTime>("ReleaseDate");
b.Property<int?>("RootFolder");
b.Property<string>("Status");
b.Property<string>("Title");
b.Property<int>("TvDbId");
b.HasKey("Id");
b.ToTable("TvRequests");
});
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("TvDbId");
b.HasKey("Id");
b.ToTable("SonarrCache");
});
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("EpisodeNumber");
b.Property<int>("SeasonNumber");
b.Property<int>("TvDbId");
b.HasKey("Id");
b.ToTable("SonarrEpisodeCache");
});
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Token");
b.Property<string>("UserId");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Tokens");
});
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AirDate");
b.Property<bool>("Approved");
b.Property<bool>("Available");
b.Property<int>("EpisodeNumber");
b.Property<bool>("Requested");
b.Property<int>("SeasonId");
b.Property<string>("Title");
b.Property<string>("Url");
b.HasKey("Id");
b.HasIndex("SeasonId");
b.ToTable("EpisodeRequests");
});
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("ChildRequestId");
b.Property<int>("SeasonNumber");
b.HasKey("Id");
b.HasIndex("ChildRequestId");
b.ToTable("SeasonRequests");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Ombi.Store.Entities.OmbiUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Ombi.Store.Entities.OmbiUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Ombi.Store.Entities.OmbiUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Ombi.Store.Entities.OmbiUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
{
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
.WithMany("Episodes")
.HasForeignKey("ParentId")
.HasPrincipalKey("EmbyId");
});
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
{
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
.WithMany("Episodes")
.HasForeignKey("GrandparentKey")
.HasPrincipalKey("Key")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
{
b.HasOne("Ombi.Store.Entities.PlexServerContent")
.WithMany("Seasons")
.HasForeignKey("PlexServerContentId");
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
{
b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest")
.WithMany("ChildRequests")
.HasForeignKey("ParentRequestId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
.WithMany()
.HasForeignKey("RequestedUserId");
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieIssues", b =>
{
b.HasOne("Ombi.Store.Entities.Requests.MovieRequests")
.WithMany("Issues")
.HasForeignKey("IssueId");
b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", "Movie")
.WithMany()
.HasForeignKey("MovieId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
{
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
.WithMany()
.HasForeignKey("RequestedUserId");
});
modelBuilder.Entity("Ombi.Store.Entities.Requests.TvIssues", b =>
{
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests")
.WithMany("Issues")
.HasForeignKey("IssueId");
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "Child")
.WithMany()
.HasForeignKey("TvId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
{
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
.WithMany()
.HasForeignKey("UserId");
});
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
{
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
.WithMany("Episodes")
.HasForeignKey("SeasonId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
{
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest")
.WithMany("SeasonRequests")
.HasForeignKey("ChildRequestId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

@ -0,0 +1,15 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Ombi.Store.Migrations
{
public partial class JobSettingsMigration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
var settings = new JobSettings()
migrationBuilder.Sql(@"
");
}
}
}

@ -1,154 +1,162 @@
import { ISettings } from "./ICommon";
export interface IExternalSettings extends ISettings {
ssl: boolean;
subDir: string;
ip: string;
port: number;
ssl: boolean;
subDir: string;
ip: string;
port: number;
}
export interface IOmbiSettings extends ISettings {
baseUrl: string;
collectAnalyticData: boolean;
wizard: boolean;
apiKey: string;
ignoreCertificateErrors: boolean;
baseUrl: string;
collectAnalyticData: boolean;
wizard: boolean;
apiKey: string;
ignoreCertificateErrors: boolean;
}
export interface IUpdateSettings extends ISettings {
autoUpdateEnabled: boolean;
username: string;
password: string;
processName: string;
useScript: boolean;
scriptLocation: string;
autoUpdateEnabled: boolean;
username: string;
password: string;
processName: string;
useScript: boolean;
scriptLocation: string;
}
export interface IEmbySettings extends ISettings {
enable: boolean;
servers: IEmbyServer[];
enable: boolean;
servers: IEmbyServer[];
}
export interface IEmbyServer extends IExternalSettings {
name: string;
apiKey: string;
administratorId: string;
enableEpisodeSearching: boolean;
name: string;
apiKey: string;
administratorId: string;
enableEpisodeSearching: boolean;
}
export interface IPlexSettings extends ISettings {
enable: boolean;
servers: IPlexServer[];
enable: boolean;
servers: IPlexServer[];
}
export interface IPlexServer extends IExternalSettings {
name: string;
enableEpisodeSearching: boolean;
plexAuthToken: string;
machineIdentifier: string;
episodeBatchSize: number;
plexSelectedLibraries: IPlexLibrariesSettings[];
name: string;
enableEpisodeSearching: boolean;
plexAuthToken: string;
machineIdentifier: string;
episodeBatchSize: number;
plexSelectedLibraries: IPlexLibrariesSettings[];
}
export interface IPlexLibrariesSettings {
key: string;
title: string;
enabled: boolean;
key: string;
title: string;
enabled: boolean;
}
export interface ISonarrSettings extends IExternalSettings {
apiKey: string;
enabled: boolean;
qualityProfile: string;
seasonFolders: boolean;
rootPath: string;
fullRootPath: string;
addOnly: boolean;
apiKey: string;
enabled: boolean;
qualityProfile: string;
seasonFolders: boolean;
rootPath: string;
fullRootPath: string;
addOnly: boolean;
}
export interface IRadarrSettings extends IExternalSettings {
enabled: boolean;
apiKey: string;
defaultQualityProfile: string;
defaultRootPath: string;
fullRootPath: string;
addOnly: boolean;
minimumAvailability: string;
enabled: boolean;
apiKey: string;
defaultQualityProfile: string;
defaultRootPath: string;
fullRootPath: string;
addOnly: boolean;
minimumAvailability: string;
}
export interface ILandingPageSettings extends ISettings {
enabled: boolean;
enabled: boolean;
noticeEnabled: boolean;
noticeText: string;
noticeEnabled: boolean;
noticeText: string;
timeLimit: boolean;
startDateTime: Date;
endDateTime: Date;
expired: boolean;
timeLimit: boolean;
startDateTime: Date;
endDateTime: Date;
expired: boolean;
}
export interface ICustomizationSettings extends ISettings {
applicationName: string;
applicationUrl: string;
logo: string;
customCssLink: string;
hasPresetTheme: boolean;
presetThemeName: string;
presetThemeContent: string;
presetThemeDisplayName: string;
presetThemeVersion: string;
applicationName: string;
applicationUrl: string;
logo: string;
customCssLink: string;
hasPresetTheme: boolean;
presetThemeName: string;
presetThemeContent: string;
presetThemeDisplayName: string;
presetThemeVersion: string;
}
export interface IThemes {
fullName: string;
displayName: string;
version: string;
url: string;
fullName: string;
displayName: string;
version: string;
url: string;
}
export interface IAuthenticationSettings extends ISettings {
export interface IJobSettings {
embyContentSync: string;
sonarrSync: string;
radarrSync: string;
plexContentSync: string;
couchPotatoSync: string;
automaticUpdater: string;
userImporter: string;
}
allowExternalUsersToAuthenticate: boolean;
// Password
export interface IAuthenticationSettings extends ISettings {
allowExternalUsersToAuthenticate: boolean;
// Password
requiredDigit: boolean;
requiredLength: number;
requiredLowercase: boolean;
requireNonAlphanumeric: boolean;
requireUppercase: boolean;
requiredDigit: boolean;
requiredLength: number;
requiredLowercase: boolean;
requireNonAlphanumeric: boolean;
requireUppercase: boolean;
}
export interface IUserManagementSettings extends ISettings {
importPlexUsers: boolean;
importPlexAdmin: boolean;
importEmbyUsers: boolean;
defaultRoles: string[];
bannedPlexUserIds: string[];
bannedEmbyUserIds: string[];
importPlexUsers: boolean;
importPlexAdmin: boolean;
importEmbyUsers: boolean;
defaultRoles: string[];
bannedPlexUserIds: string[];
bannedEmbyUserIds: string[];
}
export interface IAbout {
version: string;
branch: string;
osArchitecture: string;
osDescription: string;
processArchitecture: string;
applicationBasePath: string;
version: string;
branch: string;
osArchitecture: string;
osDescription: string;
processArchitecture: string;
applicationBasePath: string;
}
export interface ICouchPotatoSettings extends IExternalSettings {
enabled: boolean;
apiKey: string;
defaultProfileId: string;
username: string;
password: string;
enabled: boolean;
apiKey: string;
defaultProfileId: string;
username: string;
password: string;
}
export interface IDogNzbSettings extends ISettings {
enabled: boolean;
apiKey: string;
movies: boolean;
tvShows: boolean;
enabled: boolean;
apiKey: string;
movies: boolean;
tvShows: boolean;
}

@ -1,4 +1,5 @@
import { PlatformLocation } from "@angular/common";
import { IJobSettings } from './../interfaces/ISettings';
import { PlatformLocation } from "@angular/common";
import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import { AuthHttp } from "angular2-jwt";
@ -13,6 +14,7 @@ import {
IDogNzbSettings,
IEmailNotificationSettings,
IEmbySettings,
IJobSettings,
ILandingPageSettings,
IMattermostNotifcationSettings,
IOmbiSettings,
@ -240,4 +242,14 @@ export class SettingsService extends ServiceAuthHelpers {
.post(`${this.url}/notifications/telegram`, JSON.stringify(settings), { headers: this.headers })
.map(this.extractData).catch(this.handleError);
}
public getJobSettings(): Observable<IJobSettings> {
return this.httpAuth.get(`${this.url}/jobs`).map(this.extractData).catch(this.handleError);
}
public saveJobSettings(settings: IJobSettings): Observable<boolean> {
return this.httpAuth
.post(`${this.url}/jobs`, JSON.stringify(settings), { headers: this.headers })
.map(this.extractData).catch(this.handleError);
}
}

@ -0,0 +1,65 @@
<settings-menu>
</settings-menu>
<wiki [url]="'https://github.com/tidusjar/Ombi/wiki/Job-Settings'"></wiki>
<div *ngIf="form">
<fieldset>
<legend>Job Settings</legend>
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)" style="padding-top:5%;">
<div class="col-md-6">
<small>Changes to any of the below requires you to restart Ombi.</small>
<div class="form-group">
<label for="sonarrSync" class="control-label">Sonarr Sync</label>
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('sonarrSync').hasError('required')}" id="sonarrSync" name="sonarrSync" formControlName="sonarrSync">
<small *ngIf="form.get('sonarrSync').hasError('required')" class="error-text">The Sonarr Sync is required</small>
</div>
<div class="form-group">
<label for="radarrSync" class="control-label">Radarr Sync</label>
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('radarrSync').hasError('required')}" id="radarrSync" name="radarrSync" formControlName="radarrSync">
<small *ngIf="form.get('radarrSync').hasError('required')" class="error-text">The Radarr Sync is required</small>
</div>
<div class="form-group">
<label for="couchPotatoSync" class="control-label">CouchPotato Sync</label>
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('radarrSync').hasError('required')}" id="couchPotatoSync" name="couchPotatoSync" formControlName="couchPotatoSync">
<small *ngIf="form.get('couchPotatoSync').hasError('required')" class="error-text">The CouchPotato Sync is required</small>
</div>
<div class="form-group">
<label for="automaticUpdater" class="control-label">Automatic Update</label>
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('automaticUpdater').hasError('required')}" id="automaticUpdater" name="automaticUpdater" formControlName="automaticUpdater">
<small *ngIf="form.get('automaticUpdater').hasError('required')" class="error-text">The Automatic Update is required</small>
</div>
<div class="form-group">
<div>
<button type="submit" [disabled]="form.invalid" class="btn btn-primary-outline">Submit</button>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="plexContentSync" class="control-label">Plex Sync</label>
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('plexContentSync').hasError('required')}" id="plexContentSync" name="plexContentSync" formControlName="plexContentSync">
<small *ngIf="form.get('plexContentSync').hasError('required')" class="error-text">The Plex Sync is required</small>
</div>
<div class="form-group">
<label for="embyContentSync" class="control-label">Emby Sync</label>
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('embyContentSync').hasError('required')}" id="embyContentSync" name="embyContentSync" formControlName="embyContentSync">
<small *ngIf="form.get('embyContentSync').hasError('required')" class="error-text">The Emby Sync is required</small>
</div>
<div class="form-group">
<label for="userImporter" class="control-label">User Importer</label>
<input type="text" class="form-control form-control-custom" [ngClass]="{'form-error': form.get('userImporter').hasError('required')}" id="userImporter" name="userImporter" formControlName="userImporter">
<small *ngIf="form.get('userImporter').hasError('required')" class="error-text">The User Importer is required</small>
</div>
</div>
</form>
</fieldset>
</div>

@ -0,0 +1,46 @@
import { Component, OnInit } from "@angular/core";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { NotificationService, SettingsService } from "../../services";
@Component({
templateUrl: "./jobs.component.html",
})
export class JobsComponent implements OnInit {
public form: FormGroup;
public profilesRunning: boolean;
constructor(private readonly settingsService: SettingsService,
private readonly fb: FormBuilder,
private readonly notificationService: NotificationService) { }
public ngOnInit() {
this.settingsService.getJobSettings().subscribe(x => {
this.form = this.fb.group({
automaticUpdater: [x.automaticUpdater, Validators.required],
couchPotatoSync: [x.couchPotatoSync, Validators.required],
embyContentSync: [x.embyContentSync, Validators.required],
plexContentSync: [x.plexContentSync, Validators.required],
userImporter: [x.userImporter, Validators.required],
sonarrSync: [x.radarrSync, Validators.required],
radarrSync: [x.sonarrSync, Validators.required],
});
});
}
public onSubmit(form: FormGroup) {
if (form.invalid) {
this.notificationService.error("Please check your entered values");
return;
}
const settings = form.value;
this.settingsService.saveJobSettings(settings).subscribe(x => {
if (x) {
this.notificationService.success("Successfully saved the job settings");
} else {
this.notificationService.success("There was an error when saving the job settings");
}
});
}
}

@ -16,6 +16,7 @@ import { CouchPotatoComponent } from "./couchpotato/couchpotato.component";
import { CustomizationComponent } from "./customization/customization.component";
import { DogNzbComponent } from "./dognzb/dognzb.component";
import { EmbyComponent } from "./emby/emby.component";
import { JobsComponent } from "./jobs/jobs.component";
import { LandingPageComponent } from "./landingpage/landingpage.component";
import { DiscordComponent } from "./notifications/discord.component";
import { EmailNotificationComponent } from "./notifications/emailnotification.component";
@ -57,6 +58,7 @@ const routes: Routes = [
{ path: "Settings/CouchPotato", component: CouchPotatoComponent, canActivate: [AuthGuard] },
{ path: "Settings/DogNzb", component: DogNzbComponent, canActivate: [AuthGuard] },
{ path: "Settings/Telegram", component: TelegramComponent, canActivate: [AuthGuard] },
{ path: "Settings/Jobs", component: JobsComponent, canActivate: [AuthGuard] },
];
@NgModule({
@ -83,6 +85,7 @@ const routes: Routes = [
OmbiComponent,
PlexComponent,
EmbyComponent,
JobsComponent,
LandingPageComponent,
CustomizationComponent,
DiscordComponent,

@ -421,6 +421,37 @@ namespace Ombi.Controllers
return await Save(settings);
}
/// <summary>
/// Gets the JobSettings Settings.
/// </summary>
/// <returns></returns>
[HttpGet("jobs")]
public async Task<JobSettings> JobSettings()
{
var j = await Get<JobSettings>();
// Get the defaults if the jobs are not set
j.RadarrSync = j.RadarrSync.HasValue() ? j.RadarrSync : JobSettingsHelper.Radarr(j);
j.SonarrSync = j.SonarrSync.HasValue() ? j.SonarrSync : JobSettingsHelper.Sonarr(j);
j.AutomaticUpdater = j.AutomaticUpdater.HasValue() ? j.AutomaticUpdater : JobSettingsHelper.Updater(j);
j.CouchPotatoSync = j.CouchPotatoSync.HasValue() ? j.CouchPotatoSync : JobSettingsHelper.CouchPotato(j);
j.EmbyContentSync = j.EmbyContentSync.HasValue() ? j.EmbyContentSync : JobSettingsHelper.EmbyContent(j);
j.PlexContentSync = j.PlexContentSync.HasValue() ? j.PlexContentSync : JobSettingsHelper.PlexContent(j);
j.UserImporter = j.UserImporter.HasValue() ? j.UserImporter : JobSettingsHelper.UserImporter(j);
return j;
}
/// <summary>
/// Save the JobSettings settings.
/// </summary>
/// <param name="settings">The settings.</param>
/// <returns></returns>
[HttpPost("jobs")]
public async Task<bool> JobSettings([FromBody]JobSettings settings)
{
return await Save(settings);
}
/// <summary>
/// Saves the email notification settings.
/// </summary>

Loading…
Cancel
Save