Added Couchpotato support and fixed #1548

Moved the SSL Cert ignore into the Ombi Settings
pull/1614/head
tidusjar 7 years ago
parent ef82926574
commit 57f3297892

@ -1,29 +1,45 @@
using System.IO; using System;
using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Serialization; using System.Xml.Serialization;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core.Settings;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
namespace Ombi.Api namespace Ombi.Api
{ {
public class Api : IApi public class Api : IApi
{ {
public Api(ILogger<Api> log) public Api(ILogger<Api> log, ISettingsService<OmbiSettings> s, IMemoryCache cache)
{ {
Logger = log; Logger = log;
_settings = s;
_cache = cache;
} }
private ILogger<Api> Logger { get; } private ILogger<Api> Logger { get; }
private readonly ISettingsService<OmbiSettings> _settings;
private readonly IMemoryCache _cache;
private async Task<HttpMessageHandler> GetHandler()
private HttpMessageHandler GetHandler()
{ {
return new HttpClientHandler var settings = await _cache.GetOrCreateAsync(CacheKeys.OmbiSettings, async entry =>
{
entry.AbsoluteExpiration = DateTimeOffset.Now.AddHours(1);
return await _settings.GetSettingsAsync();
});
if (settings.IgnoreCertificateErrors)
{ {
ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true return new HttpClientHandler
}; {
ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true
};
}
return new HttpClientHandler();
} }
private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
@ -33,7 +49,7 @@ namespace Ombi.Api
public async Task<T> Request<T>(Request request) public async Task<T> Request<T>(Request request)
{ {
using (var httpClient = new HttpClient(GetHandler())) using (var httpClient = new HttpClient(await GetHandler()))
{ {
using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri)) using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri))
@ -79,7 +95,7 @@ namespace Ombi.Api
public async Task<string> RequestContent(Request request) public async Task<string> RequestContent(Request request)
{ {
using (var httpClient = new HttpClient(GetHandler())) using (var httpClient = new HttpClient(await GetHandler()))
{ {
using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri)) using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri))
{ {
@ -113,7 +129,7 @@ namespace Ombi.Api
public async Task Request(Request request) public async Task Request(Request request)
{ {
using (var httpClient = new HttpClient(GetHandler())) using (var httpClient = new HttpClient(await GetHandler()))
{ {
using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri)) using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri))
{ {

@ -16,6 +16,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" /> <ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -0,0 +1,35 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Context;
using Ombi.Store.Entities;
namespace Ombi.Core.Rule.Rules.Search
{
public class CouchPotatoCacheRule : BaseSearchRule, IRules<SearchViewModel>
{
public CouchPotatoCacheRule(IOmbiContext ctx)
{
_ctx = ctx;
}
private readonly IOmbiContext _ctx;
public async Task<RuleResult> Execute(SearchViewModel obj)
{
if (obj.Type == RequestType.Movie)
{
// Check if it's in Radarr
var result = await _ctx.CouchPotatoCache.FirstOrDefaultAsync(x => x.TheMovieDbId == obj.Id);
if (result != null)
{
obj.Approved =
true; // It's in cp so it's approved... Maybe have a new property called "Processing" or something?
}
}
return Success();
}
}
}

@ -38,10 +38,12 @@ using Ombi.Api.Service;
using Ombi.Api.Slack; using Ombi.Api.Slack;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Core.Senders; using Ombi.Core.Senders;
using Ombi.Schedule.Jobs.Couchpotato;
using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Emby;
using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Ombi;
using Ombi.Schedule.Jobs.Plex; using Ombi.Schedule.Jobs.Plex;
using Ombi.Schedule.Jobs.Sonarr; using Ombi.Schedule.Jobs.Sonarr;
using Ombi.Store.Entities;
using Ombi.Store.Repository.Requests; using Ombi.Store.Repository.Requests;
using PlexContentCacher = Ombi.Schedule.Jobs.Plex.PlexContentCacher; using PlexContentCacher = Ombi.Schedule.Jobs.Plex.PlexContentCacher;
@ -129,11 +131,12 @@ namespace Ombi.DependencyInjection
services.AddTransient<IMattermostNotification, MattermostNotification>(); services.AddTransient<IMattermostNotification, MattermostNotification>();
services.AddTransient<IPushoverNotification, PushoverNotification>(); services.AddTransient<IPushoverNotification, PushoverNotification>();
services.AddTransient<IBackgroundJobClient, BackgroundJobClient>();
} }
public static void RegisterJobs(this IServiceCollection services) public static void RegisterJobs(this IServiceCollection services)
{ {
services.AddTransient<IBackgroundJobClient, BackgroundJobClient>();
services.AddTransient<IPlexContentCacher, PlexContentCacher>(); services.AddTransient<IPlexContentCacher, PlexContentCacher>();
services.AddTransient<IEmbyContentCacher, EmbyContentCacher>(); services.AddTransient<IEmbyContentCacher, EmbyContentCacher>();
services.AddTransient<IEmbyEpisodeCacher, EmbyEpisodeCacher>(); services.AddTransient<IEmbyEpisodeCacher, EmbyEpisodeCacher>();
@ -147,6 +150,7 @@ namespace Ombi.DependencyInjection
services.AddTransient<IPlexUserImporter, PlexUserImporter>(); services.AddTransient<IPlexUserImporter, PlexUserImporter>();
services.AddTransient<IEmbyUserImporter, EmbyUserImporter>(); services.AddTransient<IEmbyUserImporter, EmbyUserImporter>();
services.AddTransient<IWelcomeEmail, WelcomeEmail>(); services.AddTransient<IWelcomeEmail, WelcomeEmail>();
services.AddTransient<ICouchPotatoCacher, CouchPotatoCacher>();
} }
} }
} }

@ -17,6 +17,7 @@ namespace Ombi.Helpers
public static EventId PlexUserImporter => new EventId(2004); public static EventId PlexUserImporter => new EventId(2004);
public static EventId EmbyUserImporter => new EventId(2005); public static EventId EmbyUserImporter => new EventId(2005);
public static EventId SonarrCacher => new EventId(2006); public static EventId SonarrCacher => new EventId(2006);
public static EventId CouchPotatoCacher => new EventId(2007);
public static EventId MovieSender => new EventId(3000); public static EventId MovieSender => new EventId(3000);

@ -1,5 +1,6 @@
using Hangfire; using Hangfire;
using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs;
using Ombi.Schedule.Jobs.Couchpotato;
using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Emby;
using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Ombi;
using Ombi.Schedule.Jobs.Plex; using Ombi.Schedule.Jobs.Plex;
@ -12,7 +13,7 @@ namespace Ombi.Schedule
{ {
public JobSetup(IPlexContentCacher plexContentCacher, IRadarrCacher radarrCacher, public JobSetup(IPlexContentCacher plexContentCacher, IRadarrCacher radarrCacher,
IOmbiAutomaticUpdater updater, IEmbyContentCacher embyCacher, IPlexUserImporter userImporter, IOmbiAutomaticUpdater updater, IEmbyContentCacher embyCacher, IPlexUserImporter userImporter,
IEmbyUserImporter embyUserImporter, ISonarrCacher cache) IEmbyUserImporter embyUserImporter, ISonarrCacher cache, ICouchPotatoCacher cpCache)
{ {
PlexContentCacher = plexContentCacher; PlexContentCacher = plexContentCacher;
RadarrCacher = radarrCacher; RadarrCacher = radarrCacher;
@ -21,6 +22,7 @@ namespace Ombi.Schedule
PlexUserImporter = userImporter; PlexUserImporter = userImporter;
EmbyUserImporter = embyUserImporter; EmbyUserImporter = embyUserImporter;
SonarrCacher = cache; SonarrCacher = cache;
CpCache = cpCache;
} }
private IPlexContentCacher PlexContentCacher { get; } private IPlexContentCacher PlexContentCacher { get; }
@ -30,16 +32,20 @@ namespace Ombi.Schedule
private IEmbyContentCacher EmbyContentCacher { get; } private IEmbyContentCacher EmbyContentCacher { get; }
private IEmbyUserImporter EmbyUserImporter { get; } private IEmbyUserImporter EmbyUserImporter { get; }
private ISonarrCacher SonarrCacher { get; } private ISonarrCacher SonarrCacher { get; }
private ICouchPotatoCacher CpCache { get; }
public void Setup() public void Setup()
{ {
RecurringJob.AddOrUpdate(() => PlexContentCacher.CacheContent(), Cron.Hourly(20));
RecurringJob.AddOrUpdate(() => EmbyContentCacher.Start(), Cron.Hourly(5)); RecurringJob.AddOrUpdate(() => EmbyContentCacher.Start(), Cron.Hourly(5));
RecurringJob.AddOrUpdate(() => SonarrCacher.Start(), Cron.Hourly(10)); RecurringJob.AddOrUpdate(() => SonarrCacher.Start(), Cron.Hourly(10));
RecurringJob.AddOrUpdate(() => RadarrCacher.CacheContent(), Cron.Hourly(15)); RecurringJob.AddOrUpdate(() => RadarrCacher.CacheContent(), Cron.Hourly(15));
RecurringJob.AddOrUpdate(() => PlexUserImporter.Start(), Cron.Daily(5)); RecurringJob.AddOrUpdate(() => PlexContentCacher.CacheContent(), Cron.Hourly(20));
RecurringJob.AddOrUpdate(() => EmbyUserImporter.Start(), Cron.Daily); RecurringJob.AddOrUpdate(() => CpCache.Start(), Cron.Hourly(30));
RecurringJob.AddOrUpdate(() => Updater.Update(null), Cron.HourInterval(6)); RecurringJob.AddOrUpdate(() => Updater.Update(null), Cron.HourInterval(6));
RecurringJob.AddOrUpdate(() => EmbyUserImporter.Start(), Cron.Daily);
RecurringJob.AddOrUpdate(() => PlexUserImporter.Start(), Cron.Daily(5));
} }
} }
} }

@ -0,0 +1,105 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: CouchPotatoCacher.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ombi.Api.CouchPotato;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Context;
using Ombi.Store.Entities;
namespace Ombi.Schedule.Jobs.Couchpotato
{
public class CouchPotatoCacher : ICouchPotatoCacher
{
public CouchPotatoCacher(ISettingsService<CouchPotatoSettings> cpSettings,
ICouchPotatoApi api, ILogger<CouchPotatoCacher> log, IOmbiContext ctx)
{
_settings = cpSettings;
_api = api;
_log = log;
_ctx = ctx;
}
private readonly ISettingsService<CouchPotatoSettings> _settings;
private readonly ICouchPotatoApi _api;
private readonly ILogger<CouchPotatoCacher> _log;
private readonly IOmbiContext _ctx;
public async Task Start()
{
var settings = await _settings.GetSettingsAsync();
if (!settings.Enabled)
{
return;
}
try
{
_log.LogInformation(LoggingEvents.CouchPotatoCacher, "Getting all active movies from CP");
var movies = await _api.GetMovies(settings.FullUri, settings.ApiKey, new[] {"active"});
if (movies != null)
{
// Let's remove the old cached data
await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM CouchPotatoCache");
// Save
var movieIds = new List<CouchPotatoCache>();
foreach (var m in movies.movies)
{
if (m.info == null)
{
_log.LogInformation("Movie {0} does nto have a tmdbid", m.title);
continue;
}
if (m.info.tmdb_id > 0)
{
movieIds.Add(new CouchPotatoCache { TheMovieDbId = m.info.tmdb_id });
}
else
{
_log.LogError("TMDBId is not > 0 for movie {0}", m.title);
}
}
await _ctx.CouchPotatoCache.AddRangeAsync(movieIds);
await _ctx.SaveChangesAsync();
}
}
catch (Exception e)
{
_log.LogError(LoggingEvents.CouchPotatoCacher, e, "error when trying to get movies from CP");
throw;
}
}
}
}

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Ombi.Schedule.Jobs.Couchpotato
{
public interface ICouchPotatoCacher
{
Task Start();
}
}

@ -56,7 +56,7 @@ namespace Ombi.Schedule.Jobs.Radarr
} }
else else
{ {
Log.Error("TMDBId is not > 0 for movie {0}", m.title); Logger.LogError("TMDBId is not > 0 for movie {0}", m.title);
} }
} }
await _ctx.RadarrCache.AddRangeAsync(movieIds); await _ctx.RadarrCache.AddRangeAsync(movieIds);

@ -22,6 +22,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ombi.Api.CouchPotato\Ombi.Api.CouchPotato.csproj" />
<ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" /> <ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" />
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" /> <ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
<ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" /> <ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" />

@ -6,6 +6,7 @@
public bool CollectAnalyticData { get; set; } public bool CollectAnalyticData { get; set; }
public bool Wizard { get; set; } public bool Wizard { get; set; }
public string ApiKey { get; set; } public string ApiKey { get; set; }
public bool IgnoreCertificateErrors { get; set; }
} }
} }

@ -37,5 +37,6 @@ namespace Ombi.Store.Context
DbSet<SonarrEpisodeCache> SonarrEpisodeCache { get; set; } DbSet<SonarrEpisodeCache> SonarrEpisodeCache { get; set; }
EntityEntry Update(object entity); EntityEntry Update(object entity);
EntityEntry<TEntity> Update<TEntity>(TEntity entity) where TEntity : class; EntityEntry<TEntity> Update<TEntity>(TEntity entity) where TEntity : class;
DbSet<CouchPotatoCache> CouchPotatoCache { get; set; }
} }
} }

@ -26,6 +26,7 @@ namespace Ombi.Store.Context
public DbSet<PlexContent> PlexContent { get; set; } public DbSet<PlexContent> PlexContent { get; set; }
public DbSet<PlexEpisode> PlexEpisode { get; set; } public DbSet<PlexEpisode> PlexEpisode { get; set; }
public DbSet<RadarrCache> RadarrCache { get; set; } public DbSet<RadarrCache> RadarrCache { get; set; }
public DbSet<CouchPotatoCache> CouchPotatoCache { get; set; }
public DbSet<EmbyContent> EmbyContent { get; set; } public DbSet<EmbyContent> EmbyContent { get; set; }
public DbSet<EmbyEpisode> EmbyEpisode { get; set; } public DbSet<EmbyEpisode> EmbyEpisode { get; set; }

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Ombi.Store.Entities
{
[Table("CouchPotatoCache")]
public class CouchPotatoCache : Entity
{
public int TheMovieDbId { get; set; }
}
}

@ -0,0 +1,775 @@
// <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("20171015200035_CouchPotatoCacher")]
partial class CouchPotatoCacher
{
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.PlexContent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedAt");
b.Property<int>("Key");
b.Property<string>("ProviderId");
b.Property<string>("Quality");
b.Property<string>("ReleaseYear");
b.Property<string>("Title");
b.Property<int>("Type");
b.Property<string>("Url");
b.HasKey("Id");
b.ToTable("PlexContent");
});
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>("SeasonKey");
b.Property<int>("SeasonNumber");
b.HasKey("Id");
b.HasIndex("PlexContentId");
b.ToTable("PlexSeasonsContent");
});
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<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.PlexContent", "Series")
.WithMany("Episodes")
.HasForeignKey("GrandparentKey")
.HasPrincipalKey("Key")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
{
b.HasOne("Ombi.Store.Entities.PlexContent")
.WithMany("Seasons")
.HasForeignKey("PlexContentId")
.OnDelete(DeleteBehavior.Cascade);
});
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,31 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
namespace Ombi.Store.Migrations
{
public partial class CouchPotatoCacher : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "CouchPotatoCache",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
TheMovieDbId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CouchPotatoCache", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CouchPotatoCache");
}
}
}

@ -162,6 +162,18 @@ namespace Ombi.Store.Migrations
b.ToTable("Audit"); 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 => modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")

@ -1,2 +0,0 @@
cd ..
dotnet ef migrations add Inital --context OmbiContext --startup-project ../Ombi/Ombi.csproj

@ -8,13 +8,11 @@ export interface IExternalSettings extends ISettings {
} }
export interface IOmbiSettings extends ISettings { export interface IOmbiSettings extends ISettings {
port: number;
baseUrl: string; baseUrl: string;
collectAnalyticData: boolean; collectAnalyticData: boolean;
wizard: boolean; wizard: boolean;
apiKey: string; apiKey: string;
externalUrl: string; ignoreCertificateErrors: boolean;
allowExternalUsersToAuthenticate: boolean;
} }
export interface IUpdateSettings extends ISettings { export interface IUpdateSettings extends ISettings {

@ -44,6 +44,13 @@
</div> </div>
</div> </div>
</div> </div>
<br/>
<div class="form-group">
<div class="checkbox">
<input type="checkbox" id="ignoreCertificateErrors" name="ignoreCertificateErrors" formControlName="ignoreCertificateErrors">
<label for="ignoreCertificateErrors" tooltipPosition="top" pTooltip="Enable if you are having connectivity problems over SSL">Ignore any certificate errors</label>
</div>
</div>
<div class="form-group"> <div class="form-group">
<div class="checkbox"> <div class="checkbox">

@ -18,11 +18,9 @@ export class OmbiComponent implements OnInit {
public ngOnInit() { public ngOnInit() {
this.settingsService.getOmbi().subscribe(x => { this.settingsService.getOmbi().subscribe(x => {
this.form = this.fb.group({ this.form = this.fb.group({
port: [x.port],
collectAnalyticData: [x.collectAnalyticData], collectAnalyticData: [x.collectAnalyticData],
apiKey: [x.apiKey], apiKey: [x.apiKey],
externalUrl: [x.externalUrl], ignoreCertificateErrors: [x.ignoreCertificateErrors],
allowExternalUsersToAuthenticate: [x.allowExternalUsersToAuthenticate],
baseUrl: [x.baseUrl], baseUrl: [x.baseUrl],
}); });
}); });

@ -40,7 +40,7 @@
<i class="fa fa-film" aria-hidden="true"></i> Movies <span class="caret"></span> <i class="fa fa-film" aria-hidden="true"></i> Movies <span class="caret"></span>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/CouchPotato']">CouchPotato (NOT YET READY)</a></li> <li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/CouchPotato']">CouchPotato</a></li>
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/DogNzb']">DogNzb</a></li> <li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/DogNzb']">DogNzb</a></li>
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Radarr']">Radarr</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 [routerLink]="['/Settings/Watcher']">Watcher</a></li>-->

@ -54,7 +54,7 @@
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<button type="submit" id="save" (click)="submit()" class="btn btn-primary-outline">Submit</button> <button type="submit" id="save" (click)="submit()" class="btn btn-primary-outline">Submit</button>
<button type="button" [disabled]="!settings.importEmbyUsers || !settings.importPlexUsers" (click)="runImporter()" class="btn btn-info-outline">Run Importer</button> <button type="button" [disabled]="!enableImportButton" (click)="runImporter()" class="btn btn-info-outline">Run Importer</button>
</div> </div>
<div class="form-group"> <div class="form-group">
</div> </div>

@ -22,6 +22,8 @@ export class UserManagementComponent implements OnInit {
public filteredEmbyUsers: IUsersModel[]; public filteredEmbyUsers: IUsersModel[];
public bannedEmbyUsers: IUsersModel[] = []; public bannedEmbyUsers: IUsersModel[] = [];
public enableImportButton = false;
constructor(private readonly settingsService: SettingsService, constructor(private readonly settingsService: SettingsService,
private readonly notificationService: NotificationService, private readonly notificationService: NotificationService,
private readonly identityService: IdentityService, private readonly identityService: IdentityService,
@ -34,6 +36,10 @@ export class UserManagementComponent implements OnInit {
this.settingsService.getUserManagementSettings().subscribe(x => { this.settingsService.getUserManagementSettings().subscribe(x => {
this.settings = x; this.settings = x;
if(x.importEmbyUsers || x.importPlexUsers) {
this.enableImportButton = true;
}
this.plexService.getFriends().subscribe(f => { this.plexService.getFriends().subscribe(f => {
this.plexUsers = f; this.plexUsers = f;
this.plexUsers.forEach((plex) => { this.plexUsers.forEach((plex) => {
@ -82,6 +88,10 @@ export class UserManagementComponent implements OnInit {
this.settings.defaultRoles = enabledClaims.map((claim) => claim.value); this.settings.defaultRoles = enabledClaims.map((claim) => claim.value);
this.settings.bannedPlexUserIds = this.bannedPlexUsers.map((u) => u.id); this.settings.bannedPlexUserIds = this.bannedPlexUsers.map((u) => u.id);
this.settings.bannedEmbyUserIds = this.bannedEmbyUsers.map((u) => u.id); this.settings.bannedEmbyUserIds = this.bannedEmbyUsers.map((u) => u.id);
if(this.settings.importEmbyUsers || this.settings.importPlexUsers) {
this.enableImportButton = true;
}
this.settingsService.saveUserManagementSettings(this.settings).subscribe(x => { this.settingsService.saveUserManagementSettings(this.settings).subscribe(x => {
if (x === true) { if (x === true) {
@ -101,6 +111,7 @@ export class UserManagementComponent implements OnInit {
} }
public runImporter(): void { public runImporter(): void {
this.jobService.runPlexImporter().subscribe(); this.jobService.runPlexImporter().subscribe();
this.jobService.runEmbyImporter().subscribe(); this.jobService.runEmbyImporter().subscribe();
} }

Loading…
Cancel
Save