Added the ability to customize job scheudles

This commit is contained in:
Jamie 2017-11-20 15:15:10 +00:00
parent e090800cd7
commit a89585b85a
11 changed files with 1125 additions and 106 deletions

View file

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

View file

@ -5,5 +5,9 @@
public string EmbyContentSync { get; set; } public string EmbyContentSync { get; set; }
public string SonarrSync { get; set; } public string SonarrSync { get; set; }
public string RadarrSync { 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; }
} }
} }

View file

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

View file

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

View file

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

View file

@ -37,7 +37,6 @@ export interface IEmbyServer extends IExternalSettings {
} }
export interface IPlexSettings extends ISettings { export interface IPlexSettings extends ISettings {
enable: boolean; enable: boolean;
servers: IPlexServer[]; servers: IPlexServer[];
} }
@ -108,8 +107,17 @@ export interface IThemes {
url: 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;
}
export interface IAuthenticationSettings extends ISettings {
allowExternalUsersToAuthenticate: boolean; allowExternalUsersToAuthenticate: boolean;
// Password // Password

View file

@ -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 { Injectable } from "@angular/core";
import { Http } from "@angular/http"; import { Http } from "@angular/http";
import { AuthHttp } from "angular2-jwt"; import { AuthHttp } from "angular2-jwt";
@ -13,6 +14,7 @@ import {
IDogNzbSettings, IDogNzbSettings,
IEmailNotificationSettings, IEmailNotificationSettings,
IEmbySettings, IEmbySettings,
IJobSettings,
ILandingPageSettings, ILandingPageSettings,
IMattermostNotifcationSettings, IMattermostNotifcationSettings,
IOmbiSettings, IOmbiSettings,
@ -240,4 +242,14 @@ export class SettingsService extends ServiceAuthHelpers {
.post(`${this.url}/notifications/telegram`, JSON.stringify(settings), { headers: this.headers }) .post(`${this.url}/notifications/telegram`, JSON.stringify(settings), { headers: this.headers })
.map(this.extractData).catch(this.handleError); .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);
}
} }

View file

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

View file

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

View file

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

View file

@ -421,6 +421,37 @@ namespace Ombi.Controllers
return await Save(settings); 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> /// <summary>
/// Saves the email notification settings. /// Saves the email notification settings.
/// </summary> /// </summary>