From 1b6945c27bbc2f3b4c348942341feab670b60d3b Mon Sep 17 00:00:00 2001 From: Avi Date: Wed, 4 Apr 2018 15:54:19 -0500 Subject: [PATCH 001/495] Fix broken images and new discord invite --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9b0e212e1..f3b4a0e8c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ ![](http://i.imgur.com/qQsN78U.png) ____ -[![Discord](https://img.shields.io/discord/102860784329052160.svg)](https://discord.gg/KxYZ64w) +[![Discord](https://img.shields.io/discord/102860784329052160.svg)](https://discord.gg/Sa7wNWb) [![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/ombi.svg)](https://hub.docker.com/r/linuxserver/ombi/) [![Github All Releases](https://img.shields.io/github/downloads/tidusjar/Ombi/total.svg)](https://github.com/tidusjar/Ombi) [![firsttimersonly](http://img.shields.io/badge/first--timers--only-friendly-blue.svg?style=flat-square)](http://www.firsttimersonly.com/) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/ombi/localized.svg)](https://crowdin.com/project/ombi) -[![Patreon](https://www.ombi.io/img/patreondonate.svg)](https://patreon.com/tidusjar/Ombi) -[![Paypal](https://www.ombi.io/img/paypaldonate.svg)](https://paypal.me/PlexRequestsNet) +[![Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://patreon.com/tidusjar/Ombi) +[![Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://paypal.me/PlexRequestsNet) ___ From 6b7f5e9ef4352c785711baa473374b11815d89ba Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 4 Apr 2018 22:21:59 +0100 Subject: [PATCH 002/495] Update about.component.html Updated the Discord link in the settings page --- src/Ombi/ClientApp/app/settings/about/about.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/about/about.component.html b/src/Ombi/ClientApp/app/settings/about/about.component.html index 6ad185c54..578cf36f8 100644 --- a/src/Ombi/ClientApp/app/settings/about/about.component.html +++ b/src/Ombi/ClientApp/app/settings/about/about.component.html @@ -38,7 +38,7 @@ Discord - https://discord.gg/KxYZ64w + https://discord.gg/KxYZ64w From 5cc030b23704284f808b1f96e995fa0fce597952 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 4 Apr 2018 22:22:45 +0100 Subject: [PATCH 003/495] Update about.component.html !wip --- src/Ombi/ClientApp/app/settings/about/about.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/about/about.component.html b/src/Ombi/ClientApp/app/settings/about/about.component.html index 578cf36f8..e05677c0f 100644 --- a/src/Ombi/ClientApp/app/settings/about/about.component.html +++ b/src/Ombi/ClientApp/app/settings/about/about.component.html @@ -38,7 +38,7 @@ Discord - https://discord.gg/KxYZ64w + https://discord.gg/ From 5693eda243c4a55f65a2895102eb8224f36718f5 Mon Sep 17 00:00:00 2001 From: Avi Date: Wed, 4 Apr 2018 16:35:44 -0500 Subject: [PATCH 004/495] Fix discord current user count --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3b4a0e8c..c4c0c4029 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![](http://i.imgur.com/qQsN78U.png) ____ -[![Discord](https://img.shields.io/discord/102860784329052160.svg)](https://discord.gg/Sa7wNWb) +[![Discord](https://img.shields.io/discord/270828201473736705.svg)](https://discord.gg/Sa7wNWb) [![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/ombi.svg)](https://hub.docker.com/r/linuxserver/ombi/) [![Github All Releases](https://img.shields.io/github/downloads/tidusjar/Ombi/total.svg)](https://github.com/tidusjar/Ombi) [![firsttimersonly](http://img.shields.io/badge/first--timers--only-friendly-blue.svg?style=flat-square)](http://www.firsttimersonly.com/) From 754ba3247fe7f779c96f76e8194deca3088b0ebd Mon Sep 17 00:00:00 2001 From: Louis Laureys Date: Thu, 5 Apr 2018 03:06:37 +0200 Subject: [PATCH 005/495] The fact that this button has another style really bothers me. Not anymore! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4c0c4029..1c2dc9559 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ____ [![Discord](https://img.shields.io/discord/270828201473736705.svg)](https://discord.gg/Sa7wNWb) [![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/ombi.svg)](https://hub.docker.com/r/linuxserver/ombi/) [![Github All Releases](https://img.shields.io/github/downloads/tidusjar/Ombi/total.svg)](https://github.com/tidusjar/Ombi) -[![firsttimersonly](http://img.shields.io/badge/first--timers--only-friendly-blue.svg?style=flat-square)](http://www.firsttimersonly.com/) +[![firsttimersonly](http://img.shields.io/badge/first--timers--only-friendly-blue.svg)](http://www.firsttimersonly.com/) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/ombi/localized.svg)](https://crowdin.com/project/ombi) [![Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://patreon.com/tidusjar/Ombi) From acb62f476882307ee8f11981e2a7e064ed5d4a58 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 6 Apr 2018 21:36:54 +0100 Subject: [PATCH 006/495] Added the ability to turn off TV or Movies from the newsletter --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 6 +++--- .../Models/Notifications/NewsletterSettings.cs | 2 ++ .../ClientApp/app/interfaces/INotificationSettings.ts | 2 ++ .../settings/notifications/newsletter.component.html | 10 ++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index d8629e410..28db7bff2 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -229,20 +229,20 @@ namespace Ombi.Schedule.Jobs.Ombi return resolver.ParseMessage(template, curlys); } - private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, IQueryable plexEpisodes, IQueryable embyEp) + private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, IQueryable plexEpisodes, IQueryable embyEp, NewsletterSettings settings) { var sb = new StringBuilder(); var plexMovies = plexContentToSend.Where(x => x.Type == PlexMediaTypeEntity.Movie); var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie); - if (plexMovies.Any() || embyMovies.Any()) + if ((plexMovies.Any() || embyMovies.Any()) && !settings.DisableMovies) { sb.Append("

New Movies:



"); await ProcessPlexMovies(plexMovies, sb); await ProcessEmbyMovies(embyMovies, sb); } - if (plexEpisodes.Any() || embyEp.Any()) + if ((plexEpisodes.Any() || embyEp.Any()) && !settings.DisableTv) { sb.Append("

New Episodes:



"); await ProcessPlexTv(plexEpisodes, sb); diff --git a/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs index 380e2d743..0fed1418e 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs @@ -2,6 +2,8 @@ { public class NewsletterSettings : Settings { + public bool DisableTv { get; set; } + public bool DisableMovies { get; set; } public bool Enabled { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts index a7944f1a2..5105ef13c 100644 --- a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts @@ -57,6 +57,8 @@ export interface IDiscordNotifcationSettings extends INotificationSettings { export interface INewsletterNotificationSettings extends INotificationSettings { notificationTemplate: INotificationTemplates; + disableMovies: boolean; + disableTv: boolean; } export interface ITelegramNotifcationSettings extends INotificationSettings { diff --git a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html index 19ab565b6..b2c9ea179 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html +++ b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html @@ -9,6 +9,16 @@
+ +
+
+ +
+
+
+
+ +
From 20a9720fdd5b0d6e6e2a5303f5d4950a9dd4ac96 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 6 Apr 2018 21:51:31 +0100 Subject: [PATCH 007/495] Fixed build !wip --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 28db7bff2..8d95d2e44 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -100,11 +100,11 @@ namespace Ombi.Schedule.Jobs.Ombi var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10); var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10); - body = await BuildHtml(plexm, embym, plext, embyt); + body = await BuildHtml(plexm, embym, plext, embyt, settings); } else { - body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend); + body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, settings); if (body.IsNullOrEmpty()) { return; From 3aad8bbe6bf399e48a45db7eaf14b54db49da1a6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 6 Apr 2018 22:49:25 +0100 Subject: [PATCH 008/495] Made some improvements to the Sonarr Sync job #2127 --- src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index 8e13d6f9e..5ee55d167 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; +using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; @@ -43,14 +45,15 @@ namespace Ombi.Schedule.Jobs.Sonarr var series = await _api.GetSeries(settings.ApiKey, settings.FullUri); if (series != null) { - var sonarrSeries = series as IList ?? series.ToList(); + var sonarrSeries = series as ImmutableHashSet ?? series.ToImmutableHashSet(); var ids = sonarrSeries.Select(x => x.tvdbId); await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SonarrCache"); - var entites = ids.Select(id => new SonarrCache { TvDbId = id }).ToList(); + var entites = ids.Select(id => new SonarrCache { TvDbId = id }).ToImmutableHashSet(); await _ctx.SonarrCache.AddRangeAsync(entites); - + entites.Clear(); + await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SonarrEpisodeCache"); foreach (var s in sonarrSeries) { @@ -67,10 +70,10 @@ namespace Ombi.Schedule.Jobs.Sonarr TvDbId = s.tvdbId, HasFile = episode.hasFile })); + _log.LogDebug("Commiting the transaction"); + await _ctx.SaveChangesAsync(); } - _log.LogDebug("Commiting the transaction"); - await _ctx.SaveChangesAsync(); } } catch (Exception e) From 4d285b071e3364ee74443d214579b571e3294da7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 6 Apr 2018 23:28:14 +0100 Subject: [PATCH 009/495] Update node version !wip --- appveyor.yml | 2 +- src/Ombi/package-lock.json | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c513c650e..cb4af6921 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ version: 3.0.{build} configuration: Release os: Visual Studio 2017 environment: - nodejs_version: "7.8.0" + nodejs_version: "9.9.0" install: # Get the latest stable version of Node.js or io.js diff --git a/src/Ombi/package-lock.json b/src/Ombi/package-lock.json index e3ef65167..f5e18da7b 100644 --- a/src/Ombi/package-lock.json +++ b/src/Ombi/package-lock.json @@ -12344,7 +12344,8 @@ "uglify-to-browserify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=" + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true }, "uglifyjs-webpack-plugin": { "version": "1.1.8", @@ -12945,7 +12946,7 @@ "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", "requires": { "execa": "0.7.0", "lcid": "1.0.0", @@ -12987,7 +12988,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" From 9428c668251c20c2f81e2085731cab796108681a Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 6 Apr 2018 23:31:05 +0100 Subject: [PATCH 010/495] Fixed node version !wip --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index cb4af6921..9d97046d5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,7 @@ version: 3.0.{build} configuration: Release os: Visual Studio 2017 environment: - nodejs_version: "9.9.0" + nodejs_version: "Current" install: # Get the latest stable version of Node.js or io.js From daaf52d771c29d056076818a32634f788972010e Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 6 Apr 2018 23:56:31 +0100 Subject: [PATCH 011/495] Memory improvements --- src/Ombi.Schedule/JobSetup.cs | 36 +++++++++++++++++++++++++++++++++-- src/Ombi/Startup.cs | 9 ++++++--- src/Ombi/StartupExtensions.cs | 4 ++++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index 85b842d27..b328e6daf 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -1,4 +1,5 @@ -using Hangfire; +using System; +using Hangfire; using Ombi.Core.Settings; using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs.Couchpotato; @@ -12,7 +13,7 @@ using Ombi.Settings.Settings.Models; namespace Ombi.Schedule { - public class JobSetup : IJobSetup + public class JobSetup : IJobSetup, IDisposable { public JobSetup(IPlexContentSync plexContentSync, IRadarrSync radarrSync, IOmbiAutomaticUpdater updater, IEmbyContentSync embySync, IPlexUserImporter userImporter, @@ -65,5 +66,36 @@ namespace Ombi.Schedule RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); } + + + private bool _disposed; + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + _plexContentSync?.Dispose(); + _radarrSync?.Dispose(); + _updater?.Dispose(); + _plexUserImporter?.Dispose(); + _embyContentSync?.Dispose(); + _embyUserImporter?.Dispose(); + _sonarrSync?.Dispose(); + _cpCache?.Dispose(); + _srSync?.Dispose(); + _jobSettings?.Dispose(); + _refreshMetadata?.Dispose(); + _newsletter?.Dispose(); + } + _disposed = true; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } } } diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 1d7d67550..4aaadacb6 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -11,6 +11,7 @@ using Hangfire; using Hangfire.Console; using Hangfire.Dashboard; using Hangfire.SQLite; +using Microsoft.ApplicationInsights.Extensibility; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; @@ -85,7 +86,7 @@ namespace Ombi // This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) { - + TelemetryConfiguration.Active.DisableTelemetry = true; // Add framework services. services.AddDbContext(); @@ -183,12 +184,12 @@ namespace Ombi Authorization = new[] { new HangfireAuthorizationFilter() } }); GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 3 }); - + // Setup the scheduler var jobSetup = app.ApplicationServices.GetService(); jobSetup.Setup(); ctx.Seed(); - + var provider = new FileExtensionContentTypeProvider { Mappings = { [".map"] = "application/octet-stream" } }; app.UseStaticFiles(new StaticFileOptions() @@ -218,6 +219,8 @@ namespace Ombi name: "spa-fallback", defaults: new { controller = "Home", action = "Index" }); }); + + ombiService.Dispose(); } } diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index e4dae18e4..1c8f54b4e 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -168,6 +168,7 @@ namespace Ombi if (user == null) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + context.Response.RegisterForDispose(um); await context.Response.WriteAsync("Invalid User Access Token"); } else @@ -177,6 +178,7 @@ namespace Ombi var roles = await um.GetRolesAsync(user); var principal = new GenericPrincipal(identity, roles.ToArray()); context.User = principal; + context.Response.RegisterForDispose(um); await next(); } } @@ -189,6 +191,7 @@ namespace Ombi if (!valid) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + context.Response.RegisterForDispose(settingsProvider); await context.Response.WriteAsync("Invalid API Key"); } else @@ -196,6 +199,7 @@ namespace Ombi var identity = new GenericIdentity("API"); var principal = new GenericPrincipal(identity, new[] { "Admin", "ApiUser" }); context.User = principal; + context.Response.RegisterForDispose(settingsProvider); await next(); } } From 386f5b155091b6afb318de0443da128c30a47294 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 6 Apr 2018 23:56:57 +0100 Subject: [PATCH 012/495] Emby improvments on the way we sync/cache the data. --- .../Rule/Search/EmbyAvailabilityRuleTests.cs | 4 +- src/Ombi.Core/Engine/RecentlyAddedEngine.cs | 8 +- .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 6 +- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 27 +- .../Jobs/Emby/EmbyContentSync.cs | 30 +- .../Jobs/Emby/EmbyEpisodeSync.cs | 12 +- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 25 +- .../Jobs/Ombi/RefreshMetadata.cs | 84 +- src/Ombi.Store/Entities/EmbyContent.cs | 7 + src/Ombi.Store/Entities/EmbyEpisode.cs | 6 + .../20180406224743_EmbyMetadata.Designer.cs | 948 ++++++++++++++++++ .../Migrations/20180406224743_EmbyMetadata.cs | 69 ++ .../Migrations/OmbiContextModelSnapshot.cs | 12 + .../Repository/EmbyContentRepository.cs | 50 +- .../Repository/IEmbyContentRepository.cs | 12 +- 15 files changed, 1221 insertions(+), 79 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20180406224743_EmbyMetadata.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180406224743_EmbyMetadata.cs diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs index a7f20ac40..0633d641e 100644 --- a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -25,7 +25,7 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_Available_WhenFoundInEmby() { - ContextMock.Setup(x => x.Get(It.IsAny())).ReturnsAsync(new EmbyContent + ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).ReturnsAsync(new EmbyContent { ProviderId = "123" }); @@ -39,7 +39,7 @@ namespace Ombi.Core.Tests.Rule.Search [Test] public async Task Movie_ShouldBe_NotAvailable_WhenNotFoundInEmby() { - ContextMock.Setup(x => x.Get(It.IsAny())).Returns(Task.FromResult(default(EmbyContent))); + ContextMock.Setup(x => x.GetByTheMovieDbId(It.IsAny())).Returns(Task.FromResult(default(EmbyContent))); var search = new SearchMovieViewModel(); var result = await Rule.Execute(search); diff --git a/src/Ombi.Core/Engine/RecentlyAddedEngine.cs b/src/Ombi.Core/Engine/RecentlyAddedEngine.cs index 59be359f8..8782ea028 100644 --- a/src/Ombi.Core/Engine/RecentlyAddedEngine.cs +++ b/src/Ombi.Core/Engine/RecentlyAddedEngine.cs @@ -152,7 +152,9 @@ namespace Ombi.Core.Engine model.Add(new RecentlyAddedMovieModel { Id = emby.Id, - ImdbId = emby.ProviderId, + ImdbId = emby.ImdbId, + TheMovieDbId = emby.TheMovieDbId, + TvDbId = emby.TvDbId, AddedAt = emby.AddedAt, Title = emby.Title, }); @@ -211,7 +213,9 @@ namespace Ombi.Core.Engine model.Add(new RecentlyAddedTvModel { Id = emby.Id, - ImdbId = emby.ProviderId, + ImdbId = emby.ImdbId, + TvDbId = emby.TvDbId, + TheMovieDbId = emby.TheMovieDbId, AddedAt = emby.AddedAt, Title = emby.Title, EpisodeNumber = episode.EpisodeNumber, diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 74b537352..8ac96701d 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -23,20 +23,20 @@ namespace Ombi.Core.Rule.Rules.Search EmbyContent item = null; if (obj.ImdbId.HasValue()) { - item = await EmbyContentRepository.Get(obj.ImdbId); + item = await EmbyContentRepository.GetByImdbId(obj.ImdbId); } if (item == null) { if (obj.TheMovieDbId.HasValue()) { - item = await EmbyContentRepository.Get(obj.TheMovieDbId); + item = await EmbyContentRepository.GetByTheMovieDbId(obj.TheMovieDbId); } if (item == null) { if (obj.TheTvDbId.HasValue()) { - item = await EmbyContentRepository.Get(obj.TheTvDbId); + item = await EmbyContentRepository.GetByTvDbId(obj.TheTvDbId); } } } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index af5f58cb4..59b5adc96 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -70,7 +70,16 @@ namespace Ombi.Schedule.Jobs.Emby foreach (var movie in movies) { - var embyContent = await _repo.Get(movie.ImdbId); + EmbyContent embyContent = null; + if (movie.TheMovieDbId > 0) + { + embyContent = await _repo.GetByTheMovieDbId(movie.TheMovieDbId.ToString()); + } + else if(movie.ImdbId.HasValue()) + { + embyContent = await _repo.GetByImdbId(movie.ImdbId); + } + if (embyContent == null) { // We don't have this yet @@ -112,8 +121,20 @@ namespace Ombi.Schedule.Jobs.Emby foreach (var child in tv) { - var tvDbId = child.ParentRequest.TvDbId; - var seriesEpisodes = embyEpisodes.Where(x => x.Series.ProviderId == tvDbId.ToString()); + IQueryable seriesEpisodes; + if (child.ParentRequest.TvDbId > 0) + { + seriesEpisodes = embyEpisodes.Where(x => x.Series.TvDbId == child.ParentRequest.TvDbId.ToString()); + } + else if(child.ParentRequest.ImdbId.HasValue()) + { + seriesEpisodes = embyEpisodes.Where(x => x.Series.ImdbId == child.ParentRequest.ImdbId); + } + else + { + continue; + } + foreach (var season in child.SeasonRequests) { foreach (var episode in season.Episodes) diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 9d054ea7c..99d4f5a85 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -38,12 +38,21 @@ namespace Ombi.Schedule.Jobs.Emby public async Task Start() { - var embySettings = await _settings.GetSettingsAsync(); + var embySettings = await _settings.GetSettingsAsync(); if (!embySettings.Enable) return; foreach (var server in embySettings.Servers) - await StartServerCache(server); + { + try + { + await StartServerCache(server); + } + catch (Exception e) + { + _logger.LogError(e, "Exception when caching Emby for server {0}", server.Name); + } + } // Episodes BackgroundJob.Enqueue(() => _episodeSync.Start()); @@ -55,8 +64,11 @@ namespace Ombi.Schedule.Jobs.Emby if (!ValidateSettings(server)) return; + await _repo.ExecuteSql("DELETE FROM EmbyEpisode"); + await _repo.ExecuteSql("DELETE FROM EmbyContent"); + var movies = await _api.GetAllMovies(server.ApiKey, server.AdministratorId, server.FullUri); - var mediaToAdd = new List(); + var mediaToAdd = new HashSet(); foreach (var movie in movies.Items) { if (movie.Type.Equals("boxset", StringComparison.CurrentCultureIgnoreCase)) @@ -96,7 +108,9 @@ namespace Ombi.Schedule.Jobs.Emby if (existingTv == null) mediaToAdd.Add(new EmbyContent { - ProviderId = tvInfo.ProviderIds.Tvdb, + TvDbId = tvInfo.ProviderIds?.Tvdb, + ImdbId = tvInfo.ProviderIds?.Imdb, + TheMovieDbId = tvInfo.ProviderIds?.Tmdb, Title = tvInfo.Name, Type = EmbyMediaType.Series, EmbyId = tvShow.Id, @@ -110,18 +124,14 @@ namespace Ombi.Schedule.Jobs.Emby private async Task ProcessMovies(MovieInformation movieInfo, ICollection content) { - if (string.IsNullOrEmpty(movieInfo.ProviderIds.Imdb)) - { - Log.Error("Provider Id on movie {0} is null", movieInfo.Name); - return; - } // Check if it exists var existingMovie = await _repo.GetByEmbyId(movieInfo.Id); if (existingMovie == null) content.Add(new EmbyContent { - ProviderId = movieInfo.ProviderIds.Imdb, + ImdbId = movieInfo.ProviderIds.Imdb, + TheMovieDbId = movieInfo.ProviderIds?.Tmdb, Title = movieInfo.Name, Type = EmbyMediaType.Movie, EmbyId = movieInfo.Id, diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index 749abd761..df00a37e6 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -85,10 +85,10 @@ namespace Ombi.Schedule.Jobs.Emby } var epInfo = await _api.GetEpisodeInformation(ep.Id, server.ApiKey, server.AdministratorId, server.FullUri); - if (epInfo?.ProviderIds?.Tvdb == null) - { - continue; - } + //if (epInfo?.ProviderIds?.Tvdb == null) + //{ + // continue; + //} // Let's make sure we have the parent request, stop those pesky forign key errors, // Damn me having data integrity @@ -109,7 +109,9 @@ namespace Ombi.Schedule.Jobs.Emby EpisodeNumber = ep.IndexNumber, SeasonNumber = ep.ParentIndexNumber, ParentId = ep.SeriesId, - ProviderId = epInfo.ProviderIds.Tvdb, + TvDbId = epInfo.ProviderIds.Tvdb, + TheMovieDbId = epInfo.ProviderIds.Tmdb, + ImdbId = epInfo.ProviderIds.Imdb, Title = ep.Name, AddedAt = DateTime.UtcNow }); diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 8d95d2e44..31138e012 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -292,14 +292,21 @@ namespace Ombi.Schedule.Jobs.Ombi var ordered = embyContent.OrderByDescending(x => x.AddedAt); foreach (var content in ordered) { - var imdbId = content.ProviderId; - var findResult = await _movieApi.Find(imdbId, ExternalSource.imdb_id); - var result = findResult.movie_results?.FirstOrDefault(); - if(result == null) + var theMovieDbId = content.TheMovieDbId; + if (!content.TheMovieDbId.HasValue()) { - continue; + var imdbId = content.ImdbId; + var findResult = await _movieApi.Find(imdbId, ExternalSource.imdb_id); + var result = findResult.movie_results?.FirstOrDefault(); + if (result == null) + { + continue; + } + + theMovieDbId = result.id.ToString(); } - var info = await _movieApi.GetMovieInformationWithExtraInfo(result.id); + + var info = await _movieApi.GetMovieInformationWithExtraInfo(int.Parse(theMovieDbId)); if (info == null) { continue; @@ -503,7 +510,11 @@ namespace Ombi.Schedule.Jobs.Ombi { try { - int.TryParse(t.ProviderId, out var tvdbId); + if (!t.TvDbId.HasValue()) + { + continue; + } + int.TryParse(t.TvDbId, out var tvdbId); var info = await _tvApi.ShowLookupByTheTvDbId(tvdbId); if (info == null) { diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 225efb7d3..9d073facf 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -10,7 +10,6 @@ using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; -using Ombi.Store.Repository.Requests; namespace Ombi.Schedule.Jobs.Ombi { @@ -44,6 +43,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (settings.Enable) { await StartPlex(); + await StartEmby(); } } catch (Exception e) @@ -61,6 +61,12 @@ namespace Ombi.Schedule.Jobs.Ombi await StartPlexTv(); } + private async Task StartEmby() + { + await StartEmbyMovies(); + await StartEmbyTv(); + } + private async Task StartPlexTv() { var allTv = _plexRepo.GetAll().Where(x => @@ -101,6 +107,46 @@ namespace Ombi.Schedule.Jobs.Ombi await _plexRepo.SaveChangesAsync(); } + private async Task StartEmbyTv() + { + var allTv = _embyRepo.GetAll().Where(x => + x.Type == EmbyMediaType.Series && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue())); + var tvCount = 0; + foreach (var show in allTv) + { + var hasImdb = show.ImdbId.HasValue(); + var hasTheMovieDb = show.TheMovieDbId.HasValue(); + var hasTvDbId = show.TvDbId.HasValue(); + + if (!hasTheMovieDb) + { + var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title); + show.TheMovieDbId = id; + } + + if (!hasImdb) + { + var id = await GetImdbId(hasTheMovieDb, hasTvDbId, show.Title, show.TheMovieDbId, show.TvDbId); + show.ImdbId = id; + _embyRepo.UpdateWithoutSave(show); + } + + if (!hasTvDbId) + { + var id = await GetTvDbId(hasTheMovieDb, hasImdb, show.TheMovieDbId, show.ImdbId, show.Title); + show.TvDbId = id; + _embyRepo.UpdateWithoutSave(show); + } + tvCount++; + if (tvCount >= 20) + { + await _embyRepo.SaveChangesAsync(); + tvCount = 0; + } + } + await _embyRepo.SaveChangesAsync(); + } + private async Task StartPlexMovies() { var allMovies = _plexRepo.GetAll().Where(x => @@ -135,7 +181,41 @@ namespace Ombi.Schedule.Jobs.Ombi await _plexRepo.SaveChangesAsync(); } - private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title) + private async Task StartEmbyMovies() + { + var allMovies = _embyRepo.GetAll().Where(x => + x.Type == EmbyMediaType.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue())); + int movieCount = 0; + foreach (var movie in allMovies) + { + var hasImdb = movie.ImdbId.HasValue(); + var hasTheMovieDb = movie.TheMovieDbId.HasValue(); + // Movies don't really use TheTvDb + + if (!hasImdb) + { + var imdbId = await GetImdbId(hasTheMovieDb, false, movie.Title, movie.TheMovieDbId, string.Empty); + movie.ImdbId = imdbId; + _embyRepo.UpdateWithoutSave(movie); + } + if (!hasTheMovieDb) + { + var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title); + movie.TheMovieDbId = id; + _embyRepo.UpdateWithoutSave(movie); + } + movieCount++; + if (movieCount >= 20) + { + await _embyRepo.SaveChangesAsync(); + movieCount = 0; + } + } + + await _embyRepo.SaveChangesAsync(); + } + + private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title) { _log.LogInformation("The Media item {0} does not have a TheMovieDbId, searching for TheMovieDbId", title); FindResult result = null; diff --git a/src/Ombi.Store/Entities/EmbyContent.cs b/src/Ombi.Store/Entities/EmbyContent.cs index d9d6e6983..1d3f57f13 100644 --- a/src/Ombi.Store/Entities/EmbyContent.cs +++ b/src/Ombi.Store/Entities/EmbyContent.cs @@ -36,11 +36,18 @@ namespace Ombi.Store.Entities { public string Title { get; set; } + /// + /// OBSOLETE, Cannot delete due to DB migration issues with SQLite + /// public string ProviderId { get; set; } public string EmbyId { get; set; } public EmbyMediaType Type { get; set; } public DateTime AddedAt { get; set; } + public string ImdbId { get; set; } + public string TheMovieDbId { get; set; } + public string TvDbId { get; set; } + public ICollection Episodes { get; set; } } diff --git a/src/Ombi.Store/Entities/EmbyEpisode.cs b/src/Ombi.Store/Entities/EmbyEpisode.cs index 150829240..e4e5b6a4b 100644 --- a/src/Ombi.Store/Entities/EmbyEpisode.cs +++ b/src/Ombi.Store/Entities/EmbyEpisode.cs @@ -39,8 +39,14 @@ namespace Ombi.Store.Entities public int EpisodeNumber { get; set; } public int SeasonNumber { get; set; } public string ParentId { get; set; } + /// + /// NOT USED + /// public string ProviderId { get; set; } public DateTime AddedAt { get; set; } + public string TvDbId { get; set; } + public string ImdbId { get; set; } + public string TheMovieDbId { get; set; } public EmbyContent Series { get; set; } } diff --git a/src/Ombi.Store/Migrations/20180406224743_EmbyMetadata.Designer.cs b/src/Ombi.Store/Migrations/20180406224743_EmbyMetadata.Designer.cs new file mode 100644 index 000000000..644119ea0 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180406224743_EmbyMetadata.Designer.cs @@ -0,0 +1,948 @@ +// +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 Ombi.Store.Entities.Requests; +using System; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180406224743_EmbyMetadata")] + partial class EmbyMetadata + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + 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 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180406224743_EmbyMetadata.cs b/src/Ombi.Store/Migrations/20180406224743_EmbyMetadata.cs new file mode 100644 index 000000000..b7f98525d --- /dev/null +++ b/src/Ombi.Store/Migrations/20180406224743_EmbyMetadata.cs @@ -0,0 +1,69 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace Ombi.Store.Migrations +{ + public partial class EmbyMetadata : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ImdbId", + table: "EmbyEpisode", + nullable: true); + + migrationBuilder.AddColumn( + name: "TheMovieDbId", + table: "EmbyEpisode", + nullable: true); + + migrationBuilder.AddColumn( + name: "TvDbId", + table: "EmbyEpisode", + nullable: true); + + migrationBuilder.AddColumn( + name: "ImdbId", + table: "EmbyContent", + nullable: true); + + migrationBuilder.AddColumn( + name: "TheMovieDbId", + table: "EmbyContent", + nullable: true); + + migrationBuilder.AddColumn( + name: "TvDbId", + table: "EmbyContent", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ImdbId", + table: "EmbyEpisode"); + + migrationBuilder.DropColumn( + name: "TheMovieDbId", + table: "EmbyEpisode"); + + migrationBuilder.DropColumn( + name: "TvDbId", + table: "EmbyEpisode"); + + migrationBuilder.DropColumn( + name: "ImdbId", + table: "EmbyContent"); + + migrationBuilder.DropColumn( + name: "TheMovieDbId", + table: "EmbyContent"); + + migrationBuilder.DropColumn( + name: "TvDbId", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index a24aa583a..19e14a4ca 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -185,10 +185,16 @@ namespace Ombi.Store.Migrations b.Property("EmbyId") .IsRequired(); + b.Property("ImdbId"); + b.Property("ProviderId"); + b.Property("TheMovieDbId"); + b.Property("Title"); + b.Property("TvDbId"); + b.Property("Type"); b.HasKey("Id"); @@ -207,14 +213,20 @@ namespace Ombi.Store.Migrations b.Property("EpisodeNumber"); + b.Property("ImdbId"); + b.Property("ParentId"); b.Property("ProviderId"); b.Property("SeasonNumber"); + b.Property("TheMovieDbId"); + b.Property("Title"); + b.Property("TvDbId"); + b.HasKey("Id"); b.HasIndex("ParentId"); diff --git a/src/Ombi.Store/Repository/EmbyContentRepository.cs b/src/Ombi.Store/Repository/EmbyContentRepository.cs index 280243455..c4377f929 100644 --- a/src/Ombi.Store/Repository/EmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/EmbyContentRepository.cs @@ -35,42 +35,28 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public class EmbyContentRepository : IEmbyContentRepository + public class EmbyContentRepository : Repository, IEmbyContentRepository { - public EmbyContentRepository(IOmbiContext db) + public EmbyContentRepository(IOmbiContext db):base(db) { Db = db; } private IOmbiContext Db { get; } - public IQueryable GetAll() + + public async Task GetByImdbId(string imdbid) { - return Db.EmbyContent.AsQueryable(); + return await Db.EmbyContent.FirstOrDefaultAsync(x => x.ImdbId == imdbid); } - - public async Task AddRange(IEnumerable content) + public async Task GetByTvDbId(string tv) { - Db.EmbyContent.AddRange(content); - await Db.SaveChangesAsync(); + return await Db.EmbyContent.FirstOrDefaultAsync(x => x.TvDbId == tv); } - - public async Task ContentExists(string providerId) + public async Task GetByTheMovieDbId(string mov) { - return await Db.EmbyContent.AnyAsync(x => x.ProviderId == providerId); - } - - public async Task Add(EmbyContent content) - { - await Db.EmbyContent.AddAsync(content); - await Db.SaveChangesAsync(); - return content; - } - - public async Task Get(string providerId) - { - return await Db.EmbyContent.FirstOrDefaultAsync(x => x.ProviderId == providerId); + return await Db.EmbyContent.FirstOrDefaultAsync(x => x.TheMovieDbId == mov); } public IQueryable Get() @@ -111,23 +97,9 @@ namespace Ombi.Store.Repository await Db.SaveChangesAsync(); } - private bool _disposed; - protected virtual void Dispose(bool disposing) + public void UpdateWithoutSave(EmbyContent existingContent) { - if (_disposed) - return; - - if (disposing) - { - Db?.Dispose(); - } - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); + Db.EmbyContent.Update(existingContent); } } } \ No newline at end of file diff --git a/src/Ombi.Store/Repository/IEmbyContentRepository.cs b/src/Ombi.Store/Repository/IEmbyContentRepository.cs index 3ed8d8abd..a893e9aca 100644 --- a/src/Ombi.Store/Repository/IEmbyContentRepository.cs +++ b/src/Ombi.Store/Repository/IEmbyContentRepository.cs @@ -6,19 +6,19 @@ using Ombi.Store.Entities; namespace Ombi.Store.Repository { - public interface IEmbyContentRepository : IDisposable + public interface IEmbyContentRepository : IRepository { - Task Add(EmbyContent content); - Task AddRange(IEnumerable content); - Task ContentExists(string providerId); IQueryable Get(); - Task Get(string providerId); - IQueryable GetAll(); + Task GetByTheMovieDbId(string mov); + Task GetByTvDbId(string tv); + Task GetByImdbId(string imdbid); Task GetByEmbyId(string embyId); Task Update(EmbyContent existingContent); IQueryable GetAllEpisodes(); Task Add(EmbyEpisode content); Task GetEpisodeByEmbyId(string key); Task AddRange(IEnumerable content); + + void UpdateWithoutSave(EmbyContent existingContent); } } \ No newline at end of file From 5942645045a3469bf53aa77b45c1feb8e27974f6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 7 Apr 2018 00:26:05 +0100 Subject: [PATCH 013/495] Added the ability to send newsletter out to users that are not in Ombi --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 10 ++++++++ .../Notifications/NewsletterSettings.cs | 5 +++- .../app/interfaces/INotificationSettings.ts | 1 + .../notifications/newsletter.component.html | 25 +++++++++++++++++++ .../notifications/newsletter.component.ts | 21 ++++++++++++++++ 5 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 31138e012..1a8b21fbd 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using MailKit; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Ombi.Api.TheMovieDb; @@ -120,6 +121,15 @@ namespace Ombi.Schedule.Jobs.Ombi { return; } + + foreach (var emails in settings.ExternalEmails) + { + users.Add(new OmbiUser + { + UserName = emails, + Email = emails + }); + } var emailTasks = new List(); foreach (var user in users) { diff --git a/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs index 0fed1418e..f043cd74c 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs @@ -1,9 +1,12 @@ -namespace Ombi.Settings.Settings.Models.Notifications +using System.Collections.Generic; + +namespace Ombi.Settings.Settings.Models.Notifications { public class NewsletterSettings : Settings { public bool DisableTv { get; set; } public bool DisableMovies { get; set; } public bool Enabled { get; set; } + public List ExternalEmails { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts index 5105ef13c..da1e147da 100644 --- a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts @@ -59,6 +59,7 @@ export interface INewsletterNotificationSettings extends INotificationSettings { notificationTemplate: INotificationTemplates; disableMovies: boolean; disableTv: boolean; + externalEmails: string[]; } export interface ITelegramNotifcationSettings extends INotificationSettings { diff --git a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html index b2c9ea179..0a7c27b64 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html +++ b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.html @@ -53,6 +53,31 @@
When testing, the test newsletter will go to all users that have the Admin role, please ensure that there are valid email addresses for this. The test will also only grab the latest 10 movies and 10 shows just to give you an example. +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ {{email}} +
+
+ +
+
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts index 460c54955..fda23208f 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts +++ b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts @@ -11,6 +11,7 @@ export class NewsletterComponent implements OnInit { public NotificationType = NotificationType; public settings: INewsletterNotificationSettings; + public emailToAdd: string; constructor(private settingsService: SettingsService, private notificationService: NotificationService, @@ -48,4 +49,24 @@ export class NewsletterComponent implements OnInit { }); } + public addEmail() { + + if(this.emailToAdd) { + const emailRegex = "[a-zA-Z0-9.-_]{1,}@[a-zA-Z.-]{2,}[.]{1}[a-zA-Z]{2,}"; + const match = this.emailToAdd.match(emailRegex)!; + if(match && match.length > 0) { + this.settings.externalEmails.push(this.emailToAdd); + this.emailToAdd = ""; + } else{ + this.notificationService.error("Please enter a valid email address") + } + } + } + + public deleteEmail(email: string) { + var index = this.settings.externalEmails.indexOf(email); // <-- Not supported in Date: Sat, 7 Apr 2018 00:36:28 +0100 Subject: [PATCH 014/495] !wip changelog --- CHANGELOG.md | 3665 +------------------------------------------------- 1 file changed, 55 insertions(+), 3610 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea279eae7..63cc385a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,60 @@ # Changelog +## (unreleased) + +### **New Features** + +- Added the ability to send newsletter out to users that are not in Ombi. [Jamie] + +- Added the ability to turn off TV or Movies from the newsletter. [Jamie] + +- Update about.component.html. [Jamie] + +- Update about.component.html. [Jamie] + +- Added random versioning prefix to the translations so the users don't have to clear the cache. [Jamie] + +- Added more information to the about page. [Jamie] + +- Changed let to const to adhere to linting. [Anojh] + +- Update _Layout.cshtml. [goldenpipes] + +- Update _Layout.cshtml. [goldenpipes] + +- Changed the TV Request API. We now only require the TvDbId and the seasons and episodes that you want to request. This should make integration regarding TV a lot easier. [Jamie] + +### **Fixes** + +- Emby improvments on the way we sync/cache the data. [Jamie] + +- Memory improvements. [Jamie] + +- Made some improvements to the Sonarr Sync job #2127. [Jamie] + +- Fixed #2109. [Jamie] + +- Fixed #2101. [Jamie] + +- Fixed #2105. [Jamie] + +- Fixed some styling on the issues detail page. [Jamie] + +- Fixed #2116. [Jamie] + +- Limit the amount of FileSystemWatchers being spawned. [Jamie] + +- Fixed the issue where Emby connect users could not log in #2115. [Jamie] + +- Had to update some base styles since currently some styling does not look right... [Anojh] + +- Adding wrappers and classes for LC and toggling active style for UI elements. [Anojh] + +- Fixed a little bug in the newsletter. [Jamie] + +- Fixed the issue where movies were not appearing in the newsletter for users with Emby #2111. [Jamie] + + ## v3.0.3111 (2018-03-27) ### **New Features** @@ -732,3613 +787,3 @@ - Switch to use a single HTTPClient rather than a new one every request !dev. [tidusjar] -- Fix non-admin rights (#1820) [Rob Gkemeijer] - -- Fix duplicated "Requests" element ID on new Issues link (#1817) [Shoghi Cervantes] - -- Add the Issue Reporting functionality (#1811) [Jamie] - -- Removed the forum. [tidusjar] - -- #1659 Made the option to ignore notifcations for auto approve. [Jamie] - -- New Crowdin translations (#1806) [Jamie] - -- Fixed a launch issue. [Jamie] - -- Allow users to login without a password. [Jamie] - -- Fixed the emby notifications not being sent. [Jamie] - -- #1802 and other small fixes. [tidusjar] - -- So... This sickrage thing should work now. [tidusjar] - -- Fixed emby connect login issue. [tidusjar] - -- Stop making unnecessary calls to the update service. [Jamie] - -- Fixed a bug where it blocked users with 0 limits. [Jamie] - -- Done #1788. [tidusjar] - -- More logging. [Jamie] - -- Fixed #1738. [Jamie] - -- Fixed build. [Jamie] - -- Fixed the issue where notifications were not sendind unless we restarted #1732. [tidusjar] - -- Fixed an issue with a trailing space in the subdir. [tidusjar] - -- Fixed #1774. [Jamie] - -- #1773. [Jamie] - -- Roll back rxjs (#1778) [bazhip] - -- Fixed build. [Jamie] - -- Fixed #1763. [Jamie] - -- Fix "content length error" on preview gif (#1768) [OoGuru] - -- New preview gif for Ombi V3 README (#1767) [OoGuru] - -- Remove debug code. [tidusjar] - -- Fix #1762. [tidusjar] - -- Fixed the preset themes not loading. [tidusjar] - -- Fixed #1760 and improvements on the auto updater. We may now support windows services... #1460. [Jamie] - -- Fixed #1754. [Jamie] - -- Hide the subject when it's not being used. [Jamie] - -- Error handling #1749. [Jamie] - -- New Crowdin translations (#1741) [Jamie] - -- #1732 #1722 #1711. [Jamie] - -- Fixed an issue with switching the preset themes. [Jamie] - -- Fixed #1743. [Jamie] - -- Fixed #1742. [tidusjar] - -- Fix #1742. [tidusjar] - -- Fixed landing page. [Jamie] - -- Fixed. [Jamie] - -- Translated the Requests page and fixed #1740. [Jamie] - -- Fix crash. [Jamie] - -- Sickrage done. Ish... So i've written all the code by looking at the API. the key there is i've looked at the api. I have not tested anything so expect this to fail. [Jamie] - -- SickRage settings UI. [Jamie] - -- Fixed #1721. [tidusjar] - -- Fixed the preset themes issue. [tidusjar] - -- New Crowdin translations (#1654) [Jamie] - -- Fix build. [Jamie] - -- #1460. [Jamie] - -- Fixed tests. [Jamie] - -- Return css as MIME text/css. [Jamie] - -- More added for the preset themes. [Jamie] - -- Moved around the custom styles. [Jamie] - -- More renames. [Jamie] - -- Renames. [Jamie] - -- Load the first 100 requests. [Jamie] - -- Reduce the memory consumption #1720. [Jamie] - -- Moved the schedules jobs into it's own database, see if it helps with the db locking #1720. [Jamie] - -- Fixed #1712. [tidusjar] - -- Potential fix for #1702. [tidusjar] - -- Fixed #1708. [tidusjar] - -- Fixed #1677. [tidusjar] - -- Fixed build. [tidusjar] - -- Potential fix for the DB locking issue #1720. [tidusjar] - -- #1698. [Jamie] - -- Fixed #1705. [tidusjar] - -- Fixed #1703. [tidusjar] - -- Finished adding preset themes. [Jamie] - -- Fixed #17000. [Jamie] - -- Remove the themes because waiting for a merge from lerams project. [Jamie] - -- Finsihed adding preset themes. [Jamie] - -- Fixed #1677. [Jamie] - -- Temp fix for #1683. [Jamie] - -- Fixed #1685. [Jamie] - -- Lossless Compression of images saves 83 KB (#1676) [Fish2] - -- Fixed the availability checker. [tidusjar] - -- Fixed build. [tidusjar] - -- Push out missing migration. [tidusjar] - -- Potential fix for #1674. [tidusjar] - -- Fixed an issue with the caching. [tidusjar] - -- Fixed telegram #1667. [tidusjar] - -- Fixed #1663. [tidusjar] - -- Should fix #1663. [tidusjar] - -- Stop logged in users going to the login page. [Jamie] - -- Fixed it not updating. Styles should be good now. [Jamie] - -- Re did some of the styling on the movie search page, let me know your thoughts. [Jamie] - -- Fixed #1657. [Jamie] - -- Fixed #1655. [Jamie] - -- Removed authentication resul. [Jamie] - -- New Crowdin translations (#1651) [Jamie] - -- New Crowdin translations (#1648) [Jamie] - -- New Crowdin translations (#1638) [Jamie] - -- Fixed #1644. [Jamie] - -- Moar logs #1643. [tidusjar] - -- Fixed #1640. [tidusjar] - -- Fixed the null ref exception #1460. [tidusjar] - -- Fixed landing page. [TidusJar] - -- Fixed #1641. [TidusJar] - -- Fixed #1641. [TidusJar] - -- New Crowdin translations (#1635) [Jamie] - -- Fixed #1631 and improved translation support Included startup args for the auto updater #1460 Mark TV requests as available #1632. [tidusjar] - -- Remove 32bit. [Jamie] - -- More 32bit support. [Jamie] - -- We now show "Available" for tv shows that is fully available #1602. [tidusjar] - -- Fixed the issue where we have got an episode but not the related series. #1620. [tidusjar] - -- Fixed the dropdown not working on iOS in the settings #1615. [tidusjar] - -- Fixed sonarr not monitoring the latest season #1534. [tidusjar] - -- Fixed the issue with firefox #1544. [tidusjar] - -- Fixed discord #1623. [tidusjar] - -- Add browserstack thanks (#1627) [Matt Jeanes] - -- Fix the exception #1613. [Jamie] - -- Found where we potentially are setting a new poster path, looks like the entity was being modified and being set as Tracked by entity framework, so the next time we called SaveChangesAsync() it would save the new posterpath on the entity. [Jamie] - -- Small modifications. [Jamie] - -- Fixed #1622. [Jamie] - -- Various improvements to webpack/gulp/vscode support (#1617) [Matt Jeanes] - -- Episodes in requests are now in order #1597 (#1614) [masterhuck] - -- Fixed a null reference issue in the Plex Content Cacher. [Jamie.Rees] - -- Fixed #1610. [tidusjar] - -- Really fixed the build this time. [tidusjar] - -- Fixed build. [tidusjar] - -- Made the updater work again #1460. [tidusjar] - -- Adding logging into the auto updater and also added more logging around the create inital user for #1604. [tidusjar] - -- Fixed the issue where we did not check if they are already in sonarr when choosing certain options #1540. [tidusjar] - -- We can now delete tv child requests and the parent will get remove #1603. [tidusjar] - -- Finished the api changes requested #1601. [tidusjar] - -- Fixed the Hangfire server timeout issue #1605. [tidusjar] - -- Fixed notifications not sending #1594. [tidusjar] - -- Fixed #1583 you can now delete users. Fixed the issue where the requested by was not showing. Finally fixed the broken poster paths. [tidusjar] - -- Fixed the issue where movie requests were no longer being requested. [tidusjar] - -- Started adding some more unit tests #1596. [Jamie.Rees] - -- #1588 When we make changes to any requests that we can trigger a notification, always send it to all notification agents, even if the user wont recieve it. [Jamie.Rees] - -- Add a message when email notifications are not setup when requesting a password reset. #1590. [Jamie.Rees] - -- Removed text that we no longer need. [Jamie.Rees] - -- Fixed #1574. [Jamie.Rees] - -- #1460 looks like the permissions issue has been resolved. Just need to make sure the Ombi process is terminated. [Jamie.Rees] - -- Put back the old download code. [Jamie.Rees] - -- Test. [Jamie] - -- Build sln. [Jamie.Rees] - -- Order by the username #1581. [Jamie.Rees] - -- Remove sonarr episodes from the cache table. [Jamie.Rees] - -- Couchpotato finished. [tidusjar] - -- Disable run import button if no import options are selected. [tidusjar] - -- Fixed #1574. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixes the issue with non windows systems unable to unzip the tarball #1460. [tidusjar] - -- Finished the couchpotato settings. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed #1570 #1571. [tidusjar] - -- Fixed #1547. [tidusjar] - -- Should fix #1538. [tidusjar] - -- Fixed #1553. [tidusjar] - -- Fixed #1546. [tidusjar] - -- Fixed #1543. [tidusjar] - -- Fixes an issue with Movie caching not working on develop branch of Radarr (#1567) [Jeffrey Peters] - -- This adds two fields to the Email Notifications settings page. It allows for the disabling of TLS/SSL as well as the ability to disable certificate validation when sending notification emails. (#1552) [Jeffrey Peters] - -- Fixed typo (#1551) [Codehhh] - -- Use Sqlite storage for Hangfire. [tidusjar] - -- Fixed the overrides #1539 also display it on screen now too. [tidusjar] - -- Fixed #1542 also added VSCode support. [tidusjar] - -- Fixed some cosmetic issues #865. [Jamie.Rees] - -- Fixed #1531. [Jamie.Rees] - -- Small fixes #865. [Jamie.Rees] - -- Some errors fixed and some ui improvements #865. [tidusjar] - -- Auto-scale large images down to container size (#1529) [Avi] - -- Fix logo on login page. (#1528) [Avi] - -- Another potential issue? :/ [tidusjar] - -- Real fix. [tidusjar] - -- #1513 Added storage path. [Jamie.Rees] - -- Fixed the discord issue relating to images #1513. [Jamie.Rees] - -- Fixed the issue sending movies to Radarr #1513 Fixed typo #1524. [Jamie.Rees] - -- Fixed logo on reset password pages fixed the run importer button on the user management settings. [Jamie.Rees] - -- Fixed crash/error #865. [tidusjar] - -- #1513 fixed the landing page and also the reverse proxy images. [tidusjar] - -- #1513 correctly set the child requests as approved. [tidusjar] - -- Fixed an issue that potentially causes as issue when siging into plex #865. [tidusjar] - -- Remove dev branch. [PotatoQuality] - -- Prepare readme for upcoming beta. [PotatoQuality] - -- #1513 partially fixed a bug. [tidusjar] - -- Fixed the exception. [tidusjar] - -- Fixed the application url not saving #1513. [tidusjar] - -- Fixed liniting. [tidusjar] - -- REVERSE PROXY BITCH! #1513. [tidusjar] - -- Fixed a bug where we were marking the wrong episodes as available #1513 #865. [Jamie.Rees] - -- Fixed an issue where we messed up the pages and routing. [Jamie.Rees] - -- Emby user importer is now therer! #1456. [tidusjar] - -- #1513 Added the update available icon. [tidusjar] - -- Fixed the issue of it showing as not requested when we find it in Radarr. Made the tv shows match a bit more to the movie requests Added the ability for plex and emby users to login Improved the welcome email, will only show for users that have not logged in Fixed discord notifications the about screen now checks if there is an update ready #1513. [tidusjar] - -- Support email addresses as usernames #1513. [Jamie.Rees] - -- Link to issue treath. [PotatoQuality] - -- Give correct feedback when testing email notifications #1513. [Jamie.Rees] - -- Report issue removed and the deny dropdown removed #1513. [Jamie.Rees] - -- #1513 removed the discord text when testing pushbullet. [Jamie.Rees] - -- Made a lot of changes around the notifcations to support the custom app name also started on the welcome email ##1456. [Jamie.Rees] - -- Fixed the bug where we were displaying shows where we do not have enough information to request #1513. [Jamie.Rees] - -- #1513 added the network to tv shows. [Jamie.Rees] - -- Fixed the whitespace issue #1513. [Jamie.Rees] - -- Fixed the swagger endpoint #865 #1513 Fixed the custom image issue on the login page Fixed the bug when clicking on the tab on the requests page it would switch to the wrong one Swagger is now back @ /swagger. [tidusjar] - -- Optimized images, Update old compressed image with a new lossless one. (#1514) [camjac251] - -- #1513 #865 Fixed the issue where we do not send the requests to Radarr/Sonarr when approving. [tidusjar] - -- #1506 #865 Fixed an issue with the test buttons not working correctly. [tidusjar] - -- #865 Added donation link. [tidusjar] - -- Fixed a bunch of issues on #1513. [tidusjar] - -- #1460 Added the Updater, it all seems to be working correctly. #865. [Jamie.Rees] - -- Removed percentage. [Jamie.Rees] - -- Fixed linter. [Jamie.Rees] - -- Fixed some bugs in the UI #865. [Jamie.Rees] - -- Improved the search buttons #865. [Jamie.Rees] - -- More logging #865. [Jamie.Rees] - -- Made build faster. [Jamie.Rees] - -- More logging. [Jamie.Rees] - -- Set debug level to Debug for now. [Jamie.Rees] - -- Add linting and indexes for interfaces/services (#1510) [Matt Jeanes] - -- Fixed the issue with the tv search not working #1463. [Jamie.Rees] - -- Latest practices... also probably broke some styles - sorry (#1508) [Matt Jeanes] - -- Build with the branch version. [tidusjar] - -- Build fix. [tidusjar] - -- Fixed build. [tidusjar] - -- Omgwtf so many changes. #865. [tidusjar] - -- Tests. [Jamie.Rees] - -- #1456 Started on the User Importer Also added the remember me button. [Jamie.Rees] - -- Made some UI changes, reworked the Emby and Plex screens to make them more user friendly and no so fugly. #865 Also made the login page placeholder text slightly lighter. [Jamie.Rees] - -- Cake skip verification build stuff #865. [Jamie.Rees] - -- Some fixes around the UI and managing requests #865. [tidusjar] - -- #1486. [Jamie.Rees] - -- #1486. [Jamie.Rees] - -- Upgraded to .net core 2.0 #1486. [Jamie.Rees] - -- #865 Finished the landing page, we now check the server's status. [Jamie.Rees] - -- Fixed build. [TidusJar] - -- Removed the telegram api. [Jamie.Rees] - -- Small changes on the updater #1460 #865. [Jamie.Rees] - -- Remove unused functions. [Dhruv Bhavsar] - -- Make Episode picker similar to Requests Child view. #1457 #1463. [Dhruv Bhavsar] - -- Fix merge conflict for TvRequests component. [Dhruv Bhavsar] - -- Upstream Changes... [Dhruv Bhavsar] - -- Clean up Requests page code by moving children request to old component, remove additional REST calls when merging and update component names to make more sense. [Dhruv Bhavsar] - -- Lots of different UI enhancements and fixes #865. [tidusjar] - -- Gitchangelog. [tidusjar] - -- Fixed the issue where we were using the wrong availability options. [tidusjar] - -- Fixed a bunch of bugs in Ombi #865. [tidusjar] - -- Build versioning. [Jamie.Rees] - -- #1460 The assembly versioning seems to work correctly now. [Jamie.Rees] - -- More build versioning changes #865. [tidusjar] - -- Fixed cake script. [Jamie.Rees] - -- WIP on the build versioning for the Updater #1460 #865. [Jamie.Rees] - -- Versioning. [Jamie.Rees] - -- Package versions. [Jamie.Rees] - -- #1460 #865 working on the auto updater. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Small changes around the roles #865. [tidusjar] - -- Improvements to the UI and also finished the availability checker #865 #1464. [Jamie.Rees] - -- Availability Checker #1464 #865. [Jamie.Rees] - -- Fixed ##1492 and finished the episode searcher for #1464. [Jamie.Rees] - -- #1464. [tidusjar] - -- Reload the settings #1464 #865. [Jamie.Rees] - -- #1464 added the Plex episode cacher #865. [Jamie.Rees] - -- Fixed some issues around the tv requests area Added mattermost and telegram notifications #1459 #865 #1457. [tidusjar] - -- Fix global.json. [Dhruv Bhavsar] - -- Working UI for Requests. Approval/Deny does not work as it doesn't in your code either. [Dhruv Bhavsar] - -- Enable diagnostic on build #865. [Jamie.Rees] - -- Fixed the user token issue #865. [Jamie.Rees] - -- Some small refresh token work #865. [Jamie.Rees] - -- Initial TV Requests UI rebuild. [Dhruv Bhavsar] - -- Made a start on supporting multiple emby servers, the UI needs rework #865. [Jamie.Rees] - -- #865 #1459 Added the Sender From field for email notifcations. We can now have "Friendly Names" for email notifications. [Jamie.Rees] - -- Redirect to the landing page when enabled #1458 #865. [Jamie.Rees] - -- Removed IdentityServer, it was overkill #865. [Jamie.Rees] - -- Fixed another bug with identity. #865 I'm thinking about removing it. Causing more hassle than it's worth. [tidusjar] - -- #1460 #865. [tidusjar] - -- Delete appveyor_old.yml. [Jamie] - -- Fixed path. [Jamie.Rees] - -- Silent build level. [Jamie.Rees] - -- #1459 Forgot to get the Pushbullet agent to look up the pusbullet templates rather than the Discord ones. Updated the Gitchange log. [Jamie.Rees] - -- Made the placeholder color on the login page a bit lighter #865. [Jamie.Rees] - -- Landing and login page changes #865 #1485. [tidusjar] - -- #1458 #865 More work on landing. [Jamie.Rees] - -- Working on the landing page #1458 #865. [tidusjar] - -- A lot of clean up and added a new Image api #865. [Jamie.Rees] - -- Cleaned up the Logging API slightly #1465 #865. [Jamie.Rees] - -- Fixed the Identity Server discovery bug #1456 #865. [tidusjar] - -- Fixed the issue with the Identity Server running on a different port, we can now use -url #865. [Jamie.Rees] - -- Try again. [TidusJar] - -- Publish ubuntu 16.04. [Jamie.Rees] - -- Chnaged the updater job from Minutely to Hourly. [Jamie.Rees] - -- Some work around the Auto Updater and other small changes #1460 #865. [Jamie.Rees] - -- Missed a file. [tidusjar] - -- Fixed the swagger issue. [tidusjar] - -- RDP issues. [tidusjar] - -- Appveyor build rdp investigation. [tidusjar] - -- Working on the requests page #1457 #865. [tidusjar] - -- Made the password reset email style the same as other email notifications #1456 #865. [Jamie.Rees] - -- Fixed some bugs around the authentication #1456 #865. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Fixed build #1456. [Jamie.Rees] - -- #1456 #865 Started on allowing Plex Users to sign in through the new authentication server. [Jamie.Rees] - -- Removed covalent. [Jamie.Rees] - -- #1456 Reset Password stuff #865. [Jamie.Rees] - -- Finished implimenting Identity with IdentityServer4. #865 #1456. [Jamie.Rees] - -- Moved over to using Identity Server with Asp.Net Core Identity #1456 #865. [Jamie.Rees] - -- Started on the requests rework #865. [Jamie.Rees] - -- Extended the Emby API. [Jamie.Rees] - -- Started reworking the usermanagement page #1456 #865. [tidusjar] - -- Lots of refactoring #865. [Jamie.Rees] - -- Created an individual user api endpoint so we can make the user management pages better #865. [TidusJar] - -- Lot's of refactoring. [Jamie.Rees] - -- #1462 #865 Had to refactor how we use notificaitons. So we now have more notification fields about the request. [Jamie.Rees] - -- Looks like Sonarr is finished and works. A lot simplier this time around. #865. [tidusjar] - -- More work on the Sonarr Api Integration #865. [tidusjar] - -- Started on sonarr #865. [tidusjar] - -- Small changes #865. [tidusjar] - -- Damn son. So many changes... Fixed alot of stuff around tv episodes with the new DB model #865. [tidusjar] - -- Fixed the TV Requests issue #865. [Jamie.Rees] - -- Fixed a load of bugs need to figure out what is wrong with tv requests #865. [tidusjar] - -- #865 rework the backend data. Actually use real models rather than a JSON store. [Jamie.Rees] - -- Fixed the build issue #865. [tidusjar] - -- Allow us to use Emby as a media server. [tidusjar] - -- More Update #865. [Jamie.Rees] - -- Deployment changes. [Jamie.Rees] - -- More work on the Updater. [Jamie.Rees] - -- Lots of fixes. Becoming more stable now. #865. [tidusjar] - -- Small fixes around the searching. [Jamie.Rees] - -- Some rules #865. [Jamie.Rees] - -- Oops. [TidusJar] - -- Started on the Discord API settings page. [TidusJar] - -- Email Notifications are now fully customizable and work! #865. [Jamie.Rees] - -- Small changes and fixed some stylingon the plex page #865. [Jamie.Rees] - -- More on #865 TODO, Find out whats going on with the notifications and why exceptions are being thrown. [Jamie.Rees] - -- Oops. [Jamie.Rees] - -- Ok #865 fixed the published exe. [Jamie.Rees] - -- Fixed errors. [Jamie.Rees] - -- Fixed build script. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Some more #865. [Jamie.Rees] - -- Create appveyor.yml. [Jamie] - -- The Approving child requests now work! [Jamie.Rees] - -- Fixed many bugs #865. [Jamie.Rees] - -- Loads of changes, improved the movie search stylings is back. [Jamie.Rees] - -- Moved to webpack and started on new style. [Jamie.Rees] - -- Fixed the TV search via Trakt not returning Images anymore. #865. [Jamie.Rees] - -- Rules changes and rework. [Jamie.Rees] - -- Request Grid test. [Jamie.Rees] - -- Small cleanup #865. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Started the Radarr Settings #865. [Jamie.Rees] - -- Massive amount of rework on the plex settings page. It's pretty decent now! #865. [tidusjar] - -- Fixed build. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Rules #865. [tidusjar] - -- Stuff. [Jamie.Rees] - -- Forgot to uncomment. [Jamie.Rees] - -- Tetsd. [Jamie.Rees] - -- Build task changes. [Jamie.Rees] - -- Adsa. [Jamie.Rees] - -- Appveyor. [Jamie.Rees] - -- Stuff around tokens and also builds. [Jamie.Rees] - -- Finished the Plex Content Cacher. Need to do the episodes part but things are now showing as available! #865. [tidusjar] - -- Small user changes #865. [Jamie.Rees] - -- Stuff #865 need to work on the claims correctly. [Jamie.Rees] - -- Reworked the TV model AGAIN #865. [Jamie.Rees] - -- The move! [Jamie.Rees] - -- Fixed build #865. [Jamie.Rees] - -- Fixed the user management #865. [Jamie.Rees] - -- #865 Added support for multiple plex servers. [Jamie.Rees] - -- Bleh. [tidusjar] - -- Small changes. [Jamie.Rees] - -- Fixed the build. [Jamie.Rees] - -- Fixes. [Jamie.Rees] - -- Bundling changes. [Jamie.Rees] - -- Some series information stuff, changes the pace theme too. [Jamie.Rees] - -- Docker support and more, redesign the episodes. [tidusjar] - -- Stuff around episode/season searching/requesting. [Jamie.Rees] - -- Removed redundant folders. [tidusjar] - -- Lots of backend work. [tidusjar] - -- Fixed build. [Jamie.Rees] - -- TV Request stuff. [Jamie.Rees] - -- Work around the user management. [tidusjar] - -- More. [Jamie.Rees] - -- Lots and Lots of work. [Jamie.Rees] - -- Diagnostic changes. [tidusjar] - -- Fixed hangfire exception. [tidusjar] - -- Remove xunit. [tidusjar] - -- Lots more work :( [Jamie.Rees] - -- More changes. [tidusjar] - -- #865. [Jamie.Rees] - -- Small changes. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- More mapping. [Jamie.Rees] - -- Mapping mainly. [Jamie.Rees] - -- Fix systemjs config not being included. [Matt Jeanes] - -- Fixed bundling and various improvements. [Matt Jeanes] - -- Finished the emby wizard #865. [tidusjar] - -- Finished the wizard #865 (For Plex Anyway) [tidusjar] - -- Small changes. [tidusjar] - -- More work on Wizard and Plex API #865. [tidusjar] - -- Settings. [Jamie.Rees] - -- Settings for Ombi. [Jamie.Rees] - -- Fixed some issues around the identity. [Jamie.Rees] - -- #865 more for the authentication. [tidusjar] - -- Auth. [Jamie.Rees] - -- More on the search and requests page. It's almost there for movies. Need to add some filtering logic #865. [tidusjar] - -- #865. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Messing around with the settings. [tidusjar] - -- Fixed the yml. [Jamie.Rees] - -- Remove unneeded bundle config. [Matt Jeanes] - -- Redo dotnet publish targets. [Jamie.Rees] - -- Bundling changes. [Jamie.Rees] - -- Stuff. [Jamie.Rees] - -- Move app into wwwroot. [Jamie.Rees] - -- Put uglify back in! [Jamie.Rees] - -- Wrong line. [Jamie.Rees] - -- Matt is helping. [Jamie.Rees] - -- Revert. [tidusjar] - -- Small tweaks. [tidusjar] - -- Upgrade to .Net Standard 1.6. [tidusjar] - - -## v2.2.1 (2017-04-09) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the forums. [tidusjar] - -- Updates. [tidusjar] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added a retry policy around the emby newsletter. [Jamie.Rees] - -### **Fixes** - -- Revert "Merge branch 'DotNetCore' into dev" [tidusjar] - -- More borken build. [Jamie.Rees] - -- Started adding requesting. [Jamie.Rees] - -- Done the movie searching. [tidusjar] - -- #865. [tidusjar] - -- More. [tidusjar] - -- Moar. [tidusjar] - -- Small changes. [tidusjar] - -- Styling. [Jamie.Rees] - -- MOre changes. [Jamie.Rees] - -- Spacing. [Jamie.Rees] - -- Try again. [Jamie.Rees] - -- More. [Jamie.Rees] - -- Again. [Jamie.Rees] - -- Anbother. [Jamie.Rees] - -- Another. [Jamie.Rees] - -- Another. [Jamie.Rees] - -- Retry. [Jamie.Rees] - -- A. [Jamie.Rees] - -- Fixed. [Jamie.Rees] - -- Cahnge 2. [Jamie.Rees] - -- Appveyor change. [Jamie.Rees] - -- The start of a new world. [Jamie.Rees] - -- Fixed the migration number and order by the added date for the newsletter #1264. [tidusjar] - -- Forgot this change. [tidusjar] - -- Also fixed the issue for the Emby Newsletter where episodes were not getting added :( [tidusjar] - -- #1264 "They may take our lives, but they'll never take our freedom!" [tidusjar] - -- Finished reworking the Sonarr Integration. Seems to be working as expected, faster and most stable. It's Not A Toomah! [tidusjar] - -- Small bit of work. [Jamie.Rees] - -- Made a start on the new Sonarr integration. [tidusjar] - -- For test emails, if there is no new content then just grab some old data. [tidusjar] - -- Fixed an issue where the emby newsletter was always showing series. [tidusjar] - - -## v2.2.0 (2017-03-30) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added a new setting for the Netflix option, we can now disable it appearing in the search. [tidusjar] - -- Update German Translation. [Marius Schiffer] - -- Added a release notes page, you can access via Admin>Updates>Recent Changes tab. Note to self, need to put better comments in for users to understand! [Jamie.Rees] - -- Added gravitar image. [Jamie.Rees] - -- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] - -- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] - -- Added some logging around API calls. [smcpeck] - -- Changed IEmbyAvailabilityChecker to use IEnumberables + checking actor search against Emby content + PR feedback. [smcpeck] - -- Changed actor searching to support non-actors too. [smcpeck] - -- Added a 10 second timer to refresh some new caching I put in. [smcpeck] - -- Added root folder and approving quality profiles in radarr #1065. [tidusjar] - -- Added some debugging code around the newsletter for Emby #1116. [tidusjar] - -- Added a TMDB Rate limiter for the newsletter. [tidusjar] - -- Added port check in wizard. also fixed favicon. [tidusjar] - -- Update Radarr placeholder. [d2dyno] - -- Added the user login for emby users #435. [tidusjar] - -- Added User Management support for Emby #435. [tidusjar] - -- Added emby to the sidebar #435. [tidusjar] - -- Added API endpoint for /actor/new/ to support searching for movies not already available/requested. [smcpeck] - -- Update ISSUE_TEMPLATE.md. [Jamie] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -### **Fixes** - -- Translation changes. [Jamie.Rees] - -- Syntax error. [tidusjar] - -- Fixed an issue where we were retrying the API call when the Plex users login creds were invalid. #1217. [tidusjar] - -- Slightly increased the wait time for the emby newsletter also fixed a potential error in the plex user checker. [Jamie.Rees] - -- Fixed an issue where we were not notifiying emby users. [Jamie.Rees] - -- Fixed the issue where the recent changes page was not showing the correct date. #1296. [Jamie.Rees] - -- Fixed #1252 (Show the correct user type on the management page for Plex Users) [Jamie.Rees] - -- Fixed the casting error #1292. [Jamie.Rees] - -- Fix test newletter not sending when empty. [Dhruv Bhavsar] - -- Quick fix for email false positive message. ISSUE: #1286. [Dhruv Bhavsar] - -- Fixes around the newsletter. We will now correctly show newly added shows and also newly added episodes. #1163. [tidusjar] - -- Fixed a sonarr deseralization error. [tidusjar] - -- Increased the delay for the Episode information api calls. #1163. [tidusjar] - -- Looks like we were overloading emby with out api calls. [tidusjar] - -- Fixed the root path escaping issue for Radarr too! [tidusjar] - -- Some small backend newsletter changes, we can now detect if there are any movies and/or tv shows, if there are none then we will no longer send out an empty newsletter. [Jamie.Rees] - -- Remoddeled the notificaiton settings to make it easier to add more. This is some techinical changes that no one except me will ever notice :( [Jamie.Rees] - -- Fixed #1234. [Jamie.Rees] - -- A fix to the about page and also started to rework the notification backend slightly to easily add more notifications. [Jamie.Rees] - -- Adding more logging into the Plex Cacher. [Jamie.Rees] - -- #1218 changed the text when we cannot display release notes for dev and EAP branches. [Jamie.Rees] - -- Fix for #1236. [SuperPotatoMen] - -- Tooltips. [Jamie.Rees] - -- #236. [Jamie.Rees] - -- #1102. [Jamie.Rees] - -- Done #1012. [Jamie.Rees] - -- Oops #1134. [Jamie.Rees] - -- Fixed #1121. [Jamie.Rees] - -- Fixed #1210. [Jamie.Rees] - -- Fixed typo #1134. [Jamie.Rees] - -- Fixed #1223. [Jamie.Rees] - -- Another newsletter fix attempt #1163 #1116. [tidusjar] - -- Fixup! Reset the branch on v2.1.0 tag to get to a shared state between dev and Master. [distaula] - -- Fixed a bug in the Plex Newsletter. [tidusjar] - -- Typo. [tidusjar] - -- Fixed around the newsletter and a small feature around the permissions/features (#1215) [Jamie] - -- Fixed #1189. [tidusjar] - -- Fixed #1195. [Jamie.Rees] - -- Fixed #1195. [Jamie.Rees] - -- Fixed #1192. [Jamie.Rees] - -- Fixed issue where we could get null rating keys on Plex. [tidusjar] - -- Needed to treat a 201 as success, too. + removed some commented out code. [Shaun McPeck] - -- Normalized spacing/tabs. [smcpeck] - -- Move local user login to be the first thing checked; renamed old Api variable to PlexApi now that Emby is in play. [smcpeck] - -- Remove all the polling/retry logic around HP requests. This was a problem do to not properly awaiting the initial AddArtist API call being sent to HP. Also fix SetAlbumStatus to use ReleaseId instead of MusicBrainsId (same fix previously applied to AddArtist). [smcpeck] - -- Restore checking of HTTP StatusCode on ApiRequests; remove checking of response.ErrorException. [smcpeck] - -- Reverted (for now) non-200 response handling; added some extra logging. [smcpeck] - -- Tweaked ApiRequest behavior on non-200 responses; think it was breaking login. :-" [smcpeck] - -- Only deserialize response payload in ApiRequest when StatusCode == 200. Will a default return value in other cases cause other issues? [smcpeck] - -- Headphones - added releaseID to generic RequestedModel and passing that through to HP request. Their API doesn't request via the MusicBrainzId. [smcpeck] - -- Fixed #1038. [tidusjar] - -- Fixed a slight issue where we could click the change folders button rather than the dropdown arrow #1189. [tidusjar] - -- Bunch of updater files. [tidusjar] - -- #1163 #117. [tidusjar] - -- Removed some unnecessary 'ConfigureAwait` uses. [smcpeck] - -- Remove meaningless html class from actor searching checkbox. [smcpeck] - -- Fixed an issue where we were not always showing movies from external programs. [tidusjar] - -- Remove extra delay when filtering out existing movies. [smcpeck] - -- Post merge build fixes. [smcpeck] - -- Fix. [tidusjar] - -- Fixed #1177. [tidusjar] - -- Fixed #1152. [tidusjar] - -- Fixed #1123. [tidusjar] - -- Fixed a bug when sending to radarr. [tidusjar] - -- Fixed #1133. [tidusjar] - -- Fixed issues img. [Jamie.Rees] - -- Stop Plex being enabled on the first time installing #1048. [Jamie.Rees] - -- The landing page now works for emby #435. [tidusjar] - -- Fixed #1104. [tidusjar] - -- Fixed #1090. [tidusjar] - -- Fixed #1103. [tidusjar] - -- Small changes. [tidusjar] - -- Break out Mass Email feature into its own tab, upgrade Font Awesome and clean up some comments. [dhruvb14] - -- Fix typo. [Travis Bybee] - -- Fixed #1066. [Jamie.Rees] - -- Fixed broken builds. [Jamie.Rees] - -- Fixed #1083. [Jamie.Rees] - -- #1049. [tidusjar] - -- Fixed #1071. [tidusjar] - -- Fixed #1048 #1081. [tidusjar] - -- #1074. [Jamie.Rees] - -- #1069. [Jamie.Rees] - -- Fix for #1068. [tidusjar] - -- Remove duplciate tv show status. [tidusjar] - -- Some request ui changes. [tidusjar] - -- Removed references to Plex. [tidusjar] - -- Removed plex from the scheduled jobs ui. [tidusjar] - -- First run of the newsletter set it to a test. [tidusjar] - -- Reworked the newsletter for Emby! Need to rework it for Plex and use the new way to do it. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed the mass email, it was only being set to users with the newsletter feature #358. [tidusjar] - -- Removed Plex Request from the notifications. [tidusjar] - -- Finish implementing mass email feature. [dhruvb14] - -- @tidusjar pointed out runtime error!! [dhruvb14] - -- Does not compile, need to get data from UI into nancy somehow and figure out why IMassEmail is not initializing. [dhruvb14] - -- Begin Implementing Mass Email Section. [dhruvb14] - -- Hide the auto update btn #236 Fixed where we were not populating the emby episodes #435. [tidusjar] - -- Fix Radarr labels. [d2dyno] - -- Fixed pace loader. [Jamie.Rees] - -- Check if Emby/Plex is enabled before starting the job. [Jamie.Rees] - -- Fixed #1036. [Jamie.Rees] - -- Fixed a typo and changed wording. [Torkil Liseth] - -- Fixed #1035. [Jamie.Rees] - -- Fix for #1026. [Jamie.Rees] - -- Fixed #1042. [tidusjar] - -- #435. [Jamie.Rees] - -- #435 Started the wizard. [Jamie.Rees] - -- Removed. [tidusjar] - -- Final Fixes. [dhruvb14] - -- Partial fix for broken HR tag's in Email... [dhruvb14] - -- DAMN! #435 that's a lot of code! [tidusjar] - -- Started adding Emby, Lots of backend work done. Need a few more services done and login and user management. #435. [tidusjar] - -- UI changes to add checkbox and support searching for only new matches via new API. [smcpeck] - -- REFACTOR: IAvailabilityChecker - changed arrays to IEnumerables. [smcpeck] - -- UI changes to consume actor searching API. [smcpeck] - -- API changes to allow for searching movies by actor. [smcpeck] - -- Enforcing async/await in synchronous methods that were marked async. [smcpeck] - - -## v2.1.0 (2017-01-31) - -### **New Features** - -- Update README.md. [Jamie] - -- Update .gitattributes. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added the new labels to the search. [tidusjar] - -- Added a switch to use the new search or not, just in case people do not like it. added a migration to turn on the new search. [Jamie.Rees] - -- Added a bunch of categories for tv search similar to what we have for movies. [Jamie.Rees] - -### **Fixes** - -- Fixed typos. [Haries Ramdhani] - -- Fix typo in readme. [tdorsey] - -- Fixed #985. [Jamie.Rees] - -- FIxed #978. [tidusjar] - -- Fixed the approval issue for #939. [tidusjar] - -- Some general improvements. [tidusjar] - -- Turned off migration for now. [tidusjar] - -- Fixed #998. [tidusjar] - -- Additional movie information. [Jamie.Rees] - -- Debug info around the notifications. [Jamie.Rees] - -- Small changes. [tidusjar] - -- Fixed #995. [tidusjar] - -- Fix for #978. [tidusjar] - -- Fixed #991. [tidusjar] - -- Fixed the login issue and pass Radarr the year #990. [Jamie.Rees] - -- More small tweaks around the username/alias. [Jamie.Rees] - -- Possible issue with the empty username. [Jamie.Rees] - -- Potential Fix for #985. [Jamie.Rees] - -- Small changed to the sidebar. [Jamie.Rees] - -- Small changes. [Jamie.Rees] - -- Done #627. [Jamie.Rees] - -- Finished #535 #445 #170. [tidusjar] - -- Fixed tests. [Jamie.Rees] - -- Started to add the specify Sonarr root folders. [Jamie.Rees] - -- Fixed #968. [Jamie.Rees] - -- Fixed #970. [Jamie.Rees] - -- Done #924. [Jamie.Rees] - -- Fixed. [Jamie.Rees] - -- Fixed #955. [Jamie.Rees] - -- #956. [Jamie.Rees] - -- Fixed #947. [Jamie.Rees] - -- #951. [tidusjar] - -- Finished #923 !!! [tidusjar] - -- More for #923. [Jamie.Rees] - -- Radarr integartion in progress #923. [tidusjar] - -- Fixed #940 don't show any shows without a tvdb id. [tidusjar] - -- Finished #739. [Jamie.Rees] - -- Initial impliementation of #739. [Jamie.Rees] - -- Improved the search UI and made it more consistant. Finished the Netflix API Part #884. [Jamie.Rees] - - -## v2.0.1 (2017-01-16) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added a netflix api. [Jamie.Rees] - -### **Fixes** - -- Fixed #934. [Jamie.Rees] - - -## v2.0 (2017-01-14) - -### **New Features** - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Added the settings for #925 but need to apply the settings to the UI. [Jamie.Rees] - -- Changed the settings name from Plex Requests to Ombi. [Jamie.Rees] - -- Added support for Managed Users #811. [Jamie.Rees] - -- Change solution name in travis. [mhann] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -### **Fixes** - -- Finished #925. [Jamie.Rees] - -- Some TODO's. [Jamie.Rees] - -- Fixed #915. [Jamie.Rees] - -- Fixed the issue where notifications are not being sent to users with Aliases #912. [Jamie.Rees] - -- Fixed #891. [Jamie.Rees] - -- Fix indentation issue. [Marcus Hann] - -- Implement simple button. [Marcus Hann] - -- Plex Username Case Sensitivity Fix. [thegame3202] - -- Fixed #882. [Jamie.Rees] - -- Api changed again, so more fixes for #878. [Jamie.Rees] - -- Possible fix for #893. [Jamie.Rees] - -- Fixed #898. [Jamie.Rees] - -- Fixed #878. [TidusJar] - -- * userManagementController.js: fixed #881. [TidusJar] - -- More work on watcher, should all be good now. #878. [Jamie.Rees] - -- Delete PlexRequests.sln.DotSettings. [Jamie] - -- Fixed #862. [Jamie.Rees] - -- #399 and #398 finished. [Jamie.Rees] - -- More work on #399. [Jamie.Rees] - -- Finished #884. [Jamie.Rees] - -- More for #844. [Jamie.Rees] - -- Another #844. [Jamie.Rees] - -- Fixed a dependancy issue with #844. [Jamie.Rees] - -- Finished the main part of #844 just need testing. [Jamie.Rees] - -- Fixed #832. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Fix tiny readme typo. [mhann] - -- Fixed #850 also started #844 (Wrote the API interaction) [Jamie.Rees] - -- #801 #292 done. [Jamie.Rees] - -- Should fix #841 #835 #810. [Jamie.Rees] - -- Fix small typo in ticket overview page. [mhann] - -- More work on the combined login. [Jamie.Rees] - -- Fixed db issue. [Jamie.Rees] - -- Name changes. [Jamie.Rees] - -- All Sln changes. [tidusjar] - -- Moved API Sln dir. [tidusjar] - -- Fixed build. [tidusjar] - -- Moved namespaces. [tidusjar] - -- Renamed zip. [tidusjar] - -- Product name change. [tidusjar] - - -## v1.10.1 (2016-12-17) - -### **Fixes** - -- #788 fixed! [tidusjar] - -- Fixed #788 and #791. [tidusjar] - -- #399 #398. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Small refactorings. [Jamie.Rees] - -- #782. [Jamie.Rees] - -- #785. [Jamie.Rees] - - -## v1.10.0 (2016-12-15) - -### **New Features** - -- Update README.md. [Jamie] - -- Added optional launch args for the auto updater. [Jamie.Rees] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update _Navbar.cshtml. [Jamie] - -- Update README.md. [Jamie] - -- Update _Navbar.cshtml. [Jamie] - -- Update README.md. [Jamie] - -- Added a new permission to bypass the request limit. [Jamie.Rees] - -- Update Version1100.cs. [SuperPotatoMen] - -- Added logging around the Newsletter #717. [Jamie.Rees] - -- Added missing migration. [tidusjar] - -- Added loading spinner. [Jamie.Rees] - -- Update UI.resx. [SuperPotatoMen] - -- Update Version1100.cs. [Jamie] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -### **Fixes** - -- Fixed an issue where the HTML in the newsletter was incorrect. [Jamie.Rees] - -- Fixed #201. [Jamie.Rees] - -- Fixed #720 and added better error handling around the migrations. [Jamie.Rees] - -- Fixed #769. [Jamie.Rees] - -- Write out the actual file version. [Jamie.Rees] - -- Error checking around GA. [TidusJar] - -- Fixed #761. [tidusjar] - -- Fixed #749 Fixed an issue where we were adding the read only permission when creating the admin. [tidusjar] - -- Fixed #757. [tidusjar] - -- Fixes around the server admin #754. [Jamie.Rees] - -- Removed the trace option from the UI, it is only accessible when appending the url with "?developer" #753. [Jamie.Rees] - -- Fixed an issue where the admin could not be updated. [Jamie.Rees] - -- Fixed #745. [Jamie.Rees] - -- Fixed #748. [Jamie.Rees] - -- Workaround for #748. [SuperPotatoMen] - -- Another attempt to fix #717. [tidusjar] - -- Fixed #744. [Jamie.Rees] - -- Tidied up the warnings. [Jamie.Rees] - -- Small bit of analytics. [Jamie.Rees] - -- Removed the whitelist. [Jamie.Rees] - -- Should fix #696 Fixed an issue with the scheduled jobs where it could use a different trigger if the order between the schedules and the triggers were in different positions in the array... Stupid me, ordering both arrays by the name now. [tidusjar] - -- Some better null object handling #731. [Jamie.Rees] - -- Small tweaks. [Jamie.Rees] - -- Fixed #728. [Jamie.Rees] - -- Fixed #727. [Jamie.Rees] - -- Fixed admin redirect issue. [tidusjar] - -- Fixed #718. [tidusjar] - -- Lots of small fixes and tweaks. [Jamie.Rees] - -- Tidied up some of the angular code, split the UI into it's own directives for easier maintainability. [Jamie.Rees] - -- Small tweaks to the Request Page. [Jamie.Rees] - -- Reverted the PR that may have caused #619. [Jamie.Rees] - -- Some small tweaks around #218 Just added the link to the settings and some angular improvements. [Jamie.Rees] - -- Test. [Jamie.Rees] - -- Attempt at fixing #686. [Jamie.Rees] - -- Finished #707. [Jamie.Rees] - -- Fixed #704. [Jamie.Rees] - -- Fixed #705. [Jamie.Rees] - -- Fixed #706. [Jamie.Rees] - -- #547. [Jamie.Rees] - -- Default tabs #304. [Jamie.Rees] - -- Fixed #703. [Jamie.Rees] - -- #233. [Jamie.Rees] - -- Done #678. [Jamie.Rees] - -- Fixed #670. [Jamie.Rees] - -- #456 Update all the requests when we identify that the username changes. [Jamie.Rees] - -- More user management. [Jamie.Rees] - -- #218. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Implimented the features #218. [tidusjar] - -- Use the user alias everywhere if it is set #218. [tidusjar] - -- Implimented auto approve permissions #218. [tidusjar] - -- A. [tidusjar] - -- Fixed an IOC issue. [tidusjar] - -- Fixed the issue with user management, needed to implement our own authentication provider. [Jamie.Rees] - -- Small changes including #666. [Jamie.Rees] - -- Done #679. [tidusjar] - -- Reduce the retry time. [Jamie.Rees] - -- Remove all references to the claims. [Jamie.Rees] - -- Lots of fixed and stuff. [Jamie.Rees] - -- Fixed potential crash #683. [Jamie.Rees] - -- Fixed #681. [Jamie.Rees] - -- More user management. [Jamie.Rees] - -- Finishing off the user management page #218 #359 #195. [Jamie.Rees] - -- Finished #646 and fixed #664. [Jamie.Rees] - -- Started on #646. Fixed #657. [Jamie.Rees] - -- Fixed #665. [Jamie.Rees] - -- Migrate users. [TidusJar] - -- Fixed build. [Jamie.Rees] - -- Convert the for to foreach for better readability. Still need to rework this area. [Jamie.Rees] - -- Final Tweaks #483. [Jamie.Rees] - -- Finished #483. [Jamie.Rees] - -- Finished the queue #483. [Jamie.Rees] - -- Started on the queue for requests #483 TV Requests with missing information has been completed. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Finished the notification for the fault queue. [Jamie.Rees] - -- Finished #556. [Jamie.Rees] - -- Finished #633 (First part of the queuing) [Jamie.Rees] - -- Finished #659 #236 has been modified slightly. Needs testing on Different systems. [Jamie.Rees] - -- Almost finished #659. [Jamie.Rees] - -- Started on #483. [Jamie.Rees] - -- #544. [Jamie.Rees] - -- Fixed #656 and more work on #218. [Jamie.Rees] - -- Fixed some issues with the user management work. [TidusJar] - -- Fixed build issue. [TidusJar] - -- User perms. [Jamie.Rees] - - -## v1.9.7 (2016-11-02) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Potential fix for #629. [TidusJar] - -- Fixed an issue to stop blatting over the base url. [tidusjar] - -- Fixed #643. [TidusJar] - -- Fixed #622. [TidusJar] - - -## v1.9.6 (2016-10-28) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fixed #586. [Jamie.Rees] - -- Fixed #622. [Jamie.Rees] - -- Fixed #621. [Jamie.Rees] - - -## v1.9.5 (2016-10-27) - -### **New Features** - -- Added our own custom migrations, a lot easier to migrate DB versions now. [tidusjar] - -### **Fixes** - -- Bump version. [Jamie.Rees] - -- Small bit of work on the user claims. [Jamie.Rees] - -- Fix #612 again. [Jamie.Rees] - -- User management styling. [Jamie.Rees] - -- Fixed #608 and some other small stuff. [tidusjar] - -- More user mapping. [tidusjar] - -- Fixed #615. [tidusjar] - -- Fixed #610. [tidusjar] - -- User management stuff. [Jamie.Rees] - -- User management work. [Jamie.Rees] - -- Revert the TVSender to use the old code. [Jamie.Rees] - -- Fixed the view issue. [tidusjar] - -- S582: admin improvements part 2. [Jim MacKenzie] - -- Fix #612. [Jamie.Rees] - -- User management, migration and newsletter. [Jamie.Rees] - -- #602 recently added improvements. [tidusjar] - -- Revert "Sorting out the current state of migrations" [Jamie.Rees] - -- Sorting out the current state of migrations. [Jamie.Rees] - -- Marked as obsolete. [Jim MacKenzie] - -- Migration setup. [Jim MacKenzie] - -- Removed extra line breaks. [Jim MacKenzie] - -- Moved Newsletter Settings to its own page. [Jim MacKenzie] - -- Reverted TMDB package. [Jamie.Rees] - -- Remove DB Option. [Jamie.Rees] - -- Upgrade the movie DB package and fixed #370 To fix this I had to make another API call... It slows down the search... [tidusjar] - -- Lots of small fixes including #475. [tidusjar] - -- A better fix for #587. [tidusjar] - -- Fixed #553. [tidusjar] - -- #601. [Jamie.Rees] - -- More rework to use the Plex DB. [Jamie.Rees] - -- More work around using the PlexDatabase. [Jamie.Rees] - -- Plex DB. [Jamie.Rees] - -- Allow to process even know we had an error #578. [Jamie.Rees] - -- Fix boostrapper-datetimepicker imports (#586) [David Torosyan] - -- Potential work around for #587. [tidusjar] - -- Fixed #589. [tidusjar] - - -## v1.9.4 (2016-10-10) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added Paypalme options, no UI yet (#568) [Jim MacKenize] - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -### **Fixes** - -- Reverted. [tidusjar] - -- Make sure it's enabled before sending the recently added. [tidusjar] - -- Moved the HR inside the table for TV Shows. [Jamie.Rees] - -- FIXED!!!!! YES BITCH! #550. [tidusjar] - -- Moved the horizontal rules inside the table row. [tidusjar] - - -## v1.9.3 (2016-10-09) - -### **New Features** - -- Added properties to disable tv requests for specific episodes or seasons and wired up to admin settings. [Matt McHughes] - -- Added different sonarr search commands. [tidusjar] - -### **Fixes** - -- Fixed #515. [tidusjar] - -- Fixed #561 and a small bit of work on #569. [tidusjar] - -- #569. [tidusjar] - -- Fixed case typo. [Matt McHughes] - -- Finished wiring tv request settings to tv search. [Matt McHughes] - -- WIP hide tv request options based on admin settings. [Matt McHughes] - -- Set meta charset to be utf-8. [Madeleine Schnemann] - -- F#552: updated labels text. [Jim MacKenize] - -- F#552: Re-design lables. [Jim MacKenzie] - -- Last correction.. Now the translation is ready to be used. [Michael Reber] - -- Forgot to correct two incorrect translations. [Michael Reber] - -- Correction of the German translation. [Michael Reber] - -- Notification improvements. [tidusjar] - -- #515. [tidusjar] - - -## v1.9.2 (2016-09-18) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update CouchPotatoCacher.cs. [Jamie] - -- Added some error handing around the GetMovie area #517. [tidusjar] - -- Added a version endpoint in "/api/version" #529. [tidusjar] - -### **Fixes** - -- Trying to fix the auto CP. [tidusjar] - -- Increase the notice message text box #527. [tidusjar] - -- #536 this should fix notification settings when it is being unsubscribed when testing. [tidusjar] - -- Improved how the TV search looks and feels. [tidusjar] - -- Fix for reverse proxy when using the wizard. [Devin Buhl] - -- Fixed #532. [tidusjar] - -- This should fix some issues with the episode requests #514. [tidusjar] - -- Small changes around existing series. [tidusjar] - -- Fixed #514 and the unit tests. [tidusjar] - -- If there is a bad password when changing it, we now inform the user. [tidusjar] - -- When logging out as admin remove the username from the session. [tidusjar] - -- Sorted out some of the UI for #18. [tidusjar] - -- Finished #18. [tidusjar] - - -## v1.9.1 (2016-08-30) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added french to the navbar. [tidusjar] - -- Changed the way we use the setTimeout function. Should fix #403 #491 #492. [tidusjar] - -- Change the redirection to use a relative uri redirect #473. [tidusjar] - -### **Fixes** - -- Fixed tests. [tidusjar] - -- Fixed #491 and added more logging around the email messages under the Info level. [tidusjar] - -- Finished #415. [tidusjar] - -- Fixed an issue where there were some JS errors on the landing page settings and stopped us being redirected to the login sometimes as an admin. [tidusjar] - -- Fixed #480. [tidusjar] - -- User management. [tidusjar] - -- Fixed #505. [tidusjar] - -- Append the application version to the end of our JS/CSS files. [tidusjar] - -- Fixed issue #487. [tidusjar] - -- Remove the datetime picker css from the main assets block and only load it on the pages it needs. #493. [tidusjar] - -- Redirect to search if we are already logged in #488. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed an issue where you could set the base url as requests #479. [tidusjar] - -- Working on the beta releases page and also the user management. [tidusjar] - -- User work. [tidusjar] - - -## v1.9.0 (2016-08-18) - -### **New Features** - -- Update the availability checker to search for TV Episodes. [tidusjar] - -- Changed the no TVMazeid message. [tidusjar] - -- Added an option to disable/enable the Plex episode cacher. [tidusjar] - -- Updated the episode cacher to have a minimum of 11 hours before it runs again. [tidusjar] - -- Added some useful analytical infomation around the wizard. [tidusjar] - -- Updated the German translations #402. [tidusjar] - -- Added some code to shrink the DB. reworked the search to speed it up. [tidusjar] - -- Change to use the GrandparentTitle rather than the thumbnail.... facepalm. [tidusjar] - -- Change the interval to hours! [tidusjar] - -- Added the transaction back into the DB. Do not run the episode cacher if it's been run in the last hour. [tidusjar] - -- Added logging. [tidusjar] - -- Changed the query slightly. [tidusjar] - -- Updated Newtonsoft.Json, Autofixture, Nlog and Dapper packages. [tidusjar] - -- Added the Sonarr check for episodes #254. [tidusjar] - -- Added unit tests. [tidusjar] - -- Added #436. [tidusjar] - -- Update build no. [tidusjar] - -- Updated translations for #402. [tidusjar] - -- Added a beta module. [tidusjar] - -- Added a custom debug root path provider, this means we do not have to recompile the views every time we make a view change. [tidusjar] - -- Update .gitignore. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added tests for the string hash. [tidusjar] - -- Added code to request the api key for CouchPotato. [tidusjar] - -- Added the file version to the layout. [tidusjar] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added automation tests. [tidusjar] - -- Update appveyor.yml. [Jamie] - -- Updated packages. [tidusjar] - -- Updated Polly. [tidusjar] - -- Updated Fr, IT and NL translations #402. [tidusjar] - -- Changed the way the donate button works for #414. [tidusjar] - -- Added MediatR. [tidusjar] - -### **Fixes** - -- User management stuff. [tidusjar] - -- Fixed! [tidusjar] - -- Small amount of work on the user management. [tidusjar] - -- Fixed #466. [tidusjar] - -- Fixes. [tidusjar] - -- Made the episode request better. [tidusjar] - -- Removed commented out tests. [tidusjar] - -- Fixed the bad test after the merge. [tidusjar] - -- Reworked #466. [tidusjar] - -- More unit tests around the login and also the core Plex Checker. [tidusjar] - -- Potentially fixed the issue where we were requesting everything that was also available now. [tidusjar] - -- This should fix #466. [tidusjar] - -- Attempt at fixing a potential bug found from #466. [tidusjar] - -- #464 fixed. [tidusjar] - -- Fixed the build. [tidusjar] - -- Small improvements to the wizard. [tidusjar] - -- Always set the wizard to be true when editing the Plex Requests settings (Since the flag is not in the UI, a bool defaults to false). [tidusjar] - -- Tiny bit of more info. [tidusjar] - -- Finished #459. [tidusjar] - -- #459 is almost done. [tidusjar] - -- Modified the episode modal so that we are now resetting the button after a request. [tidusjar] - -- Commented out the transaction for now to debug it. [tidusjar] - -- Since we are multithreading, we should use a threadsafe type to store the episodes to prevent any threading or race conditions. [tidusjar] - -- Wrapped the bulk insert inside a transaction. [tidusjar] - -- Made the episode check parallel. [tidusjar] - -- Log out the GUID causing the issue. [tidusjar] - -- Fixed another test. [tidusjar] - -- Fixed tests. [tidusjar] - -- Got mostly everything working for #254 Ready for testing. [tidusjar] - -- Fixed issue with saving to db. [tidusjar] - -- Need to work out why the cacher is not working and where the datatype mismatch is. [tidusjar] - -- Don't delete first. [tidusjar] - -- Fix the log path issue #451. [tidusjar] - -- Dump an item. [tidusjar] - -- Small change with the return value in the batch insert. [tidusjar] - -- #254 Removed the cache, we are now storing the plex information into the database. [tidusjar] - -- Small change in the episode saver. [tidusjar] - -- Some small tweaks to improve the memory alloc. [tidusjar] - -- Short circuit when Plex hasn't been setup. Added Miniprofiler. [tidusjar] - -- Consolidate newtonsoft.json packages. [tidusjar] - -- Some performance improvements around the new TV stuff. [tidusjar] - -- Reworked the cacher, fixed the memory leak. No more logging within tight loops. [tidusjar] - -- Another null check. [tidusjar] - -- Some more changes. [tidusjar] - -- Some error handling. [tidusjar] - -- Check if the sonarr ep is monitored. [tidusjar] - -- Some logging. [tidusjar] - -- Small changes, we will actually see the episode cacher on the scheduled jobs page now. [tidusjar] - -- Work on the UI to show what episodes have been requested #254. [tidusjar] - -- Small fix. [tidusjar] - -- Fix the api change in #450. [tidusjar] - -- #254. [tidusjar] - -- Workaround for #440. [tidusjar] - -- Async async async improvements. [tidusjar] - -- Finished #266 Added a new cacher job to cache all episodes in Plex. [tidusjar] - -- Fixed #442. [tidusjar] - -- #254. [tidusjar] - -- Work around the sonarr bug #254. [tidusjar] - -- #254 having an issue with Sonarr. [tidusjar] - -- Small bit of work on #266. [tidusjar] - -- #254. [tidusjar] - -- Precheck and disable the episode boxes if we already have requested it. TODO check sonarr to see if it's already there. #254. [tidusjar] - -- Fixed broken build. [tidusjar] - -- More work for #254. [tidusjar] - -- More work on #254. [tidusjar] - -- Fixed the bug in #438 and added unit tests to make so we dont break it in the future. [tidusjar] - -- Some reason we had dupe translations. [tidusjar] - -- Rename SubDir to Base Url. [tidusjar] - -- Fix the exception in #440. [tidusjar] - -- Reworking the login page for #426. [tidusjar] - -- Fixed #438. [tidusjar] - -- Finished the auth stuff. [tidusjar] - -- Finished up the SMTP side of #429. [tidusjar] - -- #428 Added a message when the we cannot get a TVMaze ID. [tidusjar] - -- #254 MOSTLY DONE! At last, this took a while. [tidusjar] - -- Removed the other rootpath provider. [TidusJar] - -- Removed the other rootpath provider. [TidusJar] - -- Removed the other rootpath provider. [TidusJar] - -- Should fix #429. [TidusJar] - -- Done #135 We are including the application version number in the directory. [tidusjar] - -- #387 trim the spaces from the api key. Tidied up the setting models a bit. [tidusjar] - -- Wrapped the repo to catch Sqlite corrupt messages. [tidusjar] - -- Frontend and tv episodes api work for #254. [tidusjar] - -- #424. [tidusjar] - -- #359. [tidusjar] - -- Moved the plex auth token to the plex settings where it should belong. [tidusjar] - -- Small changes around the user management. [tidusjar] - -- Missed brace. [tidusjar] - -- Removed. [tidusjar] - -- Fixed issues from the merge. [tidusjar] - -- Stupid &$(* merge. [tidusjar] - -- Angular. [tidusjar] - -- Reworked the custom notifications... again. Need to figure out how to find the view to the model. [tidusjar] - -- Fixed #417. [tidusjar] - -- Removed NinjectConventions, we hadn't started to use it anyway. [tidusjar] - -- Fixed the way we will be using custom messages. [tidusjar] - -- Test checkin. [tidusjar] - -- Better handling for #388. [tidusjar] - -- Fixed #412. [tidusjar] - -- Fixed #413. [tidusjar] - -- Fixed #409. [tidusjar] - -- Trycatch around the availbility checker. [tidusjar] - -- WIP on notification resolver. [tidusjar] - -- Tidy. [tidusjar] - -- Plugged in MediatR. [tidusjar] - -- Moved over to using Ninject. [tidusjar] - - -## v1.8.4 (2016-06-30) - -### **Fixes** - -- Fixed the bug where we were auto approving everything. Added French language into the navigation bar. [tidusjar] - - -## v1.8.3 (2016-06-29) - -### **New Features** - -- Update README.md. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added some of the backend bits for #182. [tidusjar] - -- Updates for #243. [tidusjar] - -- Added Dutch language #243. [tidusjar] - -- Added languages #243. [tidusjar] - -- Added logging #350. [tidusjar] - -### **Fixes** - -- Small changes. [tidusjar] - -- Allow html in the notice message. [tidusjar] - -- Some more unit tests around the NotificationMessageResolver. [tidusjar] - -- Fixed a timing bug found the in build. Note, when working with time differences use TotalDays. [tidusjar] - -- More translations on the search page (Mainly the notification messages) #243. [tidusjar] - -- Fixed some warnings. [tidusjar] - -- CodeCleanup. [tidusjar] - -- Fixed a bit of a stupid bug in the resetter and added unit tests around it to make sure this never happens again. [tidusjar] - -- Fixed an issue where we didn't provide the correct response when clearing the logs. [tidusjar] - -- Made it so users that are in the whitelist do not have a request limit. [tidusjar] - -- Made it so the request limit doesn't apply to admin users. [tidusjar] - -- Fixed where a user could see the delete button on the issues page. [tidusjar] - -- Fixed some small issues and improved the navbar. [tidusjar] - -- Translated the Requested page #243. [tidusjar] - -- Finished #337. [tidusjar] - -- Some analytics. [tidusjar] - -- More translations for #243 and welcome text for #293. [tidusjar] - -- Small bit of work for #359. [tidusjar] - -- Finished #6. [tidusjar] - -- Analytics and fixes. [tidusjar] - -- Translated the search page #243. [tidusjar] - -- Implemented the different languages and added the ability to change cultures. #243. [tidusjar] - -- Started #243. [tidusjar] - -- Fixed #364. [tidusjar] - -- Some more useful analytical information. [tidusjar] - -- Generic try catch to fix #350. [tidusjar] - -- Slight changes, moved the donate button. [tidusjar] - -- Potential fix for #350. [tidusjar] - -- Better way of obtaining clean enum string. [Drewster727] - -- Fixed #362. [tidusjar] - - -## v1.8.2 (2016-06-22) - -### **New Features** - -- Update readme. [tidusjar] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fixed a circular reference issue. [tidusjar] - -- Small changes around how we work with custom events in the analytics. [tidusjar] - -- Fixed #353 #354 #355. [tidusjar] - -- Null provider check for movies. [Drewster727] - -- Show request type in notifications #346 and fix an issue from previous commit for #345. [Drewster727] - -- Add an option to stop sending notifications for requests that don't require approval #345. [Drewster727] - - -## v1.8.1 (2016-06-21) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fix obj ref error when scheduler runs (ProviderId is null?) [Drewster727] - -- Fix logic for obtaining a sonarr quality profile #340. [Drewster727] - - -## v1.8.0 (2016-06-21) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the new advanced search into the search page too. [tidusjar] - -- Change the way we configure the IoC container in the bootstrapper, we are registering all the concrete instances on application start rather than on each web request. This should increase the performance per HTTP request. [tidusjar] - -- Updated nlog and fixed #295. [tidusjar] - -### **Fixes** - -- Workaround for #334. [Drewster727] - -- Create .gitattributes. [Jamie] - -- Fixes to the issues. [tidusjar] - -- Set the defaults for the landing page. [tidusjar] - -- Revert branch to 664dae2. [tidusjar] - -- Some unit tests for the issues. [tidusjar] - -- Tidied up the bootstrapper. [tidusjar] - -- Fix up landing page UI. [Drewster727] - -- Fixed CSS issue with the top arrow in the Plex theme. [tidusjar] - -- Small changes. [tidusjar] - -- Done #318. [tidusjar] - -- Fixed tests. [tidusjar] - -- #298 added some tests for the landing page. [tidusjar] - -- We are now only keeping the latest 1000 log records in the database. Delete everything else. [tidusjar] - -- Some analytic stuff. [tidusjar] - -- Capture the TVDBID when requesting. [tidusjar] - -- Attempting to improve #219. [tidusjar] - -- Just some more async changes. [tidusjar] - -- Small changes. [tidusjar] - -- More work on #298. Everything wired up. [tidusjar] - -- Fixed the issue on the landing page #298. [tidusjar] - -- #298 moved the content to the left a bit. [tidusjar] - -- Styling for #298 done, just need to wire up the model and do the actual status check. [tidusjar] - -- Bumped up the version number. [tidusjar] - -- Removed some DumpJson() from the trace logs. [tidusjar] - -- Small ui fix (100% width user/password fields to improve mobile experience) [Drewster727] - -- Landing page stuff #298. [tidusjar] - -- Datepicker UI fixes + small landing page UI fix. [Drewster727] - -- Removed a change that shoudn't have been commited. [tidusjar] - -- Fixed tests. [tidusjar] - -- More work for #298. [tidusjar] - -- #273 added for only available content on the search. [tidusjar] - -- Fixed #303 Looks like there was some incorrect business logic. [tidusjar] - -- Most of #273 done. [tidusjar] - -- Settings done for #298. [tidusjar] - -- Started #298. [tidusjar] - -- A crap tonne of work on #273. [tidusjar] - -- More work on #273. [tidusjar] - -- Reduced kept logs for 2 days. [tidusjar] - -- Fixed #300. [tidusjar] - -- #273. [tidusjar] - -- Fixed a bug with some users with the CP profiles. [tidusjar] - -- #273. [tidusjar] - -- Done the same for TV. [tidusjar] - -- Fixes #296. [tidusjar] - -- More for #273. [tidusjar] - -- Small changes. [tidusjar] - -- Revert "Small changes" [tidusjar] - -- Small changes. [tidusjar] - -- Finished #221 and added more async #278. [tidusjar] - -- Spelling mistake in the html! this fixes #264. [tidusjar] - -- More work on #273. [tidusjar] - -- Fixed #210. [tidusjar] - -- Started #273. [tidusjar] - - -## v1.7.5 (2016-05-29) - -### **New Features** - -- Update preview. [Jamie] - -- Updated dapper.contrib. Looks like there was a bug in the async methods. [tidusjar] - -- Updater wouldn't work when running a reverse proxy #236. [tidusjar] - -### **Fixes** - -- Bump build ver. [tidusjar] - -- Use HTTPS for the poster images, so there aren't any mixed content warnings when serving the application via an HTTPS reverse proxy. [Sean Callinan] - -- Removed static declarations. [tidusjar] - -- Fixed styling on modal. [tidusjar] - -- Made the search page all async goodness #278. [tidusjar] - -- Made the request module async #278. [tidusjar] - -- Started some dynamic scrolling. [tidusjar] - -- Stop dumping out the settings to the log. [tidusjar] - -- Made more async goodness. [tidusjar] - -- Made some of the searching async #278. [tidusjar] - -- Fixed #277. [tidusjar] - -- Reworked some tests. [tidusjar] - -- #26q make the auth users list taller. [Drewster727] - -- Fix 404 error. [Drewster727] - -- #262 make the auth users list taller. [Drewster727] - -- #221 delete requests per category. [Drewster727] - -- #256 #237 UI Improvements and consolidation. [Drewster727] - -- Fixed a bug in the user notification where if an admin wants to be notified they wouldn't be. [tidusjar] - -- Set the admin to have all claims. [tidusjar] - -- Fix null exception possibility in cp/sickrage cacher classes. [Drewster727] - -- Fixed #244. [tidusjar] - -- Fixed #240. [tidusjar] - -- Fixed #270. [tidusjar] - -- Fixed an issue where if you have only 1 plex friend it would not show in the list. [tidusjar] - - -## v1.7.4 (2016-05-25) - -### **New Features** - -- Update README.md. [Jamie] - -### **Fixes** - -- Fixed #252. [tidusjar] - -- Fixed #428. [tidusjar] - -- Version bump. [tidusjar] - -- Fixed tests. [tidusjar] - -- Fully fixed #239. [tidusjar] - -- We wan't updating the DB schema. [tidusjar] - - -## v1.7.3 (2016-05-25) - -### **Fixes** - -- Fixed the release build issue where we could not access the settings #239. [tidusjar] - - -## v1.7.2 (2016-05-25) - -### **Fixes** - -- Fixed a small bug where an exception would get thrown. [tidusjar] - -- Build version bump. [tidusjar] - -- Cleanup. [tidusjar] - -- Typo. [tidusjar] - -- Fixed #241. [tidusjar] - -- Fixed #239. [tidusjar] - -- Fixed #238. [tidusjar] - -- Small UI tweaks/improvements. [Drewster727] - - -## v1.7.1 (2016-05-24) - -### **New Features** - -- Update version. [tidusjar] - -### **Fixes** - -- Fixed an issue with the auth page when running with a reverse proxy. [tidusjar] - - -## v1.7 (2016-05-24) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the ability to get the apikey from the api if you provide a correct username and password. Added more unit tests Added the ability to change a users password using the api refactored the Usermapper and made it unit testsable. [tidusjar] - -- Update. [tidusjar] - -- Added in an audit table. Since we are now allowing multiple users to change and modify things we need to audit this. [TidusJar] - -- Added the updater to the soloution and did a bit of starting code. [TidusJar] - -- Updated the claims so we can support more users. Added a user management section (not yet complete) Added the api to the solution and a api key in the settings (currently only gets the requests). [TidusJar] - -- Updated packages. [TidusJar] - -- Added a retry handler into the solution. We can now retry failed api requests. [TidusJar] - -- Update README.md. [Jamie] - -- Added Released propety to RequestViewModel. Added Released filter to the Requests page. [Chris Lees] - -- Added #27 to albums. [tidusjar] - -- Added the actual notification part of #27. [tidusjar] - -- Added the missing baseurl bit on the login page for #72. [tidusjar] - -- Added the 'enable user notifications' to the email settings view and model. [tidusjar] - -- Update README.md. [Jamie] - -### **Fixes** - -- Remove pointless test, change the default theme and fix a small bug. [tidusjar] - -- Fixed api. [tidusjar] - -- Finished #26. [tidusjar] - -- Plex theme. [tidusjar] - -- Implimented a theme changer, waiting for the Plex theme. [tidusjar] - -- Finished #222 #205. [tidusjar] - -- Started working on #26. [tidusjar] - -- Undid some small changes that was checked in by accident. [tidusjar] - -- #164 has been resolved. [tidusjar] - -- Resolved #224 , Removed the 'SSL' option from the email notification settings. We will now use the correct secure socket options (SSL/TLS) for your email host. [tidusjar] - -- Small changes. [tidusjar] - -- #27 fully finished. [tidusjar] - -- Fixed #215. [tidusjar] - -- Using Mailkit to fix #204. [tidusjar] - -- Color. [tidusjar] - -- Fully finished #27 just need to test it! [tidusjar] - -- Fixed test. [tidusjar] - -- Styling for #27. [tidusjar] - -- I think the auto updater is finished! #29. [tidusjar] - -- I think we have finished the main bulk of the auto updater #29. [tidusjar] - -- #222 #205 more ! Started getting the settings out. [tidusjar] - -- Removed the service locator from the base classes and added in some Api tests added all the tests back in! [tidusjar] - -- More work on the api and documentation #222 #205. [tidusjar] - -- Started documenting the API we now have swagger under ~/apidocs #222 #205. [tidusjar] - -- Api work for #205 Refactored how we check if the user has a valid api key Added POST request, PUT and DELTE. [tidusjar] - -- First pass of the updater working. #29. [tidusjar] - -- Removed SIGHUP from the termination list #220. [tidusjar] - -- Fixed. [tidusjar] - -- Missing. [tidusjar] - -- Missed out a file. [TidusJar] - -- And some more... [TidusJar] - -- Missed some files. [TidusJar] - -- A bit more work on switching to using user claims so we can support multiple users. [TidusJar] - -- Made the store backup clean up some of the older backups (> 7 days). [TidusJar] - -- More work on the user management. [TidusJar] - -- - Notifications will no longer be send to the admins if they request something. - Looks like we missed out adding the notifications to Music requests, so I added that in. [TidusJar] - -- - Improved the RetryHandler. - Made the tester buttons on the settings pages a bit more robust and added an indication when it's testing (spinner) [TidusJar] - -- Packages. [TidusJar] - -- Nm, [TidusJar] - -- Downgraded packages. [TidusJar] - -- Better handling for #202. [TidusJar] - -- Finished #208 and #202. [TidusJar] - -- This should help #202. [TidusJar] - -- Resolved #209. [TidusJar] - -- Finished #209. [TidusJar] - -- Slight adjustments to #189. [tidusjar] - -- - Added a visual indication on the UI to tell the admin there is a update available. - We are now also recording the last scheduled run in the database. [tidusjar] - -- Did the login bit on #185. [tidusjar] - -- Finished #186. [tidusjar] - -- Fixed #185. [tidusjar] - -- Fixed issue in #27 with albums. [tidusjar] - -- #27 added TV Search to the notification. [tidusjar] - -- Fixed bug. [tidusjar] - -- More work on #27 Added a new notify button to the search UI (Needs styling). Also fixed a bug where if the user could only see their own requests, if they search for something that has been requested, it will show as requested. [tidusjar] - -- Improved the startup of the application. We now properaly parse any args passed into the console. [tidusjar] - -- Additional cacher error handling + don't bother checking the requests when we don't get data back from plex. [Drewster727] - -- Remove old migration code and added new migration code. [tidusjar] - -- Stop the Cachers from bombing out when the response from the 3rd party api returns an exception or invalid response. #171. [tidusjar] - -- Increase the scheduler cache timeframe to avoid losing cache when the remote api endpoints go offline (due to a reboot or some other reason) -- if they're online, the cache will get refreshed every 10 minutes like normal. [Drewster727] - -- Fix the cacher by adding locking + extra logging in the plex checker + use a const key for scheduler caching time. [Drewster727] - -- Small changes. [tidusjar] - -- Switched out the schedulers, this seems to be a better implimentation to the previous and is easier to add new "jobs" in. [tidusjar] - -- Fixed #168. [tidusjar] - -- Fixed #162. [tidusjar] - -- Fix saving the log level. [Drewster727] - -- Set the max json length (fixes large json response errors) [Drewster727] - - -## v1.6.1 (2016-04-16) - -### **New Features** - -- Update README.md. [Jamie] - -- Added a url base. [tidusjar] - -- Change default logging. [tidusjar] - -- Added logging around SickRage. [tidusjar] - -### **Fixes** - -- Bump up the version number ready for the release. [tidusjar] - -- BaseUrl is finally finished! #72. [tidusjar] - -- #72 Login page done. [tidusjar] - -- More changes for the urlbase #72. [tidusjar] - -- Done the auth, cp, logs and sidebar for #72. [tidusjar] - -- Add an extra check when determining if a tv show is already available (also check if it starts with the show name returned from the tv db) [Drewster727] - -- Cache plex library data regardless of whether we have requests in the database or not. [Drewster727] - -- By default don't use a url base. [tidusjar] - -- Return empty array when obtaining queued IDs in sickrage cacher. [Drewster727] - -- Fixed a small bug in the SR cacher. [tidusjar] - -- Fixed when we do not have a base. [tidusjar] - -- More changes for #72. [tidusjar] - -- Fixed exception and all areas will now use the base url #72. [tidusjar] - -- Removed the test code from #72. [tidusjar] - -- Commented out the unit tests as they need to be reworked now. [tidusjar] - -- Finally fixed #72. [tidusjar] - -- Remove test code from plex api GetLibrary method. [Drewster727] - -- Finished up the caching TODO's. [tidusjar] - -- Kick off the schedulers once the web app has started (fixes api errors on start) [Drewster727] - -- Converted the UI back down to .NET 4.5.2. [tidusjar] - -- Fixed #154. [tidusjar] - -- Revert everything (except PlexRequests.UI) back to .NET 4.5.2 -- fixes incompatibilities with the latest version of mono (4.2.3.4) -- fixes notifications not working #152 #147 #141. [Drewster727] - -- #150 start caching plex media as well. refactored the availability checker. NEEDS TESTING. also, we need to make the Requests hit the plex api directly rather than hitting the cache as it does now. [Drewster727] - -- #150 split out the cache subscriptions to make sure they subscribe properly. [Drewster727] - -- #150 sonarr/sickrage cache checking. sickrage has a couple small items left. [Drewster727] - -- Fixed args. [tidusjar] - -- Fixed. [tidusjar] - -- Made the base better. [tidusjar] - -- Remove couchpotato api test code. [Drewster727] - -- Start the initial couchpotato cache call on a separate thread to keep the startup process quick. [Drewster727] - -- Add csproj with file changes from previous commit. [Drewster727] - -- Cache the couchpotato wanted list, update it on an interval, and use it to determine if a movie has been queued already. [Drewster727] - -- I think i've fixed an issue where SickRage reports Show not found. [tidusjar] - -- Set the default log level to info. #141. [tidusjar] - -- #125 refactor async task logic to work with mono. [Drewster727] - -- Fix search spinner sticking around after clearing search text + make the "Requested" and "Available" indicators in the search page different colors. [Drewster727] - -- #125 start indicating in the results if an item is already requested or available. [Drewster727] - -- #145 firefox css dsplay issue. [Drewster727] - -- Fixes for sonarr, we now display the error messages back to the user. [tidusjar] - -- Fixed #144. [tidusjar] - - -## v1.6.0 (2016-04-06) - -### **New Features** - -- Changed the build number. [tidusjar] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Changed the title to a contains but the artist still must match, [tidusjar] - -- Added unit tests to cover the new changes to the availability checker. [tidusjar] - -- Added the music check in the Plex Checker. [tidusjar] - -- Changed around the startup so we cache the profiles after the DB has been created. [tidusjar] - -- Updated where we update the request blobs schema change. [tidusjar] - -- Update SearchModule.cs. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Change the new columns type. [tidusjar] - -- Added a DBSchema so we have an easier way to update the DB. [tidusjar] - -- Added an issue template. [tidusjar] - -- Update README.md. [Jamie] - -- Added back the username into the Session when the admin logs in. This means they do not have to log in twice. [tidusjar] - -- Added happy path tests for the Checker. [tidusjar] - -- Added music to the search and requests page. [tidusjar] - -- Added a scroll to the top thingy and a bit more work on headphones. [tidusjar] - -- Added some tests and fixed the issue where the DB would get created in the wrong place depending on how you launched the application. [tidusjar] - -- Added the settings page for #32. [tidusjar] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Some final tweaks for #32. [tidusjar] - -- Fixed a bug where if we are the admin we didn't add the request to the db. [tidusjar] - -- Fixed an issue where we would add the Sickrage series but it would fail on adding the seasons. [tidusjar] - -- Properly account for future/past dates when humanizing with moment. [Drewster727] - -- Properly display release date on requests page. [Drewster727] - -- Add missing reference for release mode. [Drewster727] - -- #139 remove dependency and usage of humanize() - should help with cross-platform issues. start using moment.js. [Drewster727] - -- Fix selectors for music list on request page to get sorting working. [Drewster727] - -- Fixed the error #32. [tidusjar] - -- Fixed the logs page. [tidusjar] - -- Another attempt at filtering #32. [tidusjar] - -- A bit more error handling #32. [tidusjar] - -- Improved the availabilty check to include music results #32. [tidusjar] - -- Small changes for #32. [tidusjar] - -- A bit more logging for #32. [tidusjar] - -- More headphones #32 I am starting to hate headphones... Sometimes the artists and albums just randomly fail. [tidusjar] - -- #134 temporary workaround for this. [Drewster727] - -- Task.run for startup caching + fix admin module unit test failures. [Drewster727] - -- Cache injection, error handling and logging on startup, etc. [Drewster727] - -- Tweaks for #32. [tidusjar] - -- #132 auto-approve for admins. [Drewster727] - -- Finished the bulk work for Headphones. Needs testing #32. [tidusjar] - -- Made the album search 10x faster. We are now loading the images in a seperate call. #32. [tidusjar] - -- Add a reference to API Interfaces to fix the build. [tidusjar] - -- #114 start caching quality profiles. Set the cache on startup and when obtaining quality profiles in settings. [Drewster727] - -- Work for #32. [tidusjar] - -- #114 first pass at choosing quality profile when approving + focus search input by default and when switching tabs. [Drewster727] - -- #131 fix for default selected tab. [Drewster727] - -- Remove references to obsolete RequestedBy property + start setting the db schema to the app version, and check that in the future for migrations. [Drewster727] - -- Fixed async issue. [Shannon Barrett] - -- Updating SickRage api to verify Season List is up to date. [Shannon Barrett] - -- Work on showing the requests for #32. [tidusjar] - -- Got the search finished up for #32. [tidusjar] - -- Remove test/temp code in UserLoginModule. [Drewster727] - -- A bit more work on #32 started working on requesting it. The DB is a bit of an issue... [tidusjar] - -- Most of the UI work done for #32. [tidusjar] - -- Basic search working for #32. [tidusjar] - -- Mono datetime offset workaround. [Drewster727] - -- #122 store utc time in the databse + obtain timezone offset of the client upon login + offset times returned to client based on session offset. [Drewster727] - -- Method reference bug fix. [Drewster727] - -- Fix search focus z-index issue (hid suggestions options) [Drewster727] - -- Minor search UI adjustments. [Drewster727] - -- #55 first attempt at "suggestions" starting with "Comming Soon" and "In Theaters" [Drewster727] - -- #106 rename sorting options and polish the dropdown UI a bit. [Drewster727] - -- Started adding the api part for headphones #32. [tidusjar] - -- Upped the time of #123. [tidusjar] - -- First attempt at #123. [tidusjar] - -- We now do not show the text Requested By to the user, we also show a 'success' message instead of a warning when something has already been requested. [tidusjar] - -- Show a "no requests yet" message on the requests page (for each cateogory) [Drewster727] - -- Ignore items that are already available when approving in bulk, and simplify the checking + compile css. [Drewster727] - -- Add a better way to merge RequestedBy and RequestedUsers to avoid code duplication and simplify checks. [Drewster727] - -- Don't query the session as much in the modules, rely on a variable from the base class and store the username as needed. [Drewster727] - -- Show the requested by user from legacy request models. [Drewster727] - -- Only show requested by users to admins + start maintaining a list of users with each request. [Drewster727] - -- #96 fix up notification test feature. [Drewster727] - -- Fix the request page sort/approve button alignment. [Drewster727] - -- When pulling requests, set each to approved that is already available (so the UI avoids showing the approve option for already available content) [Drewster727] - -- Mono doesn't seem to have Tls1.2. Let's try TLS 1 #119. [tidusjar] - -- Specify a protocol type of TLS12. Looks like CP doesn't seem to like SSL3 (it is quite old now so understandable) #119. [tidusjar] - -- Made #85 better. [tidusjar] - -- Fixed the tests. [tidusjar] - -- Made the feedback from Sonarr better when Sonarr already has the series #85. [tidusjar] - -- An attempt to fix #108. [tidusjar] - -- Add some "no results" feedback to the searching + minor UI improvements. [Drewster727] - -- Fix notification tests. [Drewster727] - -- UI - increase icon size of nav menu (they were too small before) [Drewster727] - -- #96 Finished adding test functionality to notifications. [Drewster727] - -- #96 add the necessary back-end code to produce a test message for all notification types (still have to add the test buttons for pushbullet/pushover) [Drewster727] - -- #96 modify notifications interface/service to accept a non-type specific settings object. [Drewster727] - -- #96 Email notification test button (others to come) [Drewster727] - -- Minor UI adjustments. [Drewster727] - -- #84 provide an option in settings to resttrict users from viewing requests other than their own. [Drewster727] - -- #54 comma separated list of users who don't require approval + fix a couple request messages (include show title) [Drewster727] - -- Clean up the sorting option names. add a way to see which filter/sort is currently applied. [Drewster727] - -- Fix up the animations. seems to be related to the data-bound attribute causing the animtions not to fire on each .mix object. [Drewster727] - -- Move approve buttons to the tab content. [Drewster727] - -- Allow approving all requests by category. [Drewster727] - -- Fix up sorting on the request page. [Drewster727] - -- Add ubuntu/debian instructions. [Drewster727] - -- #86 - display movie/show title + year in request notifications. [Drewster727] - -- Show the movie/show title when requesting. [Drewster727] - - -## v1.5.2 (2016-03-26) - -### **Fixes** - -- Stoped users from spamming the request button. [tidusjar] - -- Fixed the logger no longer writing to the file. [tidusjar] - -- Fixed #97. [tidusjar] - - -## v1.5.1 (2016-03-26) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added logs to the sidebar. I'm an idiot. [tidusjar] - -### **Fixes** - -- Approve tv shows or movies. [Drewster727] - -- Fixed a bug where if you had auto approve it wouldn't notify you. [tidusjar] - - -## v1.5.0 (2016-03-25) - -### **New Features** - -- Updated version number for release. [tidusjar] - -- Updated the logic for handling specific seasons in Sonarr and Sickrage. [Shannon Barrett] - -- Updated the readme and added some icons to the navbar. [tidusjar] - -- Added the ability to sepcify a username in the email notification settings for external MTA's. We have had to add a new option called Email Sender because of this. #78. [tidusjar] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added a notification model to the notifiers. Added the backend work for sending a notification for an issue report #75. [tidusjar] - -- Added a subdir to CP, SickRage, Sonarr and Plex #43. [tidusjar] - -### **Fixes** - -- And again. [tidusjar] - -- Made the check actually work. [tidusjar] - -- Finished up #68 and #62. [tidusjar] - -- Finished styling on the logger for now. #59. [tidusjar] - -- Fixed #69. [tidusjar] - -- Working on getting the Sonarr component to work correctly. [Shannon Barrett] - -- Fixes issue #62. [Shannon Barrett] - -- Refactored the Notification service to how it should have really been done in the first place. [tidusjar] - -- Fixed the build. [tidusjar] - -- Finished #49. [tidusjar] - -- Finished #57. [tidusjar] - -- Small changes around the filtering. [tidusjar] - -- Finished adding pushover support. #44. [tidusjar] - -- Resolved #75. [tidusjar] - -- Include DB changes. [tidusjar] - -- Done most on #59. [tidusjar] - -- Lowercase logs folder, because you know, linux. #59. [tidusjar] - -- Adding the imdb when requesting. [tidusjar] - -- Fixed an issue where the table didn't match the model. [tidusjar] - -- Improved the status page with the suggestion from #29. [tidusjar] - -- Hooked up most of #49 Just the validation messages need to be done. [tidusjar] - -- Fixed #74 and #64. [tidusjar] - -- Resolved #70. [tidusjar] - -- Finished #71. [tidusjar] - -- Got the filter working on both movie and tv #57. [tidusjar] - -- Started #57, currently there is a bug where the TV list won't filter. [tidusjar] - - -## v1.4.1 (2016-03-20) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update AvailabilityUpdateService.cs. [Jamie] - - -## v1.4.0 (2016-03-19) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Updated the build version ready for the next release. [tidusjar] - -- Added the api and settings page for Sickrage. Just need to do the tester and hook it up #40. [tidusjar] - -- Added the option to set a CP quality #38. [tidusjar] - -- Added the code to lookup the old requests and refresh them with new information from TVMaze. [tidusjar] - -- Update StatusCheckerTests.cs. [Jamie] - -- Update README.md. [Jamie] - -- Added TVMaze to the search. #21. [tidusjar] - -- Added migration code and cleaned up the DB. [tidusjar] - -- Updated the way we add requests. [tidusjar] - -- Updated the Dapper.Contrib package, it had a bug where it wasn't returning the correct Id from inserts. [tidusjar] - -### **Fixes** - -- This fixes #36. [tidusjar] - -- Should fix issue #36. [Shannon Barrett] - -- When we do a batch update we need to reset the cache. [tidusjar] - -- Fixed an issue where the default quality on Sickrage wouldn't work. [tidusjar] - -- Wow, that was a lot of work. - So, I have now finished #40. - Fixed a bug where we was not choosing the correct tv series (Because of TVMaze) - Fixed a bug when checking for plex titles - Fixed a bug where the wrong issue would clean on the UI (DB was correct) - Refactored how we send tv shows - And too many small changes to count. [tidusjar] - -- Fixed the new dependancy with the admin class tests. [tidusjar] - -- Back to what it was :( [tidusjar] - -- Another test for #37. [tidusjar] - -- This should fix #37. [Jamie Rees] - -- Catch the missing table exception when they have a new DB. [Jamie Rees] - -- Exploratory test for #37. [Jamie Rees] - -- Fixed #33 we now have SSL options for Sonarr and CP. [Jamie Rees] - -- Removed all the html from the new TVMaze api (for overview). Added tests to cover the html removal. updated Readme to remove TheTVDB. [Jamie Rees] - -- Fixed tests. [Jamie Rees] - -- Almost fully integrated TVMaze #21 and also improved the fix for #31. [Jamie Rees] - -- Should fix #28. [Shannon Barrett] - -- Fixed #16 and #30. [tidusjar] - -- Modified the adding of request to update the model with the added ID. [tidusjar] - -- Switched over to the new service. [tidusjar] - -- Fixed #25. [Jamie Rees] - - -## v1.3.0 (2016-03-17) - -### **New Features** - -- Added pushbullet to the sidebar. [Jamie Rees] - -- Updated build version for the next release. [Jamie Rees] - -- Updated readme link. [tidusjar] - -- Added ignore to static tests. [tidusjar] - -- Added Pushbullet notifications #8. [tidusjar] - -- Added first implimentation of the Notification Service #8 Added tests to cover the notification service. [tidusjar] - -- Added validation to the Email settings, also increased the availability checker from 2 minutes to 5. [tidusjar] - -### **Fixes** - -- Fixed #22. [Jamie Rees] - -- Started on #16, nothing is hooked up yet. [tidusjar] - -- Fixed tests. [tidusjar] - - -## v1.2.1 (2016-03-16) - -### **New Features** - -- Update Program.cs. [Jamie] - -- Update Program.cs. [Jamie] - -- Added back the reference. [tidusjar] - -### **Fixes** - -- Removed the email notification settings from the settings (for release 1.2.1) [Jamie Rees] - -- Fixed. [Jamie Rees] - -- Resolved #10. [tidusjar] - - -## v1.2.0 (2016-03-15) - -### **New Features** - -- Updated. [Jamie Rees] - -- Updated appveyor. [Jamie Rees] - -- Update appveyor.yml. [Jamie] - -- Added latest version code and view. Need to finish the view #11. [tidusjar] - -- Added test button to Plex. That's fixed #9. [tidusjar] - -- Added test sonarr button #9. [tidusjar] - -- Added more tests. [tidusjar] - -- Added a bunch of logging. [tidusjar] - -- Added the application tester for CP #9. [tidusjar] - -- Added settings page for #8. [tidusjar] - -- Added pace.js. [tidusjar] - -### **Fixes** - -- Finished the notes! Resolved #7. [Jamie Rees] - -- #12. [Jamie Rees] - -- #12. [Jamie Rees] - -- Finished the status page #11 and some more work to #12. [Jamie Rees] - -- Resolved #7. [tidusjar] - -- Small changes. [tidusjar] - -- Yeah... [tidusjar] - -- Fixed #5 and also added some tests to the availability checker. [tidusjar] - -- Started added tests. [Jamie Rees] - -- Fixed an issue where the issues text appears larger. [Jamie Rees] - - -## v1.1 (2016-03-13) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Updated readme. [Jamie Rees] - -- Added the support for TV Series integrating with Sonarr. [Jamie Rees] - -- Added the functionality to pass a port through an argument. [tidusjar] - -- Added the code to get the quality profiles from Sonarr Started plugging that into the UI. [Jamie Rees] - -- Added the spinners #3. [tidusjar] - -- Added the functionality for the admin to clear the issues. [tidusjar] - -- Added the issues to the requests page. [tidusjar] - -- Added user logout method and unit tests to cover it. [tidusjar] - -- Added DeniedUsers to the view. [tidusjar] - -- Added the denied user check to the UserLoginModule. added a test case to cover it. [tidusjar] - -- Added a missing reference. [tidusjar] - -- Added first real test. [tidusjar] - -- Update README.md. [Jamie] - -- Added the latest version of nuget. [tidusjar] - -- Added travisyml. [tidusjar] - -- Added logging. [tidusjar] - -- Added missing files. [tidusjar] - -- Update README.md. [Jamie] - -- Added logging (Still WIP) [tidusjar] - -- Added favicon and also structured the HTML correctly. [tidusjar] - -- Updated the packages so everything is now with the correct framework (4.5.2) [tidusjar] - -- Added in deletion of requests. [tidusjar] - -- Added test code. [tidusjar] - -- Added dashboard. [tidusjar] - -- Added couchpotato page. [Jamie Rees] - -- Added readme to the project and updated it. [Jamie Rees] - -- Added helpers. [tidusjar] - -### **Fixes** - -- Bug fix, Couchpotato settings wouldn't show in release due to a Nancy bug. [Jamie Rees] - -- Small changes. [Jamie Rees] - -- First release, build 1.0.0. [Jamie Rees] - -- Removed the request limit since it's not currently being used. [Jamie Rees] - -- REmoved Sickbeared for the first release. [Jamie Rees] - -- Fixed #4 We now can manually set the status of a request. [tidusjar] - -- Made the pass in the port a bit more robust. [tidusjar] - -- Styling, Added the functionality for the Sonarr Profiles on the Admin page #2 resolved. [tidusjar] - -- Fixed a bug in the Login and added a unit test to cover that. Added a button to approve an individual request. Fixed some minor bugs in the request screen. [Jamie Rees] - -- Fixed the 'responsive' issue for the search and requests pages #3. [tidusjar] - -- Styling! #3. [tidusjar] - -- Navbar category now will follow you to various screens #3. [tidusjar] - -- Fixed bugs with the 'other' reporting issue and also the clear issues. [tidusjar] - -- We now are appending the users name to who wrote the comment. Rather than it being unknown. [tidusjar] - -- More work on submitting issues. [tidusjar] - -- More test changes. [tidusjar] - -- More tests to cover the login. [tidusjar] - -- Refactoring. [tidusjar] - -- Implimented the password part and authentication with Plex. [tidusjar] - -- Initial Use authentication is working. Need to do the password bit. [tidusjar] - -- Some error handling and ensure we are an admin to delete requests. [tidusjar] - -- Fixed the issue where the Release build would not show the admin screens! [tidusjar] - -- Fixes. [tidusjar] - -- Removed the DI part of the service. TinyIOC doesn't want to work with FluentScheduler. [tidusjar] - -- First pass at the plex update service. [tidusjar] - -- Small changes. [Jamie Rees] - -- Started to impliment the Plex checker. This will check plex every x minutes to see if there is any new content and then update the avalibility of the requests. [Jamie Rees] - -- Mre work. [Jamie Rees] - -- Few small changes, added plex settings. [Jamie Rees] - -- Making the configuration actually do something. Setting a default configuration if there is no DB. [Jamie Rees] - -- Remove post build. [Jamie Rees] - -- Small changes. [Jamie Rees] - -- MOre work. [Jamie Rees] - -- Fixed the issue when sending movies to CouchPotato. [Jamie Rees] - -- Add appveyor. [tidusjar] - -- Build it on 4.5. [tidusjar] - -- Upgraded .net to 4.6. [tidusjar] - -- Typo2. [tidusjar] - -- Typo. [tidusjar] - -- Another update. [tidusjar] - -- Fixed. [tidusjar] - -- More logging to figure out why the we cannot access the admin module in a release build. [tidusjar] - -- Firstpass integrating with CouchPotato. [tidusjar] - -- Some styling. [tidusjar] - -- Fixed the plex friends. Added some unit tests, moved the plex auth into it's own page. [tidusjar] - -- Fully switched the TV shows over to use the other provider. [Jamie Rees] - -- Renamed folders. [tidusjar] - -- Assembly updates. [tidusjar] - -- Moved the rest of the projects. [tidusjar] - -- Moved UI. [tidusjar] - -- Mass rename. [tidusjar] - -- Quick changes. [tidusjar] - -- Started switching the TV over to the new provider (TheTVDB). Currently TV search is partially broken. It will search but we are not mapping all of the details. [tidusjar] - -- Implimented the new TV show Provider (needed for Sonarr TheTvDB) [tidusjar] - -- Started the user auth. [tidusjar] - -- Some work on the requests page. [tidusjar] - -- Made the 'requested' better and made the remove look nicer. [tidusjar] - -- Cleaned up the program a tiny bit. [tidusjar] - -- Removed additional namespace. [tidusjar] - -- Fixed some db issues and added a preview. [Jamie Rees] - -- More work on the settings. [Jamie Rees] - -- Upgraded Json.Net and Nancy packages. [Jamie Rees] - -- Plex friends api. [Jamie Rees] - -- Enabled trace logs. [tidusjar] - -- Sql syntax issue fixed. [tidusjar] - -- Fixed release build. [tidusjar] - -- Small updates including assembly version. [tidusjar] - -- Work on the requests page mostly done. [tidusjar] - -- Work on the TV request. the `latest` parameter is not being passed into the requestTvshow. [tidusjar] - -- Missing file. [tidusjar] - -- Using the IoC container now. [tidusjar] - -- Some plex work. [Jamie Rees] - -- More work. [Jamie Rees] - -- Removed the setup code out of the startup, since we attemtp to connect to the DB before that. [Jamie Rees] - -- Some more work. Need to stop the form submitting on a request. [tidusjar] - -- Moved everything up a directory. [tidusjar] - -- Lots of work! [tidusjar] - -- Done most of the movie search work. [Jamie Rees] - -- First pass with RequestPlex. [tidusjar] - -- Initial commit. [Jamie] - - From cd2011c6ccfa3256942a26973ad458aa54711096 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 7 Apr 2018 00:45:26 +0100 Subject: [PATCH 015/495] !wip fixed lint errors --- .../app/settings/notifications/newsletter.component.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts index fda23208f..7154543fc 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts +++ b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts @@ -57,15 +57,15 @@ export class NewsletterComponent implements OnInit { if(match && match.length > 0) { this.settings.externalEmails.push(this.emailToAdd); this.emailToAdd = ""; - } else{ - this.notificationService.error("Please enter a valid email address") + } else { + this.notificationService.error("Please enter a valid email address"); } } } public deleteEmail(email: string) { - var index = this.settings.externalEmails.indexOf(email); // <-- Not supported in Date: Mon, 9 Apr 2018 12:43:08 +0100 Subject: [PATCH 016/495] Turn off Server GC to hopefully help with #2127 --- src/Ombi/Ombi.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 3b7e7400e..f5e523db7 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -10,7 +10,9 @@ $(FullVer) - + + false + bin\Debug\netcoreapp2.0\Swagger.xml 1701;1702;1705;1591; From 7f12ab5e1436a6d953df0d19a51a9d1e9d967fa4 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Tue, 10 Apr 2018 13:09:07 +0100 Subject: [PATCH 017/495] !wip changelog --- CHANGELOG.md | 3612 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3612 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63cc385a1..8bfe7e633 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ - Made some improvements to the Sonarr Sync job #2127. [Jamie] +- Turn off Server GC to hopefully help with #2127. [Jamie Rees] + - Fixed #2109. [Jamie] - Fixed #2101. [Jamie] @@ -787,3 +789,3613 @@ - Switch to use a single HTTPClient rather than a new one every request !dev. [tidusjar] +- Fix non-admin rights (#1820) [Rob Gökemeijer] + +- Fix duplicated "Requests" element ID on new Issues link (#1817) [Shoghi Cervantes] + +- Add the Issue Reporting functionality (#1811) [Jamie] + +- Removed the forum. [tidusjar] + +- #1659 Made the option to ignore notifcations for auto approve. [Jamie] + +- New Crowdin translations (#1806) [Jamie] + +- Fixed a launch issue. [Jamie] + +- Allow users to login without a password. [Jamie] + +- Fixed the emby notifications not being sent. [Jamie] + +- #1802 and other small fixes. [tidusjar] + +- So... This sickrage thing should work now. [tidusjar] + +- Fixed emby connect login issue. [tidusjar] + +- Stop making unnecessary calls to the update service. [Jamie] + +- Fixed a bug where it blocked users with 0 limits. [Jamie] + +- Done #1788. [tidusjar] + +- More logging. [Jamie] + +- Fixed #1738. [Jamie] + +- Fixed build. [Jamie] + +- Fixed the issue where notifications were not sendind unless we restarted #1732. [tidusjar] + +- Fixed an issue with a trailing space in the subdir. [tidusjar] + +- Fixed #1774. [Jamie] + +- #1773. [Jamie] + +- Roll back rxjs (#1778) [bazhip] + +- Fixed build. [Jamie] + +- Fixed #1763. [Jamie] + +- Fix "content length error" on preview gif (#1768) [OoGuru] + +- New preview gif for Ombi V3 README (#1767) [OoGuru] + +- Remove debug code. [tidusjar] + +- Fix #1762. [tidusjar] + +- Fixed the preset themes not loading. [tidusjar] + +- Fixed #1760 and improvements on the auto updater. We may now support windows services... #1460. [Jamie] + +- Fixed #1754. [Jamie] + +- Hide the subject when it's not being used. [Jamie] + +- Error handling #1749. [Jamie] + +- New Crowdin translations (#1741) [Jamie] + +- #1732 #1722 #1711. [Jamie] + +- Fixed an issue with switching the preset themes. [Jamie] + +- Fixed #1743. [Jamie] + +- Fixed #1742. [tidusjar] + +- Fix #1742. [tidusjar] + +- Fixed landing page. [Jamie] + +- Fixed. [Jamie] + +- Translated the Requests page and fixed #1740. [Jamie] + +- Fix crash. [Jamie] + +- Sickrage done. Ish... So i've written all the code by looking at the API. the key there is i've looked at the api. I have not tested anything so expect this to fail. [Jamie] + +- SickRage settings UI. [Jamie] + +- Fixed #1721. [tidusjar] + +- Fixed the preset themes issue. [tidusjar] + +- New Crowdin translations (#1654) [Jamie] + +- Fix build. [Jamie] + +- #1460. [Jamie] + +- Fixed tests. [Jamie] + +- Return css as MIME text/css. [Jamie] + +- More added for the preset themes. [Jamie] + +- Moved around the custom styles. [Jamie] + +- More renames. [Jamie] + +- Renames. [Jamie] + +- Load the first 100 requests. [Jamie] + +- Reduce the memory consumption #1720. [Jamie] + +- Moved the schedules jobs into it's own database, see if it helps with the db locking #1720. [Jamie] + +- Fixed #1712. [tidusjar] + +- Potential fix for #1702. [tidusjar] + +- Fixed #1708. [tidusjar] + +- Fixed #1677. [tidusjar] + +- Fixed build. [tidusjar] + +- Potential fix for the DB locking issue #1720. [tidusjar] + +- #1698. [Jamie] + +- Fixed #1705. [tidusjar] + +- Fixed #1703. [tidusjar] + +- Finished adding preset themes. [Jamie] + +- Fixed #17000. [Jamie] + +- Remove the themes because waiting for a merge from lerams project. [Jamie] + +- Finsihed adding preset themes. [Jamie] + +- Fixed #1677. [Jamie] + +- Temp fix for #1683. [Jamie] + +- Fixed #1685. [Jamie] + +- Lossless Compression of images saves 83 KB (#1676) [Fish2] + +- Fixed the availability checker. [tidusjar] + +- Fixed build. [tidusjar] + +- Push out missing migration. [tidusjar] + +- Potential fix for #1674. [tidusjar] + +- Fixed an issue with the caching. [tidusjar] + +- Fixed telegram #1667. [tidusjar] + +- Fixed #1663. [tidusjar] + +- Should fix #1663. [tidusjar] + +- Stop logged in users going to the login page. [Jamie] + +- Fixed it not updating. Styles should be good now. [Jamie] + +- Re did some of the styling on the movie search page, let me know your thoughts. [Jamie] + +- Fixed #1657. [Jamie] + +- Fixed #1655. [Jamie] + +- Removed authentication resul. [Jamie] + +- New Crowdin translations (#1651) [Jamie] + +- New Crowdin translations (#1648) [Jamie] + +- New Crowdin translations (#1638) [Jamie] + +- Fixed #1644. [Jamie] + +- Moar logs #1643. [tidusjar] + +- Fixed #1640. [tidusjar] + +- Fixed the null ref exception #1460. [tidusjar] + +- Fixed landing page. [TidusJar] + +- Fixed #1641. [TidusJar] + +- Fixed #1641. [TidusJar] + +- New Crowdin translations (#1635) [Jamie] + +- Fixed #1631 and improved translation support Included startup args for the auto updater #1460 Mark TV requests as available #1632. [tidusjar] + +- Remove 32bit. [Jamie] + +- More 32bit support. [Jamie] + +- We now show "Available" for tv shows that is fully available #1602. [tidusjar] + +- Fixed the issue where we have got an episode but not the related series. #1620. [tidusjar] + +- Fixed the dropdown not working on iOS in the settings #1615. [tidusjar] + +- Fixed sonarr not monitoring the latest season #1534. [tidusjar] + +- Fixed the issue with firefox #1544. [tidusjar] + +- Fixed discord #1623. [tidusjar] + +- Add browserstack thanks (#1627) [Matt Jeanes] + +- Fix the exception #1613. [Jamie] + +- Found where we potentially are setting a new poster path, looks like the entity was being modified and being set as Tracked by entity framework, so the next time we called SaveChangesAsync() it would save the new posterpath on the entity. [Jamie] + +- Small modifications. [Jamie] + +- Fixed #1622. [Jamie] + +- Various improvements to webpack/gulp/vscode support (#1617) [Matt Jeanes] + +- Episodes in requests are now in order #1597 (#1614) [masterhuck] + +- Fixed a null reference issue in the Plex Content Cacher. [Jamie.Rees] + +- Fixed #1610. [tidusjar] + +- Really fixed the build this time. [tidusjar] + +- Fixed build. [tidusjar] + +- Made the updater work again #1460. [tidusjar] + +- Adding logging into the auto updater and also added more logging around the create inital user for #1604. [tidusjar] + +- Fixed the issue where we did not check if they are already in sonarr when choosing certain options #1540. [tidusjar] + +- We can now delete tv child requests and the parent will get remove #1603. [tidusjar] + +- Finished the api changes requested #1601. [tidusjar] + +- Fixed the Hangfire server timeout issue #1605. [tidusjar] + +- Fixed notifications not sending #1594. [tidusjar] + +- Fixed #1583 you can now delete users. Fixed the issue where the requested by was not showing. Finally fixed the broken poster paths. [tidusjar] + +- Fixed the issue where movie requests were no longer being requested. [tidusjar] + +- Started adding some more unit tests #1596. [Jamie.Rees] + +- #1588 When we make changes to any requests that we can trigger a notification, always send it to all notification agents, even if the user wont recieve it. [Jamie.Rees] + +- Add a message when email notifications are not setup when requesting a password reset. #1590. [Jamie.Rees] + +- Removed text that we no longer need. [Jamie.Rees] + +- Fixed #1574. [Jamie.Rees] + +- #1460 looks like the permissions issue has been resolved. Just need to make sure the Ombi process is terminated. [Jamie.Rees] + +- Put back the old download code. [Jamie.Rees] + +- Test. [Jamie] + +- Build sln. [Jamie.Rees] + +- Order by the username #1581. [Jamie.Rees] + +- Remove sonarr episodes from the cache table. [Jamie.Rees] + +- Couchpotato finished. [tidusjar] + +- Disable run import button if no import options are selected. [tidusjar] + +- Fixed #1574. [tidusjar] + +- Fixed build. [tidusjar] + +- Fixes the issue with non windows systems unable to unzip the tarball #1460. [tidusjar] + +- Finished the couchpotato settings. [tidusjar] + +- Fixed build. [tidusjar] + +- Fixed #1570 #1571. [tidusjar] + +- Fixed #1547. [tidusjar] + +- Should fix #1538. [tidusjar] + +- Fixed #1553. [tidusjar] + +- Fixed #1546. [tidusjar] + +- Fixed #1543. [tidusjar] + +- Fixes an issue with Movie caching not working on develop branch of Radarr (#1567) [Jeffrey Peters] + +- This adds two fields to the Email Notifications settings page. It allows for the disabling of TLS/SSL as well as the ability to disable certificate validation when sending notification emails. (#1552) [Jeffrey Peters] + +- Fixed typo (#1551) [Codehhh] + +- Use Sqlite storage for Hangfire. [tidusjar] + +- Fixed the overrides #1539 also display it on screen now too. [tidusjar] + +- Fixed #1542 also added VSCode support. [tidusjar] + +- Fixed some cosmetic issues #865. [Jamie.Rees] + +- Fixed #1531. [Jamie.Rees] + +- Small fixes #865. [Jamie.Rees] + +- Some errors fixed and some ui improvements #865. [tidusjar] + +- Auto-scale large images down to container size (#1529) [Avi] + +- Fix logo on login page. (#1528) [Avi] + +- Another potential issue? :/ [tidusjar] + +- Real fix. [tidusjar] + +- #1513 Added storage path. [Jamie.Rees] + +- Fixed the discord issue relating to images #1513. [Jamie.Rees] + +- Fixed the issue sending movies to Radarr #1513 Fixed typo #1524. [Jamie.Rees] + +- Fixed logo on reset password pages fixed the run importer button on the user management settings. [Jamie.Rees] + +- Fixed crash/error #865. [tidusjar] + +- #1513 fixed the landing page and also the reverse proxy images. [tidusjar] + +- #1513 correctly set the child requests as approved. [tidusjar] + +- Fixed an issue that potentially causes as issue when siging into plex #865. [tidusjar] + +- Remove dev branch. [PotatoQuality] + +- Prepare readme for upcoming beta. [PotatoQuality] + +- #1513 partially fixed a bug. [tidusjar] + +- Fixed the exception. [tidusjar] + +- Fixed the application url not saving #1513. [tidusjar] + +- Fixed liniting. [tidusjar] + +- REVERSE PROXY BITCH! #1513. [tidusjar] + +- Fixed a bug where we were marking the wrong episodes as available #1513 #865. [Jamie.Rees] + +- Fixed an issue where we messed up the pages and routing. [Jamie.Rees] + +- Emby user importer is now therer! #1456. [tidusjar] + +- #1513 Added the update available icon. [tidusjar] + +- Fixed the issue of it showing as not requested when we find it in Radarr. Made the tv shows match a bit more to the movie requests Added the ability for plex and emby users to login Improved the welcome email, will only show for users that have not logged in Fixed discord notifications the about screen now checks if there is an update ready #1513. [tidusjar] + +- Support email addresses as usernames #1513. [Jamie.Rees] + +- Link to issue treath. [PotatoQuality] + +- Give correct feedback when testing email notifications #1513. [Jamie.Rees] + +- Report issue removed and the deny dropdown removed #1513. [Jamie.Rees] + +- #1513 removed the discord text when testing pushbullet. [Jamie.Rees] + +- Made a lot of changes around the notifcations to support the custom app name also started on the welcome email ##1456. [Jamie.Rees] + +- Fixed the bug where we were displaying shows where we do not have enough information to request #1513. [Jamie.Rees] + +- #1513 added the network to tv shows. [Jamie.Rees] + +- Fixed the whitespace issue #1513. [Jamie.Rees] + +- Fixed the swagger endpoint #865 #1513 Fixed the custom image issue on the login page Fixed the bug when clicking on the tab on the requests page it would switch to the wrong one Swagger is now back @ /swagger. [tidusjar] + +- Optimized images, Update old compressed image with a new lossless one. (#1514) [camjac251] + +- #1513 #865 Fixed the issue where we do not send the requests to Radarr/Sonarr when approving. [tidusjar] + +- #1506 #865 Fixed an issue with the test buttons not working correctly. [tidusjar] + +- #865 Added donation link. [tidusjar] + +- Fixed a bunch of issues on #1513. [tidusjar] + +- #1460 Added the Updater, it all seems to be working correctly. #865. [Jamie.Rees] + +- Removed percentage. [Jamie.Rees] + +- Fixed linter. [Jamie.Rees] + +- Fixed some bugs in the UI #865. [Jamie.Rees] + +- Improved the search buttons #865. [Jamie.Rees] + +- More logging #865. [Jamie.Rees] + +- Made build faster. [Jamie.Rees] + +- More logging. [Jamie.Rees] + +- Set debug level to Debug for now. [Jamie.Rees] + +- Add linting and indexes for interfaces/services (#1510) [Matt Jeanes] + +- Fixed the issue with the tv search not working #1463. [Jamie.Rees] + +- Latest practices... also probably broke some styles - sorry (#1508) [Matt Jeanes] + +- Build with the branch version. [tidusjar] + +- Build fix. [tidusjar] + +- Fixed build. [tidusjar] + +- Omgwtf so many changes. #865. [tidusjar] + +- Tests. [Jamie.Rees] + +- #1456 Started on the User Importer Also added the remember me button. [Jamie.Rees] + +- Made some UI changes, reworked the Emby and Plex screens to make them more user friendly and no so fugly. #865 Also made the login page placeholder text slightly lighter. [Jamie.Rees] + +- Cake skip verification build stuff #865. [Jamie.Rees] + +- Some fixes around the UI and managing requests #865. [tidusjar] + +- #1486. [Jamie.Rees] + +- #1486. [Jamie.Rees] + +- Upgraded to .net core 2.0 #1486. [Jamie.Rees] + +- #865 Finished the landing page, we now check the server's status. [Jamie.Rees] + +- Fixed build. [TidusJar] + +- Removed the telegram api. [Jamie.Rees] + +- Small changes on the updater #1460 #865. [Jamie.Rees] + +- Remove unused functions. [Dhruv Bhavsar] + +- Make Episode picker similar to Requests Child view. #1457 #1463. [Dhruv Bhavsar] + +- Fix merge conflict for TvRequests component. [Dhruv Bhavsar] + +- Upstream Changes... [Dhruv Bhavsar] + +- Clean up Requests page code by moving children request to old component, remove additional REST calls when merging and update component names to make more sense. [Dhruv Bhavsar] + +- Lots of different UI enhancements and fixes #865. [tidusjar] + +- Gitchangelog. [tidusjar] + +- Fixed the issue where we were using the wrong availability options. [tidusjar] + +- Fixed a bunch of bugs in Ombi #865. [tidusjar] + +- Build versioning. [Jamie.Rees] + +- #1460 The assembly versioning seems to work correctly now. [Jamie.Rees] + +- More build versioning changes #865. [tidusjar] + +- Fixed cake script. [Jamie.Rees] + +- WIP on the build versioning for the Updater #1460 #865. [Jamie.Rees] + +- Versioning. [Jamie.Rees] + +- Package versions. [Jamie.Rees] + +- #1460 #865 working on the auto updater. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Small changes around the roles #865. [tidusjar] + +- Improvements to the UI and also finished the availability checker #865 #1464. [Jamie.Rees] + +- Availability Checker #1464 #865. [Jamie.Rees] + +- Fixed ##1492 and finished the episode searcher for #1464. [Jamie.Rees] + +- #1464. [tidusjar] + +- Reload the settings #1464 #865. [Jamie.Rees] + +- #1464 added the Plex episode cacher #865. [Jamie.Rees] + +- Fixed some issues around the tv requests area Added mattermost and telegram notifications #1459 #865 #1457. [tidusjar] + +- Fix global.json. [Dhruv Bhavsar] + +- Working UI for Requests. Approval/Deny does not work as it doesn't in your code either. [Dhruv Bhavsar] + +- Enable diagnostic on build #865. [Jamie.Rees] + +- Fixed the user token issue #865. [Jamie.Rees] + +- Some small refresh token work #865. [Jamie.Rees] + +- Initial TV Requests UI rebuild. [Dhruv Bhavsar] + +- Made a start on supporting multiple emby servers, the UI needs rework #865. [Jamie.Rees] + +- #865 #1459 Added the Sender From field for email notifcations. We can now have "Friendly Names" for email notifications. [Jamie.Rees] + +- Redirect to the landing page when enabled #1458 #865. [Jamie.Rees] + +- Removed IdentityServer, it was overkill #865. [Jamie.Rees] + +- Fixed another bug with identity. #865 I'm thinking about removing it. Causing more hassle than it's worth. [tidusjar] + +- #1460 #865. [tidusjar] + +- Delete appveyor_old.yml. [Jamie] + +- Fixed path. [Jamie.Rees] + +- Silent build level. [Jamie.Rees] + +- #1459 Forgot to get the Pushbullet agent to look up the pusbullet templates rather than the Discord ones. Updated the Gitchange log. [Jamie.Rees] + +- Made the placeholder color on the login page a bit lighter #865. [Jamie.Rees] + +- Landing and login page changes #865 #1485. [tidusjar] + +- #1458 #865 More work on landing. [Jamie.Rees] + +- Working on the landing page #1458 #865. [tidusjar] + +- A lot of clean up and added a new Image api #865. [Jamie.Rees] + +- Cleaned up the Logging API slightly #1465 #865. [Jamie.Rees] + +- Fixed the Identity Server discovery bug #1456 #865. [tidusjar] + +- Fixed the issue with the Identity Server running on a different port, we can now use -url #865. [Jamie.Rees] + +- Try again. [TidusJar] + +- Publish ubuntu 16.04. [Jamie.Rees] + +- Chnaged the updater job from Minutely to Hourly. [Jamie.Rees] + +- Some work around the Auto Updater and other small changes #1460 #865. [Jamie.Rees] + +- Missed a file. [tidusjar] + +- Fixed the swagger issue. [tidusjar] + +- RDP issues. [tidusjar] + +- Appveyor build rdp investigation. [tidusjar] + +- Working on the requests page #1457 #865. [tidusjar] + +- Made the password reset email style the same as other email notifications #1456 #865. [Jamie.Rees] + +- Fixed some bugs around the authentication #1456 #865. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Fixed build #1456. [Jamie.Rees] + +- #1456 #865 Started on allowing Plex Users to sign in through the new authentication server. [Jamie.Rees] + +- Removed covalent. [Jamie.Rees] + +- #1456 Reset Password stuff #865. [Jamie.Rees] + +- Finished implimenting Identity with IdentityServer4. #865 #1456. [Jamie.Rees] + +- Moved over to using Identity Server with Asp.Net Core Identity #1456 #865. [Jamie.Rees] + +- Started on the requests rework #865. [Jamie.Rees] + +- Extended the Emby API. [Jamie.Rees] + +- Started reworking the usermanagement page #1456 #865. [tidusjar] + +- Lots of refactoring #865. [Jamie.Rees] + +- Created an individual user api endpoint so we can make the user management pages better #865. [TidusJar] + +- Lot's of refactoring. [Jamie.Rees] + +- #1462 #865 Had to refactor how we use notificaitons. So we now have more notification fields about the request. [Jamie.Rees] + +- Looks like Sonarr is finished and works. A lot simplier this time around. #865. [tidusjar] + +- More work on the Sonarr Api Integration #865. [tidusjar] + +- Started on sonarr #865. [tidusjar] + +- Small changes #865. [tidusjar] + +- Damn son. So many changes... Fixed alot of stuff around tv episodes with the new DB model #865. [tidusjar] + +- Fixed the TV Requests issue #865. [Jamie.Rees] + +- Fixed a load of bugs need to figure out what is wrong with tv requests #865. [tidusjar] + +- #865 rework the backend data. Actually use real models rather than a JSON store. [Jamie.Rees] + +- Fixed the build issue #865. [tidusjar] + +- Allow us to use Emby as a media server. [tidusjar] + +- More Update #865. [Jamie.Rees] + +- Deployment changes. [Jamie.Rees] + +- More work on the Updater. [Jamie.Rees] + +- Lots of fixes. Becoming more stable now. #865. [tidusjar] + +- Small fixes around the searching. [Jamie.Rees] + +- Some rules #865. [Jamie.Rees] + +- Oops. [TidusJar] + +- Started on the Discord API settings page. [TidusJar] + +- Email Notifications are now fully customizable and work! #865. [Jamie.Rees] + +- Small changes and fixed some stylingon the plex page #865. [Jamie.Rees] + +- More on #865 TODO, Find out whats going on with the notifications and why exceptions are being thrown. [Jamie.Rees] + +- Oops. [Jamie.Rees] + +- Ok #865 fixed the published exe. [Jamie.Rees] + +- Fixed errors. [Jamie.Rees] + +- Fixed build script. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Some more #865. [Jamie.Rees] + +- Create appveyor.yml. [Jamie] + +- The Approving child requests now work! [Jamie.Rees] + +- Fixed many bugs #865. [Jamie.Rees] + +- Loads of changes, improved the movie search stylings is back. [Jamie.Rees] + +- Moved to webpack and started on new style. [Jamie.Rees] + +- Fixed the TV search via Trakt not returning Images anymore. #865. [Jamie.Rees] + +- Rules changes and rework. [Jamie.Rees] + +- Request Grid test. [Jamie.Rees] + +- Small cleanup #865. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Started the Radarr Settings #865. [Jamie.Rees] + +- Massive amount of rework on the plex settings page. It's pretty decent now! #865. [tidusjar] + +- Fixed build. [Jamie.Rees] + +- Fixed build. [tidusjar] + +- Rules #865. [tidusjar] + +- Stuff. [Jamie.Rees] + +- Forgot to uncomment. [Jamie.Rees] + +- Tetsd. [Jamie.Rees] + +- Build task changes. [Jamie.Rees] + +- Adsa. [Jamie.Rees] + +- Appveyor. [Jamie.Rees] + +- Stuff around tokens and also builds. [Jamie.Rees] + +- Finished the Plex Content Cacher. Need to do the episodes part but things are now showing as available! #865. [tidusjar] + +- Small user changes #865. [Jamie.Rees] + +- Stuff #865 need to work on the claims correctly. [Jamie.Rees] + +- Reworked the TV model AGAIN #865. [Jamie.Rees] + +- The move! [Jamie.Rees] + +- Fixed build #865. [Jamie.Rees] + +- Fixed the user management #865. [Jamie.Rees] + +- #865 Added support for multiple plex servers. [Jamie.Rees] + +- Bleh. [tidusjar] + +- Small changes. [Jamie.Rees] + +- Fixed the build. [Jamie.Rees] + +- Fixes. [Jamie.Rees] + +- Bundling changes. [Jamie.Rees] + +- Some series information stuff, changes the pace theme too. [Jamie.Rees] + +- Docker support and more, redesign the episodes. [tidusjar] + +- Stuff around episode/season searching/requesting. [Jamie.Rees] + +- Removed redundant folders. [tidusjar] + +- Lots of backend work. [tidusjar] + +- Fixed build. [Jamie.Rees] + +- TV Request stuff. [Jamie.Rees] + +- Work around the user management. [tidusjar] + +- More. [Jamie.Rees] + +- Lots and Lots of work. [Jamie.Rees] + +- Diagnostic changes. [tidusjar] + +- Fixed hangfire exception. [tidusjar] + +- Remove xunit. [tidusjar] + +- Lots more work :( [Jamie.Rees] + +- More changes. [tidusjar] + +- #865. [Jamie.Rees] + +- Small changes. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- More mapping. [Jamie.Rees] + +- Mapping mainly. [Jamie.Rees] + +- Fix systemjs config not being included. [Matt Jeanes] + +- Fixed bundling and various improvements. [Matt Jeanes] + +- Finished the emby wizard #865. [tidusjar] + +- Finished the wizard #865 (For Plex Anyway) [tidusjar] + +- Small changes. [tidusjar] + +- More work on Wizard and Plex API #865. [tidusjar] + +- Settings. [Jamie.Rees] + +- Settings for Ombi. [Jamie.Rees] + +- Fixed some issues around the identity. [Jamie.Rees] + +- #865 more for the authentication. [tidusjar] + +- Auth. [Jamie.Rees] + +- More on the search and requests page. It's almost there for movies. Need to add some filtering logic #865. [tidusjar] + +- #865. [Jamie.Rees] + +- Fixed build. [tidusjar] + +- Messing around with the settings. [tidusjar] + +- Fixed the yml. [Jamie.Rees] + +- Remove unneeded bundle config. [Matt Jeanes] + +- Redo dotnet publish targets. [Jamie.Rees] + +- Bundling changes. [Jamie.Rees] + +- Stuff. [Jamie.Rees] + +- Move app into wwwroot. [Jamie.Rees] + +- Put uglify back in! [Jamie.Rees] + +- Wrong line. [Jamie.Rees] + +- Matt is helping. [Jamie.Rees] + +- Revert. [tidusjar] + +- Small tweaks. [tidusjar] + +- Upgrade to .Net Standard 1.6. [tidusjar] + + +## v2.2.1 (2017-04-09) + +### **New Features** + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added the forums. [tidusjar] + +- Updates. [tidusjar] + +- Update gulpfile.js. [Jamie] + +- Update gulpfile.js. [Jamie] + +- Update gulpfile.js. [Jamie] + +- Update gulpfile.js. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Update gulpfile.js. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added a retry policy around the emby newsletter. [Jamie.Rees] + +### **Fixes** + +- Revert "Merge branch 'DotNetCore' into dev" [tidusjar] + +- More borken build. [Jamie.Rees] + +- Started adding requesting. [Jamie.Rees] + +- Done the movie searching. [tidusjar] + +- #865. [tidusjar] + +- More. [tidusjar] + +- Moar. [tidusjar] + +- Small changes. [tidusjar] + +- Styling. [Jamie.Rees] + +- MOre changes. [Jamie.Rees] + +- Spacing. [Jamie.Rees] + +- Try again. [Jamie.Rees] + +- More. [Jamie.Rees] + +- Again. [Jamie.Rees] + +- Anbother. [Jamie.Rees] + +- Another. [Jamie.Rees] + +- Another. [Jamie.Rees] + +- Retry. [Jamie.Rees] + +- A. [Jamie.Rees] + +- Fixed. [Jamie.Rees] + +- Cahnge 2. [Jamie.Rees] + +- Appveyor change. [Jamie.Rees] + +- The start of a new world. [Jamie.Rees] + +- Fixed the migration number and order by the added date for the newsletter #1264. [tidusjar] + +- Forgot this change. [tidusjar] + +- Also fixed the issue for the Emby Newsletter where episodes were not getting added :( [tidusjar] + +- #1264 "They may take our lives, but they'll never take our freedom!" [tidusjar] + +- Finished reworking the Sonarr Integration. Seems to be working as expected, faster and most stable. It's Not A Toomah! [tidusjar] + +- Small bit of work. [Jamie.Rees] + +- Made a start on the new Sonarr integration. [tidusjar] + +- For test emails, if there is no new content then just grab some old data. [tidusjar] + +- Fixed an issue where the emby newsletter was always showing series. [tidusjar] + + +## v2.2.0 (2017-03-30) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added a new setting for the Netflix option, we can now disable it appearing in the search. [tidusjar] + +- Update German Translation. [Marius Schiffer] + +- Added a release notes page, you can access via Admin>Updates>Recent Changes tab. Note to self, need to put better comments in for users to understand! [Jamie.Rees] + +- Added gravitar image. [Jamie.Rees] + +- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] + +- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] + +- Added some logging around API calls. [smcpeck] + +- Changed IEmbyAvailabilityChecker to use IEnumberables + checking actor search against Emby content + PR feedback. [smcpeck] + +- Changed actor searching to support non-actors too. [smcpeck] + +- Added a 10 second timer to refresh some new caching I put in. [smcpeck] + +- Added root folder and approving quality profiles in radarr #1065. [tidusjar] + +- Added some debugging code around the newsletter for Emby #1116. [tidusjar] + +- Added a TMDB Rate limiter for the newsletter. [tidusjar] + +- Added port check in wizard. also fixed favicon. [tidusjar] + +- Update Radarr placeholder. [d2dyno] + +- Added the user login for emby users #435. [tidusjar] + +- Added User Management support for Emby #435. [tidusjar] + +- Added emby to the sidebar #435. [tidusjar] + +- Added API endpoint for /actor/new/ to support searching for movies not already available/requested. [smcpeck] + +- Update ISSUE_TEMPLATE.md. [Jamie] + +- Update README.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +### **Fixes** + +- Translation changes. [Jamie.Rees] + +- Syntax error. [tidusjar] + +- Fixed an issue where we were retrying the API call when the Plex users login creds were invalid. #1217. [tidusjar] + +- Slightly increased the wait time for the emby newsletter also fixed a potential error in the plex user checker. [Jamie.Rees] + +- Fixed an issue where we were not notifiying emby users. [Jamie.Rees] + +- Fixed the issue where the recent changes page was not showing the correct date. #1296. [Jamie.Rees] + +- Fixed #1252 (Show the correct user type on the management page for Plex Users) [Jamie.Rees] + +- Fixed the casting error #1292. [Jamie.Rees] + +- Fix test newletter not sending when empty. [Dhruv Bhavsar] + +- Quick fix for email false positive message. ISSUE: #1286. [Dhruv Bhavsar] + +- Fixes around the newsletter. We will now correctly show newly added shows and also newly added episodes. #1163. [tidusjar] + +- Fixed a sonarr deseralization error. [tidusjar] + +- Increased the delay for the Episode information api calls. #1163. [tidusjar] + +- Looks like we were overloading emby with out api calls. [tidusjar] + +- Fixed the root path escaping issue for Radarr too! [tidusjar] + +- Some small backend newsletter changes, we can now detect if there are any movies and/or tv shows, if there are none then we will no longer send out an empty newsletter. [Jamie.Rees] + +- Remoddeled the notificaiton settings to make it easier to add more. This is some techinical changes that no one except me will ever notice :( [Jamie.Rees] + +- Fixed #1234. [Jamie.Rees] + +- A fix to the about page and also started to rework the notification backend slightly to easily add more notifications. [Jamie.Rees] + +- Adding more logging into the Plex Cacher. [Jamie.Rees] + +- #1218 changed the text when we cannot display release notes for dev and EAP branches. [Jamie.Rees] + +- Fix for #1236. [SuperPotatoMen] + +- Tooltips. [Jamie.Rees] + +- #236. [Jamie.Rees] + +- #1102. [Jamie.Rees] + +- Done #1012. [Jamie.Rees] + +- Oops #1134. [Jamie.Rees] + +- Fixed #1121. [Jamie.Rees] + +- Fixed #1210. [Jamie.Rees] + +- Fixed typo #1134. [Jamie.Rees] + +- Fixed #1223. [Jamie.Rees] + +- Another newsletter fix attempt #1163 #1116. [tidusjar] + +- Fixup! Reset the branch on v2.1.0 tag to get to a shared state between dev and Master. [distaula] + +- Fixed a bug in the Plex Newsletter. [tidusjar] + +- Typo. [tidusjar] + +- Fixed around the newsletter and a small feature around the permissions/features (#1215) [Jamie] + +- Fixed #1189. [tidusjar] + +- Fixed #1195. [Jamie.Rees] + +- Fixed #1195. [Jamie.Rees] + +- Fixed #1192. [Jamie.Rees] + +- Fixed issue where we could get null rating keys on Plex. [tidusjar] + +- Needed to treat a 201 as success, too. + removed some commented out code. [Shaun McPeck] + +- Normalized spacing/tabs. [smcpeck] + +- Move local user login to be the first thing checked; renamed old Api variable to PlexApi now that Emby is in play. [smcpeck] + +- Remove all the polling/retry logic around HP requests. This was a problem do to not properly awaiting the initial AddArtist API call being sent to HP. Also fix SetAlbumStatus to use ReleaseId instead of MusicBrainsId (same fix previously applied to AddArtist). [smcpeck] + +- Restore checking of HTTP StatusCode on ApiRequests; remove checking of response.ErrorException. [smcpeck] + +- Reverted (for now) non-200 response handling; added some extra logging. [smcpeck] + +- Tweaked ApiRequest behavior on non-200 responses; think it was breaking login. :-" [smcpeck] + +- Only deserialize response payload in ApiRequest when StatusCode == 200. Will a default return value in other cases cause other issues? [smcpeck] + +- Headphones - added releaseID to generic RequestedModel and passing that through to HP request. Their API doesn't request via the MusicBrainzId. [smcpeck] + +- Fixed #1038. [tidusjar] + +- Fixed a slight issue where we could click the change folders button rather than the dropdown arrow #1189. [tidusjar] + +- Bunch of updater files. [tidusjar] + +- #1163 #117. [tidusjar] + +- Removed some unnecessary 'ConfigureAwait` uses. [smcpeck] + +- Remove meaningless html class from actor searching checkbox. [smcpeck] + +- Fixed an issue where we were not always showing movies from external programs. [tidusjar] + +- Remove extra delay when filtering out existing movies. [smcpeck] + +- Post merge build fixes. [smcpeck] + +- Fix. [tidusjar] + +- Fixed #1177. [tidusjar] + +- Fixed #1152. [tidusjar] + +- Fixed #1123. [tidusjar] + +- Fixed a bug when sending to radarr. [tidusjar] + +- Fixed #1133. [tidusjar] + +- Fixed issues img. [Jamie.Rees] + +- Stop Plex being enabled on the first time installing #1048. [Jamie.Rees] + +- The landing page now works for emby #435. [tidusjar] + +- Fixed #1104. [tidusjar] + +- Fixed #1090. [tidusjar] + +- Fixed #1103. [tidusjar] + +- Small changes. [tidusjar] + +- Break out Mass Email feature into its own tab, upgrade Font Awesome and clean up some comments. [dhruvb14] + +- Fix typo. [Travis Bybee] + +- Fixed #1066. [Jamie.Rees] + +- Fixed broken builds. [Jamie.Rees] + +- Fixed #1083. [Jamie.Rees] + +- #1049. [tidusjar] + +- Fixed #1071. [tidusjar] + +- Fixed #1048 #1081. [tidusjar] + +- #1074. [Jamie.Rees] + +- #1069. [Jamie.Rees] + +- Fix for #1068. [tidusjar] + +- Remove duplciate tv show status. [tidusjar] + +- Some request ui changes. [tidusjar] + +- Removed references to Plex. [tidusjar] + +- Removed plex from the scheduled jobs ui. [tidusjar] + +- First run of the newsletter set it to a test. [tidusjar] + +- Reworked the newsletter for Emby! Need to rework it for Plex and use the new way to do it. [tidusjar] + +- Fixed build. [tidusjar] + +- Fixed the mass email, it was only being set to users with the newsletter feature #358. [tidusjar] + +- Removed Plex Request from the notifications. [tidusjar] + +- Finish implementing mass email feature. [dhruvb14] + +- @tidusjar pointed out runtime error!! [dhruvb14] + +- Does not compile, need to get data from UI into nancy somehow and figure out why IMassEmail is not initializing. [dhruvb14] + +- Begin Implementing Mass Email Section. [dhruvb14] + +- Hide the auto update btn #236 Fixed where we were not populating the emby episodes #435. [tidusjar] + +- Fix Radarr labels. [d2dyno] + +- Fixed pace loader. [Jamie.Rees] + +- Check if Emby/Plex is enabled before starting the job. [Jamie.Rees] + +- Fixed #1036. [Jamie.Rees] + +- Fixed a typo and changed wording. [Torkil Liseth] + +- Fixed #1035. [Jamie.Rees] + +- Fix for #1026. [Jamie.Rees] + +- Fixed #1042. [tidusjar] + +- #435. [Jamie.Rees] + +- #435 Started the wizard. [Jamie.Rees] + +- Removed. [tidusjar] + +- Final Fixes. [dhruvb14] + +- Partial fix for broken HR tag's in Email... [dhruvb14] + +- DAMN! #435 that's a lot of code! [tidusjar] + +- Started adding Emby, Lots of backend work done. Need a few more services done and login and user management. #435. [tidusjar] + +- UI changes to add checkbox and support searching for only new matches via new API. [smcpeck] + +- REFACTOR: IAvailabilityChecker - changed arrays to IEnumerables. [smcpeck] + +- UI changes to consume actor searching API. [smcpeck] + +- API changes to allow for searching movies by actor. [smcpeck] + +- Enforcing async/await in synchronous methods that were marked async. [smcpeck] + + +## v2.1.0 (2017-01-31) + +### **New Features** + +- Update README.md. [Jamie] + +- Update .gitattributes. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added the new labels to the search. [tidusjar] + +- Added a switch to use the new search or not, just in case people do not like it. added a migration to turn on the new search. [Jamie.Rees] + +- Added a bunch of categories for tv search similar to what we have for movies. [Jamie.Rees] + +### **Fixes** + +- Fixed typos. [Haries Ramdhani] + +- Fix typo in readme. [tdorsey] + +- Fixed #985. [Jamie.Rees] + +- FIxed #978. [tidusjar] + +- Fixed the approval issue for #939. [tidusjar] + +- Some general improvements. [tidusjar] + +- Turned off migration for now. [tidusjar] + +- Fixed #998. [tidusjar] + +- Additional movie information. [Jamie.Rees] + +- Debug info around the notifications. [Jamie.Rees] + +- Small changes. [tidusjar] + +- Fixed #995. [tidusjar] + +- Fix for #978. [tidusjar] + +- Fixed #991. [tidusjar] + +- Fixed the login issue and pass Radarr the year #990. [Jamie.Rees] + +- More small tweaks around the username/alias. [Jamie.Rees] + +- Possible issue with the empty username. [Jamie.Rees] + +- Potential Fix for #985. [Jamie.Rees] + +- Small changed to the sidebar. [Jamie.Rees] + +- Small changes. [Jamie.Rees] + +- Done #627. [Jamie.Rees] + +- Finished #535 #445 #170. [tidusjar] + +- Fixed tests. [Jamie.Rees] + +- Started to add the specify Sonarr root folders. [Jamie.Rees] + +- Fixed #968. [Jamie.Rees] + +- Fixed #970. [Jamie.Rees] + +- Done #924. [Jamie.Rees] + +- Fixed. [Jamie.Rees] + +- Fixed #955. [Jamie.Rees] + +- #956. [Jamie.Rees] + +- Fixed #947. [Jamie.Rees] + +- #951. [tidusjar] + +- Finished #923 !!! [tidusjar] + +- More for #923. [Jamie.Rees] + +- Radarr integartion in progress #923. [tidusjar] + +- Fixed #940 don't show any shows without a tvdb id. [tidusjar] + +- Finished #739. [Jamie.Rees] + +- Initial impliementation of #739. [Jamie.Rees] + +- Improved the search UI and made it more consistant. Finished the Netflix API Part #884. [Jamie.Rees] + + +## v2.0.1 (2017-01-16) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Added a netflix api. [Jamie.Rees] + +### **Fixes** + +- Fixed #934. [Jamie.Rees] + + +## v2.0 (2017-01-14) + +### **New Features** + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Added the settings for #925 but need to apply the settings to the UI. [Jamie.Rees] + +- Changed the settings name from Plex Requests to Ombi. [Jamie.Rees] + +- Added support for Managed Users #811. [Jamie.Rees] + +- Change solution name in travis. [mhann] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +### **Fixes** + +- Finished #925. [Jamie.Rees] + +- Some TODO's. [Jamie.Rees] + +- Fixed #915. [Jamie.Rees] + +- Fixed the issue where notifications are not being sent to users with Aliases #912. [Jamie.Rees] + +- Fixed #891. [Jamie.Rees] + +- Fix indentation issue. [Marcus Hann] + +- Implement simple button. [Marcus Hann] + +- Plex Username Case Sensitivity Fix. [thegame3202] + +- Fixed #882. [Jamie.Rees] + +- Api changed again, so more fixes for #878. [Jamie.Rees] + +- Possible fix for #893. [Jamie.Rees] + +- Fixed #898. [Jamie.Rees] + +- Fixed #878. [TidusJar] + +- * userManagementController.js: fixed #881. [TidusJar] + +- More work on watcher, should all be good now. #878. [Jamie.Rees] + +- Delete PlexRequests.sln.DotSettings. [Jamie] + +- Fixed #862. [Jamie.Rees] + +- #399 and #398 finished. [Jamie.Rees] + +- More work on #399. [Jamie.Rees] + +- Finished #884. [Jamie.Rees] + +- More for #844. [Jamie.Rees] + +- Another #844. [Jamie.Rees] + +- Fixed a dependancy issue with #844. [Jamie.Rees] + +- Finished the main part of #844 just need testing. [Jamie.Rees] + +- Fixed #832. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Fix tiny readme typo. [mhann] + +- Fixed #850 also started #844 (Wrote the API interaction) [Jamie.Rees] + +- #801 #292 done. [Jamie.Rees] + +- Should fix #841 #835 #810. [Jamie.Rees] + +- Fix small typo in ticket overview page. [mhann] + +- More work on the combined login. [Jamie.Rees] + +- Fixed db issue. [Jamie.Rees] + +- Name changes. [Jamie.Rees] + +- All Sln changes. [tidusjar] + +- Moved API Sln dir. [tidusjar] + +- Fixed build. [tidusjar] + +- Moved namespaces. [tidusjar] + +- Renamed zip. [tidusjar] + +- Product name change. [tidusjar] + + +## v1.10.1 (2016-12-17) + +### **Fixes** + +- #788 fixed! [tidusjar] + +- Fixed #788 and #791. [tidusjar] + +- #399 #398. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Small refactorings. [Jamie.Rees] + +- #782. [Jamie.Rees] + +- #785. [Jamie.Rees] + + +## v1.10.0 (2016-12-15) + +### **New Features** + +- Update README.md. [Jamie] + +- Added optional launch args for the auto updater. [Jamie.Rees] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update _Navbar.cshtml. [Jamie] + +- Update README.md. [Jamie] + +- Update _Navbar.cshtml. [Jamie] + +- Update README.md. [Jamie] + +- Added a new permission to bypass the request limit. [Jamie.Rees] + +- Update Version1100.cs. [SuperPotatoMen] + +- Added logging around the Newsletter #717. [Jamie.Rees] + +- Added missing migration. [tidusjar] + +- Added loading spinner. [Jamie.Rees] + +- Update UI.resx. [SuperPotatoMen] + +- Update Version1100.cs. [Jamie] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +### **Fixes** + +- Fixed an issue where the HTML in the newsletter was incorrect. [Jamie.Rees] + +- Fixed #201. [Jamie.Rees] + +- Fixed #720 and added better error handling around the migrations. [Jamie.Rees] + +- Fixed #769. [Jamie.Rees] + +- Write out the actual file version. [Jamie.Rees] + +- Error checking around GA. [TidusJar] + +- Fixed #761. [tidusjar] + +- Fixed #749 Fixed an issue where we were adding the read only permission when creating the admin. [tidusjar] + +- Fixed #757. [tidusjar] + +- Fixes around the server admin #754. [Jamie.Rees] + +- Removed the trace option from the UI, it is only accessible when appending the url with "?developer" #753. [Jamie.Rees] + +- Fixed an issue where the admin could not be updated. [Jamie.Rees] + +- Fixed #745. [Jamie.Rees] + +- Fixed #748. [Jamie.Rees] + +- Workaround for #748. [SuperPotatoMen] + +- Another attempt to fix #717. [tidusjar] + +- Fixed #744. [Jamie.Rees] + +- Tidied up the warnings. [Jamie.Rees] + +- Small bit of analytics. [Jamie.Rees] + +- Removed the whitelist. [Jamie.Rees] + +- Should fix #696 Fixed an issue with the scheduled jobs where it could use a different trigger if the order between the schedules and the triggers were in different positions in the array... Stupid me, ordering both arrays by the name now. [tidusjar] + +- Some better null object handling #731. [Jamie.Rees] + +- Small tweaks. [Jamie.Rees] + +- Fixed #728. [Jamie.Rees] + +- Fixed #727. [Jamie.Rees] + +- Fixed admin redirect issue. [tidusjar] + +- Fixed #718. [tidusjar] + +- Lots of small fixes and tweaks. [Jamie.Rees] + +- Tidied up some of the angular code, split the UI into it's own directives for easier maintainability. [Jamie.Rees] + +- Small tweaks to the Request Page. [Jamie.Rees] + +- Reverted the PR that may have caused #619. [Jamie.Rees] + +- Some small tweaks around #218 Just added the link to the settings and some angular improvements. [Jamie.Rees] + +- Test. [Jamie.Rees] + +- Attempt at fixing #686. [Jamie.Rees] + +- Finished #707. [Jamie.Rees] + +- Fixed #704. [Jamie.Rees] + +- Fixed #705. [Jamie.Rees] + +- Fixed #706. [Jamie.Rees] + +- #547. [Jamie.Rees] + +- Default tabs #304. [Jamie.Rees] + +- Fixed #703. [Jamie.Rees] + +- #233. [Jamie.Rees] + +- Done #678. [Jamie.Rees] + +- Fixed #670. [Jamie.Rees] + +- #456 Update all the requests when we identify that the username changes. [Jamie.Rees] + +- More user management. [Jamie.Rees] + +- #218. [Jamie.Rees] + +- Fixed build. [tidusjar] + +- Implimented the features #218. [tidusjar] + +- Use the user alias everywhere if it is set #218. [tidusjar] + +- Implimented auto approve permissions #218. [tidusjar] + +- A. [tidusjar] + +- Fixed an IOC issue. [tidusjar] + +- Fixed the issue with user management, needed to implement our own authentication provider. [Jamie.Rees] + +- Small changes including #666. [Jamie.Rees] + +- Done #679. [tidusjar] + +- Reduce the retry time. [Jamie.Rees] + +- Remove all references to the claims. [Jamie.Rees] + +- Lots of fixed and stuff. [Jamie.Rees] + +- Fixed potential crash #683. [Jamie.Rees] + +- Fixed #681. [Jamie.Rees] + +- More user management. [Jamie.Rees] + +- Finishing off the user management page #218 #359 #195. [Jamie.Rees] + +- Finished #646 and fixed #664. [Jamie.Rees] + +- Started on #646. Fixed #657. [Jamie.Rees] + +- Fixed #665. [Jamie.Rees] + +- Migrate users. [TidusJar] + +- Fixed build. [Jamie.Rees] + +- Convert the for to foreach for better readability. Still need to rework this area. [Jamie.Rees] + +- Final Tweaks #483. [Jamie.Rees] + +- Finished #483. [Jamie.Rees] + +- Finished the queue #483. [Jamie.Rees] + +- Started on the queue for requests #483 TV Requests with missing information has been completed. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Finished the notification for the fault queue. [Jamie.Rees] + +- Finished #556. [Jamie.Rees] + +- Finished #633 (First part of the queuing) [Jamie.Rees] + +- Finished #659 #236 has been modified slightly. Needs testing on Different systems. [Jamie.Rees] + +- Almost finished #659. [Jamie.Rees] + +- Started on #483. [Jamie.Rees] + +- #544. [Jamie.Rees] + +- Fixed #656 and more work on #218. [Jamie.Rees] + +- Fixed some issues with the user management work. [TidusJar] + +- Fixed build issue. [TidusJar] + +- User perms. [Jamie.Rees] + + +## v1.9.7 (2016-11-02) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Potential fix for #629. [TidusJar] + +- Fixed an issue to stop blatting over the base url. [tidusjar] + +- Fixed #643. [TidusJar] + +- Fixed #622. [TidusJar] + + +## v1.9.6 (2016-10-28) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Fixed #586. [Jamie.Rees] + +- Fixed #622. [Jamie.Rees] + +- Fixed #621. [Jamie.Rees] + + +## v1.9.5 (2016-10-27) + +### **New Features** + +- Added our own custom migrations, a lot easier to migrate DB versions now. [tidusjar] + +### **Fixes** + +- Bump version. [Jamie.Rees] + +- Small bit of work on the user claims. [Jamie.Rees] + +- Fix #612 again. [Jamie.Rees] + +- User management styling. [Jamie.Rees] + +- Fixed #608 and some other small stuff. [tidusjar] + +- More user mapping. [tidusjar] + +- Fixed #615. [tidusjar] + +- Fixed #610. [tidusjar] + +- User management stuff. [Jamie.Rees] + +- User management work. [Jamie.Rees] + +- Revert the TVSender to use the old code. [Jamie.Rees] + +- Fixed the view issue. [tidusjar] + +- S582: admin improvements part 2. [Jim MacKenzie] + +- Fix #612. [Jamie.Rees] + +- User management, migration and newsletter. [Jamie.Rees] + +- #602 recently added improvements. [tidusjar] + +- Revert "Sorting out the current state of migrations" [Jamie.Rees] + +- Sorting out the current state of migrations. [Jamie.Rees] + +- Marked as obsolete. [Jim MacKenzie] + +- Migration setup. [Jim MacKenzie] + +- Removed extra line breaks. [Jim MacKenzie] + +- Moved Newsletter Settings to its own page. [Jim MacKenzie] + +- Reverted TMDB package. [Jamie.Rees] + +- Remove DB Option. [Jamie.Rees] + +- Upgrade the movie DB package and fixed #370 To fix this I had to make another API call... It slows down the search... [tidusjar] + +- Lots of small fixes including #475. [tidusjar] + +- A better fix for #587. [tidusjar] + +- Fixed #553. [tidusjar] + +- #601. [Jamie.Rees] + +- More rework to use the Plex DB. [Jamie.Rees] + +- More work around using the PlexDatabase. [Jamie.Rees] + +- Plex DB. [Jamie.Rees] + +- Allow to process even know we had an error #578. [Jamie.Rees] + +- Fix boostrapper-datetimepicker imports (#586) [David Torosyan] + +- Potential work around for #587. [tidusjar] + +- Fixed #589. [tidusjar] + + +## v1.9.4 (2016-10-10) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Added Paypalme options, no UI yet (#568) [Jim MacKenize] + +- Update appveyor.yml. [Jamie] + +- Update README.md. [Jamie] + +### **Fixes** + +- Reverted. [tidusjar] + +- Make sure it's enabled before sending the recently added. [tidusjar] + +- Moved the HR inside the table for TV Shows. [Jamie.Rees] + +- FIXED!!!!! YES BITCH! #550. [tidusjar] + +- Moved the horizontal rules inside the table row. [tidusjar] + + +## v1.9.3 (2016-10-09) + +### **New Features** + +- Added properties to disable tv requests for specific episodes or seasons and wired up to admin settings. [Matt McHughes] + +- Added different sonarr search commands. [tidusjar] + +### **Fixes** + +- Fixed #515. [tidusjar] + +- Fixed #561 and a small bit of work on #569. [tidusjar] + +- #569. [tidusjar] + +- Fixed case typo. [Matt McHughes] + +- Finished wiring tv request settings to tv search. [Matt McHughes] + +- WIP hide tv request options based on admin settings. [Matt McHughes] + +- Set meta charset to be utf-8. [Madeleine Schönemann] + +- F#552: updated labels text. [Jim MacKenize] + +- F#552: Re-design lables. [Jim MacKenzie] + +- Last correction.. Now the translation is ready to be used. [Michael Reber] + +- Forgot to correct two incorrect translations. [Michael Reber] + +- Correction of the German translation. [Michael Reber] + +- Notification improvements. [tidusjar] + +- #515. [tidusjar] + + +## v1.9.2 (2016-09-18) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update CouchPotatoCacher.cs. [Jamie] + +- Added some error handing around the GetMovie area #517. [tidusjar] + +- Added a version endpoint in "/api/version" #529. [tidusjar] + +### **Fixes** + +- Trying to fix the auto CP. [tidusjar] + +- Increase the notice message text box #527. [tidusjar] + +- #536 this should fix notification settings when it is being unsubscribed when testing. [tidusjar] + +- Improved how the TV search looks and feels. [tidusjar] + +- Fix for reverse proxy when using the wizard. [Devin Buhl] + +- Fixed #532. [tidusjar] + +- This should fix some issues with the episode requests #514. [tidusjar] + +- Small changes around existing series. [tidusjar] + +- Fixed #514 and the unit tests. [tidusjar] + +- If there is a bad password when changing it, we now inform the user. [tidusjar] + +- When logging out as admin remove the username from the session. [tidusjar] + +- Sorted out some of the UI for #18. [tidusjar] + +- Finished #18. [tidusjar] + + +## v1.9.1 (2016-08-30) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Added french to the navbar. [tidusjar] + +- Changed the way we use the setTimeout function. Should fix #403 #491 #492. [tidusjar] + +- Change the redirection to use a relative uri redirect #473. [tidusjar] + +### **Fixes** + +- Fixed tests. [tidusjar] + +- Fixed #491 and added more logging around the email messages under the Info level. [tidusjar] + +- Finished #415. [tidusjar] + +- Fixed an issue where there were some JS errors on the landing page settings and stopped us being redirected to the login sometimes as an admin. [tidusjar] + +- Fixed #480. [tidusjar] + +- User management. [tidusjar] + +- Fixed #505. [tidusjar] + +- Append the application version to the end of our JS/CSS files. [tidusjar] + +- Fixed issue #487. [tidusjar] + +- Remove the datetime picker css from the main assets block and only load it on the pages it needs. #493. [tidusjar] + +- Redirect to search if we are already logged in #488. [tidusjar] + +- Fixed build. [tidusjar] + +- Fixed an issue where you could set the base url as requests #479. [tidusjar] + +- Working on the beta releases page and also the user management. [tidusjar] + +- User work. [tidusjar] + + +## v1.9.0 (2016-08-18) + +### **New Features** + +- Update the availability checker to search for TV Episodes. [tidusjar] + +- Changed the no TVMazeid message. [tidusjar] + +- Added an option to disable/enable the Plex episode cacher. [tidusjar] + +- Updated the episode cacher to have a minimum of 11 hours before it runs again. [tidusjar] + +- Added some useful analytical infomation around the wizard. [tidusjar] + +- Updated the German translations #402. [tidusjar] + +- Added some code to shrink the DB. reworked the search to speed it up. [tidusjar] + +- Change to use the GrandparentTitle rather than the thumbnail.... facepalm. [tidusjar] + +- Change the interval to hours! [tidusjar] + +- Added the transaction back into the DB. Do not run the episode cacher if it's been run in the last hour. [tidusjar] + +- Added logging. [tidusjar] + +- Changed the query slightly. [tidusjar] + +- Updated Newtonsoft.Json, Autofixture, Nlog and Dapper packages. [tidusjar] + +- Added the Sonarr check for episodes #254. [tidusjar] + +- Added unit tests. [tidusjar] + +- Added #436. [tidusjar] + +- Update build no. [tidusjar] + +- Updated translations for #402. [tidusjar] + +- Added a beta module. [tidusjar] + +- Added a custom debug root path provider, this means we do not have to recompile the views every time we make a view change. [tidusjar] + +- Update .gitignore. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added tests for the string hash. [tidusjar] + +- Added code to request the api key for CouchPotato. [tidusjar] + +- Added the file version to the layout. [tidusjar] + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added automation tests. [tidusjar] + +- Update appveyor.yml. [Jamie] + +- Updated packages. [tidusjar] + +- Updated Polly. [tidusjar] + +- Updated Fr, IT and NL translations #402. [tidusjar] + +- Changed the way the donate button works for #414. [tidusjar] + +- Added MediatR. [tidusjar] + +### **Fixes** + +- User management stuff. [tidusjar] + +- Fixed! [tidusjar] + +- Small amount of work on the user management. [tidusjar] + +- Fixed #466. [tidusjar] + +- Fixes. [tidusjar] + +- Made the episode request better. [tidusjar] + +- Removed commented out tests. [tidusjar] + +- Fixed the bad test after the merge. [tidusjar] + +- Reworked #466. [tidusjar] + +- More unit tests around the login and also the core Plex Checker. [tidusjar] + +- Potentially fixed the issue where we were requesting everything that was also available now. [tidusjar] + +- This should fix #466. [tidusjar] + +- Attempt at fixing a potential bug found from #466. [tidusjar] + +- #464 fixed. [tidusjar] + +- Fixed the build. [tidusjar] + +- Small improvements to the wizard. [tidusjar] + +- Always set the wizard to be true when editing the Plex Requests settings (Since the flag is not in the UI, a bool defaults to false). [tidusjar] + +- Tiny bit of more info. [tidusjar] + +- Finished #459. [tidusjar] + +- #459 is almost done. [tidusjar] + +- Modified the episode modal so that we are now resetting the button after a request. [tidusjar] + +- Commented out the transaction for now to debug it. [tidusjar] + +- Since we are multithreading, we should use a threadsafe type to store the episodes to prevent any threading or race conditions. [tidusjar] + +- Wrapped the bulk insert inside a transaction. [tidusjar] + +- Made the episode check parallel. [tidusjar] + +- Log out the GUID causing the issue. [tidusjar] + +- Fixed another test. [tidusjar] + +- Fixed tests. [tidusjar] + +- Got mostly everything working for #254 Ready for testing. [tidusjar] + +- Fixed issue with saving to db. [tidusjar] + +- Need to work out why the cacher is not working and where the datatype mismatch is. [tidusjar] + +- Don't delete first. [tidusjar] + +- Fix the log path issue #451. [tidusjar] + +- Dump an item. [tidusjar] + +- Small change with the return value in the batch insert. [tidusjar] + +- #254 Removed the cache, we are now storing the plex information into the database. [tidusjar] + +- Small change in the episode saver. [tidusjar] + +- Some small tweaks to improve the memory alloc. [tidusjar] + +- Short circuit when Plex hasn't been setup. Added Miniprofiler. [tidusjar] + +- Consolidate newtonsoft.json packages. [tidusjar] + +- Some performance improvements around the new TV stuff. [tidusjar] + +- Reworked the cacher, fixed the memory leak. No more logging within tight loops. [tidusjar] + +- Another null check. [tidusjar] + +- Some more changes. [tidusjar] + +- Some error handling. [tidusjar] + +- Check if the sonarr ep is monitored. [tidusjar] + +- Some logging. [tidusjar] + +- Small changes, we will actually see the episode cacher on the scheduled jobs page now. [tidusjar] + +- Work on the UI to show what episodes have been requested #254. [tidusjar] + +- Small fix. [tidusjar] + +- Fix the api change in #450. [tidusjar] + +- #254. [tidusjar] + +- Workaround for #440. [tidusjar] + +- Async async async improvements. [tidusjar] + +- Finished #266 Added a new cacher job to cache all episodes in Plex. [tidusjar] + +- Fixed #442. [tidusjar] + +- #254. [tidusjar] + +- Work around the sonarr bug #254. [tidusjar] + +- #254 having an issue with Sonarr. [tidusjar] + +- Small bit of work on #266. [tidusjar] + +- #254. [tidusjar] + +- Precheck and disable the episode boxes if we already have requested it. TODO check sonarr to see if it's already there. #254. [tidusjar] + +- Fixed broken build. [tidusjar] + +- More work for #254. [tidusjar] + +- More work on #254. [tidusjar] + +- Fixed the bug in #438 and added unit tests to make so we dont break it in the future. [tidusjar] + +- Some reason we had dupe translations. [tidusjar] + +- Rename SubDir to Base Url. [tidusjar] + +- Fix the exception in #440. [tidusjar] + +- Reworking the login page for #426. [tidusjar] + +- Fixed #438. [tidusjar] + +- Finished the auth stuff. [tidusjar] + +- Finished up the SMTP side of #429. [tidusjar] + +- #428 Added a message when the we cannot get a TVMaze ID. [tidusjar] + +- #254 MOSTLY DONE! At last, this took a while. [tidusjar] + +- Removed the other rootpath provider. [TidusJar] + +- Removed the other rootpath provider. [TidusJar] + +- Removed the other rootpath provider. [TidusJar] + +- Should fix #429. [TidusJar] + +- Done #135 We are including the application version number in the directory. [tidusjar] + +- #387 trim the spaces from the api key. Tidied up the setting models a bit. [tidusjar] + +- Wrapped the repo to catch Sqlite corrupt messages. [tidusjar] + +- Frontend and tv episodes api work for #254. [tidusjar] + +- #424. [tidusjar] + +- #359. [tidusjar] + +- Moved the plex auth token to the plex settings where it should belong. [tidusjar] + +- Small changes around the user management. [tidusjar] + +- Missed brace. [tidusjar] + +- Removed. [tidusjar] + +- Fixed issues from the merge. [tidusjar] + +- Stupid &$(*£ merge. [tidusjar] + +- Angular. [tidusjar] + +- Reworked the custom notifications... again. Need to figure out how to find the view to the model. [tidusjar] + +- Fixed #417. [tidusjar] + +- Removed NinjectConventions, we hadn't started to use it anyway. [tidusjar] + +- Fixed the way we will be using custom messages. [tidusjar] + +- Test checkin. [tidusjar] + +- Better handling for #388. [tidusjar] + +- Fixed #412. [tidusjar] + +- Fixed #413. [tidusjar] + +- Fixed #409. [tidusjar] + +- Trycatch around the availbility checker. [tidusjar] + +- WIP on notification resolver. [tidusjar] + +- Tidy. [tidusjar] + +- Plugged in MediatR. [tidusjar] + +- Moved over to using Ninject. [tidusjar] + + +## v1.8.4 (2016-06-30) + +### **Fixes** + +- Fixed the bug where we were auto approving everything. Added French language into the navigation bar. [tidusjar] + + +## v1.8.3 (2016-06-29) + +### **New Features** + +- Update README.md. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added some of the backend bits for #182. [tidusjar] + +- Updates for #243. [tidusjar] + +- Added Dutch language #243. [tidusjar] + +- Added languages #243. [tidusjar] + +- Added logging #350. [tidusjar] + +### **Fixes** + +- Small changes. [tidusjar] + +- Allow html in the notice message. [tidusjar] + +- Some more unit tests around the NotificationMessageResolver. [tidusjar] + +- Fixed a timing bug found the in build. Note, when working with time differences use TotalDays. [tidusjar] + +- More translations on the search page (Mainly the notification messages) #243. [tidusjar] + +- Fixed some warnings. [tidusjar] + +- CodeCleanup. [tidusjar] + +- Fixed a bit of a stupid bug in the resetter and added unit tests around it to make sure this never happens again. [tidusjar] + +- Fixed an issue where we didn't provide the correct response when clearing the logs. [tidusjar] + +- Made it so users that are in the whitelist do not have a request limit. [tidusjar] + +- Made it so the request limit doesn't apply to admin users. [tidusjar] + +- Fixed where a user could see the delete button on the issues page. [tidusjar] + +- Fixed some small issues and improved the navbar. [tidusjar] + +- Translated the Requested page #243. [tidusjar] + +- Finished #337. [tidusjar] + +- Some analytics. [tidusjar] + +- More translations for #243 and welcome text for #293. [tidusjar] + +- Small bit of work for #359. [tidusjar] + +- Finished #6. [tidusjar] + +- Analytics and fixes. [tidusjar] + +- Translated the search page #243. [tidusjar] + +- Implemented the different languages and added the ability to change cultures. #243. [tidusjar] + +- Started #243. [tidusjar] + +- Fixed #364. [tidusjar] + +- Some more useful analytical information. [tidusjar] + +- Generic try catch to fix #350. [tidusjar] + +- Slight changes, moved the donate button. [tidusjar] + +- Potential fix for #350. [tidusjar] + +- Better way of obtaining clean enum string. [Drewster727] + +- Fixed #362. [tidusjar] + + +## v1.8.2 (2016-06-22) + +### **New Features** + +- Update readme. [tidusjar] + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Fixed a circular reference issue. [tidusjar] + +- Small changes around how we work with custom events in the analytics. [tidusjar] + +- Fixed #353 #354 #355. [tidusjar] + +- Null provider check for movies. [Drewster727] + +- Show request type in notifications #346 and fix an issue from previous commit for #345. [Drewster727] + +- Add an option to stop sending notifications for requests that don't require approval #345. [Drewster727] + + +## v1.8.1 (2016-06-21) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Fix obj ref error when scheduler runs (ProviderId is null?) [Drewster727] + +- Fix logic for obtaining a sonarr quality profile #340. [Drewster727] + + +## v1.8.0 (2016-06-21) + +### **New Features** + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added the new advanced search into the search page too. [tidusjar] + +- Change the way we configure the IoC container in the bootstrapper, we are registering all the concrete instances on application start rather than on each web request. This should increase the performance per HTTP request. [tidusjar] + +- Updated nlog and fixed #295. [tidusjar] + +### **Fixes** + +- Workaround for #334. [Drewster727] + +- Create .gitattributes. [Jamie] + +- Fixes to the issues. [tidusjar] + +- Set the defaults for the landing page. [tidusjar] + +- Revert branch to 664dae2. [tidusjar] + +- Some unit tests for the issues. [tidusjar] + +- Tidied up the bootstrapper. [tidusjar] + +- Fix up landing page UI. [Drewster727] + +- Fixed CSS issue with the top arrow in the Plex theme. [tidusjar] + +- Small changes. [tidusjar] + +- Done #318. [tidusjar] + +- Fixed tests. [tidusjar] + +- #298 added some tests for the landing page. [tidusjar] + +- We are now only keeping the latest 1000 log records in the database. Delete everything else. [tidusjar] + +- Some analytic stuff. [tidusjar] + +- Capture the TVDBID when requesting. [tidusjar] + +- Attempting to improve #219. [tidusjar] + +- Just some more async changes. [tidusjar] + +- Small changes. [tidusjar] + +- More work on #298. Everything wired up. [tidusjar] + +- Fixed the issue on the landing page #298. [tidusjar] + +- #298 moved the content to the left a bit. [tidusjar] + +- Styling for #298 done, just need to wire up the model and do the actual status check. [tidusjar] + +- Bumped up the version number. [tidusjar] + +- Removed some DumpJson() from the trace logs. [tidusjar] + +- Small ui fix (100% width user/password fields to improve mobile experience) [Drewster727] + +- Landing page stuff #298. [tidusjar] + +- Datepicker UI fixes + small landing page UI fix. [Drewster727] + +- Removed a change that shoudn't have been commited. [tidusjar] + +- Fixed tests. [tidusjar] + +- More work for #298. [tidusjar] + +- #273 added for only available content on the search. [tidusjar] + +- Fixed #303 Looks like there was some incorrect business logic. [tidusjar] + +- Most of #273 done. [tidusjar] + +- Settings done for #298. [tidusjar] + +- Started #298. [tidusjar] + +- A crap tonne of work on #273. [tidusjar] + +- More work on #273. [tidusjar] + +- Reduced kept logs for 2 days. [tidusjar] + +- Fixed #300. [tidusjar] + +- #273. [tidusjar] + +- Fixed a bug with some users with the CP profiles. [tidusjar] + +- #273. [tidusjar] + +- Done the same for TV. [tidusjar] + +- Fixes #296. [tidusjar] + +- More for #273. [tidusjar] + +- Small changes. [tidusjar] + +- Revert "Small changes" [tidusjar] + +- Small changes. [tidusjar] + +- Finished #221 and added more async #278. [tidusjar] + +- Spelling mistake in the html! this fixes #264. [tidusjar] + +- More work on #273. [tidusjar] + +- Fixed #210. [tidusjar] + +- Started #273. [tidusjar] + + +## v1.7.5 (2016-05-29) + +### **New Features** + +- Update preview. [Jamie] + +- Updated dapper.contrib. Looks like there was a bug in the async methods. [tidusjar] + +- Updater wouldn't work when running a reverse proxy #236. [tidusjar] + +### **Fixes** + +- Bump build ver. [tidusjar] + +- Use HTTPS for the poster images, so there aren't any mixed content warnings when serving the application via an HTTPS reverse proxy. [Sean Callinan] + +- Removed static declarations. [tidusjar] + +- Fixed styling on modal. [tidusjar] + +- Made the search page all async goodness #278. [tidusjar] + +- Made the request module async #278. [tidusjar] + +- Started some dynamic scrolling. [tidusjar] + +- Stop dumping out the settings to the log. [tidusjar] + +- Made more async goodness. [tidusjar] + +- Made some of the searching async #278. [tidusjar] + +- Fixed #277. [tidusjar] + +- Reworked some tests. [tidusjar] + +- #26q make the auth users list taller. [Drewster727] + +- Fix 404 error. [Drewster727] + +- #262 make the auth users list taller. [Drewster727] + +- #221 delete requests per category. [Drewster727] + +- #256 #237 UI Improvements and consolidation. [Drewster727] + +- Fixed a bug in the user notification where if an admin wants to be notified they wouldn't be. [tidusjar] + +- Set the admin to have all claims. [tidusjar] + +- Fix null exception possibility in cp/sickrage cacher classes. [Drewster727] + +- Fixed #244. [tidusjar] + +- Fixed #240. [tidusjar] + +- Fixed #270. [tidusjar] + +- Fixed an issue where if you have only 1 plex friend it would not show in the list. [tidusjar] + + +## v1.7.4 (2016-05-25) + +### **New Features** + +- Update README.md. [Jamie] + +### **Fixes** + +- Fixed #252. [tidusjar] + +- Fixed #428. [tidusjar] + +- Version bump. [tidusjar] + +- Fixed tests. [tidusjar] + +- Fully fixed #239. [tidusjar] + +- We wan't updating the DB schema. [tidusjar] + + +## v1.7.3 (2016-05-25) + +### **Fixes** + +- Fixed the release build issue where we could not access the settings #239. [tidusjar] + + +## v1.7.2 (2016-05-25) + +### **Fixes** + +- Fixed a small bug where an exception would get thrown. [tidusjar] + +- Build version bump. [tidusjar] + +- Cleanup. [tidusjar] + +- Typo. [tidusjar] + +- Fixed #241. [tidusjar] + +- Fixed #239. [tidusjar] + +- Fixed #238. [tidusjar] + +- Small UI tweaks/improvements. [Drewster727] + + +## v1.7.1 (2016-05-24) + +### **New Features** + +- Update version. [tidusjar] + +### **Fixes** + +- Fixed an issue with the auth page when running with a reverse proxy. [tidusjar] + + +## v1.7 (2016-05-24) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added the ability to get the apikey from the api if you provide a correct username and password. Added more unit tests Added the ability to change a users password using the api refactored the Usermapper and made it unit testsable. [tidusjar] + +- Update. [tidusjar] + +- Added in an audit table. Since we are now allowing multiple users to change and modify things we need to audit this. [TidusJar] + +- Added the updater to the soloution and did a bit of starting code. [TidusJar] + +- Updated the claims so we can support more users. Added a user management section (not yet complete) Added the api to the solution and a api key in the settings (currently only gets the requests). [TidusJar] + +- Updated packages. [TidusJar] + +- Added a retry handler into the solution. We can now retry failed api requests. [TidusJar] + +- Update README.md. [Jamie] + +- Added Released propety to RequestViewModel. Added Released filter to the Requests page. [Chris Lees] + +- Added #27 to albums. [tidusjar] + +- Added the actual notification part of #27. [tidusjar] + +- Added the missing baseurl bit on the login page for #72. [tidusjar] + +- Added the 'enable user notifications' to the email settings view and model. [tidusjar] + +- Update README.md. [Jamie] + +### **Fixes** + +- Remove pointless test, change the default theme and fix a small bug. [tidusjar] + +- Fixed api. [tidusjar] + +- Finished #26. [tidusjar] + +- Plex theme. [tidusjar] + +- Implimented a theme changer, waiting for the Plex theme. [tidusjar] + +- Finished #222 #205. [tidusjar] + +- Started working on #26. [tidusjar] + +- Undid some small changes that was checked in by accident. [tidusjar] + +- #164 has been resolved. [tidusjar] + +- Resolved #224 , Removed the 'SSL' option from the email notification settings. We will now use the correct secure socket options (SSL/TLS) for your email host. [tidusjar] + +- Small changes. [tidusjar] + +- #27 fully finished. [tidusjar] + +- Fixed #215. [tidusjar] + +- Using Mailkit to fix #204. [tidusjar] + +- Color. [tidusjar] + +- Fully finished #27 just need to test it! [tidusjar] + +- Fixed test. [tidusjar] + +- Styling for #27. [tidusjar] + +- I think the auto updater is finished! #29. [tidusjar] + +- I think we have finished the main bulk of the auto updater #29. [tidusjar] + +- #222 #205 more ! Started getting the settings out. [tidusjar] + +- Removed the service locator from the base classes and added in some Api tests added all the tests back in! [tidusjar] + +- More work on the api and documentation #222 #205. [tidusjar] + +- Started documenting the API we now have swagger under ~/apidocs #222 #205. [tidusjar] + +- Api work for #205 Refactored how we check if the user has a valid api key Added POST request, PUT and DELTE. [tidusjar] + +- First pass of the updater working. #29. [tidusjar] + +- Removed SIGHUP from the termination list #220. [tidusjar] + +- Fixed. [tidusjar] + +- Missing. [tidusjar] + +- Missed out a file. [TidusJar] + +- And some more... [TidusJar] + +- Missed some files. [TidusJar] + +- A bit more work on switching to using user claims so we can support multiple users. [TidusJar] + +- Made the store backup clean up some of the older backups (> 7 days). [TidusJar] + +- More work on the user management. [TidusJar] + +- - Notifications will no longer be send to the admins if they request something. - Looks like we missed out adding the notifications to Music requests, so I added that in. [TidusJar] + +- - Improved the RetryHandler. - Made the tester buttons on the settings pages a bit more robust and added an indication when it's testing (spinner) [TidusJar] + +- Packages. [TidusJar] + +- Nm, [TidusJar] + +- Downgraded packages. [TidusJar] + +- Better handling for #202. [TidusJar] + +- Finished #208 and #202. [TidusJar] + +- This should help #202. [TidusJar] + +- Resolved #209. [TidusJar] + +- Finished #209. [TidusJar] + +- Slight adjustments to #189. [tidusjar] + +- - Added a visual indication on the UI to tell the admin there is a update available. - We are now also recording the last scheduled run in the database. [tidusjar] + +- Did the login bit on #185. [tidusjar] + +- Finished #186. [tidusjar] + +- Fixed #185. [tidusjar] + +- Fixed issue in #27 with albums. [tidusjar] + +- #27 added TV Search to the notification. [tidusjar] + +- Fixed bug. [tidusjar] + +- More work on #27 Added a new notify button to the search UI (Needs styling). Also fixed a bug where if the user could only see their own requests, if they search for something that has been requested, it will show as requested. [tidusjar] + +- Improved the startup of the application. We now properaly parse any args passed into the console. [tidusjar] + +- Additional cacher error handling + don't bother checking the requests when we don't get data back from plex. [Drewster727] + +- Remove old migration code and added new migration code. [tidusjar] + +- Stop the Cachers from bombing out when the response from the 3rd party api returns an exception or invalid response. #171. [tidusjar] + +- Increase the scheduler cache timeframe to avoid losing cache when the remote api endpoints go offline (due to a reboot or some other reason) -- if they're online, the cache will get refreshed every 10 minutes like normal. [Drewster727] + +- Fix the cacher by adding locking + extra logging in the plex checker + use a const key for scheduler caching time. [Drewster727] + +- Small changes. [tidusjar] + +- Switched out the schedulers, this seems to be a better implimentation to the previous and is easier to add new "jobs" in. [tidusjar] + +- Fixed #168. [tidusjar] + +- Fixed #162. [tidusjar] + +- Fix saving the log level. [Drewster727] + +- Set the max json length (fixes large json response errors) [Drewster727] + + +## v1.6.1 (2016-04-16) + +### **New Features** + +- Update README.md. [Jamie] + +- Added a url base. [tidusjar] + +- Change default logging. [tidusjar] + +- Added logging around SickRage. [tidusjar] + +### **Fixes** + +- Bump up the version number ready for the release. [tidusjar] + +- BaseUrl is finally finished! #72. [tidusjar] + +- #72 Login page done. [tidusjar] + +- More changes for the urlbase #72. [tidusjar] + +- Done the auth, cp, logs and sidebar for #72. [tidusjar] + +- Add an extra check when determining if a tv show is already available (also check if it starts with the show name returned from the tv db) [Drewster727] + +- Cache plex library data regardless of whether we have requests in the database or not. [Drewster727] + +- By default don't use a url base. [tidusjar] + +- Return empty array when obtaining queued IDs in sickrage cacher. [Drewster727] + +- Fixed a small bug in the SR cacher. [tidusjar] + +- Fixed when we do not have a base. [tidusjar] + +- More changes for #72. [tidusjar] + +- Fixed exception and all areas will now use the base url #72. [tidusjar] + +- Removed the test code from #72. [tidusjar] + +- Commented out the unit tests as they need to be reworked now. [tidusjar] + +- Finally fixed #72. [tidusjar] + +- Remove test code from plex api GetLibrary method. [Drewster727] + +- Finished up the caching TODO's. [tidusjar] + +- Kick off the schedulers once the web app has started (fixes api errors on start) [Drewster727] + +- Converted the UI back down to .NET 4.5.2. [tidusjar] + +- Fixed #154. [tidusjar] + +- Revert everything (except PlexRequests.UI) back to .NET 4.5.2 -- fixes incompatibilities with the latest version of mono (4.2.3.4) -- fixes notifications not working #152 #147 #141. [Drewster727] + +- #150 start caching plex media as well. refactored the availability checker. NEEDS TESTING. also, we need to make the Requests hit the plex api directly rather than hitting the cache as it does now. [Drewster727] + +- #150 split out the cache subscriptions to make sure they subscribe properly. [Drewster727] + +- #150 sonarr/sickrage cache checking. sickrage has a couple small items left. [Drewster727] + +- Fixed args. [tidusjar] + +- Fixed. [tidusjar] + +- Made the base better. [tidusjar] + +- Remove couchpotato api test code. [Drewster727] + +- Start the initial couchpotato cache call on a separate thread to keep the startup process quick. [Drewster727] + +- Add csproj with file changes from previous commit. [Drewster727] + +- Cache the couchpotato wanted list, update it on an interval, and use it to determine if a movie has been queued already. [Drewster727] + +- I think i've fixed an issue where SickRage reports Show not found. [tidusjar] + +- Set the default log level to info. #141. [tidusjar] + +- #125 refactor async task logic to work with mono. [Drewster727] + +- Fix search spinner sticking around after clearing search text + make the "Requested" and "Available" indicators in the search page different colors. [Drewster727] + +- #125 start indicating in the results if an item is already requested or available. [Drewster727] + +- #145 firefox css dsplay issue. [Drewster727] + +- Fixes for sonarr, we now display the error messages back to the user. [tidusjar] + +- Fixed #144. [tidusjar] + + +## v1.6.0 (2016-04-06) + +### **New Features** + +- Changed the build number. [tidusjar] + +- Update README.md. [Drew] + +- Update README.md. [Drew] + +- Update README.md. [Drew] + +- Update README.md. [Drew] + +- Changed the title to a contains but the artist still must match, [tidusjar] + +- Added unit tests to cover the new changes to the availability checker. [tidusjar] + +- Added the music check in the Plex Checker. [tidusjar] + +- Changed around the startup so we cache the profiles after the DB has been created. [tidusjar] + +- Updated where we update the request blobs schema change. [tidusjar] + +- Update SearchModule.cs. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Change the new columns type. [tidusjar] + +- Added a DBSchema so we have an easier way to update the DB. [tidusjar] + +- Added an issue template. [tidusjar] + +- Update README.md. [Jamie] + +- Added back the username into the Session when the admin logs in. This means they do not have to log in twice. [tidusjar] + +- Added happy path tests for the Checker. [tidusjar] + +- Added music to the search and requests page. [tidusjar] + +- Added a scroll to the top thingy and a bit more work on headphones. [tidusjar] + +- Added some tests and fixed the issue where the DB would get created in the wrong place depending on how you launched the application. [tidusjar] + +- Added the settings page for #32. [tidusjar] + +- Update README.md. [Drewster727] + +- Update README.md. [Drewster727] + +- Update README.md. [Drewster727] + +- Update README.md. [Drewster727] + +- Update README.md. [Drewster727] + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Some final tweaks for #32. [tidusjar] + +- Fixed a bug where if we are the admin we didn't add the request to the db. [tidusjar] + +- Fixed an issue where we would add the Sickrage series but it would fail on adding the seasons. [tidusjar] + +- Properly account for future/past dates when humanizing with moment. [Drewster727] + +- Properly display release date on requests page. [Drewster727] + +- Add missing reference for release mode. [Drewster727] + +- #139 remove dependency and usage of humanize() - should help with cross-platform issues. start using moment.js. [Drewster727] + +- Fix selectors for music list on request page to get sorting working. [Drewster727] + +- Fixed the error #32. [tidusjar] + +- Fixed the logs page. [tidusjar] + +- Another attempt at filtering #32. [tidusjar] + +- A bit more error handling #32. [tidusjar] + +- Improved the availabilty check to include music results #32. [tidusjar] + +- Small changes for #32. [tidusjar] + +- A bit more logging for #32. [tidusjar] + +- More headphones #32 I am starting to hate headphones... Sometimes the artists and albums just randomly fail. [tidusjar] + +- #134 temporary workaround for this. [Drewster727] + +- Task.run for startup caching + fix admin module unit test failures. [Drewster727] + +- Cache injection, error handling and logging on startup, etc. [Drewster727] + +- Tweaks for #32. [tidusjar] + +- #132 auto-approve for admins. [Drewster727] + +- Finished the bulk work for Headphones. Needs testing #32. [tidusjar] + +- Made the album search 10x faster. We are now loading the images in a seperate call. #32. [tidusjar] + +- Add a reference to API Interfaces to fix the build. [tidusjar] + +- #114 start caching quality profiles. Set the cache on startup and when obtaining quality profiles in settings. [Drewster727] + +- Work for #32. [tidusjar] + +- #114 first pass at choosing quality profile when approving + focus search input by default and when switching tabs. [Drewster727] + +- #131 fix for default selected tab. [Drewster727] + +- Remove references to obsolete RequestedBy property + start setting the db schema to the app version, and check that in the future for migrations. [Drewster727] + +- Fixed async issue. [Shannon Barrett] + +- Updating SickRage api to verify Season List is up to date. [Shannon Barrett] + +- Work on showing the requests for #32. [tidusjar] + +- Got the search finished up for #32. [tidusjar] + +- Remove test/temp code in UserLoginModule. [Drewster727] + +- A bit more work on #32 started working on requesting it. The DB is a bit of an issue... [tidusjar] + +- Most of the UI work done for #32. [tidusjar] + +- Basic search working for #32. [tidusjar] + +- Mono datetime offset workaround. [Drewster727] + +- #122 store utc time in the databse + obtain timezone offset of the client upon login + offset times returned to client based on session offset. [Drewster727] + +- Method reference bug fix. [Drewster727] + +- Fix search focus z-index issue (hid suggestions options) [Drewster727] + +- Minor search UI adjustments. [Drewster727] + +- #55 first attempt at "suggestions" starting with "Comming Soon" and "In Theaters" [Drewster727] + +- #106 rename sorting options and polish the dropdown UI a bit. [Drewster727] + +- Started adding the api part for headphones #32. [tidusjar] + +- Upped the time of #123. [tidusjar] + +- First attempt at #123. [tidusjar] + +- We now do not show the text Requested By to the user, we also show a 'success' message instead of a warning when something has already been requested. [tidusjar] + +- Show a "no requests yet" message on the requests page (for each cateogory) [Drewster727] + +- Ignore items that are already available when approving in bulk, and simplify the checking + compile css. [Drewster727] + +- Add a better way to merge RequestedBy and RequestedUsers to avoid code duplication and simplify checks. [Drewster727] + +- Don't query the session as much in the modules, rely on a variable from the base class and store the username as needed. [Drewster727] + +- Show the requested by user from legacy request models. [Drewster727] + +- Only show requested by users to admins + start maintaining a list of users with each request. [Drewster727] + +- #96 fix up notification test feature. [Drewster727] + +- Fix the request page sort/approve button alignment. [Drewster727] + +- When pulling requests, set each to approved that is already available (so the UI avoids showing the approve option for already available content) [Drewster727] + +- Mono doesn't seem to have Tls1.2. Let's try TLS 1 #119. [tidusjar] + +- Specify a protocol type of TLS12. Looks like CP doesn't seem to like SSL3 (it is quite old now so understandable) #119. [tidusjar] + +- Made #85 better. [tidusjar] + +- Fixed the tests. [tidusjar] + +- Made the feedback from Sonarr better when Sonarr already has the series #85. [tidusjar] + +- An attempt to fix #108. [tidusjar] + +- Add some "no results" feedback to the searching + minor UI improvements. [Drewster727] + +- Fix notification tests. [Drewster727] + +- UI - increase icon size of nav menu (they were too small before) [Drewster727] + +- #96 Finished adding test functionality to notifications. [Drewster727] + +- #96 add the necessary back-end code to produce a test message for all notification types (still have to add the test buttons for pushbullet/pushover) [Drewster727] + +- #96 modify notifications interface/service to accept a non-type specific settings object. [Drewster727] + +- #96 Email notification test button (others to come) [Drewster727] + +- Minor UI adjustments. [Drewster727] + +- #84 provide an option in settings to resttrict users from viewing requests other than their own. [Drewster727] + +- #54 comma separated list of users who don't require approval + fix a couple request messages (include show title) [Drewster727] + +- Clean up the sorting option names. add a way to see which filter/sort is currently applied. [Drewster727] + +- Fix up the animations. seems to be related to the data-bound attribute causing the animtions not to fire on each .mix object. [Drewster727] + +- Move approve buttons to the tab content. [Drewster727] + +- Allow approving all requests by category. [Drewster727] + +- Fix up sorting on the request page. [Drewster727] + +- Add ubuntu/debian instructions. [Drewster727] + +- #86 - display movie/show title + year in request notifications. [Drewster727] + +- Show the movie/show title when requesting. [Drewster727] + + +## v1.5.2 (2016-03-26) + +### **Fixes** + +- Stoped users from spamming the request button. [tidusjar] + +- Fixed the logger no longer writing to the file. [tidusjar] + +- Fixed #97. [tidusjar] + + +## v1.5.1 (2016-03-26) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Added logs to the sidebar. I'm an idiot. [tidusjar] + +### **Fixes** + +- Approve tv shows or movies. [Drewster727] + +- Fixed a bug where if you had auto approve it wouldn't notify you. [tidusjar] + + +## v1.5.0 (2016-03-25) + +### **New Features** + +- Updated version number for release. [tidusjar] + +- Updated the logic for handling specific seasons in Sonarr and Sickrage. [Shannon Barrett] + +- Updated the readme and added some icons to the navbar. [tidusjar] + +- Added the ability to sepcify a username in the email notification settings for external MTA's. We have had to add a new option called Email Sender because of this. #78. [tidusjar] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added a notification model to the notifiers. Added the backend work for sending a notification for an issue report #75. [tidusjar] + +- Added a subdir to CP, SickRage, Sonarr and Plex #43. [tidusjar] + +### **Fixes** + +- And again. [tidusjar] + +- Made the check actually work. [tidusjar] + +- Finished up #68 and #62. [tidusjar] + +- Finished styling on the logger for now. #59. [tidusjar] + +- Fixed #69. [tidusjar] + +- Working on getting the Sonarr component to work correctly. [Shannon Barrett] + +- Fixes issue #62. [Shannon Barrett] + +- Refactored the Notification service to how it should have really been done in the first place. [tidusjar] + +- Fixed the build. [tidusjar] + +- Finished #49. [tidusjar] + +- Finished #57. [tidusjar] + +- Small changes around the filtering. [tidusjar] + +- Finished adding pushover support. #44. [tidusjar] + +- Resolved #75. [tidusjar] + +- Include DB changes. [tidusjar] + +- Done most on #59. [tidusjar] + +- Lowercase logs folder, because you know, linux. #59. [tidusjar] + +- Adding the imdb when requesting. [tidusjar] + +- Fixed an issue where the table didn't match the model. [tidusjar] + +- Improved the status page with the suggestion from #29. [tidusjar] + +- Hooked up most of #49 Just the validation messages need to be done. [tidusjar] + +- Fixed #74 and #64. [tidusjar] + +- Resolved #70. [tidusjar] + +- Finished #71. [tidusjar] + +- Got the filter working on both movie and tv #57. [tidusjar] + +- Started #57, currently there is a bug where the TV list won't filter. [tidusjar] + + +## v1.4.1 (2016-03-20) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update AvailabilityUpdateService.cs. [Jamie] + + +## v1.4.0 (2016-03-19) + +### **New Features** + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Updated the build version ready for the next release. [tidusjar] + +- Added the api and settings page for Sickrage. Just need to do the tester and hook it up #40. [tidusjar] + +- Added the option to set a CP quality #38. [tidusjar] + +- Added the code to lookup the old requests and refresh them with new information from TVMaze. [tidusjar] + +- Update StatusCheckerTests.cs. [Jamie] + +- Update README.md. [Jamie] + +- Added TVMaze to the search. #21. [tidusjar] + +- Added migration code and cleaned up the DB. [tidusjar] + +- Updated the way we add requests. [tidusjar] + +- Updated the Dapper.Contrib package, it had a bug where it wasn't returning the correct Id from inserts. [tidusjar] + +### **Fixes** + +- This fixes #36. [tidusjar] + +- Should fix issue #36. [Shannon Barrett] + +- When we do a batch update we need to reset the cache. [tidusjar] + +- Fixed an issue where the default quality on Sickrage wouldn't work. [tidusjar] + +- Wow, that was a lot of work. - So, I have now finished #40. - Fixed a bug where we was not choosing the correct tv series (Because of TVMaze) - Fixed a bug when checking for plex titles - Fixed a bug where the wrong issue would clean on the UI (DB was correct) - Refactored how we send tv shows - And too many small changes to count. [tidusjar] + +- Fixed the new dependancy with the admin class tests. [tidusjar] + +- Back to what it was :( [tidusjar] + +- Another test for #37. [tidusjar] + +- This should fix #37. [Jamie Rees] + +- Catch the missing table exception when they have a new DB. [Jamie Rees] + +- Exploratory test for #37. [Jamie Rees] + +- Fixed #33 we now have SSL options for Sonarr and CP. [Jamie Rees] + +- Removed all the html from the new TVMaze api (for overview). Added tests to cover the html removal. updated Readme to remove TheTVDB. [Jamie Rees] + +- Fixed tests. [Jamie Rees] + +- Almost fully integrated TVMaze #21 and also improved the fix for #31. [Jamie Rees] + +- Should fix #28. [Shannon Barrett] + +- Fixed #16 and #30. [tidusjar] + +- Modified the adding of request to update the model with the added ID. [tidusjar] + +- Switched over to the new service. [tidusjar] + +- Fixed #25. [Jamie Rees] + + +## v1.3.0 (2016-03-17) + +### **New Features** + +- Added pushbullet to the sidebar. [Jamie Rees] + +- Updated build version for the next release. [Jamie Rees] + +- Updated readme link. [tidusjar] + +- Added ignore to static tests. [tidusjar] + +- Added Pushbullet notifications #8. [tidusjar] + +- Added first implimentation of the Notification Service #8 Added tests to cover the notification service. [tidusjar] + +- Added validation to the Email settings, also increased the availability checker from 2 minutes to 5. [tidusjar] + +### **Fixes** + +- Fixed #22. [Jamie Rees] + +- Started on #16, nothing is hooked up yet. [tidusjar] + +- Fixed tests. [tidusjar] + + +## v1.2.1 (2016-03-16) + +### **New Features** + +- Update Program.cs. [Jamie] + +- Update Program.cs. [Jamie] + +- Added back the reference. [tidusjar] + +### **Fixes** + +- Removed the email notification settings from the settings (for release 1.2.1) [Jamie Rees] + +- Fixed. [Jamie Rees] + +- Resolved #10. [tidusjar] + + +## v1.2.0 (2016-03-15) + +### **New Features** + +- Updated. [Jamie Rees] + +- Updated appveyor. [Jamie Rees] + +- Update appveyor.yml. [Jamie] + +- Added latest version code and view. Need to finish the view #11. [tidusjar] + +- Added test button to Plex. That's fixed #9. [tidusjar] + +- Added test sonarr button #9. [tidusjar] + +- Added more tests. [tidusjar] + +- Added a bunch of logging. [tidusjar] + +- Added the application tester for CP #9. [tidusjar] + +- Added settings page for #8. [tidusjar] + +- Added pace.js. [tidusjar] + +### **Fixes** + +- Finished the notes! Resolved #7. [Jamie Rees] + +- #12. [Jamie Rees] + +- #12. [Jamie Rees] + +- Finished the status page #11 and some more work to #12. [Jamie Rees] + +- Resolved #7. [tidusjar] + +- Small changes. [tidusjar] + +- Yeah... [tidusjar] + +- Fixed #5 and also added some tests to the availability checker. [tidusjar] + +- Started added tests. [Jamie Rees] + +- Fixed an issue where the issues text appears larger. [Jamie Rees] + + +## v1.1 (2016-03-13) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Updated readme. [Jamie Rees] + +- Added the support for TV Series integrating with Sonarr. [Jamie Rees] + +- Added the functionality to pass a port through an argument. [tidusjar] + +- Added the code to get the quality profiles from Sonarr Started plugging that into the UI. [Jamie Rees] + +- Added the spinners #3. [tidusjar] + +- Added the functionality for the admin to clear the issues. [tidusjar] + +- Added the issues to the requests page. [tidusjar] + +- Added user logout method and unit tests to cover it. [tidusjar] + +- Added DeniedUsers to the view. [tidusjar] + +- Added the denied user check to the UserLoginModule. added a test case to cover it. [tidusjar] + +- Added a missing reference. [tidusjar] + +- Added first real test. [tidusjar] + +- Update README.md. [Jamie] + +- Added the latest version of nuget. [tidusjar] + +- Added travisyml. [tidusjar] + +- Added logging. [tidusjar] + +- Added missing files. [tidusjar] + +- Update README.md. [Jamie] + +- Added logging (Still WIP) [tidusjar] + +- Added favicon and also structured the HTML correctly. [tidusjar] + +- Updated the packages so everything is now with the correct framework (4.5.2) [tidusjar] + +- Added in deletion of requests. [tidusjar] + +- Added test code. [tidusjar] + +- Added dashboard. [tidusjar] + +- Added couchpotato page. [Jamie Rees] + +- Added readme to the project and updated it. [Jamie Rees] + +- Added helpers. [tidusjar] + +### **Fixes** + +- Bug fix, Couchpotato settings wouldn't show in release due to a Nancy bug. [Jamie Rees] + +- Small changes. [Jamie Rees] + +- First release, build 1.0.0. [Jamie Rees] + +- Removed the request limit since it's not currently being used. [Jamie Rees] + +- REmoved Sickbeared for the first release. [Jamie Rees] + +- Fixed #4 We now can manually set the status of a request. [tidusjar] + +- Made the pass in the port a bit more robust. [tidusjar] + +- Styling, Added the functionality for the Sonarr Profiles on the Admin page #2 resolved. [tidusjar] + +- Fixed a bug in the Login and added a unit test to cover that. Added a button to approve an individual request. Fixed some minor bugs in the request screen. [Jamie Rees] + +- Fixed the 'responsive' issue for the search and requests pages #3. [tidusjar] + +- Styling! #3. [tidusjar] + +- Navbar category now will follow you to various screens #3. [tidusjar] + +- Fixed bugs with the 'other' reporting issue and also the clear issues. [tidusjar] + +- We now are appending the users name to who wrote the comment. Rather than it being unknown. [tidusjar] + +- More work on submitting issues. [tidusjar] + +- More test changes. [tidusjar] + +- More tests to cover the login. [tidusjar] + +- Refactoring. [tidusjar] + +- Implimented the password part and authentication with Plex. [tidusjar] + +- Initial Use authentication is working. Need to do the password bit. [tidusjar] + +- Some error handling and ensure we are an admin to delete requests. [tidusjar] + +- Fixed the issue where the Release build would not show the admin screens! [tidusjar] + +- Fixes. [tidusjar] + +- Removed the DI part of the service. TinyIOC doesn't want to work with FluentScheduler. [tidusjar] + +- First pass at the plex update service. [tidusjar] + +- Small changes. [Jamie Rees] + +- Started to impliment the Plex checker. This will check plex every x minutes to see if there is any new content and then update the avalibility of the requests. [Jamie Rees] + +- Mre work. [Jamie Rees] + +- Few small changes, added plex settings. [Jamie Rees] + +- Making the configuration actually do something. Setting a default configuration if there is no DB. [Jamie Rees] + +- Remove post build. [Jamie Rees] + +- Small changes. [Jamie Rees] + +- MOre work. [Jamie Rees] + +- Fixed the issue when sending movies to CouchPotato. [Jamie Rees] + +- Add appveyor. [tidusjar] + +- Build it on 4.5. [tidusjar] + +- Upgraded .net to 4.6. [tidusjar] + +- Typo2. [tidusjar] + +- Typo. [tidusjar] + +- Another update. [tidusjar] + +- Fixed. [tidusjar] + +- More logging to figure out why the we cannot access the admin module in a release build. [tidusjar] + +- Firstpass integrating with CouchPotato. [tidusjar] + +- Some styling. [tidusjar] + +- Fixed the plex friends. Added some unit tests, moved the plex auth into it's own page. [tidusjar] + +- Fully switched the TV shows over to use the other provider. [Jamie Rees] + +- Renamed folders. [tidusjar] + +- Assembly updates. [tidusjar] + +- Moved the rest of the projects. [tidusjar] + +- Moved UI. [tidusjar] + +- Mass rename. [tidusjar] + +- Quick changes. [tidusjar] + +- Started switching the TV over to the new provider (TheTVDB). Currently TV search is partially broken. It will search but we are not mapping all of the details. [tidusjar] + +- Implimented the new TV show Provider (needed for Sonarr TheTvDB) [tidusjar] + +- Started the user auth. [tidusjar] + +- Some work on the requests page. [tidusjar] + +- Made the 'requested' better and made the remove look nicer. [tidusjar] + +- Cleaned up the program a tiny bit. [tidusjar] + +- Removed additional namespace. [tidusjar] + +- Fixed some db issues and added a preview. [Jamie Rees] + +- More work on the settings. [Jamie Rees] + +- Upgraded Json.Net and Nancy packages. [Jamie Rees] + +- Plex friends api. [Jamie Rees] + +- Enabled trace logs. [tidusjar] + +- Sql syntax issue fixed. [tidusjar] + +- Fixed release build. [tidusjar] + +- Small updates including assembly version. [tidusjar] + +- Work on the requests page mostly done. [tidusjar] + +- Work on the TV request. the `latest` parameter is not being passed into the requestTvshow. [tidusjar] + +- Missing file. [tidusjar] + +- Using the IoC container now. [tidusjar] + +- Some plex work. [Jamie Rees] + +- More work. [Jamie Rees] + +- Removed the setup code out of the startup, since we attemtp to connect to the DB before that. [Jamie Rees] + +- Some more work. Need to stop the form submitting on a request. [tidusjar] + +- Moved everything up a directory. [tidusjar] + +- Lots of work! [tidusjar] + +- Done most of the movie search work. [Jamie Rees] + +- First pass with RequestPlex. [tidusjar] + +- Initial commit. [Jamie] + + From 827ea857e0c818af3a952b43add2278f3349fbe0 Mon Sep 17 00:00:00 2001 From: Anojh Date: Wed, 11 Apr 2018 13:55:36 -0700 Subject: [PATCH 018/495] Inject base url if set before theme file url, see issue #1795 --- src/Ombi/Controllers/SettingsController.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 9ffa9d81f..44702a073 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -274,6 +274,12 @@ namespace Ombi.Controllers public async Task GetThemeContent([FromQuery]string url) { var css = await _githubApi.GetThemesRawContent(url); + var ombiSettings = await OmbiSettings(); + if (ombiSettings.BaseUrl != null) + { + int index = css.IndexOf("/api/"); + css = css.Insert(index, ombiSettings.BaseUrl); + } return Content(css, "text/css"); } From 7d62b4a712bd38829f7bde3275fcc11f5f584ade Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 12 Apr 2018 09:14:32 +0100 Subject: [PATCH 019/495] Removed some early disposition that seemed to be causing errors in the API --- src/Ombi/StartupExtensions.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index 1c8f54b4e..e4dae18e4 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -168,7 +168,6 @@ namespace Ombi if (user == null) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; - context.Response.RegisterForDispose(um); await context.Response.WriteAsync("Invalid User Access Token"); } else @@ -178,7 +177,6 @@ namespace Ombi var roles = await um.GetRolesAsync(user); var principal = new GenericPrincipal(identity, roles.ToArray()); context.User = principal; - context.Response.RegisterForDispose(um); await next(); } } @@ -191,7 +189,6 @@ namespace Ombi if (!valid) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; - context.Response.RegisterForDispose(settingsProvider); await context.Response.WriteAsync("Invalid API Key"); } else @@ -199,7 +196,6 @@ namespace Ombi var identity = new GenericIdentity("API"); var principal = new GenericPrincipal(identity, new[] { "Admin", "ApiUser" }); context.User = principal; - context.Response.RegisterForDispose(settingsProvider); await next(); } } From 7a7b00ab25aaa234b62a29cf92dd6d98aa84dcb1 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Fri, 13 Apr 2018 14:19:21 +0100 Subject: [PATCH 020/495] Add base url as a startup argument #2153 --- .../Entities/ApplicationConfiguration.cs | 1 + src/Ombi/Program.cs | 25 +++++++++++++++++++ src/Ombi/Startup.cs | 14 +++++++++++ 3 files changed, 40 insertions(+) diff --git a/src/Ombi.Store/Entities/ApplicationConfiguration.cs b/src/Ombi.Store/Entities/ApplicationConfiguration.cs index 1499ca34f..809264312 100644 --- a/src/Ombi.Store/Entities/ApplicationConfiguration.cs +++ b/src/Ombi.Store/Entities/ApplicationConfiguration.cs @@ -17,5 +17,6 @@ namespace Ombi.Store.Entities TheMovieDb = 4, StoragePath = 5, Notification = 6, + BaseUrl=7, } } \ No newline at end of file diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 9ced1715e..9294852f9 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -23,11 +23,13 @@ namespace Ombi var host = string.Empty; var storagePath = string.Empty; + var baseUrl = string.Empty; var result = Parser.Default.ParseArguments(args) .WithParsed(o => { host = o.Host; storagePath = o.StoragePath; + baseUrl = o.BaseUrl; }).WithNotParsed(err => { foreach (var e in err) @@ -47,6 +49,7 @@ namespace Ombi { var config = ctx.ApplicationConfigurations.ToList(); var url = config.FirstOrDefault(x => x.Type == ConfigurationTypes.Url); + var dbBaseUrl = config.FirstOrDefault(x => x.Type == ConfigurationTypes.BaseUrl); if (url == null) { url = new ApplicationConfiguration @@ -65,6 +68,25 @@ namespace Ombi ctx.SaveChanges(); urlValue = url.Value; } + + if (dbBaseUrl == null) + { + if (baseUrl.HasValue() && baseUrl.StartsWith("/")) + { + dbBaseUrl = new ApplicationConfiguration + { + Type = ConfigurationTypes.BaseUrl, + Value = baseUrl + }; + ctx.ApplicationConfigurations.Add(dbBaseUrl); + ctx.SaveChanges(); + } + } + else if(!baseUrl.Equals(dbBaseUrl.Value)) + { + dbBaseUrl.Value = baseUrl; + ctx.SaveChanges(); + } } DeleteSchedulesDb(); @@ -118,5 +140,8 @@ namespace Ombi [Option("storage", Required = false, HelpText = "Storage path, where we save the logs and database")] public string StoragePath { get; set; } + [Option("baseurl", Required = false, HelpText = "The base URL for reverse proxy scenarios")] + public string BaseUrl { get; set; } + } } diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 4aaadacb6..7a94dbb61 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -32,6 +32,7 @@ using Ombi.Schedule; using Ombi.Settings.Settings.Models; using Ombi.Store.Context; using Ombi.Store.Entities; +using Ombi.Store.Repository; using Serilog; using Serilog.Events; @@ -176,6 +177,19 @@ namespace Ombi { app.UsePathBase(settings.BaseUrl); } + else + { + // Check if it's in the startup args + var appConfig = serviceProvider.GetService(); + var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result; + if (baseUrl.Value.HasValue()) + { + settings.BaseUrl = baseUrl.Value; + ombiService.SaveSettings(settings); + + app.UsePathBase(settings.BaseUrl); + } + } app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)}); app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire", From 1d4d3c547600070fd7318e6678d663bacee532f5 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Fri, 13 Apr 2018 14:21:23 +0100 Subject: [PATCH 021/495] !wip added some missing code --- src/Ombi.Helpers/OmbiRoles.cs | 2 ++ src/Ombi/Controllers/IdentityController.cs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/Ombi.Helpers/OmbiRoles.cs b/src/Ombi.Helpers/OmbiRoles.cs index e7527279d..ba8c8d087 100644 --- a/src/Ombi.Helpers/OmbiRoles.cs +++ b/src/Ombi.Helpers/OmbiRoles.cs @@ -2,6 +2,8 @@ { public static class OmbiRoles { + // DONT FORGET TO ADD TO IDENTITYCONTROLLER.CREATEROLES AND THE UI! + public const string Admin = nameof(Admin); public const string AutoApproveMovie = nameof(AutoApproveMovie); public const string AutoApproveTv = nameof(AutoApproveTv); diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 6a8aee52c..5db5f2168 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -194,6 +194,7 @@ namespace Ombi.Controllers await CreateRole(OmbiRoles.RequestMovie); await CreateRole(OmbiRoles.RequestTv); await CreateRole(OmbiRoles.Disabled); + await CreateRole(OmbiRoles.RecievesNewsletter); } private async Task CreateRole(string role) From a681932d2e5d33e7d3d3a25f179027ae69421466 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 13 Apr 2018 22:38:38 +0100 Subject: [PATCH 022/495] Fixed a bug with the RefreshMetadata where we would never get TheMovieDBId's if it was missing it --- .../Jobs/Ombi/RefreshMetadata.cs | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 9d073facf..9b7726a15 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -80,7 +80,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (!hasTheMovieDb) { - var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title); + var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title, false); show.TheMovieDbId = id; } @@ -120,7 +120,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (!hasTheMovieDb) { - var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title); + var id = await GetTheMovieDbId(hasTvDbId, hasImdb, show.TvDbId, show.ImdbId, show.Title, false); show.TheMovieDbId = id; } @@ -166,7 +166,7 @@ namespace Ombi.Schedule.Jobs.Ombi } if (!hasTheMovieDb) { - var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title); + var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title, true); movie.TheMovieDbId = id; _plexRepo.UpdateWithoutSave(movie); } @@ -200,7 +200,7 @@ namespace Ombi.Schedule.Jobs.Ombi } if (!hasTheMovieDb) { - var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title); + var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title, true); movie.TheMovieDbId = id; _embyRepo.UpdateWithoutSave(movie); } @@ -215,7 +215,7 @@ namespace Ombi.Schedule.Jobs.Ombi await _embyRepo.SaveChangesAsync(); } - private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title) + private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title, bool movie) { _log.LogInformation("The Media item {0} does not have a TheMovieDbId, searching for TheMovieDbId", title); FindResult result = null; @@ -230,13 +230,29 @@ namespace Ombi.Schedule.Jobs.Ombi if (hasImdb && !hasResult) { result = await _movieApi.Find(imdbId, ExternalSource.imdb_id); - hasResult = result?.tv_results?.Length > 0; + if (movie) + { + hasResult = result?.movie_results?.Length > 0; + } + else + { + hasResult = result?.tv_results?.Length > 0; + + } _log.LogInformation("Setting Show {0} because we have ImdbId, result: {1}", title, hasResult); } if (hasResult) { - return result.tv_results?[0]?.id.ToString() ?? string.Empty; + if (movie) + { + return result.movie_results?[0]?.id.ToString() ?? string.Empty; + } + else + { + + return result.tv_results?[0]?.id.ToString() ?? string.Empty; + } } return string.Empty; } From eeaf614a29d2a1c063b4b9250cb86352b9b5af92 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 13 Apr 2018 23:19:57 +0100 Subject: [PATCH 023/495] Added a new Job. Plex Recently Added, this is a slimmed down version of the Plex Sync job, this will just scan the recently added list and not the whole library. I'd reccomend running this very regulary and the full scan not as regular. --- CHANGELOG.md | 3622 ----------------- src/Ombi.Api.Plex/IPlexApi.cs | 1 + src/Ombi.Api.Plex/Models/Metadata.cs | 4 +- src/Ombi.Api.Plex/PlexApi.cs | 9 + src/Ombi.DependencyInjection/IocExtensions.cs | 1 + src/Ombi.Schedule/JobSetup.cs | 7 +- .../Jobs/Plex/Interfaces/IPlexContentSync.cs | 2 +- .../Plex/Interfaces/IPlexRecentlyAddedSync.cs | 9 + .../Jobs/Plex/PlexContentSync.cs | 34 +- .../Jobs/Plex/PlexRecentlyAddedSync.cs | 40 + .../Settings/Models/JobSettings.cs | 1 + .../Settings/Models/JobSettingsHelper.cs | 7 +- .../ClientApp/app/interfaces/ISettings.ts | 1 + .../ClientApp/app/services/job.service.ts | 4 + .../app/settings/jobs/jobs.component.html | 6 + .../app/settings/jobs/jobs.component.ts | 1 + .../app/settings/plex/plex.component.html | 19 +- .../app/settings/plex/plex.component.ts | 10 +- src/Ombi/Controllers/JobController.cs | 13 +- src/Ombi/Controllers/SettingsController.cs | 1 + src/Ombi/Startup.cs | 11 +- 21 files changed, 152 insertions(+), 3651 deletions(-) create mode 100644 src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexRecentlyAddedSync.cs create mode 100644 src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bfe7e633..5c557ed19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,20 +8,10 @@ - Added the ability to turn off TV or Movies from the newsletter. [Jamie] -- Update about.component.html. [Jamie] - -- Update about.component.html. [Jamie] - - Added random versioning prefix to the translations so the users don't have to clear the cache. [Jamie] - Added more information to the about page. [Jamie] -- Changed let to const to adhere to linting. [Anojh] - -- Update _Layout.cshtml. [goldenpipes] - -- Update _Layout.cshtml. [goldenpipes] - - Changed the TV Request API. We now only require the TvDbId and the seasons and episodes that you want to request. This should make integration regarding TV a lot easier. [Jamie] ### **Fixes** @@ -32,8 +22,6 @@ - Made some improvements to the Sonarr Sync job #2127. [Jamie] -- Turn off Server GC to hopefully help with #2127. [Jamie Rees] - - Fixed #2109. [Jamie] - Fixed #2101. [Jamie] @@ -789,3613 +777,3 @@ - Switch to use a single HTTPClient rather than a new one every request !dev. [tidusjar] -- Fix non-admin rights (#1820) [Rob Gökemeijer] - -- Fix duplicated "Requests" element ID on new Issues link (#1817) [Shoghi Cervantes] - -- Add the Issue Reporting functionality (#1811) [Jamie] - -- Removed the forum. [tidusjar] - -- #1659 Made the option to ignore notifcations for auto approve. [Jamie] - -- New Crowdin translations (#1806) [Jamie] - -- Fixed a launch issue. [Jamie] - -- Allow users to login without a password. [Jamie] - -- Fixed the emby notifications not being sent. [Jamie] - -- #1802 and other small fixes. [tidusjar] - -- So... This sickrage thing should work now. [tidusjar] - -- Fixed emby connect login issue. [tidusjar] - -- Stop making unnecessary calls to the update service. [Jamie] - -- Fixed a bug where it blocked users with 0 limits. [Jamie] - -- Done #1788. [tidusjar] - -- More logging. [Jamie] - -- Fixed #1738. [Jamie] - -- Fixed build. [Jamie] - -- Fixed the issue where notifications were not sendind unless we restarted #1732. [tidusjar] - -- Fixed an issue with a trailing space in the subdir. [tidusjar] - -- Fixed #1774. [Jamie] - -- #1773. [Jamie] - -- Roll back rxjs (#1778) [bazhip] - -- Fixed build. [Jamie] - -- Fixed #1763. [Jamie] - -- Fix "content length error" on preview gif (#1768) [OoGuru] - -- New preview gif for Ombi V3 README (#1767) [OoGuru] - -- Remove debug code. [tidusjar] - -- Fix #1762. [tidusjar] - -- Fixed the preset themes not loading. [tidusjar] - -- Fixed #1760 and improvements on the auto updater. We may now support windows services... #1460. [Jamie] - -- Fixed #1754. [Jamie] - -- Hide the subject when it's not being used. [Jamie] - -- Error handling #1749. [Jamie] - -- New Crowdin translations (#1741) [Jamie] - -- #1732 #1722 #1711. [Jamie] - -- Fixed an issue with switching the preset themes. [Jamie] - -- Fixed #1743. [Jamie] - -- Fixed #1742. [tidusjar] - -- Fix #1742. [tidusjar] - -- Fixed landing page. [Jamie] - -- Fixed. [Jamie] - -- Translated the Requests page and fixed #1740. [Jamie] - -- Fix crash. [Jamie] - -- Sickrage done. Ish... So i've written all the code by looking at the API. the key there is i've looked at the api. I have not tested anything so expect this to fail. [Jamie] - -- SickRage settings UI. [Jamie] - -- Fixed #1721. [tidusjar] - -- Fixed the preset themes issue. [tidusjar] - -- New Crowdin translations (#1654) [Jamie] - -- Fix build. [Jamie] - -- #1460. [Jamie] - -- Fixed tests. [Jamie] - -- Return css as MIME text/css. [Jamie] - -- More added for the preset themes. [Jamie] - -- Moved around the custom styles. [Jamie] - -- More renames. [Jamie] - -- Renames. [Jamie] - -- Load the first 100 requests. [Jamie] - -- Reduce the memory consumption #1720. [Jamie] - -- Moved the schedules jobs into it's own database, see if it helps with the db locking #1720. [Jamie] - -- Fixed #1712. [tidusjar] - -- Potential fix for #1702. [tidusjar] - -- Fixed #1708. [tidusjar] - -- Fixed #1677. [tidusjar] - -- Fixed build. [tidusjar] - -- Potential fix for the DB locking issue #1720. [tidusjar] - -- #1698. [Jamie] - -- Fixed #1705. [tidusjar] - -- Fixed #1703. [tidusjar] - -- Finished adding preset themes. [Jamie] - -- Fixed #17000. [Jamie] - -- Remove the themes because waiting for a merge from lerams project. [Jamie] - -- Finsihed adding preset themes. [Jamie] - -- Fixed #1677. [Jamie] - -- Temp fix for #1683. [Jamie] - -- Fixed #1685. [Jamie] - -- Lossless Compression of images saves 83 KB (#1676) [Fish2] - -- Fixed the availability checker. [tidusjar] - -- Fixed build. [tidusjar] - -- Push out missing migration. [tidusjar] - -- Potential fix for #1674. [tidusjar] - -- Fixed an issue with the caching. [tidusjar] - -- Fixed telegram #1667. [tidusjar] - -- Fixed #1663. [tidusjar] - -- Should fix #1663. [tidusjar] - -- Stop logged in users going to the login page. [Jamie] - -- Fixed it not updating. Styles should be good now. [Jamie] - -- Re did some of the styling on the movie search page, let me know your thoughts. [Jamie] - -- Fixed #1657. [Jamie] - -- Fixed #1655. [Jamie] - -- Removed authentication resul. [Jamie] - -- New Crowdin translations (#1651) [Jamie] - -- New Crowdin translations (#1648) [Jamie] - -- New Crowdin translations (#1638) [Jamie] - -- Fixed #1644. [Jamie] - -- Moar logs #1643. [tidusjar] - -- Fixed #1640. [tidusjar] - -- Fixed the null ref exception #1460. [tidusjar] - -- Fixed landing page. [TidusJar] - -- Fixed #1641. [TidusJar] - -- Fixed #1641. [TidusJar] - -- New Crowdin translations (#1635) [Jamie] - -- Fixed #1631 and improved translation support Included startup args for the auto updater #1460 Mark TV requests as available #1632. [tidusjar] - -- Remove 32bit. [Jamie] - -- More 32bit support. [Jamie] - -- We now show "Available" for tv shows that is fully available #1602. [tidusjar] - -- Fixed the issue where we have got an episode but not the related series. #1620. [tidusjar] - -- Fixed the dropdown not working on iOS in the settings #1615. [tidusjar] - -- Fixed sonarr not monitoring the latest season #1534. [tidusjar] - -- Fixed the issue with firefox #1544. [tidusjar] - -- Fixed discord #1623. [tidusjar] - -- Add browserstack thanks (#1627) [Matt Jeanes] - -- Fix the exception #1613. [Jamie] - -- Found where we potentially are setting a new poster path, looks like the entity was being modified and being set as Tracked by entity framework, so the next time we called SaveChangesAsync() it would save the new posterpath on the entity. [Jamie] - -- Small modifications. [Jamie] - -- Fixed #1622. [Jamie] - -- Various improvements to webpack/gulp/vscode support (#1617) [Matt Jeanes] - -- Episodes in requests are now in order #1597 (#1614) [masterhuck] - -- Fixed a null reference issue in the Plex Content Cacher. [Jamie.Rees] - -- Fixed #1610. [tidusjar] - -- Really fixed the build this time. [tidusjar] - -- Fixed build. [tidusjar] - -- Made the updater work again #1460. [tidusjar] - -- Adding logging into the auto updater and also added more logging around the create inital user for #1604. [tidusjar] - -- Fixed the issue where we did not check if they are already in sonarr when choosing certain options #1540. [tidusjar] - -- We can now delete tv child requests and the parent will get remove #1603. [tidusjar] - -- Finished the api changes requested #1601. [tidusjar] - -- Fixed the Hangfire server timeout issue #1605. [tidusjar] - -- Fixed notifications not sending #1594. [tidusjar] - -- Fixed #1583 you can now delete users. Fixed the issue where the requested by was not showing. Finally fixed the broken poster paths. [tidusjar] - -- Fixed the issue where movie requests were no longer being requested. [tidusjar] - -- Started adding some more unit tests #1596. [Jamie.Rees] - -- #1588 When we make changes to any requests that we can trigger a notification, always send it to all notification agents, even if the user wont recieve it. [Jamie.Rees] - -- Add a message when email notifications are not setup when requesting a password reset. #1590. [Jamie.Rees] - -- Removed text that we no longer need. [Jamie.Rees] - -- Fixed #1574. [Jamie.Rees] - -- #1460 looks like the permissions issue has been resolved. Just need to make sure the Ombi process is terminated. [Jamie.Rees] - -- Put back the old download code. [Jamie.Rees] - -- Test. [Jamie] - -- Build sln. [Jamie.Rees] - -- Order by the username #1581. [Jamie.Rees] - -- Remove sonarr episodes from the cache table. [Jamie.Rees] - -- Couchpotato finished. [tidusjar] - -- Disable run import button if no import options are selected. [tidusjar] - -- Fixed #1574. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixes the issue with non windows systems unable to unzip the tarball #1460. [tidusjar] - -- Finished the couchpotato settings. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed #1570 #1571. [tidusjar] - -- Fixed #1547. [tidusjar] - -- Should fix #1538. [tidusjar] - -- Fixed #1553. [tidusjar] - -- Fixed #1546. [tidusjar] - -- Fixed #1543. [tidusjar] - -- Fixes an issue with Movie caching not working on develop branch of Radarr (#1567) [Jeffrey Peters] - -- This adds two fields to the Email Notifications settings page. It allows for the disabling of TLS/SSL as well as the ability to disable certificate validation when sending notification emails. (#1552) [Jeffrey Peters] - -- Fixed typo (#1551) [Codehhh] - -- Use Sqlite storage for Hangfire. [tidusjar] - -- Fixed the overrides #1539 also display it on screen now too. [tidusjar] - -- Fixed #1542 also added VSCode support. [tidusjar] - -- Fixed some cosmetic issues #865. [Jamie.Rees] - -- Fixed #1531. [Jamie.Rees] - -- Small fixes #865. [Jamie.Rees] - -- Some errors fixed and some ui improvements #865. [tidusjar] - -- Auto-scale large images down to container size (#1529) [Avi] - -- Fix logo on login page. (#1528) [Avi] - -- Another potential issue? :/ [tidusjar] - -- Real fix. [tidusjar] - -- #1513 Added storage path. [Jamie.Rees] - -- Fixed the discord issue relating to images #1513. [Jamie.Rees] - -- Fixed the issue sending movies to Radarr #1513 Fixed typo #1524. [Jamie.Rees] - -- Fixed logo on reset password pages fixed the run importer button on the user management settings. [Jamie.Rees] - -- Fixed crash/error #865. [tidusjar] - -- #1513 fixed the landing page and also the reverse proxy images. [tidusjar] - -- #1513 correctly set the child requests as approved. [tidusjar] - -- Fixed an issue that potentially causes as issue when siging into plex #865. [tidusjar] - -- Remove dev branch. [PotatoQuality] - -- Prepare readme for upcoming beta. [PotatoQuality] - -- #1513 partially fixed a bug. [tidusjar] - -- Fixed the exception. [tidusjar] - -- Fixed the application url not saving #1513. [tidusjar] - -- Fixed liniting. [tidusjar] - -- REVERSE PROXY BITCH! #1513. [tidusjar] - -- Fixed a bug where we were marking the wrong episodes as available #1513 #865. [Jamie.Rees] - -- Fixed an issue where we messed up the pages and routing. [Jamie.Rees] - -- Emby user importer is now therer! #1456. [tidusjar] - -- #1513 Added the update available icon. [tidusjar] - -- Fixed the issue of it showing as not requested when we find it in Radarr. Made the tv shows match a bit more to the movie requests Added the ability for plex and emby users to login Improved the welcome email, will only show for users that have not logged in Fixed discord notifications the about screen now checks if there is an update ready #1513. [tidusjar] - -- Support email addresses as usernames #1513. [Jamie.Rees] - -- Link to issue treath. [PotatoQuality] - -- Give correct feedback when testing email notifications #1513. [Jamie.Rees] - -- Report issue removed and the deny dropdown removed #1513. [Jamie.Rees] - -- #1513 removed the discord text when testing pushbullet. [Jamie.Rees] - -- Made a lot of changes around the notifcations to support the custom app name also started on the welcome email ##1456. [Jamie.Rees] - -- Fixed the bug where we were displaying shows where we do not have enough information to request #1513. [Jamie.Rees] - -- #1513 added the network to tv shows. [Jamie.Rees] - -- Fixed the whitespace issue #1513. [Jamie.Rees] - -- Fixed the swagger endpoint #865 #1513 Fixed the custom image issue on the login page Fixed the bug when clicking on the tab on the requests page it would switch to the wrong one Swagger is now back @ /swagger. [tidusjar] - -- Optimized images, Update old compressed image with a new lossless one. (#1514) [camjac251] - -- #1513 #865 Fixed the issue where we do not send the requests to Radarr/Sonarr when approving. [tidusjar] - -- #1506 #865 Fixed an issue with the test buttons not working correctly. [tidusjar] - -- #865 Added donation link. [tidusjar] - -- Fixed a bunch of issues on #1513. [tidusjar] - -- #1460 Added the Updater, it all seems to be working correctly. #865. [Jamie.Rees] - -- Removed percentage. [Jamie.Rees] - -- Fixed linter. [Jamie.Rees] - -- Fixed some bugs in the UI #865. [Jamie.Rees] - -- Improved the search buttons #865. [Jamie.Rees] - -- More logging #865. [Jamie.Rees] - -- Made build faster. [Jamie.Rees] - -- More logging. [Jamie.Rees] - -- Set debug level to Debug for now. [Jamie.Rees] - -- Add linting and indexes for interfaces/services (#1510) [Matt Jeanes] - -- Fixed the issue with the tv search not working #1463. [Jamie.Rees] - -- Latest practices... also probably broke some styles - sorry (#1508) [Matt Jeanes] - -- Build with the branch version. [tidusjar] - -- Build fix. [tidusjar] - -- Fixed build. [tidusjar] - -- Omgwtf so many changes. #865. [tidusjar] - -- Tests. [Jamie.Rees] - -- #1456 Started on the User Importer Also added the remember me button. [Jamie.Rees] - -- Made some UI changes, reworked the Emby and Plex screens to make them more user friendly and no so fugly. #865 Also made the login page placeholder text slightly lighter. [Jamie.Rees] - -- Cake skip verification build stuff #865. [Jamie.Rees] - -- Some fixes around the UI and managing requests #865. [tidusjar] - -- #1486. [Jamie.Rees] - -- #1486. [Jamie.Rees] - -- Upgraded to .net core 2.0 #1486. [Jamie.Rees] - -- #865 Finished the landing page, we now check the server's status. [Jamie.Rees] - -- Fixed build. [TidusJar] - -- Removed the telegram api. [Jamie.Rees] - -- Small changes on the updater #1460 #865. [Jamie.Rees] - -- Remove unused functions. [Dhruv Bhavsar] - -- Make Episode picker similar to Requests Child view. #1457 #1463. [Dhruv Bhavsar] - -- Fix merge conflict for TvRequests component. [Dhruv Bhavsar] - -- Upstream Changes... [Dhruv Bhavsar] - -- Clean up Requests page code by moving children request to old component, remove additional REST calls when merging and update component names to make more sense. [Dhruv Bhavsar] - -- Lots of different UI enhancements and fixes #865. [tidusjar] - -- Gitchangelog. [tidusjar] - -- Fixed the issue where we were using the wrong availability options. [tidusjar] - -- Fixed a bunch of bugs in Ombi #865. [tidusjar] - -- Build versioning. [Jamie.Rees] - -- #1460 The assembly versioning seems to work correctly now. [Jamie.Rees] - -- More build versioning changes #865. [tidusjar] - -- Fixed cake script. [Jamie.Rees] - -- WIP on the build versioning for the Updater #1460 #865. [Jamie.Rees] - -- Versioning. [Jamie.Rees] - -- Package versions. [Jamie.Rees] - -- #1460 #865 working on the auto updater. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Small changes around the roles #865. [tidusjar] - -- Improvements to the UI and also finished the availability checker #865 #1464. [Jamie.Rees] - -- Availability Checker #1464 #865. [Jamie.Rees] - -- Fixed ##1492 and finished the episode searcher for #1464. [Jamie.Rees] - -- #1464. [tidusjar] - -- Reload the settings #1464 #865. [Jamie.Rees] - -- #1464 added the Plex episode cacher #865. [Jamie.Rees] - -- Fixed some issues around the tv requests area Added mattermost and telegram notifications #1459 #865 #1457. [tidusjar] - -- Fix global.json. [Dhruv Bhavsar] - -- Working UI for Requests. Approval/Deny does not work as it doesn't in your code either. [Dhruv Bhavsar] - -- Enable diagnostic on build #865. [Jamie.Rees] - -- Fixed the user token issue #865. [Jamie.Rees] - -- Some small refresh token work #865. [Jamie.Rees] - -- Initial TV Requests UI rebuild. [Dhruv Bhavsar] - -- Made a start on supporting multiple emby servers, the UI needs rework #865. [Jamie.Rees] - -- #865 #1459 Added the Sender From field for email notifcations. We can now have "Friendly Names" for email notifications. [Jamie.Rees] - -- Redirect to the landing page when enabled #1458 #865. [Jamie.Rees] - -- Removed IdentityServer, it was overkill #865. [Jamie.Rees] - -- Fixed another bug with identity. #865 I'm thinking about removing it. Causing more hassle than it's worth. [tidusjar] - -- #1460 #865. [tidusjar] - -- Delete appveyor_old.yml. [Jamie] - -- Fixed path. [Jamie.Rees] - -- Silent build level. [Jamie.Rees] - -- #1459 Forgot to get the Pushbullet agent to look up the pusbullet templates rather than the Discord ones. Updated the Gitchange log. [Jamie.Rees] - -- Made the placeholder color on the login page a bit lighter #865. [Jamie.Rees] - -- Landing and login page changes #865 #1485. [tidusjar] - -- #1458 #865 More work on landing. [Jamie.Rees] - -- Working on the landing page #1458 #865. [tidusjar] - -- A lot of clean up and added a new Image api #865. [Jamie.Rees] - -- Cleaned up the Logging API slightly #1465 #865. [Jamie.Rees] - -- Fixed the Identity Server discovery bug #1456 #865. [tidusjar] - -- Fixed the issue with the Identity Server running on a different port, we can now use -url #865. [Jamie.Rees] - -- Try again. [TidusJar] - -- Publish ubuntu 16.04. [Jamie.Rees] - -- Chnaged the updater job from Minutely to Hourly. [Jamie.Rees] - -- Some work around the Auto Updater and other small changes #1460 #865. [Jamie.Rees] - -- Missed a file. [tidusjar] - -- Fixed the swagger issue. [tidusjar] - -- RDP issues. [tidusjar] - -- Appveyor build rdp investigation. [tidusjar] - -- Working on the requests page #1457 #865. [tidusjar] - -- Made the password reset email style the same as other email notifications #1456 #865. [Jamie.Rees] - -- Fixed some bugs around the authentication #1456 #865. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Fixed build #1456. [Jamie.Rees] - -- #1456 #865 Started on allowing Plex Users to sign in through the new authentication server. [Jamie.Rees] - -- Removed covalent. [Jamie.Rees] - -- #1456 Reset Password stuff #865. [Jamie.Rees] - -- Finished implimenting Identity with IdentityServer4. #865 #1456. [Jamie.Rees] - -- Moved over to using Identity Server with Asp.Net Core Identity #1456 #865. [Jamie.Rees] - -- Started on the requests rework #865. [Jamie.Rees] - -- Extended the Emby API. [Jamie.Rees] - -- Started reworking the usermanagement page #1456 #865. [tidusjar] - -- Lots of refactoring #865. [Jamie.Rees] - -- Created an individual user api endpoint so we can make the user management pages better #865. [TidusJar] - -- Lot's of refactoring. [Jamie.Rees] - -- #1462 #865 Had to refactor how we use notificaitons. So we now have more notification fields about the request. [Jamie.Rees] - -- Looks like Sonarr is finished and works. A lot simplier this time around. #865. [tidusjar] - -- More work on the Sonarr Api Integration #865. [tidusjar] - -- Started on sonarr #865. [tidusjar] - -- Small changes #865. [tidusjar] - -- Damn son. So many changes... Fixed alot of stuff around tv episodes with the new DB model #865. [tidusjar] - -- Fixed the TV Requests issue #865. [Jamie.Rees] - -- Fixed a load of bugs need to figure out what is wrong with tv requests #865. [tidusjar] - -- #865 rework the backend data. Actually use real models rather than a JSON store. [Jamie.Rees] - -- Fixed the build issue #865. [tidusjar] - -- Allow us to use Emby as a media server. [tidusjar] - -- More Update #865. [Jamie.Rees] - -- Deployment changes. [Jamie.Rees] - -- More work on the Updater. [Jamie.Rees] - -- Lots of fixes. Becoming more stable now. #865. [tidusjar] - -- Small fixes around the searching. [Jamie.Rees] - -- Some rules #865. [Jamie.Rees] - -- Oops. [TidusJar] - -- Started on the Discord API settings page. [TidusJar] - -- Email Notifications are now fully customizable and work! #865. [Jamie.Rees] - -- Small changes and fixed some stylingon the plex page #865. [Jamie.Rees] - -- More on #865 TODO, Find out whats going on with the notifications and why exceptions are being thrown. [Jamie.Rees] - -- Oops. [Jamie.Rees] - -- Ok #865 fixed the published exe. [Jamie.Rees] - -- Fixed errors. [Jamie.Rees] - -- Fixed build script. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Some more #865. [Jamie.Rees] - -- Create appveyor.yml. [Jamie] - -- The Approving child requests now work! [Jamie.Rees] - -- Fixed many bugs #865. [Jamie.Rees] - -- Loads of changes, improved the movie search stylings is back. [Jamie.Rees] - -- Moved to webpack and started on new style. [Jamie.Rees] - -- Fixed the TV search via Trakt not returning Images anymore. #865. [Jamie.Rees] - -- Rules changes and rework. [Jamie.Rees] - -- Request Grid test. [Jamie.Rees] - -- Small cleanup #865. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Started the Radarr Settings #865. [Jamie.Rees] - -- Massive amount of rework on the plex settings page. It's pretty decent now! #865. [tidusjar] - -- Fixed build. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Rules #865. [tidusjar] - -- Stuff. [Jamie.Rees] - -- Forgot to uncomment. [Jamie.Rees] - -- Tetsd. [Jamie.Rees] - -- Build task changes. [Jamie.Rees] - -- Adsa. [Jamie.Rees] - -- Appveyor. [Jamie.Rees] - -- Stuff around tokens and also builds. [Jamie.Rees] - -- Finished the Plex Content Cacher. Need to do the episodes part but things are now showing as available! #865. [tidusjar] - -- Small user changes #865. [Jamie.Rees] - -- Stuff #865 need to work on the claims correctly. [Jamie.Rees] - -- Reworked the TV model AGAIN #865. [Jamie.Rees] - -- The move! [Jamie.Rees] - -- Fixed build #865. [Jamie.Rees] - -- Fixed the user management #865. [Jamie.Rees] - -- #865 Added support for multiple plex servers. [Jamie.Rees] - -- Bleh. [tidusjar] - -- Small changes. [Jamie.Rees] - -- Fixed the build. [Jamie.Rees] - -- Fixes. [Jamie.Rees] - -- Bundling changes. [Jamie.Rees] - -- Some series information stuff, changes the pace theme too. [Jamie.Rees] - -- Docker support and more, redesign the episodes. [tidusjar] - -- Stuff around episode/season searching/requesting. [Jamie.Rees] - -- Removed redundant folders. [tidusjar] - -- Lots of backend work. [tidusjar] - -- Fixed build. [Jamie.Rees] - -- TV Request stuff. [Jamie.Rees] - -- Work around the user management. [tidusjar] - -- More. [Jamie.Rees] - -- Lots and Lots of work. [Jamie.Rees] - -- Diagnostic changes. [tidusjar] - -- Fixed hangfire exception. [tidusjar] - -- Remove xunit. [tidusjar] - -- Lots more work :( [Jamie.Rees] - -- More changes. [tidusjar] - -- #865. [Jamie.Rees] - -- Small changes. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- More mapping. [Jamie.Rees] - -- Mapping mainly. [Jamie.Rees] - -- Fix systemjs config not being included. [Matt Jeanes] - -- Fixed bundling and various improvements. [Matt Jeanes] - -- Finished the emby wizard #865. [tidusjar] - -- Finished the wizard #865 (For Plex Anyway) [tidusjar] - -- Small changes. [tidusjar] - -- More work on Wizard and Plex API #865. [tidusjar] - -- Settings. [Jamie.Rees] - -- Settings for Ombi. [Jamie.Rees] - -- Fixed some issues around the identity. [Jamie.Rees] - -- #865 more for the authentication. [tidusjar] - -- Auth. [Jamie.Rees] - -- More on the search and requests page. It's almost there for movies. Need to add some filtering logic #865. [tidusjar] - -- #865. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Messing around with the settings. [tidusjar] - -- Fixed the yml. [Jamie.Rees] - -- Remove unneeded bundle config. [Matt Jeanes] - -- Redo dotnet publish targets. [Jamie.Rees] - -- Bundling changes. [Jamie.Rees] - -- Stuff. [Jamie.Rees] - -- Move app into wwwroot. [Jamie.Rees] - -- Put uglify back in! [Jamie.Rees] - -- Wrong line. [Jamie.Rees] - -- Matt is helping. [Jamie.Rees] - -- Revert. [tidusjar] - -- Small tweaks. [tidusjar] - -- Upgrade to .Net Standard 1.6. [tidusjar] - - -## v2.2.1 (2017-04-09) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the forums. [tidusjar] - -- Updates. [tidusjar] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added a retry policy around the emby newsletter. [Jamie.Rees] - -### **Fixes** - -- Revert "Merge branch 'DotNetCore' into dev" [tidusjar] - -- More borken build. [Jamie.Rees] - -- Started adding requesting. [Jamie.Rees] - -- Done the movie searching. [tidusjar] - -- #865. [tidusjar] - -- More. [tidusjar] - -- Moar. [tidusjar] - -- Small changes. [tidusjar] - -- Styling. [Jamie.Rees] - -- MOre changes. [Jamie.Rees] - -- Spacing. [Jamie.Rees] - -- Try again. [Jamie.Rees] - -- More. [Jamie.Rees] - -- Again. [Jamie.Rees] - -- Anbother. [Jamie.Rees] - -- Another. [Jamie.Rees] - -- Another. [Jamie.Rees] - -- Retry. [Jamie.Rees] - -- A. [Jamie.Rees] - -- Fixed. [Jamie.Rees] - -- Cahnge 2. [Jamie.Rees] - -- Appveyor change. [Jamie.Rees] - -- The start of a new world. [Jamie.Rees] - -- Fixed the migration number and order by the added date for the newsletter #1264. [tidusjar] - -- Forgot this change. [tidusjar] - -- Also fixed the issue for the Emby Newsletter where episodes were not getting added :( [tidusjar] - -- #1264 "They may take our lives, but they'll never take our freedom!" [tidusjar] - -- Finished reworking the Sonarr Integration. Seems to be working as expected, faster and most stable. It's Not A Toomah! [tidusjar] - -- Small bit of work. [Jamie.Rees] - -- Made a start on the new Sonarr integration. [tidusjar] - -- For test emails, if there is no new content then just grab some old data. [tidusjar] - -- Fixed an issue where the emby newsletter was always showing series. [tidusjar] - - -## v2.2.0 (2017-03-30) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added a new setting for the Netflix option, we can now disable it appearing in the search. [tidusjar] - -- Update German Translation. [Marius Schiffer] - -- Added a release notes page, you can access via Admin>Updates>Recent Changes tab. Note to self, need to put better comments in for users to understand! [Jamie.Rees] - -- Added gravitar image. [Jamie.Rees] - -- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] - -- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] - -- Added some logging around API calls. [smcpeck] - -- Changed IEmbyAvailabilityChecker to use IEnumberables + checking actor search against Emby content + PR feedback. [smcpeck] - -- Changed actor searching to support non-actors too. [smcpeck] - -- Added a 10 second timer to refresh some new caching I put in. [smcpeck] - -- Added root folder and approving quality profiles in radarr #1065. [tidusjar] - -- Added some debugging code around the newsletter for Emby #1116. [tidusjar] - -- Added a TMDB Rate limiter for the newsletter. [tidusjar] - -- Added port check in wizard. also fixed favicon. [tidusjar] - -- Update Radarr placeholder. [d2dyno] - -- Added the user login for emby users #435. [tidusjar] - -- Added User Management support for Emby #435. [tidusjar] - -- Added emby to the sidebar #435. [tidusjar] - -- Added API endpoint for /actor/new/ to support searching for movies not already available/requested. [smcpeck] - -- Update ISSUE_TEMPLATE.md. [Jamie] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -### **Fixes** - -- Translation changes. [Jamie.Rees] - -- Syntax error. [tidusjar] - -- Fixed an issue where we were retrying the API call when the Plex users login creds were invalid. #1217. [tidusjar] - -- Slightly increased the wait time for the emby newsletter also fixed a potential error in the plex user checker. [Jamie.Rees] - -- Fixed an issue where we were not notifiying emby users. [Jamie.Rees] - -- Fixed the issue where the recent changes page was not showing the correct date. #1296. [Jamie.Rees] - -- Fixed #1252 (Show the correct user type on the management page for Plex Users) [Jamie.Rees] - -- Fixed the casting error #1292. [Jamie.Rees] - -- Fix test newletter not sending when empty. [Dhruv Bhavsar] - -- Quick fix for email false positive message. ISSUE: #1286. [Dhruv Bhavsar] - -- Fixes around the newsletter. We will now correctly show newly added shows and also newly added episodes. #1163. [tidusjar] - -- Fixed a sonarr deseralization error. [tidusjar] - -- Increased the delay for the Episode information api calls. #1163. [tidusjar] - -- Looks like we were overloading emby with out api calls. [tidusjar] - -- Fixed the root path escaping issue for Radarr too! [tidusjar] - -- Some small backend newsletter changes, we can now detect if there are any movies and/or tv shows, if there are none then we will no longer send out an empty newsletter. [Jamie.Rees] - -- Remoddeled the notificaiton settings to make it easier to add more. This is some techinical changes that no one except me will ever notice :( [Jamie.Rees] - -- Fixed #1234. [Jamie.Rees] - -- A fix to the about page and also started to rework the notification backend slightly to easily add more notifications. [Jamie.Rees] - -- Adding more logging into the Plex Cacher. [Jamie.Rees] - -- #1218 changed the text when we cannot display release notes for dev and EAP branches. [Jamie.Rees] - -- Fix for #1236. [SuperPotatoMen] - -- Tooltips. [Jamie.Rees] - -- #236. [Jamie.Rees] - -- #1102. [Jamie.Rees] - -- Done #1012. [Jamie.Rees] - -- Oops #1134. [Jamie.Rees] - -- Fixed #1121. [Jamie.Rees] - -- Fixed #1210. [Jamie.Rees] - -- Fixed typo #1134. [Jamie.Rees] - -- Fixed #1223. [Jamie.Rees] - -- Another newsletter fix attempt #1163 #1116. [tidusjar] - -- Fixup! Reset the branch on v2.1.0 tag to get to a shared state between dev and Master. [distaula] - -- Fixed a bug in the Plex Newsletter. [tidusjar] - -- Typo. [tidusjar] - -- Fixed around the newsletter and a small feature around the permissions/features (#1215) [Jamie] - -- Fixed #1189. [tidusjar] - -- Fixed #1195. [Jamie.Rees] - -- Fixed #1195. [Jamie.Rees] - -- Fixed #1192. [Jamie.Rees] - -- Fixed issue where we could get null rating keys on Plex. [tidusjar] - -- Needed to treat a 201 as success, too. + removed some commented out code. [Shaun McPeck] - -- Normalized spacing/tabs. [smcpeck] - -- Move local user login to be the first thing checked; renamed old Api variable to PlexApi now that Emby is in play. [smcpeck] - -- Remove all the polling/retry logic around HP requests. This was a problem do to not properly awaiting the initial AddArtist API call being sent to HP. Also fix SetAlbumStatus to use ReleaseId instead of MusicBrainsId (same fix previously applied to AddArtist). [smcpeck] - -- Restore checking of HTTP StatusCode on ApiRequests; remove checking of response.ErrorException. [smcpeck] - -- Reverted (for now) non-200 response handling; added some extra logging. [smcpeck] - -- Tweaked ApiRequest behavior on non-200 responses; think it was breaking login. :-" [smcpeck] - -- Only deserialize response payload in ApiRequest when StatusCode == 200. Will a default return value in other cases cause other issues? [smcpeck] - -- Headphones - added releaseID to generic RequestedModel and passing that through to HP request. Their API doesn't request via the MusicBrainzId. [smcpeck] - -- Fixed #1038. [tidusjar] - -- Fixed a slight issue where we could click the change folders button rather than the dropdown arrow #1189. [tidusjar] - -- Bunch of updater files. [tidusjar] - -- #1163 #117. [tidusjar] - -- Removed some unnecessary 'ConfigureAwait` uses. [smcpeck] - -- Remove meaningless html class from actor searching checkbox. [smcpeck] - -- Fixed an issue where we were not always showing movies from external programs. [tidusjar] - -- Remove extra delay when filtering out existing movies. [smcpeck] - -- Post merge build fixes. [smcpeck] - -- Fix. [tidusjar] - -- Fixed #1177. [tidusjar] - -- Fixed #1152. [tidusjar] - -- Fixed #1123. [tidusjar] - -- Fixed a bug when sending to radarr. [tidusjar] - -- Fixed #1133. [tidusjar] - -- Fixed issues img. [Jamie.Rees] - -- Stop Plex being enabled on the first time installing #1048. [Jamie.Rees] - -- The landing page now works for emby #435. [tidusjar] - -- Fixed #1104. [tidusjar] - -- Fixed #1090. [tidusjar] - -- Fixed #1103. [tidusjar] - -- Small changes. [tidusjar] - -- Break out Mass Email feature into its own tab, upgrade Font Awesome and clean up some comments. [dhruvb14] - -- Fix typo. [Travis Bybee] - -- Fixed #1066. [Jamie.Rees] - -- Fixed broken builds. [Jamie.Rees] - -- Fixed #1083. [Jamie.Rees] - -- #1049. [tidusjar] - -- Fixed #1071. [tidusjar] - -- Fixed #1048 #1081. [tidusjar] - -- #1074. [Jamie.Rees] - -- #1069. [Jamie.Rees] - -- Fix for #1068. [tidusjar] - -- Remove duplciate tv show status. [tidusjar] - -- Some request ui changes. [tidusjar] - -- Removed references to Plex. [tidusjar] - -- Removed plex from the scheduled jobs ui. [tidusjar] - -- First run of the newsletter set it to a test. [tidusjar] - -- Reworked the newsletter for Emby! Need to rework it for Plex and use the new way to do it. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed the mass email, it was only being set to users with the newsletter feature #358. [tidusjar] - -- Removed Plex Request from the notifications. [tidusjar] - -- Finish implementing mass email feature. [dhruvb14] - -- @tidusjar pointed out runtime error!! [dhruvb14] - -- Does not compile, need to get data from UI into nancy somehow and figure out why IMassEmail is not initializing. [dhruvb14] - -- Begin Implementing Mass Email Section. [dhruvb14] - -- Hide the auto update btn #236 Fixed where we were not populating the emby episodes #435. [tidusjar] - -- Fix Radarr labels. [d2dyno] - -- Fixed pace loader. [Jamie.Rees] - -- Check if Emby/Plex is enabled before starting the job. [Jamie.Rees] - -- Fixed #1036. [Jamie.Rees] - -- Fixed a typo and changed wording. [Torkil Liseth] - -- Fixed #1035. [Jamie.Rees] - -- Fix for #1026. [Jamie.Rees] - -- Fixed #1042. [tidusjar] - -- #435. [Jamie.Rees] - -- #435 Started the wizard. [Jamie.Rees] - -- Removed. [tidusjar] - -- Final Fixes. [dhruvb14] - -- Partial fix for broken HR tag's in Email... [dhruvb14] - -- DAMN! #435 that's a lot of code! [tidusjar] - -- Started adding Emby, Lots of backend work done. Need a few more services done and login and user management. #435. [tidusjar] - -- UI changes to add checkbox and support searching for only new matches via new API. [smcpeck] - -- REFACTOR: IAvailabilityChecker - changed arrays to IEnumerables. [smcpeck] - -- UI changes to consume actor searching API. [smcpeck] - -- API changes to allow for searching movies by actor. [smcpeck] - -- Enforcing async/await in synchronous methods that were marked async. [smcpeck] - - -## v2.1.0 (2017-01-31) - -### **New Features** - -- Update README.md. [Jamie] - -- Update .gitattributes. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added the new labels to the search. [tidusjar] - -- Added a switch to use the new search or not, just in case people do not like it. added a migration to turn on the new search. [Jamie.Rees] - -- Added a bunch of categories for tv search similar to what we have for movies. [Jamie.Rees] - -### **Fixes** - -- Fixed typos. [Haries Ramdhani] - -- Fix typo in readme. [tdorsey] - -- Fixed #985. [Jamie.Rees] - -- FIxed #978. [tidusjar] - -- Fixed the approval issue for #939. [tidusjar] - -- Some general improvements. [tidusjar] - -- Turned off migration for now. [tidusjar] - -- Fixed #998. [tidusjar] - -- Additional movie information. [Jamie.Rees] - -- Debug info around the notifications. [Jamie.Rees] - -- Small changes. [tidusjar] - -- Fixed #995. [tidusjar] - -- Fix for #978. [tidusjar] - -- Fixed #991. [tidusjar] - -- Fixed the login issue and pass Radarr the year #990. [Jamie.Rees] - -- More small tweaks around the username/alias. [Jamie.Rees] - -- Possible issue with the empty username. [Jamie.Rees] - -- Potential Fix for #985. [Jamie.Rees] - -- Small changed to the sidebar. [Jamie.Rees] - -- Small changes. [Jamie.Rees] - -- Done #627. [Jamie.Rees] - -- Finished #535 #445 #170. [tidusjar] - -- Fixed tests. [Jamie.Rees] - -- Started to add the specify Sonarr root folders. [Jamie.Rees] - -- Fixed #968. [Jamie.Rees] - -- Fixed #970. [Jamie.Rees] - -- Done #924. [Jamie.Rees] - -- Fixed. [Jamie.Rees] - -- Fixed #955. [Jamie.Rees] - -- #956. [Jamie.Rees] - -- Fixed #947. [Jamie.Rees] - -- #951. [tidusjar] - -- Finished #923 !!! [tidusjar] - -- More for #923. [Jamie.Rees] - -- Radarr integartion in progress #923. [tidusjar] - -- Fixed #940 don't show any shows without a tvdb id. [tidusjar] - -- Finished #739. [Jamie.Rees] - -- Initial impliementation of #739. [Jamie.Rees] - -- Improved the search UI and made it more consistant. Finished the Netflix API Part #884. [Jamie.Rees] - - -## v2.0.1 (2017-01-16) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added a netflix api. [Jamie.Rees] - -### **Fixes** - -- Fixed #934. [Jamie.Rees] - - -## v2.0 (2017-01-14) - -### **New Features** - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Added the settings for #925 but need to apply the settings to the UI. [Jamie.Rees] - -- Changed the settings name from Plex Requests to Ombi. [Jamie.Rees] - -- Added support for Managed Users #811. [Jamie.Rees] - -- Change solution name in travis. [mhann] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -### **Fixes** - -- Finished #925. [Jamie.Rees] - -- Some TODO's. [Jamie.Rees] - -- Fixed #915. [Jamie.Rees] - -- Fixed the issue where notifications are not being sent to users with Aliases #912. [Jamie.Rees] - -- Fixed #891. [Jamie.Rees] - -- Fix indentation issue. [Marcus Hann] - -- Implement simple button. [Marcus Hann] - -- Plex Username Case Sensitivity Fix. [thegame3202] - -- Fixed #882. [Jamie.Rees] - -- Api changed again, so more fixes for #878. [Jamie.Rees] - -- Possible fix for #893. [Jamie.Rees] - -- Fixed #898. [Jamie.Rees] - -- Fixed #878. [TidusJar] - -- * userManagementController.js: fixed #881. [TidusJar] - -- More work on watcher, should all be good now. #878. [Jamie.Rees] - -- Delete PlexRequests.sln.DotSettings. [Jamie] - -- Fixed #862. [Jamie.Rees] - -- #399 and #398 finished. [Jamie.Rees] - -- More work on #399. [Jamie.Rees] - -- Finished #884. [Jamie.Rees] - -- More for #844. [Jamie.Rees] - -- Another #844. [Jamie.Rees] - -- Fixed a dependancy issue with #844. [Jamie.Rees] - -- Finished the main part of #844 just need testing. [Jamie.Rees] - -- Fixed #832. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Fix tiny readme typo. [mhann] - -- Fixed #850 also started #844 (Wrote the API interaction) [Jamie.Rees] - -- #801 #292 done. [Jamie.Rees] - -- Should fix #841 #835 #810. [Jamie.Rees] - -- Fix small typo in ticket overview page. [mhann] - -- More work on the combined login. [Jamie.Rees] - -- Fixed db issue. [Jamie.Rees] - -- Name changes. [Jamie.Rees] - -- All Sln changes. [tidusjar] - -- Moved API Sln dir. [tidusjar] - -- Fixed build. [tidusjar] - -- Moved namespaces. [tidusjar] - -- Renamed zip. [tidusjar] - -- Product name change. [tidusjar] - - -## v1.10.1 (2016-12-17) - -### **Fixes** - -- #788 fixed! [tidusjar] - -- Fixed #788 and #791. [tidusjar] - -- #399 #398. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Small refactorings. [Jamie.Rees] - -- #782. [Jamie.Rees] - -- #785. [Jamie.Rees] - - -## v1.10.0 (2016-12-15) - -### **New Features** - -- Update README.md. [Jamie] - -- Added optional launch args for the auto updater. [Jamie.Rees] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update _Navbar.cshtml. [Jamie] - -- Update README.md. [Jamie] - -- Update _Navbar.cshtml. [Jamie] - -- Update README.md. [Jamie] - -- Added a new permission to bypass the request limit. [Jamie.Rees] - -- Update Version1100.cs. [SuperPotatoMen] - -- Added logging around the Newsletter #717. [Jamie.Rees] - -- Added missing migration. [tidusjar] - -- Added loading spinner. [Jamie.Rees] - -- Update UI.resx. [SuperPotatoMen] - -- Update Version1100.cs. [Jamie] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -### **Fixes** - -- Fixed an issue where the HTML in the newsletter was incorrect. [Jamie.Rees] - -- Fixed #201. [Jamie.Rees] - -- Fixed #720 and added better error handling around the migrations. [Jamie.Rees] - -- Fixed #769. [Jamie.Rees] - -- Write out the actual file version. [Jamie.Rees] - -- Error checking around GA. [TidusJar] - -- Fixed #761. [tidusjar] - -- Fixed #749 Fixed an issue where we were adding the read only permission when creating the admin. [tidusjar] - -- Fixed #757. [tidusjar] - -- Fixes around the server admin #754. [Jamie.Rees] - -- Removed the trace option from the UI, it is only accessible when appending the url with "?developer" #753. [Jamie.Rees] - -- Fixed an issue where the admin could not be updated. [Jamie.Rees] - -- Fixed #745. [Jamie.Rees] - -- Fixed #748. [Jamie.Rees] - -- Workaround for #748. [SuperPotatoMen] - -- Another attempt to fix #717. [tidusjar] - -- Fixed #744. [Jamie.Rees] - -- Tidied up the warnings. [Jamie.Rees] - -- Small bit of analytics. [Jamie.Rees] - -- Removed the whitelist. [Jamie.Rees] - -- Should fix #696 Fixed an issue with the scheduled jobs where it could use a different trigger if the order between the schedules and the triggers were in different positions in the array... Stupid me, ordering both arrays by the name now. [tidusjar] - -- Some better null object handling #731. [Jamie.Rees] - -- Small tweaks. [Jamie.Rees] - -- Fixed #728. [Jamie.Rees] - -- Fixed #727. [Jamie.Rees] - -- Fixed admin redirect issue. [tidusjar] - -- Fixed #718. [tidusjar] - -- Lots of small fixes and tweaks. [Jamie.Rees] - -- Tidied up some of the angular code, split the UI into it's own directives for easier maintainability. [Jamie.Rees] - -- Small tweaks to the Request Page. [Jamie.Rees] - -- Reverted the PR that may have caused #619. [Jamie.Rees] - -- Some small tweaks around #218 Just added the link to the settings and some angular improvements. [Jamie.Rees] - -- Test. [Jamie.Rees] - -- Attempt at fixing #686. [Jamie.Rees] - -- Finished #707. [Jamie.Rees] - -- Fixed #704. [Jamie.Rees] - -- Fixed #705. [Jamie.Rees] - -- Fixed #706. [Jamie.Rees] - -- #547. [Jamie.Rees] - -- Default tabs #304. [Jamie.Rees] - -- Fixed #703. [Jamie.Rees] - -- #233. [Jamie.Rees] - -- Done #678. [Jamie.Rees] - -- Fixed #670. [Jamie.Rees] - -- #456 Update all the requests when we identify that the username changes. [Jamie.Rees] - -- More user management. [Jamie.Rees] - -- #218. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Implimented the features #218. [tidusjar] - -- Use the user alias everywhere if it is set #218. [tidusjar] - -- Implimented auto approve permissions #218. [tidusjar] - -- A. [tidusjar] - -- Fixed an IOC issue. [tidusjar] - -- Fixed the issue with user management, needed to implement our own authentication provider. [Jamie.Rees] - -- Small changes including #666. [Jamie.Rees] - -- Done #679. [tidusjar] - -- Reduce the retry time. [Jamie.Rees] - -- Remove all references to the claims. [Jamie.Rees] - -- Lots of fixed and stuff. [Jamie.Rees] - -- Fixed potential crash #683. [Jamie.Rees] - -- Fixed #681. [Jamie.Rees] - -- More user management. [Jamie.Rees] - -- Finishing off the user management page #218 #359 #195. [Jamie.Rees] - -- Finished #646 and fixed #664. [Jamie.Rees] - -- Started on #646. Fixed #657. [Jamie.Rees] - -- Fixed #665. [Jamie.Rees] - -- Migrate users. [TidusJar] - -- Fixed build. [Jamie.Rees] - -- Convert the for to foreach for better readability. Still need to rework this area. [Jamie.Rees] - -- Final Tweaks #483. [Jamie.Rees] - -- Finished #483. [Jamie.Rees] - -- Finished the queue #483. [Jamie.Rees] - -- Started on the queue for requests #483 TV Requests with missing information has been completed. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Finished the notification for the fault queue. [Jamie.Rees] - -- Finished #556. [Jamie.Rees] - -- Finished #633 (First part of the queuing) [Jamie.Rees] - -- Finished #659 #236 has been modified slightly. Needs testing on Different systems. [Jamie.Rees] - -- Almost finished #659. [Jamie.Rees] - -- Started on #483. [Jamie.Rees] - -- #544. [Jamie.Rees] - -- Fixed #656 and more work on #218. [Jamie.Rees] - -- Fixed some issues with the user management work. [TidusJar] - -- Fixed build issue. [TidusJar] - -- User perms. [Jamie.Rees] - - -## v1.9.7 (2016-11-02) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Potential fix for #629. [TidusJar] - -- Fixed an issue to stop blatting over the base url. [tidusjar] - -- Fixed #643. [TidusJar] - -- Fixed #622. [TidusJar] - - -## v1.9.6 (2016-10-28) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fixed #586. [Jamie.Rees] - -- Fixed #622. [Jamie.Rees] - -- Fixed #621. [Jamie.Rees] - - -## v1.9.5 (2016-10-27) - -### **New Features** - -- Added our own custom migrations, a lot easier to migrate DB versions now. [tidusjar] - -### **Fixes** - -- Bump version. [Jamie.Rees] - -- Small bit of work on the user claims. [Jamie.Rees] - -- Fix #612 again. [Jamie.Rees] - -- User management styling. [Jamie.Rees] - -- Fixed #608 and some other small stuff. [tidusjar] - -- More user mapping. [tidusjar] - -- Fixed #615. [tidusjar] - -- Fixed #610. [tidusjar] - -- User management stuff. [Jamie.Rees] - -- User management work. [Jamie.Rees] - -- Revert the TVSender to use the old code. [Jamie.Rees] - -- Fixed the view issue. [tidusjar] - -- S582: admin improvements part 2. [Jim MacKenzie] - -- Fix #612. [Jamie.Rees] - -- User management, migration and newsletter. [Jamie.Rees] - -- #602 recently added improvements. [tidusjar] - -- Revert "Sorting out the current state of migrations" [Jamie.Rees] - -- Sorting out the current state of migrations. [Jamie.Rees] - -- Marked as obsolete. [Jim MacKenzie] - -- Migration setup. [Jim MacKenzie] - -- Removed extra line breaks. [Jim MacKenzie] - -- Moved Newsletter Settings to its own page. [Jim MacKenzie] - -- Reverted TMDB package. [Jamie.Rees] - -- Remove DB Option. [Jamie.Rees] - -- Upgrade the movie DB package and fixed #370 To fix this I had to make another API call... It slows down the search... [tidusjar] - -- Lots of small fixes including #475. [tidusjar] - -- A better fix for #587. [tidusjar] - -- Fixed #553. [tidusjar] - -- #601. [Jamie.Rees] - -- More rework to use the Plex DB. [Jamie.Rees] - -- More work around using the PlexDatabase. [Jamie.Rees] - -- Plex DB. [Jamie.Rees] - -- Allow to process even know we had an error #578. [Jamie.Rees] - -- Fix boostrapper-datetimepicker imports (#586) [David Torosyan] - -- Potential work around for #587. [tidusjar] - -- Fixed #589. [tidusjar] - - -## v1.9.4 (2016-10-10) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added Paypalme options, no UI yet (#568) [Jim MacKenize] - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -### **Fixes** - -- Reverted. [tidusjar] - -- Make sure it's enabled before sending the recently added. [tidusjar] - -- Moved the HR inside the table for TV Shows. [Jamie.Rees] - -- FIXED!!!!! YES BITCH! #550. [tidusjar] - -- Moved the horizontal rules inside the table row. [tidusjar] - - -## v1.9.3 (2016-10-09) - -### **New Features** - -- Added properties to disable tv requests for specific episodes or seasons and wired up to admin settings. [Matt McHughes] - -- Added different sonarr search commands. [tidusjar] - -### **Fixes** - -- Fixed #515. [tidusjar] - -- Fixed #561 and a small bit of work on #569. [tidusjar] - -- #569. [tidusjar] - -- Fixed case typo. [Matt McHughes] - -- Finished wiring tv request settings to tv search. [Matt McHughes] - -- WIP hide tv request options based on admin settings. [Matt McHughes] - -- Set meta charset to be utf-8. [Madeleine Schönemann] - -- F#552: updated labels text. [Jim MacKenize] - -- F#552: Re-design lables. [Jim MacKenzie] - -- Last correction.. Now the translation is ready to be used. [Michael Reber] - -- Forgot to correct two incorrect translations. [Michael Reber] - -- Correction of the German translation. [Michael Reber] - -- Notification improvements. [tidusjar] - -- #515. [tidusjar] - - -## v1.9.2 (2016-09-18) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update CouchPotatoCacher.cs. [Jamie] - -- Added some error handing around the GetMovie area #517. [tidusjar] - -- Added a version endpoint in "/api/version" #529. [tidusjar] - -### **Fixes** - -- Trying to fix the auto CP. [tidusjar] - -- Increase the notice message text box #527. [tidusjar] - -- #536 this should fix notification settings when it is being unsubscribed when testing. [tidusjar] - -- Improved how the TV search looks and feels. [tidusjar] - -- Fix for reverse proxy when using the wizard. [Devin Buhl] - -- Fixed #532. [tidusjar] - -- This should fix some issues with the episode requests #514. [tidusjar] - -- Small changes around existing series. [tidusjar] - -- Fixed #514 and the unit tests. [tidusjar] - -- If there is a bad password when changing it, we now inform the user. [tidusjar] - -- When logging out as admin remove the username from the session. [tidusjar] - -- Sorted out some of the UI for #18. [tidusjar] - -- Finished #18. [tidusjar] - - -## v1.9.1 (2016-08-30) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added french to the navbar. [tidusjar] - -- Changed the way we use the setTimeout function. Should fix #403 #491 #492. [tidusjar] - -- Change the redirection to use a relative uri redirect #473. [tidusjar] - -### **Fixes** - -- Fixed tests. [tidusjar] - -- Fixed #491 and added more logging around the email messages under the Info level. [tidusjar] - -- Finished #415. [tidusjar] - -- Fixed an issue where there were some JS errors on the landing page settings and stopped us being redirected to the login sometimes as an admin. [tidusjar] - -- Fixed #480. [tidusjar] - -- User management. [tidusjar] - -- Fixed #505. [tidusjar] - -- Append the application version to the end of our JS/CSS files. [tidusjar] - -- Fixed issue #487. [tidusjar] - -- Remove the datetime picker css from the main assets block and only load it on the pages it needs. #493. [tidusjar] - -- Redirect to search if we are already logged in #488. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed an issue where you could set the base url as requests #479. [tidusjar] - -- Working on the beta releases page and also the user management. [tidusjar] - -- User work. [tidusjar] - - -## v1.9.0 (2016-08-18) - -### **New Features** - -- Update the availability checker to search for TV Episodes. [tidusjar] - -- Changed the no TVMazeid message. [tidusjar] - -- Added an option to disable/enable the Plex episode cacher. [tidusjar] - -- Updated the episode cacher to have a minimum of 11 hours before it runs again. [tidusjar] - -- Added some useful analytical infomation around the wizard. [tidusjar] - -- Updated the German translations #402. [tidusjar] - -- Added some code to shrink the DB. reworked the search to speed it up. [tidusjar] - -- Change to use the GrandparentTitle rather than the thumbnail.... facepalm. [tidusjar] - -- Change the interval to hours! [tidusjar] - -- Added the transaction back into the DB. Do not run the episode cacher if it's been run in the last hour. [tidusjar] - -- Added logging. [tidusjar] - -- Changed the query slightly. [tidusjar] - -- Updated Newtonsoft.Json, Autofixture, Nlog and Dapper packages. [tidusjar] - -- Added the Sonarr check for episodes #254. [tidusjar] - -- Added unit tests. [tidusjar] - -- Added #436. [tidusjar] - -- Update build no. [tidusjar] - -- Updated translations for #402. [tidusjar] - -- Added a beta module. [tidusjar] - -- Added a custom debug root path provider, this means we do not have to recompile the views every time we make a view change. [tidusjar] - -- Update .gitignore. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added tests for the string hash. [tidusjar] - -- Added code to request the api key for CouchPotato. [tidusjar] - -- Added the file version to the layout. [tidusjar] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added automation tests. [tidusjar] - -- Update appveyor.yml. [Jamie] - -- Updated packages. [tidusjar] - -- Updated Polly. [tidusjar] - -- Updated Fr, IT and NL translations #402. [tidusjar] - -- Changed the way the donate button works for #414. [tidusjar] - -- Added MediatR. [tidusjar] - -### **Fixes** - -- User management stuff. [tidusjar] - -- Fixed! [tidusjar] - -- Small amount of work on the user management. [tidusjar] - -- Fixed #466. [tidusjar] - -- Fixes. [tidusjar] - -- Made the episode request better. [tidusjar] - -- Removed commented out tests. [tidusjar] - -- Fixed the bad test after the merge. [tidusjar] - -- Reworked #466. [tidusjar] - -- More unit tests around the login and also the core Plex Checker. [tidusjar] - -- Potentially fixed the issue where we were requesting everything that was also available now. [tidusjar] - -- This should fix #466. [tidusjar] - -- Attempt at fixing a potential bug found from #466. [tidusjar] - -- #464 fixed. [tidusjar] - -- Fixed the build. [tidusjar] - -- Small improvements to the wizard. [tidusjar] - -- Always set the wizard to be true when editing the Plex Requests settings (Since the flag is not in the UI, a bool defaults to false). [tidusjar] - -- Tiny bit of more info. [tidusjar] - -- Finished #459. [tidusjar] - -- #459 is almost done. [tidusjar] - -- Modified the episode modal so that we are now resetting the button after a request. [tidusjar] - -- Commented out the transaction for now to debug it. [tidusjar] - -- Since we are multithreading, we should use a threadsafe type to store the episodes to prevent any threading or race conditions. [tidusjar] - -- Wrapped the bulk insert inside a transaction. [tidusjar] - -- Made the episode check parallel. [tidusjar] - -- Log out the GUID causing the issue. [tidusjar] - -- Fixed another test. [tidusjar] - -- Fixed tests. [tidusjar] - -- Got mostly everything working for #254 Ready for testing. [tidusjar] - -- Fixed issue with saving to db. [tidusjar] - -- Need to work out why the cacher is not working and where the datatype mismatch is. [tidusjar] - -- Don't delete first. [tidusjar] - -- Fix the log path issue #451. [tidusjar] - -- Dump an item. [tidusjar] - -- Small change with the return value in the batch insert. [tidusjar] - -- #254 Removed the cache, we are now storing the plex information into the database. [tidusjar] - -- Small change in the episode saver. [tidusjar] - -- Some small tweaks to improve the memory alloc. [tidusjar] - -- Short circuit when Plex hasn't been setup. Added Miniprofiler. [tidusjar] - -- Consolidate newtonsoft.json packages. [tidusjar] - -- Some performance improvements around the new TV stuff. [tidusjar] - -- Reworked the cacher, fixed the memory leak. No more logging within tight loops. [tidusjar] - -- Another null check. [tidusjar] - -- Some more changes. [tidusjar] - -- Some error handling. [tidusjar] - -- Check if the sonarr ep is monitored. [tidusjar] - -- Some logging. [tidusjar] - -- Small changes, we will actually see the episode cacher on the scheduled jobs page now. [tidusjar] - -- Work on the UI to show what episodes have been requested #254. [tidusjar] - -- Small fix. [tidusjar] - -- Fix the api change in #450. [tidusjar] - -- #254. [tidusjar] - -- Workaround for #440. [tidusjar] - -- Async async async improvements. [tidusjar] - -- Finished #266 Added a new cacher job to cache all episodes in Plex. [tidusjar] - -- Fixed #442. [tidusjar] - -- #254. [tidusjar] - -- Work around the sonarr bug #254. [tidusjar] - -- #254 having an issue with Sonarr. [tidusjar] - -- Small bit of work on #266. [tidusjar] - -- #254. [tidusjar] - -- Precheck and disable the episode boxes if we already have requested it. TODO check sonarr to see if it's already there. #254. [tidusjar] - -- Fixed broken build. [tidusjar] - -- More work for #254. [tidusjar] - -- More work on #254. [tidusjar] - -- Fixed the bug in #438 and added unit tests to make so we dont break it in the future. [tidusjar] - -- Some reason we had dupe translations. [tidusjar] - -- Rename SubDir to Base Url. [tidusjar] - -- Fix the exception in #440. [tidusjar] - -- Reworking the login page for #426. [tidusjar] - -- Fixed #438. [tidusjar] - -- Finished the auth stuff. [tidusjar] - -- Finished up the SMTP side of #429. [tidusjar] - -- #428 Added a message when the we cannot get a TVMaze ID. [tidusjar] - -- #254 MOSTLY DONE! At last, this took a while. [tidusjar] - -- Removed the other rootpath provider. [TidusJar] - -- Removed the other rootpath provider. [TidusJar] - -- Removed the other rootpath provider. [TidusJar] - -- Should fix #429. [TidusJar] - -- Done #135 We are including the application version number in the directory. [tidusjar] - -- #387 trim the spaces from the api key. Tidied up the setting models a bit. [tidusjar] - -- Wrapped the repo to catch Sqlite corrupt messages. [tidusjar] - -- Frontend and tv episodes api work for #254. [tidusjar] - -- #424. [tidusjar] - -- #359. [tidusjar] - -- Moved the plex auth token to the plex settings where it should belong. [tidusjar] - -- Small changes around the user management. [tidusjar] - -- Missed brace. [tidusjar] - -- Removed. [tidusjar] - -- Fixed issues from the merge. [tidusjar] - -- Stupid &$(*£ merge. [tidusjar] - -- Angular. [tidusjar] - -- Reworked the custom notifications... again. Need to figure out how to find the view to the model. [tidusjar] - -- Fixed #417. [tidusjar] - -- Removed NinjectConventions, we hadn't started to use it anyway. [tidusjar] - -- Fixed the way we will be using custom messages. [tidusjar] - -- Test checkin. [tidusjar] - -- Better handling for #388. [tidusjar] - -- Fixed #412. [tidusjar] - -- Fixed #413. [tidusjar] - -- Fixed #409. [tidusjar] - -- Trycatch around the availbility checker. [tidusjar] - -- WIP on notification resolver. [tidusjar] - -- Tidy. [tidusjar] - -- Plugged in MediatR. [tidusjar] - -- Moved over to using Ninject. [tidusjar] - - -## v1.8.4 (2016-06-30) - -### **Fixes** - -- Fixed the bug where we were auto approving everything. Added French language into the navigation bar. [tidusjar] - - -## v1.8.3 (2016-06-29) - -### **New Features** - -- Update README.md. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added some of the backend bits for #182. [tidusjar] - -- Updates for #243. [tidusjar] - -- Added Dutch language #243. [tidusjar] - -- Added languages #243. [tidusjar] - -- Added logging #350. [tidusjar] - -### **Fixes** - -- Small changes. [tidusjar] - -- Allow html in the notice message. [tidusjar] - -- Some more unit tests around the NotificationMessageResolver. [tidusjar] - -- Fixed a timing bug found the in build. Note, when working with time differences use TotalDays. [tidusjar] - -- More translations on the search page (Mainly the notification messages) #243. [tidusjar] - -- Fixed some warnings. [tidusjar] - -- CodeCleanup. [tidusjar] - -- Fixed a bit of a stupid bug in the resetter and added unit tests around it to make sure this never happens again. [tidusjar] - -- Fixed an issue where we didn't provide the correct response when clearing the logs. [tidusjar] - -- Made it so users that are in the whitelist do not have a request limit. [tidusjar] - -- Made it so the request limit doesn't apply to admin users. [tidusjar] - -- Fixed where a user could see the delete button on the issues page. [tidusjar] - -- Fixed some small issues and improved the navbar. [tidusjar] - -- Translated the Requested page #243. [tidusjar] - -- Finished #337. [tidusjar] - -- Some analytics. [tidusjar] - -- More translations for #243 and welcome text for #293. [tidusjar] - -- Small bit of work for #359. [tidusjar] - -- Finished #6. [tidusjar] - -- Analytics and fixes. [tidusjar] - -- Translated the search page #243. [tidusjar] - -- Implemented the different languages and added the ability to change cultures. #243. [tidusjar] - -- Started #243. [tidusjar] - -- Fixed #364. [tidusjar] - -- Some more useful analytical information. [tidusjar] - -- Generic try catch to fix #350. [tidusjar] - -- Slight changes, moved the donate button. [tidusjar] - -- Potential fix for #350. [tidusjar] - -- Better way of obtaining clean enum string. [Drewster727] - -- Fixed #362. [tidusjar] - - -## v1.8.2 (2016-06-22) - -### **New Features** - -- Update readme. [tidusjar] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fixed a circular reference issue. [tidusjar] - -- Small changes around how we work with custom events in the analytics. [tidusjar] - -- Fixed #353 #354 #355. [tidusjar] - -- Null provider check for movies. [Drewster727] - -- Show request type in notifications #346 and fix an issue from previous commit for #345. [Drewster727] - -- Add an option to stop sending notifications for requests that don't require approval #345. [Drewster727] - - -## v1.8.1 (2016-06-21) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fix obj ref error when scheduler runs (ProviderId is null?) [Drewster727] - -- Fix logic for obtaining a sonarr quality profile #340. [Drewster727] - - -## v1.8.0 (2016-06-21) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the new advanced search into the search page too. [tidusjar] - -- Change the way we configure the IoC container in the bootstrapper, we are registering all the concrete instances on application start rather than on each web request. This should increase the performance per HTTP request. [tidusjar] - -- Updated nlog and fixed #295. [tidusjar] - -### **Fixes** - -- Workaround for #334. [Drewster727] - -- Create .gitattributes. [Jamie] - -- Fixes to the issues. [tidusjar] - -- Set the defaults for the landing page. [tidusjar] - -- Revert branch to 664dae2. [tidusjar] - -- Some unit tests for the issues. [tidusjar] - -- Tidied up the bootstrapper. [tidusjar] - -- Fix up landing page UI. [Drewster727] - -- Fixed CSS issue with the top arrow in the Plex theme. [tidusjar] - -- Small changes. [tidusjar] - -- Done #318. [tidusjar] - -- Fixed tests. [tidusjar] - -- #298 added some tests for the landing page. [tidusjar] - -- We are now only keeping the latest 1000 log records in the database. Delete everything else. [tidusjar] - -- Some analytic stuff. [tidusjar] - -- Capture the TVDBID when requesting. [tidusjar] - -- Attempting to improve #219. [tidusjar] - -- Just some more async changes. [tidusjar] - -- Small changes. [tidusjar] - -- More work on #298. Everything wired up. [tidusjar] - -- Fixed the issue on the landing page #298. [tidusjar] - -- #298 moved the content to the left a bit. [tidusjar] - -- Styling for #298 done, just need to wire up the model and do the actual status check. [tidusjar] - -- Bumped up the version number. [tidusjar] - -- Removed some DumpJson() from the trace logs. [tidusjar] - -- Small ui fix (100% width user/password fields to improve mobile experience) [Drewster727] - -- Landing page stuff #298. [tidusjar] - -- Datepicker UI fixes + small landing page UI fix. [Drewster727] - -- Removed a change that shoudn't have been commited. [tidusjar] - -- Fixed tests. [tidusjar] - -- More work for #298. [tidusjar] - -- #273 added for only available content on the search. [tidusjar] - -- Fixed #303 Looks like there was some incorrect business logic. [tidusjar] - -- Most of #273 done. [tidusjar] - -- Settings done for #298. [tidusjar] - -- Started #298. [tidusjar] - -- A crap tonne of work on #273. [tidusjar] - -- More work on #273. [tidusjar] - -- Reduced kept logs for 2 days. [tidusjar] - -- Fixed #300. [tidusjar] - -- #273. [tidusjar] - -- Fixed a bug with some users with the CP profiles. [tidusjar] - -- #273. [tidusjar] - -- Done the same for TV. [tidusjar] - -- Fixes #296. [tidusjar] - -- More for #273. [tidusjar] - -- Small changes. [tidusjar] - -- Revert "Small changes" [tidusjar] - -- Small changes. [tidusjar] - -- Finished #221 and added more async #278. [tidusjar] - -- Spelling mistake in the html! this fixes #264. [tidusjar] - -- More work on #273. [tidusjar] - -- Fixed #210. [tidusjar] - -- Started #273. [tidusjar] - - -## v1.7.5 (2016-05-29) - -### **New Features** - -- Update preview. [Jamie] - -- Updated dapper.contrib. Looks like there was a bug in the async methods. [tidusjar] - -- Updater wouldn't work when running a reverse proxy #236. [tidusjar] - -### **Fixes** - -- Bump build ver. [tidusjar] - -- Use HTTPS for the poster images, so there aren't any mixed content warnings when serving the application via an HTTPS reverse proxy. [Sean Callinan] - -- Removed static declarations. [tidusjar] - -- Fixed styling on modal. [tidusjar] - -- Made the search page all async goodness #278. [tidusjar] - -- Made the request module async #278. [tidusjar] - -- Started some dynamic scrolling. [tidusjar] - -- Stop dumping out the settings to the log. [tidusjar] - -- Made more async goodness. [tidusjar] - -- Made some of the searching async #278. [tidusjar] - -- Fixed #277. [tidusjar] - -- Reworked some tests. [tidusjar] - -- #26q make the auth users list taller. [Drewster727] - -- Fix 404 error. [Drewster727] - -- #262 make the auth users list taller. [Drewster727] - -- #221 delete requests per category. [Drewster727] - -- #256 #237 UI Improvements and consolidation. [Drewster727] - -- Fixed a bug in the user notification where if an admin wants to be notified they wouldn't be. [tidusjar] - -- Set the admin to have all claims. [tidusjar] - -- Fix null exception possibility in cp/sickrage cacher classes. [Drewster727] - -- Fixed #244. [tidusjar] - -- Fixed #240. [tidusjar] - -- Fixed #270. [tidusjar] - -- Fixed an issue where if you have only 1 plex friend it would not show in the list. [tidusjar] - - -## v1.7.4 (2016-05-25) - -### **New Features** - -- Update README.md. [Jamie] - -### **Fixes** - -- Fixed #252. [tidusjar] - -- Fixed #428. [tidusjar] - -- Version bump. [tidusjar] - -- Fixed tests. [tidusjar] - -- Fully fixed #239. [tidusjar] - -- We wan't updating the DB schema. [tidusjar] - - -## v1.7.3 (2016-05-25) - -### **Fixes** - -- Fixed the release build issue where we could not access the settings #239. [tidusjar] - - -## v1.7.2 (2016-05-25) - -### **Fixes** - -- Fixed a small bug where an exception would get thrown. [tidusjar] - -- Build version bump. [tidusjar] - -- Cleanup. [tidusjar] - -- Typo. [tidusjar] - -- Fixed #241. [tidusjar] - -- Fixed #239. [tidusjar] - -- Fixed #238. [tidusjar] - -- Small UI tweaks/improvements. [Drewster727] - - -## v1.7.1 (2016-05-24) - -### **New Features** - -- Update version. [tidusjar] - -### **Fixes** - -- Fixed an issue with the auth page when running with a reverse proxy. [tidusjar] - - -## v1.7 (2016-05-24) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the ability to get the apikey from the api if you provide a correct username and password. Added more unit tests Added the ability to change a users password using the api refactored the Usermapper and made it unit testsable. [tidusjar] - -- Update. [tidusjar] - -- Added in an audit table. Since we are now allowing multiple users to change and modify things we need to audit this. [TidusJar] - -- Added the updater to the soloution and did a bit of starting code. [TidusJar] - -- Updated the claims so we can support more users. Added a user management section (not yet complete) Added the api to the solution and a api key in the settings (currently only gets the requests). [TidusJar] - -- Updated packages. [TidusJar] - -- Added a retry handler into the solution. We can now retry failed api requests. [TidusJar] - -- Update README.md. [Jamie] - -- Added Released propety to RequestViewModel. Added Released filter to the Requests page. [Chris Lees] - -- Added #27 to albums. [tidusjar] - -- Added the actual notification part of #27. [tidusjar] - -- Added the missing baseurl bit on the login page for #72. [tidusjar] - -- Added the 'enable user notifications' to the email settings view and model. [tidusjar] - -- Update README.md. [Jamie] - -### **Fixes** - -- Remove pointless test, change the default theme and fix a small bug. [tidusjar] - -- Fixed api. [tidusjar] - -- Finished #26. [tidusjar] - -- Plex theme. [tidusjar] - -- Implimented a theme changer, waiting for the Plex theme. [tidusjar] - -- Finished #222 #205. [tidusjar] - -- Started working on #26. [tidusjar] - -- Undid some small changes that was checked in by accident. [tidusjar] - -- #164 has been resolved. [tidusjar] - -- Resolved #224 , Removed the 'SSL' option from the email notification settings. We will now use the correct secure socket options (SSL/TLS) for your email host. [tidusjar] - -- Small changes. [tidusjar] - -- #27 fully finished. [tidusjar] - -- Fixed #215. [tidusjar] - -- Using Mailkit to fix #204. [tidusjar] - -- Color. [tidusjar] - -- Fully finished #27 just need to test it! [tidusjar] - -- Fixed test. [tidusjar] - -- Styling for #27. [tidusjar] - -- I think the auto updater is finished! #29. [tidusjar] - -- I think we have finished the main bulk of the auto updater #29. [tidusjar] - -- #222 #205 more ! Started getting the settings out. [tidusjar] - -- Removed the service locator from the base classes and added in some Api tests added all the tests back in! [tidusjar] - -- More work on the api and documentation #222 #205. [tidusjar] - -- Started documenting the API we now have swagger under ~/apidocs #222 #205. [tidusjar] - -- Api work for #205 Refactored how we check if the user has a valid api key Added POST request, PUT and DELTE. [tidusjar] - -- First pass of the updater working. #29. [tidusjar] - -- Removed SIGHUP from the termination list #220. [tidusjar] - -- Fixed. [tidusjar] - -- Missing. [tidusjar] - -- Missed out a file. [TidusJar] - -- And some more... [TidusJar] - -- Missed some files. [TidusJar] - -- A bit more work on switching to using user claims so we can support multiple users. [TidusJar] - -- Made the store backup clean up some of the older backups (> 7 days). [TidusJar] - -- More work on the user management. [TidusJar] - -- - Notifications will no longer be send to the admins if they request something. - Looks like we missed out adding the notifications to Music requests, so I added that in. [TidusJar] - -- - Improved the RetryHandler. - Made the tester buttons on the settings pages a bit more robust and added an indication when it's testing (spinner) [TidusJar] - -- Packages. [TidusJar] - -- Nm, [TidusJar] - -- Downgraded packages. [TidusJar] - -- Better handling for #202. [TidusJar] - -- Finished #208 and #202. [TidusJar] - -- This should help #202. [TidusJar] - -- Resolved #209. [TidusJar] - -- Finished #209. [TidusJar] - -- Slight adjustments to #189. [tidusjar] - -- - Added a visual indication on the UI to tell the admin there is a update available. - We are now also recording the last scheduled run in the database. [tidusjar] - -- Did the login bit on #185. [tidusjar] - -- Finished #186. [tidusjar] - -- Fixed #185. [tidusjar] - -- Fixed issue in #27 with albums. [tidusjar] - -- #27 added TV Search to the notification. [tidusjar] - -- Fixed bug. [tidusjar] - -- More work on #27 Added a new notify button to the search UI (Needs styling). Also fixed a bug where if the user could only see their own requests, if they search for something that has been requested, it will show as requested. [tidusjar] - -- Improved the startup of the application. We now properaly parse any args passed into the console. [tidusjar] - -- Additional cacher error handling + don't bother checking the requests when we don't get data back from plex. [Drewster727] - -- Remove old migration code and added new migration code. [tidusjar] - -- Stop the Cachers from bombing out when the response from the 3rd party api returns an exception or invalid response. #171. [tidusjar] - -- Increase the scheduler cache timeframe to avoid losing cache when the remote api endpoints go offline (due to a reboot or some other reason) -- if they're online, the cache will get refreshed every 10 minutes like normal. [Drewster727] - -- Fix the cacher by adding locking + extra logging in the plex checker + use a const key for scheduler caching time. [Drewster727] - -- Small changes. [tidusjar] - -- Switched out the schedulers, this seems to be a better implimentation to the previous and is easier to add new "jobs" in. [tidusjar] - -- Fixed #168. [tidusjar] - -- Fixed #162. [tidusjar] - -- Fix saving the log level. [Drewster727] - -- Set the max json length (fixes large json response errors) [Drewster727] - - -## v1.6.1 (2016-04-16) - -### **New Features** - -- Update README.md. [Jamie] - -- Added a url base. [tidusjar] - -- Change default logging. [tidusjar] - -- Added logging around SickRage. [tidusjar] - -### **Fixes** - -- Bump up the version number ready for the release. [tidusjar] - -- BaseUrl is finally finished! #72. [tidusjar] - -- #72 Login page done. [tidusjar] - -- More changes for the urlbase #72. [tidusjar] - -- Done the auth, cp, logs and sidebar for #72. [tidusjar] - -- Add an extra check when determining if a tv show is already available (also check if it starts with the show name returned from the tv db) [Drewster727] - -- Cache plex library data regardless of whether we have requests in the database or not. [Drewster727] - -- By default don't use a url base. [tidusjar] - -- Return empty array when obtaining queued IDs in sickrage cacher. [Drewster727] - -- Fixed a small bug in the SR cacher. [tidusjar] - -- Fixed when we do not have a base. [tidusjar] - -- More changes for #72. [tidusjar] - -- Fixed exception and all areas will now use the base url #72. [tidusjar] - -- Removed the test code from #72. [tidusjar] - -- Commented out the unit tests as they need to be reworked now. [tidusjar] - -- Finally fixed #72. [tidusjar] - -- Remove test code from plex api GetLibrary method. [Drewster727] - -- Finished up the caching TODO's. [tidusjar] - -- Kick off the schedulers once the web app has started (fixes api errors on start) [Drewster727] - -- Converted the UI back down to .NET 4.5.2. [tidusjar] - -- Fixed #154. [tidusjar] - -- Revert everything (except PlexRequests.UI) back to .NET 4.5.2 -- fixes incompatibilities with the latest version of mono (4.2.3.4) -- fixes notifications not working #152 #147 #141. [Drewster727] - -- #150 start caching plex media as well. refactored the availability checker. NEEDS TESTING. also, we need to make the Requests hit the plex api directly rather than hitting the cache as it does now. [Drewster727] - -- #150 split out the cache subscriptions to make sure they subscribe properly. [Drewster727] - -- #150 sonarr/sickrage cache checking. sickrage has a couple small items left. [Drewster727] - -- Fixed args. [tidusjar] - -- Fixed. [tidusjar] - -- Made the base better. [tidusjar] - -- Remove couchpotato api test code. [Drewster727] - -- Start the initial couchpotato cache call on a separate thread to keep the startup process quick. [Drewster727] - -- Add csproj with file changes from previous commit. [Drewster727] - -- Cache the couchpotato wanted list, update it on an interval, and use it to determine if a movie has been queued already. [Drewster727] - -- I think i've fixed an issue where SickRage reports Show not found. [tidusjar] - -- Set the default log level to info. #141. [tidusjar] - -- #125 refactor async task logic to work with mono. [Drewster727] - -- Fix search spinner sticking around after clearing search text + make the "Requested" and "Available" indicators in the search page different colors. [Drewster727] - -- #125 start indicating in the results if an item is already requested or available. [Drewster727] - -- #145 firefox css dsplay issue. [Drewster727] - -- Fixes for sonarr, we now display the error messages back to the user. [tidusjar] - -- Fixed #144. [tidusjar] - - -## v1.6.0 (2016-04-06) - -### **New Features** - -- Changed the build number. [tidusjar] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Changed the title to a contains but the artist still must match, [tidusjar] - -- Added unit tests to cover the new changes to the availability checker. [tidusjar] - -- Added the music check in the Plex Checker. [tidusjar] - -- Changed around the startup so we cache the profiles after the DB has been created. [tidusjar] - -- Updated where we update the request blobs schema change. [tidusjar] - -- Update SearchModule.cs. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Change the new columns type. [tidusjar] - -- Added a DBSchema so we have an easier way to update the DB. [tidusjar] - -- Added an issue template. [tidusjar] - -- Update README.md. [Jamie] - -- Added back the username into the Session when the admin logs in. This means they do not have to log in twice. [tidusjar] - -- Added happy path tests for the Checker. [tidusjar] - -- Added music to the search and requests page. [tidusjar] - -- Added a scroll to the top thingy and a bit more work on headphones. [tidusjar] - -- Added some tests and fixed the issue where the DB would get created in the wrong place depending on how you launched the application. [tidusjar] - -- Added the settings page for #32. [tidusjar] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Some final tweaks for #32. [tidusjar] - -- Fixed a bug where if we are the admin we didn't add the request to the db. [tidusjar] - -- Fixed an issue where we would add the Sickrage series but it would fail on adding the seasons. [tidusjar] - -- Properly account for future/past dates when humanizing with moment. [Drewster727] - -- Properly display release date on requests page. [Drewster727] - -- Add missing reference for release mode. [Drewster727] - -- #139 remove dependency and usage of humanize() - should help with cross-platform issues. start using moment.js. [Drewster727] - -- Fix selectors for music list on request page to get sorting working. [Drewster727] - -- Fixed the error #32. [tidusjar] - -- Fixed the logs page. [tidusjar] - -- Another attempt at filtering #32. [tidusjar] - -- A bit more error handling #32. [tidusjar] - -- Improved the availabilty check to include music results #32. [tidusjar] - -- Small changes for #32. [tidusjar] - -- A bit more logging for #32. [tidusjar] - -- More headphones #32 I am starting to hate headphones... Sometimes the artists and albums just randomly fail. [tidusjar] - -- #134 temporary workaround for this. [Drewster727] - -- Task.run for startup caching + fix admin module unit test failures. [Drewster727] - -- Cache injection, error handling and logging on startup, etc. [Drewster727] - -- Tweaks for #32. [tidusjar] - -- #132 auto-approve for admins. [Drewster727] - -- Finished the bulk work for Headphones. Needs testing #32. [tidusjar] - -- Made the album search 10x faster. We are now loading the images in a seperate call. #32. [tidusjar] - -- Add a reference to API Interfaces to fix the build. [tidusjar] - -- #114 start caching quality profiles. Set the cache on startup and when obtaining quality profiles in settings. [Drewster727] - -- Work for #32. [tidusjar] - -- #114 first pass at choosing quality profile when approving + focus search input by default and when switching tabs. [Drewster727] - -- #131 fix for default selected tab. [Drewster727] - -- Remove references to obsolete RequestedBy property + start setting the db schema to the app version, and check that in the future for migrations. [Drewster727] - -- Fixed async issue. [Shannon Barrett] - -- Updating SickRage api to verify Season List is up to date. [Shannon Barrett] - -- Work on showing the requests for #32. [tidusjar] - -- Got the search finished up for #32. [tidusjar] - -- Remove test/temp code in UserLoginModule. [Drewster727] - -- A bit more work on #32 started working on requesting it. The DB is a bit of an issue... [tidusjar] - -- Most of the UI work done for #32. [tidusjar] - -- Basic search working for #32. [tidusjar] - -- Mono datetime offset workaround. [Drewster727] - -- #122 store utc time in the databse + obtain timezone offset of the client upon login + offset times returned to client based on session offset. [Drewster727] - -- Method reference bug fix. [Drewster727] - -- Fix search focus z-index issue (hid suggestions options) [Drewster727] - -- Minor search UI adjustments. [Drewster727] - -- #55 first attempt at "suggestions" starting with "Comming Soon" and "In Theaters" [Drewster727] - -- #106 rename sorting options and polish the dropdown UI a bit. [Drewster727] - -- Started adding the api part for headphones #32. [tidusjar] - -- Upped the time of #123. [tidusjar] - -- First attempt at #123. [tidusjar] - -- We now do not show the text Requested By to the user, we also show a 'success' message instead of a warning when something has already been requested. [tidusjar] - -- Show a "no requests yet" message on the requests page (for each cateogory) [Drewster727] - -- Ignore items that are already available when approving in bulk, and simplify the checking + compile css. [Drewster727] - -- Add a better way to merge RequestedBy and RequestedUsers to avoid code duplication and simplify checks. [Drewster727] - -- Don't query the session as much in the modules, rely on a variable from the base class and store the username as needed. [Drewster727] - -- Show the requested by user from legacy request models. [Drewster727] - -- Only show requested by users to admins + start maintaining a list of users with each request. [Drewster727] - -- #96 fix up notification test feature. [Drewster727] - -- Fix the request page sort/approve button alignment. [Drewster727] - -- When pulling requests, set each to approved that is already available (so the UI avoids showing the approve option for already available content) [Drewster727] - -- Mono doesn't seem to have Tls1.2. Let's try TLS 1 #119. [tidusjar] - -- Specify a protocol type of TLS12. Looks like CP doesn't seem to like SSL3 (it is quite old now so understandable) #119. [tidusjar] - -- Made #85 better. [tidusjar] - -- Fixed the tests. [tidusjar] - -- Made the feedback from Sonarr better when Sonarr already has the series #85. [tidusjar] - -- An attempt to fix #108. [tidusjar] - -- Add some "no results" feedback to the searching + minor UI improvements. [Drewster727] - -- Fix notification tests. [Drewster727] - -- UI - increase icon size of nav menu (they were too small before) [Drewster727] - -- #96 Finished adding test functionality to notifications. [Drewster727] - -- #96 add the necessary back-end code to produce a test message for all notification types (still have to add the test buttons for pushbullet/pushover) [Drewster727] - -- #96 modify notifications interface/service to accept a non-type specific settings object. [Drewster727] - -- #96 Email notification test button (others to come) [Drewster727] - -- Minor UI adjustments. [Drewster727] - -- #84 provide an option in settings to resttrict users from viewing requests other than their own. [Drewster727] - -- #54 comma separated list of users who don't require approval + fix a couple request messages (include show title) [Drewster727] - -- Clean up the sorting option names. add a way to see which filter/sort is currently applied. [Drewster727] - -- Fix up the animations. seems to be related to the data-bound attribute causing the animtions not to fire on each .mix object. [Drewster727] - -- Move approve buttons to the tab content. [Drewster727] - -- Allow approving all requests by category. [Drewster727] - -- Fix up sorting on the request page. [Drewster727] - -- Add ubuntu/debian instructions. [Drewster727] - -- #86 - display movie/show title + year in request notifications. [Drewster727] - -- Show the movie/show title when requesting. [Drewster727] - - -## v1.5.2 (2016-03-26) - -### **Fixes** - -- Stoped users from spamming the request button. [tidusjar] - -- Fixed the logger no longer writing to the file. [tidusjar] - -- Fixed #97. [tidusjar] - - -## v1.5.1 (2016-03-26) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added logs to the sidebar. I'm an idiot. [tidusjar] - -### **Fixes** - -- Approve tv shows or movies. [Drewster727] - -- Fixed a bug where if you had auto approve it wouldn't notify you. [tidusjar] - - -## v1.5.0 (2016-03-25) - -### **New Features** - -- Updated version number for release. [tidusjar] - -- Updated the logic for handling specific seasons in Sonarr and Sickrage. [Shannon Barrett] - -- Updated the readme and added some icons to the navbar. [tidusjar] - -- Added the ability to sepcify a username in the email notification settings for external MTA's. We have had to add a new option called Email Sender because of this. #78. [tidusjar] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added a notification model to the notifiers. Added the backend work for sending a notification for an issue report #75. [tidusjar] - -- Added a subdir to CP, SickRage, Sonarr and Plex #43. [tidusjar] - -### **Fixes** - -- And again. [tidusjar] - -- Made the check actually work. [tidusjar] - -- Finished up #68 and #62. [tidusjar] - -- Finished styling on the logger for now. #59. [tidusjar] - -- Fixed #69. [tidusjar] - -- Working on getting the Sonarr component to work correctly. [Shannon Barrett] - -- Fixes issue #62. [Shannon Barrett] - -- Refactored the Notification service to how it should have really been done in the first place. [tidusjar] - -- Fixed the build. [tidusjar] - -- Finished #49. [tidusjar] - -- Finished #57. [tidusjar] - -- Small changes around the filtering. [tidusjar] - -- Finished adding pushover support. #44. [tidusjar] - -- Resolved #75. [tidusjar] - -- Include DB changes. [tidusjar] - -- Done most on #59. [tidusjar] - -- Lowercase logs folder, because you know, linux. #59. [tidusjar] - -- Adding the imdb when requesting. [tidusjar] - -- Fixed an issue where the table didn't match the model. [tidusjar] - -- Improved the status page with the suggestion from #29. [tidusjar] - -- Hooked up most of #49 Just the validation messages need to be done. [tidusjar] - -- Fixed #74 and #64. [tidusjar] - -- Resolved #70. [tidusjar] - -- Finished #71. [tidusjar] - -- Got the filter working on both movie and tv #57. [tidusjar] - -- Started #57, currently there is a bug where the TV list won't filter. [tidusjar] - - -## v1.4.1 (2016-03-20) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update AvailabilityUpdateService.cs. [Jamie] - - -## v1.4.0 (2016-03-19) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Updated the build version ready for the next release. [tidusjar] - -- Added the api and settings page for Sickrage. Just need to do the tester and hook it up #40. [tidusjar] - -- Added the option to set a CP quality #38. [tidusjar] - -- Added the code to lookup the old requests and refresh them with new information from TVMaze. [tidusjar] - -- Update StatusCheckerTests.cs. [Jamie] - -- Update README.md. [Jamie] - -- Added TVMaze to the search. #21. [tidusjar] - -- Added migration code and cleaned up the DB. [tidusjar] - -- Updated the way we add requests. [tidusjar] - -- Updated the Dapper.Contrib package, it had a bug where it wasn't returning the correct Id from inserts. [tidusjar] - -### **Fixes** - -- This fixes #36. [tidusjar] - -- Should fix issue #36. [Shannon Barrett] - -- When we do a batch update we need to reset the cache. [tidusjar] - -- Fixed an issue where the default quality on Sickrage wouldn't work. [tidusjar] - -- Wow, that was a lot of work. - So, I have now finished #40. - Fixed a bug where we was not choosing the correct tv series (Because of TVMaze) - Fixed a bug when checking for plex titles - Fixed a bug where the wrong issue would clean on the UI (DB was correct) - Refactored how we send tv shows - And too many small changes to count. [tidusjar] - -- Fixed the new dependancy with the admin class tests. [tidusjar] - -- Back to what it was :( [tidusjar] - -- Another test for #37. [tidusjar] - -- This should fix #37. [Jamie Rees] - -- Catch the missing table exception when they have a new DB. [Jamie Rees] - -- Exploratory test for #37. [Jamie Rees] - -- Fixed #33 we now have SSL options for Sonarr and CP. [Jamie Rees] - -- Removed all the html from the new TVMaze api (for overview). Added tests to cover the html removal. updated Readme to remove TheTVDB. [Jamie Rees] - -- Fixed tests. [Jamie Rees] - -- Almost fully integrated TVMaze #21 and also improved the fix for #31. [Jamie Rees] - -- Should fix #28. [Shannon Barrett] - -- Fixed #16 and #30. [tidusjar] - -- Modified the adding of request to update the model with the added ID. [tidusjar] - -- Switched over to the new service. [tidusjar] - -- Fixed #25. [Jamie Rees] - - -## v1.3.0 (2016-03-17) - -### **New Features** - -- Added pushbullet to the sidebar. [Jamie Rees] - -- Updated build version for the next release. [Jamie Rees] - -- Updated readme link. [tidusjar] - -- Added ignore to static tests. [tidusjar] - -- Added Pushbullet notifications #8. [tidusjar] - -- Added first implimentation of the Notification Service #8 Added tests to cover the notification service. [tidusjar] - -- Added validation to the Email settings, also increased the availability checker from 2 minutes to 5. [tidusjar] - -### **Fixes** - -- Fixed #22. [Jamie Rees] - -- Started on #16, nothing is hooked up yet. [tidusjar] - -- Fixed tests. [tidusjar] - - -## v1.2.1 (2016-03-16) - -### **New Features** - -- Update Program.cs. [Jamie] - -- Update Program.cs. [Jamie] - -- Added back the reference. [tidusjar] - -### **Fixes** - -- Removed the email notification settings from the settings (for release 1.2.1) [Jamie Rees] - -- Fixed. [Jamie Rees] - -- Resolved #10. [tidusjar] - - -## v1.2.0 (2016-03-15) - -### **New Features** - -- Updated. [Jamie Rees] - -- Updated appveyor. [Jamie Rees] - -- Update appveyor.yml. [Jamie] - -- Added latest version code and view. Need to finish the view #11. [tidusjar] - -- Added test button to Plex. That's fixed #9. [tidusjar] - -- Added test sonarr button #9. [tidusjar] - -- Added more tests. [tidusjar] - -- Added a bunch of logging. [tidusjar] - -- Added the application tester for CP #9. [tidusjar] - -- Added settings page for #8. [tidusjar] - -- Added pace.js. [tidusjar] - -### **Fixes** - -- Finished the notes! Resolved #7. [Jamie Rees] - -- #12. [Jamie Rees] - -- #12. [Jamie Rees] - -- Finished the status page #11 and some more work to #12. [Jamie Rees] - -- Resolved #7. [tidusjar] - -- Small changes. [tidusjar] - -- Yeah... [tidusjar] - -- Fixed #5 and also added some tests to the availability checker. [tidusjar] - -- Started added tests. [Jamie Rees] - -- Fixed an issue where the issues text appears larger. [Jamie Rees] - - -## v1.1 (2016-03-13) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Updated readme. [Jamie Rees] - -- Added the support for TV Series integrating with Sonarr. [Jamie Rees] - -- Added the functionality to pass a port through an argument. [tidusjar] - -- Added the code to get the quality profiles from Sonarr Started plugging that into the UI. [Jamie Rees] - -- Added the spinners #3. [tidusjar] - -- Added the functionality for the admin to clear the issues. [tidusjar] - -- Added the issues to the requests page. [tidusjar] - -- Added user logout method and unit tests to cover it. [tidusjar] - -- Added DeniedUsers to the view. [tidusjar] - -- Added the denied user check to the UserLoginModule. added a test case to cover it. [tidusjar] - -- Added a missing reference. [tidusjar] - -- Added first real test. [tidusjar] - -- Update README.md. [Jamie] - -- Added the latest version of nuget. [tidusjar] - -- Added travisyml. [tidusjar] - -- Added logging. [tidusjar] - -- Added missing files. [tidusjar] - -- Update README.md. [Jamie] - -- Added logging (Still WIP) [tidusjar] - -- Added favicon and also structured the HTML correctly. [tidusjar] - -- Updated the packages so everything is now with the correct framework (4.5.2) [tidusjar] - -- Added in deletion of requests. [tidusjar] - -- Added test code. [tidusjar] - -- Added dashboard. [tidusjar] - -- Added couchpotato page. [Jamie Rees] - -- Added readme to the project and updated it. [Jamie Rees] - -- Added helpers. [tidusjar] - -### **Fixes** - -- Bug fix, Couchpotato settings wouldn't show in release due to a Nancy bug. [Jamie Rees] - -- Small changes. [Jamie Rees] - -- First release, build 1.0.0. [Jamie Rees] - -- Removed the request limit since it's not currently being used. [Jamie Rees] - -- REmoved Sickbeared for the first release. [Jamie Rees] - -- Fixed #4 We now can manually set the status of a request. [tidusjar] - -- Made the pass in the port a bit more robust. [tidusjar] - -- Styling, Added the functionality for the Sonarr Profiles on the Admin page #2 resolved. [tidusjar] - -- Fixed a bug in the Login and added a unit test to cover that. Added a button to approve an individual request. Fixed some minor bugs in the request screen. [Jamie Rees] - -- Fixed the 'responsive' issue for the search and requests pages #3. [tidusjar] - -- Styling! #3. [tidusjar] - -- Navbar category now will follow you to various screens #3. [tidusjar] - -- Fixed bugs with the 'other' reporting issue and also the clear issues. [tidusjar] - -- We now are appending the users name to who wrote the comment. Rather than it being unknown. [tidusjar] - -- More work on submitting issues. [tidusjar] - -- More test changes. [tidusjar] - -- More tests to cover the login. [tidusjar] - -- Refactoring. [tidusjar] - -- Implimented the password part and authentication with Plex. [tidusjar] - -- Initial Use authentication is working. Need to do the password bit. [tidusjar] - -- Some error handling and ensure we are an admin to delete requests. [tidusjar] - -- Fixed the issue where the Release build would not show the admin screens! [tidusjar] - -- Fixes. [tidusjar] - -- Removed the DI part of the service. TinyIOC doesn't want to work with FluentScheduler. [tidusjar] - -- First pass at the plex update service. [tidusjar] - -- Small changes. [Jamie Rees] - -- Started to impliment the Plex checker. This will check plex every x minutes to see if there is any new content and then update the avalibility of the requests. [Jamie Rees] - -- Mre work. [Jamie Rees] - -- Few small changes, added plex settings. [Jamie Rees] - -- Making the configuration actually do something. Setting a default configuration if there is no DB. [Jamie Rees] - -- Remove post build. [Jamie Rees] - -- Small changes. [Jamie Rees] - -- MOre work. [Jamie Rees] - -- Fixed the issue when sending movies to CouchPotato. [Jamie Rees] - -- Add appveyor. [tidusjar] - -- Build it on 4.5. [tidusjar] - -- Upgraded .net to 4.6. [tidusjar] - -- Typo2. [tidusjar] - -- Typo. [tidusjar] - -- Another update. [tidusjar] - -- Fixed. [tidusjar] - -- More logging to figure out why the we cannot access the admin module in a release build. [tidusjar] - -- Firstpass integrating with CouchPotato. [tidusjar] - -- Some styling. [tidusjar] - -- Fixed the plex friends. Added some unit tests, moved the plex auth into it's own page. [tidusjar] - -- Fully switched the TV shows over to use the other provider. [Jamie Rees] - -- Renamed folders. [tidusjar] - -- Assembly updates. [tidusjar] - -- Moved the rest of the projects. [tidusjar] - -- Moved UI. [tidusjar] - -- Mass rename. [tidusjar] - -- Quick changes. [tidusjar] - -- Started switching the TV over to the new provider (TheTVDB). Currently TV search is partially broken. It will search but we are not mapping all of the details. [tidusjar] - -- Implimented the new TV show Provider (needed for Sonarr TheTvDB) [tidusjar] - -- Started the user auth. [tidusjar] - -- Some work on the requests page. [tidusjar] - -- Made the 'requested' better and made the remove look nicer. [tidusjar] - -- Cleaned up the program a tiny bit. [tidusjar] - -- Removed additional namespace. [tidusjar] - -- Fixed some db issues and added a preview. [Jamie Rees] - -- More work on the settings. [Jamie Rees] - -- Upgraded Json.Net and Nancy packages. [Jamie Rees] - -- Plex friends api. [Jamie Rees] - -- Enabled trace logs. [tidusjar] - -- Sql syntax issue fixed. [tidusjar] - -- Fixed release build. [tidusjar] - -- Small updates including assembly version. [tidusjar] - -- Work on the requests page mostly done. [tidusjar] - -- Work on the TV request. the `latest` parameter is not being passed into the requestTvshow. [tidusjar] - -- Missing file. [tidusjar] - -- Using the IoC container now. [tidusjar] - -- Some plex work. [Jamie Rees] - -- More work. [Jamie Rees] - -- Removed the setup code out of the startup, since we attemtp to connect to the DB before that. [Jamie Rees] - -- Some more work. Need to stop the form submitting on a request. [tidusjar] - -- Moved everything up a directory. [tidusjar] - -- Lots of work! [tidusjar] - -- Done most of the movie search work. [Jamie Rees] - -- First pass with RequestPlex. [tidusjar] - -- Initial commit. [Jamie] - - diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index e11d6d914..0734262cf 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -19,5 +19,6 @@ namespace Ombi.Api.Plex Task GetAllEpisodes(string authToken, string host, string section, int start, int retCount); Task GetUsers(string authToken); Task GetAccount(string authToken); + Task GetRecentlyAdded(string authToken, string uri, string sectionId); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/Metadata.cs b/src/Ombi.Api.Plex/Models/Metadata.cs index 28bdf002d..dcde62818 100644 --- a/src/Ombi.Api.Plex/Models/Metadata.cs +++ b/src/Ombi.Api.Plex/Models/Metadata.cs @@ -23,8 +23,8 @@ namespace Ombi.Api.Plex.Models public int leafCount { get; set; } public int viewedLeafCount { get; set; } public int childCount { get; set; } - public long addedAt { get; set; } - public int updatedAt { get; set; } + //public long addedAt { get; set; } + //public int updatedAt { get; set; } public Genre[] Genre { get; set; } //public Role[] Role { get; set; } public string primaryExtraKey { get; set; } diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index b5c6b958d..e6c52d1df 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -147,6 +147,15 @@ namespace Ombi.Api.Plex return await Api.Request(request); } + public async Task GetRecentlyAdded(string authToken, string uri, string sectionId) + { + var request = new Request($"library/sections/{sectionId}/recentlyAdded", uri, HttpMethod.Get); + AddHeaders(request, authToken); + AddLimitHeaders(request, 0, 50); + + return await Api.Request(request); + } + /// /// Adds the required headers and also the authorization header /// diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 92ecf8282..e2f667465 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -175,6 +175,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index b328e6daf..1e78d226c 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -19,7 +19,7 @@ namespace Ombi.Schedule IOmbiAutomaticUpdater updater, IEmbyContentSync embySync, IPlexUserImporter userImporter, IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache, ISettingsService jobsettings, ISickRageSync srSync, IRefreshMetadata refresh, - INewsletterJob newsletter) + INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedSync) { _plexContentSync = plexContentSync; _radarrSync = radarrSync; @@ -33,6 +33,7 @@ namespace Ombi.Schedule _srSync = srSync; _refreshMetadata = refresh; _newsletter = newsletter; + _plexRecentlyAddedSync = recentlyAddedSync; } private readonly IPlexContentSync _plexContentSync; @@ -47,6 +48,7 @@ namespace Ombi.Schedule private readonly ISettingsService _jobSettings; private readonly IRefreshMetadata _refreshMetadata; private readonly INewsletterJob _newsletter; + private readonly IPlexRecentlyAddedSync _plexRecentlyAddedSync; public void Setup() { @@ -55,7 +57,8 @@ namespace Ombi.Schedule 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(() => _plexContentSync.CacheContent(false), JobSettingsHelper.PlexContent(s)); + RecurringJob.AddOrUpdate(() => _plexContentSync.CacheContent(true), JobSettingsHelper.PlexRecentlyAdded(s)); RecurringJob.AddOrUpdate(() => _cpCache.Start(), JobSettingsHelper.CouchPotato(s)); RecurringJob.AddOrUpdate(() => _srSync.Start(), JobSettingsHelper.SickRageSync(s)); RecurringJob.AddOrUpdate(() => _refreshMetadata.Start(), JobSettingsHelper.RefreshMetadata(s)); diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs index a9fadae9d..17a8bbb4f 100644 --- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexContentSync.cs @@ -4,6 +4,6 @@ namespace Ombi.Schedule.Jobs { public interface IPlexContentSync : IBaseJob { - Task CacheContent(); + Task CacheContent(bool recentlyAddedSearch = false); } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexRecentlyAddedSync.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexRecentlyAddedSync.cs new file mode 100644 index 000000000..6616f29bc --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexRecentlyAddedSync.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Schedule.Jobs.Plex +{ + public interface IPlexRecentlyAddedSync : IBaseJob + { + Task Start(); + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 3c00a7a29..0292b6b54 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -62,7 +62,7 @@ namespace Ombi.Schedule.Jobs.Plex private IPlexContentRepository Repo { get; } private IPlexEpisodeSync EpisodeSync { get; } - public async Task CacheContent() + public async Task CacheContent(bool recentlyAddedSearch = false) { var plexSettings = await Plex.GetSettingsAsync(); if (!plexSettings.Enable) @@ -78,7 +78,7 @@ namespace Ombi.Schedule.Jobs.Plex Logger.LogInformation("Starting Plex Content Cacher"); try { - await StartTheCache(plexSettings); + await StartTheCache(plexSettings, recentlyAddedSearch); } catch (Exception e) { @@ -89,14 +89,14 @@ namespace Ombi.Schedule.Jobs.Plex BackgroundJob.Enqueue(() => EpisodeSync.Start()); } - private async Task StartTheCache(PlexSettings plexSettings) + private async Task StartTheCache(PlexSettings plexSettings, bool recentlyAddedSearch) { foreach (var servers in plexSettings.Servers ?? new List()) { try { Logger.LogInformation("Starting to cache the content on server {0}", servers.Name); - await ProcessServer(servers); + await ProcessServer(servers, recentlyAddedSearch); } catch (Exception e) { @@ -105,10 +105,10 @@ namespace Ombi.Schedule.Jobs.Plex } } - private async Task ProcessServer(PlexServers servers) + private async Task ProcessServer(PlexServers servers, bool recentlyAddedSearch) { Logger.LogInformation("Getting all content from server {0}", servers.Name); - var allContent = await GetAllContent(servers); + var allContent = await GetAllContent(servers, recentlyAddedSearch); Logger.LogInformation("We found {0} items", allContent.Count); // Let's now process this. @@ -388,8 +388,9 @@ namespace Ombi.Schedule.Jobs.Plex /// If they have not set the settings then we will monitor them all /// /// The plex settings. + /// /// - private async Task> GetAllContent(PlexServers plexSettings) + private async Task> GetAllContent(PlexServers plexSettings, bool recentlyAddedSearch) { var sections = await PlexApi.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri); @@ -413,10 +414,23 @@ namespace Ombi.Schedule.Jobs.Plex } } } - var lib = await PlexApi.GetLibrary(plexSettings.PlexAuthToken, plexSettings.FullUri, dir.key); - if (lib != null) + + if (recentlyAddedSearch) { - libs.Add(lib.MediaContainer); + var container = await PlexApi.GetRecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, + dir.key); + if (container != null) + { + libs.Add(container.MediaContainer); + } + } + else + { + var lib = await PlexApi.GetLibrary(plexSettings.PlexAuthToken, plexSettings.FullUri, dir.key); + if (lib != null) + { + libs.Add(lib.MediaContainer); + } } } } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs new file mode 100644 index 000000000..dfcb9cac1 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using Ombi.Api.Plex; + +namespace Ombi.Schedule.Jobs.Plex +{ + public class PlexRecentlyAddedSync : IPlexRecentlyAddedSync + { + public PlexRecentlyAddedSync(IPlexContentSync contentSync) + { + _sync = contentSync; + } + + private readonly IPlexContentSync _sync; + + public async Task Start() + { + await _sync.CacheContent(true); + } + + private bool _disposed; + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + _sync?.Dispose(); + } + _disposed = true; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index a68ceb8bb..bb536a685 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -6,6 +6,7 @@ public string SonarrSync { get; set; } public string RadarrSync { get; set; } public string PlexContentSync { get; set; } + public string PlexRecentlyAddedSync { get; set; } public string CouchPotatoSync { get; set; } public string AutomaticUpdater { get; set; } public string UserImporter { get; set; } diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index db4083fcd..c4fcb8ceb 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -21,7 +21,11 @@ namespace Ombi.Settings.Settings.Models } public static string PlexContent(JobSettings s) { - return Get(s.PlexContentSync, Cron.Hourly(20)); + return Get(s.PlexContentSync, Cron.HourInterval(6)); + } + public static string PlexRecentlyAdded(JobSettings s) + { + return Get(s.PlexRecentlyAddedSync, Cron.Hourly(0)); } public static string CouchPotato(JobSettings s) { @@ -49,7 +53,6 @@ namespace Ombi.Settings.Settings.Models return Get(s.RefreshMetadata, Cron.Daily(3)); } - private static string Get(string settings, string defaultCron) { return settings.HasValue() ? settings : defaultCron; diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 1ce3778ec..d67ebc698 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -128,6 +128,7 @@ export interface IJobSettings { sickRageSync: string; refreshMetadata: string; newsletter: string; + plexRecentlyAddedSync: string; } export interface IIssueSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/services/job.service.ts b/src/Ombi/ClientApp/app/services/job.service.ts index 79957af97..2fe940316 100644 --- a/src/Ombi/ClientApp/app/services/job.service.ts +++ b/src/Ombi/ClientApp/app/services/job.service.ts @@ -35,6 +35,10 @@ export class JobService extends ServiceHelpers { return this.http.post(`${this.url}plexcontentcacher/`, {headers: this.headers}); } + public runPlexRecentlyAddedCacher(): Observable { + return this.http.post(`${this.url}plexrecentlyadded/`, {headers: this.headers}); + } + public runEmbyCacher(): Observable { return this.http.post(`${this.url}embycontentcacher/`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index 0d8b85930..72b78a64d 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -57,6 +57,12 @@ The Plex Sync is required +
+ + + The Plex Sync is required + +
diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index 5978e7ab2..1fd8237ae 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -33,6 +33,7 @@ export class JobsComponent implements OnInit { sickRageSync: [x.sickRageSync, Validators.required], refreshMetadata: [x.refreshMetadata, Validators.required], newsletter: [x.newsletter, Validators.required], + plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required] }); }); } diff --git a/src/Ombi/ClientApp/app/settings/plex/plex.component.html b/src/Ombi/ClientApp/app/settings/plex/plex.component.html index 6beaa3fea..6310a9cf1 100644 --- a/src/Ombi/ClientApp/app/settings/plex/plex.component.html +++ b/src/Ombi/ClientApp/app/settings/plex/plex.component.html @@ -171,19 +171,26 @@
-
+
-
-
-
- -
+
+
+
+
+
+
+
+
+ +
+
+
diff --git a/src/Ombi/ClientApp/app/settings/plex/plex.component.ts b/src/Ombi/ClientApp/app/settings/plex/plex.component.ts index 61b57b393..23bd74225 100644 --- a/src/Ombi/ClientApp/app/settings/plex/plex.component.ts +++ b/src/Ombi/ClientApp/app/settings/plex/plex.component.ts @@ -121,7 +121,15 @@ export class PlexComponent implements OnInit, OnDestroy { public runCacher(): void { this.jobService.runPlexCacher().subscribe(x => { if(x) { - this.notificationService.success("Triggered the Plex Content Cacher"); + this.notificationService.success("Triggered the Plex Full Sync"); + } + }); + } + + public runRecentlyAddedCacher(): void { + this.jobService.runPlexRecentlyAddedCacher().subscribe(x => { + if(x) { + this.notificationService.success("Triggered the Plex Recently Added Sync"); } }); } diff --git a/src/Ombi/Controllers/JobController.cs b/src/Ombi/Controllers/JobController.cs index 76ca42c41..a89346250 100644 --- a/src/Ombi/Controllers/JobController.cs +++ b/src/Ombi/Controllers/JobController.cs @@ -117,7 +117,18 @@ namespace Ombi.Controllers [HttpPost("plexcontentcacher")] public bool StartPlexContentCacher() { - BackgroundJob.Enqueue(() => _plexContentSync.CacheContent()); + BackgroundJob.Enqueue(() => _plexContentSync.CacheContent(false)); + return true; + } + + /// + /// Runs a smaller version of the content cacher + /// + /// + [HttpPost("plexrecentlyadded")] + public bool StartRecentlyAdded() + { + BackgroundJob.Enqueue(() => _plexContentSync.CacheContent(true)); return true; } diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 9ffa9d81f..f8e58418a 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -473,6 +473,7 @@ namespace Ombi.Controllers j.UserImporter = j.UserImporter.HasValue() ? j.UserImporter : JobSettingsHelper.UserImporter(j); j.SickRageSync = j.SickRageSync.HasValue() ? j.SickRageSync : JobSettingsHelper.SickRageSync(j); j.RefreshMetadata = j.RefreshMetadata.HasValue() ? j.RefreshMetadata : JobSettingsHelper.RefreshMetadata(j); + j.PlexRecentlyAddedSync = j.PlexRecentlyAddedSync.HasValue() ? j.PlexRecentlyAddedSync : JobSettingsHelper.PlexRecentlyAdded(j); return j; } diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 7a94dbb61..7fc0522ed 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -182,12 +182,15 @@ namespace Ombi // Check if it's in the startup args var appConfig = serviceProvider.GetService(); var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result; - if (baseUrl.Value.HasValue()) + if (baseUrl != null) { - settings.BaseUrl = baseUrl.Value; - ombiService.SaveSettings(settings); + if (baseUrl.Value.HasValue()) + { + settings.BaseUrl = baseUrl.Value; + ombiService.SaveSettings(settings); - app.UsePathBase(settings.BaseUrl); + app.UsePathBase(settings.BaseUrl); + } } } From 66687bd177474923118b93914982befd57b23b8f Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 13 Apr 2018 23:20:22 +0100 Subject: [PATCH 024/495] Fixed the bug where the newsletter CRON was not appearing on the job settings page --- src/Ombi/Controllers/SettingsController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index f8e58418a..30469cd57 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -474,6 +474,7 @@ namespace Ombi.Controllers j.SickRageSync = j.SickRageSync.HasValue() ? j.SickRageSync : JobSettingsHelper.SickRageSync(j); j.RefreshMetadata = j.RefreshMetadata.HasValue() ? j.RefreshMetadata : JobSettingsHelper.RefreshMetadata(j); j.PlexRecentlyAddedSync = j.PlexRecentlyAddedSync.HasValue() ? j.PlexRecentlyAddedSync : JobSettingsHelper.PlexRecentlyAdded(j); + j.Newsletter = j.Newsletter.HasValue() ? j.Newsletter : JobSettingsHelper.Newsletter(j); return j; } From 75a631bfcfcf7f67fd14496b6bc6095edc7baf60 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 13 Apr 2018 23:23:58 +0100 Subject: [PATCH 025/495] !wip changelog --- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c557ed19..fa6cf0714 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,46 @@ ### **New Features** +- Added a new Job. Plex Recently Added, this is a slimmed down version of the Plex Sync job, this will just scan the recently added list and not the whole library. I'd reccomend running this very regulary and the full scan not as regular. [Jamie] + +### **Fixes** + +- Fixed the bug where the newsletter CRON was not appearing on the job settings page. [Jamie] + +- Add base url as a startup argument #2153. [Jamie Rees] + +- Fixed a bug with the RefreshMetadata where we would never get TheMovieDBId's if it was missing it. [Jamie] + + +## v3.0.3173 (2018-04-12) + +### **Fixes** + +- Removed some early disposition that seemed to be causing errors in the API. [Jamie] + + +## v3.0.3164 (2018-04-10) + +### **New Features** + - Added the ability to send newsletter out to users that are not in Ombi. [Jamie] - Added the ability to turn off TV or Movies from the newsletter. [Jamie] +- Update about.component.html. [Jamie] + +- Update about.component.html. [Jamie] + - Added random versioning prefix to the translations so the users don't have to clear the cache. [Jamie] - Added more information to the about page. [Jamie] +- Changed let to const to adhere to linting. [Anojh] + +- Update _Layout.cshtml. [goldenpipes] + +- Update _Layout.cshtml. [goldenpipes] + - Changed the TV Request API. We now only require the TvDbId and the seasons and episodes that you want to request. This should make integration regarding TV a lot easier. [Jamie] ### **Fixes** @@ -22,6 +54,8 @@ - Made some improvements to the Sonarr Sync job #2127. [Jamie] +- Turn off Server GC to hopefully help with #2127. [Jamie Rees] + - Fixed #2109. [Jamie] - Fixed #2101. [Jamie] @@ -44,6 +78,12 @@ - Fixed the issue where movies were not appearing in the newsletter for users with Emby #2111. [Jamie] +- The fact that this button has another style really bothers me. [Louis Laureys] + +- Fix discord current user count. [Avi] + +- Fix broken images and new discord invite. [Avi] + ## v3.0.3111 (2018-03-27) From 87b79dfa167e4d02eb2580132bb0a99816363a48 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 13 Apr 2018 23:46:21 +0100 Subject: [PATCH 026/495] !wip fixed lint --- src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index 1fd8237ae..d0a7a8b83 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -33,7 +33,7 @@ export class JobsComponent implements OnInit { sickRageSync: [x.sickRageSync, Validators.required], refreshMetadata: [x.refreshMetadata, Validators.required], newsletter: [x.newsletter, Validators.required], - plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required] + plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], }); }); } From 964377b1959ea122a49cbaec73559db0d6375de2 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 15 Apr 2018 10:43:08 +0200 Subject: [PATCH 027/495] Add web-app-capable for IOS and Android --- src/Ombi/Views/Shared/_Layout.cshtml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Ombi/Views/Shared/_Layout.cshtml b/src/Ombi/Views/Shared/_Layout.cshtml index cafd75357..cb9985bac 100644 --- a/src/Ombi/Views/Shared/_Layout.cshtml +++ b/src/Ombi/Views/Shared/_Layout.cshtml @@ -75,6 +75,8 @@ O:::::::OOO:::::::Om::::m m::::m m::::mb:::::bbbbbb::::::bi::::::i + + From 487d68729b1b8f5a16431a24a5bb5bc19e8b9f36 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 15 Apr 2018 17:20:22 +0100 Subject: [PATCH 028/495] !cosmetic changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa6cf0714..4ce452bfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### **Fixes** +- Add web-app-capable for IOS and Android. [Thomas] + - Fixed the bug where the newsletter CRON was not appearing on the job settings page. [Jamie] - Add base url as a startup argument #2153. [Jamie Rees] From a837868be5e95030c83f2effce5e8a0fe05f704a Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 16 Apr 2018 14:45:42 +0100 Subject: [PATCH 029/495] !cosmetic changelog --- CHANGELOG.md | 3610 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3610 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ce452bfb..ecb1a790d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -819,3 +819,3613 @@ - Switch to use a single HTTPClient rather than a new one every request !dev. [tidusjar] +- Fix non-admin rights (#1820) [Rob Gökemeijer] + +- Fix duplicated "Requests" element ID on new Issues link (#1817) [Shoghi Cervantes] + +- Add the Issue Reporting functionality (#1811) [Jamie] + +- Removed the forum. [tidusjar] + +- #1659 Made the option to ignore notifcations for auto approve. [Jamie] + +- New Crowdin translations (#1806) [Jamie] + +- Fixed a launch issue. [Jamie] + +- Allow users to login without a password. [Jamie] + +- Fixed the emby notifications not being sent. [Jamie] + +- #1802 and other small fixes. [tidusjar] + +- So... This sickrage thing should work now. [tidusjar] + +- Fixed emby connect login issue. [tidusjar] + +- Stop making unnecessary calls to the update service. [Jamie] + +- Fixed a bug where it blocked users with 0 limits. [Jamie] + +- Done #1788. [tidusjar] + +- More logging. [Jamie] + +- Fixed #1738. [Jamie] + +- Fixed build. [Jamie] + +- Fixed the issue where notifications were not sendind unless we restarted #1732. [tidusjar] + +- Fixed an issue with a trailing space in the subdir. [tidusjar] + +- Fixed #1774. [Jamie] + +- #1773. [Jamie] + +- Roll back rxjs (#1778) [bazhip] + +- Fixed build. [Jamie] + +- Fixed #1763. [Jamie] + +- Fix "content length error" on preview gif (#1768) [OoGuru] + +- New preview gif for Ombi V3 README (#1767) [OoGuru] + +- Remove debug code. [tidusjar] + +- Fix #1762. [tidusjar] + +- Fixed the preset themes not loading. [tidusjar] + +- Fixed #1760 and improvements on the auto updater. We may now support windows services... #1460. [Jamie] + +- Fixed #1754. [Jamie] + +- Hide the subject when it's not being used. [Jamie] + +- Error handling #1749. [Jamie] + +- New Crowdin translations (#1741) [Jamie] + +- #1732 #1722 #1711. [Jamie] + +- Fixed an issue with switching the preset themes. [Jamie] + +- Fixed #1743. [Jamie] + +- Fixed #1742. [tidusjar] + +- Fix #1742. [tidusjar] + +- Fixed landing page. [Jamie] + +- Fixed. [Jamie] + +- Translated the Requests page and fixed #1740. [Jamie] + +- Fix crash. [Jamie] + +- Sickrage done. Ish... So i've written all the code by looking at the API. the key there is i've looked at the api. I have not tested anything so expect this to fail. [Jamie] + +- SickRage settings UI. [Jamie] + +- Fixed #1721. [tidusjar] + +- Fixed the preset themes issue. [tidusjar] + +- New Crowdin translations (#1654) [Jamie] + +- Fix build. [Jamie] + +- #1460. [Jamie] + +- Fixed tests. [Jamie] + +- Return css as MIME text/css. [Jamie] + +- More added for the preset themes. [Jamie] + +- Moved around the custom styles. [Jamie] + +- More renames. [Jamie] + +- Renames. [Jamie] + +- Load the first 100 requests. [Jamie] + +- Reduce the memory consumption #1720. [Jamie] + +- Moved the schedules jobs into it's own database, see if it helps with the db locking #1720. [Jamie] + +- Fixed #1712. [tidusjar] + +- Potential fix for #1702. [tidusjar] + +- Fixed #1708. [tidusjar] + +- Fixed #1677. [tidusjar] + +- Fixed build. [tidusjar] + +- Potential fix for the DB locking issue #1720. [tidusjar] + +- #1698. [Jamie] + +- Fixed #1705. [tidusjar] + +- Fixed #1703. [tidusjar] + +- Finished adding preset themes. [Jamie] + +- Fixed #17000. [Jamie] + +- Remove the themes because waiting for a merge from lerams project. [Jamie] + +- Finsihed adding preset themes. [Jamie] + +- Fixed #1677. [Jamie] + +- Temp fix for #1683. [Jamie] + +- Fixed #1685. [Jamie] + +- Lossless Compression of images saves 83 KB (#1676) [Fish2] + +- Fixed the availability checker. [tidusjar] + +- Fixed build. [tidusjar] + +- Push out missing migration. [tidusjar] + +- Potential fix for #1674. [tidusjar] + +- Fixed an issue with the caching. [tidusjar] + +- Fixed telegram #1667. [tidusjar] + +- Fixed #1663. [tidusjar] + +- Should fix #1663. [tidusjar] + +- Stop logged in users going to the login page. [Jamie] + +- Fixed it not updating. Styles should be good now. [Jamie] + +- Re did some of the styling on the movie search page, let me know your thoughts. [Jamie] + +- Fixed #1657. [Jamie] + +- Fixed #1655. [Jamie] + +- Removed authentication resul. [Jamie] + +- New Crowdin translations (#1651) [Jamie] + +- New Crowdin translations (#1648) [Jamie] + +- New Crowdin translations (#1638) [Jamie] + +- Fixed #1644. [Jamie] + +- Moar logs #1643. [tidusjar] + +- Fixed #1640. [tidusjar] + +- Fixed the null ref exception #1460. [tidusjar] + +- Fixed landing page. [TidusJar] + +- Fixed #1641. [TidusJar] + +- Fixed #1641. [TidusJar] + +- New Crowdin translations (#1635) [Jamie] + +- Fixed #1631 and improved translation support Included startup args for the auto updater #1460 Mark TV requests as available #1632. [tidusjar] + +- Remove 32bit. [Jamie] + +- More 32bit support. [Jamie] + +- We now show "Available" for tv shows that is fully available #1602. [tidusjar] + +- Fixed the issue where we have got an episode but not the related series. #1620. [tidusjar] + +- Fixed the dropdown not working on iOS in the settings #1615. [tidusjar] + +- Fixed sonarr not monitoring the latest season #1534. [tidusjar] + +- Fixed the issue with firefox #1544. [tidusjar] + +- Fixed discord #1623. [tidusjar] + +- Add browserstack thanks (#1627) [Matt Jeanes] + +- Fix the exception #1613. [Jamie] + +- Found where we potentially are setting a new poster path, looks like the entity was being modified and being set as Tracked by entity framework, so the next time we called SaveChangesAsync() it would save the new posterpath on the entity. [Jamie] + +- Small modifications. [Jamie] + +- Fixed #1622. [Jamie] + +- Various improvements to webpack/gulp/vscode support (#1617) [Matt Jeanes] + +- Episodes in requests are now in order #1597 (#1614) [masterhuck] + +- Fixed a null reference issue in the Plex Content Cacher. [Jamie.Rees] + +- Fixed #1610. [tidusjar] + +- Really fixed the build this time. [tidusjar] + +- Fixed build. [tidusjar] + +- Made the updater work again #1460. [tidusjar] + +- Adding logging into the auto updater and also added more logging around the create inital user for #1604. [tidusjar] + +- Fixed the issue where we did not check if they are already in sonarr when choosing certain options #1540. [tidusjar] + +- We can now delete tv child requests and the parent will get remove #1603. [tidusjar] + +- Finished the api changes requested #1601. [tidusjar] + +- Fixed the Hangfire server timeout issue #1605. [tidusjar] + +- Fixed notifications not sending #1594. [tidusjar] + +- Fixed #1583 you can now delete users. Fixed the issue where the requested by was not showing. Finally fixed the broken poster paths. [tidusjar] + +- Fixed the issue where movie requests were no longer being requested. [tidusjar] + +- Started adding some more unit tests #1596. [Jamie.Rees] + +- #1588 When we make changes to any requests that we can trigger a notification, always send it to all notification agents, even if the user wont recieve it. [Jamie.Rees] + +- Add a message when email notifications are not setup when requesting a password reset. #1590. [Jamie.Rees] + +- Removed text that we no longer need. [Jamie.Rees] + +- Fixed #1574. [Jamie.Rees] + +- #1460 looks like the permissions issue has been resolved. Just need to make sure the Ombi process is terminated. [Jamie.Rees] + +- Put back the old download code. [Jamie.Rees] + +- Test. [Jamie] + +- Build sln. [Jamie.Rees] + +- Order by the username #1581. [Jamie.Rees] + +- Remove sonarr episodes from the cache table. [Jamie.Rees] + +- Couchpotato finished. [tidusjar] + +- Disable run import button if no import options are selected. [tidusjar] + +- Fixed #1574. [tidusjar] + +- Fixed build. [tidusjar] + +- Fixes the issue with non windows systems unable to unzip the tarball #1460. [tidusjar] + +- Finished the couchpotato settings. [tidusjar] + +- Fixed build. [tidusjar] + +- Fixed #1570 #1571. [tidusjar] + +- Fixed #1547. [tidusjar] + +- Should fix #1538. [tidusjar] + +- Fixed #1553. [tidusjar] + +- Fixed #1546. [tidusjar] + +- Fixed #1543. [tidusjar] + +- Fixes an issue with Movie caching not working on develop branch of Radarr (#1567) [Jeffrey Peters] + +- This adds two fields to the Email Notifications settings page. It allows for the disabling of TLS/SSL as well as the ability to disable certificate validation when sending notification emails. (#1552) [Jeffrey Peters] + +- Fixed typo (#1551) [Codehhh] + +- Use Sqlite storage for Hangfire. [tidusjar] + +- Fixed the overrides #1539 also display it on screen now too. [tidusjar] + +- Fixed #1542 also added VSCode support. [tidusjar] + +- Fixed some cosmetic issues #865. [Jamie.Rees] + +- Fixed #1531. [Jamie.Rees] + +- Small fixes #865. [Jamie.Rees] + +- Some errors fixed and some ui improvements #865. [tidusjar] + +- Auto-scale large images down to container size (#1529) [Avi] + +- Fix logo on login page. (#1528) [Avi] + +- Another potential issue? :/ [tidusjar] + +- Real fix. [tidusjar] + +- #1513 Added storage path. [Jamie.Rees] + +- Fixed the discord issue relating to images #1513. [Jamie.Rees] + +- Fixed the issue sending movies to Radarr #1513 Fixed typo #1524. [Jamie.Rees] + +- Fixed logo on reset password pages fixed the run importer button on the user management settings. [Jamie.Rees] + +- Fixed crash/error #865. [tidusjar] + +- #1513 fixed the landing page and also the reverse proxy images. [tidusjar] + +- #1513 correctly set the child requests as approved. [tidusjar] + +- Fixed an issue that potentially causes as issue when siging into plex #865. [tidusjar] + +- Remove dev branch. [PotatoQuality] + +- Prepare readme for upcoming beta. [PotatoQuality] + +- #1513 partially fixed a bug. [tidusjar] + +- Fixed the exception. [tidusjar] + +- Fixed the application url not saving #1513. [tidusjar] + +- Fixed liniting. [tidusjar] + +- REVERSE PROXY BITCH! #1513. [tidusjar] + +- Fixed a bug where we were marking the wrong episodes as available #1513 #865. [Jamie.Rees] + +- Fixed an issue where we messed up the pages and routing. [Jamie.Rees] + +- Emby user importer is now therer! #1456. [tidusjar] + +- #1513 Added the update available icon. [tidusjar] + +- Fixed the issue of it showing as not requested when we find it in Radarr. Made the tv shows match a bit more to the movie requests Added the ability for plex and emby users to login Improved the welcome email, will only show for users that have not logged in Fixed discord notifications the about screen now checks if there is an update ready #1513. [tidusjar] + +- Support email addresses as usernames #1513. [Jamie.Rees] + +- Link to issue treath. [PotatoQuality] + +- Give correct feedback when testing email notifications #1513. [Jamie.Rees] + +- Report issue removed and the deny dropdown removed #1513. [Jamie.Rees] + +- #1513 removed the discord text when testing pushbullet. [Jamie.Rees] + +- Made a lot of changes around the notifcations to support the custom app name also started on the welcome email ##1456. [Jamie.Rees] + +- Fixed the bug where we were displaying shows where we do not have enough information to request #1513. [Jamie.Rees] + +- #1513 added the network to tv shows. [Jamie.Rees] + +- Fixed the whitespace issue #1513. [Jamie.Rees] + +- Fixed the swagger endpoint #865 #1513 Fixed the custom image issue on the login page Fixed the bug when clicking on the tab on the requests page it would switch to the wrong one Swagger is now back @ /swagger. [tidusjar] + +- Optimized images, Update old compressed image with a new lossless one. (#1514) [camjac251] + +- #1513 #865 Fixed the issue where we do not send the requests to Radarr/Sonarr when approving. [tidusjar] + +- #1506 #865 Fixed an issue with the test buttons not working correctly. [tidusjar] + +- #865 Added donation link. [tidusjar] + +- Fixed a bunch of issues on #1513. [tidusjar] + +- #1460 Added the Updater, it all seems to be working correctly. #865. [Jamie.Rees] + +- Removed percentage. [Jamie.Rees] + +- Fixed linter. [Jamie.Rees] + +- Fixed some bugs in the UI #865. [Jamie.Rees] + +- Improved the search buttons #865. [Jamie.Rees] + +- More logging #865. [Jamie.Rees] + +- Made build faster. [Jamie.Rees] + +- More logging. [Jamie.Rees] + +- Set debug level to Debug for now. [Jamie.Rees] + +- Add linting and indexes for interfaces/services (#1510) [Matt Jeanes] + +- Fixed the issue with the tv search not working #1463. [Jamie.Rees] + +- Latest practices... also probably broke some styles - sorry (#1508) [Matt Jeanes] + +- Build with the branch version. [tidusjar] + +- Build fix. [tidusjar] + +- Fixed build. [tidusjar] + +- Omgwtf so many changes. #865. [tidusjar] + +- Tests. [Jamie.Rees] + +- #1456 Started on the User Importer Also added the remember me button. [Jamie.Rees] + +- Made some UI changes, reworked the Emby and Plex screens to make them more user friendly and no so fugly. #865 Also made the login page placeholder text slightly lighter. [Jamie.Rees] + +- Cake skip verification build stuff #865. [Jamie.Rees] + +- Some fixes around the UI and managing requests #865. [tidusjar] + +- #1486. [Jamie.Rees] + +- #1486. [Jamie.Rees] + +- Upgraded to .net core 2.0 #1486. [Jamie.Rees] + +- #865 Finished the landing page, we now check the server's status. [Jamie.Rees] + +- Fixed build. [TidusJar] + +- Removed the telegram api. [Jamie.Rees] + +- Small changes on the updater #1460 #865. [Jamie.Rees] + +- Remove unused functions. [Dhruv Bhavsar] + +- Make Episode picker similar to Requests Child view. #1457 #1463. [Dhruv Bhavsar] + +- Fix merge conflict for TvRequests component. [Dhruv Bhavsar] + +- Upstream Changes... [Dhruv Bhavsar] + +- Clean up Requests page code by moving children request to old component, remove additional REST calls when merging and update component names to make more sense. [Dhruv Bhavsar] + +- Lots of different UI enhancements and fixes #865. [tidusjar] + +- Gitchangelog. [tidusjar] + +- Fixed the issue where we were using the wrong availability options. [tidusjar] + +- Fixed a bunch of bugs in Ombi #865. [tidusjar] + +- Build versioning. [Jamie.Rees] + +- #1460 The assembly versioning seems to work correctly now. [Jamie.Rees] + +- More build versioning changes #865. [tidusjar] + +- Fixed cake script. [Jamie.Rees] + +- WIP on the build versioning for the Updater #1460 #865. [Jamie.Rees] + +- Versioning. [Jamie.Rees] + +- Package versions. [Jamie.Rees] + +- #1460 #865 working on the auto updater. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Small changes around the roles #865. [tidusjar] + +- Improvements to the UI and also finished the availability checker #865 #1464. [Jamie.Rees] + +- Availability Checker #1464 #865. [Jamie.Rees] + +- Fixed ##1492 and finished the episode searcher for #1464. [Jamie.Rees] + +- #1464. [tidusjar] + +- Reload the settings #1464 #865. [Jamie.Rees] + +- #1464 added the Plex episode cacher #865. [Jamie.Rees] + +- Fixed some issues around the tv requests area Added mattermost and telegram notifications #1459 #865 #1457. [tidusjar] + +- Fix global.json. [Dhruv Bhavsar] + +- Working UI for Requests. Approval/Deny does not work as it doesn't in your code either. [Dhruv Bhavsar] + +- Enable diagnostic on build #865. [Jamie.Rees] + +- Fixed the user token issue #865. [Jamie.Rees] + +- Some small refresh token work #865. [Jamie.Rees] + +- Initial TV Requests UI rebuild. [Dhruv Bhavsar] + +- Made a start on supporting multiple emby servers, the UI needs rework #865. [Jamie.Rees] + +- #865 #1459 Added the Sender From field for email notifcations. We can now have "Friendly Names" for email notifications. [Jamie.Rees] + +- Redirect to the landing page when enabled #1458 #865. [Jamie.Rees] + +- Removed IdentityServer, it was overkill #865. [Jamie.Rees] + +- Fixed another bug with identity. #865 I'm thinking about removing it. Causing more hassle than it's worth. [tidusjar] + +- #1460 #865. [tidusjar] + +- Delete appveyor_old.yml. [Jamie] + +- Fixed path. [Jamie.Rees] + +- Silent build level. [Jamie.Rees] + +- #1459 Forgot to get the Pushbullet agent to look up the pusbullet templates rather than the Discord ones. Updated the Gitchange log. [Jamie.Rees] + +- Made the placeholder color on the login page a bit lighter #865. [Jamie.Rees] + +- Landing and login page changes #865 #1485. [tidusjar] + +- #1458 #865 More work on landing. [Jamie.Rees] + +- Working on the landing page #1458 #865. [tidusjar] + +- A lot of clean up and added a new Image api #865. [Jamie.Rees] + +- Cleaned up the Logging API slightly #1465 #865. [Jamie.Rees] + +- Fixed the Identity Server discovery bug #1456 #865. [tidusjar] + +- Fixed the issue with the Identity Server running on a different port, we can now use -url #865. [Jamie.Rees] + +- Try again. [TidusJar] + +- Publish ubuntu 16.04. [Jamie.Rees] + +- Chnaged the updater job from Minutely to Hourly. [Jamie.Rees] + +- Some work around the Auto Updater and other small changes #1460 #865. [Jamie.Rees] + +- Missed a file. [tidusjar] + +- Fixed the swagger issue. [tidusjar] + +- RDP issues. [tidusjar] + +- Appveyor build rdp investigation. [tidusjar] + +- Working on the requests page #1457 #865. [tidusjar] + +- Made the password reset email style the same as other email notifications #1456 #865. [Jamie.Rees] + +- Fixed some bugs around the authentication #1456 #865. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Fixed build #1456. [Jamie.Rees] + +- #1456 #865 Started on allowing Plex Users to sign in through the new authentication server. [Jamie.Rees] + +- Removed covalent. [Jamie.Rees] + +- #1456 Reset Password stuff #865. [Jamie.Rees] + +- Finished implimenting Identity with IdentityServer4. #865 #1456. [Jamie.Rees] + +- Moved over to using Identity Server with Asp.Net Core Identity #1456 #865. [Jamie.Rees] + +- Started on the requests rework #865. [Jamie.Rees] + +- Extended the Emby API. [Jamie.Rees] + +- Started reworking the usermanagement page #1456 #865. [tidusjar] + +- Lots of refactoring #865. [Jamie.Rees] + +- Created an individual user api endpoint so we can make the user management pages better #865. [TidusJar] + +- Lot's of refactoring. [Jamie.Rees] + +- #1462 #865 Had to refactor how we use notificaitons. So we now have more notification fields about the request. [Jamie.Rees] + +- Looks like Sonarr is finished and works. A lot simplier this time around. #865. [tidusjar] + +- More work on the Sonarr Api Integration #865. [tidusjar] + +- Started on sonarr #865. [tidusjar] + +- Small changes #865. [tidusjar] + +- Damn son. So many changes... Fixed alot of stuff around tv episodes with the new DB model #865. [tidusjar] + +- Fixed the TV Requests issue #865. [Jamie.Rees] + +- Fixed a load of bugs need to figure out what is wrong with tv requests #865. [tidusjar] + +- #865 rework the backend data. Actually use real models rather than a JSON store. [Jamie.Rees] + +- Fixed the build issue #865. [tidusjar] + +- Allow us to use Emby as a media server. [tidusjar] + +- More Update #865. [Jamie.Rees] + +- Deployment changes. [Jamie.Rees] + +- More work on the Updater. [Jamie.Rees] + +- Lots of fixes. Becoming more stable now. #865. [tidusjar] + +- Small fixes around the searching. [Jamie.Rees] + +- Some rules #865. [Jamie.Rees] + +- Oops. [TidusJar] + +- Started on the Discord API settings page. [TidusJar] + +- Email Notifications are now fully customizable and work! #865. [Jamie.Rees] + +- Small changes and fixed some stylingon the plex page #865. [Jamie.Rees] + +- More on #865 TODO, Find out whats going on with the notifications and why exceptions are being thrown. [Jamie.Rees] + +- Oops. [Jamie.Rees] + +- Ok #865 fixed the published exe. [Jamie.Rees] + +- Fixed errors. [Jamie.Rees] + +- Fixed build script. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Some more #865. [Jamie.Rees] + +- Create appveyor.yml. [Jamie] + +- The Approving child requests now work! [Jamie.Rees] + +- Fixed many bugs #865. [Jamie.Rees] + +- Loads of changes, improved the movie search stylings is back. [Jamie.Rees] + +- Moved to webpack and started on new style. [Jamie.Rees] + +- Fixed the TV search via Trakt not returning Images anymore. #865. [Jamie.Rees] + +- Rules changes and rework. [Jamie.Rees] + +- Request Grid test. [Jamie.Rees] + +- Small cleanup #865. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Started the Radarr Settings #865. [Jamie.Rees] + +- Massive amount of rework on the plex settings page. It's pretty decent now! #865. [tidusjar] + +- Fixed build. [Jamie.Rees] + +- Fixed build. [tidusjar] + +- Rules #865. [tidusjar] + +- Stuff. [Jamie.Rees] + +- Forgot to uncomment. [Jamie.Rees] + +- Tetsd. [Jamie.Rees] + +- Build task changes. [Jamie.Rees] + +- Adsa. [Jamie.Rees] + +- Appveyor. [Jamie.Rees] + +- Stuff around tokens and also builds. [Jamie.Rees] + +- Finished the Plex Content Cacher. Need to do the episodes part but things are now showing as available! #865. [tidusjar] + +- Small user changes #865. [Jamie.Rees] + +- Stuff #865 need to work on the claims correctly. [Jamie.Rees] + +- Reworked the TV model AGAIN #865. [Jamie.Rees] + +- The move! [Jamie.Rees] + +- Fixed build #865. [Jamie.Rees] + +- Fixed the user management #865. [Jamie.Rees] + +- #865 Added support for multiple plex servers. [Jamie.Rees] + +- Bleh. [tidusjar] + +- Small changes. [Jamie.Rees] + +- Fixed the build. [Jamie.Rees] + +- Fixes. [Jamie.Rees] + +- Bundling changes. [Jamie.Rees] + +- Some series information stuff, changes the pace theme too. [Jamie.Rees] + +- Docker support and more, redesign the episodes. [tidusjar] + +- Stuff around episode/season searching/requesting. [Jamie.Rees] + +- Removed redundant folders. [tidusjar] + +- Lots of backend work. [tidusjar] + +- Fixed build. [Jamie.Rees] + +- TV Request stuff. [Jamie.Rees] + +- Work around the user management. [tidusjar] + +- More. [Jamie.Rees] + +- Lots and Lots of work. [Jamie.Rees] + +- Diagnostic changes. [tidusjar] + +- Fixed hangfire exception. [tidusjar] + +- Remove xunit. [tidusjar] + +- Lots more work :( [Jamie.Rees] + +- More changes. [tidusjar] + +- #865. [Jamie.Rees] + +- Small changes. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- More mapping. [Jamie.Rees] + +- Mapping mainly. [Jamie.Rees] + +- Fix systemjs config not being included. [Matt Jeanes] + +- Fixed bundling and various improvements. [Matt Jeanes] + +- Finished the emby wizard #865. [tidusjar] + +- Finished the wizard #865 (For Plex Anyway) [tidusjar] + +- Small changes. [tidusjar] + +- More work on Wizard and Plex API #865. [tidusjar] + +- Settings. [Jamie.Rees] + +- Settings for Ombi. [Jamie.Rees] + +- Fixed some issues around the identity. [Jamie.Rees] + +- #865 more for the authentication. [tidusjar] + +- Auth. [Jamie.Rees] + +- More on the search and requests page. It's almost there for movies. Need to add some filtering logic #865. [tidusjar] + +- #865. [Jamie.Rees] + +- Fixed build. [tidusjar] + +- Messing around with the settings. [tidusjar] + +- Fixed the yml. [Jamie.Rees] + +- Remove unneeded bundle config. [Matt Jeanes] + +- Redo dotnet publish targets. [Jamie.Rees] + +- Bundling changes. [Jamie.Rees] + +- Stuff. [Jamie.Rees] + +- Move app into wwwroot. [Jamie.Rees] + +- Put uglify back in! [Jamie.Rees] + +- Wrong line. [Jamie.Rees] + +- Matt is helping. [Jamie.Rees] + +- Revert. [tidusjar] + +- Small tweaks. [tidusjar] + +- Upgrade to .Net Standard 1.6. [tidusjar] + + +## v2.2.1 (2017-04-09) + +### **New Features** + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added the forums. [tidusjar] + +- Updates. [tidusjar] + +- Update gulpfile.js. [Jamie] + +- Update gulpfile.js. [Jamie] + +- Update gulpfile.js. [Jamie] + +- Update gulpfile.js. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Update gulpfile.js. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added a retry policy around the emby newsletter. [Jamie.Rees] + +### **Fixes** + +- Revert "Merge branch 'DotNetCore' into dev" [tidusjar] + +- More borken build. [Jamie.Rees] + +- Started adding requesting. [Jamie.Rees] + +- Done the movie searching. [tidusjar] + +- #865. [tidusjar] + +- More. [tidusjar] + +- Moar. [tidusjar] + +- Small changes. [tidusjar] + +- Styling. [Jamie.Rees] + +- MOre changes. [Jamie.Rees] + +- Spacing. [Jamie.Rees] + +- Try again. [Jamie.Rees] + +- More. [Jamie.Rees] + +- Again. [Jamie.Rees] + +- Anbother. [Jamie.Rees] + +- Another. [Jamie.Rees] + +- Another. [Jamie.Rees] + +- Retry. [Jamie.Rees] + +- A. [Jamie.Rees] + +- Fixed. [Jamie.Rees] + +- Cahnge 2. [Jamie.Rees] + +- Appveyor change. [Jamie.Rees] + +- The start of a new world. [Jamie.Rees] + +- Fixed the migration number and order by the added date for the newsletter #1264. [tidusjar] + +- Forgot this change. [tidusjar] + +- Also fixed the issue for the Emby Newsletter where episodes were not getting added :( [tidusjar] + +- #1264 "They may take our lives, but they'll never take our freedom!" [tidusjar] + +- Finished reworking the Sonarr Integration. Seems to be working as expected, faster and most stable. It's Not A Toomah! [tidusjar] + +- Small bit of work. [Jamie.Rees] + +- Made a start on the new Sonarr integration. [tidusjar] + +- For test emails, if there is no new content then just grab some old data. [tidusjar] + +- Fixed an issue where the emby newsletter was always showing series. [tidusjar] + + +## v2.2.0 (2017-03-30) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added a new setting for the Netflix option, we can now disable it appearing in the search. [tidusjar] + +- Update German Translation. [Marius Schiffer] + +- Added a release notes page, you can access via Admin>Updates>Recent Changes tab. Note to self, need to put better comments in for users to understand! [Jamie.Rees] + +- Added gravitar image. [Jamie.Rees] + +- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] + +- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] + +- Added some logging around API calls. [smcpeck] + +- Changed IEmbyAvailabilityChecker to use IEnumberables + checking actor search against Emby content + PR feedback. [smcpeck] + +- Changed actor searching to support non-actors too. [smcpeck] + +- Added a 10 second timer to refresh some new caching I put in. [smcpeck] + +- Added root folder and approving quality profiles in radarr #1065. [tidusjar] + +- Added some debugging code around the newsletter for Emby #1116. [tidusjar] + +- Added a TMDB Rate limiter for the newsletter. [tidusjar] + +- Added port check in wizard. also fixed favicon. [tidusjar] + +- Update Radarr placeholder. [d2dyno] + +- Added the user login for emby users #435. [tidusjar] + +- Added User Management support for Emby #435. [tidusjar] + +- Added emby to the sidebar #435. [tidusjar] + +- Added API endpoint for /actor/new/ to support searching for movies not already available/requested. [smcpeck] + +- Update ISSUE_TEMPLATE.md. [Jamie] + +- Update README.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +### **Fixes** + +- Translation changes. [Jamie.Rees] + +- Syntax error. [tidusjar] + +- Fixed an issue where we were retrying the API call when the Plex users login creds were invalid. #1217. [tidusjar] + +- Slightly increased the wait time for the emby newsletter also fixed a potential error in the plex user checker. [Jamie.Rees] + +- Fixed an issue where we were not notifiying emby users. [Jamie.Rees] + +- Fixed the issue where the recent changes page was not showing the correct date. #1296. [Jamie.Rees] + +- Fixed #1252 (Show the correct user type on the management page for Plex Users) [Jamie.Rees] + +- Fixed the casting error #1292. [Jamie.Rees] + +- Fix test newletter not sending when empty. [Dhruv Bhavsar] + +- Quick fix for email false positive message. ISSUE: #1286. [Dhruv Bhavsar] + +- Fixes around the newsletter. We will now correctly show newly added shows and also newly added episodes. #1163. [tidusjar] + +- Fixed a sonarr deseralization error. [tidusjar] + +- Increased the delay for the Episode information api calls. #1163. [tidusjar] + +- Looks like we were overloading emby with out api calls. [tidusjar] + +- Fixed the root path escaping issue for Radarr too! [tidusjar] + +- Some small backend newsletter changes, we can now detect if there are any movies and/or tv shows, if there are none then we will no longer send out an empty newsletter. [Jamie.Rees] + +- Remoddeled the notificaiton settings to make it easier to add more. This is some techinical changes that no one except me will ever notice :( [Jamie.Rees] + +- Fixed #1234. [Jamie.Rees] + +- A fix to the about page and also started to rework the notification backend slightly to easily add more notifications. [Jamie.Rees] + +- Adding more logging into the Plex Cacher. [Jamie.Rees] + +- #1218 changed the text when we cannot display release notes for dev and EAP branches. [Jamie.Rees] + +- Fix for #1236. [SuperPotatoMen] + +- Tooltips. [Jamie.Rees] + +- #236. [Jamie.Rees] + +- #1102. [Jamie.Rees] + +- Done #1012. [Jamie.Rees] + +- Oops #1134. [Jamie.Rees] + +- Fixed #1121. [Jamie.Rees] + +- Fixed #1210. [Jamie.Rees] + +- Fixed typo #1134. [Jamie.Rees] + +- Fixed #1223. [Jamie.Rees] + +- Another newsletter fix attempt #1163 #1116. [tidusjar] + +- Fixup! Reset the branch on v2.1.0 tag to get to a shared state between dev and Master. [distaula] + +- Fixed a bug in the Plex Newsletter. [tidusjar] + +- Typo. [tidusjar] + +- Fixed around the newsletter and a small feature around the permissions/features (#1215) [Jamie] + +- Fixed #1189. [tidusjar] + +- Fixed #1195. [Jamie.Rees] + +- Fixed #1195. [Jamie.Rees] + +- Fixed #1192. [Jamie.Rees] + +- Fixed issue where we could get null rating keys on Plex. [tidusjar] + +- Needed to treat a 201 as success, too. + removed some commented out code. [Shaun McPeck] + +- Normalized spacing/tabs. [smcpeck] + +- Move local user login to be the first thing checked; renamed old Api variable to PlexApi now that Emby is in play. [smcpeck] + +- Remove all the polling/retry logic around HP requests. This was a problem do to not properly awaiting the initial AddArtist API call being sent to HP. Also fix SetAlbumStatus to use ReleaseId instead of MusicBrainsId (same fix previously applied to AddArtist). [smcpeck] + +- Restore checking of HTTP StatusCode on ApiRequests; remove checking of response.ErrorException. [smcpeck] + +- Reverted (for now) non-200 response handling; added some extra logging. [smcpeck] + +- Tweaked ApiRequest behavior on non-200 responses; think it was breaking login. :-" [smcpeck] + +- Only deserialize response payload in ApiRequest when StatusCode == 200. Will a default return value in other cases cause other issues? [smcpeck] + +- Headphones - added releaseID to generic RequestedModel and passing that through to HP request. Their API doesn't request via the MusicBrainzId. [smcpeck] + +- Fixed #1038. [tidusjar] + +- Fixed a slight issue where we could click the change folders button rather than the dropdown arrow #1189. [tidusjar] + +- Bunch of updater files. [tidusjar] + +- #1163 #117. [tidusjar] + +- Removed some unnecessary 'ConfigureAwait` uses. [smcpeck] + +- Remove meaningless html class from actor searching checkbox. [smcpeck] + +- Fixed an issue where we were not always showing movies from external programs. [tidusjar] + +- Remove extra delay when filtering out existing movies. [smcpeck] + +- Post merge build fixes. [smcpeck] + +- Fix. [tidusjar] + +- Fixed #1177. [tidusjar] + +- Fixed #1152. [tidusjar] + +- Fixed #1123. [tidusjar] + +- Fixed a bug when sending to radarr. [tidusjar] + +- Fixed #1133. [tidusjar] + +- Fixed issues img. [Jamie.Rees] + +- Stop Plex being enabled on the first time installing #1048. [Jamie.Rees] + +- The landing page now works for emby #435. [tidusjar] + +- Fixed #1104. [tidusjar] + +- Fixed #1090. [tidusjar] + +- Fixed #1103. [tidusjar] + +- Small changes. [tidusjar] + +- Break out Mass Email feature into its own tab, upgrade Font Awesome and clean up some comments. [dhruvb14] + +- Fix typo. [Travis Bybee] + +- Fixed #1066. [Jamie.Rees] + +- Fixed broken builds. [Jamie.Rees] + +- Fixed #1083. [Jamie.Rees] + +- #1049. [tidusjar] + +- Fixed #1071. [tidusjar] + +- Fixed #1048 #1081. [tidusjar] + +- #1074. [Jamie.Rees] + +- #1069. [Jamie.Rees] + +- Fix for #1068. [tidusjar] + +- Remove duplciate tv show status. [tidusjar] + +- Some request ui changes. [tidusjar] + +- Removed references to Plex. [tidusjar] + +- Removed plex from the scheduled jobs ui. [tidusjar] + +- First run of the newsletter set it to a test. [tidusjar] + +- Reworked the newsletter for Emby! Need to rework it for Plex and use the new way to do it. [tidusjar] + +- Fixed build. [tidusjar] + +- Fixed the mass email, it was only being set to users with the newsletter feature #358. [tidusjar] + +- Removed Plex Request from the notifications. [tidusjar] + +- Finish implementing mass email feature. [dhruvb14] + +- @tidusjar pointed out runtime error!! [dhruvb14] + +- Does not compile, need to get data from UI into nancy somehow and figure out why IMassEmail is not initializing. [dhruvb14] + +- Begin Implementing Mass Email Section. [dhruvb14] + +- Hide the auto update btn #236 Fixed where we were not populating the emby episodes #435. [tidusjar] + +- Fix Radarr labels. [d2dyno] + +- Fixed pace loader. [Jamie.Rees] + +- Check if Emby/Plex is enabled before starting the job. [Jamie.Rees] + +- Fixed #1036. [Jamie.Rees] + +- Fixed a typo and changed wording. [Torkil Liseth] + +- Fixed #1035. [Jamie.Rees] + +- Fix for #1026. [Jamie.Rees] + +- Fixed #1042. [tidusjar] + +- #435. [Jamie.Rees] + +- #435 Started the wizard. [Jamie.Rees] + +- Removed. [tidusjar] + +- Final Fixes. [dhruvb14] + +- Partial fix for broken HR tag's in Email... [dhruvb14] + +- DAMN! #435 that's a lot of code! [tidusjar] + +- Started adding Emby, Lots of backend work done. Need a few more services done and login and user management. #435. [tidusjar] + +- UI changes to add checkbox and support searching for only new matches via new API. [smcpeck] + +- REFACTOR: IAvailabilityChecker - changed arrays to IEnumerables. [smcpeck] + +- UI changes to consume actor searching API. [smcpeck] + +- API changes to allow for searching movies by actor. [smcpeck] + +- Enforcing async/await in synchronous methods that were marked async. [smcpeck] + + +## v2.1.0 (2017-01-31) + +### **New Features** + +- Update README.md. [Jamie] + +- Update .gitattributes. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added the new labels to the search. [tidusjar] + +- Added a switch to use the new search or not, just in case people do not like it. added a migration to turn on the new search. [Jamie.Rees] + +- Added a bunch of categories for tv search similar to what we have for movies. [Jamie.Rees] + +### **Fixes** + +- Fixed typos. [Haries Ramdhani] + +- Fix typo in readme. [tdorsey] + +- Fixed #985. [Jamie.Rees] + +- FIxed #978. [tidusjar] + +- Fixed the approval issue for #939. [tidusjar] + +- Some general improvements. [tidusjar] + +- Turned off migration for now. [tidusjar] + +- Fixed #998. [tidusjar] + +- Additional movie information. [Jamie.Rees] + +- Debug info around the notifications. [Jamie.Rees] + +- Small changes. [tidusjar] + +- Fixed #995. [tidusjar] + +- Fix for #978. [tidusjar] + +- Fixed #991. [tidusjar] + +- Fixed the login issue and pass Radarr the year #990. [Jamie.Rees] + +- More small tweaks around the username/alias. [Jamie.Rees] + +- Possible issue with the empty username. [Jamie.Rees] + +- Potential Fix for #985. [Jamie.Rees] + +- Small changed to the sidebar. [Jamie.Rees] + +- Small changes. [Jamie.Rees] + +- Done #627. [Jamie.Rees] + +- Finished #535 #445 #170. [tidusjar] + +- Fixed tests. [Jamie.Rees] + +- Started to add the specify Sonarr root folders. [Jamie.Rees] + +- Fixed #968. [Jamie.Rees] + +- Fixed #970. [Jamie.Rees] + +- Done #924. [Jamie.Rees] + +- Fixed. [Jamie.Rees] + +- Fixed #955. [Jamie.Rees] + +- #956. [Jamie.Rees] + +- Fixed #947. [Jamie.Rees] + +- #951. [tidusjar] + +- Finished #923 !!! [tidusjar] + +- More for #923. [Jamie.Rees] + +- Radarr integartion in progress #923. [tidusjar] + +- Fixed #940 don't show any shows without a tvdb id. [tidusjar] + +- Finished #739. [Jamie.Rees] + +- Initial impliementation of #739. [Jamie.Rees] + +- Improved the search UI and made it more consistant. Finished the Netflix API Part #884. [Jamie.Rees] + + +## v2.0.1 (2017-01-16) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Added a netflix api. [Jamie.Rees] + +### **Fixes** + +- Fixed #934. [Jamie.Rees] + + +## v2.0 (2017-01-14) + +### **New Features** + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Update README.md. [SuperPotatoMen] + +- Added the settings for #925 but need to apply the settings to the UI. [Jamie.Rees] + +- Changed the settings name from Plex Requests to Ombi. [Jamie.Rees] + +- Added support for Managed Users #811. [Jamie.Rees] + +- Change solution name in travis. [mhann] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +### **Fixes** + +- Finished #925. [Jamie.Rees] + +- Some TODO's. [Jamie.Rees] + +- Fixed #915. [Jamie.Rees] + +- Fixed the issue where notifications are not being sent to users with Aliases #912. [Jamie.Rees] + +- Fixed #891. [Jamie.Rees] + +- Fix indentation issue. [Marcus Hann] + +- Implement simple button. [Marcus Hann] + +- Plex Username Case Sensitivity Fix. [thegame3202] + +- Fixed #882. [Jamie.Rees] + +- Api changed again, so more fixes for #878. [Jamie.Rees] + +- Possible fix for #893. [Jamie.Rees] + +- Fixed #898. [Jamie.Rees] + +- Fixed #878. [TidusJar] + +- * userManagementController.js: fixed #881. [TidusJar] + +- More work on watcher, should all be good now. #878. [Jamie.Rees] + +- Delete PlexRequests.sln.DotSettings. [Jamie] + +- Fixed #862. [Jamie.Rees] + +- #399 and #398 finished. [Jamie.Rees] + +- More work on #399. [Jamie.Rees] + +- Finished #884. [Jamie.Rees] + +- More for #844. [Jamie.Rees] + +- Another #844. [Jamie.Rees] + +- Fixed a dependancy issue with #844. [Jamie.Rees] + +- Finished the main part of #844 just need testing. [Jamie.Rees] + +- Fixed #832. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Fix tiny readme typo. [mhann] + +- Fixed #850 also started #844 (Wrote the API interaction) [Jamie.Rees] + +- #801 #292 done. [Jamie.Rees] + +- Should fix #841 #835 #810. [Jamie.Rees] + +- Fix small typo in ticket overview page. [mhann] + +- More work on the combined login. [Jamie.Rees] + +- Fixed db issue. [Jamie.Rees] + +- Name changes. [Jamie.Rees] + +- All Sln changes. [tidusjar] + +- Moved API Sln dir. [tidusjar] + +- Fixed build. [tidusjar] + +- Moved namespaces. [tidusjar] + +- Renamed zip. [tidusjar] + +- Product name change. [tidusjar] + + +## v1.10.1 (2016-12-17) + +### **Fixes** + +- #788 fixed! [tidusjar] + +- Fixed #788 and #791. [tidusjar] + +- #399 #398. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Small refactorings. [Jamie.Rees] + +- #782. [Jamie.Rees] + +- #785. [Jamie.Rees] + + +## v1.10.0 (2016-12-15) + +### **New Features** + +- Update README.md. [Jamie] + +- Added optional launch args for the auto updater. [Jamie.Rees] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update _Navbar.cshtml. [Jamie] + +- Update README.md. [Jamie] + +- Update _Navbar.cshtml. [Jamie] + +- Update README.md. [Jamie] + +- Added a new permission to bypass the request limit. [Jamie.Rees] + +- Update Version1100.cs. [SuperPotatoMen] + +- Added logging around the Newsletter #717. [Jamie.Rees] + +- Added missing migration. [tidusjar] + +- Added loading spinner. [Jamie.Rees] + +- Update UI.resx. [SuperPotatoMen] + +- Update Version1100.cs. [Jamie] + +- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] + +### **Fixes** + +- Fixed an issue where the HTML in the newsletter was incorrect. [Jamie.Rees] + +- Fixed #201. [Jamie.Rees] + +- Fixed #720 and added better error handling around the migrations. [Jamie.Rees] + +- Fixed #769. [Jamie.Rees] + +- Write out the actual file version. [Jamie.Rees] + +- Error checking around GA. [TidusJar] + +- Fixed #761. [tidusjar] + +- Fixed #749 Fixed an issue where we were adding the read only permission when creating the admin. [tidusjar] + +- Fixed #757. [tidusjar] + +- Fixes around the server admin #754. [Jamie.Rees] + +- Removed the trace option from the UI, it is only accessible when appending the url with "?developer" #753. [Jamie.Rees] + +- Fixed an issue where the admin could not be updated. [Jamie.Rees] + +- Fixed #745. [Jamie.Rees] + +- Fixed #748. [Jamie.Rees] + +- Workaround for #748. [SuperPotatoMen] + +- Another attempt to fix #717. [tidusjar] + +- Fixed #744. [Jamie.Rees] + +- Tidied up the warnings. [Jamie.Rees] + +- Small bit of analytics. [Jamie.Rees] + +- Removed the whitelist. [Jamie.Rees] + +- Should fix #696 Fixed an issue with the scheduled jobs where it could use a different trigger if the order between the schedules and the triggers were in different positions in the array... Stupid me, ordering both arrays by the name now. [tidusjar] + +- Some better null object handling #731. [Jamie.Rees] + +- Small tweaks. [Jamie.Rees] + +- Fixed #728. [Jamie.Rees] + +- Fixed #727. [Jamie.Rees] + +- Fixed admin redirect issue. [tidusjar] + +- Fixed #718. [tidusjar] + +- Lots of small fixes and tweaks. [Jamie.Rees] + +- Tidied up some of the angular code, split the UI into it's own directives for easier maintainability. [Jamie.Rees] + +- Small tweaks to the Request Page. [Jamie.Rees] + +- Reverted the PR that may have caused #619. [Jamie.Rees] + +- Some small tweaks around #218 Just added the link to the settings and some angular improvements. [Jamie.Rees] + +- Test. [Jamie.Rees] + +- Attempt at fixing #686. [Jamie.Rees] + +- Finished #707. [Jamie.Rees] + +- Fixed #704. [Jamie.Rees] + +- Fixed #705. [Jamie.Rees] + +- Fixed #706. [Jamie.Rees] + +- #547. [Jamie.Rees] + +- Default tabs #304. [Jamie.Rees] + +- Fixed #703. [Jamie.Rees] + +- #233. [Jamie.Rees] + +- Done #678. [Jamie.Rees] + +- Fixed #670. [Jamie.Rees] + +- #456 Update all the requests when we identify that the username changes. [Jamie.Rees] + +- More user management. [Jamie.Rees] + +- #218. [Jamie.Rees] + +- Fixed build. [tidusjar] + +- Implimented the features #218. [tidusjar] + +- Use the user alias everywhere if it is set #218. [tidusjar] + +- Implimented auto approve permissions #218. [tidusjar] + +- A. [tidusjar] + +- Fixed an IOC issue. [tidusjar] + +- Fixed the issue with user management, needed to implement our own authentication provider. [Jamie.Rees] + +- Small changes including #666. [Jamie.Rees] + +- Done #679. [tidusjar] + +- Reduce the retry time. [Jamie.Rees] + +- Remove all references to the claims. [Jamie.Rees] + +- Lots of fixed and stuff. [Jamie.Rees] + +- Fixed potential crash #683. [Jamie.Rees] + +- Fixed #681. [Jamie.Rees] + +- More user management. [Jamie.Rees] + +- Finishing off the user management page #218 #359 #195. [Jamie.Rees] + +- Finished #646 and fixed #664. [Jamie.Rees] + +- Started on #646. Fixed #657. [Jamie.Rees] + +- Fixed #665. [Jamie.Rees] + +- Migrate users. [TidusJar] + +- Fixed build. [Jamie.Rees] + +- Convert the for to foreach for better readability. Still need to rework this area. [Jamie.Rees] + +- Final Tweaks #483. [Jamie.Rees] + +- Finished #483. [Jamie.Rees] + +- Finished the queue #483. [Jamie.Rees] + +- Started on the queue for requests #483 TV Requests with missing information has been completed. [Jamie.Rees] + +- Fixed build. [Jamie.Rees] + +- Finished the notification for the fault queue. [Jamie.Rees] + +- Finished #556. [Jamie.Rees] + +- Finished #633 (First part of the queuing) [Jamie.Rees] + +- Finished #659 #236 has been modified slightly. Needs testing on Different systems. [Jamie.Rees] + +- Almost finished #659. [Jamie.Rees] + +- Started on #483. [Jamie.Rees] + +- #544. [Jamie.Rees] + +- Fixed #656 and more work on #218. [Jamie.Rees] + +- Fixed some issues with the user management work. [TidusJar] + +- Fixed build issue. [TidusJar] + +- User perms. [Jamie.Rees] + + +## v1.9.7 (2016-11-02) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Potential fix for #629. [TidusJar] + +- Fixed an issue to stop blatting over the base url. [tidusjar] + +- Fixed #643. [TidusJar] + +- Fixed #622. [TidusJar] + + +## v1.9.6 (2016-10-28) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Fixed #586. [Jamie.Rees] + +- Fixed #622. [Jamie.Rees] + +- Fixed #621. [Jamie.Rees] + + +## v1.9.5 (2016-10-27) + +### **New Features** + +- Added our own custom migrations, a lot easier to migrate DB versions now. [tidusjar] + +### **Fixes** + +- Bump version. [Jamie.Rees] + +- Small bit of work on the user claims. [Jamie.Rees] + +- Fix #612 again. [Jamie.Rees] + +- User management styling. [Jamie.Rees] + +- Fixed #608 and some other small stuff. [tidusjar] + +- More user mapping. [tidusjar] + +- Fixed #615. [tidusjar] + +- Fixed #610. [tidusjar] + +- User management stuff. [Jamie.Rees] + +- User management work. [Jamie.Rees] + +- Revert the TVSender to use the old code. [Jamie.Rees] + +- Fixed the view issue. [tidusjar] + +- S582: admin improvements part 2. [Jim MacKenzie] + +- Fix #612. [Jamie.Rees] + +- User management, migration and newsletter. [Jamie.Rees] + +- #602 recently added improvements. [tidusjar] + +- Revert "Sorting out the current state of migrations" [Jamie.Rees] + +- Sorting out the current state of migrations. [Jamie.Rees] + +- Marked as obsolete. [Jim MacKenzie] + +- Migration setup. [Jim MacKenzie] + +- Removed extra line breaks. [Jim MacKenzie] + +- Moved Newsletter Settings to its own page. [Jim MacKenzie] + +- Reverted TMDB package. [Jamie.Rees] + +- Remove DB Option. [Jamie.Rees] + +- Upgrade the movie DB package and fixed #370 To fix this I had to make another API call... It slows down the search... [tidusjar] + +- Lots of small fixes including #475. [tidusjar] + +- A better fix for #587. [tidusjar] + +- Fixed #553. [tidusjar] + +- #601. [Jamie.Rees] + +- More rework to use the Plex DB. [Jamie.Rees] + +- More work around using the PlexDatabase. [Jamie.Rees] + +- Plex DB. [Jamie.Rees] + +- Allow to process even know we had an error #578. [Jamie.Rees] + +- Fix boostrapper-datetimepicker imports (#586) [David Torosyan] + +- Potential work around for #587. [tidusjar] + +- Fixed #589. [tidusjar] + + +## v1.9.4 (2016-10-10) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Added Paypalme options, no UI yet (#568) [Jim MacKenize] + +- Update appveyor.yml. [Jamie] + +- Update README.md. [Jamie] + +### **Fixes** + +- Reverted. [tidusjar] + +- Make sure it's enabled before sending the recently added. [tidusjar] + +- Moved the HR inside the table for TV Shows. [Jamie.Rees] + +- FIXED!!!!! YES BITCH! #550. [tidusjar] + +- Moved the horizontal rules inside the table row. [tidusjar] + + +## v1.9.3 (2016-10-09) + +### **New Features** + +- Added properties to disable tv requests for specific episodes or seasons and wired up to admin settings. [Matt McHughes] + +- Added different sonarr search commands. [tidusjar] + +### **Fixes** + +- Fixed #515. [tidusjar] + +- Fixed #561 and a small bit of work on #569. [tidusjar] + +- #569. [tidusjar] + +- Fixed case typo. [Matt McHughes] + +- Finished wiring tv request settings to tv search. [Matt McHughes] + +- WIP hide tv request options based on admin settings. [Matt McHughes] + +- Set meta charset to be utf-8. [Madeleine Schönemann] + +- F#552: updated labels text. [Jim MacKenize] + +- F#552: Re-design lables. [Jim MacKenzie] + +- Last correction.. Now the translation is ready to be used. [Michael Reber] + +- Forgot to correct two incorrect translations. [Michael Reber] + +- Correction of the German translation. [Michael Reber] + +- Notification improvements. [tidusjar] + +- #515. [tidusjar] + + +## v1.9.2 (2016-09-18) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update CouchPotatoCacher.cs. [Jamie] + +- Added some error handing around the GetMovie area #517. [tidusjar] + +- Added a version endpoint in "/api/version" #529. [tidusjar] + +### **Fixes** + +- Trying to fix the auto CP. [tidusjar] + +- Increase the notice message text box #527. [tidusjar] + +- #536 this should fix notification settings when it is being unsubscribed when testing. [tidusjar] + +- Improved how the TV search looks and feels. [tidusjar] + +- Fix for reverse proxy when using the wizard. [Devin Buhl] + +- Fixed #532. [tidusjar] + +- This should fix some issues with the episode requests #514. [tidusjar] + +- Small changes around existing series. [tidusjar] + +- Fixed #514 and the unit tests. [tidusjar] + +- If there is a bad password when changing it, we now inform the user. [tidusjar] + +- When logging out as admin remove the username from the session. [tidusjar] + +- Sorted out some of the UI for #18. [tidusjar] + +- Finished #18. [tidusjar] + + +## v1.9.1 (2016-08-30) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Added french to the navbar. [tidusjar] + +- Changed the way we use the setTimeout function. Should fix #403 #491 #492. [tidusjar] + +- Change the redirection to use a relative uri redirect #473. [tidusjar] + +### **Fixes** + +- Fixed tests. [tidusjar] + +- Fixed #491 and added more logging around the email messages under the Info level. [tidusjar] + +- Finished #415. [tidusjar] + +- Fixed an issue where there were some JS errors on the landing page settings and stopped us being redirected to the login sometimes as an admin. [tidusjar] + +- Fixed #480. [tidusjar] + +- User management. [tidusjar] + +- Fixed #505. [tidusjar] + +- Append the application version to the end of our JS/CSS files. [tidusjar] + +- Fixed issue #487. [tidusjar] + +- Remove the datetime picker css from the main assets block and only load it on the pages it needs. #493. [tidusjar] + +- Redirect to search if we are already logged in #488. [tidusjar] + +- Fixed build. [tidusjar] + +- Fixed an issue where you could set the base url as requests #479. [tidusjar] + +- Working on the beta releases page and also the user management. [tidusjar] + +- User work. [tidusjar] + + +## v1.9.0 (2016-08-18) + +### **New Features** + +- Update the availability checker to search for TV Episodes. [tidusjar] + +- Changed the no TVMazeid message. [tidusjar] + +- Added an option to disable/enable the Plex episode cacher. [tidusjar] + +- Updated the episode cacher to have a minimum of 11 hours before it runs again. [tidusjar] + +- Added some useful analytical infomation around the wizard. [tidusjar] + +- Updated the German translations #402. [tidusjar] + +- Added some code to shrink the DB. reworked the search to speed it up. [tidusjar] + +- Change to use the GrandparentTitle rather than the thumbnail.... facepalm. [tidusjar] + +- Change the interval to hours! [tidusjar] + +- Added the transaction back into the DB. Do not run the episode cacher if it's been run in the last hour. [tidusjar] + +- Added logging. [tidusjar] + +- Changed the query slightly. [tidusjar] + +- Updated Newtonsoft.Json, Autofixture, Nlog and Dapper packages. [tidusjar] + +- Added the Sonarr check for episodes #254. [tidusjar] + +- Added unit tests. [tidusjar] + +- Added #436. [tidusjar] + +- Update build no. [tidusjar] + +- Updated translations for #402. [tidusjar] + +- Added a beta module. [tidusjar] + +- Added a custom debug root path provider, this means we do not have to recompile the views every time we make a view change. [tidusjar] + +- Update .gitignore. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added tests for the string hash. [tidusjar] + +- Added code to request the api key for CouchPotato. [tidusjar] + +- Added the file version to the layout. [tidusjar] + +- Update appveyor.yml. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added automation tests. [tidusjar] + +- Update appveyor.yml. [Jamie] + +- Updated packages. [tidusjar] + +- Updated Polly. [tidusjar] + +- Updated Fr, IT and NL translations #402. [tidusjar] + +- Changed the way the donate button works for #414. [tidusjar] + +- Added MediatR. [tidusjar] + +### **Fixes** + +- User management stuff. [tidusjar] + +- Fixed! [tidusjar] + +- Small amount of work on the user management. [tidusjar] + +- Fixed #466. [tidusjar] + +- Fixes. [tidusjar] + +- Made the episode request better. [tidusjar] + +- Removed commented out tests. [tidusjar] + +- Fixed the bad test after the merge. [tidusjar] + +- Reworked #466. [tidusjar] + +- More unit tests around the login and also the core Plex Checker. [tidusjar] + +- Potentially fixed the issue where we were requesting everything that was also available now. [tidusjar] + +- This should fix #466. [tidusjar] + +- Attempt at fixing a potential bug found from #466. [tidusjar] + +- #464 fixed. [tidusjar] + +- Fixed the build. [tidusjar] + +- Small improvements to the wizard. [tidusjar] + +- Always set the wizard to be true when editing the Plex Requests settings (Since the flag is not in the UI, a bool defaults to false). [tidusjar] + +- Tiny bit of more info. [tidusjar] + +- Finished #459. [tidusjar] + +- #459 is almost done. [tidusjar] + +- Modified the episode modal so that we are now resetting the button after a request. [tidusjar] + +- Commented out the transaction for now to debug it. [tidusjar] + +- Since we are multithreading, we should use a threadsafe type to store the episodes to prevent any threading or race conditions. [tidusjar] + +- Wrapped the bulk insert inside a transaction. [tidusjar] + +- Made the episode check parallel. [tidusjar] + +- Log out the GUID causing the issue. [tidusjar] + +- Fixed another test. [tidusjar] + +- Fixed tests. [tidusjar] + +- Got mostly everything working for #254 Ready for testing. [tidusjar] + +- Fixed issue with saving to db. [tidusjar] + +- Need to work out why the cacher is not working and where the datatype mismatch is. [tidusjar] + +- Don't delete first. [tidusjar] + +- Fix the log path issue #451. [tidusjar] + +- Dump an item. [tidusjar] + +- Small change with the return value in the batch insert. [tidusjar] + +- #254 Removed the cache, we are now storing the plex information into the database. [tidusjar] + +- Small change in the episode saver. [tidusjar] + +- Some small tweaks to improve the memory alloc. [tidusjar] + +- Short circuit when Plex hasn't been setup. Added Miniprofiler. [tidusjar] + +- Consolidate newtonsoft.json packages. [tidusjar] + +- Some performance improvements around the new TV stuff. [tidusjar] + +- Reworked the cacher, fixed the memory leak. No more logging within tight loops. [tidusjar] + +- Another null check. [tidusjar] + +- Some more changes. [tidusjar] + +- Some error handling. [tidusjar] + +- Check if the sonarr ep is monitored. [tidusjar] + +- Some logging. [tidusjar] + +- Small changes, we will actually see the episode cacher on the scheduled jobs page now. [tidusjar] + +- Work on the UI to show what episodes have been requested #254. [tidusjar] + +- Small fix. [tidusjar] + +- Fix the api change in #450. [tidusjar] + +- #254. [tidusjar] + +- Workaround for #440. [tidusjar] + +- Async async async improvements. [tidusjar] + +- Finished #266 Added a new cacher job to cache all episodes in Plex. [tidusjar] + +- Fixed #442. [tidusjar] + +- #254. [tidusjar] + +- Work around the sonarr bug #254. [tidusjar] + +- #254 having an issue with Sonarr. [tidusjar] + +- Small bit of work on #266. [tidusjar] + +- #254. [tidusjar] + +- Precheck and disable the episode boxes if we already have requested it. TODO check sonarr to see if it's already there. #254. [tidusjar] + +- Fixed broken build. [tidusjar] + +- More work for #254. [tidusjar] + +- More work on #254. [tidusjar] + +- Fixed the bug in #438 and added unit tests to make so we dont break it in the future. [tidusjar] + +- Some reason we had dupe translations. [tidusjar] + +- Rename SubDir to Base Url. [tidusjar] + +- Fix the exception in #440. [tidusjar] + +- Reworking the login page for #426. [tidusjar] + +- Fixed #438. [tidusjar] + +- Finished the auth stuff. [tidusjar] + +- Finished up the SMTP side of #429. [tidusjar] + +- #428 Added a message when the we cannot get a TVMaze ID. [tidusjar] + +- #254 MOSTLY DONE! At last, this took a while. [tidusjar] + +- Removed the other rootpath provider. [TidusJar] + +- Removed the other rootpath provider. [TidusJar] + +- Removed the other rootpath provider. [TidusJar] + +- Should fix #429. [TidusJar] + +- Done #135 We are including the application version number in the directory. [tidusjar] + +- #387 trim the spaces from the api key. Tidied up the setting models a bit. [tidusjar] + +- Wrapped the repo to catch Sqlite corrupt messages. [tidusjar] + +- Frontend and tv episodes api work for #254. [tidusjar] + +- #424. [tidusjar] + +- #359. [tidusjar] + +- Moved the plex auth token to the plex settings where it should belong. [tidusjar] + +- Small changes around the user management. [tidusjar] + +- Missed brace. [tidusjar] + +- Removed. [tidusjar] + +- Fixed issues from the merge. [tidusjar] + +- Stupid &$(*£ merge. [tidusjar] + +- Angular. [tidusjar] + +- Reworked the custom notifications... again. Need to figure out how to find the view to the model. [tidusjar] + +- Fixed #417. [tidusjar] + +- Removed NinjectConventions, we hadn't started to use it anyway. [tidusjar] + +- Fixed the way we will be using custom messages. [tidusjar] + +- Test checkin. [tidusjar] + +- Better handling for #388. [tidusjar] + +- Fixed #412. [tidusjar] + +- Fixed #413. [tidusjar] + +- Fixed #409. [tidusjar] + +- Trycatch around the availbility checker. [tidusjar] + +- WIP on notification resolver. [tidusjar] + +- Tidy. [tidusjar] + +- Plugged in MediatR. [tidusjar] + +- Moved over to using Ninject. [tidusjar] + + +## v1.8.4 (2016-06-30) + +### **Fixes** + +- Fixed the bug where we were auto approving everything. Added French language into the navigation bar. [tidusjar] + + +## v1.8.3 (2016-06-29) + +### **New Features** + +- Update README.md. [Jamie] + +- Update appveyor.yml. [Jamie] + +- Added some of the backend bits for #182. [tidusjar] + +- Updates for #243. [tidusjar] + +- Added Dutch language #243. [tidusjar] + +- Added languages #243. [tidusjar] + +- Added logging #350. [tidusjar] + +### **Fixes** + +- Small changes. [tidusjar] + +- Allow html in the notice message. [tidusjar] + +- Some more unit tests around the NotificationMessageResolver. [tidusjar] + +- Fixed a timing bug found the in build. Note, when working with time differences use TotalDays. [tidusjar] + +- More translations on the search page (Mainly the notification messages) #243. [tidusjar] + +- Fixed some warnings. [tidusjar] + +- CodeCleanup. [tidusjar] + +- Fixed a bit of a stupid bug in the resetter and added unit tests around it to make sure this never happens again. [tidusjar] + +- Fixed an issue where we didn't provide the correct response when clearing the logs. [tidusjar] + +- Made it so users that are in the whitelist do not have a request limit. [tidusjar] + +- Made it so the request limit doesn't apply to admin users. [tidusjar] + +- Fixed where a user could see the delete button on the issues page. [tidusjar] + +- Fixed some small issues and improved the navbar. [tidusjar] + +- Translated the Requested page #243. [tidusjar] + +- Finished #337. [tidusjar] + +- Some analytics. [tidusjar] + +- More translations for #243 and welcome text for #293. [tidusjar] + +- Small bit of work for #359. [tidusjar] + +- Finished #6. [tidusjar] + +- Analytics and fixes. [tidusjar] + +- Translated the search page #243. [tidusjar] + +- Implemented the different languages and added the ability to change cultures. #243. [tidusjar] + +- Started #243. [tidusjar] + +- Fixed #364. [tidusjar] + +- Some more useful analytical information. [tidusjar] + +- Generic try catch to fix #350. [tidusjar] + +- Slight changes, moved the donate button. [tidusjar] + +- Potential fix for #350. [tidusjar] + +- Better way of obtaining clean enum string. [Drewster727] + +- Fixed #362. [tidusjar] + + +## v1.8.2 (2016-06-22) + +### **New Features** + +- Update readme. [tidusjar] + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Fixed a circular reference issue. [tidusjar] + +- Small changes around how we work with custom events in the analytics. [tidusjar] + +- Fixed #353 #354 #355. [tidusjar] + +- Null provider check for movies. [Drewster727] + +- Show request type in notifications #346 and fix an issue from previous commit for #345. [Drewster727] + +- Add an option to stop sending notifications for requests that don't require approval #345. [Drewster727] + + +## v1.8.1 (2016-06-21) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Fix obj ref error when scheduler runs (ProviderId is null?) [Drewster727] + +- Fix logic for obtaining a sonarr quality profile #340. [Drewster727] + + +## v1.8.0 (2016-06-21) + +### **New Features** + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added the new advanced search into the search page too. [tidusjar] + +- Change the way we configure the IoC container in the bootstrapper, we are registering all the concrete instances on application start rather than on each web request. This should increase the performance per HTTP request. [tidusjar] + +- Updated nlog and fixed #295. [tidusjar] + +### **Fixes** + +- Workaround for #334. [Drewster727] + +- Create .gitattributes. [Jamie] + +- Fixes to the issues. [tidusjar] + +- Set the defaults for the landing page. [tidusjar] + +- Revert branch to 664dae2. [tidusjar] + +- Some unit tests for the issues. [tidusjar] + +- Tidied up the bootstrapper. [tidusjar] + +- Fix up landing page UI. [Drewster727] + +- Fixed CSS issue with the top arrow in the Plex theme. [tidusjar] + +- Small changes. [tidusjar] + +- Done #318. [tidusjar] + +- Fixed tests. [tidusjar] + +- #298 added some tests for the landing page. [tidusjar] + +- We are now only keeping the latest 1000 log records in the database. Delete everything else. [tidusjar] + +- Some analytic stuff. [tidusjar] + +- Capture the TVDBID when requesting. [tidusjar] + +- Attempting to improve #219. [tidusjar] + +- Just some more async changes. [tidusjar] + +- Small changes. [tidusjar] + +- More work on #298. Everything wired up. [tidusjar] + +- Fixed the issue on the landing page #298. [tidusjar] + +- #298 moved the content to the left a bit. [tidusjar] + +- Styling for #298 done, just need to wire up the model and do the actual status check. [tidusjar] + +- Bumped up the version number. [tidusjar] + +- Removed some DumpJson() from the trace logs. [tidusjar] + +- Small ui fix (100% width user/password fields to improve mobile experience) [Drewster727] + +- Landing page stuff #298. [tidusjar] + +- Datepicker UI fixes + small landing page UI fix. [Drewster727] + +- Removed a change that shoudn't have been commited. [tidusjar] + +- Fixed tests. [tidusjar] + +- More work for #298. [tidusjar] + +- #273 added for only available content on the search. [tidusjar] + +- Fixed #303 Looks like there was some incorrect business logic. [tidusjar] + +- Most of #273 done. [tidusjar] + +- Settings done for #298. [tidusjar] + +- Started #298. [tidusjar] + +- A crap tonne of work on #273. [tidusjar] + +- More work on #273. [tidusjar] + +- Reduced kept logs for 2 days. [tidusjar] + +- Fixed #300. [tidusjar] + +- #273. [tidusjar] + +- Fixed a bug with some users with the CP profiles. [tidusjar] + +- #273. [tidusjar] + +- Done the same for TV. [tidusjar] + +- Fixes #296. [tidusjar] + +- More for #273. [tidusjar] + +- Small changes. [tidusjar] + +- Revert "Small changes" [tidusjar] + +- Small changes. [tidusjar] + +- Finished #221 and added more async #278. [tidusjar] + +- Spelling mistake in the html! this fixes #264. [tidusjar] + +- More work on #273. [tidusjar] + +- Fixed #210. [tidusjar] + +- Started #273. [tidusjar] + + +## v1.7.5 (2016-05-29) + +### **New Features** + +- Update preview. [Jamie] + +- Updated dapper.contrib. Looks like there was a bug in the async methods. [tidusjar] + +- Updater wouldn't work when running a reverse proxy #236. [tidusjar] + +### **Fixes** + +- Bump build ver. [tidusjar] + +- Use HTTPS for the poster images, so there aren't any mixed content warnings when serving the application via an HTTPS reverse proxy. [Sean Callinan] + +- Removed static declarations. [tidusjar] + +- Fixed styling on modal. [tidusjar] + +- Made the search page all async goodness #278. [tidusjar] + +- Made the request module async #278. [tidusjar] + +- Started some dynamic scrolling. [tidusjar] + +- Stop dumping out the settings to the log. [tidusjar] + +- Made more async goodness. [tidusjar] + +- Made some of the searching async #278. [tidusjar] + +- Fixed #277. [tidusjar] + +- Reworked some tests. [tidusjar] + +- #26q make the auth users list taller. [Drewster727] + +- Fix 404 error. [Drewster727] + +- #262 make the auth users list taller. [Drewster727] + +- #221 delete requests per category. [Drewster727] + +- #256 #237 UI Improvements and consolidation. [Drewster727] + +- Fixed a bug in the user notification where if an admin wants to be notified they wouldn't be. [tidusjar] + +- Set the admin to have all claims. [tidusjar] + +- Fix null exception possibility in cp/sickrage cacher classes. [Drewster727] + +- Fixed #244. [tidusjar] + +- Fixed #240. [tidusjar] + +- Fixed #270. [tidusjar] + +- Fixed an issue where if you have only 1 plex friend it would not show in the list. [tidusjar] + + +## v1.7.4 (2016-05-25) + +### **New Features** + +- Update README.md. [Jamie] + +### **Fixes** + +- Fixed #252. [tidusjar] + +- Fixed #428. [tidusjar] + +- Version bump. [tidusjar] + +- Fixed tests. [tidusjar] + +- Fully fixed #239. [tidusjar] + +- We wan't updating the DB schema. [tidusjar] + + +## v1.7.3 (2016-05-25) + +### **Fixes** + +- Fixed the release build issue where we could not access the settings #239. [tidusjar] + + +## v1.7.2 (2016-05-25) + +### **Fixes** + +- Fixed a small bug where an exception would get thrown. [tidusjar] + +- Build version bump. [tidusjar] + +- Cleanup. [tidusjar] + +- Typo. [tidusjar] + +- Fixed #241. [tidusjar] + +- Fixed #239. [tidusjar] + +- Fixed #238. [tidusjar] + +- Small UI tweaks/improvements. [Drewster727] + + +## v1.7.1 (2016-05-24) + +### **New Features** + +- Update version. [tidusjar] + +### **Fixes** + +- Fixed an issue with the auth page when running with a reverse proxy. [tidusjar] + + +## v1.7 (2016-05-24) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added the ability to get the apikey from the api if you provide a correct username and password. Added more unit tests Added the ability to change a users password using the api refactored the Usermapper and made it unit testsable. [tidusjar] + +- Update. [tidusjar] + +- Added in an audit table. Since we are now allowing multiple users to change and modify things we need to audit this. [TidusJar] + +- Added the updater to the soloution and did a bit of starting code. [TidusJar] + +- Updated the claims so we can support more users. Added a user management section (not yet complete) Added the api to the solution and a api key in the settings (currently only gets the requests). [TidusJar] + +- Updated packages. [TidusJar] + +- Added a retry handler into the solution. We can now retry failed api requests. [TidusJar] + +- Update README.md. [Jamie] + +- Added Released propety to RequestViewModel. Added Released filter to the Requests page. [Chris Lees] + +- Added #27 to albums. [tidusjar] + +- Added the actual notification part of #27. [tidusjar] + +- Added the missing baseurl bit on the login page for #72. [tidusjar] + +- Added the 'enable user notifications' to the email settings view and model. [tidusjar] + +- Update README.md. [Jamie] + +### **Fixes** + +- Remove pointless test, change the default theme and fix a small bug. [tidusjar] + +- Fixed api. [tidusjar] + +- Finished #26. [tidusjar] + +- Plex theme. [tidusjar] + +- Implimented a theme changer, waiting for the Plex theme. [tidusjar] + +- Finished #222 #205. [tidusjar] + +- Started working on #26. [tidusjar] + +- Undid some small changes that was checked in by accident. [tidusjar] + +- #164 has been resolved. [tidusjar] + +- Resolved #224 , Removed the 'SSL' option from the email notification settings. We will now use the correct secure socket options (SSL/TLS) for your email host. [tidusjar] + +- Small changes. [tidusjar] + +- #27 fully finished. [tidusjar] + +- Fixed #215. [tidusjar] + +- Using Mailkit to fix #204. [tidusjar] + +- Color. [tidusjar] + +- Fully finished #27 just need to test it! [tidusjar] + +- Fixed test. [tidusjar] + +- Styling for #27. [tidusjar] + +- I think the auto updater is finished! #29. [tidusjar] + +- I think we have finished the main bulk of the auto updater #29. [tidusjar] + +- #222 #205 more ! Started getting the settings out. [tidusjar] + +- Removed the service locator from the base classes and added in some Api tests added all the tests back in! [tidusjar] + +- More work on the api and documentation #222 #205. [tidusjar] + +- Started documenting the API we now have swagger under ~/apidocs #222 #205. [tidusjar] + +- Api work for #205 Refactored how we check if the user has a valid api key Added POST request, PUT and DELTE. [tidusjar] + +- First pass of the updater working. #29. [tidusjar] + +- Removed SIGHUP from the termination list #220. [tidusjar] + +- Fixed. [tidusjar] + +- Missing. [tidusjar] + +- Missed out a file. [TidusJar] + +- And some more... [TidusJar] + +- Missed some files. [TidusJar] + +- A bit more work on switching to using user claims so we can support multiple users. [TidusJar] + +- Made the store backup clean up some of the older backups (> 7 days). [TidusJar] + +- More work on the user management. [TidusJar] + +- - Notifications will no longer be send to the admins if they request something. - Looks like we missed out adding the notifications to Music requests, so I added that in. [TidusJar] + +- - Improved the RetryHandler. - Made the tester buttons on the settings pages a bit more robust and added an indication when it's testing (spinner) [TidusJar] + +- Packages. [TidusJar] + +- Nm, [TidusJar] + +- Downgraded packages. [TidusJar] + +- Better handling for #202. [TidusJar] + +- Finished #208 and #202. [TidusJar] + +- This should help #202. [TidusJar] + +- Resolved #209. [TidusJar] + +- Finished #209. [TidusJar] + +- Slight adjustments to #189. [tidusjar] + +- - Added a visual indication on the UI to tell the admin there is a update available. - We are now also recording the last scheduled run in the database. [tidusjar] + +- Did the login bit on #185. [tidusjar] + +- Finished #186. [tidusjar] + +- Fixed #185. [tidusjar] + +- Fixed issue in #27 with albums. [tidusjar] + +- #27 added TV Search to the notification. [tidusjar] + +- Fixed bug. [tidusjar] + +- More work on #27 Added a new notify button to the search UI (Needs styling). Also fixed a bug where if the user could only see their own requests, if they search for something that has been requested, it will show as requested. [tidusjar] + +- Improved the startup of the application. We now properaly parse any args passed into the console. [tidusjar] + +- Additional cacher error handling + don't bother checking the requests when we don't get data back from plex. [Drewster727] + +- Remove old migration code and added new migration code. [tidusjar] + +- Stop the Cachers from bombing out when the response from the 3rd party api returns an exception or invalid response. #171. [tidusjar] + +- Increase the scheduler cache timeframe to avoid losing cache when the remote api endpoints go offline (due to a reboot or some other reason) -- if they're online, the cache will get refreshed every 10 minutes like normal. [Drewster727] + +- Fix the cacher by adding locking + extra logging in the plex checker + use a const key for scheduler caching time. [Drewster727] + +- Small changes. [tidusjar] + +- Switched out the schedulers, this seems to be a better implimentation to the previous and is easier to add new "jobs" in. [tidusjar] + +- Fixed #168. [tidusjar] + +- Fixed #162. [tidusjar] + +- Fix saving the log level. [Drewster727] + +- Set the max json length (fixes large json response errors) [Drewster727] + + +## v1.6.1 (2016-04-16) + +### **New Features** + +- Update README.md. [Jamie] + +- Added a url base. [tidusjar] + +- Change default logging. [tidusjar] + +- Added logging around SickRage. [tidusjar] + +### **Fixes** + +- Bump up the version number ready for the release. [tidusjar] + +- BaseUrl is finally finished! #72. [tidusjar] + +- #72 Login page done. [tidusjar] + +- More changes for the urlbase #72. [tidusjar] + +- Done the auth, cp, logs and sidebar for #72. [tidusjar] + +- Add an extra check when determining if a tv show is already available (also check if it starts with the show name returned from the tv db) [Drewster727] + +- Cache plex library data regardless of whether we have requests in the database or not. [Drewster727] + +- By default don't use a url base. [tidusjar] + +- Return empty array when obtaining queued IDs in sickrage cacher. [Drewster727] + +- Fixed a small bug in the SR cacher. [tidusjar] + +- Fixed when we do not have a base. [tidusjar] + +- More changes for #72. [tidusjar] + +- Fixed exception and all areas will now use the base url #72. [tidusjar] + +- Removed the test code from #72. [tidusjar] + +- Commented out the unit tests as they need to be reworked now. [tidusjar] + +- Finally fixed #72. [tidusjar] + +- Remove test code from plex api GetLibrary method. [Drewster727] + +- Finished up the caching TODO's. [tidusjar] + +- Kick off the schedulers once the web app has started (fixes api errors on start) [Drewster727] + +- Converted the UI back down to .NET 4.5.2. [tidusjar] + +- Fixed #154. [tidusjar] + +- Revert everything (except PlexRequests.UI) back to .NET 4.5.2 -- fixes incompatibilities with the latest version of mono (4.2.3.4) -- fixes notifications not working #152 #147 #141. [Drewster727] + +- #150 start caching plex media as well. refactored the availability checker. NEEDS TESTING. also, we need to make the Requests hit the plex api directly rather than hitting the cache as it does now. [Drewster727] + +- #150 split out the cache subscriptions to make sure they subscribe properly. [Drewster727] + +- #150 sonarr/sickrage cache checking. sickrage has a couple small items left. [Drewster727] + +- Fixed args. [tidusjar] + +- Fixed. [tidusjar] + +- Made the base better. [tidusjar] + +- Remove couchpotato api test code. [Drewster727] + +- Start the initial couchpotato cache call on a separate thread to keep the startup process quick. [Drewster727] + +- Add csproj with file changes from previous commit. [Drewster727] + +- Cache the couchpotato wanted list, update it on an interval, and use it to determine if a movie has been queued already. [Drewster727] + +- I think i've fixed an issue where SickRage reports Show not found. [tidusjar] + +- Set the default log level to info. #141. [tidusjar] + +- #125 refactor async task logic to work with mono. [Drewster727] + +- Fix search spinner sticking around after clearing search text + make the "Requested" and "Available" indicators in the search page different colors. [Drewster727] + +- #125 start indicating in the results if an item is already requested or available. [Drewster727] + +- #145 firefox css dsplay issue. [Drewster727] + +- Fixes for sonarr, we now display the error messages back to the user. [tidusjar] + +- Fixed #144. [tidusjar] + + +## v1.6.0 (2016-04-06) + +### **New Features** + +- Changed the build number. [tidusjar] + +- Update README.md. [Drew] + +- Update README.md. [Drew] + +- Update README.md. [Drew] + +- Update README.md. [Drew] + +- Changed the title to a contains but the artist still must match, [tidusjar] + +- Added unit tests to cover the new changes to the availability checker. [tidusjar] + +- Added the music check in the Plex Checker. [tidusjar] + +- Changed around the startup so we cache the profiles after the DB has been created. [tidusjar] + +- Updated where we update the request blobs schema change. [tidusjar] + +- Update SearchModule.cs. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Change the new columns type. [tidusjar] + +- Added a DBSchema so we have an easier way to update the DB. [tidusjar] + +- Added an issue template. [tidusjar] + +- Update README.md. [Jamie] + +- Added back the username into the Session when the admin logs in. This means they do not have to log in twice. [tidusjar] + +- Added happy path tests for the Checker. [tidusjar] + +- Added music to the search and requests page. [tidusjar] + +- Added a scroll to the top thingy and a bit more work on headphones. [tidusjar] + +- Added some tests and fixed the issue where the DB would get created in the wrong place depending on how you launched the application. [tidusjar] + +- Added the settings page for #32. [tidusjar] + +- Update README.md. [Drewster727] + +- Update README.md. [Drewster727] + +- Update README.md. [Drewster727] + +- Update README.md. [Drewster727] + +- Update README.md. [Drewster727] + +- Update appveyor.yml. [Jamie] + +### **Fixes** + +- Some final tweaks for #32. [tidusjar] + +- Fixed a bug where if we are the admin we didn't add the request to the db. [tidusjar] + +- Fixed an issue where we would add the Sickrage series but it would fail on adding the seasons. [tidusjar] + +- Properly account for future/past dates when humanizing with moment. [Drewster727] + +- Properly display release date on requests page. [Drewster727] + +- Add missing reference for release mode. [Drewster727] + +- #139 remove dependency and usage of humanize() - should help with cross-platform issues. start using moment.js. [Drewster727] + +- Fix selectors for music list on request page to get sorting working. [Drewster727] + +- Fixed the error #32. [tidusjar] + +- Fixed the logs page. [tidusjar] + +- Another attempt at filtering #32. [tidusjar] + +- A bit more error handling #32. [tidusjar] + +- Improved the availabilty check to include music results #32. [tidusjar] + +- Small changes for #32. [tidusjar] + +- A bit more logging for #32. [tidusjar] + +- More headphones #32 I am starting to hate headphones... Sometimes the artists and albums just randomly fail. [tidusjar] + +- #134 temporary workaround for this. [Drewster727] + +- Task.run for startup caching + fix admin module unit test failures. [Drewster727] + +- Cache injection, error handling and logging on startup, etc. [Drewster727] + +- Tweaks for #32. [tidusjar] + +- #132 auto-approve for admins. [Drewster727] + +- Finished the bulk work for Headphones. Needs testing #32. [tidusjar] + +- Made the album search 10x faster. We are now loading the images in a seperate call. #32. [tidusjar] + +- Add a reference to API Interfaces to fix the build. [tidusjar] + +- #114 start caching quality profiles. Set the cache on startup and when obtaining quality profiles in settings. [Drewster727] + +- Work for #32. [tidusjar] + +- #114 first pass at choosing quality profile when approving + focus search input by default and when switching tabs. [Drewster727] + +- #131 fix for default selected tab. [Drewster727] + +- Remove references to obsolete RequestedBy property + start setting the db schema to the app version, and check that in the future for migrations. [Drewster727] + +- Fixed async issue. [Shannon Barrett] + +- Updating SickRage api to verify Season List is up to date. [Shannon Barrett] + +- Work on showing the requests for #32. [tidusjar] + +- Got the search finished up for #32. [tidusjar] + +- Remove test/temp code in UserLoginModule. [Drewster727] + +- A bit more work on #32 started working on requesting it. The DB is a bit of an issue... [tidusjar] + +- Most of the UI work done for #32. [tidusjar] + +- Basic search working for #32. [tidusjar] + +- Mono datetime offset workaround. [Drewster727] + +- #122 store utc time in the databse + obtain timezone offset of the client upon login + offset times returned to client based on session offset. [Drewster727] + +- Method reference bug fix. [Drewster727] + +- Fix search focus z-index issue (hid suggestions options) [Drewster727] + +- Minor search UI adjustments. [Drewster727] + +- #55 first attempt at "suggestions" starting with "Comming Soon" and "In Theaters" [Drewster727] + +- #106 rename sorting options and polish the dropdown UI a bit. [Drewster727] + +- Started adding the api part for headphones #32. [tidusjar] + +- Upped the time of #123. [tidusjar] + +- First attempt at #123. [tidusjar] + +- We now do not show the text Requested By to the user, we also show a 'success' message instead of a warning when something has already been requested. [tidusjar] + +- Show a "no requests yet" message on the requests page (for each cateogory) [Drewster727] + +- Ignore items that are already available when approving in bulk, and simplify the checking + compile css. [Drewster727] + +- Add a better way to merge RequestedBy and RequestedUsers to avoid code duplication and simplify checks. [Drewster727] + +- Don't query the session as much in the modules, rely on a variable from the base class and store the username as needed. [Drewster727] + +- Show the requested by user from legacy request models. [Drewster727] + +- Only show requested by users to admins + start maintaining a list of users with each request. [Drewster727] + +- #96 fix up notification test feature. [Drewster727] + +- Fix the request page sort/approve button alignment. [Drewster727] + +- When pulling requests, set each to approved that is already available (so the UI avoids showing the approve option for already available content) [Drewster727] + +- Mono doesn't seem to have Tls1.2. Let's try TLS 1 #119. [tidusjar] + +- Specify a protocol type of TLS12. Looks like CP doesn't seem to like SSL3 (it is quite old now so understandable) #119. [tidusjar] + +- Made #85 better. [tidusjar] + +- Fixed the tests. [tidusjar] + +- Made the feedback from Sonarr better when Sonarr already has the series #85. [tidusjar] + +- An attempt to fix #108. [tidusjar] + +- Add some "no results" feedback to the searching + minor UI improvements. [Drewster727] + +- Fix notification tests. [Drewster727] + +- UI - increase icon size of nav menu (they were too small before) [Drewster727] + +- #96 Finished adding test functionality to notifications. [Drewster727] + +- #96 add the necessary back-end code to produce a test message for all notification types (still have to add the test buttons for pushbullet/pushover) [Drewster727] + +- #96 modify notifications interface/service to accept a non-type specific settings object. [Drewster727] + +- #96 Email notification test button (others to come) [Drewster727] + +- Minor UI adjustments. [Drewster727] + +- #84 provide an option in settings to resttrict users from viewing requests other than their own. [Drewster727] + +- #54 comma separated list of users who don't require approval + fix a couple request messages (include show title) [Drewster727] + +- Clean up the sorting option names. add a way to see which filter/sort is currently applied. [Drewster727] + +- Fix up the animations. seems to be related to the data-bound attribute causing the animtions not to fire on each .mix object. [Drewster727] + +- Move approve buttons to the tab content. [Drewster727] + +- Allow approving all requests by category. [Drewster727] + +- Fix up sorting on the request page. [Drewster727] + +- Add ubuntu/debian instructions. [Drewster727] + +- #86 - display movie/show title + year in request notifications. [Drewster727] + +- Show the movie/show title when requesting. [Drewster727] + + +## v1.5.2 (2016-03-26) + +### **Fixes** + +- Stoped users from spamming the request button. [tidusjar] + +- Fixed the logger no longer writing to the file. [tidusjar] + +- Fixed #97. [tidusjar] + + +## v1.5.1 (2016-03-26) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Added logs to the sidebar. I'm an idiot. [tidusjar] + +### **Fixes** + +- Approve tv shows or movies. [Drewster727] + +- Fixed a bug where if you had auto approve it wouldn't notify you. [tidusjar] + + +## v1.5.0 (2016-03-25) + +### **New Features** + +- Updated version number for release. [tidusjar] + +- Updated the logic for handling specific seasons in Sonarr and Sickrage. [Shannon Barrett] + +- Updated the readme and added some icons to the navbar. [tidusjar] + +- Added the ability to sepcify a username in the email notification settings for external MTA's. We have had to add a new option called Email Sender because of this. #78. [tidusjar] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Added a notification model to the notifiers. Added the backend work for sending a notification for an issue report #75. [tidusjar] + +- Added a subdir to CP, SickRage, Sonarr and Plex #43. [tidusjar] + +### **Fixes** + +- And again. [tidusjar] + +- Made the check actually work. [tidusjar] + +- Finished up #68 and #62. [tidusjar] + +- Finished styling on the logger for now. #59. [tidusjar] + +- Fixed #69. [tidusjar] + +- Working on getting the Sonarr component to work correctly. [Shannon Barrett] + +- Fixes issue #62. [Shannon Barrett] + +- Refactored the Notification service to how it should have really been done in the first place. [tidusjar] + +- Fixed the build. [tidusjar] + +- Finished #49. [tidusjar] + +- Finished #57. [tidusjar] + +- Small changes around the filtering. [tidusjar] + +- Finished adding pushover support. #44. [tidusjar] + +- Resolved #75. [tidusjar] + +- Include DB changes. [tidusjar] + +- Done most on #59. [tidusjar] + +- Lowercase logs folder, because you know, linux. #59. [tidusjar] + +- Adding the imdb when requesting. [tidusjar] + +- Fixed an issue where the table didn't match the model. [tidusjar] + +- Improved the status page with the suggestion from #29. [tidusjar] + +- Hooked up most of #49 Just the validation messages need to be done. [tidusjar] + +- Fixed #74 and #64. [tidusjar] + +- Resolved #70. [tidusjar] + +- Finished #71. [tidusjar] + +- Got the filter working on both movie and tv #57. [tidusjar] + +- Started #57, currently there is a bug where the TV list won't filter. [tidusjar] + + +## v1.4.1 (2016-03-20) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Update AvailabilityUpdateService.cs. [Jamie] + + +## v1.4.0 (2016-03-19) + +### **New Features** + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Update README.md. [Jamie] + +- Updated the build version ready for the next release. [tidusjar] + +- Added the api and settings page for Sickrage. Just need to do the tester and hook it up #40. [tidusjar] + +- Added the option to set a CP quality #38. [tidusjar] + +- Added the code to lookup the old requests and refresh them with new information from TVMaze. [tidusjar] + +- Update StatusCheckerTests.cs. [Jamie] + +- Update README.md. [Jamie] + +- Added TVMaze to the search. #21. [tidusjar] + +- Added migration code and cleaned up the DB. [tidusjar] + +- Updated the way we add requests. [tidusjar] + +- Updated the Dapper.Contrib package, it had a bug where it wasn't returning the correct Id from inserts. [tidusjar] + +### **Fixes** + +- This fixes #36. [tidusjar] + +- Should fix issue #36. [Shannon Barrett] + +- When we do a batch update we need to reset the cache. [tidusjar] + +- Fixed an issue where the default quality on Sickrage wouldn't work. [tidusjar] + +- Wow, that was a lot of work. - So, I have now finished #40. - Fixed a bug where we was not choosing the correct tv series (Because of TVMaze) - Fixed a bug when checking for plex titles - Fixed a bug where the wrong issue would clean on the UI (DB was correct) - Refactored how we send tv shows - And too many small changes to count. [tidusjar] + +- Fixed the new dependancy with the admin class tests. [tidusjar] + +- Back to what it was :( [tidusjar] + +- Another test for #37. [tidusjar] + +- This should fix #37. [Jamie Rees] + +- Catch the missing table exception when they have a new DB. [Jamie Rees] + +- Exploratory test for #37. [Jamie Rees] + +- Fixed #33 we now have SSL options for Sonarr and CP. [Jamie Rees] + +- Removed all the html from the new TVMaze api (for overview). Added tests to cover the html removal. updated Readme to remove TheTVDB. [Jamie Rees] + +- Fixed tests. [Jamie Rees] + +- Almost fully integrated TVMaze #21 and also improved the fix for #31. [Jamie Rees] + +- Should fix #28. [Shannon Barrett] + +- Fixed #16 and #30. [tidusjar] + +- Modified the adding of request to update the model with the added ID. [tidusjar] + +- Switched over to the new service. [tidusjar] + +- Fixed #25. [Jamie Rees] + + +## v1.3.0 (2016-03-17) + +### **New Features** + +- Added pushbullet to the sidebar. [Jamie Rees] + +- Updated build version for the next release. [Jamie Rees] + +- Updated readme link. [tidusjar] + +- Added ignore to static tests. [tidusjar] + +- Added Pushbullet notifications #8. [tidusjar] + +- Added first implimentation of the Notification Service #8 Added tests to cover the notification service. [tidusjar] + +- Added validation to the Email settings, also increased the availability checker from 2 minutes to 5. [tidusjar] + +### **Fixes** + +- Fixed #22. [Jamie Rees] + +- Started on #16, nothing is hooked up yet. [tidusjar] + +- Fixed tests. [tidusjar] + + +## v1.2.1 (2016-03-16) + +### **New Features** + +- Update Program.cs. [Jamie] + +- Update Program.cs. [Jamie] + +- Added back the reference. [tidusjar] + +### **Fixes** + +- Removed the email notification settings from the settings (for release 1.2.1) [Jamie Rees] + +- Fixed. [Jamie Rees] + +- Resolved #10. [tidusjar] + + +## v1.2.0 (2016-03-15) + +### **New Features** + +- Updated. [Jamie Rees] + +- Updated appveyor. [Jamie Rees] + +- Update appveyor.yml. [Jamie] + +- Added latest version code and view. Need to finish the view #11. [tidusjar] + +- Added test button to Plex. That's fixed #9. [tidusjar] + +- Added test sonarr button #9. [tidusjar] + +- Added more tests. [tidusjar] + +- Added a bunch of logging. [tidusjar] + +- Added the application tester for CP #9. [tidusjar] + +- Added settings page for #8. [tidusjar] + +- Added pace.js. [tidusjar] + +### **Fixes** + +- Finished the notes! Resolved #7. [Jamie Rees] + +- #12. [Jamie Rees] + +- #12. [Jamie Rees] + +- Finished the status page #11 and some more work to #12. [Jamie Rees] + +- Resolved #7. [tidusjar] + +- Small changes. [tidusjar] + +- Yeah... [tidusjar] + +- Fixed #5 and also added some tests to the availability checker. [tidusjar] + +- Started added tests. [Jamie Rees] + +- Fixed an issue where the issues text appears larger. [Jamie Rees] + + +## v1.1 (2016-03-13) + +### **New Features** + +- Update appveyor.yml. [Jamie] + +- Updated readme. [Jamie Rees] + +- Added the support for TV Series integrating with Sonarr. [Jamie Rees] + +- Added the functionality to pass a port through an argument. [tidusjar] + +- Added the code to get the quality profiles from Sonarr Started plugging that into the UI. [Jamie Rees] + +- Added the spinners #3. [tidusjar] + +- Added the functionality for the admin to clear the issues. [tidusjar] + +- Added the issues to the requests page. [tidusjar] + +- Added user logout method and unit tests to cover it. [tidusjar] + +- Added DeniedUsers to the view. [tidusjar] + +- Added the denied user check to the UserLoginModule. added a test case to cover it. [tidusjar] + +- Added a missing reference. [tidusjar] + +- Added first real test. [tidusjar] + +- Update README.md. [Jamie] + +- Added the latest version of nuget. [tidusjar] + +- Added travisyml. [tidusjar] + +- Added logging. [tidusjar] + +- Added missing files. [tidusjar] + +- Update README.md. [Jamie] + +- Added logging (Still WIP) [tidusjar] + +- Added favicon and also structured the HTML correctly. [tidusjar] + +- Updated the packages so everything is now with the correct framework (4.5.2) [tidusjar] + +- Added in deletion of requests. [tidusjar] + +- Added test code. [tidusjar] + +- Added dashboard. [tidusjar] + +- Added couchpotato page. [Jamie Rees] + +- Added readme to the project and updated it. [Jamie Rees] + +- Added helpers. [tidusjar] + +### **Fixes** + +- Bug fix, Couchpotato settings wouldn't show in release due to a Nancy bug. [Jamie Rees] + +- Small changes. [Jamie Rees] + +- First release, build 1.0.0. [Jamie Rees] + +- Removed the request limit since it's not currently being used. [Jamie Rees] + +- REmoved Sickbeared for the first release. [Jamie Rees] + +- Fixed #4 We now can manually set the status of a request. [tidusjar] + +- Made the pass in the port a bit more robust. [tidusjar] + +- Styling, Added the functionality for the Sonarr Profiles on the Admin page #2 resolved. [tidusjar] + +- Fixed a bug in the Login and added a unit test to cover that. Added a button to approve an individual request. Fixed some minor bugs in the request screen. [Jamie Rees] + +- Fixed the 'responsive' issue for the search and requests pages #3. [tidusjar] + +- Styling! #3. [tidusjar] + +- Navbar category now will follow you to various screens #3. [tidusjar] + +- Fixed bugs with the 'other' reporting issue and also the clear issues. [tidusjar] + +- We now are appending the users name to who wrote the comment. Rather than it being unknown. [tidusjar] + +- More work on submitting issues. [tidusjar] + +- More test changes. [tidusjar] + +- More tests to cover the login. [tidusjar] + +- Refactoring. [tidusjar] + +- Implimented the password part and authentication with Plex. [tidusjar] + +- Initial Use authentication is working. Need to do the password bit. [tidusjar] + +- Some error handling and ensure we are an admin to delete requests. [tidusjar] + +- Fixed the issue where the Release build would not show the admin screens! [tidusjar] + +- Fixes. [tidusjar] + +- Removed the DI part of the service. TinyIOC doesn't want to work with FluentScheduler. [tidusjar] + +- First pass at the plex update service. [tidusjar] + +- Small changes. [Jamie Rees] + +- Started to impliment the Plex checker. This will check plex every x minutes to see if there is any new content and then update the avalibility of the requests. [Jamie Rees] + +- Mre work. [Jamie Rees] + +- Few small changes, added plex settings. [Jamie Rees] + +- Making the configuration actually do something. Setting a default configuration if there is no DB. [Jamie Rees] + +- Remove post build. [Jamie Rees] + +- Small changes. [Jamie Rees] + +- MOre work. [Jamie Rees] + +- Fixed the issue when sending movies to CouchPotato. [Jamie Rees] + +- Add appveyor. [tidusjar] + +- Build it on 4.5. [tidusjar] + +- Upgraded .net to 4.6. [tidusjar] + +- Typo2. [tidusjar] + +- Typo. [tidusjar] + +- Another update. [tidusjar] + +- Fixed. [tidusjar] + +- More logging to figure out why the we cannot access the admin module in a release build. [tidusjar] + +- Firstpass integrating with CouchPotato. [tidusjar] + +- Some styling. [tidusjar] + +- Fixed the plex friends. Added some unit tests, moved the plex auth into it's own page. [tidusjar] + +- Fully switched the TV shows over to use the other provider. [Jamie Rees] + +- Renamed folders. [tidusjar] + +- Assembly updates. [tidusjar] + +- Moved the rest of the projects. [tidusjar] + +- Moved UI. [tidusjar] + +- Mass rename. [tidusjar] + +- Quick changes. [tidusjar] + +- Started switching the TV over to the new provider (TheTVDB). Currently TV search is partially broken. It will search but we are not mapping all of the details. [tidusjar] + +- Implimented the new TV show Provider (needed for Sonarr TheTvDB) [tidusjar] + +- Started the user auth. [tidusjar] + +- Some work on the requests page. [tidusjar] + +- Made the 'requested' better and made the remove look nicer. [tidusjar] + +- Cleaned up the program a tiny bit. [tidusjar] + +- Removed additional namespace. [tidusjar] + +- Fixed some db issues and added a preview. [Jamie Rees] + +- More work on the settings. [Jamie Rees] + +- Upgraded Json.Net and Nancy packages. [Jamie Rees] + +- Plex friends api. [Jamie Rees] + +- Enabled trace logs. [tidusjar] + +- Sql syntax issue fixed. [tidusjar] + +- Fixed release build. [tidusjar] + +- Small updates including assembly version. [tidusjar] + +- Work on the requests page mostly done. [tidusjar] + +- Work on the TV request. the `latest` parameter is not being passed into the requestTvshow. [tidusjar] + +- Missing file. [tidusjar] + +- Using the IoC container now. [tidusjar] + +- Some plex work. [Jamie Rees] + +- More work. [Jamie Rees] + +- Removed the setup code out of the startup, since we attemtp to connect to the DB before that. [Jamie Rees] + +- Some more work. Need to stop the form submitting on a request. [tidusjar] + +- Moved everything up a directory. [tidusjar] + +- Lots of work! [tidusjar] + +- Done most of the movie search work. [Jamie Rees] + +- First pass with RequestPlex. [tidusjar] + +- Initial commit. [Jamie] + + From 0000ff1ce90ffcacbd9e8f9f8c7b692a664f763e Mon Sep 17 00:00:00 2001 From: Anojh Thayaparan Date: Mon, 16 Apr 2018 06:47:01 -0700 Subject: [PATCH 030/495] Inject base url if set before theme file url, see issue #1795 (#2148) --- src/Ombi/Controllers/SettingsController.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 30469cd57..a5aef25fb 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -274,6 +274,12 @@ namespace Ombi.Controllers public async Task GetThemeContent([FromQuery]string url) { var css = await _githubApi.GetThemesRawContent(url); + var ombiSettings = await OmbiSettings(); + if (ombiSettings.BaseUrl != null) + { + int index = css.IndexOf("/api/"); + css = css.Insert(index, ombiSettings.BaseUrl); + } return Content(css, "text/css"); } From bc4db4184ce9e6dfc70aa6d0840c9584c9bcd49e Mon Sep 17 00:00:00 2001 From: Anojh Thayaparan Date: Mon, 16 Apr 2018 06:47:50 -0700 Subject: [PATCH 031/495] Knocking out LC requirements in issue #2124 (#2125) --- src/Ombi.Core/Engine/TvRequestEngine.cs | 7 +- src/Ombi.Core/Helpers/TvShowRequestBuilder.cs | 16 +++- src/Ombi.Mapping/Profiles/MovieProfile.cs | 13 ++++ src/Ombi.TheMovieDbApi/IMovieDbApi.cs | 1 + src/Ombi.TheMovieDbApi/Models/SearchResult.cs | 3 + .../Models/TvSearchResult.cs | 18 +++++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 13 +++- .../app/issues/issueDetails.component.html | 2 +- .../app/issues/issueDetails.component.ts | 12 ++- .../app/issues/issuestable.component.html | 8 +- .../app/issues/issuestable.component.ts | 22 +++++- .../app/requests/movierequests.component.html | 67 ++++++++-------- .../app/requests/movierequests.component.ts | 47 +++++++++++- .../tvrequest-children.component.html | 15 +--- .../requests/tvrequest-children.component.ts | 16 +--- .../app/requests/tvrequests.component.html | 72 ++++++++++-------- .../app/requests/tvrequests.component.ts | 18 +++++ .../app/search/moviesearch.component.html | 2 +- .../app/search/moviesearch.component.ts | 18 +++-- .../app/search/tvsearch.component.html | 2 +- .../app/search/tvsearch.component.ts | 15 +++- src/Ombi/ClientApp/styles/Themes/plex.scss | 2 +- src/Ombi/ClientApp/styles/base.scss | 4 + src/Ombi/tsconfig.json | 2 +- .../wwwroot/images/default_movie_poster.png | Bin 0 -> 1685 bytes src/Ombi/wwwroot/images/default_tv_poster.png | Bin 0 -> 1776 bytes 26 files changed, 272 insertions(+), 123 deletions(-) create mode 100644 src/Ombi.TheMovieDbApi/Models/TvSearchResult.cs create mode 100644 src/Ombi/wwwroot/images/default_movie_poster.png create mode 100644 src/Ombi/wwwroot/images/default_tv_poster.png diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index aaa2d353d..7671c13fc 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -1,6 +1,7 @@ using System; using AutoMapper; using Ombi.Api.TvMaze; +using Ombi.Api.TheMovieDb; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Helpers; @@ -26,11 +27,12 @@ namespace Ombi.Core.Engine { public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine { - public TvRequestEngine(ITvMazeApi tvApi, IRequestServiceMain requestService, IPrincipal user, + public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user, INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ITvSender sender, IAuditRepository audit, IRepository rl, ISettingsService settings, ICacheService cache) : base(user, requestService, rule, manager, cache, settings) { TvApi = tvApi; + MovieDbApi = movApi; NotificationHelper = helper; TvSender = sender; Audit = audit; @@ -39,6 +41,7 @@ namespace Ombi.Core.Engine private INotificationHelper NotificationHelper { get; } private ITvMazeApi TvApi { get; } + private IMovieDbApi MovieDbApi { get; } private ITvSender TvSender { get; } private IAuditRepository Audit { get; } private readonly IRepository _requestLog; @@ -47,7 +50,7 @@ namespace Ombi.Core.Engine { var user = await GetUser(); - var tvBuilder = new TvShowRequestBuilder(TvApi); + var tvBuilder = new TvShowRequestBuilder(TvApi, MovieDbApi); (await tvBuilder .GetShowInfo(tv.TvDbId)) .CreateTvList(tv) diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs index 1f92536b8..6e4d20be8 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Ombi.Api.TvMaze; +using Ombi.Api.TheMovieDb; using Ombi.Api.TvMaze.Models; +using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Helpers; @@ -16,12 +18,14 @@ namespace Ombi.Core.Helpers public class TvShowRequestBuilder { - public TvShowRequestBuilder(ITvMazeApi tvApi) + public TvShowRequestBuilder(ITvMazeApi tvApi, IMovieDbApi movApi) { TvApi = tvApi; + MovieDbApi = movApi; } private ITvMazeApi TvApi { get; } + private IMovieDbApi MovieDbApi { get; } public ChildRequests ChildRequest { get; set; } public List TvRequests { get; protected set; } @@ -29,10 +33,20 @@ namespace Ombi.Core.Helpers public DateTime FirstAir { get; protected set; } public TvRequests NewRequest { get; protected set; } protected TvMazeShow ShowInfo { get; set; } + protected List Results { get; set; } public async Task GetShowInfo(int id) { ShowInfo = await TvApi.ShowLookupByTheTvDbId(id); + Results = await MovieDbApi.SearchTv(ShowInfo.name); + foreach (TvSearchResult result in Results) { + if (result.Name == ShowInfo.name) + { + var showIds = await MovieDbApi.GetTvExternals(result.Id); + ShowInfo.externals.imdb = showIds.imdb_id; + break; + } + } DateTime.TryParse(ShowInfo.premiered, out var dt); diff --git a/src/Ombi.Mapping/Profiles/MovieProfile.cs b/src/Ombi.Mapping/Profiles/MovieProfile.cs index d7e43fc50..dd7e03379 100644 --- a/src/Ombi.Mapping/Profiles/MovieProfile.cs +++ b/src/Ombi.Mapping/Profiles/MovieProfile.cs @@ -24,6 +24,19 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.VoteAverage, opts => opts.MapFrom(src => src.vote_average)) .ForMember(dest => dest.VoteCount, opts => opts.MapFrom(src => src.vote_count)); + CreateMap() + .ForMember(dest => dest.BackdropPath, opts => opts.MapFrom(src => src.backdrop_path)) + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) + .ForMember(dest => dest.OriginalLanguage, opts => opts.MapFrom(src => src.original_language)) + .ForMember(dest => dest.OriginalName, opts => opts.MapFrom(src => src.original_name)) + .ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.overview)) + .ForMember(dest => dest.Popularity, opts => opts.MapFrom(src => src.popularity)) + .ForMember(dest => dest.PosterPath, opts => opts.MapFrom(src => src.poster_path)) + .ForMember(dest => dest.ReleaseDate, opts => opts.MapFrom(src => src.first_air_date)) + .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)) + .ForMember(dest => dest.VoteAverage, opts => opts.MapFrom(src => src.vote_average)) + .ForMember(dest => dest.VoteCount, opts => opts.MapFrom(src => src.vote_count)); + CreateMap() .ForMember(dest => dest.Adult, opts => opts.MapFrom(src => src.adult)) .ForMember(dest => dest.BackdropPath, opts => opts.MapFrom(src => src.backdrop_path)) diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index 787902a4b..5d0a89992 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -12,6 +12,7 @@ namespace Ombi.Api.TheMovieDb Task> NowPlaying(); Task> PopularMovies(); Task> SearchMovie(string searchTerm); + Task> SearchTv(string searchTerm); Task> TopRated(); Task> Upcoming(); Task> SimilarMovies(int movieId); diff --git a/src/Ombi.TheMovieDbApi/Models/SearchResult.cs b/src/Ombi.TheMovieDbApi/Models/SearchResult.cs index 81d8115f6..7b09b5e4b 100644 --- a/src/Ombi.TheMovieDbApi/Models/SearchResult.cs +++ b/src/Ombi.TheMovieDbApi/Models/SearchResult.cs @@ -32,9 +32,12 @@ namespace Ombi.TheMovieDbApi.Models public bool adult { get; set; } public string overview { get; set; } public string release_date { get; set; } + public string first_air_date { get; set; } public int?[] genre_ids { get; set; } public int id { get; set; } public string original_title { get; set; } + public string original_name { get; set; } + public string name { get; set; } public string original_language { get; set; } public string title { get; set; } public string backdrop_path { get; set; } diff --git a/src/Ombi.TheMovieDbApi/Models/TvSearchResult.cs b/src/Ombi.TheMovieDbApi/Models/TvSearchResult.cs new file mode 100644 index 000000000..eaf93d7cc --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/TvSearchResult.cs @@ -0,0 +1,18 @@ +namespace Ombi.Api.TheMovieDb.Models +{ + public class TvSearchResult + { + public string PosterPath { get; set; } + public string Overview { get; set; } + public string ReleaseDate { get; set; } + public int?[] GenreIds { get; set; } + public int Id { get; set; } + public string OriginalName { get; set; } + public string OriginalLanguage { get; set; } + public string Name { get; set; } + public string BackdropPath { get; set; } + public float Popularity { get; set; } + public int VoteCount { get; set; } + public float VoteAverage { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 08925e490..ccd0e52e6 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -42,7 +42,18 @@ namespace Ombi.Api.TheMovieDb return await Api.Request(request); } - + + public async Task> SearchTv(string searchTerm) + { + var request = new Request($"search/tv", BaseUri, HttpMethod.Get); + request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); + AddRetry(request); + + var result = await Api.Request>(request); + return Mapper.Map>(result.results); + } + public async Task GetTvExternals(int theMovieDbId) { var request = new Request($"/tv/{theMovieDbId}/external_ids", BaseUri, HttpMethod.Get); diff --git a/src/Ombi/ClientApp/app/issues/issueDetails.component.html b/src/Ombi/ClientApp/app/issues/issueDetails.component.html index e88ad621c..990b9d636 100644 --- a/src/Ombi/ClientApp/app/issues/issueDetails.component.html +++ b/src/Ombi/ClientApp/app/issues/issueDetails.component.html @@ -1,5 +1,5 @@
-
+

{{issue.title}}

diff --git a/src/Ombi/ClientApp/app/issues/issueDetails.component.ts b/src/Ombi/ClientApp/app/issues/issueDetails.component.ts index 34fcbe302..1072bedbd 100644 --- a/src/Ombi/ClientApp/app/issues/issueDetails.component.ts +++ b/src/Ombi/ClientApp/app/issues/issueDetails.component.ts @@ -98,7 +98,11 @@ export class IssueDetailsComponent implements OnInit { ("url(" + x + ")"); }); this.imageService.getMoviePoster(issue.providerId).subscribe(x => { - this.posterPath = x.toString(); + if (x.length === 0) { + this.posterPath = "../../../images/default_movie_poster.png"; + } else { + this.posterPath = x.toString(); + } }); } else { @@ -107,7 +111,11 @@ export class IssueDetailsComponent implements OnInit { ("url(" + x + ")"); }); this.imageService.getTvPoster(Number(issue.providerId)).subscribe(x => { - this.posterPath = x.toString(); + if (x.length === 0) { + this.posterPath = "../../../images/default_tv_poster.png"; + } else { + this.posterPath = x.toString(); + } }); } diff --git a/src/Ombi/ClientApp/app/issues/issuestable.component.html b/src/Ombi/ClientApp/app/issues/issuestable.component.html index f98d6eb0e..83dc8a1db 100644 --- a/src/Ombi/ClientApp/app/issues/issuestable.component.html +++ b/src/Ombi/ClientApp/app/issues/issuestable.component.html @@ -1,25 +1,25 @@ - - - - "); sb.Append( " + +
+ + + + diff --git a/src/Ombi/ClientApp/app/issues/issuestable.component.ts b/src/Ombi/ClientApp/app/issues/issuestable.component.ts index ee93e689d..f03dd9a6d 100644 --- a/src/Ombi/ClientApp/app/issues/issuestable.component.ts +++ b/src/Ombi/ClientApp/app/issues/issuestable.component.ts @@ -20,11 +20,25 @@ export class IssuesTableComponent { public rowCount = 10; - public setOrder(value: string) { - if (this.order === value) { - this.reverse = !this.reverse; + public setOrder(value: string, el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + if (el.nodeName === "A") { + el = el.parentElement; } - + + const parent = el.parentElement; + const previousFilter = parent.querySelector(".active"); + + if (this.order === value) { + this.reverse = !this.reverse; + } else { + if (previousFilter) { + previousFilter.className = ""; + } + el.className = "active"; + } + this.order = value; } diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 6b2300f38..8eded8dba 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -67,7 +67,7 @@
- poster + poster
@@ -222,42 +222,43 @@

{{ 'Requests.Filter' | translate }}


- -

{{ 'Filter.FilterHeaderAvailability' | translate }}

-
-
- - +
+

{{ 'Filter.FilterHeaderAvailability' | translate }}

+
+
+ + +
+
+
+
+ + +
-
-
- - +
+

{{ 'Filter.FilterHeaderRequestStatus' | translate }}

+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
-

{{ 'Filter.FilterHeaderRequestStatus' | translate }}

-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
- - - \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 0fc5f6651..e28b86eaa 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -149,7 +149,16 @@ export class MovieRequestsComponent implements OnInit { event.preventDefault(); } - public clearFilter() { + public clearFilter(el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + el = el.parentElement; + el = el.querySelectorAll("INPUT"); + for (el of el) { + el.checked = false; + el.parentElement.classList.remove("active"); + } + this.filterDisplay = false; this.filter.availabilityFilter = FilterType.None; this.filter.statusFilter = FilterType.None; @@ -157,7 +166,8 @@ export class MovieRequestsComponent implements OnInit { this.resetSearch(); } - public filterAvailability(filter: FilterType) { + public filterAvailability(filter: FilterType, el: any) { + this.filterActiveStyle(el); this.filter.availabilityFilter = filter; this.requestService.filterMovies(this.filter) .subscribe(x => { @@ -166,7 +176,8 @@ export class MovieRequestsComponent implements OnInit { }); } - public filterStatus(filter: FilterType) { + public filterStatus(filter: FilterType, el: any) { + this.filterActiveStyle(el); this.filter.statusFilter = filter; this.requestService.filterMovies(this.filter) .subscribe(x => { @@ -190,6 +201,24 @@ export class MovieRequestsComponent implements OnInit { this.order = value; } + private filterActiveStyle(el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + el = el.parentElement; //gets radio div + el = el.parentElement; //gets form group div + el = el.parentElement; //gets status filter div + el = el.querySelectorAll("INPUT"); + for (el of el) { + if (el.checked) { + if (!el.parentElement.classList.contains("active")) { + el.parentElement.className += " active"; + } + } else { + el.parentElement.classList.remove("active"); + } + } + } + private loadRequests(amountToLoad: number, currentlyLoaded: number) { this.requestService.getMovieRequests(amountToLoad, currentlyLoaded + 1) .subscribe(x => { @@ -243,7 +272,8 @@ export class MovieRequestsComponent implements OnInit { this.movieRequests = x; this.movieRequests.forEach((req) => { - this.movieRequests.forEach((req) => this.setBackground(req)); + this.setBackground(req); + this.setPoster(req); }); this.radarrService.getQualityProfilesFromSettings().subscribe(c => { this.radarrProfiles = c; @@ -296,11 +326,20 @@ export class MovieRequestsComponent implements OnInit { } private setOverride(req: IMovieRequests): void { + this.setPoster(req); this.setBackground(req); this.setQualityOverrides(req); this.setRootFolderOverrides(req); } + private setPoster(req: IMovieRequests): void { + if (req.posterPath === null) { + req.posterPath = "../../../images/default_movie_poster.png"; + } else { + req.posterPath = "https://image.tmdb.org/t/p/w300/" + req.posterPath; + } + } + private setBackground(req: IMovieRequests): void { req.backgroundPath = this.sanitizer.bypassSecurityTrustStyle ("url(" + "https://image.tmdb.org/t/p/w1280" + req.background + ")"); diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html index 30e1398eb..736878d4b 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html @@ -22,15 +22,7 @@
- +
@@ -101,8 +93,3 @@
- - - - \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts index 300599063..e9da2342f 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { IChildRequests, IIssueCategory } from "../interfaces"; +import { IChildRequests } from "../interfaces"; import { NotificationService, RequestService } from "../services"; @@ -13,13 +13,6 @@ export class TvRequestChildrenComponent { @Output() public requestDeleted = new EventEmitter(); - @Input() public issueCategories: IIssueCategory[]; - @Input() public issuesEnabled: boolean; - @Input() public issueProviderId: string; - public issuesBarVisible = false; - public issueRequest: IChildRequests; - public issueCategorySelected: IIssueCategory; - constructor(private requestService: RequestService, private notificationService: NotificationService) { } @@ -101,13 +94,6 @@ export class TvRequestChildrenComponent { }); } - public reportIssue(catId: IIssueCategory, req: IChildRequests) { - this.issueRequest = req; - this.issueCategorySelected = catId; - this.issuesBarVisible = true; - this.issueProviderId = req.id.toString(); - } - private removeRequestFromUi(key: IChildRequests) { const index = this.childRequests.indexOf(key, 0); if (index > -1) { diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.html b/src/Ombi/ClientApp/app/requests/tvrequests.component.html index a602d27e1..9a3c4d186 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.html @@ -64,51 +64,63 @@
- +
- -
- - - + +
+ + + +
+ + +
+ + + +
+
- - -
- - -
- -
+ (requestDeleted)="childRequestDeleted($event)">
+ + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts index ad8b4ca50..344bf5712 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts @@ -33,6 +33,9 @@ export class TvRequestsComponent implements OnInit { @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; public issueProviderId: string; + public issuesBarVisible = false; + public issueRequest: ITvRequests; + public issueCategorySelected: IIssueCategory; public sonarrProfiles: ISonarrProfile[] = []; public sonarrRootFolders: ISonarrRootFolder[] = []; @@ -151,6 +154,13 @@ export class TvRequestsComponent implements OnInit { this.updateRequest(searchResult); } + public reportIssue(catId: IIssueCategory, req: ITvRequests) { + this.issueRequest = req; + this.issueCategorySelected = catId; + this.issuesBarVisible = true; + this.issueProviderId = req.id.toString(); + } + private setOverride(req: ITvRequests): void { this.setQualityOverrides(req); this.setRootFolderOverrides(req); @@ -191,6 +201,7 @@ export class TvRequestsComponent implements OnInit { .subscribe(x => { this.tvRequests = x; this.tvRequests.forEach((val, index) => { + this.setDefaults(val); this.loadBackdrop(val); this.setOverride(val.data); }); @@ -209,6 +220,13 @@ export class TvRequestsComponent implements OnInit { this.currentlyLoaded = 5; this.loadInit(); } + + private setDefaults(val: any) { + if (val.data.posterPath === null) { + val.data.posterPath = "../../../images/default_tv_poster.png"; + } + } + private loadBackdrop(val: TreeNode): void { this.imageService.getTvBanner(val.data.tvDbId).subscribe(x => { val.data.background = this.sanitizer.bypassSecurityTrustStyle diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index 58d8415fb..cac78531b 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -33,7 +33,7 @@
- poster + poster
diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 819463c4f..0abc10474 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -157,12 +157,15 @@ export class MovieSearchComponent implements OnInit { private getExtraInfo() { - this.movieResults.forEach((val, index) => { - - val.background = this.sanitizer. - bypassSecurityTrustStyle - ("url(" + "https://image.tmdb.org/t/p/w1280" + val.backdropPath + ")"); - this.searchService.getMovieInformation(val.id) + this.movieResults.forEach((val, index) => { + if (val.posterPath === null) { + val.posterPath = "../../../images/default_movie_poster.png"; + } else { + val.posterPath = "https://image.tmdb.org/t/p/w300/" + val.posterPath; + } + val.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + "https://image.tmdb.org/t/p/w1280" + val.backdropPath + ")"); + this.searchService.getMovieInformation(val.id) .subscribe(m => { this.updateItem(val, m); }); @@ -174,7 +177,8 @@ export class MovieSearchComponent implements OnInit { if (index > -1) { const copy = { ...this.movieResults[index] }; this.movieResults[index] = updated; - this.movieResults[index].background = copy.background; + this.movieResults[index].background = copy.background; + this.movieResults[index].posterPath = copy.posterPath; } } private clearResults() { diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index fb1729e50..42232a564 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -62,7 +62,7 @@
- +

{{node.data.title}} ({{node.data.firstAired | date: 'yyyy'}})

diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.ts b/src/Ombi/ClientApp/app/search/tvsearch.component.ts index 961e85f63..bb30810e4 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.ts @@ -130,7 +130,6 @@ export class TvSearchComponent implements OnInit { public getExtraInfo() { this.tvResults.forEach((val, index) => { this.imageService.getTvBanner(val.data.id).subscribe(x => { - val.data.background = this.sanitizer. bypassSecurityTrustStyle ("url(" + x + ")"); @@ -138,6 +137,7 @@ export class TvSearchComponent implements OnInit { this.searchService.getShowInformationTreeNode(val.data.id) .subscribe(x => { if (x.data) { + this.setDefaults(x); this.updateItem(val, x); } else { const index = this.tvResults.indexOf(val, 0); @@ -216,6 +216,7 @@ export class TvSearchComponent implements OnInit { const index = this.tvResults.indexOf(key, 0); if (index > -1) { // Update certain properties, otherwise we will loose some data + this.tvResults[index].data.title = updated.data.title; this.tvResults[index].data.banner = updated.data.banner; this.tvResults[index].data.imdbId = updated.data.imdbId; this.tvResults[index].data.seasonRequests = updated.data.seasonRequests; @@ -225,6 +226,18 @@ export class TvSearchComponent implements OnInit { } } + private setDefaults(x: any) { + if (x.data.banner === null) { + x.data.banner = "../../../images/default_tv_poster.png"; + } + + if (x.data.imdbId === null) { + x.data.imdbId = "https://www.tvmaze.com/shows/" + x.data.seriesId; + } else { + x.data.imdbId = "http://www.imdb.com/title/" + x.data.imdbId + "/"; + } + } + private clearResults() { this.tvResults = []; this.searchApplied = false; diff --git a/src/Ombi/ClientApp/styles/Themes/plex.scss b/src/Ombi/ClientApp/styles/Themes/plex.scss index 1e3c27eaf..1475aef91 100644 --- a/src/Ombi/ClientApp/styles/Themes/plex.scss +++ b/src/Ombi/ClientApp/styles/Themes/plex.scss @@ -351,5 +351,5 @@ button.list-group-item:focus { position: absolute; } table.table > thead > tr > th.active { - background-color: transparent; + background-color: $primary-colour; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 619dd8042..3a5deb2a3 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -541,6 +541,10 @@ $border-radius: 10px; cursor: pointer; } +.table-usermanagement { + margin-top: 20px; +} + .input-group-sm { padding-top: 2px; padding-bottom: 2px; diff --git a/src/Ombi/tsconfig.json b/src/Ombi/tsconfig.json index daff6b451..8f860760c 100644 --- a/src/Ombi/tsconfig.json +++ b/src/Ombi/tsconfig.json @@ -11,7 +11,7 @@ "noUnusedLocals": true, "noImplicitThis": true, "noImplicitReturns": true, - "noImplicitAny": true, + "noImplicitAny": false, "suppressImplicitAnyIndexErrors": true, "alwaysStrict": true, "emitDecoratorMetadata": true, diff --git a/src/Ombi/wwwroot/images/default_movie_poster.png b/src/Ombi/wwwroot/images/default_movie_poster.png new file mode 100644 index 0000000000000000000000000000000000000000..f5cec85a5b313321a2840ebbb07c5bd52843678b GIT binary patch literal 1685 zcmeAS@N?(olHy`uVBq!ia0vp^Cm0wQbvW37thQf&_AxN9#dx|nhE&XXd)MDzDq80F zL*t5{{xK7>axU-q_ILjhy;;k0V#ong(>C9n;y>TcRBr!{9U9FC7hEZgUAKPy>9oz2N3ZUcz5BDX>_Uy5{^px& zg8BbUzw-L)sT?!y&p-d%@P4`G|8xI;tv+g#2^mm8;lT*mq2z`OVFPiJklx^Z2ehb`4aO7_j`|1VjJ98Nzq ziu+lm`TqWX{lgDGJh=bdUuA;roqPA}ZZ?O6hN?~Wl#tSm3gzYH zOV_>LbT_a5_xFn#AwX}hUh{UXu!r~Sue)mg|Eqnz@%HW8MU|B|SN8rY+pQbFzphru zUDN)WwG5y4{`>ZaPTdomt{+uZQITP@?QUMVok0J~ou*5FAGU`l*UXnso-Fwo5gI!8 z)`IDu{>-}c_o4i{q^(!pe?MJgcmL<2`zb~*QxwwE(}C_#KhDnl7p?U$vM_s-&JKO7W#)iK^>&8k&}e6QcVTUU7J?g~$9 zrcBM=Svq3fa~G@qt=nJo=f}qd#*u&P>Ys~hE>_cbR?yulX?n9%_4Sh{Pc){7-0qph z@ucz_G)*P&U%Iqk*0i#s!s3+L-{-SteN%Mvy(Q@34K!&__4mB><))GAuRs0#{5<>q zGru1mZdaFnw`$d?pFb-fr^ZQtDP!5xelus=_1EmDpMHAqe`40|yVIT)?flGWFV|nb z&(66TV$br3>K!|GX3CVme{>}$_ImH*clo(SKOrvcm4Wx>weSTSu&S_fqj2p zZT21J-s8#AU&ZDmZG95!`_Bhn2y6j!K>=x!_3883)w?B5fE+SAe0S5;K8J4`-mf^B zZObuxUw`1_|9%SWCNg}dj~+dG(B9#Adb3QQ10OJ@{bX5T?xO&AO**5VSog8Q^2KUz zIaF@snC-V?EZZ7o+BfS;>D`^Zzs?6vj(xT3-`mM~=CjXc>%H|YoM~QR^WyuR<`vzG z)lNSCy*YcqM0uNL7W?^zyDV1z7BZXdyYls}k25C*ty;Z$b>81s&3uJjtfPe(JPIi& c&j0Yl zO)W`OsL0L9E4HezRRWu91!RMS^_3LBN=mYAl^~9a@C{IK&M!(;Fx4~DO*S+!QZTpF zGc+@>G&0dqFfuSS*EcZNH#F8YFtjo-vof|+fC43;ZAB?*RzWUqP`iLUTcwPWk^(Dz z{qpj1y>er{{GxPyLrY6beFGzXBO_g)3fZE`@j@w*YQzUNJP7fB~jokyxN_sAmB35=^15FMg%Dxp39RB|)hO_hL1; zIHa;5RX-@TIKQ+g85nVC${?!>telHd6HD@oLh|!-V4)b0kzbNuoRMFk;OwlR5uTZs zl3!k|30CgwYvq|&T#}fVoa*Ufs{}MaFEca6%FM*V$kfEu*x1s*($LV=!qLdW)zQSn z+1SzCz{Sbc5~kNBKe;qFHLnDwHwB^B1gBn5O2{n$+U$~Alv$RV;#QQOs{r<~RVHq? z7~(V!sy799yBiO3djj(>Wj6+5Kc& z-Lg|`mm~G2%U{@X#JgdGfY>3XL`9tz)q1Rudu9rqma}8`ceyFN<)w9o)+i&OooDey! z*KM&u`n=~Kw~9Utl2{k2yZ+T`gDi;~a<5riL@yjTRCVChyk%@+*POTMvu&%aZ@ZdR zx-;h1r$E0+N0T1j=QZ4MrzSzug{Y8fVdeiIW*^}@>4?Fhtb5jfmfQ{M*bsO5Wr@*- z4YR_hEp2SQx@VEbs#R4}GY_vweDLF5Yy9MsD%ZNhW-ZJ8#}#({YuWC*IcD!>{V_Te z{q^^|9&*r<0+{(ORQ@Dylq8^mODt z#fC-{YMuVH{NCLS_4nVF9qJ0c;qtt)&PHy2&B9fywB~%TvHKk+u@)G_aqHKfUWb`> jI8G1w)b;;eKLay^g>(Pw(m4fvpgPFY)z4*}Q$iB}QrLNN literal 0 HcmV?d00001 From 7bbcb9a6267df751c47d2b91e2ee5da0d8c0fe65 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Wed, 18 Apr 2018 15:11:44 +0100 Subject: [PATCH 032/495] Made an attempt at PlexOAuth !wip --- src/Ombi/Controllers/PlexOAuthController.cs | 40 +++++++++ src/Ombi/Controllers/TokenController.cs | 95 ++++++++++++--------- src/Ombi/Models/UserAuthModel.cs | 1 + 3 files changed, 97 insertions(+), 39 deletions(-) create mode 100644 src/Ombi/Controllers/PlexOAuthController.cs diff --git a/src/Ombi/Controllers/PlexOAuthController.cs b/src/Ombi/Controllers/PlexOAuthController.cs new file mode 100644 index 000000000..8f33e37be --- /dev/null +++ b/src/Ombi/Controllers/PlexOAuthController.cs @@ -0,0 +1,40 @@ +using System.Net; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Http.Internal; +using System.IO; +using System.Text; + +namespace Ombi.Controllers +{ + [ApiExplorerSettings(IgnoreApi = true)] + [ApiV1] + [AllowAnonymous] + public class PlexOAuthController : Controller + { + + [HttpGet] + public IActionResult OAuthCallBack() + { + var bodyStr = ""; + var req = Request; + + // Allows using several time the stream in ASP.Net Core + req.EnableRewind(); + + // Arguments: Stream, Encoding, detect encoding, buffer size + // AND, the most important: keep stream opened + using (StreamReader reader + = new StreamReader(req.Body, Encoding.UTF8, true, 1024, true)) + { + bodyStr = reader.ReadToEnd(); + } + + // Rewind, so the core is not lost when it looks the body for the request + req.Body.Position = 0; + + // Do your work with bodyStr + return Ok(); + } + } +} diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 18da61e3a..5d524b7ba 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; +using System.Net.Http; using System.Security.Claims; using System.Text; using System.Threading.Tasks; @@ -9,6 +10,7 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; +using Ombi.Api; using Ombi.Core.Authentication; using Ombi.Helpers; using Ombi.Models; @@ -62,50 +64,65 @@ namespace Ombi.Controllers user.EmailLogin = true; } - // Verify Password - if (await _userManager.CheckPasswordAsync(user, model.Password)) + if (!model.UsePlexOAuth) { - var roles = await _userManager.GetRolesAsync(user); - - if (roles.Contains(OmbiRoles.Disabled)) + // Verify Password + if (await _userManager.CheckPasswordAsync(user, model.Password)) { - return new UnauthorizedResult(); + var roles = await _userManager.GetRolesAsync(user); + + if (roles.Contains(OmbiRoles.Disabled)) + { + return new UnauthorizedResult(); + } + + user.LastLoggedIn = DateTime.UtcNow; + await _userManager.UpdateAsync(user); + + var claims = new List + { + new Claim(JwtRegisteredClaimNames.Sub, user.UserName), + new Claim(ClaimTypes.NameIdentifier, user.Id), + new Claim(ClaimTypes.Name, user.UserName), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) + }; + claims.AddRange(roles.Select(role => new Claim("role", role))); + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey)); + var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + + + var token = new JwtSecurityToken( + claims: claims, + expires: model.RememberMe ? DateTime.UtcNow.AddDays(7) : DateTime.UtcNow.AddHours(5), + signingCredentials: creds, + audience: "Ombi", issuer: "Ombi" + ); + var accessToken = new JwtSecurityTokenHandler().WriteToken(token); + if (model.RememberMe) + { + // Save the token so we can refresh it later + //await _token.CreateToken(new Tokens() {Token = accessToken, User = user}); + } + + return new JsonResult(new + { + access_token = accessToken, + expiration = token.ValidTo + }); } + } + else + { + // Plex OAuth + // Redirect them to Plex - user.LastLoggedIn = DateTime.UtcNow; - await _userManager.UpdateAsync(user); + var request = new Request("auth", "https://app.plex.tv", HttpMethod.Get); + request.AddQueryString("clientID", "OMBIv3"); + request.AddQueryString("forwardUrl", "http://localhost:5000"); + request.AddQueryString("context-device-product", "http://localhost:5000"); + return new RedirectResult("https://app.plex.tv/auth#?forwardUrl=http://localhost:5000/api/v1/plexoauth&clientID=OMBIv3&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO"); - var claims = new List - { - new Claim(JwtRegisteredClaimNames.Sub, user.UserName), - new Claim(ClaimTypes.NameIdentifier, user.Id), - new Claim(ClaimTypes.Name, user.UserName), - new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) - }; - claims.AddRange(roles.Select(role => new Claim("role", role))); - - var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey)); - var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); - - - var token = new JwtSecurityToken( - claims: claims, - expires: model.RememberMe ? DateTime.UtcNow.AddDays(7) : DateTime.UtcNow.AddHours(5), - signingCredentials: creds, - audience: "Ombi", issuer:"Ombi" - ); - var accessToken = new JwtSecurityTokenHandler().WriteToken(token); - if (model.RememberMe) - { - // Save the token so we can refresh it later - //await _token.CreateToken(new Tokens() {Token = accessToken, User = user}); - } - - return new JsonResult(new - { - access_token = accessToken, - expiration = token.ValidTo - }); } return new UnauthorizedResult(); diff --git a/src/Ombi/Models/UserAuthModel.cs b/src/Ombi/Models/UserAuthModel.cs index 5b3d69a29..046119821 100644 --- a/src/Ombi/Models/UserAuthModel.cs +++ b/src/Ombi/Models/UserAuthModel.cs @@ -6,5 +6,6 @@ public string Password { get; set; } public bool RememberMe { get; set; } public bool UsePlexAdminAccount { get; set; } + public bool UsePlexOAuth { get; set; } } } \ No newline at end of file From bd741e053f5bc764ce95180bba23370fdad1041b Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Wed, 18 Apr 2018 15:15:44 +0100 Subject: [PATCH 033/495] Fixed #2169 --- src/Ombi.DependencyInjection/IocExtensions.cs | 1 - src/Ombi.Schedule/JobSetup.cs | 4 +- .../Plex/Interfaces/IPlexRecentlyAddedSync.cs | 9 ----- .../Jobs/Plex/PlexRecentlyAddedSync.cs | 40 ------------------- .../app/settings/jobs/jobs.component.html | 2 +- 5 files changed, 2 insertions(+), 54 deletions(-) delete mode 100644 src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexRecentlyAddedSync.cs delete mode 100644 src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index e2f667465..92ecf8282 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -175,7 +175,6 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); } } } diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index 1e78d226c..6626ef933 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -19,7 +19,7 @@ namespace Ombi.Schedule IOmbiAutomaticUpdater updater, IEmbyContentSync embySync, IPlexUserImporter userImporter, IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache, ISettingsService jobsettings, ISickRageSync srSync, IRefreshMetadata refresh, - INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedSync) + INewsletterJob newsletter) { _plexContentSync = plexContentSync; _radarrSync = radarrSync; @@ -33,7 +33,6 @@ namespace Ombi.Schedule _srSync = srSync; _refreshMetadata = refresh; _newsletter = newsletter; - _plexRecentlyAddedSync = recentlyAddedSync; } private readonly IPlexContentSync _plexContentSync; @@ -48,7 +47,6 @@ namespace Ombi.Schedule private readonly ISettingsService _jobSettings; private readonly IRefreshMetadata _refreshMetadata; private readonly INewsletterJob _newsletter; - private readonly IPlexRecentlyAddedSync _plexRecentlyAddedSync; public void Setup() { diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexRecentlyAddedSync.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexRecentlyAddedSync.cs deleted file mode 100644 index 6616f29bc..000000000 --- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexRecentlyAddedSync.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace Ombi.Schedule.Jobs.Plex -{ - public interface IPlexRecentlyAddedSync : IBaseJob - { - Task Start(); - } -} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs deleted file mode 100644 index dfcb9cac1..000000000 --- a/src/Ombi.Schedule/Jobs/Plex/PlexRecentlyAddedSync.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Threading.Tasks; -using Ombi.Api.Plex; - -namespace Ombi.Schedule.Jobs.Plex -{ - public class PlexRecentlyAddedSync : IPlexRecentlyAddedSync - { - public PlexRecentlyAddedSync(IPlexContentSync contentSync) - { - _sync = contentSync; - } - - private readonly IPlexContentSync _sync; - - public async Task Start() - { - await _sync.CacheContent(true); - } - - private bool _disposed; - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; - - if (disposing) - { - _sync?.Dispose(); - } - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - } -} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index 72b78a64d..8b9eb89f5 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -59,7 +59,7 @@
- + The Plex Sync is required
From 025797c1baebe7bf830d50f8caf82c84d659f501 Mon Sep 17 00:00:00 2001 From: Anojh Thayaparan Date: Thu, 19 Apr 2018 00:05:49 -0700 Subject: [PATCH 034/495] added background property to tvrequests API (#2172) * Added background property to TvRequests * set background property for new requests and display in UI --- src/Ombi.Core/Engine/TvRequestEngine.cs | 1 + src/Ombi.Core/Helpers/TvShowRequestBuilder.cs | 5 +- src/Ombi.Helpers/PosterPathHelper.cs | 14 + .../Entities/Requests/TvRequests.cs | 1 + ...413021646_tvrequestsbackground.Designer.cs | 950 ++++++++++++++++++ .../20180413021646_tvrequestsbackground.cs | 24 + .../Migrations/OmbiContextModelSnapshot.cs | 2 + .../app/requests/tvrequests.component.ts | 9 +- 8 files changed, 1003 insertions(+), 3 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.cs diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 7671c13fc..44eec3fd1 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -277,6 +277,7 @@ namespace Ombi.Core.Engine results.ImdbId = request.ImdbId; results.Overview = request.Overview; results.PosterPath = PosterPathHelper.FixPosterPath(request.PosterPath); + results.Background = PosterPathHelper.FixBackgroundPath(request.Background); results.QualityOverride = request.QualityOverride; results.RootFolder = request.RootFolder; diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs index 6e4d20be8..0b7d1ee6e 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs @@ -30,6 +30,7 @@ namespace Ombi.Core.Helpers public ChildRequests ChildRequest { get; set; } public List TvRequests { get; protected set; } public string PosterPath { get; protected set; } + public string BackdropPath { get; protected set; } public DateTime FirstAir { get; protected set; } public TvRequests NewRequest { get; protected set; } protected TvMazeShow ShowInfo { get; set; } @@ -44,6 +45,7 @@ namespace Ombi.Core.Helpers { var showIds = await MovieDbApi.GetTvExternals(result.Id); ShowInfo.externals.imdb = showIds.imdb_id; + BackdropPath = result.BackdropPath; break; } } @@ -240,7 +242,8 @@ namespace Ombi.Core.Helpers ImdbId = ShowInfo.externals?.imdb ?? string.Empty, TvDbId = tv.TvDbId, ChildRequests = new List(), - TotalSeasons = tv.Seasons.Count() + TotalSeasons = tv.Seasons.Count(), + Background = BackdropPath }; NewRequest.ChildRequests.Add(ChildRequest); diff --git a/src/Ombi.Helpers/PosterPathHelper.cs b/src/Ombi.Helpers/PosterPathHelper.cs index 7de767e44..ed1dee5c0 100644 --- a/src/Ombi.Helpers/PosterPathHelper.cs +++ b/src/Ombi.Helpers/PosterPathHelper.cs @@ -18,5 +18,19 @@ namespace Ombi.Helpers return poster; } + + public static string FixBackgroundPath(string background) + { + // https://image.tmdb.org/t/p/w1280/fJAvGOitU8y53ByeHnM4avtKFaG.jpg + + if (background.Contains("image.tmdb.org", CompareOptions.IgnoreCase)) + { + // Somehow we have a full path here for the poster, we only want the last segment + var backgroundSegments = background.Split('/'); + return backgroundSegments.Last(); + } + + return background; + } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Requests/TvRequests.cs b/src/Ombi.Store/Entities/Requests/TvRequests.cs index 88e1c36d7..7a6abc792 100644 --- a/src/Ombi.Store/Entities/Requests/TvRequests.cs +++ b/src/Ombi.Store/Entities/Requests/TvRequests.cs @@ -13,6 +13,7 @@ namespace Ombi.Store.Entities.Requests public string Overview { get; set; } public string Title { get; set; } public string PosterPath { get; set; } + public string Background { get; set; } public DateTime ReleaseDate { get; set; } public string Status { get; set; } /// diff --git a/src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.Designer.cs b/src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.Designer.cs new file mode 100644 index 000000000..b79528e34 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.Designer.cs @@ -0,0 +1,950 @@ +// +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 Ombi.Store.Entities.Requests; +using System; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180413021646_tvrequestsbackground")] + partial class tvrequestsbackground + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + 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 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.cs b/src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.cs new file mode 100644 index 000000000..d385d6000 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace Ombi.Store.Migrations +{ + public partial class tvrequestsbackground : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Background", + table: "TvRequests", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Background", + table: "TvRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 19e14a4ca..b722b0d30 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -645,6 +645,8 @@ namespace Ombi.Store.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("Background"); + b.Property("ImdbId"); b.Property("Overview"); diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts index 344bf5712..1ce5f0b8b 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts @@ -228,9 +228,14 @@ export class TvRequestsComponent implements OnInit { } private loadBackdrop(val: TreeNode): void { - this.imageService.getTvBanner(val.data.tvDbId).subscribe(x => { + if (val.data.background != null) { val.data.background = this.sanitizer.bypassSecurityTrustStyle - ("url(" + x + ")"); + ("url(https://image.tmdb.org/t/p/w1280" + val.data.background + ")"); + } else { + this.imageService.getTvBanner(val.data.tvDbId).subscribe(x => { + val.data.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + x + ")"); }); + } } } From 2fc4ef2613a1e26c30e24e4e8ed6205ba30d04f0 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 19 Apr 2018 14:26:22 +0100 Subject: [PATCH 035/495] Got plex oauth working! !wip --- src/Ombi.Api.Plex/IPlexApi.cs | 7 +- src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs | 27 ++++ src/Ombi.Api.Plex/PlexApi.cs | 79 +++++++++- src/Ombi.Api/Request.cs | 4 +- .../Authentication/PlexOAuthManager.cs | 76 ++++++++++ src/Ombi.Core/IPlexOAuthManager.cs | 16 +++ src/Ombi.DependencyInjection/IocExtensions.cs | 2 + .../Settings/Models/External/PlexSettings.cs | 2 +- src/Ombi/ClientApp/app/auth/auth.service.ts | 4 + src/Ombi/ClientApp/app/interfaces/IPlex.ts | 4 + .../app/services/applications/index.ts | 1 + .../app/services/applications/plex.service.ts | 4 + .../applications/plexoauth.service.ts | 20 +++ .../app/wizard/plex/plex.component.html | 7 + .../app/wizard/plex/plex.component.ts | 8 ++ .../app/wizard/plex/plexoauth.component.html | 14 ++ .../app/wizard/plex/plexoauth.component.ts | 76 ++++++++++ .../ClientApp/app/wizard/wizard.module.ts | 5 + .../Controllers/External/PlexController.cs | 38 ++++- src/Ombi/Controllers/PlexOAuthController.cs | 72 +++++++--- src/Ombi/Controllers/SettingsController.cs | 8 +- src/Ombi/Controllers/TokenController.cs | 135 +++++++++++------- 22 files changed, 535 insertions(+), 74 deletions(-) create mode 100644 src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs create mode 100644 src/Ombi.Core/Authentication/PlexOAuthManager.cs create mode 100644 src/Ombi.Core/IPlexOAuthManager.cs create mode 100644 src/Ombi/ClientApp/app/services/applications/plexoauth.service.ts create mode 100644 src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.html create mode 100644 src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index 0734262cf..cc61dfa5d 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -1,6 +1,8 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models.Friends; +using Ombi.Api.Plex.Models.OAuth; using Ombi.Api.Plex.Models.Server; using Ombi.Api.Plex.Models.Status; @@ -20,5 +22,8 @@ namespace Ombi.Api.Plex Task GetUsers(string authToken); Task GetAccount(string authToken); Task GetRecentlyAdded(string authToken, string uri, string sectionId); + Task CreatePin(); + Task GetPin(int pinId); + Uri GetOAuthUrl(int pinId, string code, string applicationUrl, bool wizard); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs b/src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs new file mode 100644 index 000000000..e65cd91d4 --- /dev/null +++ b/src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs @@ -0,0 +1,27 @@ +using System; + +namespace Ombi.Api.Plex.Models.OAuth +{ + public class OAuthPin + { + public int id { get; set; } + public string code { get; set; } + public bool trusted { get; set; } + public string clientIdentifier { get; set; } + public Location location { get; set; } + public int expiresIn { get; set; } + public DateTime createdAt { get; set; } + public DateTime expiresAt { get; set; } + public string authToken { get; set; } + } + + public class Location + { + public string code { get; set; } + public string country { get; set; } + public string city { get; set; } + public string subdivisions { get; set; } + public string coordinates { get; set; } + } + +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index e6c52d1df..5fb87aca7 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -1,20 +1,49 @@ -using System.Net.Http; +using System; +using System.Net.Http; +using System.Reflection; using System.Threading.Tasks; using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models.Friends; +using Ombi.Api.Plex.Models.OAuth; using Ombi.Api.Plex.Models.Server; using Ombi.Api.Plex.Models.Status; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; namespace Ombi.Api.Plex { public class PlexApi : IPlexApi { - public PlexApi(IApi api) + public PlexApi(IApi api, ISettingsService settings) { Api = api; + _plex = settings; } private IApi Api { get; } + private readonly ISettingsService _plex; + + private string _clientId; + private string ClientIdSecret + { + get + { + if (string.IsNullOrEmpty(_clientId)) + { + var settings = _plex.GetSettings(); + if (settings.UniqueInstallCode.IsNullOrEmpty()) + { + settings.UniqueInstallCode = Guid.NewGuid().ToString("N"); + _plex.SaveSettings(settings); + } + + _clientId = settings.UniqueInstallCode; + } + + return _clientId; + } + } private const string SignInUri = "https://plex.tv/users/sign_in.json"; private const string FriendsUri = "https://plex.tv/pms/friends/all"; @@ -156,6 +185,50 @@ namespace Ombi.Api.Plex return await Api.Request(request); } + public async Task CreatePin() + { + var request = new Request($"api/v2/pins", "https://plex.tv/", HttpMethod.Post); + request.AddQueryString("strong", "true"); + AddHeaders(request); + + return await Api.Request(request); + } + + public async Task GetPin(int pinId) + { + var request = new Request($"api/v2/pins/{pinId}", "https://plex.tv/", HttpMethod.Get); + AddHeaders(request); + + return await Api.Request(request); + } + + public Uri GetOAuthUrl(int pinId, string code, string applicationUrl, bool wizard) + { + var request = new Request("auth#", "https://app.plex.tv", HttpMethod.Get); + AddHeaders(request); + var forwardUrl = wizard + ? new Request($"Wizard/OAuth/{pinId}", applicationUrl, HttpMethod.Get) + : new Request($"api/v1/PlexOAuth/{pinId}", applicationUrl, HttpMethod.Get); + + request.AddQueryString("forwardUrl", forwardUrl.FullUri.ToString()); + request.AddQueryString("pinID", pinId.ToString()); + request.AddQueryString("code", code); + request.AddQueryString("context[device][product]", "Ombi"); + request.AddQueryString("context[device][environment]", "bundled"); + request.AddQueryString("clientID", $"OmbiV3{ClientIdSecret}"); + + if (request.FullUri.Fragment.Equals("#")) + { + var uri = request.FullUri.ToString(); + var withoutEnd = uri.Remove(uri.Length - 1, 1); + var startOfQueryLocation = withoutEnd.IndexOf('?'); + var better = withoutEnd.Insert(startOfQueryLocation, "#"); + request.FullUri = new Uri(better); + } + + return request.FullUri; + } + /// /// Adds the required headers and also the authorization header /// @@ -173,7 +246,7 @@ namespace Ombi.Api.Plex /// private void AddHeaders(Request request) { - request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3"); + request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3{ClientIdSecret}"); request.AddHeader("X-Plex-Product", "Ombi"); request.AddHeader("X-Plex-Version", "3"); request.AddContentHeader("Content-Type", request.ContentType == ContentType.Json ? "application/json" : "application/xml"); diff --git a/src/Ombi.Api/Request.cs b/src/Ombi.Api/Request.cs index e4120ed9c..89c3a7f2d 100644 --- a/src/Ombi.Api/Request.cs +++ b/src/Ombi.Api/Request.cs @@ -10,7 +10,7 @@ namespace Ombi.Api { public Request() { - + } public Request(string endpoint, string baseUrl, HttpMethod http, ContentType contentType = ContentType.Json) @@ -105,10 +105,10 @@ namespace Ombi.Api hasQuery = true; startingTag = builder.Query.Contains("?") ? "&" : "?"; } - builder.Query = hasQuery ? $"{builder.Query}{startingTag}{key}={value}" : $"{startingTag}{key}={value}"; + _modified = builder.Uri; } diff --git a/src/Ombi.Core/Authentication/PlexOAuthManager.cs b/src/Ombi.Core/Authentication/PlexOAuthManager.cs new file mode 100644 index 000000000..d3bab0a05 --- /dev/null +++ b/src/Ombi.Core/Authentication/PlexOAuthManager.cs @@ -0,0 +1,76 @@ +using System; +using System.Threading.Tasks; +using Ombi.Api.Plex; +using Ombi.Api.Plex.Models; +using Ombi.Api.Plex.Models.OAuth; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Settings.Settings.Models; + +namespace Ombi.Core.Authentication +{ + public class PlexOAuthManager : IPlexOAuthManager + { + public PlexOAuthManager(IPlexApi api, ISettingsService settings) + { + _api = api; + _customizationSettingsService = settings; + } + + private readonly IPlexApi _api; + private readonly ISettingsService _customizationSettingsService; + + public async Task RequestPin() + { + var pin = await _api.CreatePin(); + return pin; + } + + public async Task GetAccessTokenFromPin(int pinId) + { + var pin = await _api.GetPin(pinId); + if (pin.expiresAt < DateTime.UtcNow) + { + return string.Empty; + } + + if (pin.authToken.IsNullOrEmpty()) + { + // Looks like we do not have a pin yet, we should retry a few times. + var retryCount = 0; + var retryMax = 5; + var retryWaitMs = 1000; + while (pin.authToken.IsNullOrEmpty() && retryCount < retryMax) + { + retryCount++; + await Task.Delay(retryWaitMs); + pin = await _api.GetPin(pinId); + } + } + return pin.authToken; + } + + public async Task GetAccount(string accessToken) + { + return await _api.GetAccount(accessToken); + } + + public async Task GetOAuthUrl(int pinId, string code) + { + var settings = await _customizationSettingsService.GetSettingsAsync(); + if (settings.ApplicationUrl.IsNullOrEmpty()) + { + return null; + } + + var url = _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl, false); + return url; + } + + public Uri GetWizardOAuthUrl(int pinId, string code, string websiteAddress) + { + var url = _api.GetOAuthUrl(pinId, code, websiteAddress, true); + return url; + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/IPlexOAuthManager.cs b/src/Ombi.Core/IPlexOAuthManager.cs new file mode 100644 index 000000000..142d4162a --- /dev/null +++ b/src/Ombi.Core/IPlexOAuthManager.cs @@ -0,0 +1,16 @@ +using System; +using System.Threading.Tasks; +using Ombi.Api.Plex.Models; +using Ombi.Api.Plex.Models.OAuth; + +namespace Ombi.Core.Authentication +{ + public interface IPlexOAuthManager + { + Task GetAccessTokenFromPin(int pinId); + Task RequestPin(); + Task GetOAuthUrl(int pinId, string code); + Uri GetWizardOAuthUrl(int pinId, string code, string websiteAddress); + Task GetAccount(string accessToken); + } +} \ No newline at end of file diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index e2f667465..68f4b7218 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -51,6 +51,7 @@ using Ombi.Store.Repository.Requests; using Ombi.Updater; using PlexContentCacher = Ombi.Schedule.Jobs.Plex; using Ombi.Api.Telegram; +using Ombi.Core.Authentication; using Ombi.Core.Processor; using Ombi.Schedule.Jobs.Plex.Interfaces; using Ombi.Schedule.Jobs.SickRage; @@ -82,6 +83,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterHttp(this IServiceCollection services) { diff --git a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs index 3fcde951a..dd92eba18 100644 --- a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs @@ -6,8 +6,8 @@ namespace Ombi.Core.Settings.Models.External public sealed class PlexSettings : Ombi.Settings.Settings.Models.Settings { public bool Enable { get; set; } + public string UniqueInstallCode { get; set; } public List Servers { get; set; } - } public class PlexServers : ExternalSettings diff --git a/src/Ombi/ClientApp/app/auth/auth.service.ts b/src/Ombi/ClientApp/app/auth/auth.service.ts index b9899c9a4..92b41ccd9 100644 --- a/src/Ombi/ClientApp/app/auth/auth.service.ts +++ b/src/Ombi/ClientApp/app/auth/auth.service.ts @@ -18,6 +18,10 @@ export class AuthService extends ServiceHelpers { return this.http.post(`${this.url}/`, JSON.stringify(login), {headers: this.headers}); } + public oAuth(pin: number): Observable { + return this.http.get(`${this.url}/${pin}`, {headers: this.headers}); + } + public requiresPassword(login: IUserLogin): Observable { return this.http.post(`${this.url}/requirePassword`, JSON.stringify(login), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/interfaces/IPlex.ts b/src/Ombi/ClientApp/app/interfaces/IPlex.ts index 7125ae4bc..823b80d32 100644 --- a/src/Ombi/ClientApp/app/interfaces/IPlex.ts +++ b/src/Ombi/ClientApp/app/interfaces/IPlex.ts @@ -2,6 +2,10 @@ user: IPlexUser; } +export interface IPlexOAuthAccessToken { + accessToken: string; +} + export interface IPlexUser { email: string; uuid: string; diff --git a/src/Ombi/ClientApp/app/services/applications/index.ts b/src/Ombi/ClientApp/app/services/applications/index.ts index 9433dfce0..98c61cf04 100644 --- a/src/Ombi/ClientApp/app/services/applications/index.ts +++ b/src/Ombi/ClientApp/app/services/applications/index.ts @@ -4,3 +4,4 @@ export * from "./plex.service"; export * from "./radarr.service"; export * from "./sonarr.service"; export * from "./tester.service"; +export * from "./plexoauth.service"; diff --git a/src/Ombi/ClientApp/app/services/applications/plex.service.ts b/src/Ombi/ClientApp/app/services/applications/plex.service.ts index c04a990e1..53fd31f9d 100644 --- a/src/Ombi/ClientApp/app/services/applications/plex.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/plex.service.ts @@ -29,4 +29,8 @@ export class PlexService extends ServiceHelpers { public getFriends(): Observable { return this.http.get(`${this.url}Friends`, {headers: this.headers}); } + + public oAuth(wizard: boolean): Observable { + return this.http.get(`${this.url}oauth/${wizard}`, {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/app/services/applications/plexoauth.service.ts b/src/Ombi/ClientApp/app/services/applications/plexoauth.service.ts new file mode 100644 index 000000000..59a884714 --- /dev/null +++ b/src/Ombi/ClientApp/app/services/applications/plexoauth.service.ts @@ -0,0 +1,20 @@ +import { PlatformLocation } from "@angular/common"; +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; + +import { Observable } from "rxjs/Rx"; + +import { ServiceHelpers } from "../service.helpers"; + +import { IPlexOAuthAccessToken } from "../../interfaces"; + +@Injectable() +export class PlexOAuthService extends ServiceHelpers { + constructor(http: HttpClient, public platformLocation: PlatformLocation) { + super(http, "/api/v1/PlexOAuth/", platformLocation); + } + + public oAuth(pin: number): Observable { + return this.http.get(`${this.url}${pin}`, {headers: this.headers}); + } +} diff --git a/src/Ombi/ClientApp/app/wizard/plex/plex.component.html b/src/Ombi/ClientApp/app/wizard/plex/plex.component.html index 2ba63c43e..6c4b846a7 100644 --- a/src/Ombi/ClientApp/app/wizard/plex/plex.component.html +++ b/src/Ombi/ClientApp/app/wizard/plex/plex.component.html @@ -20,6 +20,13 @@
+ +
+
+ +
+
+ diff --git a/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts b/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts index 146d794fe..6bc21d628 100644 --- a/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts +++ b/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts @@ -70,4 +70,12 @@ export class PlexComponent { }); }); } + + public oauth() { + this.plexService.oAuth(true).subscribe(x => { + if(x.url) { + window.location.href = x.url; + } + }); + } } diff --git a/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.html b/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.html new file mode 100644 index 000000000..d60f1d1f0 --- /dev/null +++ b/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.html @@ -0,0 +1,14 @@ + + +
+
+
+

Plex Authentication

+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts b/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts new file mode 100644 index 000000000..1397fe7f5 --- /dev/null +++ b/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts @@ -0,0 +1,76 @@ +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { ConfirmationService } from "primeng/primeng"; + +import { PlexOAuthService, IdentityService, SettingsService } from "../../services"; +import { AuthService } from "./../../auth/auth.service"; + +@Component({ + templateUrl: "./plexoauth.component.html", +}) +export class PlexOAuthComponent implements OnInit { + public pinId: number; + + constructor(private route: ActivatedRoute, + private plexOauth: PlexOAuthService, + private confirmationService: ConfirmationService, + private identityService: IdentityService, + private settings: SettingsService, + private router: Router, + private auth: AuthService) { + + this.route.params + .subscribe((params: any) => { + this.pinId = params.pin; + }); + } + + ngOnInit(): void { + this.plexOauth.oAuth(this.pinId).subscribe(x => { + x.accessToken; + + this.confirmationService.confirm({ + message: "Do you want your Plex user to be the main admin account on Ombi?", + header: "Use Plex Account", + icon: "fa fa-check", + accept: () => { + this.identityService.createWizardUser({ + username: "", + password: "", + usePlexAdminAccount: true, + }).subscribe(x => { + if (x) { + this.auth.oAuth(this.pinId).subscribe(c => { + localStorage.setItem("id_token", c.access_token); + + // Mark that we have done the settings now + this.settings.getOmbi().subscribe(ombi => { + ombi.wizard = true; + + this.settings.saveOmbi(ombi).subscribe(x => { + this.settings.getUserManagementSettings().subscribe(usr => { + + usr.importPlexAdmin = true; + this.settings.saveUserManagementSettings(usr).subscribe(saved => { + this.router.navigate(["login"]); + }); + }); + + }); + }); + }); + } else { + //this.notificationService.error("Could not get the Plex Admin Information"); + return; + } + }); + }, + reject: () => { + this.router.navigate(["Wizard/CreateAdmin"]); + }, + }); + }); + } + +} diff --git a/src/Ombi/ClientApp/app/wizard/wizard.module.ts b/src/Ombi/ClientApp/app/wizard/wizard.module.ts index 96cbdddc1..7eae2e4f4 100644 --- a/src/Ombi/ClientApp/app/wizard/wizard.module.ts +++ b/src/Ombi/ClientApp/app/wizard/wizard.module.ts @@ -14,6 +14,8 @@ import { WelcomeComponent } from "./welcome/welcome.component"; import { EmbyService } from "../services"; import { PlexService } from "../services"; import { IdentityService } from "../services"; +import { PlexOAuthService } from "../services"; +import { PlexOAuthComponent } from "./plex/plexoauth.component"; const routes: Routes = [ { path: "", component: WelcomeComponent}, @@ -21,6 +23,7 @@ const routes: Routes = [ { path: "Plex", component: PlexComponent}, { path: "Emby", component: EmbyComponent}, { path: "CreateAdmin", component: CreateAdminComponent}, + { path: "OAuth/:pin", component: PlexOAuthComponent}, ]; @NgModule({ imports: [ @@ -33,6 +36,7 @@ const routes: Routes = [ WelcomeComponent, MediaServerComponent, PlexComponent, + PlexOAuthComponent, CreateAdminComponent, EmbyComponent, ], @@ -44,6 +48,7 @@ const routes: Routes = [ IdentityService, EmbyService, ConfirmationService, + PlexOAuthService, ], }) diff --git a/src/Ombi/Controllers/External/PlexController.cs b/src/Ombi/Controllers/External/PlexController.cs index 2d45d7565..cde78bc64 100644 --- a/src/Ombi/Controllers/External/PlexController.cs +++ b/src/Ombi/Controllers/External/PlexController.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging; using Ombi.Api.Plex; using Ombi.Api.Plex.Models; using Ombi.Attributes; +using Ombi.Core.Authentication; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; @@ -21,16 +22,18 @@ namespace Ombi.Controllers.External public class PlexController : Controller { public PlexController(IPlexApi plexApi, ISettingsService plexSettings, - ILogger logger) + ILogger logger, IPlexOAuthManager manager) { PlexApi = plexApi; PlexSettings = plexSettings; _log = logger; + _plexOAuthManager = manager; } private IPlexApi PlexApi { get; } private ISettingsService PlexSettings { get; } private readonly ILogger _log; + private readonly IPlexOAuthManager _plexOAuthManager; /// /// Signs into the Plex API. @@ -66,6 +69,7 @@ namespace Ombi.Controllers.External _log.LogDebug("Adding first server"); settings.Enable = true; + settings.UniqueInstallCode = Guid.NewGuid().ToString("N"); settings.Servers = new List { new PlexServers { @@ -173,5 +177,37 @@ namespace Ombi.Controllers.External // Filter out any dupes return vm.DistinctBy(x => x.Id); } + + [HttpGet("oauth/{wizard:bool}")] + [AllowAnonymous] + public async Task OAuth(bool wizard) + { + //https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd + // Plex OAuth + // Redirect them to Plex + // We need a PIN first + var pin = await _plexOAuthManager.RequestPin(); + + Uri url; + if (!wizard) + { + url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code); + } + else + { + var websiteAddress =$"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}"; + url = _plexOAuthManager.GetWizardOAuthUrl(pin.id, pin.code, websiteAddress); + } + + if (url == null) + { + return new JsonResult(new + { + error = "Application URL has not been set" + }); + } + + return new JsonResult(new {url = url.ToString()}); + } } } diff --git a/src/Ombi/Controllers/PlexOAuthController.cs b/src/Ombi/Controllers/PlexOAuthController.cs index 8f33e37be..2aad2a2a9 100644 --- a/src/Ombi/Controllers/PlexOAuthController.cs +++ b/src/Ombi/Controllers/PlexOAuthController.cs @@ -1,9 +1,19 @@ -using System.Net; +using System; +using System.Collections.Generic; +using System.Net; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http.Internal; using System.IO; +using System.Linq; using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Ombi.Api.Plex; +using Ombi.Core.Authentication; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Helpers; namespace Ombi.Controllers { @@ -12,29 +22,57 @@ namespace Ombi.Controllers [AllowAnonymous] public class PlexOAuthController : Controller { - - [HttpGet] - public IActionResult OAuthCallBack() + public PlexOAuthController(IPlexOAuthManager manager, IPlexApi plexApi, ISettingsService plexSettings, + ILogger log) { - var bodyStr = ""; - var req = Request; + _manager = manager; + _plexApi = plexApi; + _plexSettings = plexSettings; + _log = log; + } - // Allows using several time the stream in ASP.Net Core - req.EnableRewind(); + private readonly IPlexOAuthManager _manager; + private readonly IPlexApi _plexApi; + private readonly ISettingsService _plexSettings; + private readonly ILogger _log; - // Arguments: Stream, Encoding, detect encoding, buffer size - // AND, the most important: keep stream opened - using (StreamReader reader - = new StreamReader(req.Body, Encoding.UTF8, true, 1024, true)) + [HttpGet("{pinId:int}")] + public async Task OAuthWizardCallBack([FromRoute] int pinId) + { + var accessToken = await _manager.GetAccessTokenFromPin(pinId); + if (accessToken.IsNullOrEmpty()) { - bodyStr = reader.ReadToEnd(); + return Json(new + { + success = false, + error = "Authentication did not work. Please try again" + }); } + var settings = await _plexSettings.GetSettingsAsync(); + var server = await _plexApi.GetServer(accessToken); + var servers = server.Server.FirstOrDefault(); + if (servers == null) + { + _log.LogWarning("Looks like we can't find any Plex Servers"); + } + _log.LogDebug("Adding first server"); - // Rewind, so the core is not lost when it looks the body for the request - req.Body.Position = 0; + settings.Enable = true; + settings.Servers = new List { + new PlexServers + { + PlexAuthToken = accessToken, + Id = new Random().Next(), + Ip = servers?.LocalAddresses?.Split(new []{','}, StringSplitOptions.RemoveEmptyEntries)?.FirstOrDefault() ?? string.Empty, + MachineIdentifier = servers?.MachineIdentifier ?? string.Empty, + Port = int.Parse(servers?.Port ?? "0"), + Ssl = (servers?.Scheme ?? "http") != "http", + Name = "Server 1", + } + }; - // Do your work with bodyStr - return Ok(); + await _plexSettings.SaveSettingsAsync(settings); + return Json(new { accessToken }); } } } diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 30469cd57..867a7517c 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -142,7 +142,13 @@ namespace Ombi.Controllers [HttpGet("plex")] public async Task PlexSettings() { - return await Get(); + var s = await Get(); + if (s.UniqueInstallCode.IsNullOrEmpty()) + { + s.UniqueInstallCode = Guid.NewGuid().ToString("N"); + } + + return s; } /// diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 5d524b7ba..62e43635d 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -25,18 +25,21 @@ namespace Ombi.Controllers [Produces("application/json")] public class TokenController { - public TokenController(OmbiUserManager um, IOptions ta, IAuditRepository audit, ITokenRepository token) + public TokenController(OmbiUserManager um, IOptions ta, IAuditRepository audit, ITokenRepository token, + IPlexOAuthManager oAuthManager) { _userManager = um; _tokenAuthenticationOptions = ta.Value; _audit = audit; _token = token; + _plexOAuthManager = oAuthManager; } private readonly TokenAuthentication _tokenAuthenticationOptions; private readonly IAuditRepository _audit; private readonly ITokenRepository _token; private readonly OmbiUserManager _userManager; + private readonly IPlexOAuthManager _plexOAuthManager; /// /// Gets the token. @@ -69,65 +72,101 @@ namespace Ombi.Controllers // Verify Password if (await _userManager.CheckPasswordAsync(user, model.Password)) { - var roles = await _userManager.GetRolesAsync(user); - - if (roles.Contains(OmbiRoles.Disabled)) - { - return new UnauthorizedResult(); - } - - user.LastLoggedIn = DateTime.UtcNow; - await _userManager.UpdateAsync(user); - - var claims = new List - { - new Claim(JwtRegisteredClaimNames.Sub, user.UserName), - new Claim(ClaimTypes.NameIdentifier, user.Id), - new Claim(ClaimTypes.Name, user.UserName), - new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) - }; - claims.AddRange(roles.Select(role => new Claim("role", role))); - - var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey)); - var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); - - - var token = new JwtSecurityToken( - claims: claims, - expires: model.RememberMe ? DateTime.UtcNow.AddDays(7) : DateTime.UtcNow.AddHours(5), - signingCredentials: creds, - audience: "Ombi", issuer: "Ombi" - ); - var accessToken = new JwtSecurityTokenHandler().WriteToken(token); - if (model.RememberMe) - { - // Save the token so we can refresh it later - //await _token.CreateToken(new Tokens() {Token = accessToken, User = user}); - } - - return new JsonResult(new - { - access_token = accessToken, - expiration = token.ValidTo - }); + return await CreateToken(model.RememberMe, user); } } else { // Plex OAuth // Redirect them to Plex + // We need a PIN first + var pin = await _plexOAuthManager.RequestPin(); - var request = new Request("auth", "https://app.plex.tv", HttpMethod.Get); - request.AddQueryString("clientID", "OMBIv3"); - request.AddQueryString("forwardUrl", "http://localhost:5000"); - request.AddQueryString("context-device-product", "http://localhost:5000"); - return new RedirectResult("https://app.plex.tv/auth#?forwardUrl=http://localhost:5000/api/v1/plexoauth&clientID=OMBIv3&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO"); - + //https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd + var url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code); + if (url == null) + { + return new JsonResult(new + { + error = "Application URL has not been set" + }); + } + return new RedirectResult(url.ToString()); } return new UnauthorizedResult(); } + private async Task CreateToken(bool rememberMe, OmbiUser user) + { + var roles = await _userManager.GetRolesAsync(user); + + if (roles.Contains(OmbiRoles.Disabled)) + { + return new UnauthorizedResult(); + } + + user.LastLoggedIn = DateTime.UtcNow; + await _userManager.UpdateAsync(user); + + var claims = new List + { + new Claim(JwtRegisteredClaimNames.Sub, user.UserName), + new Claim(ClaimTypes.NameIdentifier, user.Id), + new Claim(ClaimTypes.Name, user.UserName), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) + }; + claims.AddRange(roles.Select(role => new Claim("role", role))); + + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey)); + var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + + + var token = new JwtSecurityToken( + claims: claims, + expires: rememberMe ? DateTime.UtcNow.AddDays(7) : DateTime.UtcNow.AddHours(5), + signingCredentials: creds, + audience: "Ombi", issuer: "Ombi" + ); + var accessToken = new JwtSecurityTokenHandler().WriteToken(token); + if (rememberMe) + { + // Save the token so we can refresh it later + //await _token.CreateToken(new Tokens() {Token = accessToken, User = user}); + } + + return new JsonResult(new + { + access_token = accessToken, + expiration = token.ValidTo + }); + } + + [HttpGet("{pinId:int}")] + public async Task OAuth(int pinId) + { + var accessToken = await _plexOAuthManager.GetAccessTokenFromPin(pinId); + + // Let's look for the users account + var account = await _plexOAuthManager.GetAccount(accessToken); + + // Get the ombi user + var user = await _userManager.FindByNameAsync(account.user.username); + + if (user == null) + { + // Could this be an email login? + user = await _userManager.FindByEmailAsync(account.user.email); + + if (user == null) + { + return new UnauthorizedResult(); + } + } + + return await CreateToken(true, user); + } + /// /// Refreshes the token. /// From 1c54eedc6ff66ac93ecdc64da7cb7612c42485d6 Mon Sep 17 00:00:00 2001 From: Anojh Thayaparan Date: Thu, 19 Apr 2018 11:08:49 -0700 Subject: [PATCH 036/495] Added View on Emby Button (#2173) * Added Emby content url property * Fetch and set the Emby url property * Added View on Emby button to frontend and did UI work * removed debug logging --- .../Models/Search/SearchViewModel.cs | 1 + .../Rule/Rules/Search/EmbyAvailabilityRule.cs | 1 + src/Ombi.Helpers/EmbyHelper.cs | 17 + .../Jobs/Emby/EmbyContentSync.cs | 2 + src/Ombi.Store/Entities/EmbyContent.cs | 1 + .../20180419054711_EmbyButton.Designer.cs | 950 ++++++++++++++++++ .../Migrations/20180419054711_EmbyButton.cs | 24 + .../Migrations/OmbiContextModelSnapshot.cs | 2 + .../app/interfaces/ISearchMovieResult.ts | 1 + .../app/interfaces/ISearchTvResult.ts | 1 + .../app/search/moviesearch.component.html | 1 + .../app/search/tvsearch.component.html | 24 +- src/Ombi/wwwroot/translations/da.json | 1 + src/Ombi/wwwroot/translations/de.json | 1 + src/Ombi/wwwroot/translations/en.json | 1 + src/Ombi/wwwroot/translations/es.json | 1 + src/Ombi/wwwroot/translations/fr.json | 1 + src/Ombi/wwwroot/translations/it.json | 1 + src/Ombi/wwwroot/translations/nl.json | 1 + src/Ombi/wwwroot/translations/no.json | 1 + src/Ombi/wwwroot/translations/sv.json | 1 + 21 files changed, 1026 insertions(+), 8 deletions(-) create mode 100644 src/Ombi.Helpers/EmbyHelper.cs create mode 100644 src/Ombi.Store/Migrations/20180419054711_EmbyButton.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180419054711_EmbyButton.cs diff --git a/src/Ombi.Core/Models/Search/SearchViewModel.cs b/src/Ombi.Core/Models/Search/SearchViewModel.cs index 8c8d49aff..0de295a69 100644 --- a/src/Ombi.Core/Models/Search/SearchViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchViewModel.cs @@ -10,6 +10,7 @@ namespace Ombi.Core.Models.Search public bool Requested { get; set; } public bool Available { get; set; } public string PlexUrl { get; set; } + public string EmbyUrl { get; set; } public string Quality { get; set; } public abstract RequestType Type { get; } diff --git a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs index 8ac96701d..4f2f56b28 100644 --- a/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/EmbyAvailabilityRule.cs @@ -44,6 +44,7 @@ namespace Ombi.Core.Rule.Rules.Search if (item != null) { obj.Available = true; + obj.EmbyUrl = item.Url; if (obj.Type == RequestType.TvShow) { diff --git a/src/Ombi.Helpers/EmbyHelper.cs b/src/Ombi.Helpers/EmbyHelper.cs new file mode 100644 index 000000000..cf6904a0c --- /dev/null +++ b/src/Ombi.Helpers/EmbyHelper.cs @@ -0,0 +1,17 @@ +using System; +using System.Globalization; +using System.Collections.Generic; +using System.Text; + +namespace Ombi.Helpers +{ + public class EmbyHelper + { + public static string GetEmbyMediaUrl(string mediaId) + { + var url = + $"http://app.emby.media/itemdetails.html?id={mediaId}"; + return url; + } + } +} diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 99d4f5a85..4d0026f48 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -114,6 +114,7 @@ namespace Ombi.Schedule.Jobs.Emby Title = tvInfo.Name, Type = EmbyMediaType.Series, EmbyId = tvShow.Id, + Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id), AddedAt = DateTime.UtcNow }); } @@ -135,6 +136,7 @@ namespace Ombi.Schedule.Jobs.Emby Title = movieInfo.Name, Type = EmbyMediaType.Movie, EmbyId = movieInfo.Id, + Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id), AddedAt = DateTime.UtcNow, }); } diff --git a/src/Ombi.Store/Entities/EmbyContent.cs b/src/Ombi.Store/Entities/EmbyContent.cs index 1d3f57f13..4506ef071 100644 --- a/src/Ombi.Store/Entities/EmbyContent.cs +++ b/src/Ombi.Store/Entities/EmbyContent.cs @@ -48,6 +48,7 @@ namespace Ombi.Store.Entities public string TheMovieDbId { get; set; } public string TvDbId { get; set; } + public string Url { get; set; } public ICollection Episodes { get; set; } } diff --git a/src/Ombi.Store/Migrations/20180419054711_EmbyButton.Designer.cs b/src/Ombi.Store/Migrations/20180419054711_EmbyButton.Designer.cs new file mode 100644 index 000000000..c5ddc8fa2 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180419054711_EmbyButton.Designer.cs @@ -0,0 +1,950 @@ +// +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 Ombi.Store.Entities.Requests; +using System; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180419054711_EmbyButton")] + partial class EmbyButton + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + 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 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180419054711_EmbyButton.cs b/src/Ombi.Store/Migrations/20180419054711_EmbyButton.cs new file mode 100644 index 000000000..07e5cb730 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180419054711_EmbyButton.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace Ombi.Store.Migrations +{ + public partial class EmbyButton : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Url", + table: "EmbyContent", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Url", + table: "EmbyContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index b722b0d30..248551d97 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -197,6 +197,8 @@ namespace Ombi.Store.Migrations b.Property("Type"); + b.Property("Url"); + b.HasKey("Id"); b.ToTable("EmbyContent"); diff --git a/src/Ombi/ClientApp/app/interfaces/ISearchMovieResult.ts b/src/Ombi/ClientApp/app/interfaces/ISearchMovieResult.ts index c5301d2b0..ee66598fd 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISearchMovieResult.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISearchMovieResult.ts @@ -21,6 +21,7 @@ requested: boolean; available: boolean; plexUrl: string; + embyUrl: string; quality: string; digitalReleaseDate: Date; diff --git a/src/Ombi/ClientApp/app/interfaces/ISearchTvResult.ts b/src/Ombi/ClientApp/app/interfaces/ISearchTvResult.ts index f0afa76b2..81d716bfc 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISearchTvResult.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISearchTvResult.ts @@ -27,6 +27,7 @@ export interface ISearchTvResult { requested: boolean; available: boolean; plexUrl: string; + embyUrl: string; firstSeason: boolean; latestSeason: boolean; } diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index cac78531b..3130cb79d 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -85,6 +85,7 @@

+ + {{ 'Search.ViewOnPlex' | translate }} + + +
-
-
+
+
diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index ec4b0bce5..dd3872ac0 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -76,6 +76,7 @@ "DigitalDate": "Digital Release: {{date}}", "TheatricalRelease": "Theatrical Release: {{date}}", "ViewOnPlex": "Se på Plex", + "ViewOnEmby": "Se på Emby", "RequestAdded": "{{title}} er anmodet med succes", "Similar": "Similar", "Movies": { diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index df8b6a724..2a46e2db3 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -76,6 +76,7 @@ "DigitalDate": "Digital Release: {{date}}", "TheatricalRelease": "Theatrical Release: {{date}}", "ViewOnPlex": "In Plex anschauen", + "ViewOnEmby": "In Emby anschauen", "RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt", "Similar": "Similar", "Movies": { diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 124c26fc5..cb7c0fe8b 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -81,6 +81,7 @@ "DigitalDate": "Digital Release: {{date}}", "TheatricalRelease":"Theatrical Release: {{date}}", "ViewOnPlex": "View On Plex", + "ViewOnEmby": "View On Emby", "RequestAdded": "Request for {{title}} has been added successfully", "Similar":"Similar", "Movies": { diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 6b2f87874..17036ade3 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -76,6 +76,7 @@ "DigitalDate": "Digital Release: {{date}}", "TheatricalRelease": "Theatrical Release: {{date}}", "ViewOnPlex": "Ver en Plex", + "ViewOnEmby": "Ver en Emby", "RequestAdded": "La solicitud de {{title}} se ha agregado con éxito", "Similar": "Similar", "Movies": { diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 983763a08..bc3f395dd 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -76,6 +76,7 @@ "DigitalDate": "Digital Release: {{date}}", "TheatricalRelease": "Theatrical Release: {{date}}", "ViewOnPlex": "Regarder sur Plex", + "ViewOnEmby": "Regarder sur Emby", "RequestAdded": "La demande pour {{title}} a été ajoutée avec succès", "Similar": "Similar", "Movies": { diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 2081ce2a1..1e91047ff 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -76,6 +76,7 @@ "DigitalDate": "Digital Release: {{date}}", "TheatricalRelease": "Theatrical Release: {{date}}", "ViewOnPlex": "Guarda su Plex", + "ViewOnEmby": "Guarda su Emby", "RequestAdded": "La richiesta per {{title}} è stata aggiunta correttamente", "Similar": "Similar", "Movies": { diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index a9ba6b683..d5fd62bba 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -76,6 +76,7 @@ "DigitalDate": "Digital Release: {{date}}", "TheatricalRelease": "Theatrical Release: {{date}}", "ViewOnPlex": "Bekijk op Plex", + "ViewOnEmby": "Bekijk op Emby", "RequestAdded": "Aanvraag voor {{title}} is succesvol toegevoegd", "Similar": "Similar", "Movies": { diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index cbaf1379a..d94e977df 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -76,6 +76,7 @@ "DigitalDate": "Digital utgivelse: {{date}}", "TheatricalRelease": "Kinopremiere: {{date}}", "ViewOnPlex": "Spill av på Plex", + "ViewOnEmby": "Spill av på Emby", "RequestAdded": "Forespørsel om {{title}} er lagt til", "Similar": "Lignende", "Movies": { diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index b750b5e0c..cbc87c2d4 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -76,6 +76,7 @@ "DigitalDate": "Digital Release: {{date}}", "TheatricalRelease": "Theatrical Release: {{date}}", "ViewOnPlex": "Visa på Plex", + "ViewOnEmby": "Visa på Emby", "RequestAdded": "Efterfrågan om {{title}} har lagts till", "Similar": "Similar", "Movies": { From 2cd9c4d9b123f4849c11304d5fd2e159553f32c7 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 19 Apr 2018 22:15:20 +0100 Subject: [PATCH 037/495] frontend is all done !wip --- src/Ombi.Api.Plex/PlexApi.cs | 2 +- src/Ombi/ClientApp/app/app.module.ts | 3 ++ src/Ombi/ClientApp/app/auth/IUserLogin.ts | 1 + .../ClientApp/app/login/login.component.html | 12 ++++++ .../ClientApp/app/login/login.component.ts | 39 ++++++++++++++++++- .../app/login/loginoauth.component.html | 9 +++++ .../app/login/loginoauth.component.ts | 35 +++++++++++++++++ .../app/services/settings.service.ts | 4 ++ .../createadmin/createadmin.component.ts | 2 +- .../app/wizard/plex/plex.component.html | 2 +- .../app/wizard/plex/plex.component.ts | 24 ++++-------- .../app/wizard/plex/plexoauth.component.ts | 26 +++++-------- src/Ombi/Controllers/SettingsController.cs | 10 +++++ src/Ombi/Controllers/TokenController.cs | 29 +++++++------- 14 files changed, 146 insertions(+), 52 deletions(-) create mode 100644 src/Ombi/ClientApp/app/login/loginoauth.component.html create mode 100644 src/Ombi/ClientApp/app/login/loginoauth.component.ts diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index 5fb87aca7..6d814adf3 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -208,7 +208,7 @@ namespace Ombi.Api.Plex AddHeaders(request); var forwardUrl = wizard ? new Request($"Wizard/OAuth/{pinId}", applicationUrl, HttpMethod.Get) - : new Request($"api/v1/PlexOAuth/{pinId}", applicationUrl, HttpMethod.Get); + : new Request($"Login/OAuth/{pinId}", applicationUrl, HttpMethod.Get); request.AddQueryString("forwardUrl", forwardUrl.FullUri.ToString()); request.AddQueryString("pinID", pinId.ToString()); diff --git a/src/Ombi/ClientApp/app/app.module.ts b/src/Ombi/ClientApp/app/app.module.ts index 0936b13cd..1421b1117 100644 --- a/src/Ombi/ClientApp/app/app.module.ts +++ b/src/Ombi/ClientApp/app/app.module.ts @@ -24,6 +24,7 @@ import { CookieComponent } from "./auth/cookie.component"; import { PageNotFoundComponent } from "./errors/not-found.component"; import { LandingPageComponent } from "./landingpage/landingpage.component"; import { LoginComponent } from "./login/login.component"; +import { LoginOAuthComponent } from "./login/loginoauth.component"; import { ResetPasswordComponent } from "./login/resetpassword.component"; import { TokenResetPasswordComponent } from "./login/tokenresetpassword.component"; @@ -41,6 +42,7 @@ const routes: Routes = [ { path: "*", component: PageNotFoundComponent }, { path: "", redirectTo: "/search", pathMatch: "full" }, { path: "login", component: LoginComponent }, + { path: "Login/OAuth/:pin", component: LoginOAuthComponent }, { path: "login/:landing", component: LoginComponent }, { path: "reset", component: ResetPasswordComponent }, { path: "token", component: TokenResetPasswordComponent }, @@ -116,6 +118,7 @@ export function HttpLoaderFactory(http: HttpClient, platformLocation: PlatformLo ResetPasswordComponent, TokenResetPasswordComponent, CookieComponent, + LoginOAuthComponent, ], providers: [ NotificationService, diff --git a/src/Ombi/ClientApp/app/auth/IUserLogin.ts b/src/Ombi/ClientApp/app/auth/IUserLogin.ts index af152a6b1..609055c8e 100644 --- a/src/Ombi/ClientApp/app/auth/IUserLogin.ts +++ b/src/Ombi/ClientApp/app/auth/IUserLogin.ts @@ -2,6 +2,7 @@ username: string; password: string; rememberMe: boolean; + usePlexOAuth: boolean; } export interface ILocalUser { diff --git a/src/Ombi/ClientApp/app/login/login.component.html b/src/Ombi/ClientApp/app/login/login.component.html index 5fc0150ff..528fe9917 100644 --- a/src/Ombi/ClientApp/app/login/login.component.html +++ b/src/Ombi/ClientApp/app/login/login.component.html @@ -7,11 +7,13 @@ include the remember me checkbox
+

+
+
+ + + diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 661850e86..cde2ef085 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -25,9 +25,39 @@ export class LoginComponent implements OnDestroy, OnInit { public form: FormGroup; public customizationSettings: ICustomizationSettings; public authenticationSettings: IAuthenticationSettings; + public plexEnabled: boolean; public background: any; public landingFlag: boolean; public baseUrl: string; + + public get showLoginForm(): boolean { + if(this.customizationSettings.applicationUrl && this.plexEnabled) { + this.loginWithOmbi = false; + return false; + } + if(!this.customizationSettings.applicationUrl || !this.plexEnabled) { + + this.loginWithOmbi = true; + return true; + } + if(this.loginWithOmbi) { + return true; + } + + + this.loginWithOmbi = true; + return true; + } + public loginWithOmbi: boolean = false; + + public get appName(): string { + if(this.customizationSettings.applicationName) { + return this.customizationSettings.applicationName; + } else { + return "Ombi"; + } + } + private timer: any; private errorBody: string; @@ -68,6 +98,7 @@ export class LoginComponent implements OnDestroy, OnInit { public ngOnInit() { this.settingsService.getAuthentication().subscribe(x => this.authenticationSettings = x); this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x); + this.settingsService.getStatusPlex().subscribe(x => this.plexEnabled = x); this.images.getRandomBackground().subscribe(x => { this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%),url(" + x.url + ")"); }); @@ -90,7 +121,7 @@ export class LoginComponent implements OnDestroy, OnInit { return; } const value = form.value; - const user = { password: value.password, username: value.username, rememberMe:value.rememberMe }; + const user = { password: value.password, username: value.username, rememberMe: value.rememberMe, usePlexOAuth: false }; this.authService.requiresPassword(user).subscribe(x => { if(x && this.authenticationSettings.allowNoPassword) { // Looks like this user requires a password @@ -111,6 +142,12 @@ export class LoginComponent implements OnDestroy, OnInit { }); } + public oauth() { + this.authService.login({usePlexOAuth: true, password:"",rememberMe:true,username:""}).subscribe(x => { + window.location.href = x.url; + }) + } + public ngOnDestroy() { clearInterval(this.timer); } diff --git a/src/Ombi/ClientApp/app/login/loginoauth.component.html b/src/Ombi/ClientApp/app/login/loginoauth.component.html new file mode 100644 index 000000000..e80f1239f --- /dev/null +++ b/src/Ombi/ClientApp/app/login/loginoauth.component.html @@ -0,0 +1,9 @@ + +
+ +
+
+ +
+
+
diff --git a/src/Ombi/ClientApp/app/login/loginoauth.component.ts b/src/Ombi/ClientApp/app/login/loginoauth.component.ts new file mode 100644 index 000000000..a0a9a9414 --- /dev/null +++ b/src/Ombi/ClientApp/app/login/loginoauth.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { AuthService } from "../auth/auth.service"; + +@Component({ + templateUrl: "./loginoauth.component.html" +}) +export class LoginOAuthComponent implements OnInit { + public pin: number; + + constructor(private authService: AuthService, private router: Router, + private route: ActivatedRoute) { + this.route.params + .subscribe((params: any) => { + this.pin = params.pin; + + }); + } + + ngOnInit(): void { + this.auth(); + } + + public auth() { + this.authService.oAuth(this.pin).subscribe(x => { + localStorage.setItem("id_token", x.access_token); + + if (this.authService.loggedIn()) { + this.router.navigate(["search"]); + } + + }); + } +} diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index f6f770a19..61a85874e 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -71,6 +71,10 @@ export class SettingsService extends ServiceHelpers { return this.http.get(`${this.url}/Plex/`, {headers: this.headers}); } + public getStatusPlex(): Observable { + return this.http.get(`${this.url}/Plexstatus/`, {headers: this.headers}); + } + public savePlex(settings: IPlexSettings): Observable { return this.http.post(`${this.url}/Plex/`, JSON.stringify(settings), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.ts b/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.ts index 481c96a99..07f47f265 100644 --- a/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.ts +++ b/src/Ombi/ClientApp/app/wizard/createadmin/createadmin.component.ts @@ -21,7 +21,7 @@ export class CreateAdminComponent { this.identityService.createWizardUser({username: this.username, password: this.password, usePlexAdminAccount: false}).subscribe(x => { if (x) { // Log me in. - this.auth.login({ username: this.username, password: this.password, rememberMe:false }).subscribe(c => { + this.auth.login({ username: this.username, password: this.password, rememberMe: false, usePlexOAuth:false }).subscribe(c => { localStorage.setItem("id_token", c.access_token); diff --git a/src/Ombi/ClientApp/app/wizard/plex/plex.component.html b/src/Ombi/ClientApp/app/wizard/plex/plex.component.html index 6c4b846a7..5d69c435b 100644 --- a/src/Ombi/ClientApp/app/wizard/plex/plex.component.html +++ b/src/Ombi/ClientApp/app/wizard/plex/plex.component.html @@ -23,7 +23,7 @@
- +
diff --git a/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts b/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts index 6bc21d628..2f5b2dd79 100644 --- a/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts +++ b/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts @@ -1,7 +1,6 @@ import { Component } from "@angular/core"; import { Router } from "@angular/router"; -import { ConfirmationService } from "primeng/primeng"; import { PlexService } from "../../services"; import { IdentityService, NotificationService, SettingsService } from "../../services"; @@ -17,7 +16,6 @@ export class PlexComponent { constructor(private plexService: PlexService, private router: Router, private notificationService: NotificationService, - private confirmationService: ConfirmationService, private identityService: IdentityService, private settings: SettingsService, private auth: AuthService) { } @@ -28,25 +26,21 @@ export class PlexComponent { this.notificationService.error("Username or password was incorrect. Could not authenticate with Plex."); return; } - this.confirmationService.confirm({ - message: "Do you want your Plex user to be the main admin account on Ombi?", - header: "Use Plex Account", - icon: "fa fa-check", - accept: () => { + this.identityService.createWizardUser({ username: "", password: "", usePlexAdminAccount: true, - }).subscribe(x => { - if (x) { - this.auth.login({ username: this.login, password: this.password, rememberMe:false }).subscribe(c => { + }).subscribe(y => { + if (y) { + this.auth.login({ username: this.login, password: this.password, rememberMe: false, usePlexOAuth: false }).subscribe(c => { localStorage.setItem("id_token", c.access_token); // Mark that we have done the settings now this.settings.getOmbi().subscribe(ombi => { ombi.wizard = true; - this.settings.saveOmbi(ombi).subscribe(x => { + this.settings.saveOmbi(ombi).subscribe(s => { this.settings.getUserManagementSettings().subscribe(usr => { usr.importPlexAdmin = true; @@ -63,12 +57,8 @@ export class PlexComponent { return; } }); - }, - reject: () => { - this.router.navigate(["Wizard/CreateAdmin"]); - }, - }); - }); + } + ); } public oauth() { diff --git a/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts b/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts index 1397fe7f5..7d0d0bf9d 100644 --- a/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts +++ b/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts @@ -1,8 +1,6 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { ConfirmationService } from "primeng/primeng"; - import { PlexOAuthService, IdentityService, SettingsService } from "../../services"; import { AuthService } from "./../../auth/auth.service"; @@ -14,7 +12,6 @@ export class PlexOAuthComponent implements OnInit { constructor(private route: ActivatedRoute, private plexOauth: PlexOAuthService, - private confirmationService: ConfirmationService, private identityService: IdentityService, private settings: SettingsService, private router: Router, @@ -28,19 +25,18 @@ export class PlexOAuthComponent implements OnInit { ngOnInit(): void { this.plexOauth.oAuth(this.pinId).subscribe(x => { - x.accessToken; + if(!x.accessToken) { + return; + // RETURN + } - this.confirmationService.confirm({ - message: "Do you want your Plex user to be the main admin account on Ombi?", - header: "Use Plex Account", - icon: "fa fa-check", - accept: () => { + this.identityService.createWizardUser({ username: "", password: "", usePlexAdminAccount: true, - }).subscribe(x => { - if (x) { + }).subscribe(u => { + if (u) { this.auth.oAuth(this.pinId).subscribe(c => { localStorage.setItem("id_token", c.access_token); @@ -48,7 +44,7 @@ export class PlexOAuthComponent implements OnInit { this.settings.getOmbi().subscribe(ombi => { ombi.wizard = true; - this.settings.saveOmbi(ombi).subscribe(x => { + this.settings.saveOmbi(ombi).subscribe(s => { this.settings.getUserManagementSettings().subscribe(usr => { usr.importPlexAdmin = true; @@ -65,11 +61,7 @@ export class PlexOAuthComponent implements OnInit { return; } }); - }, - reject: () => { - this.router.navigate(["Wizard/CreateAdmin"]); - }, - }); + }); } diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 867a7517c..1f0d62147 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -151,6 +151,16 @@ namespace Ombi.Controllers return s; } + [HttpGet("plexstatus")] + [AllowAnonymous] + public async Task PlexStatusSettings() + { + var s = await Get(); + + + return s.Enable; + } + /// /// Save the Plex settings. /// diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 62e43635d..624267989 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -49,26 +49,27 @@ namespace Ombi.Controllers [HttpPost] public async Task GetToken([FromBody] UserAuthModel model) { - await _audit.Record(AuditType.None, AuditArea.Authentication, + if (!model.UsePlexOAuth) + { + await _audit.Record(AuditType.None, AuditArea.Authentication, $"UserName {model.Username} attempting to authenticate"); - var user = await _userManager.FindByNameAsync(model.Username); - - if (user == null) - { - // Could this be an email login? - user = await _userManager.FindByEmailAsync(model.Username); + var user = await _userManager.FindByNameAsync(model.Username); if (user == null) { - return new UnauthorizedResult(); + // Could this be an email login? + user = await _userManager.FindByEmailAsync(model.Username); + + if (user == null) + { + return new UnauthorizedResult(); + } + + user.EmailLogin = true; } - user.EmailLogin = true; - } - if (!model.UsePlexOAuth) - { // Verify Password if (await _userManager.CheckPasswordAsync(user, model.Password)) { @@ -91,7 +92,7 @@ namespace Ombi.Controllers error = "Application URL has not been set" }); } - return new RedirectResult(url.ToString()); + return new JsonResult(new { url = url.ToString() }); } return new UnauthorizedResult(); @@ -183,7 +184,7 @@ namespace Ombi.Controllers { return new UnauthorizedResult(); } - + throw new NotImplementedException(); } From 5531af462cc67189f6a5d37f1c388dd230ea1fac Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 19 Apr 2018 22:18:25 +0100 Subject: [PATCH 038/495] Made the app name customizable for the OAUth !wip --- src/Ombi.Api.Plex/PlexApi.cs | 34 +++++++++++-------- .../Settings/Models/External/PlexSettings.cs | 1 - 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index 6d814adf3..a16dee9ec 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -10,38 +10,42 @@ using Ombi.Api.Plex.Models.Status; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; +using Ombi.Settings.Settings.Models; namespace Ombi.Api.Plex { public class PlexApi : IPlexApi { - public PlexApi(IApi api, ISettingsService settings) + public PlexApi(IApi api, ISettingsService settings) { Api = api; - _plex = settings; + _custom = settings; } private IApi Api { get; } - private readonly ISettingsService _plex; + private readonly ISettingsService _custom; - private string _clientId; - private string ClientIdSecret + private string _app; + private string ApplicationName { get { - if (string.IsNullOrEmpty(_clientId)) + if (string.IsNullOrEmpty(_app)) { - var settings = _plex.GetSettings(); - if (settings.UniqueInstallCode.IsNullOrEmpty()) + var settings = _custom.GetSettings(); + if (settings.ApplicationName.IsNullOrEmpty()) { - settings.UniqueInstallCode = Guid.NewGuid().ToString("N"); - _plex.SaveSettings(settings); + _app = "Ombi"; + } + else + { + _app = settings.ApplicationName; } - _clientId = settings.UniqueInstallCode; + return _app; } - return _clientId; + return _app; } } @@ -215,7 +219,7 @@ namespace Ombi.Api.Plex request.AddQueryString("code", code); request.AddQueryString("context[device][product]", "Ombi"); request.AddQueryString("context[device][environment]", "bundled"); - request.AddQueryString("clientID", $"OmbiV3{ClientIdSecret}"); + request.AddQueryString("clientID", $"OmbiV3"); if (request.FullUri.Fragment.Equals("#")) { @@ -246,8 +250,8 @@ namespace Ombi.Api.Plex /// private void AddHeaders(Request request) { - request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3{ClientIdSecret}"); - request.AddHeader("X-Plex-Product", "Ombi"); + request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3"); + request.AddHeader("X-Plex-Product", ApplicationName); request.AddHeader("X-Plex-Version", "3"); request.AddContentHeader("Content-Type", request.ContentType == ContentType.Json ? "application/json" : "application/xml"); request.AddHeader("Accept", "application/json"); diff --git a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs index dd92eba18..3faba3e42 100644 --- a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs @@ -6,7 +6,6 @@ namespace Ombi.Core.Settings.Models.External public sealed class PlexSettings : Ombi.Settings.Settings.Models.Settings { public bool Enable { get; set; } - public string UniqueInstallCode { get; set; } public List Servers { get; set; } } From f05a9a5090ecc68ba56522c7ecf453e3dc97b549 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Fri, 20 Apr 2018 10:41:40 +0100 Subject: [PATCH 039/495] Removed no longer needed stuff and fixed linting !wip --- src/Ombi/ClientApp/app/login/login.component.ts | 4 +--- src/Ombi/ClientApp/app/login/loginoauth.component.ts | 4 ++-- src/Ombi/ClientApp/app/wizard/plex/plex.component.ts | 5 ++--- src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts | 7 +++---- src/Ombi/Controllers/External/PlexController.cs | 1 - src/Ombi/Controllers/SettingsController.cs | 4 ---- 6 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index cde2ef085..3c2636b2f 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -44,7 +44,6 @@ export class LoginComponent implements OnDestroy, OnInit { return true; } - this.loginWithOmbi = true; return true; } @@ -145,7 +144,7 @@ export class LoginComponent implements OnDestroy, OnInit { public oauth() { this.authService.login({usePlexOAuth: true, password:"",rememberMe:true,username:""}).subscribe(x => { window.location.href = x.url; - }) + }); } public ngOnDestroy() { @@ -161,5 +160,4 @@ export class LoginComponent implements OnDestroy, OnInit { .bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%), url(" + x.url + ")"); }); } - } diff --git a/src/Ombi/ClientApp/app/login/loginoauth.component.ts b/src/Ombi/ClientApp/app/login/loginoauth.component.ts index a0a9a9414..03922d8b3 100644 --- a/src/Ombi/ClientApp/app/login/loginoauth.component.ts +++ b/src/Ombi/ClientApp/app/login/loginoauth.component.ts @@ -4,7 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router"; import { AuthService } from "../auth/auth.service"; @Component({ - templateUrl: "./loginoauth.component.html" + templateUrl: "./loginoauth.component.html", }) export class LoginOAuthComponent implements OnInit { public pin: number; @@ -18,7 +18,7 @@ export class LoginOAuthComponent implements OnInit { }); } - ngOnInit(): void { + public ngOnInit(): void { this.auth(); } diff --git a/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts b/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts index 2f5b2dd79..bafe67756 100644 --- a/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts +++ b/src/Ombi/ClientApp/app/wizard/plex/plex.component.ts @@ -1,7 +1,6 @@ import { Component } from "@angular/core"; import { Router } from "@angular/router"; - import { PlexService } from "../../services"; import { IdentityService, NotificationService, SettingsService } from "../../services"; import { AuthService } from "./../../auth/auth.service"; @@ -27,7 +26,7 @@ export class PlexComponent { return; } - this.identityService.createWizardUser({ + this.identityService.createWizardUser({ username: "", password: "", usePlexAdminAccount: true, @@ -57,7 +56,7 @@ export class PlexComponent { return; } }); - } + }, ); } diff --git a/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts b/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts index 7d0d0bf9d..25517541c 100644 --- a/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts +++ b/src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { PlexOAuthService, IdentityService, SettingsService } from "../../services"; +import { IdentityService, PlexOAuthService, SettingsService } from "../../services"; import { AuthService } from "./../../auth/auth.service"; @Component({ @@ -23,15 +23,14 @@ export class PlexOAuthComponent implements OnInit { }); } - ngOnInit(): void { + public ngOnInit(): void { this.plexOauth.oAuth(this.pinId).subscribe(x => { if(!x.accessToken) { return; // RETURN } - - this.identityService.createWizardUser({ + this.identityService.createWizardUser({ username: "", password: "", usePlexAdminAccount: true, diff --git a/src/Ombi/Controllers/External/PlexController.cs b/src/Ombi/Controllers/External/PlexController.cs index cde78bc64..4819ed8a0 100644 --- a/src/Ombi/Controllers/External/PlexController.cs +++ b/src/Ombi/Controllers/External/PlexController.cs @@ -69,7 +69,6 @@ namespace Ombi.Controllers.External _log.LogDebug("Adding first server"); settings.Enable = true; - settings.UniqueInstallCode = Guid.NewGuid().ToString("N"); settings.Servers = new List { new PlexServers { diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 1f0d62147..0a515d9cb 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -143,10 +143,6 @@ namespace Ombi.Controllers public async Task PlexSettings() { var s = await Get(); - if (s.UniqueInstallCode.IsNullOrEmpty()) - { - s.UniqueInstallCode = Guid.NewGuid().ToString("N"); - } return s; } From e980ac6fc540595a5798c128ec2440a25bbe19e5 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Fri, 20 Apr 2018 10:48:25 +0100 Subject: [PATCH 040/495] Fixed styling !wip --- src/Ombi/ClientApp/app/wizard/plex/plex.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/wizard/plex/plex.component.html b/src/Ombi/ClientApp/app/wizard/plex/plex.component.html index 5d69c435b..a48c0f73e 100644 --- a/src/Ombi/ClientApp/app/wizard/plex/plex.component.html +++ b/src/Ombi/ClientApp/app/wizard/plex/plex.component.html @@ -17,13 +17,13 @@ Please note we do not store this information, we only store your Plex Authorization Token that will allow Ombi to view your media and friends
- +
- +

OR

- +
From 738bdb46d72f3c1cd13c521548ec2fad89f03042 Mon Sep 17 00:00:00 2001 From: Anojh Date: Fri, 20 Apr 2018 14:02:19 -0700 Subject: [PATCH 041/495] Fix baseurl breaking themes --- src/Ombi/Controllers/SettingsController.cs | 6 ------ src/Ombi/Views/Shared/_Layout.cshtml | 10 ++++++++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 44702a073..9ffa9d81f 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -274,12 +274,6 @@ namespace Ombi.Controllers public async Task GetThemeContent([FromQuery]string url) { var css = await _githubApi.GetThemesRawContent(url); - var ombiSettings = await OmbiSettings(); - if (ombiSettings.BaseUrl != null) - { - int index = css.IndexOf("/api/"); - css = css.Insert(index, ombiSettings.BaseUrl); - } return Content(css, "text/css"); } diff --git a/src/Ombi/Views/Shared/_Layout.cshtml b/src/Ombi/Views/Shared/_Layout.cshtml index cafd75357..1f2610e1c 100644 --- a/src/Ombi/Views/Shared/_Layout.cshtml +++ b/src/Ombi/Views/Shared/_Layout.cshtml @@ -85,8 +85,14 @@ O:::::::OOO:::::::Om::::m m::::m m::::mb:::::bbbbbb::::::bi::::::i @{ - if (customization.HasPresetTheme) - { + if (customization.HasPresetTheme) + { + if (!string.IsNullOrEmpty(baseUrl)) + { + var index = customization.PresetThemeContent.IndexOf("/api/"); + customization.PresetThemeContent = customization.PresetThemeContent.Insert(index, "/" + baseUrl); + } + From 2c08908c8b29bc9c9f26ef1a5f08a99321b09492 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 20 Apr 2018 23:29:00 +0100 Subject: [PATCH 042/495] Fixed the ombi login button !wip --- .../ClientApp/app/login/login.component.html | 67 +++++++++++-------- .../ClientApp/app/login/login.component.ts | 22 +----- .../app/login/loginoauth.component.html | 7 ++ .../app/login/loginoauth.component.ts | 7 ++ src/Ombi/Controllers/TokenController.cs | 9 +++ 5 files changed, 64 insertions(+), 48 deletions(-) diff --git a/src/Ombi/ClientApp/app/login/login.component.html b/src/Ombi/ClientApp/app/login/login.component.html index 528fe9917..50d887feb 100644 --- a/src/Ombi/ClientApp/app/login/login.component.html +++ b/src/Ombi/ClientApp/app/login/login.component.html @@ -9,39 +9,50 @@ include the remember me checkbox
-
-
+
+ +
+
+ +

-
- -
+ +
+ +
+ + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 3c2636b2f..5bc5f022a 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -29,26 +29,8 @@ export class LoginComponent implements OnDestroy, OnInit { public background: any; public landingFlag: boolean; public baseUrl: string; - - public get showLoginForm(): boolean { - if(this.customizationSettings.applicationUrl && this.plexEnabled) { - this.loginWithOmbi = false; - return false; - } - if(!this.customizationSettings.applicationUrl || !this.plexEnabled) { - - this.loginWithOmbi = true; - return true; - } - if(this.loginWithOmbi) { - return true; - } - - this.loginWithOmbi = true; - return true; - } - public loginWithOmbi: boolean = false; - + public loginWithOmbi: boolean; + public get appName(): string { if(this.customizationSettings.applicationName) { return this.customizationSettings.applicationName; diff --git a/src/Ombi/ClientApp/app/login/loginoauth.component.html b/src/Ombi/ClientApp/app/login/loginoauth.component.html index e80f1239f..e2118c7aa 100644 --- a/src/Ombi/ClientApp/app/login/loginoauth.component.html +++ b/src/Ombi/ClientApp/app/login/loginoauth.component.html @@ -4,6 +4,13 @@
+ +
+ + + + Back +
diff --git a/src/Ombi/ClientApp/app/login/loginoauth.component.ts b/src/Ombi/ClientApp/app/login/loginoauth.component.ts index 03922d8b3..1adcff19c 100644 --- a/src/Ombi/ClientApp/app/login/loginoauth.component.ts +++ b/src/Ombi/ClientApp/app/login/loginoauth.component.ts @@ -8,6 +8,7 @@ import { AuthService } from "../auth/auth.service"; }) export class LoginOAuthComponent implements OnInit { public pin: number; + public error: string; constructor(private authService: AuthService, private router: Router, private route: ActivatedRoute) { @@ -24,11 +25,17 @@ export class LoginOAuthComponent implements OnInit { public auth() { this.authService.oAuth(this.pin).subscribe(x => { + if(x.access_token) { localStorage.setItem("id_token", x.access_token); if (this.authService.loggedIn()) { this.router.navigate(["search"]); + return; } + } + if(x.errorMessage) { + this.error = x.errorMessage; + } }); } diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 624267989..b337b3f51 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -148,6 +148,15 @@ namespace Ombi.Controllers { var accessToken = await _plexOAuthManager.GetAccessTokenFromPin(pinId); + if (accessToken.IsNullOrEmpty()) + { + // Looks like we are not authenticated. + return new JsonResult(new + { + errorMessage = "Could not authenticate with Plex" + }); + } + // Let's look for the users account var account = await _plexOAuthManager.GetAccount(accessToken); From 77280cf4aea29b4cf2642b7269e29cd00bb14203 Mon Sep 17 00:00:00 2001 From: Avi Date: Fri, 20 Apr 2018 18:25:58 -0500 Subject: [PATCH 043/495] Sign In rather than Login/Continue --- src/Ombi/ClientApp/app/login/login.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/login/login.component.html b/src/Ombi/ClientApp/app/login/login.component.html index 50d887feb..a50040fab 100644 --- a/src/Ombi/ClientApp/app/login/login.component.html +++ b/src/Ombi/ClientApp/app/login/login.component.html @@ -43,11 +43,11 @@ include the remember me checkbox @@ -55,4 +55,4 @@ include the remember me checkbox - \ No newline at end of file + From 04af799efb02671d6b9d9214d4a2f2a527457654 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Sat, 21 Apr 2018 21:22:25 +0100 Subject: [PATCH 044/495] Fixed the newsletter not sending #2134 --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 274 +++++++++--------- .../Notifications/NewsletterSettings.cs | 2 +- 2 files changed, 146 insertions(+), 130 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 1a8b21fbd..6cfe67bb6 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using MailKit; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TvMaze; @@ -26,7 +27,7 @@ namespace Ombi.Schedule.Jobs.Ombi public NewsletterJob(IPlexContentRepository plex, IEmbyContentRepository emby, IRepository addedLog, IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService custom, ISettingsService emailSettings, INotificationTemplatesRepository templateRepo, - UserManager um, ISettingsService newsletter) + UserManager um, ISettingsService newsletter, ILogger log) { _plex = plex; _emby = emby; @@ -42,6 +43,7 @@ namespace Ombi.Schedule.Jobs.Ombi _emailSettings.ClearCache(); _customizationSettings.ClearCache(); _newsletterSettings.ClearCache(); + _log = log; } private readonly IPlexContentRepository _plex; @@ -55,6 +57,7 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly ISettingsService _emailSettings; private readonly ISettingsService _newsletterSettings; private readonly UserManager _userManager; + private readonly ILogger _log; public async Task Start(NewsletterSettings settings, bool test) { @@ -74,152 +77,167 @@ namespace Ombi.Schedule.Jobs.Ombi return; } - var customization = await _customizationSettings.GetSettingsAsync(); - - // Get the Content - var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); - var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); - - var addedLog = _recentlyAddedLog.GetAll(); - var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId); - var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId); - - var addedPlexEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode).Select(x => x.ContentId); - var addedEmbyEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode).Select(x => x.ContentId); - - // Filter out the ones that we haven't sent yet - var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(x.Id)); - var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(x.Id)); - - var plexEpisodesToSend = _plex.GetAllEpisodes().Include(x => x.Series).Where(x => !addedPlexEpisodesLogIds.Contains(x.Id)).AsNoTracking(); - var embyEpisodesToSend = _emby.GetAllEpisodes().Include(x => x.Series).Where(x => !addedEmbyEpisodesLogIds.Contains(x.Id)).AsNoTracking(); - - var body = string.Empty; - if (test) + try { - var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10); - var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10); - body = await BuildHtml(plexm, embym, plext, embyt, settings); - } - else - { - body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, settings); - if (body.IsNullOrEmpty()) + + + var customization = await _customizationSettings.GetSettingsAsync(); + + // Get the Content + var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); + var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); + + var addedLog = _recentlyAddedLog.GetAll(); + var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId); + var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId); + + var addedPlexEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode).Select(x => x.ContentId); + var addedEmbyEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode).Select(x => x.ContentId); + + // Filter out the ones that we haven't sent yet + var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(x.Id)); + var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(x.Id)); + _log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count()); + _log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count()); + + var plexEpisodesToSend = _plex.GetAllEpisodes().Include(x => x.Series).Where(x => !addedPlexEpisodesLogIds.Contains(x.Id)).AsNoTracking(); + var embyEpisodesToSend = _emby.GetAllEpisodes().Include(x => x.Series).Where(x => !addedEmbyEpisodesLogIds.Contains(x.Id)).AsNoTracking(); + + _log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count()); + _log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count()); + + var body = string.Empty; + if (test) { - return; + var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10); + var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); + var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10); + var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10); + body = await BuildHtml(plexm, embym, plext, embyt, settings); } - - } - - if (!test) - { - // Get the users to send it to - var users = await _userManager.GetUsersInRoleAsync(OmbiRoles.RecievesNewsletter); - if (!users.Any()) + else { - return; - } - - foreach (var emails in settings.ExternalEmails) - { - users.Add(new OmbiUser + body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, settings); + if (body.IsNullOrEmpty()) { - UserName = emails, - Email = emails - }); + return; + } } - var emailTasks = new List(); - foreach (var user in users) + + if (!test) { - if (user.Email.IsNullOrEmpty()) + // Get the users to send it to + var users = await _userManager.GetUsersInRoleAsync(OmbiRoles.RecievesNewsletter); + if (!users.Any()) { - continue; + return; } - var messageContent = ParseTemplate(template, customization, user); - var email = new NewsletterTemplate(); - - var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo); - - emailTasks.Add(_email.Send( - new NotificationMessage { Message = html, Subject = messageContent.Subject, To = user.Email }, - emailSettings)); - } - - // Now add all of this to the Recently Added log - var recentlyAddedLog = new HashSet(); - foreach (var p in plexContentMoviesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog + foreach (var emails in settings.ExternalEmails) { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Plex, - ContentType = ContentType.Parent, - ContentId = p.Id - }); - - } - - foreach (var p in plexEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog + users.Add(new OmbiUser + { + UserName = emails, + Email = emails + }); + } + var emailTasks = new List(); + foreach (var user in users) { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Plex, - ContentType = ContentType.Episode, - ContentId = p.Id - }); - } + if (user.Email.IsNullOrEmpty()) + { + continue; + } - foreach (var e in embyContentMoviesToSend) - { - if (e.Type == EmbyMediaType.Movie) + var messageContent = ParseTemplate(template, customization, user); + var email = new NewsletterTemplate(); + + var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo); + + emailTasks.Add(_email.Send( + new NotificationMessage { Message = html, Subject = messageContent.Subject, To = user.Email }, + emailSettings)); + } + + // Now add all of this to the Recently Added log + var recentlyAddedLog = new HashSet(); + foreach (var p in plexContentMoviesToSend) + { + recentlyAddedLog.Add(new RecentlyAddedLog + { + AddedAt = DateTime.Now, + Type = RecentlyAddedType.Plex, + ContentType = ContentType.Parent, + ContentId = p.Id + }); + + } + + foreach (var p in plexEpisodesToSend) + { + recentlyAddedLog.Add(new RecentlyAddedLog + { + AddedAt = DateTime.Now, + Type = RecentlyAddedType.Plex, + ContentType = ContentType.Episode, + ContentId = p.Id + }); + } + + foreach (var e in embyContentMoviesToSend) + { + if (e.Type == EmbyMediaType.Movie) + { + recentlyAddedLog.Add(new RecentlyAddedLog + { + AddedAt = DateTime.Now, + Type = RecentlyAddedType.Emby, + ContentType = ContentType.Parent, + ContentId = e.Id + }); + } + } + + foreach (var p in embyEpisodesToSend) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, - ContentType = ContentType.Parent, - ContentId = e.Id + ContentType = ContentType.Episode, + ContentId = p.Id }); } - } + await _recentlyAddedLog.AddRange(recentlyAddedLog); - foreach (var p in embyEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog - { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Emby, - ContentType = ContentType.Episode, - ContentId = p.Id - }); + await Task.WhenAll(emailTasks.ToArray()); } - await _recentlyAddedLog.AddRange(recentlyAddedLog); - - await Task.WhenAll(emailTasks.ToArray()); - } - else - { - var admins = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin); - foreach (var a in admins) + else { - if (a.Email.IsNullOrEmpty()) + var admins = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin); + foreach (var a in admins) { - continue; + if (a.Email.IsNullOrEmpty()) + { + continue; + } + var messageContent = ParseTemplate(template, customization, a); + + var email = new NewsletterTemplate(); + + var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo); + + await _email.Send( + new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email }, + emailSettings); } - var messageContent = ParseTemplate(template, customization, a); - - var email = new NewsletterTemplate(); - - var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo); - - await _email.Send( - new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email }, - emailSettings); } + + } + catch (Exception e) + { + _log.LogError(e, "Error when attempting to create newsletter"); + throw; } } @@ -285,8 +303,7 @@ namespace Ombi.Schedule.Jobs.Ombi } catch (Exception e) { - Console.WriteLine(e); - throw; + _log.LogError(e, "Error when Processing Plex Movies {0}", info.Title); } finally { @@ -315,7 +332,7 @@ namespace Ombi.Schedule.Jobs.Ombi theMovieDbId = result.id.ToString(); } - + var info = await _movieApi.GetMovieInformationWithExtraInfo(int.Parse(theMovieDbId)); if (info == null) { @@ -327,8 +344,7 @@ namespace Ombi.Schedule.Jobs.Ombi } catch (Exception e) { - Console.WriteLine(e); - throw; + _log.LogError(e, "Error when processing Emby Movies {0}", info.Title); } finally { @@ -437,7 +453,7 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append("
"); - + var title = $"{t.Title} ({t.ReleaseYear})"; Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/"); @@ -483,7 +499,7 @@ namespace Ombi.Schedule.Jobs.Ombi } catch (Exception e) { - //Log.Error(e); + _log.LogError(e, "Error when processing Plex TV {0}", t.Title); } finally { @@ -584,7 +600,7 @@ namespace Ombi.Schedule.Jobs.Ombi } catch (Exception e) { - //Log.Error(e); + _log.LogError(e, "Error when processing Emby TV {0}", t.Title); } finally { diff --git a/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs index f043cd74c..e79f3182c 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs @@ -7,6 +7,6 @@ namespace Ombi.Settings.Settings.Models.Notifications public bool DisableTv { get; set; } public bool DisableMovies { get; set; } public bool Enabled { get; set; } - public List ExternalEmails { get; set; } + public List ExternalEmails { get; set; } = new List(); } } \ No newline at end of file From 703203ed5c301de21d3e7b0fbe28886f8459aacd Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 21 Apr 2018 21:27:42 +0100 Subject: [PATCH 045/495] !wip --- src/Ombi.Core/Engine/RecentlyAddedEngine.cs | 32 +- src/Ombi.Helpers/LinqHelpers.cs | 7 + src/Ombi.Schedule/JobSetup.cs | 2 + src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 76 +- src/Ombi.Store/Entities/RecentlyAddedLog.cs | 4 +- ...180420225638_NewsletterChanges.Designer.cs | 956 ++++++++++++++++++ .../20180420225638_NewsletterChanges.cs | 33 + .../Migrations/OmbiContextModelSnapshot.cs | 4 + 8 files changed, 1091 insertions(+), 23 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.cs diff --git a/src/Ombi.Core/Engine/RecentlyAddedEngine.cs b/src/Ombi.Core/Engine/RecentlyAddedEngine.cs index 8782ea028..114d32a24 100644 --- a/src/Ombi.Core/Engine/RecentlyAddedEngine.cs +++ b/src/Ombi.Core/Engine/RecentlyAddedEngine.cs @@ -63,13 +63,17 @@ namespace Ombi.Core.Engine var recentlyAddedLog = new HashSet(); foreach (var p in plexContent) { + if (!p.HasTheMovieDb) + { + continue; + } if (p.Type == PlexMediaTypeEntity.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, - ContentId = p.Id, + ContentId = int.Parse(p.TheMovieDbId), ContentType = ContentType.Parent }); } @@ -78,12 +82,18 @@ namespace Ombi.Core.Engine // Add the episodes foreach (var ep in p.Episodes) { + if (!ep.Series.HasTvDb) + { + continue; + } recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, - ContentId = ep.Id, - ContentType = ContentType.Episode + ContentId = int.Parse(ep.Series.TvDbId), + ContentType = ContentType.Episode, + EpisodeNumber = ep.EpisodeNumber, + SeasonNumber = ep.SeasonNumber }); } } @@ -91,13 +101,17 @@ namespace Ombi.Core.Engine foreach (var e in embyContent) { + if (e.TheMovieDbId.IsNullOrEmpty()) + { + continue; + } if (e.Type == EmbyMediaType.Movie) { recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, - ContentId = e.Id, + ContentId = int.Parse(e.TheMovieDbId), ContentType = ContentType.Parent }); } @@ -106,12 +120,18 @@ namespace Ombi.Core.Engine // Add the episodes foreach (var ep in e.Episodes) { + if (ep.Series.TvDbId.IsNullOrEmpty()) + { + continue; + } recentlyAddedLog.Add(new RecentlyAddedLog { AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, - ContentId = ep.Id, - ContentType = ContentType.Episode + ContentId = int.Parse(ep.Series.TvDbId), + ContentType = ContentType.Episode, + EpisodeNumber = ep.EpisodeNumber, + SeasonNumber = ep.SeasonNumber }); } } diff --git a/src/Ombi.Helpers/LinqHelpers.cs b/src/Ombi.Helpers/LinqHelpers.cs index 279d161b7..67fdb5c53 100644 --- a/src/Ombi.Helpers/LinqHelpers.cs +++ b/src/Ombi.Helpers/LinqHelpers.cs @@ -14,5 +14,12 @@ namespace Ombi.Helpers yield return source1; } } + + public static HashSet ToHashSet( + this IEnumerable source, + IEqualityComparer comparer = null) + { + return new HashSet(source, comparer); + } } } \ No newline at end of file diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index 6626ef933..73d7c3536 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -66,6 +66,8 @@ namespace Ombi.Schedule RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); + + BackgroundJob.Enqueue(() => _refreshMetadata.Start()); } diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 1a8b21fbd..75dc9723d 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using MailKit; @@ -84,23 +86,28 @@ namespace Ombi.Schedule.Jobs.Ombi var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId); var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId); - var addedPlexEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode).Select(x => x.ContentId); - var addedEmbyEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode).Select(x => x.ContentId); + var addedPlexEpisodesLogIds = + addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode); + var addedEmbyEpisodesLogIds = + addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode); // Filter out the ones that we haven't sent yet - var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(x.Id)); - var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(x.Id)); + var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(int.Parse(x.TheMovieDbId))); + var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(int.Parse(x.TheMovieDbId))); - var plexEpisodesToSend = _plex.GetAllEpisodes().Include(x => x.Series).Where(x => !addedPlexEpisodesLogIds.Contains(x.Id)).AsNoTracking(); - var embyEpisodesToSend = _emby.GetAllEpisodes().Include(x => x.Series).Where(x => !addedEmbyEpisodesLogIds.Contains(x.Id)).AsNoTracking(); + + var plexEpisodesToSend = + FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds); + var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), + addedEmbyEpisodesLogIds); var body = string.Empty; if (test) { var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10); var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10); - var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10); + var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); + var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); body = await BuildHtml(plexm, embym, plext, embyt, settings); } else @@ -110,7 +117,6 @@ namespace Ombi.Schedule.Jobs.Ombi { return; } - } if (!test) @@ -157,7 +163,7 @@ namespace Ombi.Schedule.Jobs.Ombi AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, ContentType = ContentType.Parent, - ContentId = p.Id + ContentId = int.Parse(p.TheMovieDbId), }); } @@ -169,7 +175,9 @@ namespace Ombi.Schedule.Jobs.Ombi AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, ContentType = ContentType.Episode, - ContentId = p.Id + ContentId = int.Parse(p.Series.TvDbId), + EpisodeNumber = p.EpisodeNumber, + SeasonNumber = p.SeasonNumber }); } @@ -182,7 +190,7 @@ namespace Ombi.Schedule.Jobs.Ombi AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, ContentType = ContentType.Parent, - ContentId = e.Id + ContentId = int.Parse(e.TheMovieDbId), }); } } @@ -194,7 +202,9 @@ namespace Ombi.Schedule.Jobs.Ombi AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, ContentType = ContentType.Episode, - ContentId = p.Id + ContentId = int.Parse(p.Series.TvDbId), + EpisodeNumber = p.EpisodeNumber, + SeasonNumber = p.SeasonNumber }); } await _recentlyAddedLog.AddRange(recentlyAddedLog); @@ -229,6 +239,40 @@ namespace Ombi.Schedule.Jobs.Ombi await Start(newsletterSettings, false); } + private HashSet FilterPlexEpisodes(IEnumerable source, IQueryable recentlyAdded) + { + var itemsToReturn = new HashSet(); + foreach (var ep in source) + { + var tvDbId = int.Parse(ep.Series.TvDbId); + if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) + { + continue; + } + + itemsToReturn.Add(ep); + } + + return itemsToReturn; + } + + private HashSet FilterEmbyEpisodes(IEnumerable source, IQueryable recentlyAdded) + { + var itemsToReturn = new HashSet(); + foreach (var ep in source) + { + var tvDbId = int.Parse(ep.Series.TvDbId); + if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) + { + continue; + } + + itemsToReturn.Add(ep); + } + + return itemsToReturn; + } + private NotificationMessageContent ParseTemplate(NotificationTemplates template, CustomizationSettings settings, OmbiUser username) { var resolver = new NotificationMessageResolver(); @@ -239,7 +283,7 @@ namespace Ombi.Schedule.Jobs.Ombi return resolver.ParseMessage(template, curlys); } - private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, IQueryable plexEpisodes, IQueryable embyEp, NewsletterSettings settings) + private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, HashSet plexEpisodes, HashSet embyEp, NewsletterSettings settings) { var sb = new StringBuilder(); @@ -366,7 +410,7 @@ namespace Ombi.Schedule.Jobs.Ombi AddParagraph(sb, info.Overview); } - private async Task ProcessPlexTv(IQueryable plexContent, StringBuilder sb) + private async Task ProcessPlexTv(HashSet plexContent, StringBuilder sb) { var series = new List(); foreach (var plexEpisode in plexContent) @@ -494,7 +538,7 @@ namespace Ombi.Schedule.Jobs.Ombi } - private async Task ProcessEmbyTv(IQueryable embyContent, StringBuilder sb) + private async Task ProcessEmbyTv(HashSet embyContent, StringBuilder sb) { var series = new List(); foreach (var episode in embyContent) diff --git a/src/Ombi.Store/Entities/RecentlyAddedLog.cs b/src/Ombi.Store/Entities/RecentlyAddedLog.cs index ba26eb566..1ef091149 100644 --- a/src/Ombi.Store/Entities/RecentlyAddedLog.cs +++ b/src/Ombi.Store/Entities/RecentlyAddedLog.cs @@ -8,7 +8,9 @@ namespace Ombi.Store.Entities { public RecentlyAddedType Type { get; set; } public ContentType ContentType { get; set; } - public int ContentId { get; set; } // This is dependant on the type + public int ContentId { get; set; } // This is dependant on the type, it's either TMDBID or TVDBID + public int? EpisodeNumber { get; set; } + public int? SeasonNumber { get; set; } public DateTime AddedAt { get; set; } } diff --git a/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.Designer.cs b/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.Designer.cs new file mode 100644 index 000000000..64c581108 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.Designer.cs @@ -0,0 +1,956 @@ +// +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 Ombi.Store.Entities.Requests; +using System; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180420225638_NewsletterChanges")] + partial class NewsletterChanges + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + 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 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.cs b/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.cs new file mode 100644 index 000000000..bea4d7080 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace Ombi.Store.Migrations +{ + public partial class NewsletterChanges : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EpisodeNumber", + table: "RecentlyAddedLog", + nullable: true); + + migrationBuilder.AddColumn( + name: "SeasonNumber", + table: "RecentlyAddedLog", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EpisodeNumber", + table: "RecentlyAddedLog"); + + migrationBuilder.DropColumn( + name: "SeasonNumber", + table: "RecentlyAddedLog"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 248551d97..794bde8a6 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -455,6 +455,10 @@ namespace Ombi.Store.Migrations b.Property("ContentType"); + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + b.Property("Type"); b.HasKey("Id"); From 443c79b0cae49ec43d8d6c52e42f0c6f2e0c9d69 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Sat, 21 Apr 2018 21:43:33 +0100 Subject: [PATCH 046/495] Fixed #2179. Note: This requires you to press the update database again before using the newsletter! --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 16 ++++++++-------- .../20180420225638_NewsletterChanges.cs | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 75dc9723d..ea3276982 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -128,14 +128,14 @@ namespace Ombi.Schedule.Jobs.Ombi return; } - foreach (var emails in settings.ExternalEmails) - { - users.Add(new OmbiUser - { - UserName = emails, - Email = emails - }); - } + //foreach (var emails in settings.ExternalEmails) + //{ + // users.Add(new OmbiUser + // { + // UserName = emails, + // Email = emails + // }); + //} var emailTasks = new List(); foreach (var user in users) { diff --git a/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.cs b/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.cs index bea4d7080..ad4786772 100644 --- a/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.cs +++ b/src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.cs @@ -17,6 +17,8 @@ namespace Ombi.Store.Migrations name: "SeasonNumber", table: "RecentlyAddedLog", nullable: true); + + migrationBuilder.Sql("DELETE FROM RecentlyAddedLog"); } protected override void Down(MigrationBuilder migrationBuilder) From b80ef04ab7b5f2d55349eae0420e274cc5f07e88 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Sat, 21 Apr 2018 22:04:44 +0100 Subject: [PATCH 047/495] !wip fixed merge --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 104 +++++++++---------- 1 file changed, 47 insertions(+), 57 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index ba8725b69..79731637b 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -84,62 +84,51 @@ namespace Ombi.Schedule.Jobs.Ombi var customization = await _customizationSettings.GetSettingsAsync(); + // Get the Content + var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); + var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); - var addedPlexEpisodesLogIds = + var addedLog = _recentlyAddedLog.GetAll(); + var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId); + var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId); + + var addedPlexEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode); - var addedEmbyEpisodesLogIds = - addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode); + var addedEmbyEpisodesLogIds = + addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode); - // Filter out the ones that we haven't sent yet - var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(int.Parse(x.TheMovieDbId))); - var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(int.Parse(x.TheMovieDbId))); + // Filter out the ones that we haven't sent yet + var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(int.Parse(x.TheMovieDbId))); + var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(int.Parse(x.TheMovieDbId))); _log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count()); _log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count()); - var plexEpisodesToSend = - FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds); - var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), - addedEmbyEpisodesLogIds); + var plexEpisodesToSend = + FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds); + var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), + addedEmbyEpisodesLogIds); _log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count()); _log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count()); - var body = string.Empty; - if (test) - { - var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); - var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); - var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - body = await BuildHtml(plexm, embym, plext, embyt, settings); - } - else - { - body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, settings); - if (body.IsNullOrEmpty()) + var body = string.Empty; + if (test) { - return; + var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10); + var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10); + var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); + var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); + body = await BuildHtml(plexm, embym, plext, embyt, settings); } - } - - if (!test) - { - // Get the users to send it to - var users = await _userManager.GetUsersInRoleAsync(OmbiRoles.RecievesNewsletter); - if (!users.Any()) + else { - return; + body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, settings); + if (body.IsNullOrEmpty()) + { + return; + } } - foreach (var emails in settings.ExternalEmails) - { - users.Add(new OmbiUser - { - UserName = emails, - Email = emails - }); - } - var emailTasks = new List(); - foreach (var user in users) + if (!test) { // Get the users to send it to var users = await _userManager.GetUsersInRoleAsync(OmbiRoles.RecievesNewsletter); @@ -159,6 +148,7 @@ namespace Ombi.Schedule.Jobs.Ombi var emailTasks = new List(); foreach (var user in users) { + // Get the users to send it to if (user.Email.IsNullOrEmpty()) { continue; @@ -180,26 +170,26 @@ namespace Ombi.Schedule.Jobs.Ombi { recentlyAddedLog.Add(new RecentlyAddedLog { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Plex, - ContentType = ContentType.Parent, - ContentId = int.Parse(p.TheMovieDbId), - }); + AddedAt = DateTime.Now, + Type = RecentlyAddedType.Plex, + ContentType = ContentType.Parent, + ContentId = int.Parse(p.TheMovieDbId), + }); } foreach (var p in plexEpisodesToSend) - { - recentlyAddedLog.Add(new RecentlyAddedLog + { + recentlyAddedLog.Add(new RecentlyAddedLog { - AddedAt = DateTime.Now, - Type = RecentlyAddedType.Plex, - ContentType = ContentType.Episode, - ContentId = int.Parse(p.Series.TvDbId), - EpisodeNumber = p.EpisodeNumber, - SeasonNumber = p.SeasonNumber - }); - } + AddedAt = DateTime.Now, + Type = RecentlyAddedType.Plex, + ContentType = ContentType.Episode, + ContentId = int.Parse(p.Series.TvDbId), + EpisodeNumber = p.EpisodeNumber, + SeasonNumber = p.SeasonNumber + }); + } foreach (var e in embyContentMoviesToSend) { if (e.Type == EmbyMediaType.Movie) From 0ce9fb2df94e292bfa061a8d8ca33dedd6722b2c Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Sat, 21 Apr 2018 22:25:53 +0100 Subject: [PATCH 048/495] Fixed #2170 --- .../Repository/SettingsJsonRepository.cs | 1 + src/Ombi/Program.cs | 2 +- src/Ombi/Startup.cs | 28 ++++++++----------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/Ombi.Store/Repository/SettingsJsonRepository.cs b/src/Ombi.Store/Repository/SettingsJsonRepository.cs index 09bf61695..248413ccc 100644 --- a/src/Ombi.Store/Repository/SettingsJsonRepository.cs +++ b/src/Ombi.Store/Repository/SettingsJsonRepository.cs @@ -81,6 +81,7 @@ namespace Ombi.Store.Repository public void Update(GlobalSettings entity) { + Db.Update(entity); //_cache.Remove(GetName(entity.SettingsName)); Db.SaveChanges(); } diff --git a/src/Ombi/Program.cs b/src/Ombi/Program.cs index 9294852f9..7e9fa6f78 100644 --- a/src/Ombi/Program.cs +++ b/src/Ombi/Program.cs @@ -82,7 +82,7 @@ namespace Ombi ctx.SaveChanges(); } } - else if(!baseUrl.Equals(dbBaseUrl.Value)) + else if(baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value)) { dbBaseUrl.Value = baseUrl; ctx.SaveChanges(); diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 7fc0522ed..55a49fa92 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -173,26 +173,22 @@ namespace Ombi settings.ApiKey = Guid.NewGuid().ToString("N"); ombiService.SaveSettings(settings); } + + // Check if it's in the startup args + var appConfig = serviceProvider.GetService(); + var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result; + if (baseUrl != null) + { + if (baseUrl.Value.HasValue()) + { + settings.BaseUrl = baseUrl.Value; + ombiService.SaveSettings(settings); + } + } if (settings.BaseUrl.HasValue()) { app.UsePathBase(settings.BaseUrl); } - else - { - // Check if it's in the startup args - var appConfig = serviceProvider.GetService(); - var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result; - if (baseUrl != null) - { - if (baseUrl.Value.HasValue()) - { - settings.BaseUrl = baseUrl.Value; - ombiService.SaveSettings(settings); - - app.UsePathBase(settings.BaseUrl); - } - } - } app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)}); app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire", From a0dbd1c442b5e32ccab40335e378988bd57fce89 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Sat, 21 Apr 2018 22:47:01 +0100 Subject: [PATCH 049/495] Fixed #2151 --- src/Ombi.Core/Engine/Interfaces/BaseEngine.cs | 15 +-------------- src/Ombi.Store/Context/OmbiContext.cs | 16 ++++++++++++++++ src/Ombi.Store/Entities/User.cs | 1 + src/Ombi/Controllers/IdentityController.cs | 2 +- src/Ombi/Properties/launchSettings.json | 1 + 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs index e608ffebb..26bc5969c 100644 --- a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs @@ -32,14 +32,7 @@ namespace Ombi.Core.Engine.Interfaces private OmbiUser _user; protected async Task GetUser() { - if (IsApiUser) - { - return new OmbiUser - { - UserName = Username, - }; - } - return _user ?? (_user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == Username)); + return _user ?? (_user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(Username, StringComparison.CurrentCultureIgnoreCase))); } protected async Task UserAlias() @@ -49,10 +42,6 @@ namespace Ombi.Core.Engine.Interfaces protected async Task IsInRole(string roleName) { - if (IsApiUser && roleName != OmbiRoles.Disabled) - { - return true; - } return await UserManager.IsInRoleAsync(await GetUser(), roleName); } @@ -72,7 +61,5 @@ namespace Ombi.Core.Engine.Interfaces var ruleResults = await Rules.StartSpecificRules(model, rule); return ruleResults; } - - private bool IsApiUser => Username.Equals("Api", StringComparison.CurrentCultureIgnoreCase); } } \ No newline at end of file diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index e4c9be516..d1963e765 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -123,7 +123,23 @@ namespace Ombi.Store.Context { NormalizedName = OmbiRoles.RecievesNewsletter.ToUpper() }); + SaveChanges(); } + + // Make sure we have the API User + var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase)); + if (!apiUserExists) + { + Users.Add(new OmbiUser + { + UserName = "Api", + UserType = UserType.SystemUser, + NormalizedUserName = "API", + + }); + SaveChanges(); + } + //Check if templates exist var templates = NotificationTemplates.ToList(); diff --git a/src/Ombi.Store/Entities/User.cs b/src/Ombi.Store/Entities/User.cs index d9a3207b2..68d1dbe00 100644 --- a/src/Ombi.Store/Entities/User.cs +++ b/src/Ombi.Store/Entities/User.cs @@ -29,6 +29,7 @@ namespace Ombi.Store.Entities { public enum UserType { + SystemUser = 0, LocalUser = 1, PlexUser = 2, EmbyUser = 3, diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 5db5f2168..fe63226e6 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -213,7 +213,7 @@ namespace Ombi.Controllers [PowerUser] public async Task> GetAllUsers() { - var users = await UserManager.Users + var users = await UserManager.Users.Where(x => x.UserType != UserType.LocalUser) .ToListAsync(); var model = new List(); diff --git a/src/Ombi/Properties/launchSettings.json b/src/Ombi/Properties/launchSettings.json index ec5deb319..33794436c 100644 --- a/src/Ombi/Properties/launchSettings.json +++ b/src/Ombi/Properties/launchSettings.json @@ -10,6 +10,7 @@ "profiles": { "IIS Express": { "commandName": "IISExpress", + "commandLineArgs": "-baseurl /testing", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" From 8927c5fa9cc312bfbd84882925a117fd348deec2 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Sat, 21 Apr 2018 22:51:56 +0100 Subject: [PATCH 050/495] Fixed #2164 --- src/Ombi.Api.Pushover/PushoverApi.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Api.Pushover/PushoverApi.cs b/src/Ombi.Api.Pushover/PushoverApi.cs index 96f4d2e95..4ac08c0f5 100644 --- a/src/Ombi.Api.Pushover/PushoverApi.cs +++ b/src/Ombi.Api.Pushover/PushoverApi.cs @@ -1,4 +1,5 @@ using System; +using System.Net; using System.Net.Http; using System.Threading.Tasks; using Ombi.Api.Pushover.Models; @@ -17,7 +18,7 @@ namespace Ombi.Api.Pushover public async Task PushAsync(string accessToken, string message, string userToken) { - var request = new Request($"messages.json?token={accessToken}&user={userToken}&message={message}", PushoverEndpoint, HttpMethod.Post); + var request = new Request($"messages.json?token={accessToken}&user={userToken}&message={WebUtility.HtmlEncode(message)}", PushoverEndpoint, HttpMethod.Post); var result = await _api.Request(request); return result; From 0c6083dd9af91275b0ab88050cd5420b89dffc1c Mon Sep 17 00:00:00 2001 From: Anojh Date: Sat, 21 Apr 2018 22:26:25 -0700 Subject: [PATCH 051/495] detect if baseurl is already set, and reset the link --- src/Ombi/Views/Shared/_Layout.cshtml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Ombi/Views/Shared/_Layout.cshtml b/src/Ombi/Views/Shared/_Layout.cshtml index 1f2610e1c..8433f7b4e 100644 --- a/src/Ombi/Views/Shared/_Layout.cshtml +++ b/src/Ombi/Views/Shared/_Layout.cshtml @@ -88,10 +88,20 @@ O:::::::OOO:::::::Om::::m m::::m m::::mb:::::bbbbbb::::::bi::::::i if (customization.HasPresetTheme) { if (!string.IsNullOrEmpty(baseUrl)) + { + if (!customization.PresetThemeContent.Contains("/" + baseUrl)) { var index = customization.PresetThemeContent.IndexOf("/api/"); customization.PresetThemeContent = customization.PresetThemeContent.Insert(index, "/" + baseUrl); + } else + { + var startIndex = customization.PresetThemeContent.IndexOf("href="); + var index = customization.PresetThemeContent.IndexOf("/api/"); + customization.PresetThemeContent = customization.PresetThemeContent.Remove(startIndex+6, (index-(startIndex+6))); + index = customization.PresetThemeContent.IndexOf("/api/"); + customization.PresetThemeContent = customization.PresetThemeContent.Insert(index, "/" + baseUrl); } + } + } if (!string.IsNullOrEmpty(customization.CustomCssLink)) { - + } } From b8c64dff2d1e014e6feb872fb9b4f4b7876f0f3b Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 23 Apr 2018 16:27:33 +0100 Subject: [PATCH 054/495] Update Hangfire, Newtonsoft and Swagger --- src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj | 2 +- src/Ombi.Api/Ombi.Api.csproj | 2 +- src/Ombi.Core/Ombi.Core.csproj | 4 ++-- src/Ombi.Helpers/Ombi.Helpers.csproj | 2 +- src/Ombi.Schedule/Ombi.Schedule.csproj | 6 +++--- src/Ombi.Settings/Ombi.Settings.csproj | 2 +- src/Ombi.Store/Ombi.Store.csproj | 2 +- src/Ombi/Ombi.csproj | 6 +++--- src/Ombi/Startup.cs | 1 - 9 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj index ca15bae05..83318be7b 100644 --- a/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj +++ b/src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/Ombi.Api/Ombi.Api.csproj b/src/Ombi.Api/Ombi.Api.csproj index 325f316b8..8379691c5 100644 --- a/src/Ombi.Api/Ombi.Api.csproj +++ b/src/Ombi.Api/Ombi.Api.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index c2af094bb..de6f5c8fa 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -11,12 +11,12 @@ - + - + diff --git a/src/Ombi.Helpers/Ombi.Helpers.csproj b/src/Ombi.Helpers/Ombi.Helpers.csproj index 00cd8d5e9..9bb599c2a 100644 --- a/src/Ombi.Helpers/Ombi.Helpers.csproj +++ b/src/Ombi.Helpers/Ombi.Helpers.csproj @@ -12,7 +12,7 @@ - + diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj index 5088bc9f8..47e599e80 100644 --- a/src/Ombi.Schedule/Ombi.Schedule.csproj +++ b/src/Ombi.Schedule/Ombi.Schedule.csproj @@ -10,9 +10,9 @@ - - - + + + diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj index 5a99cc830..3cb56cb07 100644 --- a/src/Ombi.Settings/Ombi.Settings.csproj +++ b/src/Ombi.Settings/Ombi.Settings.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index 901882669..522a96957 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index f5e523db7..7f3cd8055 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -61,8 +61,8 @@ - - + + @@ -78,7 +78,7 @@ - + diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 55a49fa92..be78c5b11 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -219,7 +219,6 @@ namespace Ombi app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); - c.ShowJsonEditor(); }); app.UseMvc(routes => From f24b0f20eb35ff6a1899dad09b7c564bb58c03ec Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 23 Apr 2018 16:30:02 +0100 Subject: [PATCH 055/495] Updated Mailkit dependancy --- src/Ombi.Notifications/Ombi.Notifications.csproj | 2 +- src/Ombi/Ombi.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Notifications/Ombi.Notifications.csproj b/src/Ombi.Notifications/Ombi.Notifications.csproj index ccdb29e65..46a64072e 100644 --- a/src/Ombi.Notifications/Ombi.Notifications.csproj +++ b/src/Ombi.Notifications/Ombi.Notifications.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 7f3cd8055..89e432580 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -67,7 +67,7 @@ - + From 6806b97c1b19158d697196248a1701cf80dd384c Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 23 Apr 2018 21:15:03 +0100 Subject: [PATCH 056/495] Fixed the bug where only showing API User #2187 --- src/Ombi/Controllers/IdentityController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index fe63226e6..8a9c76a34 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -213,7 +213,7 @@ namespace Ombi.Controllers [PowerUser] public async Task> GetAllUsers() { - var users = await UserManager.Users.Where(x => x.UserType != UserType.LocalUser) + var users = await UserManager.Users.Where(x => x.UserType != UserType.SystemUser) .ToListAsync(); var model = new List(); From f62e97bb32818c3b454ca6f347053e82e1029866 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 24 Apr 2018 08:09:11 +0100 Subject: [PATCH 057/495] Fixed bug #2188 #2134 --- src/Ombi.Helpers/StringHelper.cs | 10 ++++++++++ src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 18 +++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Helpers/StringHelper.cs b/src/Ombi.Helpers/StringHelper.cs index daa8cabe7..aba120c65 100644 --- a/src/Ombi.Helpers/StringHelper.cs +++ b/src/Ombi.Helpers/StringHelper.cs @@ -65,5 +65,15 @@ namespace Ombi.Helpers securePassword.MakeReadOnly(); return securePassword; } + + public static int IntParseLinq(string stringIn) + { + if (int.TryParse(stringIn, out var result)) + { + return result; + } + + return -1; + } } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 79731637b..8b246e97e 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -98,8 +98,8 @@ namespace Ombi.Schedule.Jobs.Ombi addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode); // Filter out the ones that we haven't sent yet - var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(int.Parse(x.TheMovieDbId))); - var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(int.Parse(x.TheMovieDbId))); + var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); + var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); _log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count()); _log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count()); @@ -173,7 +173,7 @@ namespace Ombi.Schedule.Jobs.Ombi AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, ContentType = ContentType.Parent, - ContentId = int.Parse(p.TheMovieDbId), + ContentId = StringHelper.IntParseLinq(p.TheMovieDbId), }); } @@ -185,7 +185,7 @@ namespace Ombi.Schedule.Jobs.Ombi AddedAt = DateTime.Now, Type = RecentlyAddedType.Plex, ContentType = ContentType.Episode, - ContentId = int.Parse(p.Series.TvDbId), + ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), EpisodeNumber = p.EpisodeNumber, SeasonNumber = p.SeasonNumber }); @@ -199,7 +199,7 @@ namespace Ombi.Schedule.Jobs.Ombi AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, ContentType = ContentType.Parent, - ContentId = int.Parse(e.TheMovieDbId), + ContentId = StringHelper.IntParseLinq(e.TheMovieDbId), }); } } @@ -211,7 +211,7 @@ namespace Ombi.Schedule.Jobs.Ombi AddedAt = DateTime.Now, Type = RecentlyAddedType.Emby, ContentType = ContentType.Episode, - ContentId = int.Parse(p.Series.TvDbId), + ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), EpisodeNumber = p.EpisodeNumber, SeasonNumber = p.SeasonNumber }); @@ -259,7 +259,7 @@ namespace Ombi.Schedule.Jobs.Ombi var itemsToReturn = new HashSet(); foreach (var ep in source) { - var tvDbId = int.Parse(ep.Series.TvDbId); + var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) { continue; @@ -276,7 +276,7 @@ namespace Ombi.Schedule.Jobs.Ombi var itemsToReturn = new HashSet(); foreach (var ep in source) { - var tvDbId = int.Parse(ep.Series.TvDbId); + var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId); if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber)) { continue; @@ -374,7 +374,7 @@ namespace Ombi.Schedule.Jobs.Ombi theMovieDbId = result.id.ToString(); } - var info = await _movieApi.GetMovieInformationWithExtraInfo(int.Parse(theMovieDbId)); + var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId)); if (info == null) { continue; From e12146c98666d5de0471b106e918ff8ea7568468 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 24 Apr 2018 08:32:31 +0100 Subject: [PATCH 058/495] More improvements to the Plex OAuth, Added the ability to turn it off if needed --- .../Authentication/PlexOAuthManager.cs | 19 ++++++++++++++----- src/Ombi.Core/IPlexOAuthManager.cs | 2 +- src/Ombi.Helpers/UriHelper.cs | 1 + .../Settings/Models/External/PlexSettings.cs | 1 + .../ClientApp/app/interfaces/ISettings.ts | 1 + .../ClientApp/app/login/login.component.html | 9 +++++---- .../ClientApp/app/login/login.component.ts | 8 +++++++- .../app/settings/plex/plex.component.html | 6 ++++++ src/Ombi/Controllers/SettingsController.cs | 2 +- src/Ombi/Controllers/TokenController.cs | 5 +++-- 10 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/Ombi.Core/Authentication/PlexOAuthManager.cs b/src/Ombi.Core/Authentication/PlexOAuthManager.cs index d3bab0a05..f3a3e4d01 100644 --- a/src/Ombi.Core/Authentication/PlexOAuthManager.cs +++ b/src/Ombi.Core/Authentication/PlexOAuthManager.cs @@ -55,15 +55,24 @@ namespace Ombi.Core.Authentication return await _api.GetAccount(accessToken); } - public async Task GetOAuthUrl(int pinId, string code) + public async Task GetOAuthUrl(int pinId, string code, string websiteAddress = null) { - var settings = await _customizationSettingsService.GetSettingsAsync(); - if (settings.ApplicationUrl.IsNullOrEmpty()) + Uri url; + if (websiteAddress.IsNullOrEmpty()) { - return null; + var settings = await _customizationSettingsService.GetSettingsAsync(); + if (settings.ApplicationUrl.IsNullOrEmpty()) + { + return null; + } + + url = _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl, false); + } + else + { + url = _api.GetOAuthUrl(pinId, code, websiteAddress, false); } - var url = _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl, false); return url; } diff --git a/src/Ombi.Core/IPlexOAuthManager.cs b/src/Ombi.Core/IPlexOAuthManager.cs index 142d4162a..9c4f0582e 100644 --- a/src/Ombi.Core/IPlexOAuthManager.cs +++ b/src/Ombi.Core/IPlexOAuthManager.cs @@ -9,7 +9,7 @@ namespace Ombi.Core.Authentication { Task GetAccessTokenFromPin(int pinId); Task RequestPin(); - Task GetOAuthUrl(int pinId, string code); + Task GetOAuthUrl(int pinId, string code, string websiteAddress = null); Uri GetWizardOAuthUrl(int pinId, string code, string websiteAddress); Task GetAccount(string accessToken); } diff --git a/src/Ombi.Helpers/UriHelper.cs b/src/Ombi.Helpers/UriHelper.cs index 83cd27e9d..6ec8047ae 100644 --- a/src/Ombi.Helpers/UriHelper.cs +++ b/src/Ombi.Helpers/UriHelper.cs @@ -112,6 +112,7 @@ namespace Ombi.Helpers return uriBuilder.Uri; } + } public class ApplicationSettingsException : Exception diff --git a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs index 3faba3e42..a77b54a87 100644 --- a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs @@ -6,6 +6,7 @@ namespace Ombi.Core.Settings.Models.External public sealed class PlexSettings : Ombi.Settings.Settings.Models.Settings { public bool Enable { get; set; } + public bool EnableOAuth { get; set; } public List Servers { get; set; } } diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index d67ebc698..234e0aa5b 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -43,6 +43,7 @@ export interface IEmbyServer extends IExternalSettings { export interface IPlexSettings extends ISettings { enable: boolean; + enableOAuth: boolean; servers: IPlexServer[]; } diff --git a/src/Ombi/ClientApp/app/login/login.component.html b/src/Ombi/ClientApp/app/login/login.component.html index a50040fab..40a5ef5a0 100644 --- a/src/Ombi/ClientApp/app/login/login.component.html +++ b/src/Ombi/ClientApp/app/login/login.component.html @@ -17,7 +17,7 @@ include the remember me checkbox

-
+
-
+
+
+ + +
+
diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 0a515d9cb..1bbb5af49 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -154,7 +154,7 @@ namespace Ombi.Controllers var s = await Get(); - return s.Enable; + return s.Enable && s.EnableOAuth; } /// diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index b337b3f51..a488ba172 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -23,7 +23,7 @@ namespace Ombi.Controllers { [ApiV1] [Produces("application/json")] - public class TokenController + public class TokenController : Controller { public TokenController(OmbiUserManager um, IOptions ta, IAuditRepository audit, ITokenRepository token, IPlexOAuthManager oAuthManager) @@ -83,8 +83,9 @@ namespace Ombi.Controllers // We need a PIN first var pin = await _plexOAuthManager.RequestPin(); + var websiteAddress = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}"; //https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd - var url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code); + var url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code, websiteAddress); if (url == null) { return new JsonResult(new From c244faca7d28a138ce2287e27dd9ddfc33efd22f Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 24 Apr 2018 08:34:48 +0100 Subject: [PATCH 059/495] !wip changelog --- CHANGELOG.md | 3655 +------------------------------------------------- 1 file changed, 45 insertions(+), 3610 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecb1a790d..49d85aca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,51 @@ ### **New Features** +- Updated Mailkit dependancy. [Jamie Rees] + +- Update Hangfire, Newtonsoft and Swagger. [Jamie Rees] + +- Added View on Emby Button (#2173) [Anojh Thayaparan] + +- Added background property to tvrequests API (#2172) [Anojh Thayaparan] + +### **Fixes** + +- More improvements to the Plex OAuth, Added the ability to turn it off if needed. [Jamie] + +- Fixed bug #2188 #2134. [Jamie] + +- Fixed the bug where only showing API User #2187. [Jamie] + +- Detect if baseurl is already set, and reset the link. [Anojh] + +- Fixed #2164. [Jamie Rees] + +- Fixed #2151. [Jamie Rees] + +- Fixed #2170. [Jamie Rees] + +- Fixed the newsletter not sending #2134. [Jamie Rees] + +- Fix baseurl breaking themes. [Anojh] + +- Inject base url if set before theme file url, see issue #1795. [Anojh] + +- Sign In rather than Login/Continue. [Avi] + +- Fixed #2179. [Jamie Rees] + +- Fixed #2169. [Jamie Rees] + +- Knocking out LC requirements in issue #2124 (#2125) [Anojh Thayaparan] + +- Inject base url if set before theme file url, see issue #1795 (#2148) [Anojh Thayaparan] + + +## v3.0.3185 (2018-04-16) + +### **New Features** + - Added a new Job. Plex Recently Added, this is a slimmed down version of the Plex Sync job, this will just scan the recently added list and not the whole library. I'd reccomend running this very regulary and the full scan not as regular. [Jamie] ### **Fixes** @@ -819,3613 +864,3 @@ - Switch to use a single HTTPClient rather than a new one every request !dev. [tidusjar] -- Fix non-admin rights (#1820) [Rob Gökemeijer] - -- Fix duplicated "Requests" element ID on new Issues link (#1817) [Shoghi Cervantes] - -- Add the Issue Reporting functionality (#1811) [Jamie] - -- Removed the forum. [tidusjar] - -- #1659 Made the option to ignore notifcations for auto approve. [Jamie] - -- New Crowdin translations (#1806) [Jamie] - -- Fixed a launch issue. [Jamie] - -- Allow users to login without a password. [Jamie] - -- Fixed the emby notifications not being sent. [Jamie] - -- #1802 and other small fixes. [tidusjar] - -- So... This sickrage thing should work now. [tidusjar] - -- Fixed emby connect login issue. [tidusjar] - -- Stop making unnecessary calls to the update service. [Jamie] - -- Fixed a bug where it blocked users with 0 limits. [Jamie] - -- Done #1788. [tidusjar] - -- More logging. [Jamie] - -- Fixed #1738. [Jamie] - -- Fixed build. [Jamie] - -- Fixed the issue where notifications were not sendind unless we restarted #1732. [tidusjar] - -- Fixed an issue with a trailing space in the subdir. [tidusjar] - -- Fixed #1774. [Jamie] - -- #1773. [Jamie] - -- Roll back rxjs (#1778) [bazhip] - -- Fixed build. [Jamie] - -- Fixed #1763. [Jamie] - -- Fix "content length error" on preview gif (#1768) [OoGuru] - -- New preview gif for Ombi V3 README (#1767) [OoGuru] - -- Remove debug code. [tidusjar] - -- Fix #1762. [tidusjar] - -- Fixed the preset themes not loading. [tidusjar] - -- Fixed #1760 and improvements on the auto updater. We may now support windows services... #1460. [Jamie] - -- Fixed #1754. [Jamie] - -- Hide the subject when it's not being used. [Jamie] - -- Error handling #1749. [Jamie] - -- New Crowdin translations (#1741) [Jamie] - -- #1732 #1722 #1711. [Jamie] - -- Fixed an issue with switching the preset themes. [Jamie] - -- Fixed #1743. [Jamie] - -- Fixed #1742. [tidusjar] - -- Fix #1742. [tidusjar] - -- Fixed landing page. [Jamie] - -- Fixed. [Jamie] - -- Translated the Requests page and fixed #1740. [Jamie] - -- Fix crash. [Jamie] - -- Sickrage done. Ish... So i've written all the code by looking at the API. the key there is i've looked at the api. I have not tested anything so expect this to fail. [Jamie] - -- SickRage settings UI. [Jamie] - -- Fixed #1721. [tidusjar] - -- Fixed the preset themes issue. [tidusjar] - -- New Crowdin translations (#1654) [Jamie] - -- Fix build. [Jamie] - -- #1460. [Jamie] - -- Fixed tests. [Jamie] - -- Return css as MIME text/css. [Jamie] - -- More added for the preset themes. [Jamie] - -- Moved around the custom styles. [Jamie] - -- More renames. [Jamie] - -- Renames. [Jamie] - -- Load the first 100 requests. [Jamie] - -- Reduce the memory consumption #1720. [Jamie] - -- Moved the schedules jobs into it's own database, see if it helps with the db locking #1720. [Jamie] - -- Fixed #1712. [tidusjar] - -- Potential fix for #1702. [tidusjar] - -- Fixed #1708. [tidusjar] - -- Fixed #1677. [tidusjar] - -- Fixed build. [tidusjar] - -- Potential fix for the DB locking issue #1720. [tidusjar] - -- #1698. [Jamie] - -- Fixed #1705. [tidusjar] - -- Fixed #1703. [tidusjar] - -- Finished adding preset themes. [Jamie] - -- Fixed #17000. [Jamie] - -- Remove the themes because waiting for a merge from lerams project. [Jamie] - -- Finsihed adding preset themes. [Jamie] - -- Fixed #1677. [Jamie] - -- Temp fix for #1683. [Jamie] - -- Fixed #1685. [Jamie] - -- Lossless Compression of images saves 83 KB (#1676) [Fish2] - -- Fixed the availability checker. [tidusjar] - -- Fixed build. [tidusjar] - -- Push out missing migration. [tidusjar] - -- Potential fix for #1674. [tidusjar] - -- Fixed an issue with the caching. [tidusjar] - -- Fixed telegram #1667. [tidusjar] - -- Fixed #1663. [tidusjar] - -- Should fix #1663. [tidusjar] - -- Stop logged in users going to the login page. [Jamie] - -- Fixed it not updating. Styles should be good now. [Jamie] - -- Re did some of the styling on the movie search page, let me know your thoughts. [Jamie] - -- Fixed #1657. [Jamie] - -- Fixed #1655. [Jamie] - -- Removed authentication resul. [Jamie] - -- New Crowdin translations (#1651) [Jamie] - -- New Crowdin translations (#1648) [Jamie] - -- New Crowdin translations (#1638) [Jamie] - -- Fixed #1644. [Jamie] - -- Moar logs #1643. [tidusjar] - -- Fixed #1640. [tidusjar] - -- Fixed the null ref exception #1460. [tidusjar] - -- Fixed landing page. [TidusJar] - -- Fixed #1641. [TidusJar] - -- Fixed #1641. [TidusJar] - -- New Crowdin translations (#1635) [Jamie] - -- Fixed #1631 and improved translation support Included startup args for the auto updater #1460 Mark TV requests as available #1632. [tidusjar] - -- Remove 32bit. [Jamie] - -- More 32bit support. [Jamie] - -- We now show "Available" for tv shows that is fully available #1602. [tidusjar] - -- Fixed the issue where we have got an episode but not the related series. #1620. [tidusjar] - -- Fixed the dropdown not working on iOS in the settings #1615. [tidusjar] - -- Fixed sonarr not monitoring the latest season #1534. [tidusjar] - -- Fixed the issue with firefox #1544. [tidusjar] - -- Fixed discord #1623. [tidusjar] - -- Add browserstack thanks (#1627) [Matt Jeanes] - -- Fix the exception #1613. [Jamie] - -- Found where we potentially are setting a new poster path, looks like the entity was being modified and being set as Tracked by entity framework, so the next time we called SaveChangesAsync() it would save the new posterpath on the entity. [Jamie] - -- Small modifications. [Jamie] - -- Fixed #1622. [Jamie] - -- Various improvements to webpack/gulp/vscode support (#1617) [Matt Jeanes] - -- Episodes in requests are now in order #1597 (#1614) [masterhuck] - -- Fixed a null reference issue in the Plex Content Cacher. [Jamie.Rees] - -- Fixed #1610. [tidusjar] - -- Really fixed the build this time. [tidusjar] - -- Fixed build. [tidusjar] - -- Made the updater work again #1460. [tidusjar] - -- Adding logging into the auto updater and also added more logging around the create inital user for #1604. [tidusjar] - -- Fixed the issue where we did not check if they are already in sonarr when choosing certain options #1540. [tidusjar] - -- We can now delete tv child requests and the parent will get remove #1603. [tidusjar] - -- Finished the api changes requested #1601. [tidusjar] - -- Fixed the Hangfire server timeout issue #1605. [tidusjar] - -- Fixed notifications not sending #1594. [tidusjar] - -- Fixed #1583 you can now delete users. Fixed the issue where the requested by was not showing. Finally fixed the broken poster paths. [tidusjar] - -- Fixed the issue where movie requests were no longer being requested. [tidusjar] - -- Started adding some more unit tests #1596. [Jamie.Rees] - -- #1588 When we make changes to any requests that we can trigger a notification, always send it to all notification agents, even if the user wont recieve it. [Jamie.Rees] - -- Add a message when email notifications are not setup when requesting a password reset. #1590. [Jamie.Rees] - -- Removed text that we no longer need. [Jamie.Rees] - -- Fixed #1574. [Jamie.Rees] - -- #1460 looks like the permissions issue has been resolved. Just need to make sure the Ombi process is terminated. [Jamie.Rees] - -- Put back the old download code. [Jamie.Rees] - -- Test. [Jamie] - -- Build sln. [Jamie.Rees] - -- Order by the username #1581. [Jamie.Rees] - -- Remove sonarr episodes from the cache table. [Jamie.Rees] - -- Couchpotato finished. [tidusjar] - -- Disable run import button if no import options are selected. [tidusjar] - -- Fixed #1574. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixes the issue with non windows systems unable to unzip the tarball #1460. [tidusjar] - -- Finished the couchpotato settings. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed #1570 #1571. [tidusjar] - -- Fixed #1547. [tidusjar] - -- Should fix #1538. [tidusjar] - -- Fixed #1553. [tidusjar] - -- Fixed #1546. [tidusjar] - -- Fixed #1543. [tidusjar] - -- Fixes an issue with Movie caching not working on develop branch of Radarr (#1567) [Jeffrey Peters] - -- This adds two fields to the Email Notifications settings page. It allows for the disabling of TLS/SSL as well as the ability to disable certificate validation when sending notification emails. (#1552) [Jeffrey Peters] - -- Fixed typo (#1551) [Codehhh] - -- Use Sqlite storage for Hangfire. [tidusjar] - -- Fixed the overrides #1539 also display it on screen now too. [tidusjar] - -- Fixed #1542 also added VSCode support. [tidusjar] - -- Fixed some cosmetic issues #865. [Jamie.Rees] - -- Fixed #1531. [Jamie.Rees] - -- Small fixes #865. [Jamie.Rees] - -- Some errors fixed and some ui improvements #865. [tidusjar] - -- Auto-scale large images down to container size (#1529) [Avi] - -- Fix logo on login page. (#1528) [Avi] - -- Another potential issue? :/ [tidusjar] - -- Real fix. [tidusjar] - -- #1513 Added storage path. [Jamie.Rees] - -- Fixed the discord issue relating to images #1513. [Jamie.Rees] - -- Fixed the issue sending movies to Radarr #1513 Fixed typo #1524. [Jamie.Rees] - -- Fixed logo on reset password pages fixed the run importer button on the user management settings. [Jamie.Rees] - -- Fixed crash/error #865. [tidusjar] - -- #1513 fixed the landing page and also the reverse proxy images. [tidusjar] - -- #1513 correctly set the child requests as approved. [tidusjar] - -- Fixed an issue that potentially causes as issue when siging into plex #865. [tidusjar] - -- Remove dev branch. [PotatoQuality] - -- Prepare readme for upcoming beta. [PotatoQuality] - -- #1513 partially fixed a bug. [tidusjar] - -- Fixed the exception. [tidusjar] - -- Fixed the application url not saving #1513. [tidusjar] - -- Fixed liniting. [tidusjar] - -- REVERSE PROXY BITCH! #1513. [tidusjar] - -- Fixed a bug where we were marking the wrong episodes as available #1513 #865. [Jamie.Rees] - -- Fixed an issue where we messed up the pages and routing. [Jamie.Rees] - -- Emby user importer is now therer! #1456. [tidusjar] - -- #1513 Added the update available icon. [tidusjar] - -- Fixed the issue of it showing as not requested when we find it in Radarr. Made the tv shows match a bit more to the movie requests Added the ability for plex and emby users to login Improved the welcome email, will only show for users that have not logged in Fixed discord notifications the about screen now checks if there is an update ready #1513. [tidusjar] - -- Support email addresses as usernames #1513. [Jamie.Rees] - -- Link to issue treath. [PotatoQuality] - -- Give correct feedback when testing email notifications #1513. [Jamie.Rees] - -- Report issue removed and the deny dropdown removed #1513. [Jamie.Rees] - -- #1513 removed the discord text when testing pushbullet. [Jamie.Rees] - -- Made a lot of changes around the notifcations to support the custom app name also started on the welcome email ##1456. [Jamie.Rees] - -- Fixed the bug where we were displaying shows where we do not have enough information to request #1513. [Jamie.Rees] - -- #1513 added the network to tv shows. [Jamie.Rees] - -- Fixed the whitespace issue #1513. [Jamie.Rees] - -- Fixed the swagger endpoint #865 #1513 Fixed the custom image issue on the login page Fixed the bug when clicking on the tab on the requests page it would switch to the wrong one Swagger is now back @ /swagger. [tidusjar] - -- Optimized images, Update old compressed image with a new lossless one. (#1514) [camjac251] - -- #1513 #865 Fixed the issue where we do not send the requests to Radarr/Sonarr when approving. [tidusjar] - -- #1506 #865 Fixed an issue with the test buttons not working correctly. [tidusjar] - -- #865 Added donation link. [tidusjar] - -- Fixed a bunch of issues on #1513. [tidusjar] - -- #1460 Added the Updater, it all seems to be working correctly. #865. [Jamie.Rees] - -- Removed percentage. [Jamie.Rees] - -- Fixed linter. [Jamie.Rees] - -- Fixed some bugs in the UI #865. [Jamie.Rees] - -- Improved the search buttons #865. [Jamie.Rees] - -- More logging #865. [Jamie.Rees] - -- Made build faster. [Jamie.Rees] - -- More logging. [Jamie.Rees] - -- Set debug level to Debug for now. [Jamie.Rees] - -- Add linting and indexes for interfaces/services (#1510) [Matt Jeanes] - -- Fixed the issue with the tv search not working #1463. [Jamie.Rees] - -- Latest practices... also probably broke some styles - sorry (#1508) [Matt Jeanes] - -- Build with the branch version. [tidusjar] - -- Build fix. [tidusjar] - -- Fixed build. [tidusjar] - -- Omgwtf so many changes. #865. [tidusjar] - -- Tests. [Jamie.Rees] - -- #1456 Started on the User Importer Also added the remember me button. [Jamie.Rees] - -- Made some UI changes, reworked the Emby and Plex screens to make them more user friendly and no so fugly. #865 Also made the login page placeholder text slightly lighter. [Jamie.Rees] - -- Cake skip verification build stuff #865. [Jamie.Rees] - -- Some fixes around the UI and managing requests #865. [tidusjar] - -- #1486. [Jamie.Rees] - -- #1486. [Jamie.Rees] - -- Upgraded to .net core 2.0 #1486. [Jamie.Rees] - -- #865 Finished the landing page, we now check the server's status. [Jamie.Rees] - -- Fixed build. [TidusJar] - -- Removed the telegram api. [Jamie.Rees] - -- Small changes on the updater #1460 #865. [Jamie.Rees] - -- Remove unused functions. [Dhruv Bhavsar] - -- Make Episode picker similar to Requests Child view. #1457 #1463. [Dhruv Bhavsar] - -- Fix merge conflict for TvRequests component. [Dhruv Bhavsar] - -- Upstream Changes... [Dhruv Bhavsar] - -- Clean up Requests page code by moving children request to old component, remove additional REST calls when merging and update component names to make more sense. [Dhruv Bhavsar] - -- Lots of different UI enhancements and fixes #865. [tidusjar] - -- Gitchangelog. [tidusjar] - -- Fixed the issue where we were using the wrong availability options. [tidusjar] - -- Fixed a bunch of bugs in Ombi #865. [tidusjar] - -- Build versioning. [Jamie.Rees] - -- #1460 The assembly versioning seems to work correctly now. [Jamie.Rees] - -- More build versioning changes #865. [tidusjar] - -- Fixed cake script. [Jamie.Rees] - -- WIP on the build versioning for the Updater #1460 #865. [Jamie.Rees] - -- Versioning. [Jamie.Rees] - -- Package versions. [Jamie.Rees] - -- #1460 #865 working on the auto updater. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Small changes around the roles #865. [tidusjar] - -- Improvements to the UI and also finished the availability checker #865 #1464. [Jamie.Rees] - -- Availability Checker #1464 #865. [Jamie.Rees] - -- Fixed ##1492 and finished the episode searcher for #1464. [Jamie.Rees] - -- #1464. [tidusjar] - -- Reload the settings #1464 #865. [Jamie.Rees] - -- #1464 added the Plex episode cacher #865. [Jamie.Rees] - -- Fixed some issues around the tv requests area Added mattermost and telegram notifications #1459 #865 #1457. [tidusjar] - -- Fix global.json. [Dhruv Bhavsar] - -- Working UI for Requests. Approval/Deny does not work as it doesn't in your code either. [Dhruv Bhavsar] - -- Enable diagnostic on build #865. [Jamie.Rees] - -- Fixed the user token issue #865. [Jamie.Rees] - -- Some small refresh token work #865. [Jamie.Rees] - -- Initial TV Requests UI rebuild. [Dhruv Bhavsar] - -- Made a start on supporting multiple emby servers, the UI needs rework #865. [Jamie.Rees] - -- #865 #1459 Added the Sender From field for email notifcations. We can now have "Friendly Names" for email notifications. [Jamie.Rees] - -- Redirect to the landing page when enabled #1458 #865. [Jamie.Rees] - -- Removed IdentityServer, it was overkill #865. [Jamie.Rees] - -- Fixed another bug with identity. #865 I'm thinking about removing it. Causing more hassle than it's worth. [tidusjar] - -- #1460 #865. [tidusjar] - -- Delete appveyor_old.yml. [Jamie] - -- Fixed path. [Jamie.Rees] - -- Silent build level. [Jamie.Rees] - -- #1459 Forgot to get the Pushbullet agent to look up the pusbullet templates rather than the Discord ones. Updated the Gitchange log. [Jamie.Rees] - -- Made the placeholder color on the login page a bit lighter #865. [Jamie.Rees] - -- Landing and login page changes #865 #1485. [tidusjar] - -- #1458 #865 More work on landing. [Jamie.Rees] - -- Working on the landing page #1458 #865. [tidusjar] - -- A lot of clean up and added a new Image api #865. [Jamie.Rees] - -- Cleaned up the Logging API slightly #1465 #865. [Jamie.Rees] - -- Fixed the Identity Server discovery bug #1456 #865. [tidusjar] - -- Fixed the issue with the Identity Server running on a different port, we can now use -url #865. [Jamie.Rees] - -- Try again. [TidusJar] - -- Publish ubuntu 16.04. [Jamie.Rees] - -- Chnaged the updater job from Minutely to Hourly. [Jamie.Rees] - -- Some work around the Auto Updater and other small changes #1460 #865. [Jamie.Rees] - -- Missed a file. [tidusjar] - -- Fixed the swagger issue. [tidusjar] - -- RDP issues. [tidusjar] - -- Appveyor build rdp investigation. [tidusjar] - -- Working on the requests page #1457 #865. [tidusjar] - -- Made the password reset email style the same as other email notifications #1456 #865. [Jamie.Rees] - -- Fixed some bugs around the authentication #1456 #865. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Fixed build #1456. [Jamie.Rees] - -- #1456 #865 Started on allowing Plex Users to sign in through the new authentication server. [Jamie.Rees] - -- Removed covalent. [Jamie.Rees] - -- #1456 Reset Password stuff #865. [Jamie.Rees] - -- Finished implimenting Identity with IdentityServer4. #865 #1456. [Jamie.Rees] - -- Moved over to using Identity Server with Asp.Net Core Identity #1456 #865. [Jamie.Rees] - -- Started on the requests rework #865. [Jamie.Rees] - -- Extended the Emby API. [Jamie.Rees] - -- Started reworking the usermanagement page #1456 #865. [tidusjar] - -- Lots of refactoring #865. [Jamie.Rees] - -- Created an individual user api endpoint so we can make the user management pages better #865. [TidusJar] - -- Lot's of refactoring. [Jamie.Rees] - -- #1462 #865 Had to refactor how we use notificaitons. So we now have more notification fields about the request. [Jamie.Rees] - -- Looks like Sonarr is finished and works. A lot simplier this time around. #865. [tidusjar] - -- More work on the Sonarr Api Integration #865. [tidusjar] - -- Started on sonarr #865. [tidusjar] - -- Small changes #865. [tidusjar] - -- Damn son. So many changes... Fixed alot of stuff around tv episodes with the new DB model #865. [tidusjar] - -- Fixed the TV Requests issue #865. [Jamie.Rees] - -- Fixed a load of bugs need to figure out what is wrong with tv requests #865. [tidusjar] - -- #865 rework the backend data. Actually use real models rather than a JSON store. [Jamie.Rees] - -- Fixed the build issue #865. [tidusjar] - -- Allow us to use Emby as a media server. [tidusjar] - -- More Update #865. [Jamie.Rees] - -- Deployment changes. [Jamie.Rees] - -- More work on the Updater. [Jamie.Rees] - -- Lots of fixes. Becoming more stable now. #865. [tidusjar] - -- Small fixes around the searching. [Jamie.Rees] - -- Some rules #865. [Jamie.Rees] - -- Oops. [TidusJar] - -- Started on the Discord API settings page. [TidusJar] - -- Email Notifications are now fully customizable and work! #865. [Jamie.Rees] - -- Small changes and fixed some stylingon the plex page #865. [Jamie.Rees] - -- More on #865 TODO, Find out whats going on with the notifications and why exceptions are being thrown. [Jamie.Rees] - -- Oops. [Jamie.Rees] - -- Ok #865 fixed the published exe. [Jamie.Rees] - -- Fixed errors. [Jamie.Rees] - -- Fixed build script. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Some more #865. [Jamie.Rees] - -- Create appveyor.yml. [Jamie] - -- The Approving child requests now work! [Jamie.Rees] - -- Fixed many bugs #865. [Jamie.Rees] - -- Loads of changes, improved the movie search stylings is back. [Jamie.Rees] - -- Moved to webpack and started on new style. [Jamie.Rees] - -- Fixed the TV search via Trakt not returning Images anymore. #865. [Jamie.Rees] - -- Rules changes and rework. [Jamie.Rees] - -- Request Grid test. [Jamie.Rees] - -- Small cleanup #865. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Started the Radarr Settings #865. [Jamie.Rees] - -- Massive amount of rework on the plex settings page. It's pretty decent now! #865. [tidusjar] - -- Fixed build. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Rules #865. [tidusjar] - -- Stuff. [Jamie.Rees] - -- Forgot to uncomment. [Jamie.Rees] - -- Tetsd. [Jamie.Rees] - -- Build task changes. [Jamie.Rees] - -- Adsa. [Jamie.Rees] - -- Appveyor. [Jamie.Rees] - -- Stuff around tokens and also builds. [Jamie.Rees] - -- Finished the Plex Content Cacher. Need to do the episodes part but things are now showing as available! #865. [tidusjar] - -- Small user changes #865. [Jamie.Rees] - -- Stuff #865 need to work on the claims correctly. [Jamie.Rees] - -- Reworked the TV model AGAIN #865. [Jamie.Rees] - -- The move! [Jamie.Rees] - -- Fixed build #865. [Jamie.Rees] - -- Fixed the user management #865. [Jamie.Rees] - -- #865 Added support for multiple plex servers. [Jamie.Rees] - -- Bleh. [tidusjar] - -- Small changes. [Jamie.Rees] - -- Fixed the build. [Jamie.Rees] - -- Fixes. [Jamie.Rees] - -- Bundling changes. [Jamie.Rees] - -- Some series information stuff, changes the pace theme too. [Jamie.Rees] - -- Docker support and more, redesign the episodes. [tidusjar] - -- Stuff around episode/season searching/requesting. [Jamie.Rees] - -- Removed redundant folders. [tidusjar] - -- Lots of backend work. [tidusjar] - -- Fixed build. [Jamie.Rees] - -- TV Request stuff. [Jamie.Rees] - -- Work around the user management. [tidusjar] - -- More. [Jamie.Rees] - -- Lots and Lots of work. [Jamie.Rees] - -- Diagnostic changes. [tidusjar] - -- Fixed hangfire exception. [tidusjar] - -- Remove xunit. [tidusjar] - -- Lots more work :( [Jamie.Rees] - -- More changes. [tidusjar] - -- #865. [Jamie.Rees] - -- Small changes. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- More mapping. [Jamie.Rees] - -- Mapping mainly. [Jamie.Rees] - -- Fix systemjs config not being included. [Matt Jeanes] - -- Fixed bundling and various improvements. [Matt Jeanes] - -- Finished the emby wizard #865. [tidusjar] - -- Finished the wizard #865 (For Plex Anyway) [tidusjar] - -- Small changes. [tidusjar] - -- More work on Wizard and Plex API #865. [tidusjar] - -- Settings. [Jamie.Rees] - -- Settings for Ombi. [Jamie.Rees] - -- Fixed some issues around the identity. [Jamie.Rees] - -- #865 more for the authentication. [tidusjar] - -- Auth. [Jamie.Rees] - -- More on the search and requests page. It's almost there for movies. Need to add some filtering logic #865. [tidusjar] - -- #865. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Messing around with the settings. [tidusjar] - -- Fixed the yml. [Jamie.Rees] - -- Remove unneeded bundle config. [Matt Jeanes] - -- Redo dotnet publish targets. [Jamie.Rees] - -- Bundling changes. [Jamie.Rees] - -- Stuff. [Jamie.Rees] - -- Move app into wwwroot. [Jamie.Rees] - -- Put uglify back in! [Jamie.Rees] - -- Wrong line. [Jamie.Rees] - -- Matt is helping. [Jamie.Rees] - -- Revert. [tidusjar] - -- Small tweaks. [tidusjar] - -- Upgrade to .Net Standard 1.6. [tidusjar] - - -## v2.2.1 (2017-04-09) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the forums. [tidusjar] - -- Updates. [tidusjar] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update gulpfile.js. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added a retry policy around the emby newsletter. [Jamie.Rees] - -### **Fixes** - -- Revert "Merge branch 'DotNetCore' into dev" [tidusjar] - -- More borken build. [Jamie.Rees] - -- Started adding requesting. [Jamie.Rees] - -- Done the movie searching. [tidusjar] - -- #865. [tidusjar] - -- More. [tidusjar] - -- Moar. [tidusjar] - -- Small changes. [tidusjar] - -- Styling. [Jamie.Rees] - -- MOre changes. [Jamie.Rees] - -- Spacing. [Jamie.Rees] - -- Try again. [Jamie.Rees] - -- More. [Jamie.Rees] - -- Again. [Jamie.Rees] - -- Anbother. [Jamie.Rees] - -- Another. [Jamie.Rees] - -- Another. [Jamie.Rees] - -- Retry. [Jamie.Rees] - -- A. [Jamie.Rees] - -- Fixed. [Jamie.Rees] - -- Cahnge 2. [Jamie.Rees] - -- Appveyor change. [Jamie.Rees] - -- The start of a new world. [Jamie.Rees] - -- Fixed the migration number and order by the added date for the newsletter #1264. [tidusjar] - -- Forgot this change. [tidusjar] - -- Also fixed the issue for the Emby Newsletter where episodes were not getting added :( [tidusjar] - -- #1264 "They may take our lives, but they'll never take our freedom!" [tidusjar] - -- Finished reworking the Sonarr Integration. Seems to be working as expected, faster and most stable. It's Not A Toomah! [tidusjar] - -- Small bit of work. [Jamie.Rees] - -- Made a start on the new Sonarr integration. [tidusjar] - -- For test emails, if there is no new content then just grab some old data. [tidusjar] - -- Fixed an issue where the emby newsletter was always showing series. [tidusjar] - - -## v2.2.0 (2017-03-30) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added a new setting for the Netflix option, we can now disable it appearing in the search. [tidusjar] - -- Update German Translation. [Marius Schiffer] - -- Added a release notes page, you can access via Admin>Updates>Recent Changes tab. Note to self, need to put better comments in for users to understand! [Jamie.Rees] - -- Added gravitar image. [Jamie.Rees] - -- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] - -- Added a missing `await` for an HP AddArtist call. Added some more Trace logging. [smcpeck] - -- Added some logging around API calls. [smcpeck] - -- Changed IEmbyAvailabilityChecker to use IEnumberables + checking actor search against Emby content + PR feedback. [smcpeck] - -- Changed actor searching to support non-actors too. [smcpeck] - -- Added a 10 second timer to refresh some new caching I put in. [smcpeck] - -- Added root folder and approving quality profiles in radarr #1065. [tidusjar] - -- Added some debugging code around the newsletter for Emby #1116. [tidusjar] - -- Added a TMDB Rate limiter for the newsletter. [tidusjar] - -- Added port check in wizard. also fixed favicon. [tidusjar] - -- Update Radarr placeholder. [d2dyno] - -- Added the user login for emby users #435. [tidusjar] - -- Added User Management support for Emby #435. [tidusjar] - -- Added emby to the sidebar #435. [tidusjar] - -- Added API endpoint for /actor/new/ to support searching for movies not already available/requested. [smcpeck] - -- Update ISSUE_TEMPLATE.md. [Jamie] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -### **Fixes** - -- Translation changes. [Jamie.Rees] - -- Syntax error. [tidusjar] - -- Fixed an issue where we were retrying the API call when the Plex users login creds were invalid. #1217. [tidusjar] - -- Slightly increased the wait time for the emby newsletter also fixed a potential error in the plex user checker. [Jamie.Rees] - -- Fixed an issue where we were not notifiying emby users. [Jamie.Rees] - -- Fixed the issue where the recent changes page was not showing the correct date. #1296. [Jamie.Rees] - -- Fixed #1252 (Show the correct user type on the management page for Plex Users) [Jamie.Rees] - -- Fixed the casting error #1292. [Jamie.Rees] - -- Fix test newletter not sending when empty. [Dhruv Bhavsar] - -- Quick fix for email false positive message. ISSUE: #1286. [Dhruv Bhavsar] - -- Fixes around the newsletter. We will now correctly show newly added shows and also newly added episodes. #1163. [tidusjar] - -- Fixed a sonarr deseralization error. [tidusjar] - -- Increased the delay for the Episode information api calls. #1163. [tidusjar] - -- Looks like we were overloading emby with out api calls. [tidusjar] - -- Fixed the root path escaping issue for Radarr too! [tidusjar] - -- Some small backend newsletter changes, we can now detect if there are any movies and/or tv shows, if there are none then we will no longer send out an empty newsletter. [Jamie.Rees] - -- Remoddeled the notificaiton settings to make it easier to add more. This is some techinical changes that no one except me will ever notice :( [Jamie.Rees] - -- Fixed #1234. [Jamie.Rees] - -- A fix to the about page and also started to rework the notification backend slightly to easily add more notifications. [Jamie.Rees] - -- Adding more logging into the Plex Cacher. [Jamie.Rees] - -- #1218 changed the text when we cannot display release notes for dev and EAP branches. [Jamie.Rees] - -- Fix for #1236. [SuperPotatoMen] - -- Tooltips. [Jamie.Rees] - -- #236. [Jamie.Rees] - -- #1102. [Jamie.Rees] - -- Done #1012. [Jamie.Rees] - -- Oops #1134. [Jamie.Rees] - -- Fixed #1121. [Jamie.Rees] - -- Fixed #1210. [Jamie.Rees] - -- Fixed typo #1134. [Jamie.Rees] - -- Fixed #1223. [Jamie.Rees] - -- Another newsletter fix attempt #1163 #1116. [tidusjar] - -- Fixup! Reset the branch on v2.1.0 tag to get to a shared state between dev and Master. [distaula] - -- Fixed a bug in the Plex Newsletter. [tidusjar] - -- Typo. [tidusjar] - -- Fixed around the newsletter and a small feature around the permissions/features (#1215) [Jamie] - -- Fixed #1189. [tidusjar] - -- Fixed #1195. [Jamie.Rees] - -- Fixed #1195. [Jamie.Rees] - -- Fixed #1192. [Jamie.Rees] - -- Fixed issue where we could get null rating keys on Plex. [tidusjar] - -- Needed to treat a 201 as success, too. + removed some commented out code. [Shaun McPeck] - -- Normalized spacing/tabs. [smcpeck] - -- Move local user login to be the first thing checked; renamed old Api variable to PlexApi now that Emby is in play. [smcpeck] - -- Remove all the polling/retry logic around HP requests. This was a problem do to not properly awaiting the initial AddArtist API call being sent to HP. Also fix SetAlbumStatus to use ReleaseId instead of MusicBrainsId (same fix previously applied to AddArtist). [smcpeck] - -- Restore checking of HTTP StatusCode on ApiRequests; remove checking of response.ErrorException. [smcpeck] - -- Reverted (for now) non-200 response handling; added some extra logging. [smcpeck] - -- Tweaked ApiRequest behavior on non-200 responses; think it was breaking login. :-" [smcpeck] - -- Only deserialize response payload in ApiRequest when StatusCode == 200. Will a default return value in other cases cause other issues? [smcpeck] - -- Headphones - added releaseID to generic RequestedModel and passing that through to HP request. Their API doesn't request via the MusicBrainzId. [smcpeck] - -- Fixed #1038. [tidusjar] - -- Fixed a slight issue where we could click the change folders button rather than the dropdown arrow #1189. [tidusjar] - -- Bunch of updater files. [tidusjar] - -- #1163 #117. [tidusjar] - -- Removed some unnecessary 'ConfigureAwait` uses. [smcpeck] - -- Remove meaningless html class from actor searching checkbox. [smcpeck] - -- Fixed an issue where we were not always showing movies from external programs. [tidusjar] - -- Remove extra delay when filtering out existing movies. [smcpeck] - -- Post merge build fixes. [smcpeck] - -- Fix. [tidusjar] - -- Fixed #1177. [tidusjar] - -- Fixed #1152. [tidusjar] - -- Fixed #1123. [tidusjar] - -- Fixed a bug when sending to radarr. [tidusjar] - -- Fixed #1133. [tidusjar] - -- Fixed issues img. [Jamie.Rees] - -- Stop Plex being enabled on the first time installing #1048. [Jamie.Rees] - -- The landing page now works for emby #435. [tidusjar] - -- Fixed #1104. [tidusjar] - -- Fixed #1090. [tidusjar] - -- Fixed #1103. [tidusjar] - -- Small changes. [tidusjar] - -- Break out Mass Email feature into its own tab, upgrade Font Awesome and clean up some comments. [dhruvb14] - -- Fix typo. [Travis Bybee] - -- Fixed #1066. [Jamie.Rees] - -- Fixed broken builds. [Jamie.Rees] - -- Fixed #1083. [Jamie.Rees] - -- #1049. [tidusjar] - -- Fixed #1071. [tidusjar] - -- Fixed #1048 #1081. [tidusjar] - -- #1074. [Jamie.Rees] - -- #1069. [Jamie.Rees] - -- Fix for #1068. [tidusjar] - -- Remove duplciate tv show status. [tidusjar] - -- Some request ui changes. [tidusjar] - -- Removed references to Plex. [tidusjar] - -- Removed plex from the scheduled jobs ui. [tidusjar] - -- First run of the newsletter set it to a test. [tidusjar] - -- Reworked the newsletter for Emby! Need to rework it for Plex and use the new way to do it. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed the mass email, it was only being set to users with the newsletter feature #358. [tidusjar] - -- Removed Plex Request from the notifications. [tidusjar] - -- Finish implementing mass email feature. [dhruvb14] - -- @tidusjar pointed out runtime error!! [dhruvb14] - -- Does not compile, need to get data from UI into nancy somehow and figure out why IMassEmail is not initializing. [dhruvb14] - -- Begin Implementing Mass Email Section. [dhruvb14] - -- Hide the auto update btn #236 Fixed where we were not populating the emby episodes #435. [tidusjar] - -- Fix Radarr labels. [d2dyno] - -- Fixed pace loader. [Jamie.Rees] - -- Check if Emby/Plex is enabled before starting the job. [Jamie.Rees] - -- Fixed #1036. [Jamie.Rees] - -- Fixed a typo and changed wording. [Torkil Liseth] - -- Fixed #1035. [Jamie.Rees] - -- Fix for #1026. [Jamie.Rees] - -- Fixed #1042. [tidusjar] - -- #435. [Jamie.Rees] - -- #435 Started the wizard. [Jamie.Rees] - -- Removed. [tidusjar] - -- Final Fixes. [dhruvb14] - -- Partial fix for broken HR tag's in Email... [dhruvb14] - -- DAMN! #435 that's a lot of code! [tidusjar] - -- Started adding Emby, Lots of backend work done. Need a few more services done and login and user management. #435. [tidusjar] - -- UI changes to add checkbox and support searching for only new matches via new API. [smcpeck] - -- REFACTOR: IAvailabilityChecker - changed arrays to IEnumerables. [smcpeck] - -- UI changes to consume actor searching API. [smcpeck] - -- API changes to allow for searching movies by actor. [smcpeck] - -- Enforcing async/await in synchronous methods that were marked async. [smcpeck] - - -## v2.1.0 (2017-01-31) - -### **New Features** - -- Update README.md. [Jamie] - -- Update .gitattributes. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added the new labels to the search. [tidusjar] - -- Added a switch to use the new search or not, just in case people do not like it. added a migration to turn on the new search. [Jamie.Rees] - -- Added a bunch of categories for tv search similar to what we have for movies. [Jamie.Rees] - -### **Fixes** - -- Fixed typos. [Haries Ramdhani] - -- Fix typo in readme. [tdorsey] - -- Fixed #985. [Jamie.Rees] - -- FIxed #978. [tidusjar] - -- Fixed the approval issue for #939. [tidusjar] - -- Some general improvements. [tidusjar] - -- Turned off migration for now. [tidusjar] - -- Fixed #998. [tidusjar] - -- Additional movie information. [Jamie.Rees] - -- Debug info around the notifications. [Jamie.Rees] - -- Small changes. [tidusjar] - -- Fixed #995. [tidusjar] - -- Fix for #978. [tidusjar] - -- Fixed #991. [tidusjar] - -- Fixed the login issue and pass Radarr the year #990. [Jamie.Rees] - -- More small tweaks around the username/alias. [Jamie.Rees] - -- Possible issue with the empty username. [Jamie.Rees] - -- Potential Fix for #985. [Jamie.Rees] - -- Small changed to the sidebar. [Jamie.Rees] - -- Small changes. [Jamie.Rees] - -- Done #627. [Jamie.Rees] - -- Finished #535 #445 #170. [tidusjar] - -- Fixed tests. [Jamie.Rees] - -- Started to add the specify Sonarr root folders. [Jamie.Rees] - -- Fixed #968. [Jamie.Rees] - -- Fixed #970. [Jamie.Rees] - -- Done #924. [Jamie.Rees] - -- Fixed. [Jamie.Rees] - -- Fixed #955. [Jamie.Rees] - -- #956. [Jamie.Rees] - -- Fixed #947. [Jamie.Rees] - -- #951. [tidusjar] - -- Finished #923 !!! [tidusjar] - -- More for #923. [Jamie.Rees] - -- Radarr integartion in progress #923. [tidusjar] - -- Fixed #940 don't show any shows without a tvdb id. [tidusjar] - -- Finished #739. [Jamie.Rees] - -- Initial impliementation of #739. [Jamie.Rees] - -- Improved the search UI and made it more consistant. Finished the Netflix API Part #884. [Jamie.Rees] - - -## v2.0.1 (2017-01-16) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added a netflix api. [Jamie.Rees] - -### **Fixes** - -- Fixed #934. [Jamie.Rees] - - -## v2.0 (2017-01-14) - -### **New Features** - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Update README.md. [SuperPotatoMen] - -- Added the settings for #925 but need to apply the settings to the UI. [Jamie.Rees] - -- Changed the settings name from Plex Requests to Ombi. [Jamie.Rees] - -- Added support for Managed Users #811. [Jamie.Rees] - -- Change solution name in travis. [mhann] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -### **Fixes** - -- Finished #925. [Jamie.Rees] - -- Some TODO's. [Jamie.Rees] - -- Fixed #915. [Jamie.Rees] - -- Fixed the issue where notifications are not being sent to users with Aliases #912. [Jamie.Rees] - -- Fixed #891. [Jamie.Rees] - -- Fix indentation issue. [Marcus Hann] - -- Implement simple button. [Marcus Hann] - -- Plex Username Case Sensitivity Fix. [thegame3202] - -- Fixed #882. [Jamie.Rees] - -- Api changed again, so more fixes for #878. [Jamie.Rees] - -- Possible fix for #893. [Jamie.Rees] - -- Fixed #898. [Jamie.Rees] - -- Fixed #878. [TidusJar] - -- * userManagementController.js: fixed #881. [TidusJar] - -- More work on watcher, should all be good now. #878. [Jamie.Rees] - -- Delete PlexRequests.sln.DotSettings. [Jamie] - -- Fixed #862. [Jamie.Rees] - -- #399 and #398 finished. [Jamie.Rees] - -- More work on #399. [Jamie.Rees] - -- Finished #884. [Jamie.Rees] - -- More for #844. [Jamie.Rees] - -- Another #844. [Jamie.Rees] - -- Fixed a dependancy issue with #844. [Jamie.Rees] - -- Finished the main part of #844 just need testing. [Jamie.Rees] - -- Fixed #832. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Fix tiny readme typo. [mhann] - -- Fixed #850 also started #844 (Wrote the API interaction) [Jamie.Rees] - -- #801 #292 done. [Jamie.Rees] - -- Should fix #841 #835 #810. [Jamie.Rees] - -- Fix small typo in ticket overview page. [mhann] - -- More work on the combined login. [Jamie.Rees] - -- Fixed db issue. [Jamie.Rees] - -- Name changes. [Jamie.Rees] - -- All Sln changes. [tidusjar] - -- Moved API Sln dir. [tidusjar] - -- Fixed build. [tidusjar] - -- Moved namespaces. [tidusjar] - -- Renamed zip. [tidusjar] - -- Product name change. [tidusjar] - - -## v1.10.1 (2016-12-17) - -### **Fixes** - -- #788 fixed! [tidusjar] - -- Fixed #788 and #791. [tidusjar] - -- #399 #398. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Small refactorings. [Jamie.Rees] - -- #782. [Jamie.Rees] - -- #785. [Jamie.Rees] - - -## v1.10.0 (2016-12-15) - -### **New Features** - -- Update README.md. [Jamie] - -- Added optional launch args for the auto updater. [Jamie.Rees] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update _Navbar.cshtml. [Jamie] - -- Update README.md. [Jamie] - -- Update _Navbar.cshtml. [Jamie] - -- Update README.md. [Jamie] - -- Added a new permission to bypass the request limit. [Jamie.Rees] - -- Update Version1100.cs. [SuperPotatoMen] - -- Added logging around the Newsletter #717. [Jamie.Rees] - -- Added missing migration. [tidusjar] - -- Added loading spinner. [Jamie.Rees] - -- Update UI.resx. [SuperPotatoMen] - -- Update Version1100.cs. [Jamie] - -- Update ISSUE_TEMPLATE.md. [SuperPotatoMen] - -### **Fixes** - -- Fixed an issue where the HTML in the newsletter was incorrect. [Jamie.Rees] - -- Fixed #201. [Jamie.Rees] - -- Fixed #720 and added better error handling around the migrations. [Jamie.Rees] - -- Fixed #769. [Jamie.Rees] - -- Write out the actual file version. [Jamie.Rees] - -- Error checking around GA. [TidusJar] - -- Fixed #761. [tidusjar] - -- Fixed #749 Fixed an issue where we were adding the read only permission when creating the admin. [tidusjar] - -- Fixed #757. [tidusjar] - -- Fixes around the server admin #754. [Jamie.Rees] - -- Removed the trace option from the UI, it is only accessible when appending the url with "?developer" #753. [Jamie.Rees] - -- Fixed an issue where the admin could not be updated. [Jamie.Rees] - -- Fixed #745. [Jamie.Rees] - -- Fixed #748. [Jamie.Rees] - -- Workaround for #748. [SuperPotatoMen] - -- Another attempt to fix #717. [tidusjar] - -- Fixed #744. [Jamie.Rees] - -- Tidied up the warnings. [Jamie.Rees] - -- Small bit of analytics. [Jamie.Rees] - -- Removed the whitelist. [Jamie.Rees] - -- Should fix #696 Fixed an issue with the scheduled jobs where it could use a different trigger if the order between the schedules and the triggers were in different positions in the array... Stupid me, ordering both arrays by the name now. [tidusjar] - -- Some better null object handling #731. [Jamie.Rees] - -- Small tweaks. [Jamie.Rees] - -- Fixed #728. [Jamie.Rees] - -- Fixed #727. [Jamie.Rees] - -- Fixed admin redirect issue. [tidusjar] - -- Fixed #718. [tidusjar] - -- Lots of small fixes and tweaks. [Jamie.Rees] - -- Tidied up some of the angular code, split the UI into it's own directives for easier maintainability. [Jamie.Rees] - -- Small tweaks to the Request Page. [Jamie.Rees] - -- Reverted the PR that may have caused #619. [Jamie.Rees] - -- Some small tweaks around #218 Just added the link to the settings and some angular improvements. [Jamie.Rees] - -- Test. [Jamie.Rees] - -- Attempt at fixing #686. [Jamie.Rees] - -- Finished #707. [Jamie.Rees] - -- Fixed #704. [Jamie.Rees] - -- Fixed #705. [Jamie.Rees] - -- Fixed #706. [Jamie.Rees] - -- #547. [Jamie.Rees] - -- Default tabs #304. [Jamie.Rees] - -- Fixed #703. [Jamie.Rees] - -- #233. [Jamie.Rees] - -- Done #678. [Jamie.Rees] - -- Fixed #670. [Jamie.Rees] - -- #456 Update all the requests when we identify that the username changes. [Jamie.Rees] - -- More user management. [Jamie.Rees] - -- #218. [Jamie.Rees] - -- Fixed build. [tidusjar] - -- Implimented the features #218. [tidusjar] - -- Use the user alias everywhere if it is set #218. [tidusjar] - -- Implimented auto approve permissions #218. [tidusjar] - -- A. [tidusjar] - -- Fixed an IOC issue. [tidusjar] - -- Fixed the issue with user management, needed to implement our own authentication provider. [Jamie.Rees] - -- Small changes including #666. [Jamie.Rees] - -- Done #679. [tidusjar] - -- Reduce the retry time. [Jamie.Rees] - -- Remove all references to the claims. [Jamie.Rees] - -- Lots of fixed and stuff. [Jamie.Rees] - -- Fixed potential crash #683. [Jamie.Rees] - -- Fixed #681. [Jamie.Rees] - -- More user management. [Jamie.Rees] - -- Finishing off the user management page #218 #359 #195. [Jamie.Rees] - -- Finished #646 and fixed #664. [Jamie.Rees] - -- Started on #646. Fixed #657. [Jamie.Rees] - -- Fixed #665. [Jamie.Rees] - -- Migrate users. [TidusJar] - -- Fixed build. [Jamie.Rees] - -- Convert the for to foreach for better readability. Still need to rework this area. [Jamie.Rees] - -- Final Tweaks #483. [Jamie.Rees] - -- Finished #483. [Jamie.Rees] - -- Finished the queue #483. [Jamie.Rees] - -- Started on the queue for requests #483 TV Requests with missing information has been completed. [Jamie.Rees] - -- Fixed build. [Jamie.Rees] - -- Finished the notification for the fault queue. [Jamie.Rees] - -- Finished #556. [Jamie.Rees] - -- Finished #633 (First part of the queuing) [Jamie.Rees] - -- Finished #659 #236 has been modified slightly. Needs testing on Different systems. [Jamie.Rees] - -- Almost finished #659. [Jamie.Rees] - -- Started on #483. [Jamie.Rees] - -- #544. [Jamie.Rees] - -- Fixed #656 and more work on #218. [Jamie.Rees] - -- Fixed some issues with the user management work. [TidusJar] - -- Fixed build issue. [TidusJar] - -- User perms. [Jamie.Rees] - - -## v1.9.7 (2016-11-02) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Potential fix for #629. [TidusJar] - -- Fixed an issue to stop blatting over the base url. [tidusjar] - -- Fixed #643. [TidusJar] - -- Fixed #622. [TidusJar] - - -## v1.9.6 (2016-10-28) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fixed #586. [Jamie.Rees] - -- Fixed #622. [Jamie.Rees] - -- Fixed #621. [Jamie.Rees] - - -## v1.9.5 (2016-10-27) - -### **New Features** - -- Added our own custom migrations, a lot easier to migrate DB versions now. [tidusjar] - -### **Fixes** - -- Bump version. [Jamie.Rees] - -- Small bit of work on the user claims. [Jamie.Rees] - -- Fix #612 again. [Jamie.Rees] - -- User management styling. [Jamie.Rees] - -- Fixed #608 and some other small stuff. [tidusjar] - -- More user mapping. [tidusjar] - -- Fixed #615. [tidusjar] - -- Fixed #610. [tidusjar] - -- User management stuff. [Jamie.Rees] - -- User management work. [Jamie.Rees] - -- Revert the TVSender to use the old code. [Jamie.Rees] - -- Fixed the view issue. [tidusjar] - -- S582: admin improvements part 2. [Jim MacKenzie] - -- Fix #612. [Jamie.Rees] - -- User management, migration and newsletter. [Jamie.Rees] - -- #602 recently added improvements. [tidusjar] - -- Revert "Sorting out the current state of migrations" [Jamie.Rees] - -- Sorting out the current state of migrations. [Jamie.Rees] - -- Marked as obsolete. [Jim MacKenzie] - -- Migration setup. [Jim MacKenzie] - -- Removed extra line breaks. [Jim MacKenzie] - -- Moved Newsletter Settings to its own page. [Jim MacKenzie] - -- Reverted TMDB package. [Jamie.Rees] - -- Remove DB Option. [Jamie.Rees] - -- Upgrade the movie DB package and fixed #370 To fix this I had to make another API call... It slows down the search... [tidusjar] - -- Lots of small fixes including #475. [tidusjar] - -- A better fix for #587. [tidusjar] - -- Fixed #553. [tidusjar] - -- #601. [Jamie.Rees] - -- More rework to use the Plex DB. [Jamie.Rees] - -- More work around using the PlexDatabase. [Jamie.Rees] - -- Plex DB. [Jamie.Rees] - -- Allow to process even know we had an error #578. [Jamie.Rees] - -- Fix boostrapper-datetimepicker imports (#586) [David Torosyan] - -- Potential work around for #587. [tidusjar] - -- Fixed #589. [tidusjar] - - -## v1.9.4 (2016-10-10) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added Paypalme options, no UI yet (#568) [Jim MacKenize] - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -### **Fixes** - -- Reverted. [tidusjar] - -- Make sure it's enabled before sending the recently added. [tidusjar] - -- Moved the HR inside the table for TV Shows. [Jamie.Rees] - -- FIXED!!!!! YES BITCH! #550. [tidusjar] - -- Moved the horizontal rules inside the table row. [tidusjar] - - -## v1.9.3 (2016-10-09) - -### **New Features** - -- Added properties to disable tv requests for specific episodes or seasons and wired up to admin settings. [Matt McHughes] - -- Added different sonarr search commands. [tidusjar] - -### **Fixes** - -- Fixed #515. [tidusjar] - -- Fixed #561 and a small bit of work on #569. [tidusjar] - -- #569. [tidusjar] - -- Fixed case typo. [Matt McHughes] - -- Finished wiring tv request settings to tv search. [Matt McHughes] - -- WIP hide tv request options based on admin settings. [Matt McHughes] - -- Set meta charset to be utf-8. [Madeleine Schönemann] - -- F#552: updated labels text. [Jim MacKenize] - -- F#552: Re-design lables. [Jim MacKenzie] - -- Last correction.. Now the translation is ready to be used. [Michael Reber] - -- Forgot to correct two incorrect translations. [Michael Reber] - -- Correction of the German translation. [Michael Reber] - -- Notification improvements. [tidusjar] - -- #515. [tidusjar] - - -## v1.9.2 (2016-09-18) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update CouchPotatoCacher.cs. [Jamie] - -- Added some error handing around the GetMovie area #517. [tidusjar] - -- Added a version endpoint in "/api/version" #529. [tidusjar] - -### **Fixes** - -- Trying to fix the auto CP. [tidusjar] - -- Increase the notice message text box #527. [tidusjar] - -- #536 this should fix notification settings when it is being unsubscribed when testing. [tidusjar] - -- Improved how the TV search looks and feels. [tidusjar] - -- Fix for reverse proxy when using the wizard. [Devin Buhl] - -- Fixed #532. [tidusjar] - -- This should fix some issues with the episode requests #514. [tidusjar] - -- Small changes around existing series. [tidusjar] - -- Fixed #514 and the unit tests. [tidusjar] - -- If there is a bad password when changing it, we now inform the user. [tidusjar] - -- When logging out as admin remove the username from the session. [tidusjar] - -- Sorted out some of the UI for #18. [tidusjar] - -- Finished #18. [tidusjar] - - -## v1.9.1 (2016-08-30) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added french to the navbar. [tidusjar] - -- Changed the way we use the setTimeout function. Should fix #403 #491 #492. [tidusjar] - -- Change the redirection to use a relative uri redirect #473. [tidusjar] - -### **Fixes** - -- Fixed tests. [tidusjar] - -- Fixed #491 and added more logging around the email messages under the Info level. [tidusjar] - -- Finished #415. [tidusjar] - -- Fixed an issue where there were some JS errors on the landing page settings and stopped us being redirected to the login sometimes as an admin. [tidusjar] - -- Fixed #480. [tidusjar] - -- User management. [tidusjar] - -- Fixed #505. [tidusjar] - -- Append the application version to the end of our JS/CSS files. [tidusjar] - -- Fixed issue #487. [tidusjar] - -- Remove the datetime picker css from the main assets block and only load it on the pages it needs. #493. [tidusjar] - -- Redirect to search if we are already logged in #488. [tidusjar] - -- Fixed build. [tidusjar] - -- Fixed an issue where you could set the base url as requests #479. [tidusjar] - -- Working on the beta releases page and also the user management. [tidusjar] - -- User work. [tidusjar] - - -## v1.9.0 (2016-08-18) - -### **New Features** - -- Update the availability checker to search for TV Episodes. [tidusjar] - -- Changed the no TVMazeid message. [tidusjar] - -- Added an option to disable/enable the Plex episode cacher. [tidusjar] - -- Updated the episode cacher to have a minimum of 11 hours before it runs again. [tidusjar] - -- Added some useful analytical infomation around the wizard. [tidusjar] - -- Updated the German translations #402. [tidusjar] - -- Added some code to shrink the DB. reworked the search to speed it up. [tidusjar] - -- Change to use the GrandparentTitle rather than the thumbnail.... facepalm. [tidusjar] - -- Change the interval to hours! [tidusjar] - -- Added the transaction back into the DB. Do not run the episode cacher if it's been run in the last hour. [tidusjar] - -- Added logging. [tidusjar] - -- Changed the query slightly. [tidusjar] - -- Updated Newtonsoft.Json, Autofixture, Nlog and Dapper packages. [tidusjar] - -- Added the Sonarr check for episodes #254. [tidusjar] - -- Added unit tests. [tidusjar] - -- Added #436. [tidusjar] - -- Update build no. [tidusjar] - -- Updated translations for #402. [tidusjar] - -- Added a beta module. [tidusjar] - -- Added a custom debug root path provider, this means we do not have to recompile the views every time we make a view change. [tidusjar] - -- Update .gitignore. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added tests for the string hash. [tidusjar] - -- Added code to request the api key for CouchPotato. [tidusjar] - -- Added the file version to the layout. [tidusjar] - -- Update appveyor.yml. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added automation tests. [tidusjar] - -- Update appveyor.yml. [Jamie] - -- Updated packages. [tidusjar] - -- Updated Polly. [tidusjar] - -- Updated Fr, IT and NL translations #402. [tidusjar] - -- Changed the way the donate button works for #414. [tidusjar] - -- Added MediatR. [tidusjar] - -### **Fixes** - -- User management stuff. [tidusjar] - -- Fixed! [tidusjar] - -- Small amount of work on the user management. [tidusjar] - -- Fixed #466. [tidusjar] - -- Fixes. [tidusjar] - -- Made the episode request better. [tidusjar] - -- Removed commented out tests. [tidusjar] - -- Fixed the bad test after the merge. [tidusjar] - -- Reworked #466. [tidusjar] - -- More unit tests around the login and also the core Plex Checker. [tidusjar] - -- Potentially fixed the issue where we were requesting everything that was also available now. [tidusjar] - -- This should fix #466. [tidusjar] - -- Attempt at fixing a potential bug found from #466. [tidusjar] - -- #464 fixed. [tidusjar] - -- Fixed the build. [tidusjar] - -- Small improvements to the wizard. [tidusjar] - -- Always set the wizard to be true when editing the Plex Requests settings (Since the flag is not in the UI, a bool defaults to false). [tidusjar] - -- Tiny bit of more info. [tidusjar] - -- Finished #459. [tidusjar] - -- #459 is almost done. [tidusjar] - -- Modified the episode modal so that we are now resetting the button after a request. [tidusjar] - -- Commented out the transaction for now to debug it. [tidusjar] - -- Since we are multithreading, we should use a threadsafe type to store the episodes to prevent any threading or race conditions. [tidusjar] - -- Wrapped the bulk insert inside a transaction. [tidusjar] - -- Made the episode check parallel. [tidusjar] - -- Log out the GUID causing the issue. [tidusjar] - -- Fixed another test. [tidusjar] - -- Fixed tests. [tidusjar] - -- Got mostly everything working for #254 Ready for testing. [tidusjar] - -- Fixed issue with saving to db. [tidusjar] - -- Need to work out why the cacher is not working and where the datatype mismatch is. [tidusjar] - -- Don't delete first. [tidusjar] - -- Fix the log path issue #451. [tidusjar] - -- Dump an item. [tidusjar] - -- Small change with the return value in the batch insert. [tidusjar] - -- #254 Removed the cache, we are now storing the plex information into the database. [tidusjar] - -- Small change in the episode saver. [tidusjar] - -- Some small tweaks to improve the memory alloc. [tidusjar] - -- Short circuit when Plex hasn't been setup. Added Miniprofiler. [tidusjar] - -- Consolidate newtonsoft.json packages. [tidusjar] - -- Some performance improvements around the new TV stuff. [tidusjar] - -- Reworked the cacher, fixed the memory leak. No more logging within tight loops. [tidusjar] - -- Another null check. [tidusjar] - -- Some more changes. [tidusjar] - -- Some error handling. [tidusjar] - -- Check if the sonarr ep is monitored. [tidusjar] - -- Some logging. [tidusjar] - -- Small changes, we will actually see the episode cacher on the scheduled jobs page now. [tidusjar] - -- Work on the UI to show what episodes have been requested #254. [tidusjar] - -- Small fix. [tidusjar] - -- Fix the api change in #450. [tidusjar] - -- #254. [tidusjar] - -- Workaround for #440. [tidusjar] - -- Async async async improvements. [tidusjar] - -- Finished #266 Added a new cacher job to cache all episodes in Plex. [tidusjar] - -- Fixed #442. [tidusjar] - -- #254. [tidusjar] - -- Work around the sonarr bug #254. [tidusjar] - -- #254 having an issue with Sonarr. [tidusjar] - -- Small bit of work on #266. [tidusjar] - -- #254. [tidusjar] - -- Precheck and disable the episode boxes if we already have requested it. TODO check sonarr to see if it's already there. #254. [tidusjar] - -- Fixed broken build. [tidusjar] - -- More work for #254. [tidusjar] - -- More work on #254. [tidusjar] - -- Fixed the bug in #438 and added unit tests to make so we dont break it in the future. [tidusjar] - -- Some reason we had dupe translations. [tidusjar] - -- Rename SubDir to Base Url. [tidusjar] - -- Fix the exception in #440. [tidusjar] - -- Reworking the login page for #426. [tidusjar] - -- Fixed #438. [tidusjar] - -- Finished the auth stuff. [tidusjar] - -- Finished up the SMTP side of #429. [tidusjar] - -- #428 Added a message when the we cannot get a TVMaze ID. [tidusjar] - -- #254 MOSTLY DONE! At last, this took a while. [tidusjar] - -- Removed the other rootpath provider. [TidusJar] - -- Removed the other rootpath provider. [TidusJar] - -- Removed the other rootpath provider. [TidusJar] - -- Should fix #429. [TidusJar] - -- Done #135 We are including the application version number in the directory. [tidusjar] - -- #387 trim the spaces from the api key. Tidied up the setting models a bit. [tidusjar] - -- Wrapped the repo to catch Sqlite corrupt messages. [tidusjar] - -- Frontend and tv episodes api work for #254. [tidusjar] - -- #424. [tidusjar] - -- #359. [tidusjar] - -- Moved the plex auth token to the plex settings where it should belong. [tidusjar] - -- Small changes around the user management. [tidusjar] - -- Missed brace. [tidusjar] - -- Removed. [tidusjar] - -- Fixed issues from the merge. [tidusjar] - -- Stupid &$(*£ merge. [tidusjar] - -- Angular. [tidusjar] - -- Reworked the custom notifications... again. Need to figure out how to find the view to the model. [tidusjar] - -- Fixed #417. [tidusjar] - -- Removed NinjectConventions, we hadn't started to use it anyway. [tidusjar] - -- Fixed the way we will be using custom messages. [tidusjar] - -- Test checkin. [tidusjar] - -- Better handling for #388. [tidusjar] - -- Fixed #412. [tidusjar] - -- Fixed #413. [tidusjar] - -- Fixed #409. [tidusjar] - -- Trycatch around the availbility checker. [tidusjar] - -- WIP on notification resolver. [tidusjar] - -- Tidy. [tidusjar] - -- Plugged in MediatR. [tidusjar] - -- Moved over to using Ninject. [tidusjar] - - -## v1.8.4 (2016-06-30) - -### **Fixes** - -- Fixed the bug where we were auto approving everything. Added French language into the navigation bar. [tidusjar] - - -## v1.8.3 (2016-06-29) - -### **New Features** - -- Update README.md. [Jamie] - -- Update appveyor.yml. [Jamie] - -- Added some of the backend bits for #182. [tidusjar] - -- Updates for #243. [tidusjar] - -- Added Dutch language #243. [tidusjar] - -- Added languages #243. [tidusjar] - -- Added logging #350. [tidusjar] - -### **Fixes** - -- Small changes. [tidusjar] - -- Allow html in the notice message. [tidusjar] - -- Some more unit tests around the NotificationMessageResolver. [tidusjar] - -- Fixed a timing bug found the in build. Note, when working with time differences use TotalDays. [tidusjar] - -- More translations on the search page (Mainly the notification messages) #243. [tidusjar] - -- Fixed some warnings. [tidusjar] - -- CodeCleanup. [tidusjar] - -- Fixed a bit of a stupid bug in the resetter and added unit tests around it to make sure this never happens again. [tidusjar] - -- Fixed an issue where we didn't provide the correct response when clearing the logs. [tidusjar] - -- Made it so users that are in the whitelist do not have a request limit. [tidusjar] - -- Made it so the request limit doesn't apply to admin users. [tidusjar] - -- Fixed where a user could see the delete button on the issues page. [tidusjar] - -- Fixed some small issues and improved the navbar. [tidusjar] - -- Translated the Requested page #243. [tidusjar] - -- Finished #337. [tidusjar] - -- Some analytics. [tidusjar] - -- More translations for #243 and welcome text for #293. [tidusjar] - -- Small bit of work for #359. [tidusjar] - -- Finished #6. [tidusjar] - -- Analytics and fixes. [tidusjar] - -- Translated the search page #243. [tidusjar] - -- Implemented the different languages and added the ability to change cultures. #243. [tidusjar] - -- Started #243. [tidusjar] - -- Fixed #364. [tidusjar] - -- Some more useful analytical information. [tidusjar] - -- Generic try catch to fix #350. [tidusjar] - -- Slight changes, moved the donate button. [tidusjar] - -- Potential fix for #350. [tidusjar] - -- Better way of obtaining clean enum string. [Drewster727] - -- Fixed #362. [tidusjar] - - -## v1.8.2 (2016-06-22) - -### **New Features** - -- Update readme. [tidusjar] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fixed a circular reference issue. [tidusjar] - -- Small changes around how we work with custom events in the analytics. [tidusjar] - -- Fixed #353 #354 #355. [tidusjar] - -- Null provider check for movies. [Drewster727] - -- Show request type in notifications #346 and fix an issue from previous commit for #345. [Drewster727] - -- Add an option to stop sending notifications for requests that don't require approval #345. [Drewster727] - - -## v1.8.1 (2016-06-21) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Fix obj ref error when scheduler runs (ProviderId is null?) [Drewster727] - -- Fix logic for obtaining a sonarr quality profile #340. [Drewster727] - - -## v1.8.0 (2016-06-21) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the new advanced search into the search page too. [tidusjar] - -- Change the way we configure the IoC container in the bootstrapper, we are registering all the concrete instances on application start rather than on each web request. This should increase the performance per HTTP request. [tidusjar] - -- Updated nlog and fixed #295. [tidusjar] - -### **Fixes** - -- Workaround for #334. [Drewster727] - -- Create .gitattributes. [Jamie] - -- Fixes to the issues. [tidusjar] - -- Set the defaults for the landing page. [tidusjar] - -- Revert branch to 664dae2. [tidusjar] - -- Some unit tests for the issues. [tidusjar] - -- Tidied up the bootstrapper. [tidusjar] - -- Fix up landing page UI. [Drewster727] - -- Fixed CSS issue with the top arrow in the Plex theme. [tidusjar] - -- Small changes. [tidusjar] - -- Done #318. [tidusjar] - -- Fixed tests. [tidusjar] - -- #298 added some tests for the landing page. [tidusjar] - -- We are now only keeping the latest 1000 log records in the database. Delete everything else. [tidusjar] - -- Some analytic stuff. [tidusjar] - -- Capture the TVDBID when requesting. [tidusjar] - -- Attempting to improve #219. [tidusjar] - -- Just some more async changes. [tidusjar] - -- Small changes. [tidusjar] - -- More work on #298. Everything wired up. [tidusjar] - -- Fixed the issue on the landing page #298. [tidusjar] - -- #298 moved the content to the left a bit. [tidusjar] - -- Styling for #298 done, just need to wire up the model and do the actual status check. [tidusjar] - -- Bumped up the version number. [tidusjar] - -- Removed some DumpJson() from the trace logs. [tidusjar] - -- Small ui fix (100% width user/password fields to improve mobile experience) [Drewster727] - -- Landing page stuff #298. [tidusjar] - -- Datepicker UI fixes + small landing page UI fix. [Drewster727] - -- Removed a change that shoudn't have been commited. [tidusjar] - -- Fixed tests. [tidusjar] - -- More work for #298. [tidusjar] - -- #273 added for only available content on the search. [tidusjar] - -- Fixed #303 Looks like there was some incorrect business logic. [tidusjar] - -- Most of #273 done. [tidusjar] - -- Settings done for #298. [tidusjar] - -- Started #298. [tidusjar] - -- A crap tonne of work on #273. [tidusjar] - -- More work on #273. [tidusjar] - -- Reduced kept logs for 2 days. [tidusjar] - -- Fixed #300. [tidusjar] - -- #273. [tidusjar] - -- Fixed a bug with some users with the CP profiles. [tidusjar] - -- #273. [tidusjar] - -- Done the same for TV. [tidusjar] - -- Fixes #296. [tidusjar] - -- More for #273. [tidusjar] - -- Small changes. [tidusjar] - -- Revert "Small changes" [tidusjar] - -- Small changes. [tidusjar] - -- Finished #221 and added more async #278. [tidusjar] - -- Spelling mistake in the html! this fixes #264. [tidusjar] - -- More work on #273. [tidusjar] - -- Fixed #210. [tidusjar] - -- Started #273. [tidusjar] - - -## v1.7.5 (2016-05-29) - -### **New Features** - -- Update preview. [Jamie] - -- Updated dapper.contrib. Looks like there was a bug in the async methods. [tidusjar] - -- Updater wouldn't work when running a reverse proxy #236. [tidusjar] - -### **Fixes** - -- Bump build ver. [tidusjar] - -- Use HTTPS for the poster images, so there aren't any mixed content warnings when serving the application via an HTTPS reverse proxy. [Sean Callinan] - -- Removed static declarations. [tidusjar] - -- Fixed styling on modal. [tidusjar] - -- Made the search page all async goodness #278. [tidusjar] - -- Made the request module async #278. [tidusjar] - -- Started some dynamic scrolling. [tidusjar] - -- Stop dumping out the settings to the log. [tidusjar] - -- Made more async goodness. [tidusjar] - -- Made some of the searching async #278. [tidusjar] - -- Fixed #277. [tidusjar] - -- Reworked some tests. [tidusjar] - -- #26q make the auth users list taller. [Drewster727] - -- Fix 404 error. [Drewster727] - -- #262 make the auth users list taller. [Drewster727] - -- #221 delete requests per category. [Drewster727] - -- #256 #237 UI Improvements and consolidation. [Drewster727] - -- Fixed a bug in the user notification where if an admin wants to be notified they wouldn't be. [tidusjar] - -- Set the admin to have all claims. [tidusjar] - -- Fix null exception possibility in cp/sickrage cacher classes. [Drewster727] - -- Fixed #244. [tidusjar] - -- Fixed #240. [tidusjar] - -- Fixed #270. [tidusjar] - -- Fixed an issue where if you have only 1 plex friend it would not show in the list. [tidusjar] - - -## v1.7.4 (2016-05-25) - -### **New Features** - -- Update README.md. [Jamie] - -### **Fixes** - -- Fixed #252. [tidusjar] - -- Fixed #428. [tidusjar] - -- Version bump. [tidusjar] - -- Fixed tests. [tidusjar] - -- Fully fixed #239. [tidusjar] - -- We wan't updating the DB schema. [tidusjar] - - -## v1.7.3 (2016-05-25) - -### **Fixes** - -- Fixed the release build issue where we could not access the settings #239. [tidusjar] - - -## v1.7.2 (2016-05-25) - -### **Fixes** - -- Fixed a small bug where an exception would get thrown. [tidusjar] - -- Build version bump. [tidusjar] - -- Cleanup. [tidusjar] - -- Typo. [tidusjar] - -- Fixed #241. [tidusjar] - -- Fixed #239. [tidusjar] - -- Fixed #238. [tidusjar] - -- Small UI tweaks/improvements. [Drewster727] - - -## v1.7.1 (2016-05-24) - -### **New Features** - -- Update version. [tidusjar] - -### **Fixes** - -- Fixed an issue with the auth page when running with a reverse proxy. [tidusjar] - - -## v1.7 (2016-05-24) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added the ability to get the apikey from the api if you provide a correct username and password. Added more unit tests Added the ability to change a users password using the api refactored the Usermapper and made it unit testsable. [tidusjar] - -- Update. [tidusjar] - -- Added in an audit table. Since we are now allowing multiple users to change and modify things we need to audit this. [TidusJar] - -- Added the updater to the soloution and did a bit of starting code. [TidusJar] - -- Updated the claims so we can support more users. Added a user management section (not yet complete) Added the api to the solution and a api key in the settings (currently only gets the requests). [TidusJar] - -- Updated packages. [TidusJar] - -- Added a retry handler into the solution. We can now retry failed api requests. [TidusJar] - -- Update README.md. [Jamie] - -- Added Released propety to RequestViewModel. Added Released filter to the Requests page. [Chris Lees] - -- Added #27 to albums. [tidusjar] - -- Added the actual notification part of #27. [tidusjar] - -- Added the missing baseurl bit on the login page for #72. [tidusjar] - -- Added the 'enable user notifications' to the email settings view and model. [tidusjar] - -- Update README.md. [Jamie] - -### **Fixes** - -- Remove pointless test, change the default theme and fix a small bug. [tidusjar] - -- Fixed api. [tidusjar] - -- Finished #26. [tidusjar] - -- Plex theme. [tidusjar] - -- Implimented a theme changer, waiting for the Plex theme. [tidusjar] - -- Finished #222 #205. [tidusjar] - -- Started working on #26. [tidusjar] - -- Undid some small changes that was checked in by accident. [tidusjar] - -- #164 has been resolved. [tidusjar] - -- Resolved #224 , Removed the 'SSL' option from the email notification settings. We will now use the correct secure socket options (SSL/TLS) for your email host. [tidusjar] - -- Small changes. [tidusjar] - -- #27 fully finished. [tidusjar] - -- Fixed #215. [tidusjar] - -- Using Mailkit to fix #204. [tidusjar] - -- Color. [tidusjar] - -- Fully finished #27 just need to test it! [tidusjar] - -- Fixed test. [tidusjar] - -- Styling for #27. [tidusjar] - -- I think the auto updater is finished! #29. [tidusjar] - -- I think we have finished the main bulk of the auto updater #29. [tidusjar] - -- #222 #205 more ! Started getting the settings out. [tidusjar] - -- Removed the service locator from the base classes and added in some Api tests added all the tests back in! [tidusjar] - -- More work on the api and documentation #222 #205. [tidusjar] - -- Started documenting the API we now have swagger under ~/apidocs #222 #205. [tidusjar] - -- Api work for #205 Refactored how we check if the user has a valid api key Added POST request, PUT and DELTE. [tidusjar] - -- First pass of the updater working. #29. [tidusjar] - -- Removed SIGHUP from the termination list #220. [tidusjar] - -- Fixed. [tidusjar] - -- Missing. [tidusjar] - -- Missed out a file. [TidusJar] - -- And some more... [TidusJar] - -- Missed some files. [TidusJar] - -- A bit more work on switching to using user claims so we can support multiple users. [TidusJar] - -- Made the store backup clean up some of the older backups (> 7 days). [TidusJar] - -- More work on the user management. [TidusJar] - -- - Notifications will no longer be send to the admins if they request something. - Looks like we missed out adding the notifications to Music requests, so I added that in. [TidusJar] - -- - Improved the RetryHandler. - Made the tester buttons on the settings pages a bit more robust and added an indication when it's testing (spinner) [TidusJar] - -- Packages. [TidusJar] - -- Nm, [TidusJar] - -- Downgraded packages. [TidusJar] - -- Better handling for #202. [TidusJar] - -- Finished #208 and #202. [TidusJar] - -- This should help #202. [TidusJar] - -- Resolved #209. [TidusJar] - -- Finished #209. [TidusJar] - -- Slight adjustments to #189. [tidusjar] - -- - Added a visual indication on the UI to tell the admin there is a update available. - We are now also recording the last scheduled run in the database. [tidusjar] - -- Did the login bit on #185. [tidusjar] - -- Finished #186. [tidusjar] - -- Fixed #185. [tidusjar] - -- Fixed issue in #27 with albums. [tidusjar] - -- #27 added TV Search to the notification. [tidusjar] - -- Fixed bug. [tidusjar] - -- More work on #27 Added a new notify button to the search UI (Needs styling). Also fixed a bug where if the user could only see their own requests, if they search for something that has been requested, it will show as requested. [tidusjar] - -- Improved the startup of the application. We now properaly parse any args passed into the console. [tidusjar] - -- Additional cacher error handling + don't bother checking the requests when we don't get data back from plex. [Drewster727] - -- Remove old migration code and added new migration code. [tidusjar] - -- Stop the Cachers from bombing out when the response from the 3rd party api returns an exception or invalid response. #171. [tidusjar] - -- Increase the scheduler cache timeframe to avoid losing cache when the remote api endpoints go offline (due to a reboot or some other reason) -- if they're online, the cache will get refreshed every 10 minutes like normal. [Drewster727] - -- Fix the cacher by adding locking + extra logging in the plex checker + use a const key for scheduler caching time. [Drewster727] - -- Small changes. [tidusjar] - -- Switched out the schedulers, this seems to be a better implimentation to the previous and is easier to add new "jobs" in. [tidusjar] - -- Fixed #168. [tidusjar] - -- Fixed #162. [tidusjar] - -- Fix saving the log level. [Drewster727] - -- Set the max json length (fixes large json response errors) [Drewster727] - - -## v1.6.1 (2016-04-16) - -### **New Features** - -- Update README.md. [Jamie] - -- Added a url base. [tidusjar] - -- Change default logging. [tidusjar] - -- Added logging around SickRage. [tidusjar] - -### **Fixes** - -- Bump up the version number ready for the release. [tidusjar] - -- BaseUrl is finally finished! #72. [tidusjar] - -- #72 Login page done. [tidusjar] - -- More changes for the urlbase #72. [tidusjar] - -- Done the auth, cp, logs and sidebar for #72. [tidusjar] - -- Add an extra check when determining if a tv show is already available (also check if it starts with the show name returned from the tv db) [Drewster727] - -- Cache plex library data regardless of whether we have requests in the database or not. [Drewster727] - -- By default don't use a url base. [tidusjar] - -- Return empty array when obtaining queued IDs in sickrage cacher. [Drewster727] - -- Fixed a small bug in the SR cacher. [tidusjar] - -- Fixed when we do not have a base. [tidusjar] - -- More changes for #72. [tidusjar] - -- Fixed exception and all areas will now use the base url #72. [tidusjar] - -- Removed the test code from #72. [tidusjar] - -- Commented out the unit tests as they need to be reworked now. [tidusjar] - -- Finally fixed #72. [tidusjar] - -- Remove test code from plex api GetLibrary method. [Drewster727] - -- Finished up the caching TODO's. [tidusjar] - -- Kick off the schedulers once the web app has started (fixes api errors on start) [Drewster727] - -- Converted the UI back down to .NET 4.5.2. [tidusjar] - -- Fixed #154. [tidusjar] - -- Revert everything (except PlexRequests.UI) back to .NET 4.5.2 -- fixes incompatibilities with the latest version of mono (4.2.3.4) -- fixes notifications not working #152 #147 #141. [Drewster727] - -- #150 start caching plex media as well. refactored the availability checker. NEEDS TESTING. also, we need to make the Requests hit the plex api directly rather than hitting the cache as it does now. [Drewster727] - -- #150 split out the cache subscriptions to make sure they subscribe properly. [Drewster727] - -- #150 sonarr/sickrage cache checking. sickrage has a couple small items left. [Drewster727] - -- Fixed args. [tidusjar] - -- Fixed. [tidusjar] - -- Made the base better. [tidusjar] - -- Remove couchpotato api test code. [Drewster727] - -- Start the initial couchpotato cache call on a separate thread to keep the startup process quick. [Drewster727] - -- Add csproj with file changes from previous commit. [Drewster727] - -- Cache the couchpotato wanted list, update it on an interval, and use it to determine if a movie has been queued already. [Drewster727] - -- I think i've fixed an issue where SickRage reports Show not found. [tidusjar] - -- Set the default log level to info. #141. [tidusjar] - -- #125 refactor async task logic to work with mono. [Drewster727] - -- Fix search spinner sticking around after clearing search text + make the "Requested" and "Available" indicators in the search page different colors. [Drewster727] - -- #125 start indicating in the results if an item is already requested or available. [Drewster727] - -- #145 firefox css dsplay issue. [Drewster727] - -- Fixes for sonarr, we now display the error messages back to the user. [tidusjar] - -- Fixed #144. [tidusjar] - - -## v1.6.0 (2016-04-06) - -### **New Features** - -- Changed the build number. [tidusjar] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Update README.md. [Drew] - -- Changed the title to a contains but the artist still must match, [tidusjar] - -- Added unit tests to cover the new changes to the availability checker. [tidusjar] - -- Added the music check in the Plex Checker. [tidusjar] - -- Changed around the startup so we cache the profiles after the DB has been created. [tidusjar] - -- Updated where we update the request blobs schema change. [tidusjar] - -- Update SearchModule.cs. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Change the new columns type. [tidusjar] - -- Added a DBSchema so we have an easier way to update the DB. [tidusjar] - -- Added an issue template. [tidusjar] - -- Update README.md. [Jamie] - -- Added back the username into the Session when the admin logs in. This means they do not have to log in twice. [tidusjar] - -- Added happy path tests for the Checker. [tidusjar] - -- Added music to the search and requests page. [tidusjar] - -- Added a scroll to the top thingy and a bit more work on headphones. [tidusjar] - -- Added some tests and fixed the issue where the DB would get created in the wrong place depending on how you launched the application. [tidusjar] - -- Added the settings page for #32. [tidusjar] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update README.md. [Drewster727] - -- Update appveyor.yml. [Jamie] - -### **Fixes** - -- Some final tweaks for #32. [tidusjar] - -- Fixed a bug where if we are the admin we didn't add the request to the db. [tidusjar] - -- Fixed an issue where we would add the Sickrage series but it would fail on adding the seasons. [tidusjar] - -- Properly account for future/past dates when humanizing with moment. [Drewster727] - -- Properly display release date on requests page. [Drewster727] - -- Add missing reference for release mode. [Drewster727] - -- #139 remove dependency and usage of humanize() - should help with cross-platform issues. start using moment.js. [Drewster727] - -- Fix selectors for music list on request page to get sorting working. [Drewster727] - -- Fixed the error #32. [tidusjar] - -- Fixed the logs page. [tidusjar] - -- Another attempt at filtering #32. [tidusjar] - -- A bit more error handling #32. [tidusjar] - -- Improved the availabilty check to include music results #32. [tidusjar] - -- Small changes for #32. [tidusjar] - -- A bit more logging for #32. [tidusjar] - -- More headphones #32 I am starting to hate headphones... Sometimes the artists and albums just randomly fail. [tidusjar] - -- #134 temporary workaround for this. [Drewster727] - -- Task.run for startup caching + fix admin module unit test failures. [Drewster727] - -- Cache injection, error handling and logging on startup, etc. [Drewster727] - -- Tweaks for #32. [tidusjar] - -- #132 auto-approve for admins. [Drewster727] - -- Finished the bulk work for Headphones. Needs testing #32. [tidusjar] - -- Made the album search 10x faster. We are now loading the images in a seperate call. #32. [tidusjar] - -- Add a reference to API Interfaces to fix the build. [tidusjar] - -- #114 start caching quality profiles. Set the cache on startup and when obtaining quality profiles in settings. [Drewster727] - -- Work for #32. [tidusjar] - -- #114 first pass at choosing quality profile when approving + focus search input by default and when switching tabs. [Drewster727] - -- #131 fix for default selected tab. [Drewster727] - -- Remove references to obsolete RequestedBy property + start setting the db schema to the app version, and check that in the future for migrations. [Drewster727] - -- Fixed async issue. [Shannon Barrett] - -- Updating SickRage api to verify Season List is up to date. [Shannon Barrett] - -- Work on showing the requests for #32. [tidusjar] - -- Got the search finished up for #32. [tidusjar] - -- Remove test/temp code in UserLoginModule. [Drewster727] - -- A bit more work on #32 started working on requesting it. The DB is a bit of an issue... [tidusjar] - -- Most of the UI work done for #32. [tidusjar] - -- Basic search working for #32. [tidusjar] - -- Mono datetime offset workaround. [Drewster727] - -- #122 store utc time in the databse + obtain timezone offset of the client upon login + offset times returned to client based on session offset. [Drewster727] - -- Method reference bug fix. [Drewster727] - -- Fix search focus z-index issue (hid suggestions options) [Drewster727] - -- Minor search UI adjustments. [Drewster727] - -- #55 first attempt at "suggestions" starting with "Comming Soon" and "In Theaters" [Drewster727] - -- #106 rename sorting options and polish the dropdown UI a bit. [Drewster727] - -- Started adding the api part for headphones #32. [tidusjar] - -- Upped the time of #123. [tidusjar] - -- First attempt at #123. [tidusjar] - -- We now do not show the text Requested By to the user, we also show a 'success' message instead of a warning when something has already been requested. [tidusjar] - -- Show a "no requests yet" message on the requests page (for each cateogory) [Drewster727] - -- Ignore items that are already available when approving in bulk, and simplify the checking + compile css. [Drewster727] - -- Add a better way to merge RequestedBy and RequestedUsers to avoid code duplication and simplify checks. [Drewster727] - -- Don't query the session as much in the modules, rely on a variable from the base class and store the username as needed. [Drewster727] - -- Show the requested by user from legacy request models. [Drewster727] - -- Only show requested by users to admins + start maintaining a list of users with each request. [Drewster727] - -- #96 fix up notification test feature. [Drewster727] - -- Fix the request page sort/approve button alignment. [Drewster727] - -- When pulling requests, set each to approved that is already available (so the UI avoids showing the approve option for already available content) [Drewster727] - -- Mono doesn't seem to have Tls1.2. Let's try TLS 1 #119. [tidusjar] - -- Specify a protocol type of TLS12. Looks like CP doesn't seem to like SSL3 (it is quite old now so understandable) #119. [tidusjar] - -- Made #85 better. [tidusjar] - -- Fixed the tests. [tidusjar] - -- Made the feedback from Sonarr better when Sonarr already has the series #85. [tidusjar] - -- An attempt to fix #108. [tidusjar] - -- Add some "no results" feedback to the searching + minor UI improvements. [Drewster727] - -- Fix notification tests. [Drewster727] - -- UI - increase icon size of nav menu (they were too small before) [Drewster727] - -- #96 Finished adding test functionality to notifications. [Drewster727] - -- #96 add the necessary back-end code to produce a test message for all notification types (still have to add the test buttons for pushbullet/pushover) [Drewster727] - -- #96 modify notifications interface/service to accept a non-type specific settings object. [Drewster727] - -- #96 Email notification test button (others to come) [Drewster727] - -- Minor UI adjustments. [Drewster727] - -- #84 provide an option in settings to resttrict users from viewing requests other than their own. [Drewster727] - -- #54 comma separated list of users who don't require approval + fix a couple request messages (include show title) [Drewster727] - -- Clean up the sorting option names. add a way to see which filter/sort is currently applied. [Drewster727] - -- Fix up the animations. seems to be related to the data-bound attribute causing the animtions not to fire on each .mix object. [Drewster727] - -- Move approve buttons to the tab content. [Drewster727] - -- Allow approving all requests by category. [Drewster727] - -- Fix up sorting on the request page. [Drewster727] - -- Add ubuntu/debian instructions. [Drewster727] - -- #86 - display movie/show title + year in request notifications. [Drewster727] - -- Show the movie/show title when requesting. [Drewster727] - - -## v1.5.2 (2016-03-26) - -### **Fixes** - -- Stoped users from spamming the request button. [tidusjar] - -- Fixed the logger no longer writing to the file. [tidusjar] - -- Fixed #97. [tidusjar] - - -## v1.5.1 (2016-03-26) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Added logs to the sidebar. I'm an idiot. [tidusjar] - -### **Fixes** - -- Approve tv shows or movies. [Drewster727] - -- Fixed a bug where if you had auto approve it wouldn't notify you. [tidusjar] - - -## v1.5.0 (2016-03-25) - -### **New Features** - -- Updated version number for release. [tidusjar] - -- Updated the logic for handling specific seasons in Sonarr and Sickrage. [Shannon Barrett] - -- Updated the readme and added some icons to the navbar. [tidusjar] - -- Added the ability to sepcify a username in the email notification settings for external MTA's. We have had to add a new option called Email Sender because of this. #78. [tidusjar] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Added a notification model to the notifiers. Added the backend work for sending a notification for an issue report #75. [tidusjar] - -- Added a subdir to CP, SickRage, Sonarr and Plex #43. [tidusjar] - -### **Fixes** - -- And again. [tidusjar] - -- Made the check actually work. [tidusjar] - -- Finished up #68 and #62. [tidusjar] - -- Finished styling on the logger for now. #59. [tidusjar] - -- Fixed #69. [tidusjar] - -- Working on getting the Sonarr component to work correctly. [Shannon Barrett] - -- Fixes issue #62. [Shannon Barrett] - -- Refactored the Notification service to how it should have really been done in the first place. [tidusjar] - -- Fixed the build. [tidusjar] - -- Finished #49. [tidusjar] - -- Finished #57. [tidusjar] - -- Small changes around the filtering. [tidusjar] - -- Finished adding pushover support. #44. [tidusjar] - -- Resolved #75. [tidusjar] - -- Include DB changes. [tidusjar] - -- Done most on #59. [tidusjar] - -- Lowercase logs folder, because you know, linux. #59. [tidusjar] - -- Adding the imdb when requesting. [tidusjar] - -- Fixed an issue where the table didn't match the model. [tidusjar] - -- Improved the status page with the suggestion from #29. [tidusjar] - -- Hooked up most of #49 Just the validation messages need to be done. [tidusjar] - -- Fixed #74 and #64. [tidusjar] - -- Resolved #70. [tidusjar] - -- Finished #71. [tidusjar] - -- Got the filter working on both movie and tv #57. [tidusjar] - -- Started #57, currently there is a bug where the TV list won't filter. [tidusjar] - - -## v1.4.1 (2016-03-20) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Update AvailabilityUpdateService.cs. [Jamie] - - -## v1.4.0 (2016-03-19) - -### **New Features** - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Update README.md. [Jamie] - -- Updated the build version ready for the next release. [tidusjar] - -- Added the api and settings page for Sickrage. Just need to do the tester and hook it up #40. [tidusjar] - -- Added the option to set a CP quality #38. [tidusjar] - -- Added the code to lookup the old requests and refresh them with new information from TVMaze. [tidusjar] - -- Update StatusCheckerTests.cs. [Jamie] - -- Update README.md. [Jamie] - -- Added TVMaze to the search. #21. [tidusjar] - -- Added migration code and cleaned up the DB. [tidusjar] - -- Updated the way we add requests. [tidusjar] - -- Updated the Dapper.Contrib package, it had a bug where it wasn't returning the correct Id from inserts. [tidusjar] - -### **Fixes** - -- This fixes #36. [tidusjar] - -- Should fix issue #36. [Shannon Barrett] - -- When we do a batch update we need to reset the cache. [tidusjar] - -- Fixed an issue where the default quality on Sickrage wouldn't work. [tidusjar] - -- Wow, that was a lot of work. - So, I have now finished #40. - Fixed a bug where we was not choosing the correct tv series (Because of TVMaze) - Fixed a bug when checking for plex titles - Fixed a bug where the wrong issue would clean on the UI (DB was correct) - Refactored how we send tv shows - And too many small changes to count. [tidusjar] - -- Fixed the new dependancy with the admin class tests. [tidusjar] - -- Back to what it was :( [tidusjar] - -- Another test for #37. [tidusjar] - -- This should fix #37. [Jamie Rees] - -- Catch the missing table exception when they have a new DB. [Jamie Rees] - -- Exploratory test for #37. [Jamie Rees] - -- Fixed #33 we now have SSL options for Sonarr and CP. [Jamie Rees] - -- Removed all the html from the new TVMaze api (for overview). Added tests to cover the html removal. updated Readme to remove TheTVDB. [Jamie Rees] - -- Fixed tests. [Jamie Rees] - -- Almost fully integrated TVMaze #21 and also improved the fix for #31. [Jamie Rees] - -- Should fix #28. [Shannon Barrett] - -- Fixed #16 and #30. [tidusjar] - -- Modified the adding of request to update the model with the added ID. [tidusjar] - -- Switched over to the new service. [tidusjar] - -- Fixed #25. [Jamie Rees] - - -## v1.3.0 (2016-03-17) - -### **New Features** - -- Added pushbullet to the sidebar. [Jamie Rees] - -- Updated build version for the next release. [Jamie Rees] - -- Updated readme link. [tidusjar] - -- Added ignore to static tests. [tidusjar] - -- Added Pushbullet notifications #8. [tidusjar] - -- Added first implimentation of the Notification Service #8 Added tests to cover the notification service. [tidusjar] - -- Added validation to the Email settings, also increased the availability checker from 2 minutes to 5. [tidusjar] - -### **Fixes** - -- Fixed #22. [Jamie Rees] - -- Started on #16, nothing is hooked up yet. [tidusjar] - -- Fixed tests. [tidusjar] - - -## v1.2.1 (2016-03-16) - -### **New Features** - -- Update Program.cs. [Jamie] - -- Update Program.cs. [Jamie] - -- Added back the reference. [tidusjar] - -### **Fixes** - -- Removed the email notification settings from the settings (for release 1.2.1) [Jamie Rees] - -- Fixed. [Jamie Rees] - -- Resolved #10. [tidusjar] - - -## v1.2.0 (2016-03-15) - -### **New Features** - -- Updated. [Jamie Rees] - -- Updated appveyor. [Jamie Rees] - -- Update appveyor.yml. [Jamie] - -- Added latest version code and view. Need to finish the view #11. [tidusjar] - -- Added test button to Plex. That's fixed #9. [tidusjar] - -- Added test sonarr button #9. [tidusjar] - -- Added more tests. [tidusjar] - -- Added a bunch of logging. [tidusjar] - -- Added the application tester for CP #9. [tidusjar] - -- Added settings page for #8. [tidusjar] - -- Added pace.js. [tidusjar] - -### **Fixes** - -- Finished the notes! Resolved #7. [Jamie Rees] - -- #12. [Jamie Rees] - -- #12. [Jamie Rees] - -- Finished the status page #11 and some more work to #12. [Jamie Rees] - -- Resolved #7. [tidusjar] - -- Small changes. [tidusjar] - -- Yeah... [tidusjar] - -- Fixed #5 and also added some tests to the availability checker. [tidusjar] - -- Started added tests. [Jamie Rees] - -- Fixed an issue where the issues text appears larger. [Jamie Rees] - - -## v1.1 (2016-03-13) - -### **New Features** - -- Update appveyor.yml. [Jamie] - -- Updated readme. [Jamie Rees] - -- Added the support for TV Series integrating with Sonarr. [Jamie Rees] - -- Added the functionality to pass a port through an argument. [tidusjar] - -- Added the code to get the quality profiles from Sonarr Started plugging that into the UI. [Jamie Rees] - -- Added the spinners #3. [tidusjar] - -- Added the functionality for the admin to clear the issues. [tidusjar] - -- Added the issues to the requests page. [tidusjar] - -- Added user logout method and unit tests to cover it. [tidusjar] - -- Added DeniedUsers to the view. [tidusjar] - -- Added the denied user check to the UserLoginModule. added a test case to cover it. [tidusjar] - -- Added a missing reference. [tidusjar] - -- Added first real test. [tidusjar] - -- Update README.md. [Jamie] - -- Added the latest version of nuget. [tidusjar] - -- Added travisyml. [tidusjar] - -- Added logging. [tidusjar] - -- Added missing files. [tidusjar] - -- Update README.md. [Jamie] - -- Added logging (Still WIP) [tidusjar] - -- Added favicon and also structured the HTML correctly. [tidusjar] - -- Updated the packages so everything is now with the correct framework (4.5.2) [tidusjar] - -- Added in deletion of requests. [tidusjar] - -- Added test code. [tidusjar] - -- Added dashboard. [tidusjar] - -- Added couchpotato page. [Jamie Rees] - -- Added readme to the project and updated it. [Jamie Rees] - -- Added helpers. [tidusjar] - -### **Fixes** - -- Bug fix, Couchpotato settings wouldn't show in release due to a Nancy bug. [Jamie Rees] - -- Small changes. [Jamie Rees] - -- First release, build 1.0.0. [Jamie Rees] - -- Removed the request limit since it's not currently being used. [Jamie Rees] - -- REmoved Sickbeared for the first release. [Jamie Rees] - -- Fixed #4 We now can manually set the status of a request. [tidusjar] - -- Made the pass in the port a bit more robust. [tidusjar] - -- Styling, Added the functionality for the Sonarr Profiles on the Admin page #2 resolved. [tidusjar] - -- Fixed a bug in the Login and added a unit test to cover that. Added a button to approve an individual request. Fixed some minor bugs in the request screen. [Jamie Rees] - -- Fixed the 'responsive' issue for the search and requests pages #3. [tidusjar] - -- Styling! #3. [tidusjar] - -- Navbar category now will follow you to various screens #3. [tidusjar] - -- Fixed bugs with the 'other' reporting issue and also the clear issues. [tidusjar] - -- We now are appending the users name to who wrote the comment. Rather than it being unknown. [tidusjar] - -- More work on submitting issues. [tidusjar] - -- More test changes. [tidusjar] - -- More tests to cover the login. [tidusjar] - -- Refactoring. [tidusjar] - -- Implimented the password part and authentication with Plex. [tidusjar] - -- Initial Use authentication is working. Need to do the password bit. [tidusjar] - -- Some error handling and ensure we are an admin to delete requests. [tidusjar] - -- Fixed the issue where the Release build would not show the admin screens! [tidusjar] - -- Fixes. [tidusjar] - -- Removed the DI part of the service. TinyIOC doesn't want to work with FluentScheduler. [tidusjar] - -- First pass at the plex update service. [tidusjar] - -- Small changes. [Jamie Rees] - -- Started to impliment the Plex checker. This will check plex every x minutes to see if there is any new content and then update the avalibility of the requests. [Jamie Rees] - -- Mre work. [Jamie Rees] - -- Few small changes, added plex settings. [Jamie Rees] - -- Making the configuration actually do something. Setting a default configuration if there is no DB. [Jamie Rees] - -- Remove post build. [Jamie Rees] - -- Small changes. [Jamie Rees] - -- MOre work. [Jamie Rees] - -- Fixed the issue when sending movies to CouchPotato. [Jamie Rees] - -- Add appveyor. [tidusjar] - -- Build it on 4.5. [tidusjar] - -- Upgraded .net to 4.6. [tidusjar] - -- Typo2. [tidusjar] - -- Typo. [tidusjar] - -- Another update. [tidusjar] - -- Fixed. [tidusjar] - -- More logging to figure out why the we cannot access the admin module in a release build. [tidusjar] - -- Firstpass integrating with CouchPotato. [tidusjar] - -- Some styling. [tidusjar] - -- Fixed the plex friends. Added some unit tests, moved the plex auth into it's own page. [tidusjar] - -- Fully switched the TV shows over to use the other provider. [Jamie Rees] - -- Renamed folders. [tidusjar] - -- Assembly updates. [tidusjar] - -- Moved the rest of the projects. [tidusjar] - -- Moved UI. [tidusjar] - -- Mass rename. [tidusjar] - -- Quick changes. [tidusjar] - -- Started switching the TV over to the new provider (TheTVDB). Currently TV search is partially broken. It will search but we are not mapping all of the details. [tidusjar] - -- Implimented the new TV show Provider (needed for Sonarr TheTvDB) [tidusjar] - -- Started the user auth. [tidusjar] - -- Some work on the requests page. [tidusjar] - -- Made the 'requested' better and made the remove look nicer. [tidusjar] - -- Cleaned up the program a tiny bit. [tidusjar] - -- Removed additional namespace. [tidusjar] - -- Fixed some db issues and added a preview. [Jamie Rees] - -- More work on the settings. [Jamie Rees] - -- Upgraded Json.Net and Nancy packages. [Jamie Rees] - -- Plex friends api. [Jamie Rees] - -- Enabled trace logs. [tidusjar] - -- Sql syntax issue fixed. [tidusjar] - -- Fixed release build. [tidusjar] - -- Small updates including assembly version. [tidusjar] - -- Work on the requests page mostly done. [tidusjar] - -- Work on the TV request. the `latest` parameter is not being passed into the requestTvshow. [tidusjar] - -- Missing file. [tidusjar] - -- Using the IoC container now. [tidusjar] - -- Some plex work. [Jamie Rees] - -- More work. [Jamie Rees] - -- Removed the setup code out of the startup, since we attemtp to connect to the DB before that. [Jamie Rees] - -- Some more work. Need to stop the form submitting on a request. [tidusjar] - -- Moved everything up a directory. [tidusjar] - -- Lots of work! [tidusjar] - -- Done most of the movie search work. [Jamie Rees] - -- First pass with RequestPlex. [tidusjar] - -- Initial commit. [Jamie] - - From e3adbcb51e5a43e733160a9889e31f3d8af47f44 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Tue, 24 Apr 2018 14:05:18 +0100 Subject: [PATCH 060/495] Fixed the error from upgrading the hangfire package !wip --- src/Ombi/Startup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index be78c5b11..fc80be838 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -134,7 +134,7 @@ namespace Ombi { x.UseSQLiteStorage(sqliteStorage); x.UseActivator(new IoCJobActivator(services.BuildServiceProvider())); - x.UseConsole(); + //x.UseConsole(); }); From 69e324c6701ce373c7562f9b6ef02f16e0f7277d Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Tue, 24 Apr 2018 14:23:07 +0100 Subject: [PATCH 061/495] Added Paging to the Movie Requests Page --- .../app/requests/movierequests.component.html | 4 +++- .../app/requests/movierequests.component.ts | 14 ++++++++------ src/Ombi/ClientApp/app/requests/requests.module.ts | 3 ++- src/Ombi/ClientApp/styles/base.scss | 4 ++++ 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 8eded8dba..19814b330 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -56,7 +56,7 @@
-
+
@@ -212,6 +212,8 @@
+ +
diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index e28b86eaa..bb6e17b7f 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -8,7 +8,7 @@ import { Subject } from "rxjs/Subject"; import { AuthService } from "../auth/auth.service"; import { NotificationService, RadarrService, RequestService } from "../services"; -import { FilterType, IFilter, IIssueCategory, IMovieRequests, IRadarrProfile, IRadarrRootFolder } from "../interfaces"; +import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder } from "../interfaces"; @Component({ selector: "movie-requests", @@ -65,8 +65,8 @@ export class MovieRequestsComponent implements OnInit { } public ngOnInit() { - this.amountToLoad = 100; - this.currentlyLoaded = 100; + this.amountToLoad = 10; + this.currentlyLoaded = 10; this.loadInit(); this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); this.filter = { @@ -74,8 +74,10 @@ export class MovieRequestsComponent implements OnInit { statusFilter: FilterType.None}; } - public loadMore() { - this.loadRequests(this.amountToLoad, this.currentlyLoaded); + public paginate(event: IPagenator) { + const skipAmount = event.first; + + this.loadRequests(this.amountToLoad, skipAmount); } public search(text: any) { @@ -226,7 +228,7 @@ export class MovieRequestsComponent implements OnInit { if(!this.movieRequests) { this.movieRequests = []; } - this.movieRequests.push.apply(this.movieRequests, x); + this.movieRequests = x; this.currentlyLoaded = currentlyLoaded + amountToLoad; }); } diff --git a/src/Ombi/ClientApp/app/requests/requests.module.ts b/src/Ombi/ClientApp/app/requests/requests.module.ts index 7bddee71c..18be5ed25 100644 --- a/src/Ombi/ClientApp/app/requests/requests.module.ts +++ b/src/Ombi/ClientApp/app/requests/requests.module.ts @@ -6,7 +6,7 @@ import { OrderModule } from "ngx-order-pipe"; import { InfiniteScrollModule } from "ngx-infinite-scroll"; -import { ButtonModule, DialogModule } from "primeng/primeng"; +import { ButtonModule, DialogModule, PaginatorModule } from "primeng/primeng"; import { MovieRequestsComponent } from "./movierequests.component"; // Request import { RequestComponent } from "./request.component"; @@ -36,6 +36,7 @@ const routes: Routes = [ SharedModule, SidebarModule, OrderModule, + PaginatorModule, ], declarations: [ RequestComponent, diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 3a5deb2a3..2f9b35982 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -959,3 +959,7 @@ a > h4:hover { width: 94%; } +.ui-state-active { + background-color: $primary-colour-outline $i; + color: black $i; +} \ No newline at end of file From 0b2e488e8f42f90e63065a6e174d48d9d3a3773b Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Tue, 24 Apr 2018 14:44:22 +0100 Subject: [PATCH 062/495] Added paging to the TV Requests page --- .../Engine/Interfaces/IMovieRequestEngine.cs | 1 + .../Engine/Interfaces/IRequestEngine.cs | 1 + src/Ombi.Core/Engine/MovieRequestEngine.cs | 13 +++++++++ src/Ombi.Core/Engine/TvRequestEngine.cs | 17 ++++++++++-- .../app/requests/movierequests.component.html | 2 +- .../app/requests/movierequests.component.ts | 2 ++ .../app/requests/tvrequests.component.html | 1 + .../app/requests/tvrequests.component.ts | 27 +++++++++---------- .../ClientApp/app/services/request.service.ts | 8 ++++++ src/Ombi/Controllers/RequestController.cs | 18 +++++++++++++ 10 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs index bfeb4fbe0..2f765fede 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs @@ -18,5 +18,6 @@ namespace Ombi.Core.Engine.Interfaces Task ApproveMovieById(int requestId); Task DenyMovieById(int modelId); Task> Filter(FilterViewModel vm); + } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs index bfb8be4e8..5dbf6e449 100644 --- a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs @@ -17,5 +17,6 @@ namespace Ombi.Core.Engine.Interfaces Task MarkUnavailable(int modelId); Task MarkAvailable(int modelId); + Task GetTotal(); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index f4b0ee48c..0e47a28f6 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -144,6 +144,19 @@ namespace Ombi.Core.Engine return allRequests; } + public async Task GetTotal() + { + var shouldHide = await HideFromOtherUsers(); + if (shouldHide.Hide) + { + return await MovieRepository.GetWithUser(shouldHide.UserId).CountAsync(); + } + else + { + return await MovieRepository.GetWithUser().CountAsync(); + } + } + /// /// Gets the requests. /// diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 44eec3fd1..c3f1139bf 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -130,7 +130,7 @@ namespace Ombi.Core.Engine var newRequest = tvBuilder.CreateNewRequest(tv); return await AddRequest(newRequest.NewRequest); } - + public async Task> GetRequests(int count, int position) { var shouldHide = await HideFromOtherUsers(); @@ -280,7 +280,7 @@ namespace Ombi.Core.Engine results.Background = PosterPathHelper.FixBackgroundPath(request.Background); results.QualityOverride = request.QualityOverride; results.RootFolder = request.RootFolder; - + await TvRepository.Update(results); return results; } @@ -432,6 +432,19 @@ namespace Ombi.Core.Engine }; } + public async Task GetTotal() + { + var shouldHide = await HideFromOtherUsers(); + if (shouldHide.Hide) + { + return await TvRepository.Get(shouldHide.UserId).CountAsync(); + } + else + { + return await TvRepository.Get().CountAsync(); + } + } + private async Task AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest) { // Add the child diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.html b/src/Ombi/ClientApp/app/requests/movierequests.component.html index 19814b330..2431b5477 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.html +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.html @@ -213,7 +213,7 @@
- + diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index bb6e17b7f..3339b6941 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -39,6 +39,7 @@ export class MovieRequestsComponent implements OnInit { public order: string = "requestedDate"; public reverse = false; + public totalMovies: number = 100; private currentlyLoaded: number; private amountToLoad: number; @@ -269,6 +270,7 @@ export class MovieRequestsComponent implements OnInit { } private loadInit() { + this.requestService.getTotalMovies().subscribe(x => this.totalMovies = x); this.requestService.getMovieRequests(this.amountToLoad, 0) .subscribe(x => { this.movieRequests = x; diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.html b/src/Ombi/ClientApp/app/requests/tvrequests.component.html index 9a3c4d186..c15166e96 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.html @@ -120,6 +120,7 @@ + { - this.tvRequests = x; - this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad; - }); + public paginate(event: IPagenator) { + const skipAmount = event.first; + + this.requestService.getTvRequestsTree(this.amountToLoad, skipAmount) + .subscribe(x => { + this.tvRequests = x; + this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad; + }); } public search(text: any) { @@ -197,6 +195,7 @@ export class TvRequestsComponent implements OnInit { } private loadInit() { + this.requestService.getTotalTv().subscribe(x => this.totalTv = x); this.requestService.getTvRequestsTree(this.amountToLoad, 0) .subscribe(x => { this.tvRequests = x; diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index a2757427d..c06b39434 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -20,6 +20,14 @@ export class RequestService extends ServiceHelpers { return this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}); } + public getTotalMovies(): Observable { + return this.http.get(`${this.url}Movie/total`, {headers: this.headers}); + } + + public getTotalTv(): Observable { + return this.http.get(`${this.url}tv/total`, {headers: this.headers}); + } + public requestTv(tv: ITvRequestViewModel): Observable { return this.http.post(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers}); } diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index 59bd75606..5b83a7981 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -37,6 +37,15 @@ namespace Ombi.Controllers return await MovieRequestEngine.GetRequests(count, position); } + /// + /// Gets the total amount of movie requests. + /// + [HttpGet("movie/total")] + public async Task GetTotalMovies() + { + return await MovieRequestEngine.GetTotal(); + } + /// /// Gets all movie requests. /// @@ -146,6 +155,15 @@ namespace Ombi.Controllers return await TvRequestEngine.GetRequestsTreeNode(count, position); } + /// + /// Gets the total amount of TV requests. + /// + [HttpGet("tv/total")] + public async Task GetTotalTV() + { + return await TvRequestEngine.GetTotal(); + } + /// /// Gets the tv requests. /// From d80c50a40a2333c19cfd1b9571624f24b4ab60c2 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Tue, 24 Apr 2018 14:50:44 +0100 Subject: [PATCH 063/495] !wip changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d85aca7..e94945927 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ### **New Features** +- Added paging to the TV Requests page. [Jamie Rees] + +- Added Paging to the Movie Requests Page. [Jamie Rees] + - Updated Mailkit dependancy. [Jamie Rees] - Update Hangfire, Newtonsoft and Swagger. [Jamie Rees] From 73340d4fb65a549617a9eb6c3249a41f84e059f5 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 24 Apr 2018 21:13:52 +0100 Subject: [PATCH 064/495] moved the Plex OAuth setting to the Authentication Settings !wip --- .../Settings/Models/AuthenticationSettings.cs | 1 + .../Settings/Models/External/PlexSettings.cs | 1 - src/Ombi/ClientApp/app/interfaces/ISettings.ts | 2 +- src/Ombi/ClientApp/app/login/login.component.html | 4 ++-- src/Ombi/ClientApp/app/login/login.component.ts | 1 - src/Ombi/ClientApp/app/services/settings.service.ts | 4 ---- .../authentication/authentication.component.html | 7 +++++++ .../authentication/authentication.component.ts | 1 + .../ClientApp/app/settings/plex/plex.component.html | 6 ------ src/Ombi/Controllers/SettingsController.cs | 10 ---------- 10 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs b/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs index 9ce5c72ac..f6736e7c5 100644 --- a/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/AuthenticationSettings.cs @@ -12,5 +12,6 @@ namespace Ombi.Settings.Settings.Models public bool RequireLowercase { get; set; } public bool RequireNonAlphanumeric { get; set; } public bool RequireUppercase { get; set; } + public bool EnableOAuth { get; set; } // Plex OAuth } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs index a77b54a87..3faba3e42 100644 --- a/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/PlexSettings.cs @@ -6,7 +6,6 @@ namespace Ombi.Core.Settings.Models.External public sealed class PlexSettings : Ombi.Settings.Settings.Models.Settings { public bool Enable { get; set; } - public bool EnableOAuth { get; set; } public List Servers { get; set; } } diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 234e0aa5b..bf429d6d5 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -43,7 +43,6 @@ export interface IEmbyServer extends IExternalSettings { export interface IPlexSettings extends ISettings { enable: boolean; - enableOAuth: boolean; servers: IPlexServer[]; } @@ -146,6 +145,7 @@ export interface IAuthenticationSettings extends ISettings { requiredLowercase: boolean; requireNonAlphanumeric: boolean; requireUppercase: boolean; + enableOAuth: boolean; } export interface IUserManagementSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/login/login.component.html b/src/Ombi/ClientApp/app/login/login.component.html index 40a5ef5a0..d87b7121e 100644 --- a/src/Ombi/ClientApp/app/login/login.component.html +++ b/src/Ombi/ClientApp/app/login/login.component.html @@ -17,7 +17,7 @@ include the remember me checkbox

-
+
@@ -41,7 +41,7 @@ include the remember me checkbox
-
+
+
+
+ + +
+
+ - +
@@ -144,23 +143,24 @@
- +
-
-
-

{@INTRO}

+
+
+

Here is a list of Movies and TV Shows that have recently been added!

- {@RECENTLYADDED} -
+ {@RECENTLYADDED}
From 552cd5e16bf3b9e6c5f7f94ae53463e94720a8ca Mon Sep 17 00:00:00 2001 From: Anojh Date: Tue, 24 Apr 2018 18:54:17 -0700 Subject: [PATCH 066/495] Fixing some format issues --- .../Templates/NewsletterTemplate.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 6b2a76c9d..79d97e2fe 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -143,14 +143,14 @@ From 86e49115d06e32bc19d8078240c2cc896855e759 Mon Sep 17 00:00:00 2001 From: Anojh Date: Wed, 25 Apr 2018 01:26:34 -0700 Subject: [PATCH 067/495] CSS done for the template --- .../Templates/NewsletterTemplate.html | 205 ++++++++++-------- 1 file changed, 114 insertions(+), 91 deletions(-) diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index 79d97e2fe..67a632ee6 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -4,118 +4,141 @@ Ombi - -
+
diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.scss b/src/Ombi/ClientApp/app/search/seriesinformation.component.scss index 1a1ac35b3..c7dca5e86 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.scss +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.scss @@ -10,4 +10,16 @@ #requestFloatingBtn:hover { background-color: #555; /* Add a dark-grey background on hover */ + } + + #bannerimage { + width: 758px; + height: 140px; + background-color: black; + background-position: center; + padding-bottom:30px; + } + + .content-space { + padding-top: 10px; } \ No newline at end of file From 20100b01469a84184f380f20ef6feb08d9399b8d Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 13 Aug 2018 22:14:46 +0100 Subject: [PATCH 310/495] Fixed #2424 --- src/Ombi/webpack.config.common.ts | 5 +++-- src/Ombi/webpack.config.ts | 1 + src/Ombi/webpack.config.vendor.ts | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Ombi/webpack.config.common.ts b/src/Ombi/webpack.config.common.ts index 2d7d22ecf..54835ae2e 100644 --- a/src/Ombi/webpack.config.common.ts +++ b/src/Ombi/webpack.config.common.ts @@ -1,3 +1,4 @@ +"use strict"; import { AngularCompilerPlugin } from "@ngtools/webpack"; import * as MiniCssExtractPlugin from "mini-css-extract-plugin"; import * as path from "path"; @@ -35,7 +36,7 @@ export const WebpackCommonConfig = (env: any, type: string) => { output: { path: path.resolve(outputDir), filename: "[name].js", - chunkFilename: "[id].chunk.js", + chunkFilename: "[id].[hash].chunk.js", publicPath: "/dist/", }, module: { @@ -46,7 +47,7 @@ export const WebpackCommonConfig = (env: any, type: string) => { { test: /\.scss$/, exclude: /ClientApp/, use: [MiniCssExtractPlugin.loader, cssLoader, "sass-loader"] }, { test: /\.scss$/, include: /ClientApp(\\|\/)app/, use: ["to-string-loader", cssLoader, "sass-loader"] }, { test: /\.scss$/, include: /ClientApp(\\|\/)styles/, use: ["style-loader", cssLoader, "sass-loader"] }, - { test: /\.(png|jpg|jpeg|gif|woff|woff2|eot|ttf|svg)(\?|$)/, use: "url-loader?limit=8192" }, + { test: /\.(png|woff|woff2|eot|ttf|svg|gif)(\?|$)/, use: "url-loader?limit=100000" }, { test: /[\/\\]@angular[\/\\].+\.js$/, parser: { system: true } }, // ignore System.import warnings https://github.com/angular/angular/issues/21560 ], }, diff --git a/src/Ombi/webpack.config.ts b/src/Ombi/webpack.config.ts index 4f8b94594..0ab82c8dc 100644 --- a/src/Ombi/webpack.config.ts +++ b/src/Ombi/webpack.config.ts @@ -1,3 +1,4 @@ +"use strict"; import * as path from "path"; import { Configuration, DllReferencePlugin } from "webpack"; import * as webpackMerge from "webpack-merge"; diff --git a/src/Ombi/webpack.config.vendor.ts b/src/Ombi/webpack.config.vendor.ts index d0a34cd72..e4ad442ab 100644 --- a/src/Ombi/webpack.config.vendor.ts +++ b/src/Ombi/webpack.config.vendor.ts @@ -1,3 +1,4 @@ +"use strict"; import * as path from "path"; import * as webpack from "webpack"; import * as webpackMerge from "webpack-merge"; From b60e802ba7087b2677493551870eb9bcc6259123 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 13 Aug 2018 22:23:04 +0100 Subject: [PATCH 311/495] Fixed #2427 --- src/Ombi.Api.Plex/PlexApi.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index 4276f6203..f9de4f639 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -41,7 +41,18 @@ namespace Ombi.Api.Plex } else { - _app = settings.ApplicationName; + // Check for non-ascii characters (New .Net Core HTTPLib does not allow this) + var chars = settings.ApplicationName.ToCharArray(); + var hasNonAscii = false; + foreach (var c in chars) + { + if (c > 128) + { + hasNonAscii = true; + } + } + + _app = hasNonAscii ? "Ombi" : settings.ApplicationName; } return _app; From e4f90e6c178ed022ffe29611622405f73f0ce02b Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 13 Aug 2018 23:10:07 +0100 Subject: [PATCH 312/495] Fixed the 'loop' in the cacher #2429 --- src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs b/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs index be70d0029..fc46e88b7 100644 --- a/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs +++ b/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs @@ -8,7 +8,7 @@ namespace Ombi.Schedule.Jobs.Plex.Models public IEnumerable Content { get; set; } public IEnumerable Episodes { get; set; } - public bool HasProcessedContent => Content.Any(); - public bool HasProcessedEpisodes => Episodes.Any(); + public bool HasProcessedContent => Content?.Any() ?? false; + public bool HasProcessedEpisodes => Episodes?.Any() ?? false; } } \ No newline at end of file From 51f5bbc6a83909cd515a001cc8e2b150d996e1c3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 13 Aug 2018 23:10:11 +0100 Subject: [PATCH 313/495] Fixed the issue where we wouldn't correctly mark some shows as available when there was no provider id #2429 --- .../Jobs/Plex/PlexContentSync.cs | 54 ++++++++++++------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 796cc89a0..c39b80c1f 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -381,6 +381,19 @@ namespace Ombi.Schedule.Jobs.Plex if (existingContent != null) { + // Let's make sure that we have some sort of ID e.g. Imdbid for this, + // Looks like it's possible to not have an Id for a show + // I suspect we cached that show just as it was added to Plex. + + if (!existingContent.HasImdb && !existingContent.HasTheMovieDb && !existingContent.HasTvDb) + { + var showMetadata = await PlexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri, + existingContent.Key); + GetProviderIds(showMetadata, existingContent); + + await Repo.Update(existingContent); + } + // Just check the key if (existingKey != null) { @@ -478,10 +491,7 @@ namespace Ombi.Schedule.Jobs.Plex // But it does not contain the `guid` property that we need to pull out thetvdb id... var showMetadata = await PlexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri, show.ratingKey); - var providerIds = - PlexHelper.GetProviderIdFromPlexGuid(showMetadata.MediaContainer.Metadata.FirstOrDefault() - .guid); - + var item = new PlexServerContent { AddedAt = DateTime.Now, @@ -492,20 +502,7 @@ namespace Ombi.Schedule.Jobs.Plex Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, show.ratingKey), Seasons = new List() }; - if (providerIds.Type == ProviderType.ImdbId) - { - item.ImdbId = providerIds.ImdbId; - } - - if (providerIds.Type == ProviderType.TheMovieDbId) - { - item.TheMovieDbId = providerIds.TheMovieDb; - } - - if (providerIds.Type == ProviderType.TvDbId) - { - item.TvDbId = providerIds.TheTvDb; - } + GetProviderIds(showMetadata, item); // Let's just double check to make sure we do not have it now we have some id's var existingImdb = false; @@ -547,6 +544,27 @@ namespace Ombi.Schedule.Jobs.Plex } } + private static void GetProviderIds(PlexMetadata showMetadata, PlexServerContent existingContent) + { + var providerIds = + PlexHelper.GetProviderIdFromPlexGuid(showMetadata.MediaContainer.Metadata.FirstOrDefault() + .guid); + if (providerIds.Type == ProviderType.ImdbId) + { + existingContent.ImdbId = providerIds.ImdbId; + } + + if (providerIds.Type == ProviderType.TheMovieDbId) + { + existingContent.TheMovieDbId = providerIds.TheMovieDb; + } + + if (providerIds.Type == ProviderType.TvDbId) + { + existingContent.TvDbId = providerIds.TheTvDb; + } + } + /// /// Gets all the library sections. /// If the user has specified only certain libraries then we will only look for those From d8972cfa2a46cd6263398f635b031b1294689958 Mon Sep 17 00:00:00 2001 From: Chris Pritchard Date: Wed, 15 Aug 2018 08:39:39 +0100 Subject: [PATCH 314/495] Add cake.config --- cake.config | 2 ++ src/Ombi.sln | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 cake.config diff --git a/cake.config b/cake.config new file mode 100644 index 000000000..e797f1a5b --- /dev/null +++ b/cake.config @@ -0,0 +1,2 @@ +[Settings] +SkipVerification=true \ No newline at end of file diff --git a/src/Ombi.sln b/src/Ombi.sln index ab9f8550c..a626cfe84 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject ..\appveyor.yml = ..\appveyor.yml ..\build.cake = ..\build.cake + ..\cake.config = ..\cake.config ..\CHANGELOG.md = ..\CHANGELOG.md EndProjectSection EndProject @@ -92,7 +93,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Github", "Ombi.Api EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.SickRage", "Ombi.Api.SickRage\Ombi.Api.SickRage.csproj", "{94C9A366-2595-45EA-AABB-8E4A2E90EC5B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Notifications", "Ombi.Api.Notifications\Ombi.Api.Notifications.csproj", "{10D1FE9D-9124-42B7-B1E1-CEB99B832618}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Notifications", "Ombi.Api.Notifications\Ombi.Api.Notifications.csproj", "{10D1FE9D-9124-42B7-B1E1-CEB99B832618}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From c1eb1e2738f56b9269f6bd45799ac59ea96dd1f2 Mon Sep 17 00:00:00 2001 From: Chris Pritchard Date: Wed, 15 Aug 2018 08:49:51 +0100 Subject: [PATCH 315/495] Initial attempt at getting anime seriestype working --- cake.config | 15 ++++++++++++++- src/Ombi.Api.Sonarr/Models/NewSeries.cs | 1 + src/Ombi.Core/Senders/TvSender.cs | 5 +++++ src/Ombi.sln | 1 - 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cake.config b/cake.config index e797f1a5b..8089cd408 100644 --- a/cake.config +++ b/cake.config @@ -1,2 +1,15 @@ +; This is the default configuration file for Cake. +; This file was downloaded from https://github.com/cake-build/resources + +[Nuget] +Source=https://api.nuget.org/v3/index.json +UseInProcessClient=true +LoadDependencies=false + +[Paths] +Tools=./tools +Addins=./tools/Addins +Modules=./tools/Modules + [Settings] -SkipVerification=true \ No newline at end of file +SkipVerification=false diff --git a/src/Ombi.Api.Sonarr/Models/NewSeries.cs b/src/Ombi.Api.Sonarr/Models/NewSeries.cs index 4d2c17308..ef18baddb 100644 --- a/src/Ombi.Api.Sonarr/Models/NewSeries.cs +++ b/src/Ombi.Api.Sonarr/Models/NewSeries.cs @@ -23,6 +23,7 @@ namespace Ombi.Api.Sonarr.Models public string cleanTitle { get; set; } public string imdbId { get; set; } public string titleSlug { get; set; } + public string seriesType { get; set; } public int id { get; set; } public List images { get; set; } diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 2cccd6778..b9135467b 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -120,6 +120,7 @@ namespace Ombi.Core.Senders int qualityToUse; string rootFolderPath; + string seriesType; if (model.SeriesType == SeriesType.Anime) { @@ -128,6 +129,8 @@ namespace Ombi.Core.Senders // TODO make this overrideable via the UI rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder ?? int.Parse(s.RootPathAnime), s); int.TryParse(s.QualityProfileAnime, out qualityToUse); + seriesType = "anime"; + } else { @@ -136,6 +139,7 @@ namespace Ombi.Core.Senders // For some reason, if we haven't got one use the first root folder in Sonarr // TODO make this overrideable via the UI rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder ?? int.Parse(s.RootPath), s); + seriesType = "standard"; } if (model.ParentRequest.QualityOverride.HasValue) @@ -163,6 +167,7 @@ namespace Ombi.Core.Senders rootFolderPath = rootFolderPath, qualityProfileId = qualityToUse, titleSlug = model.ParentRequest.Title, + seriesType = seriesType, addOptions = new AddOptions { ignoreEpisodesWithFiles = true, // There shouldn't be any episodes with files, this is a new season diff --git a/src/Ombi.sln b/src/Ombi.sln index a626cfe84..f29eeb8a6 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -9,7 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject ..\appveyor.yml = ..\appveyor.yml ..\build.cake = ..\build.cake - ..\cake.config = ..\cake.config ..\CHANGELOG.md = ..\CHANGELOG.md EndProjectSection EndProject From b73f4e2058c7320bed0e5a693d707311f29977c8 Mon Sep 17 00:00:00 2001 From: Chris Pritchard Date: Wed, 15 Aug 2018 09:27:04 +0100 Subject: [PATCH 316/495] Delete cake.config --- cake.config | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 cake.config diff --git a/cake.config b/cake.config deleted file mode 100644 index 8089cd408..000000000 --- a/cake.config +++ /dev/null @@ -1,15 +0,0 @@ -; This is the default configuration file for Cake. -; This file was downloaded from https://github.com/cake-build/resources - -[Nuget] -Source=https://api.nuget.org/v3/index.json -UseInProcessClient=true -LoadDependencies=false - -[Paths] -Tools=./tools -Addins=./tools/Addins -Modules=./tools/Modules - -[Settings] -SkipVerification=false From 79fe8bb3318b6f174b65acef4fdcd1108a45e0c8 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 18 Aug 2018 01:15:17 +0100 Subject: [PATCH 317/495] !wip started on the Plex add user UI --- src/Ombi.Api.Plex/IPlexApi.cs | 1 + src/Ombi.Api.Plex/Models/PlexAdd.cs | 84 +++++++++++++++++ src/Ombi.Api.Plex/PlexApi.cs | 28 ++++++ src/Ombi.Api/Api.cs | 13 ++- src/Ombi.Api/IApi.cs | 1 + src/Ombi.Store/Entities/RequestType.cs | 4 +- src/Ombi/ClientApp/app/interfaces/IPlex.ts | 22 +++++ .../app/services/applications/plex.service.ts | 14 ++- .../usermanagement/addplexuser.component.ts | 25 +++++ .../usermanagement.component.html | 10 +- .../usermanagement.component.ts | 71 +++++++++++++- .../usermanagement/usermanagement.module.ts | 8 +- .../Controllers/External/PlexController.cs | 94 +++++++++++++++++++ .../External/PlexServersAddUserModel.cs | 9 ++ src/Ombi/Models/External/PlexUserViewModel.cs | 9 ++ 15 files changed, 379 insertions(+), 14 deletions(-) create mode 100644 src/Ombi.Api.Plex/Models/PlexAdd.cs create mode 100644 src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts create mode 100644 src/Ombi/Models/External/PlexServersAddUserModel.cs create mode 100644 src/Ombi/Models/External/PlexUserViewModel.cs diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index 2dd1a638f..9cf188981 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -24,5 +24,6 @@ namespace Ombi.Api.Plex Task GetRecentlyAdded(string authToken, string uri, string sectionId); Task GetPin(int pinId); Task GetOAuthUrl(int pinId, string code, string applicationUrl, bool wizard); + Task AddUser(string emailAddress, string serverId, string authToken, int[] libs); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/Models/PlexAdd.cs b/src/Ombi.Api.Plex/Models/PlexAdd.cs new file mode 100644 index 000000000..fb0a550d0 --- /dev/null +++ b/src/Ombi.Api.Plex/Models/PlexAdd.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace Ombi.Api.Plex.Models +{ + [XmlRoot(ElementName = "Section")] + public class Section + { + [XmlAttribute(AttributeName = "id")] + public string Id { get; set; } + [XmlAttribute(AttributeName = "key")] + public string Key { get; set; } + [XmlAttribute(AttributeName = "title")] + public string Title { get; set; } + [XmlAttribute(AttributeName = "type")] + public string Type { get; set; } + [XmlAttribute(AttributeName = "shared")] + public string Shared { get; set; } + } + + [XmlRoot(ElementName = "SharedServer")] + public class SharedServer + { + [XmlElement(ElementName = "Section")] + public List
Section { get; set; } + [XmlAttribute(AttributeName = "id")] + public string Id { get; set; } + [XmlAttribute(AttributeName = "username")] + public string Username { get; set; } + [XmlAttribute(AttributeName = "email")] + public string Email { get; set; } + [XmlAttribute(AttributeName = "userID")] + public string UserID { get; set; } + [XmlAttribute(AttributeName = "accessToken")] + public string AccessToken { get; set; } + [XmlAttribute(AttributeName = "name")] + public string Name { get; set; } + [XmlAttribute(AttributeName = "acceptedAt")] + public string AcceptedAt { get; set; } + [XmlAttribute(AttributeName = "invitedAt")] + public string InvitedAt { get; set; } + [XmlAttribute(AttributeName = "allowSync")] + public string AllowSync { get; set; } + [XmlAttribute(AttributeName = "allowCameraUpload")] + public string AllowCameraUpload { get; set; } + [XmlAttribute(AttributeName = "allowChannels")] + public string AllowChannels { get; set; } + [XmlAttribute(AttributeName = "allowTuners")] + public string AllowTuners { get; set; } + [XmlAttribute(AttributeName = "owned")] + public string Owned { get; set; } + } + + [XmlRoot(ElementName = "MediaContainer")] + public class PlexAdd + { + [XmlElement(ElementName = "SharedServer")] + public SharedServer SharedServer { get; set; } + [XmlAttribute(AttributeName = "friendlyName")] + public string FriendlyName { get; set; } + [XmlAttribute(AttributeName = "identifier")] + public string Identifier { get; set; } + [XmlAttribute(AttributeName = "machineIdentifier")] + public string MachineIdentifier { get; set; } + [XmlAttribute(AttributeName = "size")] + public string Size { get; set; } + } + + [XmlRoot(ElementName = "Response")] + public class AddUserError + { + [XmlAttribute(AttributeName = "code")] + public string Code { get; set; } + [XmlAttribute(AttributeName = "status")] + public string Status { get; set; } + } + + public class PlexAddWrapper + { + public PlexAdd Add { get; set; } + public AddUserError Error { get; set; } + public bool HasError => Error != null; + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index f9de4f639..556d23b24 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -243,6 +243,34 @@ namespace Ombi.Api.Plex return request.FullUri; } + public async Task AddUser(string emailAddress, string serverId, string authToken, int[] libs) + { + var request = new Request(string.Empty, $"https://plex.tv/api/servers/{serverId}/shared_servers", HttpMethod.Post, ContentType.Xml); + await AddHeaders(request, authToken); + request.AddJsonBody(new + { + server_id = serverId, + shared_server = new + { + library_section_ids = libs.Length > 0 ? libs : new int[]{}, + invited_email = emailAddress + }, + sharing_settings = new { } + }); + var result = await Api.RequestContent(request); + try + { + var add = Api.DeserializeXml(result); + return new PlexAddWrapper{Add = add}; + } + catch (InvalidOperationException) + { + var error = Api.DeserializeXml(result); + return new PlexAddWrapper{Error = error}; + } + } + + /// /// Adds the required headers and also the authorization header /// diff --git a/src/Ombi.Api/Api.cs b/src/Ombi.Api/Api.cs index b0e7066a8..19dab7530 100644 --- a/src/Ombi.Api/Api.cs +++ b/src/Ombi.Api/Api.cs @@ -80,15 +80,20 @@ namespace Ombi.Api else { // XML - XmlSerializer serializer = new XmlSerializer(typeof(T)); - StringReader reader = new StringReader(receivedString); - var value = (T)serializer.Deserialize(reader); - return value; + return DeserializeXml(receivedString); } } } + public T DeserializeXml(string receivedString) + { + XmlSerializer serializer = new XmlSerializer(typeof(T)); + StringReader reader = new StringReader(receivedString); + var value = (T) serializer.Deserialize(reader); + return value; + } + public async Task RequestContent(Request request) { using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri)) diff --git a/src/Ombi.Api/IApi.cs b/src/Ombi.Api/IApi.cs index 2b7f71bb8..e573d2d07 100644 --- a/src/Ombi.Api/IApi.cs +++ b/src/Ombi.Api/IApi.cs @@ -7,5 +7,6 @@ namespace Ombi.Api Task Request(Request request); Task Request(Request request); Task RequestContent(Request request); + T DeserializeXml(string receivedString); } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/RequestType.cs b/src/Ombi.Store/Entities/RequestType.cs index 42356985f..06cd6c069 100644 --- a/src/Ombi.Store/Entities/RequestType.cs +++ b/src/Ombi.Store/Entities/RequestType.cs @@ -6,7 +6,7 @@ namespace Ombi.Store.Entities { public enum RequestType { - TvShow, - Movie + TvShow = 0, + Movie = 1 } } diff --git a/src/Ombi/ClientApp/app/interfaces/IPlex.ts b/src/Ombi/ClientApp/app/interfaces/IPlex.ts index ccc4e0300..6e9a6b35a 100644 --- a/src/Ombi/ClientApp/app/interfaces/IPlex.ts +++ b/src/Ombi/ClientApp/app/interfaces/IPlex.ts @@ -49,6 +49,28 @@ export interface IPlexServerViewModel { servers: IPlexServerResult; } +export interface IPlexServerAddViewModel { + success: boolean; + servers: IPlexServersAdd[]; +} + +export interface IPlexServersAdd { + serverId: number; + machineId: string; + serverName: string; +} + +export interface IPlexUserViewModel { + username: string; + machineIdentifier: string; + libsSelected: number[]; +} + +export interface IPlexUserAddResponse { + success: boolean; + error: string; +} + export interface IPlexServerResult { friendlyName: string; machineIdentifier: string; diff --git a/src/Ombi/ClientApp/app/services/applications/plex.service.ts b/src/Ombi/ClientApp/app/services/applications/plex.service.ts index 5248e89f3..4a616ba33 100644 --- a/src/Ombi/ClientApp/app/services/applications/plex.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/plex.service.ts @@ -6,7 +6,7 @@ import { Observable } from "rxjs"; import { ServiceHelpers } from "../service.helpers"; -import { IPlexAuthentication, IPlexLibResponse, IPlexOAuthViewModel, IPlexServer, IPlexServerViewModel, IUsersModel } from "../../interfaces"; +import { IPlexAuthentication, IPlexLibResponse, IPlexOAuthViewModel, IPlexServer, IPlexServerAddViewModel, IPlexServerViewModel, IPlexUserAddResponse, IPlexUserViewModel, IUsersModel } from "../../interfaces"; @Injectable() export class PlexService extends ServiceHelpers { @@ -22,10 +22,22 @@ export class PlexService extends ServiceHelpers { return this.http.post(`${this.url}servers`, JSON.stringify({ login, password }), {headers: this.headers}); } + public getServersFromSettings(): Observable { + return this.http.get(`${this.url}servers`, {headers: this.headers}); + } + public getLibraries(plexSettings: IPlexServer): Observable { return this.http.post(`${this.url}Libraries`, JSON.stringify(plexSettings), {headers: this.headers}); } + public getLibrariesFromSettings(machineId: string): Observable { + return this.http.get(`${this.url}Libraries/${machineId}`, {headers: this.headers}); + } + + public addUserToServer(user: IPlexUserViewModel): Observable { + return this.http.post(`${this.url}user`,JSON.stringify(user), {headers: this.headers}); + } + public getFriends(): Observable { return this.http.get(`${this.url}Friends`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts new file mode 100644 index 000000000..da63b67dd --- /dev/null +++ b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts @@ -0,0 +1,25 @@ +import { Component, Input } from "@angular/core"; +import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; + +@Component({ + selector: "ngbd-modal-content", +template: ` + + + +`, +}) +export class AddPlexUserComponent { + + @Input() public name: string; + + constructor(public activeModal: NgbActiveModal) { + console.log("called"); + } + +} diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 37ea2eea5..c38e87a51 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -1,8 +1,11 @@ 

User Management

- - +
+ +
+
+
- +
-
-
-

Here is a list of Movies and TV Shows that have recently been added!

+
+
+

{@INTRO}

@@ -127,4 +130,5 @@ - \ No newline at end of file + + diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts index dc137909e..6f48d4080 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts @@ -1,10 +1,28 @@ import { Component, OnInit } from "@angular/core"; -import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IUser } from "../interfaces"; -import { IdentityService, NotificationService, SettingsService } from "../services"; +import { NgbModal } from "@ng-bootstrap/ng-bootstrap"; +import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IPlexLibraries, IPlexServersAdd, IUser } from "../interfaces"; +import { IdentityService, NotificationService, PlexService, SettingsService } from "../services"; +import { AddPlexUserComponent } from "./addplexuser.component"; @Component({ templateUrl: "./usermanagement.component.html", + styles:[`.modal-backdrop.fade{opacity:0.5} + .fade { + opacity:1 !important; + } + .modal { + display: none; + overflow: hidden; + position: fixed; + top: 100px; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; + }`], }) export class UserManagementComponent implements OnInit { @@ -20,10 +38,20 @@ export class UserManagementComponent implements OnInit { public availableClaims: ICheckbox[]; public bulkMovieLimit?: number; public bulkEpisodeLimit?: number; + public plexEnabled: boolean; + public plexServers: IPlexServersAdd[]; + public plexLibs: IPlexLibraries; + + public plexUsername: string; + public libsSelected: number[]; + public machineId: string; constructor(private identityService: IdentityService, private settingsService: SettingsService, - private notificationService: NotificationService) { } + private notificationService: NotificationService, + private plexSettings: SettingsService, + private plexService: PlexService, + private modalService: NgbModal) { } public ngOnInit() { this.users = []; @@ -31,11 +59,18 @@ export class UserManagementComponent implements OnInit { this.users = x; }); + this.plexSettings.getPlex().subscribe(x => this.plexEnabled = x.enable); + this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x); this.settingsService.getEmailNotificationSettings().subscribe(x => this.emailSettings = x); } + public open() { + const modalRef = this.modalService.open(AddPlexUserComponent, {container:"ombi"}); + modalRef.componentInstance.name = "World"; + } + public welcomeEmail(user: IUser) { if (!user.emailAddress) { this.notificationService.error("The user needs an email address."); @@ -118,4 +153,34 @@ export class UserManagementComponent implements OnInit { this.order = value; } + + public getServers() { + if(!this.plexEnabled) { + return this.notificationService.error("Plex is not enabled"); + } + + this.plexService.getServersFromSettings().subscribe(x => { + if(x.success) { + this.plexServers = x.servers; + } + }); + } + + public getPlexLibs(machineId: string) { + this.plexService.getLibrariesFromSettings(machineId).subscribe(x => { + if(x.successful) { + this.plexLibs = x.data; + } + }); + } + + public addUser() { + this.plexService.addUserToServer({ username: this.plexUsername, machineIdentifier: this.machineId, libsSelected: this.libsSelected}).subscribe(x => { + if(x.success) { + this.notificationService.success("User added to Plex"); + } else { + this.notificationService.error(x.error); + } + }); + } } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index 40dba285d..cf25446f5 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -12,11 +12,12 @@ import { UserManagementEditComponent } from "./usermanagement-edit.component"; import { UserManagementComponent } from "./usermanagement.component"; import { PipeModule } from "../pipes/pipe.module"; -import { IdentityService } from "../services"; +import { IdentityService, PlexService } from "../services"; import { AuthGuard } from "../auth/auth.guard"; import { OrderModule } from "ngx-order-pipe"; +import { AddPlexUserComponent } from "./addplexuser.component"; const routes: Routes = [ { path: "", component: UserManagementComponent, canActivate: [AuthGuard] }, @@ -44,6 +45,10 @@ const routes: Routes = [ UserManagementAddComponent, UserManagementEditComponent, UpdateDetailsComponent, + AddPlexUserComponent, + ], + entryComponents:[ + AddPlexUserComponent, ], exports: [ RouterModule, @@ -51,6 +56,7 @@ const routes: Routes = [ providers: [ IdentityService, ConfirmationService, + PlexService, ], }) diff --git a/src/Ombi/Controllers/External/PlexController.cs b/src/Ombi/Controllers/External/PlexController.cs index 6ea37e9cc..8a627b710 100644 --- a/src/Ombi/Controllers/External/PlexController.cs +++ b/src/Ombi/Controllers/External/PlexController.cs @@ -127,6 +127,100 @@ namespace Ombi.Controllers.External } } + + [HttpGet("Libraries/{machineId}")] + [PowerUser] + public async Task GetPlexLibraries(string machineId) + { + try + { + var s = await PlexSettings.GetSettingsAsync(); + var settings = s.Servers.FirstOrDefault(x => x.MachineIdentifier == machineId); + var libs = await PlexApi.GetLibrarySections(settings.PlexAuthToken, settings.FullUri); + + return new PlexLibrariesResponse + { + Successful = true, + Data = libs + }; + } + catch (Exception e) + { + _log.LogWarning(e, "Error thrown when attempting to obtain the plex libs"); + + var message = e.InnerException != null ? $"{e.Message} - {e.InnerException.Message}" : e.Message; + return new PlexLibrariesResponse + { + Successful = false, + Message = message + }; + } + } + + [HttpPost("user")] + [PowerUser] + public async Task AddUser([FromBody] PlexUserViewModel user) + { + var s = await PlexSettings.GetSettingsAsync(); + var server = s.Servers.FirstOrDefault(x => x.MachineIdentifier == user.MachineIdentifier); + var result = await PlexApi.AddUser(user.Username, user.MachineIdentifier, server.PlexAuthToken, + user.LibsSelected); + if (result.HasError) + { + return Json(new + { + Success = false, + Error = result.Error.Status + }); + } + else + { + return Json(new + { + Success = true + }); + } + } + + /// + /// Gets the plex servers. + /// + /// The u. + /// + [HttpGet("servers")] + [PowerUser] + public async Task GetServers() + { + try + { + var s = await PlexSettings.GetSettingsAsync(); + var servers = new List(); + foreach (var plexServer in s.Servers) + { + servers.Add(new PlexServersAddUserModel + { + ServerId = plexServer.Id, + MachineId = plexServer.MachineIdentifier, + ServerName = plexServer.Name + }); + } + + return Json(new + { + Success = true, + Servers = servers + }); + } + catch (Exception e) + { + _log.LogWarning(e, "Error thrown when attempting to obtain the GetServers for Add User VM"); + return Json(new PlexServersViewModel + { + Success = false, + }); + } + } + /// /// Gets the plex servers. /// diff --git a/src/Ombi/Models/External/PlexServersAddUserModel.cs b/src/Ombi/Models/External/PlexServersAddUserModel.cs new file mode 100644 index 000000000..8d272b37e --- /dev/null +++ b/src/Ombi/Models/External/PlexServersAddUserModel.cs @@ -0,0 +1,9 @@ +namespace Ombi.Models.External +{ + public class PlexServersAddUserModel + { + public string ServerName { get; set; } + public int ServerId { get; set; } + public string MachineId { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/Models/External/PlexUserViewModel.cs b/src/Ombi/Models/External/PlexUserViewModel.cs new file mode 100644 index 000000000..7dddf6a9f --- /dev/null +++ b/src/Ombi/Models/External/PlexUserViewModel.cs @@ -0,0 +1,9 @@ +namespace Ombi.Models.External +{ + public class PlexUserViewModel + { + public string Username { get; set; } + public string MachineIdentifier { get; set; } + public int[] LibsSelected { get; set; } + } +} \ No newline at end of file From 61a2a59879ab8e2d104d11dcdb8033113b2d143f Mon Sep 17 00:00:00 2001 From: TidusJar Date: Sat, 18 Aug 2018 19:16:31 +0100 Subject: [PATCH 318/495] Fixed #2440 --- src/Ombi.Api.Radarr/RadarrApi.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Api.Radarr/RadarrApi.cs b/src/Ombi.Api.Radarr/RadarrApi.cs index 1f897b60b..fd4deb140 100644 --- a/src/Ombi.Api.Radarr/RadarrApi.cs +++ b/src/Ombi.Api.Radarr/RadarrApi.cs @@ -79,7 +79,7 @@ namespace Ombi.Api.Radarr tmdbId = tmdbId, qualityProfileId = qualityId, rootFolderPath = rootPath, - titleSlug = title, + titleSlug = title + year, monitored = true, year = year, minimumAvailability = minimumAvailability From 8aba799681b7ada7f78472daca1eb974795ce3f4 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Sat, 18 Aug 2018 21:20:52 +0100 Subject: [PATCH 319/495] !wip almost finished the add plex friend --- .../usermanagement/addplexuser.component.html | 59 +++++++++++ .../usermanagement/addplexuser.component.ts | 97 +++++++++++++++---- .../usermanagement.component.html | 2 +- .../usermanagement.component.ts | 59 +---------- src/Ombi/ClientApp/styles/base.scss | 15 +++ 5 files changed, 156 insertions(+), 76 deletions(-) create mode 100644 src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html diff --git a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html new file mode 100644 index 000000000..d21509043 --- /dev/null +++ b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html @@ -0,0 +1,59 @@ + + + + \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts index da63b67dd..c45dfc0e9 100644 --- a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts @@ -1,25 +1,84 @@ -import { Component, Input } from "@angular/core"; +import { Component, Input, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; -@Component({ - selector: "ngbd-modal-content", -template: ` - - - -`, -}) -export class AddPlexUserComponent { - - @Input() public name: string; +import { NotificationService, PlexService } from "../services"; - constructor(public activeModal: NgbActiveModal) { - console.log("called"); +import { IPlexLibraries, IPlexServersAdd } from "../interfaces"; + +@Component({ + selector: "ngbd-modal-content", + templateUrl: "./addplexuser.component.html", +}) +export class AddPlexUserComponent implements OnInit { + + @Input() public name: string; + + public plexServers: IPlexServersAdd[]; + public plexLibs: IPlexLibraries; + + public libsSelected: number[] = []; + + public form: FormGroup; + + constructor(public activeModal: NgbActiveModal, + private plexService: PlexService, + private notificationService: NotificationService, + private fb: FormBuilder) { } + public ngOnInit(): void { + this.form = this.fb.group({ + selectedServer: [null, Validators.required], + allLibsSelected: [true], + username:[null, Validators.required], + }); + this.getServers(); + } + + public getServers() { + this.plexService.getServersFromSettings().subscribe(x => { + if (x.success) { + this.plexServers = x.servers; + } + }); + } + + public getPlexLibs(machineId: string) { + this.plexService.getLibrariesFromSettings(machineId).subscribe(x => { + if (x.successful) { + this.plexLibs = x.data; + } + }); + } + + public selected() { + this.getPlexLibs(this.form.value.selectedServer); + } + + public checkedLib(checked: boolean, value: number) { + if(checked) { + this.libsSelected.push(value); + } else { + this.libsSelected = this.libsSelected.filter(v => v !== value); + } + } + + public onSubmit(form: FormGroup) { + debugger; + if (form.invalid) { + this.notificationService.error("Please check your entered values"); + return; + } + const libs = form.value.allLibsSelected ? this.plexLibs.mediaContainer.directory.map(x => +x.key) : this.libsSelected; + + this.plexService.addUserToServer({ username: form.value.username, machineIdentifier: form.value.selectedServer, libsSelected: libs }).subscribe(x => { + if (x.success) { + this.notificationService.success("User added to Plex"); + } else { + this.notificationService.error(x.error); + } + }); + + } } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index c38e87a51..6d371847d 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -2,7 +2,7 @@
- +
diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts index 6f48d4080..082a6086c 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.ts @@ -1,28 +1,12 @@ import { Component, OnInit } from "@angular/core"; import { NgbModal } from "@ng-bootstrap/ng-bootstrap"; -import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IPlexLibraries, IPlexServersAdd, IUser } from "../interfaces"; -import { IdentityService, NotificationService, PlexService, SettingsService } from "../services"; +import { ICheckbox, ICustomizationSettings, IEmailNotificationSettings, IUser } from "../interfaces"; +import { IdentityService, NotificationService, SettingsService } from "../services"; import { AddPlexUserComponent } from "./addplexuser.component"; @Component({ templateUrl: "./usermanagement.component.html", - styles:[`.modal-backdrop.fade{opacity:0.5} - .fade { - opacity:1 !important; - } - .modal { - display: none; - overflow: hidden; - position: fixed; - top: 100px; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - -webkit-overflow-scrolling: touch; - outline: 0; - }`], }) export class UserManagementComponent implements OnInit { @@ -39,18 +23,11 @@ export class UserManagementComponent implements OnInit { public bulkMovieLimit?: number; public bulkEpisodeLimit?: number; public plexEnabled: boolean; - public plexServers: IPlexServersAdd[]; - public plexLibs: IPlexLibraries; - - public plexUsername: string; - public libsSelected: number[]; - public machineId: string; constructor(private identityService: IdentityService, private settingsService: SettingsService, private notificationService: NotificationService, private plexSettings: SettingsService, - private plexService: PlexService, private modalService: NgbModal) { } public ngOnInit() { @@ -67,7 +44,7 @@ export class UserManagementComponent implements OnInit { } public open() { - const modalRef = this.modalService.open(AddPlexUserComponent, {container:"ombi"}); + const modalRef = this.modalService.open(AddPlexUserComponent, {container:"ombi", backdropClass:"custom-modal-backdrop", windowClass:"window"}); modalRef.componentInstance.name = "World"; } @@ -153,34 +130,4 @@ export class UserManagementComponent implements OnInit { this.order = value; } - - public getServers() { - if(!this.plexEnabled) { - return this.notificationService.error("Plex is not enabled"); - } - - this.plexService.getServersFromSettings().subscribe(x => { - if(x.success) { - this.plexServers = x.servers; - } - }); - } - - public getPlexLibs(machineId: string) { - this.plexService.getLibrariesFromSettings(machineId).subscribe(x => { - if(x.successful) { - this.plexLibs = x.data; - } - }); - } - - public addUser() { - this.plexService.addUserToServer({ username: this.plexUsername, machineIdentifier: this.machineId, libsSelected: this.libsSelected}).subscribe(x => { - if(x.success) { - this.notificationService.success("User added to Plex"); - } else { - this.notificationService.error(x.error); - } - }); - } } diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index d36986be8..9666e9077 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -966,3 +966,18 @@ a > h4:hover { .subject { display: inline-block; } + +.custom-modal-backdrop { + opacity: 0.5 !important; + filter: alpha(opacity=0.5); +} + +.window { + opacity: 1 !important; + top: 7%; +} + +.modal-header { + background-color: #282828; + padding-top:75px; +} \ No newline at end of file From 505929737c253c1bc5859400a9441d9442f42cfd Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 18 Aug 2018 22:18:41 +0100 Subject: [PATCH 320/495] Added the ability to invite Plex Friends from the user management screen. --- src/Ombi.Api.Plex/IPlexApi.cs | 1 + .../Models/PlexLibrariesForMachineId.cs | 66 +++++++++++++++++++ src/Ombi.Api.Plex/PlexApi.cs | 7 ++ src/Ombi/ClientApp/app/interfaces/IPlex.ts | 13 ++++ .../app/services/applications/plex.service.ts | 6 +- .../usermanagement/addplexuser.component.html | 19 ++++-- .../usermanagement/addplexuser.component.ts | 8 +-- .../usermanagement.component.html | 9 +-- src/Ombi/ClientApp/styles/base.scss | 16 ++++- .../Controllers/External/PlexController.cs | 10 +-- .../Models/External/PlexLibrariesResponse.cs | 8 +++ 11 files changed, 138 insertions(+), 25 deletions(-) create mode 100644 src/Ombi.Api.Plex/Models/PlexLibrariesForMachineId.cs diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index 9cf188981..82db74278 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -11,6 +11,7 @@ namespace Ombi.Api.Plex public interface IPlexApi { Task GetStatus(string authToken, string uri); + Task GetLibrariesForMachineId(string authToken, string machineId); Task SignIn(UserRequest user); Task GetServer(string authToken); Task GetLibrarySections(string authToken, string plexFullHost); diff --git a/src/Ombi.Api.Plex/Models/PlexLibrariesForMachineId.cs b/src/Ombi.Api.Plex/Models/PlexLibrariesForMachineId.cs new file mode 100644 index 000000000..17ac59b81 --- /dev/null +++ b/src/Ombi.Api.Plex/Models/PlexLibrariesForMachineId.cs @@ -0,0 +1,66 @@ +namespace Ombi.Api.Plex.Models +{ + + using System; + using System.Xml.Serialization; + using System.Collections.Generic; + + [XmlRoot(ElementName = "Section")] + public class SectionLite + { + [XmlAttribute(AttributeName = "id")] + public string Id { get; set; } + [XmlAttribute(AttributeName = "key")] + public string Key { get; set; } + [XmlAttribute(AttributeName = "type")] + public string Type { get; set; } + [XmlAttribute(AttributeName = "title")] + public string Title { get; set; } + } + + [XmlRoot(ElementName = "Server")] + public class ServerLib + { + [XmlElement(ElementName = "Section")] + public List Section { get; set; } + [XmlAttribute(AttributeName = "name")] + public string Name { get; set; } + [XmlAttribute(AttributeName = "address")] + public string Address { get; set; } + [XmlAttribute(AttributeName = "port")] + public string Port { get; set; } + [XmlAttribute(AttributeName = "version")] + public string Version { get; set; } + [XmlAttribute(AttributeName = "scheme")] + public string Scheme { get; set; } + [XmlAttribute(AttributeName = "host")] + public string Host { get; set; } + [XmlAttribute(AttributeName = "localAddresses")] + public string LocalAddresses { get; set; } + [XmlAttribute(AttributeName = "machineIdentifier")] + public string MachineIdentifier { get; set; } + [XmlAttribute(AttributeName = "createdAt")] + public string CreatedAt { get; set; } + [XmlAttribute(AttributeName = "updatedAt")] + public string UpdatedAt { get; set; } + [XmlAttribute(AttributeName = "owned")] + public string Owned { get; set; } + [XmlAttribute(AttributeName = "synced")] + public string Synced { get; set; } + } + + [XmlRoot(ElementName = "MediaContainer")] + public class PlexLibrariesForMachineId + { + [XmlElement(ElementName = "Server")] + public ServerLib Server { get; set; } + [XmlAttribute(AttributeName = "friendlyName")] + public string FriendlyName { get; set; } + [XmlAttribute(AttributeName = "identifier")] + public string Identifier { get; set; } + [XmlAttribute(AttributeName = "machineIdentifier")] + public string MachineIdentifier { get; set; } + [XmlAttribute(AttributeName = "size")] + public string Size { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index 556d23b24..bed75b4d8 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -127,6 +127,13 @@ namespace Ombi.Api.Plex return await Api.Request(request); } + public async Task GetLibrariesForMachineId(string authToken, string machineId) + { + var request = new Request("", $"https://plex.tv/api/servers/{machineId}", HttpMethod.Get, ContentType.Xml); + await AddHeaders(request, authToken); + return await Api.Request(request); + } + /// // 192.168.1.69:32400/library/metadata/3662/allLeaves // The metadata ratingkey should be in the Cache diff --git a/src/Ombi/ClientApp/app/interfaces/IPlex.ts b/src/Ombi/ClientApp/app/interfaces/IPlex.ts index 6e9a6b35a..de3fc8cf1 100644 --- a/src/Ombi/ClientApp/app/interfaces/IPlex.ts +++ b/src/Ombi/ClientApp/app/interfaces/IPlex.ts @@ -34,6 +34,19 @@ export interface IPlexLibResponse { data: IPlexLibraries; } +export interface IPlexLibSimpleResponse { + successful: boolean; + message: string; + data: IPlexSection[]; +} + +export interface IPlexSection { + id: string; + key: string; + type: string; + title: string; +} + export interface IMediaContainer { directory: IDirectory[]; } diff --git a/src/Ombi/ClientApp/app/services/applications/plex.service.ts b/src/Ombi/ClientApp/app/services/applications/plex.service.ts index 4a616ba33..9f53d0e34 100644 --- a/src/Ombi/ClientApp/app/services/applications/plex.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/plex.service.ts @@ -6,7 +6,7 @@ import { Observable } from "rxjs"; import { ServiceHelpers } from "../service.helpers"; -import { IPlexAuthentication, IPlexLibResponse, IPlexOAuthViewModel, IPlexServer, IPlexServerAddViewModel, IPlexServerViewModel, IPlexUserAddResponse, IPlexUserViewModel, IUsersModel } from "../../interfaces"; +import { IPlexAuthentication, IPlexLibResponse, IPlexLibSimpleResponse, IPlexOAuthViewModel, IPlexServer, IPlexServerAddViewModel, IPlexServerViewModel, IPlexUserAddResponse, IPlexUserViewModel, IUsersModel } from "../../interfaces"; @Injectable() export class PlexService extends ServiceHelpers { @@ -30,8 +30,8 @@ export class PlexService extends ServiceHelpers { return this.http.post(`${this.url}Libraries`, JSON.stringify(plexSettings), {headers: this.headers}); } - public getLibrariesFromSettings(machineId: string): Observable { - return this.http.get(`${this.url}Libraries/${machineId}`, {headers: this.headers}); + public getLibrariesFromSettings(machineId: string): Observable { + return this.http.get(`${this.url}Libraries/${machineId}`, {headers: this.headers}); } public addUserToServer(user: IPlexUserViewModel): Observable { diff --git a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html index d21509043..5f56ee710 100644 --- a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.html @@ -3,6 +3,9 @@ \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts index c45dfc0e9..1c77a0181 100644 --- a/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/addplexuser.component.ts @@ -4,7 +4,7 @@ import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; import { NotificationService, PlexService } from "../services"; -import { IPlexLibraries, IPlexServersAdd } from "../interfaces"; +import { IPlexSection, IPlexServersAdd } from "../interfaces"; @Component({ selector: "ngbd-modal-content", @@ -15,7 +15,7 @@ export class AddPlexUserComponent implements OnInit { @Input() public name: string; public plexServers: IPlexServersAdd[]; - public plexLibs: IPlexLibraries; + public plexLibs: IPlexSection[]; public libsSelected: number[] = []; @@ -65,12 +65,11 @@ export class AddPlexUserComponent implements OnInit { } public onSubmit(form: FormGroup) { - debugger; if (form.invalid) { this.notificationService.error("Please check your entered values"); return; } - const libs = form.value.allLibsSelected ? this.plexLibs.mediaContainer.directory.map(x => +x.key) : this.libsSelected; + const libs = form.value.allLibsSelected ? [] : this.libsSelected; this.plexService.addUserToServer({ username: form.value.username, machineIdentifier: form.value.selectedServer, libsSelected: libs }).subscribe(x => { if (x.success) { @@ -78,6 +77,7 @@ export class AddPlexUserComponent implements OnInit { } else { this.notificationService.error(x.error); } + this.activeModal.close(); }); } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 6d371847d..519db023f 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -1,12 +1,13 @@ 

User Management

-
- -
-
+ + +
+ +
diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 9666e9077..7bd29aaaa 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -977,7 +977,17 @@ a > h4:hover { top: 7%; } -.modal-header { - background-color: #282828; - padding-top:75px; +.modal.fade .modal-dialog { + -webkit-transform: translate(0, 0%); + -ms-transform: translate(0, 0%); + -o-transform: translate(0, 0%); + transform: translate(0, 0%); + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; +} + +.modal-footer .btn+.btn { + margin-left: 5px; + margin-bottom: 10px; } \ No newline at end of file diff --git a/src/Ombi/Controllers/External/PlexController.cs b/src/Ombi/Controllers/External/PlexController.cs index 8a627b710..d7cefd091 100644 --- a/src/Ombi/Controllers/External/PlexController.cs +++ b/src/Ombi/Controllers/External/PlexController.cs @@ -130,18 +130,18 @@ namespace Ombi.Controllers.External [HttpGet("Libraries/{machineId}")] [PowerUser] - public async Task GetPlexLibraries(string machineId) + public async Task GetPlexLibraries(string machineId) { try { var s = await PlexSettings.GetSettingsAsync(); var settings = s.Servers.FirstOrDefault(x => x.MachineIdentifier == machineId); - var libs = await PlexApi.GetLibrarySections(settings.PlexAuthToken, settings.FullUri); + var libs = await PlexApi.GetLibrariesForMachineId(settings.PlexAuthToken, machineId); - return new PlexLibrariesResponse + return new PlexLibrariesLiteResponse { Successful = true, - Data = libs + Data = libs.Server.Section }; } catch (Exception e) @@ -149,7 +149,7 @@ namespace Ombi.Controllers.External _log.LogWarning(e, "Error thrown when attempting to obtain the plex libs"); var message = e.InnerException != null ? $"{e.Message} - {e.InnerException.Message}" : e.Message; - return new PlexLibrariesResponse + return new PlexLibrariesLiteResponse { Successful = false, Message = message diff --git a/src/Ombi/Models/External/PlexLibrariesResponse.cs b/src/Ombi/Models/External/PlexLibrariesResponse.cs index d1033f12e..e5aaa5a3c 100644 --- a/src/Ombi/Models/External/PlexLibrariesResponse.cs +++ b/src/Ombi/Models/External/PlexLibrariesResponse.cs @@ -25,6 +25,7 @@ // ************************************************************************/ #endregion +using System.Collections.Generic; using Ombi.Api.Plex.Models; namespace Ombi.Models.External @@ -35,4 +36,11 @@ namespace Ombi.Models.External public bool Successful { get; set; } public string Message { get; set; } } + + public class PlexLibrariesLiteResponse + { + public List Data { get; set; } + public bool Successful { get; set; } + public string Message { get; set; } + } } \ No newline at end of file From eecf1de303f0a9e25c718e9971cc5b99688eba9a Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 18 Aug 2018 22:22:26 +0100 Subject: [PATCH 321/495] !wip changelog --- CHANGELOG.md | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb3b8539..c24f499cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,134 @@ # Changelog +## (unreleased) + +### **New Features** + +- Added the ability to invite Plex Friends from the user management screen. [Jamie] + +- Added rich notifications for mobile. [Jamie] + +- Updater fixes. [Jamie] + +- Added updater test mode. [Jamie Rees] + +- Added a new API method to delete issue comments. [TidusJar] + +- Updated @ngu/carousel to beta version to remove rxjs-compat dependency. [Matt Jeanes] + +- Update to Angular 6/Webpack 4. [Matt Jeanes] + +- Update CHANGELOG.md. [Jamie] + +- Updated the way we create the wizard user, errors show now be fed back to the user. [Jamie] + +- Added Brazillian Portuguese as a language and also Polish. [Jamie] + +- Updated swagger. [Jamie] + +- Updated to 2.1.1. [Jamie] + +### **Fixes** + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (French) [Jamie] + +- Fixed #2440. [TidusJar] + +- Delete cake.config. [Chris Pritchard] + +- Initial attempt at getting anime seriestype working. [Chris Pritchard] + +- Add cake.config. [Chris Pritchard] + +- Fixed the issue where we wouldn't correctly mark some shows as available when there was no provider id #2429. [Jamie] + +- Fixed the 'loop' in the cacher #2429. [Jamie] + +- Fixed #2427. [Jamie] + +- Fixed #2424. [Jamie] + +- Fixed #2409. [Jamie] + +- More updater. [Jamie] + +- Humanize the request type enum in notifications e.g. TvShow will now appear as "Tv Show" #2416. [TidusJar] + +- Made the quality override and root folder override load when we load the show (It will now appear) [Jamie] + +- Fixed #2415 where power users could not set the Sonarr Quality Override or Root Folder Override. [Jamie] + +- #2371 Fixed the issue where certain actions would not setup the series correctly in Sonarr. [Jamie] + +- Tightened up the security from an API perspecitve. [TidusJar] + +- Stop the root folder and profile calls from erroring. [TidusJar] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- Fixed all linting. [TidusJar] + +- Comment out envparam stuff. [Matt Jeanes] + +- Fixed prod build issue. [Matt Jeanes] + +- Missed a tiny bit. [Matt Jeanes] + +- Fix test. [Matt Jeanes] + +- Fix test build. [Matt Jeanes] + +- Linting + remove debug. [Matt Jeanes] + +- Switch to Yarn and disable auto publish in release mode. [Matt Jeanes] + +- Fix for #2409. [TidusJar] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Norwegian) [Jamie] + +- New translations en.json (Italian) [Jamie] + +- New translations en.json (German) [Jamie] + +- New translations en.json (French) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Danish) [Jamie] + +- Possible fix for #2298. [D34DC3N73R] + +- Fixed the text for #2370. [Jamie] + +- Fixed where you couldn't bulk edit the limits to 0 #2318. [Jamie] + +- Upgraded to .net 2.1.2 (Includes security fixes) [Jamie] + + ## v3.0.3477 (2018-07-18) ### **New Features** From d98dafb8d29667bd3807dd4f8336426bd27be91d Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 18 Aug 2018 22:33:42 +0100 Subject: [PATCH 322/495] #2408 Added the feature to delete comments on issues --- src/Ombi/ClientApp/app/interfaces/IIssues.ts | 1 + src/Ombi/ClientApp/app/issues/issueDetails.component.html | 8 +++++--- src/Ombi/ClientApp/app/issues/issueDetails.component.ts | 7 +++++++ src/Ombi/ClientApp/app/services/issues.service.ts | 4 ++++ src/Ombi/Controllers/IssuesController.cs | 5 +++-- src/Ombi/Models/IssueCommentChatViewModel.cs | 1 + 6 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Ombi/ClientApp/app/interfaces/IIssues.ts b/src/Ombi/ClientApp/app/interfaces/IIssues.ts index 023ac131b..cd2ad53a6 100644 --- a/src/Ombi/ClientApp/app/interfaces/IIssues.ts +++ b/src/Ombi/ClientApp/app/interfaces/IIssues.ts @@ -46,6 +46,7 @@ export interface IIssueComments { } export interface IIssuesChat { + id: number; comment: string; date: Date; username: string; diff --git a/src/Ombi/ClientApp/app/issues/issueDetails.component.html b/src/Ombi/ClientApp/app/issues/issueDetails.component.html index ece2d9966..33157cd09 100644 --- a/src/Ombi/ClientApp/app/issues/issueDetails.component.html +++ b/src/Ombi/ClientApp/app/issues/issueDetails.component.html @@ -51,15 +51,17 @@
-
-

+ +
+

-
+ +

{{comment.comment}}

diff --git a/src/Ombi/ClientApp/app/issues/issueDetails.component.ts b/src/Ombi/ClientApp/app/issues/issueDetails.component.ts index 109823067..1fda9acc5 100644 --- a/src/Ombi/ClientApp/app/issues/issueDetails.component.ts +++ b/src/Ombi/ClientApp/app/issues/issueDetails.component.ts @@ -97,6 +97,13 @@ export class IssueDetailsComponent implements OnInit { }); } + public deleteComment(id: number) { + this.issueService.deleteComment(id).subscribe(x => { + this.loadComments(); + this.notificationService.success("Comment Deleted"); + }); + } + private loadComments() { this.issueService.getComments(this.issueId).subscribe(x => this.comments = x); } diff --git a/src/Ombi/ClientApp/app/services/issues.service.ts b/src/Ombi/ClientApp/app/services/issues.service.ts index aa49d58a3..41cbb4df1 100644 --- a/src/Ombi/ClientApp/app/services/issues.service.ts +++ b/src/Ombi/ClientApp/app/services/issues.service.ts @@ -56,4 +56,8 @@ export class IssuesService extends ServiceHelpers { public updateStatus(model: IUpdateStatus): Observable { return this.http.post(`${this.url}status`, JSON.stringify(model), { headers: this.headers }); } + + public deleteComment(id: number): Observable { + return this.http.delete(`${this.url}comments/${id}`, { headers: this.headers }); + } } diff --git a/src/Ombi/Controllers/IssuesController.cs b/src/Ombi/Controllers/IssuesController.cs index 07ee3216a..a228a63ef 100644 --- a/src/Ombi/Controllers/IssuesController.cs +++ b/src/Ombi/Controllers/IssuesController.cs @@ -182,6 +182,7 @@ namespace Ombi.Controllers var roles = await _userManager.GetRolesAsync(c.User); vm.Add(new IssueCommentChatViewModel { + Id = c.Id, Comment = c.Comment, Date = c.Date, Username = c.User.UserAlias, @@ -245,9 +246,9 @@ namespace Ombi.Controllers /// [HttpDelete("comments/{id:int}")] [PowerUser] - public async Task DeleteComment(int commentId) + public async Task DeleteComment(int id) { - var comment = await _issueComments.GetAll().FirstOrDefaultAsync(x => x.Id == commentId); + var comment = await _issueComments.GetAll().FirstOrDefaultAsync(x => x.Id == id); await _issueComments.Delete(comment); return true; diff --git a/src/Ombi/Models/IssueCommentChatViewModel.cs b/src/Ombi/Models/IssueCommentChatViewModel.cs index cc943263c..a75ccdfcd 100644 --- a/src/Ombi/Models/IssueCommentChatViewModel.cs +++ b/src/Ombi/Models/IssueCommentChatViewModel.cs @@ -4,6 +4,7 @@ namespace Ombi.Models { public class IssueCommentChatViewModel { + public int Id { get; set; } public string Comment { get; set; } public DateTime Date { get; set; } public string Username { get; set; } From c4b21c5f778050df08262abbd5a50d244809ce82 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 18 Aug 2018 22:38:41 +0100 Subject: [PATCH 323/495] !wip changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c24f499cf..404f1cdc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ ### **Fixes** +- #2408 Added the feature to delete comments on issues. [Jamie] + - New translations en.json (Swedish) [Jamie] - New translations en.json (French) [Jamie] From b6645c8b58cfca7d74f44a60b9a88ed5e3686a97 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 18 Aug 2018 23:04:48 +0100 Subject: [PATCH 324/495] Made the OAuth a Popout to work with Org --- src/Ombi.Api.Plex/IPlexApi.cs | 2 +- src/Ombi.Api.Plex/PlexApi.cs | 8 ++--- .../Authentication/PlexOAuthManager.cs | 17 ++-------- .../ClientApp/app/login/login.component.ts | 31 ++++++++++++++----- src/Ombi/Controllers/TokenController.cs | 2 +- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Ombi.Api.Plex/IPlexApi.cs b/src/Ombi.Api.Plex/IPlexApi.cs index 82db74278..343eaa2d7 100644 --- a/src/Ombi.Api.Plex/IPlexApi.cs +++ b/src/Ombi.Api.Plex/IPlexApi.cs @@ -24,7 +24,7 @@ namespace Ombi.Api.Plex Task GetAccount(string authToken); Task GetRecentlyAdded(string authToken, string uri, string sectionId); Task GetPin(int pinId); - Task GetOAuthUrl(int pinId, string code, string applicationUrl, bool wizard); + Task GetOAuthUrl(int pinId, string code, string applicationUrl); Task AddUser(string emailAddress, string serverId, string authToken, int[] libs); } } \ No newline at end of file diff --git a/src/Ombi.Api.Plex/PlexApi.cs b/src/Ombi.Api.Plex/PlexApi.cs index bed75b4d8..f0808622f 100644 --- a/src/Ombi.Api.Plex/PlexApi.cs +++ b/src/Ombi.Api.Plex/PlexApi.cs @@ -217,15 +217,11 @@ namespace Ombi.Api.Plex return await Api.Request(request); } - public async Task GetOAuthUrl(int pinId, string code, string applicationUrl, bool wizard) + public async Task GetOAuthUrl(int pinId, string code, string applicationUrl) { var request = new Request("auth#", "https://app.plex.tv", HttpMethod.Get); await AddHeaders(request); - var forwardUrl = wizard - ? new Request($"Wizard/OAuth/{pinId}", applicationUrl, HttpMethod.Get) - : new Request($"Login/OAuth/{pinId}", applicationUrl, HttpMethod.Get); - - request.AddQueryString("forwardUrl", forwardUrl.FullUri.ToString()); + request.AddQueryString("pinID", pinId.ToString()); request.AddQueryString("code", code); request.AddQueryString("context[device][product]", ApplicationName); diff --git a/src/Ombi.Core/Authentication/PlexOAuthManager.cs b/src/Ombi.Core/Authentication/PlexOAuthManager.cs index 803176d74..426037bb7 100644 --- a/src/Ombi.Core/Authentication/PlexOAuthManager.cs +++ b/src/Ombi.Core/Authentication/PlexOAuthManager.cs @@ -28,19 +28,6 @@ namespace Ombi.Core.Authentication return string.Empty; } - if (pin.authToken.IsNullOrEmpty()) - { - // Looks like we do not have a pin yet, we should retry a few times. - var retryCount = 0; - var retryMax = 5; - var retryWaitMs = 1000; - while (pin.authToken.IsNullOrEmpty() && retryCount < retryMax) - { - retryCount++; - await Task.Delay(retryWaitMs); - pin = await _api.GetPin(pinId); - } - } return pin.authToken; } @@ -52,14 +39,14 @@ namespace Ombi.Core.Authentication public async Task GetOAuthUrl(int pinId, string code, string websiteAddress = null) { var settings = await _customizationSettingsService.GetSettingsAsync(); - var url = await _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl.IsNullOrEmpty() ? websiteAddress : settings.ApplicationUrl, false); + var url = await _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl.IsNullOrEmpty() ? websiteAddress : settings.ApplicationUrl); return url; } public async Task GetWizardOAuthUrl(int pinId, string code, string websiteAddress) { - var url = await _api.GetOAuthUrl(pinId, code, websiteAddress, true); + var url = await _api.GetOAuthUrl(pinId, code, websiteAddress); return url; } } diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 349c1600e..e4e530461 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -40,6 +40,7 @@ export class LoginComponent implements OnDestroy, OnInit { } private timer: any; + private pinTimer: any; private clientId: string; private errorBody: string; @@ -128,17 +129,33 @@ export class LoginComponent implements OnDestroy, OnInit { this.plexTv.GetPin(this.clientId, this.appName).subscribe((pin: any) => { this.authService.login({ usePlexOAuth: true, password: "", rememberMe: true, username: "", plexTvPin: pin }).subscribe(x => { - if (window.frameElement) { - // in frame - window.open(x.url, "_blank"); - } else { - // not in frame - window.location.href = x.url; - } + + window.open(x.url, "_blank"); + this.pinTimer = setInterval(() => { + this.getPinResult(x.pinId); + }, 10000); }); }); } + public getPinResult(pinId: number) { + this.authService.oAuth(pinId).subscribe(x => { + if(x.access_token) { + localStorage.setItem("id_token", x.access_token); + + if (this.authService.loggedIn()) { + this.router.navigate(["search"]); + return; + } + } + + }, err => { + this.notify.error(err.statusText); + + this.router.navigate(["login"]); + }); + } + public ngOnDestroy() { clearInterval(this.timer); } diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index aad367dbe..1314a741a 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -91,7 +91,7 @@ namespace Ombi.Controllers error = "Application URL has not been set" }); } - return new JsonResult(new { url = url.ToString() }); + return new JsonResult(new { url = url.ToString(), pinId = model.PlexTvPin.id }); } return new UnauthorizedResult(); From 70a3f2d02c586d1f30fb09f76f6b9e85174ca8f0 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 18 Aug 2018 23:15:12 +0100 Subject: [PATCH 325/495] Fixed linting !wip --- src/Ombi/ClientApp/app/login/login.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index e4e530461..2c5a52404 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -30,6 +30,7 @@ export class LoginComponent implements OnDestroy, OnInit { public landingFlag: boolean; public baseUrl: string; public loginWithOmbi: boolean; + public pinTimer: any; public get appName(): string { if (this.customizationSettings.applicationName) { @@ -40,7 +41,6 @@ export class LoginComponent implements OnDestroy, OnInit { } private timer: any; - private pinTimer: any; private clientId: string; private errorBody: string; @@ -158,6 +158,7 @@ export class LoginComponent implements OnDestroy, OnInit { public ngOnDestroy() { clearInterval(this.timer); + clearInterval(this.pinTimer); } private cycleBackground() { From af9739d80596bbe1505bf268abf308e279dad269 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Sun, 19 Aug 2018 20:28:26 +0100 Subject: [PATCH 326/495] Made the popup a bit better !wip --- src/Ombi/ClientApp/app/login/login.component.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index 2c5a52404..abf387fa1 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -116,6 +116,7 @@ export class LoginComponent implements OnDestroy, OnInit { localStorage.setItem("id_token", x.access_token); if (this.authService.loggedIn()) { + this.ngOnDestroy(); this.router.navigate(["search"]); } else { this.notify.error(this.errorBody); @@ -130,8 +131,17 @@ export class LoginComponent implements OnDestroy, OnInit { this.authService.login({ usePlexOAuth: true, password: "", rememberMe: true, username: "", plexTvPin: pin }).subscribe(x => { - window.open(x.url, "_blank"); + window.open(x.url, "_blank", `toolbar=0, + location=0, + status=0, + menubar=0, + scrollbars=1, + resizable=1, + width=500, + height=500`); + this.pinTimer = setInterval(() => { + this.notify.info("Authenticating", "Loading... Please Wait"); this.getPinResult(x.pinId); }, 10000); }); @@ -144,6 +154,7 @@ export class LoginComponent implements OnDestroy, OnInit { localStorage.setItem("id_token", x.access_token); if (this.authService.loggedIn()) { + this.ngOnDestroy(); this.router.navigate(["search"]); return; } From 2a066e315e275230a9df8e5f286cbdd81bc01d6c Mon Sep 17 00:00:00 2001 From: TidusJar Date: Sun, 19 Aug 2018 20:42:23 +0100 Subject: [PATCH 327/495] Fixed #2418 --- src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index 5ee55d167..ec5502581 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -57,6 +57,10 @@ namespace Ombi.Schedule.Jobs.Sonarr await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SonarrEpisodeCache"); foreach (var s in sonarrSeries) { + if (!s.monitored) + { + continue; + } _log.LogDebug("Syncing series: {0}", s.title); var episodes = await _api.GetEpisodes(s.id, settings.ApiKey, settings.FullUri); var monitoredEpisodes = episodes.Where(x => x.monitored || x.hasFile); From 77a1bf5c7821d6dac4de6a73d6ff383b42e29c2c Mon Sep 17 00:00:00 2001 From: TidusJar Date: Sun, 19 Aug 2018 21:04:24 +0100 Subject: [PATCH 328/495] Now include the release year in the issue title #2381 --- src/Ombi/ClientApp/app/search/moviesearch.component.ts | 2 +- src/Ombi/ClientApp/app/search/tvsearch.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 775a2c6c4..824308b21 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -150,7 +150,7 @@ export class MovieSearchComponent implements OnInit { public reportIssue(catId: IIssueCategory, req: ISearchMovieResult) { this.issueRequestId = req.id; - this.issueRequestTitle = req.title; + this.issueRequestTitle = req.title + `(${req.releaseDate.getFullYear})`; this.issueCategorySelected = catId; this.issuesBarVisible = true; this.issueProviderId = req.id.toString(); diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.ts b/src/Ombi/ClientApp/app/search/tvsearch.component.ts index 5478608bf..a41f34586 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.ts @@ -195,7 +195,7 @@ export class TvSearchComponent implements OnInit { public reportIssue(catId: IIssueCategory, req: ISearchTvResult) { this.issueRequestId = req.id; - this.issueRequestTitle = req.title; + this.issueRequestTitle = req.title + `(${req.firstAired})`; this.issueCategorySelected = catId; this.issuesBarVisible = true; this.issueProviderId = req.id.toString(); From e9f2d9a21d2ee2ba3e05b69fd4e8441a352b2125 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 19 Aug 2018 21:30:42 +0100 Subject: [PATCH 329/495] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 404f1cdc1..8bd996857 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## (unreleased) +## v3.0.3587 (2018-08-19) ### **New Features** From e84b108c394beaa2fdf7e66254c8294cb64dcf04 Mon Sep 17 00:00:00 2001 From: Joe Groocock Date: Sun, 19 Aug 2018 22:12:35 +0100 Subject: [PATCH 330/495] Fix non-Windows builds. Fixes #2453 --- src/Ombi/gulpfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/gulpfile.js b/src/Ombi/gulpfile.js index 1b8a62c04..5723c21cc 100644 --- a/src/Ombi/gulpfile.js +++ b/src/Ombi/gulpfile.js @@ -30,7 +30,7 @@ function getEnvOptions() { function webpack(type) { // 'webpack' instead of direct path can cause https://github.com/angular/angular-cli/issues/6417 - return run(`node node_modules\\webpack\\bin\\webpack.js --config webpack.config${type ? `.${type}` : ""}.ts${getEnvOptions()}`).exec(); + return run(`node ${path.join('node_modules', 'webpack', 'bin', 'webpack.js')} --config webpack.config${type ? `.${type}` : ""}.ts${getEnvOptions()}`).exec(); } gulp.task("vendor", () => { From ce79fec216005a18e8ea109b712ab25ab95ccbcf Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 21 Aug 2018 13:55:24 +0100 Subject: [PATCH 331/495] Stript out certain characters when sending a pushover message #2385 --- src/Ombi.Core.Tests/Ombi.Core.Tests.csproj | 8 +++--- src/Ombi.Core.Tests/StringHelperTests.cs | 26 +++++++++++++++++++ src/Ombi.Helpers/StringHelper.cs | 5 ++++ .../Agents/PushoverNotification.cs | 3 ++- 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/Ombi.Core.Tests/StringHelperTests.cs diff --git a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj index 8f0abee8f..30de4b6f0 100644 --- a/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj +++ b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj @@ -5,10 +5,10 @@ - - - - + + + + diff --git a/src/Ombi.Core.Tests/StringHelperTests.cs b/src/Ombi.Core.Tests/StringHelperTests.cs new file mode 100644 index 000000000..c1b95fcd7 --- /dev/null +++ b/src/Ombi.Core.Tests/StringHelperTests.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +using NUnit.Framework; +using Ombi.Helpers; + +namespace Ombi.Core.Tests +{ + [TestFixture] + public class StringHelperTests + { + [TestCaseSource(nameof(StripCharsData))] + public string StripCharacters(string str, char[] chars) + { + return str.StripCharacters(chars); + } + + private static IEnumerable StripCharsData + { + get + { + yield return new TestCaseData("this!is^a*string",new []{'!','^','*'}).Returns("thisisastring").SetName("Basic Strip Multipe Chars"); + yield return new TestCaseData("What is this madness'",new []{'\'','^','*'}).Returns("What is this madness").SetName("Basic Strip Multipe Chars"); + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Helpers/StringHelper.cs b/src/Ombi.Helpers/StringHelper.cs index aba120c65..2dad81015 100644 --- a/src/Ombi.Helpers/StringHelper.cs +++ b/src/Ombi.Helpers/StringHelper.cs @@ -75,5 +75,10 @@ namespace Ombi.Helpers return -1; } + + public static string StripCharacters(this string str, params char[] chars) + { + return string.Concat(str.Where(c => !chars.Contains(c))); + } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs index 5b82eb8a3..72af001dc 100644 --- a/src/Ombi.Notifications/Agents/PushoverNotification.cs +++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs @@ -177,7 +177,8 @@ namespace Ombi.Notifications.Agents { try { - await Api.PushAsync(settings.AccessToken, model.Message, settings.UserToken); + //&+' < > + await Api.PushAsync(settings.AccessToken, model.Message.StripCharacters('&','+','<','>'), settings.UserToken); } catch (Exception e) { From eb1c2a695995b3192a9bd76596214b0aa102b426 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 22 Aug 2018 14:01:50 +0100 Subject: [PATCH 332/495] !wip added the lidarr settings ui --- src/Ombi.Api.Lidarr/ILidarrApi.cs | 14 ++ src/Ombi.Api.Lidarr/LidarrApi.cs | 2 +- src/Ombi.DependencyInjection/IocExtensions.cs | 2 + .../Ombi.DependencyInjection.csproj | 1 + src/Ombi.Helpers/CacheKeys.cs | 2 + src/Ombi/ClientApp/app/interfaces/IIssues.ts | 2 +- src/Ombi/ClientApp/app/interfaces/ILidarr.ts | 9 + src/Ombi/ClientApp/app/interfaces/IUser.ts | 2 +- src/Ombi/ClientApp/app/interfaces/index.ts | 1 + .../app/issues/issuestable.component.ts | 2 +- .../recentlyAdded/recentlyAdded.component.ts | 2 +- .../app/requests/request.component.ts | 4 +- .../app/requests/tvrequests.component.ts | 2 +- .../search/music/musicsearch.component.html | 118 ++++++++++ .../app/search/music/musicsearch.component.ts | 214 ++++++++++++++++++ .../ClientApp/app/search/search.component.ts | 4 +- .../app/services/applications/index.ts | 1 + .../services/applications/lidarr.service.ts | 29 +++ .../ClientApp/app/services/mobile.service.ts | 2 +- .../services/notificationMessage.service.ts | 2 +- .../app/services/recentlyAdded.service.ts | 2 +- .../ClientApp/app/services/search.service.ts | 4 + .../app/services/settings.service.ts | 1 + .../app/settings/jobs/jobs.component.ts | 2 +- .../notifications/newsletter.component.ts | 2 +- .../ClientApp/app/settings/settings.module.ts | 5 +- .../app/settings/settingsmenu.component.html | 9 + .../app/shared/issues-report.component.ts | 4 +- .../app/wizard/plex/plexoauth.component.ts | 2 +- .../Controllers/External/LidarrController.cs | 91 ++++++++ .../Controllers/External/RadarrController.cs | 4 +- src/Ombi/Ombi.csproj | 1 + 32 files changed, 520 insertions(+), 22 deletions(-) create mode 100644 src/Ombi.Api.Lidarr/ILidarrApi.cs create mode 100644 src/Ombi/ClientApp/app/interfaces/ILidarr.ts create mode 100644 src/Ombi/ClientApp/app/search/music/musicsearch.component.html create mode 100644 src/Ombi/ClientApp/app/search/music/musicsearch.component.ts create mode 100644 src/Ombi/ClientApp/app/services/applications/lidarr.service.ts create mode 100644 src/Ombi/Controllers/External/LidarrController.cs diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs new file mode 100644 index 000000000..6732693db --- /dev/null +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Api.Lidarr.Models; + +namespace Ombi.Api.Lidarr +{ + public interface ILidarrApi + { + Task> AlbumLookup(string searchTerm, string apiKey, string baseUrl); + Task> ArtistLookup(string searchTerm, string apiKey, string baseUrl); + Task> GetProfiles(string apiKey, string baseUrl); + Task> GetRootFolders(string apiKey, string baseUrl); + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index 62b412fc1..2becb57aa 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -7,7 +7,7 @@ using Ombi.Api.Lidarr.Models; namespace Ombi.Api.Lidarr { - public class LidarrApi + public class LidarrApi : ILidarrApi { public LidarrApi(ILogger logger, IApi api) { diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 2644fa9c7..d0a56bbcd 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -32,6 +32,7 @@ using Ombi.Api.CouchPotato; using Ombi.Api.DogNzb; using Ombi.Api.FanartTv; using Ombi.Api.Github; +using Ombi.Api.Lidarr; using Ombi.Api.Mattermost; using Ombi.Api.Notifications; using Ombi.Api.Pushbullet; @@ -117,6 +118,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } public static void RegisterStore(this IServiceCollection services) { diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index 2e7f984a7..6fe083fe3 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -21,6 +21,7 @@ + diff --git a/src/Ombi.Helpers/CacheKeys.cs b/src/Ombi.Helpers/CacheKeys.cs index e6c482f7b..f7a40d321 100644 --- a/src/Ombi.Helpers/CacheKeys.cs +++ b/src/Ombi.Helpers/CacheKeys.cs @@ -18,6 +18,8 @@ namespace Ombi.Helpers public const string NowPlayingMovies = nameof(NowPlayingMovies); public const string RadarrRootProfiles = nameof(RadarrRootProfiles); public const string RadarrQualityProfiles = nameof(RadarrQualityProfiles); + public const string LidarrRootFolders = nameof(LidarrRootFolders); + public const string LidarrQualityProfiles = nameof(LidarrQualityProfiles); public const string FanartTv = nameof(FanartTv); } } diff --git a/src/Ombi/ClientApp/app/interfaces/IIssues.ts b/src/Ombi/ClientApp/app/interfaces/IIssues.ts index cd2ad53a6..dce9882ec 100644 --- a/src/Ombi/ClientApp/app/interfaces/IIssues.ts +++ b/src/Ombi/ClientApp/app/interfaces/IIssues.ts @@ -1,4 +1,4 @@ -import { IIssueCategory, IUser, RequestType } from "./"; +import { IIssueCategory, IUser, RequestType } from "."; export interface IIssues { id?: number; diff --git a/src/Ombi/ClientApp/app/interfaces/ILidarr.ts b/src/Ombi/ClientApp/app/interfaces/ILidarr.ts new file mode 100644 index 000000000..2674a7dac --- /dev/null +++ b/src/Ombi/ClientApp/app/interfaces/ILidarr.ts @@ -0,0 +1,9 @@ +export interface ILidarrRootFolder { + id: number; + path: string; +} + +export interface ILidarrProfile { + name: string; + id: number; +} diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index 0e8141b52..cd96848fb 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -1,4 +1,4 @@ -import { ICheckbox } from "./index"; +import { ICheckbox } from "."; export interface IUser { id: string; diff --git a/src/Ombi/ClientApp/app/interfaces/index.ts b/src/Ombi/ClientApp/app/interfaces/index.ts index 538e1bd95..013d4278d 100644 --- a/src/Ombi/ClientApp/app/interfaces/index.ts +++ b/src/Ombi/ClientApp/app/interfaces/index.ts @@ -14,3 +14,4 @@ export * from "./ISonarr"; export * from "./IUser"; export * from "./IIssues"; export * from "./IRecentlyAdded"; +export * from "./ILidarr"; diff --git a/src/Ombi/ClientApp/app/issues/issuestable.component.ts b/src/Ombi/ClientApp/app/issues/issuestable.component.ts index 5df8a35bd..aadfd546a 100644 --- a/src/Ombi/ClientApp/app/issues/issuestable.component.ts +++ b/src/Ombi/ClientApp/app/issues/issuestable.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { IIssues, IPagenator, IssueStatus } from "./../interfaces"; +import { IIssues, IPagenator, IssueStatus } from "../interfaces"; @Component({ selector: "issues-table", diff --git a/src/Ombi/ClientApp/app/recentlyAdded/recentlyAdded.component.ts b/src/Ombi/ClientApp/app/recentlyAdded/recentlyAdded.component.ts index 303e530e1..d2120cdcf 100644 --- a/src/Ombi/ClientApp/app/recentlyAdded/recentlyAdded.component.ts +++ b/src/Ombi/ClientApp/app/recentlyAdded/recentlyAdded.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { NguCarouselConfig } from "@ngu/carousel"; import { ImageService, RecentlyAddedService } from "../services"; -import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "./../interfaces"; +import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "../interfaces"; @Component({ templateUrl: "recentlyAdded.component.html", diff --git a/src/Ombi/ClientApp/app/requests/request.component.ts b/src/Ombi/ClientApp/app/requests/request.component.ts index 08df3f2be..557bb7a07 100644 --- a/src/Ombi/ClientApp/app/requests/request.component.ts +++ b/src/Ombi/ClientApp/app/requests/request.component.ts @@ -1,8 +1,8 @@  import { Component, OnInit } from "@angular/core"; -import { IIssueCategory } from "./../interfaces"; -import { IssuesService, SettingsService } from "./../services"; +import { IIssueCategory } from "../interfaces"; +import { IssuesService, SettingsService } from "../services"; @Component({ templateUrl: "./request.component.html", diff --git a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts index 6a17066d7..144de0206 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/tvrequests.component.ts @@ -7,7 +7,7 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { FilterType, IIssueCategory, IPagenator, IRequestsViewModel, ISonarrProfile, ISonarrRootFolder, ITvRequests, OrderType } from "../interfaces"; import { NotificationService, RequestService, SonarrService } from "../services"; -import { ImageService } from "./../services/image.service"; +import { ImageService } from "../services/image.service"; @Component({ selector: "tv-requests", diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.html b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html new file mode 100644 index 000000000..44dc345bc --- /dev/null +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html @@ -0,0 +1,118 @@ + +
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+
+
+ poster + +
+
+
+ +

{{result.title}} ({{result.releaseDate | date: 'yyyy'}})

+
+ + {{ 'Search.TheatricalRelease' | translate: {date: result.releaseDate | date: 'mediumDate'} }} + {{ 'Search.DigitalDate' | translate: {date: result.digitalReleaseDate | date: 'mediumDate'} }} + + + + + {{result.quality}}p + + + + + + + + + +
+
+

{{result.overview}}

+
+ + +
+
+
+ + + +
+
+
+ +
+
+
+ + + + + + +
+ + +
+ + + +
+ +
+
+
+
+ +
+
+ + + diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts new file mode 100644 index 000000000..38f02eb8b --- /dev/null +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts @@ -0,0 +1,214 @@ +import { PlatformLocation } from "@angular/common"; +import { Component, Input, OnInit } from "@angular/core"; +import { DomSanitizer } from "@angular/platform-browser"; +import { TranslateService } from "@ngx-translate/core"; +import { Subject } from "rxjs"; +import { debounceTime, distinctUntilChanged } from "rxjs/operators"; + +import { AuthService } from "../auth/auth.service"; +import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../interfaces"; +import { NotificationService, RequestService, SearchService } from "../services"; + +@Component({ + selector: "music-search", + templateUrl: "./music.component.html", +}) +export class MusicSearchComponent implements OnInit { + + public searchText: string; + public searchChanged: Subject = new Subject(); + public movieResults: ISearchMovieResult[]; + public result: IRequestEngineResult; + public searchApplied = false; + + @Input() public issueCategories: IIssueCategory[]; + @Input() public issuesEnabled: boolean; + public issuesBarVisible = false; + public issueRequestTitle: string; + public issueRequestId: number; + public issueProviderId: string; + public issueCategorySelected: IIssueCategory; + public defaultPoster: string; + + constructor( + private searchService: SearchService, private requestService: RequestService, + private notificationService: NotificationService, private authService: AuthService, + private readonly translate: TranslateService, private sanitizer: DomSanitizer, + private readonly platformLocation: PlatformLocation) { + + this.searchChanged.pipe( + debounceTime(600), // Wait Xms after the last event before emitting last event + distinctUntilChanged(), // only emit if value is different from previous value + ).subscribe(x => { + this.searchText = x as string; + if (this.searchText === "") { + this.clearResults(); + return; + } + this.searchService.searchMusic(this.searchText) + .subscribe(x => { + this.movieResults = x; + this.searchApplied = true; + // Now let's load some extra info including IMDB Id + // This way the search is fast at displaying results. + this.getExtraInfo(); + }); + }); + this.defaultPoster = "../../../images/default_movie_poster.png"; + const base = this.platformLocation.getBaseHrefFromDOM(); + if (base) { + this.defaultPoster = "../../.." + base + "/images/default_movie_poster.png"; + } + } + + public ngOnInit() { + this.searchText = ""; + this.movieResults = []; + this.result = { + message: "", + result: false, + errorMessage: "", + }; + this.popularMovies(); + } + + public search(text: any) { + this.searchChanged.next(text.target.value); + } + + public request(searchResult: ISearchMovieResult) { + searchResult.requested = true; + searchResult.requestProcessing = true; + searchResult.showSubscribe = false; + if (this.authService.hasRole("admin") || this.authService.hasRole("AutoApproveMovie")) { + searchResult.approved = true; + } + + try { + this.requestService.requestMovie({ theMovieDbId: searchResult.id }) + .subscribe(x => { + this.result = x; + + if (this.result.result) { + this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { + this.notificationService.success(x); + searchResult.processed = true; + }); + } else { + if (this.result.errorMessage && this.result.message) { + this.notificationService.warning("Request Added", `${this.result.message} - ${this.result.errorMessage}`); + } else { + this.notificationService.warning("Request Added", this.result.message ? this.result.message : this.result.errorMessage); + } + searchResult.requested = false; + searchResult.approved = false; + searchResult.processed = false; + searchResult.requestProcessing = false; + + } + }); + } catch (e) { + + searchResult.processed = false; + searchResult.requestProcessing = false; + this.notificationService.error(e); + } + } + + public popularMovies() { + this.clearResults(); + this.searchService.popularMovies() + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + public nowPlayingMovies() { + this.clearResults(); + this.searchService.nowPlayingMovies() + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + public topRatedMovies() { + this.clearResults(); + this.searchService.topRatedMovies() + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + public upcomingMovies() { + this.clearResults(); + this.searchService.upcomingMovies() + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + + public reportIssue(catId: IIssueCategory, req: ISearchMovieResult) { + this.issueRequestId = req.id; + this.issueRequestTitle = req.title + `(${req.releaseDate.getFullYear})`; + this.issueCategorySelected = catId; + this.issuesBarVisible = true; + this.issueProviderId = req.id.toString(); + } + + public similarMovies(theMovieDbId: number) { + this.clearResults(); + this.searchService.similarMovies(theMovieDbId) + .subscribe(x => { + this.movieResults = x; + this.getExtraInfo(); + }); + } + + public subscribe(r: ISearchMovieResult) { + r.subscribed = true; + this.requestService.subscribeToMovie(r.requestId) + .subscribe(x => { + this.notificationService.success("Subscribed To Movie!"); + }); + } + + public unSubscribe(r: ISearchMovieResult) { + r.subscribed = false; + this.requestService.unSubscribeToMovie(r.requestId) + .subscribe(x => { + this.notificationService.success("Unsubscribed Movie!"); + }); + } + + private getExtraInfo() { + + this.movieResults.forEach((val, index) => { + if (val.posterPath === null) { + val.posterPath = this.defaultPoster; + } else { + val.posterPath = "https://image.tmdb.org/t/p/w300/" + val.posterPath; + } + val.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + "https://image.tmdb.org/t/p/w1280" + val.backdropPath + ")"); + this.searchService.getMovieInformation(val.id) + .subscribe(m => { + this.updateItem(val, m); + }); + }); + } + + private updateItem(key: ISearchMovieResult, updated: ISearchMovieResult) { + const index = this.movieResults.indexOf(key, 0); + if (index > -1) { + const copy = { ...this.movieResults[index] }; + this.movieResults[index] = updated; + this.movieResults[index].background = copy.background; + this.movieResults[index].posterPath = copy.posterPath; + } + } + private clearResults() { + this.movieResults = []; + this.searchApplied = false; + } +} diff --git a/src/Ombi/ClientApp/app/search/search.component.ts b/src/Ombi/ClientApp/app/search/search.component.ts index f583266ee..4f1c6c3ad 100644 --- a/src/Ombi/ClientApp/app/search/search.component.ts +++ b/src/Ombi/ClientApp/app/search/search.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; -import { IIssueCategory } from "./../interfaces"; -import { IssuesService, SettingsService } from "./../services"; +import { IIssueCategory } from "../interfaces"; +import { IssuesService, SettingsService } from "../services"; @Component({ templateUrl: "./search.component.html", diff --git a/src/Ombi/ClientApp/app/services/applications/index.ts b/src/Ombi/ClientApp/app/services/applications/index.ts index 9fe4a5403..295a53415 100644 --- a/src/Ombi/ClientApp/app/services/applications/index.ts +++ b/src/Ombi/ClientApp/app/services/applications/index.ts @@ -6,3 +6,4 @@ export * from "./sonarr.service"; export * from "./tester.service"; export * from "./plexoauth.service"; export * from "./plextv.service"; +export * from "./lidarr.service"; diff --git a/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts b/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts new file mode 100644 index 000000000..ddd7e48ec --- /dev/null +++ b/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts @@ -0,0 +1,29 @@ +import { PlatformLocation } from "@angular/common"; +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; + +import { ILidarrProfile, ILidarrRootFolder } from "../../interfaces"; +import { ILidarrSettings } from "../../interfaces"; +import { ServiceHelpers } from "../service.helpers"; + +@Injectable() +export class LidarrService extends ServiceHelpers { + constructor(http: HttpClient, public platformLocation: PlatformLocation) { + super(http, "/api/v1/Lidarr", platformLocation); + } + + public getRootFolders(settings: ILidarrSettings): Observable { + return this.http.post(`${this.url}/RootFolders/`, JSON.stringify(settings), {headers: this.headers}); + } + public getQualityProfiles(settings: ILidarrSettings): Observable { + return this.http.post(`${this.url}/Profiles/`, JSON.stringify(settings), {headers: this.headers}); + } + + public getRootFoldersFromSettings(): Observable { + return this.http.get(`${this.url}/RootFolders/`, {headers: this.headers}); + } + public getQualityProfilesFromSettings(): Observable { + return this.http.get(`${this.url}/Profiles/`, {headers: this.headers}); + } +} diff --git a/src/Ombi/ClientApp/app/services/mobile.service.ts b/src/Ombi/ClientApp/app/services/mobile.service.ts index 29cf5f609..1f9e3fb24 100644 --- a/src/Ombi/ClientApp/app/services/mobile.service.ts +++ b/src/Ombi/ClientApp/app/services/mobile.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IMobileUsersViewModel } from "./../interfaces"; +import { IMobileUsersViewModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @Injectable() diff --git a/src/Ombi/ClientApp/app/services/notificationMessage.service.ts b/src/Ombi/ClientApp/app/services/notificationMessage.service.ts index 1e4603689..93727c5d2 100644 --- a/src/Ombi/ClientApp/app/services/notificationMessage.service.ts +++ b/src/Ombi/ClientApp/app/services/notificationMessage.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IMassEmailModel } from "./../interfaces"; +import { IMassEmailModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; diff --git a/src/Ombi/ClientApp/app/services/recentlyAdded.service.ts b/src/Ombi/ClientApp/app/services/recentlyAdded.service.ts index 18e24470c..c062f973b 100644 --- a/src/Ombi/ClientApp/app/services/recentlyAdded.service.ts +++ b/src/Ombi/ClientApp/app/services/recentlyAdded.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "./../interfaces"; +import { IRecentlyAddedMovies, IRecentlyAddedTvShows } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @Injectable() diff --git a/src/Ombi/ClientApp/app/services/search.service.ts b/src/Ombi/ClientApp/app/services/search.service.ts index 4454bda0a..e0da44613 100644 --- a/src/Ombi/ClientApp/app/services/search.service.ts +++ b/src/Ombi/ClientApp/app/services/search.service.ts @@ -68,4 +68,8 @@ export class SearchService extends ServiceHelpers { public trendingTv(): Observable { return this.http.get(`${this.url}/Tv/trending`, {headers: this.headers}); } + // Music + public searchMusic(searchTerm: string): Observable { + return this.http.get(`${this.url}/Music/` + searchTerm); + } } diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index d912d03ff..2016d10b7 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -18,6 +18,7 @@ import { IJobSettings, IJobSettingsViewModel, ILandingPageSettings, + ILidarrSettings, IMattermostNotifcationSettings, IMobileNotifcationSettings, INewsletterNotificationSettings, diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index d0a7a8b83..c69d07731 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -3,7 +3,7 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { NotificationService, SettingsService } from "../../services"; -import { ICronTestModel } from "./../../interfaces"; +import { ICronTestModel } from "../../interfaces"; @Component({ templateUrl: "./jobs.component.html", diff --git a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts index 06ed6617a..eae7176e2 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts +++ b/src/Ombi/ClientApp/app/settings/notifications/newsletter.component.ts @@ -2,7 +2,7 @@ import { INewsletterNotificationSettings, NotificationType } from "../../interfaces"; import { JobService, NotificationService, SettingsService } from "../../services"; -import { TesterService } from "./../../services/applications/tester.service"; +import { TesterService } from "../../services/applications/tester.service"; @Component({ templateUrl: "./newsletter.component.html", diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 6ba7e3f52..f102a03fe 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -8,7 +8,7 @@ import { ClipboardModule } from "ngx-clipboard"; import { AuthGuard } from "../auth/auth.guard"; import { AuthService } from "../auth/auth.service"; import { - CouchPotatoService, EmbyService, IssuesService, JobService, MobileService, NotificationMessageService, PlexService, RadarrService, + CouchPotatoService, EmbyService, IssuesService, JobService, LidarrService, MobileService, NotificationMessageService, PlexService, RadarrService, SonarrService, TesterService, ValidationService, } from "../services"; @@ -22,6 +22,7 @@ import { EmbyComponent } from "./emby/emby.component"; import { IssuesComponent } from "./issues/issues.component"; import { JobsComponent } from "./jobs/jobs.component"; import { LandingPageComponent } from "./landingpage/landingpage.component"; +import { LidarrComponent } from "./lidarr/lidarr.component"; import { MassEmailComponent } from "./massemail/massemail.component"; import { DiscordComponent } from "./notifications/discord.component"; import { EmailNotificationComponent } from "./notifications/emailnotification.component"; @@ -36,7 +37,6 @@ import { TelegramComponent } from "./notifications/telegram.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; -import { LidarrComponent } from "./lidarr/lidarr.component"; import { SickRageComponent } from "./sickrage/sickrage.component"; import { SonarrComponent } from "./sonarr/sonarr.component"; import { UpdateComponent } from "./update/update.component"; @@ -145,6 +145,7 @@ const routes: Routes = [ EmbyService, MobileService, NotificationMessageService, + LidarrService, ], }) diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index 6c6bb5c3f..a3e5a16e7 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -48,6 +48,15 @@ + +
diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts index 2d1becf3a..bf739f783 100644 --- a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts @@ -4,13 +4,13 @@ import { TranslateService } from "@ngx-translate/core"; import { Subject } from "rxjs"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; -import { AuthService } from "../auth/auth.service"; -import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../interfaces"; -import { NotificationService, RequestService, SearchService } from "../services"; +import { AuthService } from "../../auth/auth.service"; +import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../../interfaces"; +import { NotificationService, RequestService, SearchService } from "../../services"; @Component({ selector: "music-search", - templateUrl: "./music.component.html", + templateUrl: "./musicsearch.component.html", }) export class MusicSearchComponent implements OnInit { @@ -19,6 +19,7 @@ export class MusicSearchComponent implements OnInit { public movieResults: ISearchMovieResult[]; public result: IRequestEngineResult; public searchApplied = false; + public searchArtist: boolean; @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; @@ -44,11 +45,20 @@ export class MusicSearchComponent implements OnInit { this.clearResults(); return; } - this.searchService.searchMusic(this.searchText) + if(this.searchArtist) { + this.searchService.searchArtist(this.searchText) .subscribe(x => { this.movieResults = x; this.searchApplied = true; }); + } else { + this.searchService.searchAlbum(this.searchText) + .subscribe(x => { + this.movieResults = x; + this.searchApplied = true; + }); + } + }); this.defaultPoster = "../../../images/default_movie_poster.png"; const base = this.platformLocation.getBaseHrefFromDOM(); @@ -65,7 +75,6 @@ export class MusicSearchComponent implements OnInit { result: false, errorMessage: "", }; - this.popularMovies(); } public search(text: any) { @@ -111,77 +120,6 @@ export class MusicSearchComponent implements OnInit { } } - public popularMovies() { - this.clearResults(); - this.searchService.popularMovies() - .subscribe(x => { - this.movieResults = x; - }); - } - public nowPlayingMovies() { - this.clearResults(); - this.searchService.nowPlayingMovies() - .subscribe(x => { - this.movieResults = x; - }); - } - public topRatedMovies() { - this.clearResults(); - this.searchService.topRatedMovies() - .subscribe(x => { - this.movieResults = x; - }); - } - public upcomingMovies() { - this.clearResults(); - this.searchService.upcomingMovies() - .subscribe(x => { - this.movieResults = x; - }); - } - - public reportIssue(catId: IIssueCategory, req: ISearchMovieResult) { - this.issueRequestId = req.id; - this.issueRequestTitle = req.title + `(${req.releaseDate.getFullYear})`; - this.issueCategorySelected = catId; - this.issuesBarVisible = true; - this.issueProviderId = req.id.toString(); - } - - public similarMovies(theMovieDbId: number) { - this.clearResults(); - this.searchService.similarMovies(theMovieDbId) - .subscribe(x => { - this.movieResults = x; - this.getExtraInfo(); - }); - } - - public subscribe(r: ISearchMovieResult) { - r.subscribed = true; - this.requestService.subscribeToMovie(r.requestId) - .subscribe(x => { - this.notificationService.success("Subscribed To Movie!"); - }); - } - - public unSubscribe(r: ISearchMovieResult) { - r.subscribed = false; - this.requestService.unSubscribeToMovie(r.requestId) - .subscribe(x => { - this.notificationService.success("Unsubscribed Movie!"); - }); - } - - private updateItem(key: ISearchMovieResult, updated: ISearchMovieResult) { - const index = this.movieResults.indexOf(key, 0); - if (index > -1) { - const copy = { ...this.movieResults[index] }; - this.movieResults[index] = updated; - this.movieResults[index].background = copy.background; - this.movieResults[index].posterPath = copy.posterPath; - } - } private clearResults() { this.movieResults = []; this.searchApplied = false; diff --git a/src/Ombi/ClientApp/app/search/search.component.html b/src/Ombi/ClientApp/app/search/search.component.html index 398bfd311..046635812 100644 --- a/src/Ombi/ClientApp/app/search/search.component.html +++ b/src/Ombi/ClientApp/app/search/search.component.html @@ -13,6 +13,9 @@
  • {{ 'Search.TvTab' | translate }}
  • +
  • + {{ 'Search.MusicTab' | translate }} +
  • @@ -25,6 +28,9 @@
    +
    + +
    diff --git a/src/Ombi/ClientApp/app/search/search.component.ts b/src/Ombi/ClientApp/app/search/search.component.ts index 4f1c6c3ad..74221e71c 100644 --- a/src/Ombi/ClientApp/app/search/search.component.ts +++ b/src/Ombi/ClientApp/app/search/search.component.ts @@ -9,8 +9,10 @@ import { IssuesService, SettingsService } from "../services"; export class SearchComponent implements OnInit { public showTv: boolean; public showMovie: boolean; + public showMusic: boolean; public issueCategories: IIssueCategory[]; public issuesEnabled = false; + public musicEnabled: boolean; constructor(private issuesService: IssuesService, private settingsService: SettingsService) { @@ -18,8 +20,10 @@ export class SearchComponent implements OnInit { } public ngOnInit() { + this.settingsService.getLidarr().subscribe(x => this.musicEnabled = x.enabled); this.showMovie = true; this.showTv = false; + this.showMusic = false; this.issuesService.getCategories().subscribe(x => this.issueCategories = x); this.settingsService.getIssueSettings().subscribe(x => this.issuesEnabled = x.enabled); } @@ -27,10 +31,17 @@ export class SearchComponent implements OnInit { public selectMovieTab() { this.showMovie = true; this.showTv = false; + this.showMusic = false; } public selectTvTab() { this.showMovie = false; this.showTv = true; + this.showMusic = false; + } + public selectMusicTab() { + this.showMovie = false; + this.showTv = false; + this.showMusic = true; } } diff --git a/src/Ombi/ClientApp/app/search/search.module.ts b/src/Ombi/ClientApp/app/search/search.module.ts index 855207616..3e8181807 100644 --- a/src/Ombi/ClientApp/app/search/search.module.ts +++ b/src/Ombi/ClientApp/app/search/search.module.ts @@ -7,6 +7,7 @@ import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { MovieSearchComponent } from "./moviesearch.component"; import { MovieSearchGridComponent } from "./moviesearchgrid.component"; +import { MusicSearchComponent } from "./music/musicsearch.component"; import { SearchComponent } from "./search.component"; import { SeriesInformationComponent } from "./seriesinformation.component"; import { TvSearchComponent } from "./tvsearch.component"; @@ -41,6 +42,7 @@ const routes: Routes = [ TvSearchComponent, SeriesInformationComponent, MovieSearchGridComponent, + MusicSearchComponent, ], exports: [ RouterModule, diff --git a/src/Ombi/ClientApp/app/services/search.service.ts b/src/Ombi/ClientApp/app/services/search.service.ts index e0da44613..7d2783dd9 100644 --- a/src/Ombi/ClientApp/app/services/search.service.ts +++ b/src/Ombi/ClientApp/app/services/search.service.ts @@ -69,7 +69,10 @@ export class SearchService extends ServiceHelpers { return this.http.get(`${this.url}/Tv/trending`, {headers: this.headers}); } // Music - public searchMusic(searchTerm: string): Observable { - return this.http.get(`${this.url}/Music/` + searchTerm); + public searchArtist(searchTerm: string): Observable { + return this.http.get(`${this.url}/Music/Artist/` + searchTerm); + } + public searchAlbum(searchTerm: string): Observable { + return this.http.get(`${this.url}/Music/Album/` + searchTerm); } } diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts index 7e5571f14..91d7ead80 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -3,8 +3,7 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { ILidarrSettings, IMinimumAvailability, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; import { IRadarrSettings } from "../../interfaces"; -import { RadarrService } from "../../services"; -import { TesterService } from "../../services"; +import { LidarrService, TesterService } from "../../services"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; @@ -22,7 +21,7 @@ export class LidarrComponent implements OnInit { public form: FormGroup; constructor(private settingsService: SettingsService, - private radarrService: RadarrService, + private lidarrService: LidarrService, private notificationService: NotificationService, private fb: FormBuilder, private testerService: TesterService) { } @@ -59,7 +58,7 @@ export class LidarrComponent implements OnInit { public getProfiles(form: FormGroup) { this.profilesRunning = true; - this.radarrService.getQualityProfiles(form.value).subscribe(x => { + this.lidarrService.getQualityProfiles(form.value).subscribe(x => { this.qualities = x; this.qualities.unshift({ name: "Please Select", id: -1 }); @@ -70,7 +69,7 @@ export class LidarrComponent implements OnInit { public getRootFolders(form: FormGroup) { this.rootFoldersRunning = true; - this.radarrService.getRootFolders(form.value).subscribe(x => { + this.lidarrService.getRootFolders(form.value).subscribe(x => { this.rootFolders = x; this.rootFolders.unshift({ path: "Please Select", id: -1 }); diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index a3e5a16e7..a8d89ab1c 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -50,7 +50,7 @@
    +
    + + + The Lidarr Sync is required + +
    +
    diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 5d99e391f..84192c53c 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -506,6 +506,7 @@ namespace Ombi.Controllers j.RefreshMetadata = j.RefreshMetadata.HasValue() ? j.RefreshMetadata : JobSettingsHelper.RefreshMetadata(j); j.PlexRecentlyAddedSync = j.PlexRecentlyAddedSync.HasValue() ? j.PlexRecentlyAddedSync : JobSettingsHelper.PlexRecentlyAdded(j); j.Newsletter = j.Newsletter.HasValue() ? j.Newsletter : JobSettingsHelper.Newsletter(j); + j.LidarrArtistSync = j.LidarrArtistSync.HasValue() ? j.LidarrArtistSync : JobSettingsHelper.LidarrArtistSync(j); return j; } From 3750243f1147e0826f8131efa2747b9805edacdf Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 24 Aug 2018 23:02:40 +0100 Subject: [PATCH 344/495] A lot more lidarr work, i'm done for the day wow... !wip #2313 --- src/Ombi.Api.Lidarr/Models/Statistics.cs | 2 +- src/Ombi.Core/Engine/MusicSearchEngine.cs | 13 +++-- .../Models/Search/SearchAlbumViewModel.cs | 8 +++- .../Models/Search/SearchArtistViewModel.cs | 2 - .../Rule/Interfaces/SpecificRules.cs | 2 + .../Rule/Rules/Search/ExistingRule.cs | 23 +++++++-- .../Rule/Rules/Search/LidarrAlbumCacheRule.cs | 36 ++++++++++++++ .../Rules/Search/LidarrArtistCacheRule.cs | 35 ++++++++++++++ .../Jobs/Lidarr/LidarrAlbumSync.cs | 9 ++-- src/Ombi.Store/Entities/LidarrAlbumCache.cs | 4 +- src/Ombi.Store/Entities/LidarrArtistCache.cs | 3 -- ...20180824211553_LidarrSyncJobs.Designer.cs} | 14 ++---- ...bs.cs => 20180824211553_LidarrSyncJobs.cs} | 48 ++++++++----------- .../Migrations/OmbiContextModelSnapshot.cs | 12 +---- .../app/interfaces/ISearchMusicResult.ts | 9 ++-- .../search/music/albumsearch.component.html | 41 +++++++++------- .../app/settings/jobs/jobs.component.ts | 1 + src/Ombi/Properties/launchSettings.json | 4 +- src/Ombi/wwwroot/translations/en.json | 2 + 19 files changed, 174 insertions(+), 94 deletions(-) create mode 100644 src/Ombi.Core/Rule/Rules/Search/LidarrAlbumCacheRule.cs create mode 100644 src/Ombi.Core/Rule/Rules/Search/LidarrArtistCacheRule.cs rename src/Ombi.Store/Migrations/{20180824202308_LidarrSyncJobs.Designer.cs => 20180824211553_LidarrSyncJobs.Designer.cs} (98%) rename src/Ombi.Store/Migrations/{20180824202308_LidarrSyncJobs.cs => 20180824211553_LidarrSyncJobs.cs} (80%) diff --git a/src/Ombi.Api.Lidarr/Models/Statistics.cs b/src/Ombi.Api.Lidarr/Models/Statistics.cs index 0f334fcdd..5d8eb4275 100644 --- a/src/Ombi.Api.Lidarr/Models/Statistics.cs +++ b/src/Ombi.Api.Lidarr/Models/Statistics.cs @@ -7,6 +7,6 @@ public int trackCount { get; set; } public int totalTrackCount { get; set; } public int sizeOnDisk { get; set; } - public decimal percentOfTracks { get; set; } + public decimal percentOfEpisodes { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs index b90fca88c..7eba0429d 100644 --- a/src/Ombi.Core/Engine/MusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs @@ -73,7 +73,7 @@ namespace Ombi.Core.Engine var vm = new List(); foreach (var r in result) { - vm.Add(MapIntoArtistVm(r)); + vm.Add(await MapIntoArtistVm(r)); } return vm; @@ -107,7 +107,7 @@ namespace Ombi.Core.Engine return await _lidarrApi.GetArtist(artistId, settings.ApiKey, settings.FullUri); } - private SearchArtistViewModel MapIntoArtistVm(ArtistLookup a) + private async Task MapIntoArtistVm(ArtistLookup a) { var vm = new SearchArtistViewModel { @@ -121,13 +121,16 @@ namespace Ombi.Core.Engine Links = a.links, Overview = a.overview, }; - + var poster = a.images?.FirstOrDefault(x => x.coverType.Equals("poaster")); if (poster == null) { vm.Poster = a.remotePoster; } + + await Rules.StartSpecificRules(vm, SpecificRules.LidarrArtist); + return vm; } @@ -162,6 +165,10 @@ namespace Ombi.Core.Engine vm.Cover = a.remoteCover; } + await Rules.StartSpecificRules(vm, SpecificRules.LidarrAlbum); + + await RunSearchRules(vm); + return vm; } private LidarrSettings _settings; diff --git a/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs b/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs index b243c5374..a494a3cb5 100644 --- a/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchAlbumViewModel.cs @@ -1,8 +1,9 @@ using System; +using Ombi.Store.Entities; namespace Ombi.Core.Models.Search { - public class SearchAlbumViewModel + public class SearchAlbumViewModel : SearchViewModel { public string Title { get; set; } public string ForeignAlbumId { get; set; } @@ -14,6 +15,9 @@ namespace Ombi.Core.Models.Search public string ForeignArtistId { get; set; } public string Cover { get; set; } public string Disk { get; set; } - + public decimal PercentOfTracks { get; set; } + public override RequestType Type => RequestType.Album; + public bool PartiallyAvailable => PercentOfTracks != 100 && PercentOfTracks > 0; + public bool FullyAvailable => PercentOfTracks == 100; } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/SearchArtistViewModel.cs b/src/Ombi.Core/Models/Search/SearchArtistViewModel.cs index da1cc892f..b736df529 100644 --- a/src/Ombi.Core/Models/Search/SearchArtistViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchArtistViewModel.cs @@ -12,8 +12,6 @@ namespace Ombi.Core.Models.Search public string Poster { get; set; } public string Logo { get; set; } public bool Monitored { get; set; } - public bool Available { get; set; } - public bool Requested { get; set; } public string ArtistType { get; set; } public string CleanName { get; set; } public Link[] Links { get; set; } // Couldn't be bothered to map it diff --git a/src/Ombi.Core/Rule/Interfaces/SpecificRules.cs b/src/Ombi.Core/Rule/Interfaces/SpecificRules.cs index 522ba8a95..d432f87be 100644 --- a/src/Ombi.Core/Rule/Interfaces/SpecificRules.cs +++ b/src/Ombi.Core/Rule/Interfaces/SpecificRules.cs @@ -3,5 +3,7 @@ public enum SpecificRules { CanSendNotification, + LidarrArtist, + LidarrAlbum, } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs index bd7218145..965fcdfaf 100644 --- a/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/ExistingRule.cs @@ -11,13 +11,15 @@ namespace Ombi.Core.Rule.Rules.Search { public class ExistingRule : BaseSearchRule, IRules { - public ExistingRule(IMovieRequestRepository movie, ITvRequestRepository tv) + public ExistingRule(IMovieRequestRepository movie, ITvRequestRepository tv, IMusicRequestRepository music) { Movie = movie; Tv = tv; + Music = music; } private IMovieRequestRepository Movie { get; } + private IMusicRequestRepository Music { get; } private ITvRequestRepository Tv { get; } public async Task Execute(SearchViewModel obj) @@ -37,7 +39,7 @@ namespace Ombi.Core.Rule.Rules.Search } return Success(); } - else if (obj.Type == RequestType.Album) + if (obj.Type == RequestType.TvShow) { //var tvRequests = Tv.GetRequest(obj.Id); //if (tvRequests != null) // Do we already have a request for this? @@ -50,7 +52,7 @@ namespace Ombi.Core.Rule.Rules.Search // return Task.FromResult(Success()); //} - var request = (SearchTvShowViewModel) obj; + var request = (SearchTvShowViewModel)obj; var tvRequests = Tv.GetRequest(obj.Id); if (tvRequests != null) // Do we already have a request for this? { @@ -96,6 +98,21 @@ namespace Ombi.Core.Rule.Rules.Search return Success(); } + if (obj.Type == RequestType.Album) + { + var album = (SearchAlbumViewModel) obj; + var albumRequest = await Music.GetRequestAsync(album.ForeignAlbumId); + if (albumRequest != null) // Do we already have a request for this? + { + obj.Requested = true; + obj.RequestId = albumRequest.Id; + obj.Approved = albumRequest.Approved; + obj.Available = albumRequest.Available; + + return Success(); + } + return Success(); + } return Success(); } } diff --git a/src/Ombi.Core/Rule/Rules/Search/LidarrAlbumCacheRule.cs b/src/Ombi.Core/Rule/Rules/Search/LidarrAlbumCacheRule.cs new file mode 100644 index 000000000..97a27d47f --- /dev/null +++ b/src/Ombi.Core/Rule/Rules/Search/LidarrAlbumCacheRule.cs @@ -0,0 +1,36 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Interfaces; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Core.Rule.Rules.Search +{ + public class LidarrAlbumCacheRule : SpecificRule, ISpecificRule + { + public LidarrAlbumCacheRule(IRepository db) + { + _db = db; + } + + private readonly IRepository _db; + + public Task Execute(object objec) + { + var obj = (SearchAlbumViewModel) objec; + // Check if it's in Lidarr + var result = _db.GetAll().FirstOrDefault(x => x.ForeignAlbumId.Equals(obj.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + if (result != null) + { + obj.PercentOfTracks = result.PercentOfTracks; + obj.Monitored = true; // It's in Lidarr so it's monitored + } + + return Task.FromResult(Success()); + } + + public override SpecificRules Rule => SpecificRules.LidarrAlbum; + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/LidarrArtistCacheRule.cs b/src/Ombi.Core/Rule/Rules/Search/LidarrArtistCacheRule.cs new file mode 100644 index 000000000..db472a951 --- /dev/null +++ b/src/Ombi.Core/Rule/Rules/Search/LidarrArtistCacheRule.cs @@ -0,0 +1,35 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Interfaces; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Core.Rule.Rules.Search +{ + public class LidarrArtistCacheRule : SpecificRule, ISpecificRule + { + public LidarrArtistCacheRule(IRepository db) + { + _db = db; + } + + private readonly IRepository _db; + + public Task Execute(object objec) + { + var obj = (SearchArtistViewModel) objec; + // Check if it's in Lidarr + var result = _db.GetAll().FirstOrDefault(x => x.ForeignArtistId.Equals(obj.ForignArtistId, StringComparison.InvariantCultureIgnoreCase)); + if (result != null) + { + obj.Monitored = true; // It's in Lidarr so it's monitored + } + + return Task.FromResult(Success()); + } + + public override SpecificRules Rule => SpecificRules.LidarrArtist; + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index 031a9e9f5..2eae36206 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs @@ -48,23 +48,24 @@ namespace Ombi.Schedule.Jobs.Lidarr // Let's remove the old cached data await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM LidarrAlbumCache"); - var artistCache = new List(); + var albumCache = new List(); foreach (var a in albums) { if (a.id > 0) { - artistCache.Add(new LidarrAlbumCache + albumCache.Add(new LidarrAlbumCache { ArtistId = a.artistId, ForeignAlbumId = a.foreignAlbumId, ReleaseDate = a.releaseDate, TrackCount = a.currentRelease.trackCount, Monitored = a.monitored, - Title = a.title + Title = a.title, + PercentOfTracks = a.statistics?.percentOfEpisodes ?? 0m }); } } - await _ctx.LidarrAlbumCache.AddRangeAsync(artistCache); + await _ctx.LidarrAlbumCache.AddRangeAsync(albumCache); await _ctx.SaveChangesAsync(); } diff --git a/src/Ombi.Store/Entities/LidarrAlbumCache.cs b/src/Ombi.Store/Entities/LidarrAlbumCache.cs index 5fd1ffcdd..15d0a53da 100644 --- a/src/Ombi.Store/Entities/LidarrAlbumCache.cs +++ b/src/Ombi.Store/Entities/LidarrAlbumCache.cs @@ -12,8 +12,6 @@ namespace Ombi.Store.Entities public DateTime ReleaseDate { get; set; } public bool Monitored { get; set; } public string Title { get; set; } - - [ForeignKey(nameof(ArtistId))] - public LidarrArtistCache Artist { get; set; } + public decimal PercentOfTracks { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/LidarrArtistCache.cs b/src/Ombi.Store/Entities/LidarrArtistCache.cs index 86daebd2b..dd78b4e2c 100644 --- a/src/Ombi.Store/Entities/LidarrArtistCache.cs +++ b/src/Ombi.Store/Entities/LidarrArtistCache.cs @@ -6,12 +6,9 @@ namespace Ombi.Store.Entities [Table("LidarrArtistCache")] public class LidarrArtistCache : Entity { - [ForeignKey(nameof(ArtistId))] public int ArtistId { get; set; } public string ArtistName { get; set; } public string ForeignArtistId { get; set; } public bool Monitored { get; set; } - - public List Albums { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Migrations/20180824202308_LidarrSyncJobs.Designer.cs b/src/Ombi.Store/Migrations/20180824211553_LidarrSyncJobs.Designer.cs similarity index 98% rename from src/Ombi.Store/Migrations/20180824202308_LidarrSyncJobs.Designer.cs rename to src/Ombi.Store/Migrations/20180824211553_LidarrSyncJobs.Designer.cs index 5929fe0f5..c97886525 100644 --- a/src/Ombi.Store/Migrations/20180824202308_LidarrSyncJobs.Designer.cs +++ b/src/Ombi.Store/Migrations/20180824211553_LidarrSyncJobs.Designer.cs @@ -9,7 +9,7 @@ using Ombi.Store.Context; namespace Ombi.Store.Migrations { [DbContext(typeof(OmbiContext))] - [Migration("20180824202308_LidarrSyncJobs")] + [Migration("20180824211553_LidarrSyncJobs")] partial class LidarrSyncJobs { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -257,6 +257,8 @@ namespace Ombi.Store.Migrations b.Property("Monitored"); + b.Property("PercentOfTracks"); + b.Property("ReleaseDate"); b.Property("Title"); @@ -265,8 +267,6 @@ namespace Ombi.Store.Migrations b.HasKey("Id"); - b.HasIndex("ArtistId"); - b.ToTable("LidarrAlbumCache"); }); @@ -965,14 +965,6 @@ namespace Ombi.Store.Migrations .HasPrincipalKey("EmbyId"); }); - modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => - { - b.HasOne("Ombi.Store.Entities.LidarrArtistCache", "Artist") - .WithMany("Albums") - .HasForeignKey("ArtistId") - .OnDelete(DeleteBehavior.Cascade); - }); - modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "User") diff --git a/src/Ombi.Store/Migrations/20180824202308_LidarrSyncJobs.cs b/src/Ombi.Store/Migrations/20180824211553_LidarrSyncJobs.cs similarity index 80% rename from src/Ombi.Store/Migrations/20180824202308_LidarrSyncJobs.cs rename to src/Ombi.Store/Migrations/20180824211553_LidarrSyncJobs.cs index e741b2294..2b843d3e2 100644 --- a/src/Ombi.Store/Migrations/20180824202308_LidarrSyncJobs.cs +++ b/src/Ombi.Store/Migrations/20180824211553_LidarrSyncJobs.cs @@ -7,6 +7,25 @@ namespace Ombi.Store.Migrations { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.CreateTable( + name: "LidarrAlbumCache", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ArtistId = table.Column(nullable: false), + ForeignAlbumId = table.Column(nullable: true), + TrackCount = table.Column(nullable: false), + ReleaseDate = table.Column(nullable: false), + Monitored = table.Column(nullable: false), + Title = table.Column(nullable: true), + PercentOfTracks = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id); + }); + migrationBuilder.CreateTable( name: "LidarrArtistCache", columns: table => new @@ -22,35 +41,6 @@ namespace Ombi.Store.Migrations { table.PrimaryKey("PK_LidarrArtistCache", x => x.Id); }); - - migrationBuilder.CreateTable( - name: "LidarrAlbumCache", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - ArtistId = table.Column(nullable: false), - ForeignAlbumId = table.Column(nullable: true), - TrackCount = table.Column(nullable: false), - ReleaseDate = table.Column(nullable: false), - Monitored = table.Column(nullable: false), - Title = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id); - table.ForeignKey( - name: "FK_LidarrAlbumCache_LidarrArtistCache_ArtistId", - column: x => x.ArtistId, - principalTable: "LidarrArtistCache", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_LidarrAlbumCache_ArtistId", - table: "LidarrAlbumCache", - column: "ArtistId"); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 893c22edc..0e3d1efea 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -255,6 +255,8 @@ namespace Ombi.Store.Migrations b.Property("Monitored"); + b.Property("PercentOfTracks"); + b.Property("ReleaseDate"); b.Property("Title"); @@ -263,8 +265,6 @@ namespace Ombi.Store.Migrations b.HasKey("Id"); - b.HasIndex("ArtistId"); - b.ToTable("LidarrAlbumCache"); }); @@ -963,14 +963,6 @@ namespace Ombi.Store.Migrations .HasPrincipalKey("EmbyId"); }); - modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => - { - b.HasOne("Ombi.Store.Entities.LidarrArtistCache", "Artist") - .WithMany("Albums") - .HasForeignKey("ArtistId") - .OnDelete(DeleteBehavior.Cascade); - }); - modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => { b.HasOne("Ombi.Store.Entities.OmbiUser", "User") diff --git a/src/Ombi/ClientApp/app/interfaces/ISearchMusicResult.ts b/src/Ombi/ClientApp/app/interfaces/ISearchMusicResult.ts index 6afd10b19..806beb92f 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISearchMusicResult.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISearchMusicResult.ts @@ -29,6 +29,8 @@ export interface ILink { } export interface ISearchAlbumResult { + id: number; + requestId: number; albumType: string; artistName: string; cover: string; @@ -39,10 +41,11 @@ export interface ISearchAlbumResult { rating: number; releaseDate: Date; title: string; - approved: boolean; + fullyAvailable: boolean; + partiallyAvailable: boolean; requested: boolean; - requestId: number; - available: boolean; + approved: boolean; + subscribed: boolean; // for the UI showSubscribe: boolean; diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html index cf98c84cc..6b5cc52a9 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html @@ -33,27 +33,32 @@ --> - - - Release Date: {{result.releaseDate | date:'yyyy-MM-dd'}} + + + + + + + + + + + - - {{result.rating}}/10 - - - - - - - - - - + - - - + + + + + + + Release Date: {{result.releaseDate | date:'yyyy-MM-dd'}} + + + {{result.rating}}/10 + diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index c69d07731..756d6ba89 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -34,6 +34,7 @@ export class JobsComponent implements OnInit { refreshMetadata: [x.refreshMetadata, Validators.required], newsletter: [x.newsletter, Validators.required], plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], + lidarrArtistSync: [x.lidarrArtistSync, Validators.required], }); }); } diff --git a/src/Ombi/Properties/launchSettings.json b/src/Ombi/Properties/launchSettings.json index 96b1ceb6e..19e5d23af 100644 --- a/src/Ombi/Properties/launchSettings.json +++ b/src/Ombi/Properties/launchSettings.json @@ -3,14 +3,14 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:3579/", + "applicationUrl": "http://localhost:3577/", "sslPort": 0 } }, "profiles": { "IIS Express": { "commandName": "IISExpress", - "commandLineArgs": "--host http://*:3579", + "commandLineArgs": "--host http://*:3577", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 1d195d251..4fd3ccb1b 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -12,6 +12,8 @@ "Common": { "ContinueButton": "Continue", "Available": "Available", + "PartiallyAvailable": "Partially Available", + "Monitored": "Monitored", "NotAvailable": "Not Available", "ProcessingRequest": "Processing Request", "PendingApproval": "Pending Approval", From 5df232f3f56e9a5fe5e71f30666c058a745a9e67 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 26 Aug 2018 10:10:58 +0100 Subject: [PATCH 345/495] got the view albums button working !wip --- src/Ombi.Api.Lidarr/ILidarrApi.cs | 4 +- src/Ombi.Api.Lidarr/LidarrApi.cs | 12 ++-- .../Models/AlbumByArtistResponse.cs | 51 +++++++++------- src/Ombi.Api.Lidarr/Models/AlbumResponse.cs | 27 +++++++++ src/Ombi.Api/Request.cs | 3 +- .../Rule/Search/ExistingRequestRuleTests.cs | 4 +- .../Engine/Interfaces/IMusicSearchEngine.cs | 2 +- src/Ombi.Core/Engine/MusicSearchEngine.cs | 47 +++++++++++++-- .../search/music/artistsearch.component.html | 2 +- .../search/music/artistsearch.component.ts | 58 ++++--------------- .../search/music/musicsearch.component.html | 6 +- .../app/search/music/musicsearch.component.ts | 9 ++- .../ClientApp/app/services/search.service.ts | 9 ++- src/Ombi/Controllers/SearchController.cs | 11 ++++ 14 files changed, 151 insertions(+), 94 deletions(-) create mode 100644 src/Ombi.Api.Lidarr/Models/AlbumResponse.cs diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs index 2fe74f803..d66f9716c 100644 --- a/src/Ombi.Api.Lidarr/ILidarrApi.cs +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -12,9 +12,9 @@ namespace Ombi.Api.Lidarr Task> GetRootFolders(string apiKey, string baseUrl); Task GetArtist(int artistId, string apiKey, string baseUrl); Task GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl); - Task GetAlbumsByArtist(int artistId, string apiKey, string baseUrl); + Task GetAlbumsByArtist(string foreignArtistId); Task GetAlbumByForeignId(string foreignArtistId, string apiKey, string baseUrl); Task> GetArtists(string apiKey, string baseUrl); - Task> GetAllAlbums(string apiKey, string baseUrl); + Task> GetAllAlbums(string apiKey, string baseUrl); } } \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index 09b670afa..84e0d090a 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -82,12 +82,10 @@ namespace Ombi.Api.Lidarr return albums.FirstOrDefault(); } - public Task GetAlbumsByArtist(int artistId, string apiKey, string baseUrl) + public Task GetAlbumsByArtist(string foreignArtistId) { - var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); - - request.AddQueryString("artistId", artistId.ToString()); - AddHeaders(request, apiKey); + var request = new Request(string.Empty, $"https://api.lidarr.audio/api/v0.3/artist/{foreignArtistId}", + HttpMethod.Get) {IgnoreBaseUrlAppend = true}; return Api.Request(request); } @@ -99,12 +97,12 @@ namespace Ombi.Api.Lidarr return Api.Request>(request); } - public Task> GetAllAlbums(string apiKey, string baseUrl) + public Task> GetAllAlbums(string apiKey, string baseUrl) { var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); AddHeaders(request, apiKey); - return Api.Request>(request); + return Api.Request>(request); } private void AddHeaders(Request request, string key) diff --git a/src/Ombi.Api.Lidarr/Models/AlbumByArtistResponse.cs b/src/Ombi.Api.Lidarr/Models/AlbumByArtistResponse.cs index 0a54dbfeb..62f19651f 100644 --- a/src/Ombi.Api.Lidarr/Models/AlbumByArtistResponse.cs +++ b/src/Ombi.Api.Lidarr/Models/AlbumByArtistResponse.cs @@ -1,27 +1,34 @@ -using System; - -namespace Ombi.Api.Lidarr.Models +namespace Ombi.Api.Lidarr.Models { public class AlbumByArtistResponse { - public string title { get; set; } - public string disambiguation { get; set; } - public int artistId { get; set; } - public string foreignAlbumId { get; set; } - public bool monitored { get; set; } - public int profileId { get; set; } - public int duration { get; set; } - public string albumType { get; set; } - public object[] secondaryTypes { get; set; } - public int mediumCount { get; set; } - public Ratings ratings { get; set; } - public DateTime releaseDate { get; set; } - public Currentrelease currentRelease { get; set; } - public Release[] releases { get; set; } - public object[] genres { get; set; } - public Medium[] media { get; set; } - public Image[] images { get; set; } - public Statistics statistics { get; set; } - public int id { get; set; } + public Album[] Albums { get; set; } + public string ArtistName { get; set; } + public string Disambiguation { get; set; } + public string Id { get; set; } + public Image[] Images { get; set; } + public Link[] Links { get; set; } + public string Overview { get; set; } + public Rating Rating { get; set; } + public string SortName { get; set; } + public string Status { get; set; } + public string Type { get; set; } + } + + public class Rating + { + public int Count { get; set; } + public decimal Value { get; set; } + } + + public class Album + { + public string Disambiguation { get; set; } + public string Id { get; set; } + public string ReleaseDate { get; set; } + public string[] ReleaseStatuses { get; set; } + public string[] SecondaryTypes { get; set; } + public string Title { get; set; } + public string Type { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/AlbumResponse.cs b/src/Ombi.Api.Lidarr/Models/AlbumResponse.cs new file mode 100644 index 000000000..f9d35c43b --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/AlbumResponse.cs @@ -0,0 +1,27 @@ +using System; + +namespace Ombi.Api.Lidarr.Models +{ + public class AlbumResponse + { + public string title { get; set; } + public string disambiguation { get; set; } + public int artistId { get; set; } + public string foreignAlbumId { get; set; } + public bool monitored { get; set; } + public int profileId { get; set; } + public int duration { get; set; } + public string albumType { get; set; } + public object[] secondaryTypes { get; set; } + public int mediumCount { get; set; } + public Ratings ratings { get; set; } + public DateTime releaseDate { get; set; } + public Currentrelease currentRelease { get; set; } + public Release[] releases { get; set; } + public object[] genres { get; set; } + public Medium[] media { get; set; } + public Image[] images { get; set; } + public Statistics statistics { get; set; } + public int id { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api/Request.cs b/src/Ombi.Api/Request.cs index cfd284f54..fd888d0d2 100644 --- a/src/Ombi.Api/Request.cs +++ b/src/Ombi.Api/Request.cs @@ -28,6 +28,7 @@ namespace Ombi.Api public bool IgnoreErrors { get; set; } public bool Retry { get; set; } public List StatusCodeToRetry { get; set; } = new List(); + public bool IgnoreBaseUrlAppend { get; set; } public Action OnBeforeDeserialization { get; set; } @@ -38,7 +39,7 @@ namespace Ombi.Api var sb = new StringBuilder(); if (!string.IsNullOrEmpty(BaseUrl)) { - sb.Append(!BaseUrl.EndsWith("/") ? string.Format("{0}/", BaseUrl) : BaseUrl); + sb.Append(!BaseUrl.EndsWith("/") && !IgnoreBaseUrlAppend ? string.Format("{0}/", BaseUrl) : BaseUrl); } sb.Append(Endpoint.StartsWith("/") ? Endpoint.Remove(0, 1) : Endpoint); return sb.ToString(); diff --git a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs index a706472dd..e32c8e996 100644 --- a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs @@ -19,12 +19,14 @@ namespace Ombi.Core.Tests.Rule.Search MovieMock = new Mock(); TvMock = new Mock(); - Rule = new ExistingRule(MovieMock.Object, TvMock.Object); + MusicMock = new Mock(); + Rule = new ExistingRule(MovieMock.Object, TvMock.Object, MusicMock.Object); } private ExistingRule Rule { get; set; } private Mock MovieMock { get; set; } private Mock TvMock { get; set; } + private Mock MusicMock { get; set; } [Test] diff --git a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs index 44643bc9d..03294982a 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMusicSearchEngine.cs @@ -9,7 +9,7 @@ namespace Ombi.Core.Engine { Task GetAlbumArtist(string foreignArtistId); Task GetArtist(int artistId); - Task GetArtistAlbums(string foreignArtistId); + Task> GetArtistAlbums(string foreignArtistId); Task> SearchAlbum(string search); Task> SearchArtist(string search); } diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs index 7eba0429d..17f1aed54 100644 --- a/src/Ombi.Core/Engine/MusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs @@ -82,12 +82,21 @@ namespace Ombi.Core.Engine /// /// Returns all albums by the specified artist /// - /// + /// /// - public async Task GetArtistAlbums(string foreignArtistId) + public async Task> GetArtistAlbums(string foreignArtistId) { var settings = await GetSettings(); - return await _lidarrApi.GetArtistByForeignId(foreignArtistId, settings.ApiKey, settings.FullUri); + var result = await _lidarrApi.GetAlbumsByArtist(foreignArtistId); + // We do not want any Singles (This will include EP's) + var albumsOnly = + result.Albums.Where(x => !x.Type.Equals("Single", StringComparison.InvariantCultureIgnoreCase)); + var vm = new List(); + foreach (var album in albumsOnly) + { + vm.Add(await MapIntoAlbumVm(album, result.Id, result.ArtistName, settings)); + } + return vm; } /// @@ -121,7 +130,7 @@ namespace Ombi.Core.Engine Links = a.links, Overview = a.overview, }; - + var poster = a.images?.FirstOrDefault(x => x.coverType.Equals("poaster")); if (poster == null) { @@ -147,6 +156,7 @@ namespace Ombi.Core.Engine }; if (vm.Monitored) { + //TODO THEY HAVE FIXED THIS IN DEV // The JSON is different for some stupid reason // Need to lookup the artist now and all the images -.-" var artist = await _lidarrApi.GetArtist(a.artistId, settings.ApiKey, settings.FullUri); @@ -171,6 +181,35 @@ namespace Ombi.Core.Engine return vm; } + + private async Task MapIntoAlbumVm(Album a, string artistId, string artistName, LidarrSettings settings) + { + var fullAlbum = await _lidarrApi.GetAlbumByForeignId(a.Id, settings.ApiKey, settings.FullUri); + var vm = new SearchAlbumViewModel + { + ForeignAlbumId = a.Id, + Monitored = fullAlbum.monitored, + Rating = fullAlbum.ratings?.value ?? 0m, + ReleaseDate = fullAlbum.releaseDate, + Title = a.Title, + Disk = fullAlbum.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url, + ForeignArtistId = artistId, + ArtistName = artistName, + Cover = fullAlbum.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url + }; + + if (vm.Cover.IsNullOrEmpty()) + { + vm.Cover = fullAlbum.remoteCover; + } + + await Rules.StartSpecificRules(vm, SpecificRules.LidarrAlbum); + + await RunSearchRules(vm); + + return vm; + } + private LidarrSettings _settings; private async Task GetSettings() { diff --git a/src/Ombi/ClientApp/app/search/music/artistsearch.component.html b/src/Ombi/ClientApp/app/search/music/artistsearch.component.html index b68990d69..5ea5433f1 100644 --- a/src/Ombi/ClientApp/app/search/music/artistsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/artistsearch.component.html @@ -51,7 +51,7 @@ --> - diff --git a/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts b/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts index 8794d5efc..76a223d09 100644 --- a/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts @@ -1,10 +1,7 @@ -import { Component, Input } from "@angular/core"; -import { TranslateService } from "@ngx-translate/core"; +import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { AuthService } from "../../auth/auth.service"; -import { IRequestEngineResult, ISearchMovieResult } from "../../interfaces"; -import { ISearchArtistResult } from "../../interfaces/ISearchMusicResult"; -import { NotificationService, RequestService } from "../../services"; +import { ISearchAlbumResult, ISearchArtistResult } from "../../interfaces/ISearchMusicResult"; +import { SearchService } from "../../services"; @Component({ selector: "artist-search", @@ -13,51 +10,16 @@ import { NotificationService, RequestService } from "../../services"; export class ArtistSearchComponent { @Input() public result: ISearchArtistResult; - public engineResult: IRequestEngineResult; @Input() public defaultPoster: string; - constructor( - private requestService: RequestService, - private notificationService: NotificationService, private authService: AuthService, - private readonly translate: TranslateService) { + @Output() public viewAlbumsResult = new EventEmitter(); + + constructor(private searchService: SearchService) { } - public request(searchResult: ISearchMovieResult) { - searchResult.requested = true; - searchResult.requestProcessing = true; - searchResult.showSubscribe = false; - if (this.authService.hasRole("admin") || this.authService.hasRole("AutoApproveMovie")) { - searchResult.approved = true; - } - - try { - this.requestService.requestMovie({ theMovieDbId: searchResult.id }) - .subscribe(x => { - this.engineResult = x; - - if (this.engineResult.result) { - this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { - this.notificationService.success(x); - searchResult.processed = true; - }); - } else { - if (this.engineResult.errorMessage && this.engineResult.message) { - this.notificationService.warning("Request Added", `${this.engineResult.message} - ${this.engineResult.errorMessage}`); - } else { - this.notificationService.warning("Request Added", this.engineResult.message ? this.engineResult.message : this.engineResult.errorMessage); - } - searchResult.requested = false; - searchResult.approved = false; - searchResult.processed = false; - searchResult.requestProcessing = false; - - } - }); - } catch (e) { - - searchResult.processed = false; - searchResult.requestProcessing = false; - this.notificationService.error(e); - } + public viewAllAlbums() { + this.searchService.getAlbumsForArtist(this.result.forignArtistId).subscribe(x => { + this.viewAlbumsResult.emit(x); + }); } } diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.html b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html index 867d7803e..b73ee553b 100644 --- a/src/Ombi/ClientApp/app/search/music/musicsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html @@ -8,10 +8,10 @@
    - - + +
    @@ -29,7 +29,7 @@
    - +

    diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts index ad980ff60..e022ab6c3 100644 --- a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts @@ -22,7 +22,7 @@ export class MusicSearchComponent implements OnInit { public albumResult: ISearchAlbumResult[]; public result: IRequestEngineResult; public searchApplied = false; - public searchAlbum: boolean = false; + public searchAlbum: boolean = true; @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; @@ -148,6 +148,13 @@ export class MusicSearchComponent implements OnInit { } } + public viewAlbumsForArtist(albums: ISearchAlbumResult[]) { + this.clearArtistResults(); + this.searchAlbum = true; + this.albumResult = albums; + this.setAlbumBackground(); + } + private clearArtistResults() { this.artistResult = []; this.searchApplied = false; diff --git a/src/Ombi/ClientApp/app/services/search.service.ts b/src/Ombi/ClientApp/app/services/search.service.ts index f6a5271f5..9769ad229 100644 --- a/src/Ombi/ClientApp/app/services/search.service.ts +++ b/src/Ombi/ClientApp/app/services/search.service.ts @@ -7,7 +7,7 @@ import { Observable } from "rxjs"; import { TreeNode } from "primeng/primeng"; import { ISearchMovieResult } from "../interfaces"; import { ISearchTvResult } from "../interfaces"; -import { ISearchArtistResult } from "../interfaces/ISearchMusicResult"; +import { ISearchAlbumResult, ISearchArtistResult } from "../interfaces/ISearchMusicResult"; import { ServiceHelpers } from "./service.helpers"; @Injectable() @@ -73,7 +73,10 @@ export class SearchService extends ServiceHelpers { public searchArtist(searchTerm: string): Observable { return this.http.get(`${this.url}/Music/Artist/` + searchTerm); } - public searchAlbum(searchTerm: string): Observable { - return this.http.get(`${this.url}/Music/Album/` + searchTerm); + public searchAlbum(searchTerm: string): Observable { + return this.http.get(`${this.url}/Music/Album/` + searchTerm); + } + public getAlbumsForArtist(foreignArtistId: string): Observable { + return this.http.get(`${this.url}/Music/Artist/Album/${foreignArtistId}`); } } diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index 026e4541d..5d05ceae5 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -206,5 +206,16 @@ namespace Ombi.Controllers { return await MusicEngine.SearchAlbum(searchTerm); } + + /// + /// Returns all albums for the artist using the ForeignArtistId + /// + /// We use Lidarr as the Provider + /// + [HttpGet("music/artist/album/{foreignArtistId}")] + public async Task> GetAlbumsByArtist(string foreignArtistId) + { + return await MusicEngine.GetArtistAlbums(foreignArtistId); + } } } From 82d610e2357a30a2e2de7e0a55d5ffba2dfe6668 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 26 Aug 2018 10:32:08 +0100 Subject: [PATCH 346/495] Added the availablility checker #2313 !wip --- .../Agents/DiscordNotification.cs | 12 ++- .../Agents/EmailNotification.cs | 2 +- .../Agents/MattermostNotification.cs | 2 +- .../Agents/MobileNotification.cs | 2 +- .../Agents/PushbulletNotification.cs | 2 +- .../Agents/PushoverNotification.cs | 2 +- .../Agents/SlackNotification.cs | 2 +- .../Agents/TelegramNotification.cs | 2 +- src/Ombi.Notifications/BaseNotification.cs | 18 ++++- .../NotificationMessageCurlys.cs | 38 +++++++++- .../Jobs/Lidarr/LidarrAvailabilityChecker.cs | 73 +++++++++++++++++++ src/Ombi.Store/Entities/LidarrAlbumCache.cs | 5 ++ .../search/music/artistsearch.component.html | 2 +- .../search/music/artistsearch.component.ts | 2 + 14 files changed, 148 insertions(+), 16 deletions(-) create mode 100644 src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs diff --git a/src/Ombi.Notifications/Agents/DiscordNotification.cs b/src/Ombi.Notifications/Agents/DiscordNotification.cs index 66280ef70..d788b471c 100644 --- a/src/Ombi.Notifications/Agents/DiscordNotification.cs +++ b/src/Ombi.Notifications/Agents/DiscordNotification.cs @@ -20,8 +20,8 @@ namespace Ombi.Notifications.Agents { public DiscordNotification(IDiscordApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, - IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub) - : base(sn, r, m, t,s,log, sub) + IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music) + : base(sn, r, m, t, s, log, sub, music) { Api = api; Logger = log; @@ -130,12 +130,18 @@ namespace Ombi.Notifications.Agents title = MovieRequest.Title; image = MovieRequest.PosterPath; } - else + else if (model.RequestType == RequestType.TvShow) { user = TvRequest.RequestedUser.UserAlias; title = TvRequest.ParentRequest.Title; image = TvRequest.ParentRequest.PosterPath; } + else if (model.RequestType == RequestType.Album) + { + user = AlbumRequest.RequestedUser.UserAlias; + title = AlbumRequest.Title; + image = AlbumRequest.Cover; + } var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; var notification = new NotificationMessage { diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs index 53046ade0..3ab045e87 100644 --- a/src/Ombi.Notifications/Agents/EmailNotification.cs +++ b/src/Ombi.Notifications/Agents/EmailNotification.cs @@ -22,7 +22,7 @@ namespace Ombi.Notifications.Agents public class EmailNotification : BaseNotification, IEmailNotification { public EmailNotification(ISettingsService settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService c, - ILogger log, UserManager um, IRepository sub) : base(settings, r, m, t, c, log, sub) + ILogger log, UserManager um, IRepository sub, IMusicRequestRepository music) : base(settings, r, m, t, c, log, sub, music) { EmailProvider = prov; Logger = log; diff --git a/src/Ombi.Notifications/Agents/MattermostNotification.cs b/src/Ombi.Notifications/Agents/MattermostNotification.cs index 8199d8bfe..9e8a34e3b 100644 --- a/src/Ombi.Notifications/Agents/MattermostNotification.cs +++ b/src/Ombi.Notifications/Agents/MattermostNotification.cs @@ -21,7 +21,7 @@ namespace Ombi.Notifications.Agents public class MattermostNotification : BaseNotification, IMattermostNotification { public MattermostNotification(IMattermostApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub) : base(sn, r, m, t,s,log, sub) + ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs index 8559c043d..c521b99a4 100644 --- a/src/Ombi.Notifications/Agents/MobileNotification.cs +++ b/src/Ombi.Notifications/Agents/MobileNotification.cs @@ -22,7 +22,7 @@ namespace Ombi.Notifications.Agents { public MobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, - UserManager um, IRepository sub) : base(sn, r, m, t, s,log, sub) + UserManager um, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) { _api = api; _logger = log; diff --git a/src/Ombi.Notifications/Agents/PushbulletNotification.cs b/src/Ombi.Notifications/Agents/PushbulletNotification.cs index 24aa8cd22..0e488bf79 100644 --- a/src/Ombi.Notifications/Agents/PushbulletNotification.cs +++ b/src/Ombi.Notifications/Agents/PushbulletNotification.cs @@ -17,7 +17,7 @@ namespace Ombi.Notifications.Agents public class PushbulletNotification : BaseNotification, IPushbulletNotification { public PushbulletNotification(IPushbulletApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub) : base(sn, r, m, t,s,log, sub) + ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs index 5b82eb8a3..95b2a18d3 100644 --- a/src/Ombi.Notifications/Agents/PushoverNotification.cs +++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs @@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents public class PushoverNotification : BaseNotification, IPushoverNotification { public PushoverNotification(IPushoverApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub) : base(sn, r, m, t, s, log, sub) + ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/SlackNotification.cs b/src/Ombi.Notifications/Agents/SlackNotification.cs index 894758591..6c04f5ea6 100644 --- a/src/Ombi.Notifications/Agents/SlackNotification.cs +++ b/src/Ombi.Notifications/Agents/SlackNotification.cs @@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents public class SlackNotification : BaseNotification, ISlackNotification { public SlackNotification(ISlackApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub) : base(sn, r, m, t, s, log, sub) + ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/TelegramNotification.cs b/src/Ombi.Notifications/Agents/TelegramNotification.cs index 827b0b590..7bcda7c7f 100644 --- a/src/Ombi.Notifications/Agents/TelegramNotification.cs +++ b/src/Ombi.Notifications/Agents/TelegramNotification.cs @@ -19,7 +19,7 @@ namespace Ombi.Notifications.Agents public TelegramNotification(ITelegramApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s - , IRepository sub) : base(sn, r, m, t,s,log, sub) + , IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t,s,log, sub, music) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index 507b8059b..287f86455 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -19,7 +19,7 @@ namespace Ombi.Notifications.Interfaces public abstract class BaseNotification : INotification where T : Settings.Settings.Models.Settings, new() { protected BaseNotification(ISettingsService settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv, - ISettingsService customization, ILogger> log, IRepository sub) + ISettingsService customization, ILogger> log, IRepository sub, IMusicRequestRepository album) { Settings = settings; TemplateRepository = templateRepo; @@ -30,12 +30,14 @@ namespace Ombi.Notifications.Interfaces CustomizationSettings.ClearCache(); RequestSubscription = sub; _log = log; + AlbumRepository = album; } protected ISettingsService Settings { get; } protected INotificationTemplatesRepository TemplateRepository { get; } protected IMovieRequestRepository MovieRepository { get; } protected ITvRequestRepository TvRepository { get; } + protected IMusicRequestRepository AlbumRepository { get; } protected CustomizationSettings Customization { get; set; } protected IRepository RequestSubscription { get; set; } private ISettingsService CustomizationSettings { get; } @@ -43,6 +45,7 @@ namespace Ombi.Notifications.Interfaces protected ChildRequests TvRequest { get; set; } + protected AlbumRequest AlbumRequest { get; set; } protected MovieRequests MovieRequest { get; set; } protected IQueryable SubsribedUsers { get; private set; } @@ -130,10 +133,14 @@ namespace Ombi.Notifications.Interfaces { MovieRequest = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId); } - else + else if (type == RequestType.TvShow) { TvRequest = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId); } + else if (type == RequestType.Album) + { + AlbumRequest = await AlbumRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId); + } } private async Task GetConfiguration() @@ -181,11 +188,16 @@ namespace Ombi.Notifications.Interfaces curlys.Setup(model, MovieRequest, Customization); } - else + else if (model.RequestType == RequestType.TvShow) { _log.LogDebug("Notification options: {@model}, Req: {@TvRequest}, Settings: {@Customization}", model, TvRequest, Customization); curlys.Setup(model, TvRequest, Customization); } + else if (model.RequestType == RequestType.Album) + { + _log.LogDebug("Notification options: {@model}, Req: {@AlbumRequest}, Settings: {@Customization}", model, AlbumRequest, Customization); + curlys.Setup(model, AlbumRequest, Customization); + } var parsed = resolver.ParseMessage(template, curlys); return parsed; diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 497c49c86..710f64619 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -47,14 +47,48 @@ namespace Ombi.Notifications if (req?.RequestType == RequestType.Movie) { - PosterImage = string.Format((req?.PosterPath ?? string.Empty).StartsWith("/", StringComparison.InvariantCultureIgnoreCase) + PosterImage = string.Format((req?.PosterPath ?? string.Empty).StartsWith("/", StringComparison.InvariantCultureIgnoreCase) ? "https://image.tmdb.org/t/p/w300{0}" : "https://image.tmdb.org/t/p/w300/{0}", req?.PosterPath); } else { PosterImage = req?.PosterPath; } - + + AdditionalInformation = opts?.AdditionalInformation ?? string.Empty; + } + + public void Setup(NotificationOptions opts, AlbumRequest req, CustomizationSettings s) + { + LoadIssues(opts); + string title; + if (req == null) + { + opts.Substitutes.TryGetValue("Title", out title); + } + else + { + title = req?.Title; + } + ApplicationUrl = (s?.ApplicationUrl.HasValue() ?? false) ? s.ApplicationUrl : string.Empty; + ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s?.ApplicationName; + RequestedUser = req?.RequestedUser?.UserName; + if (UserName.IsNullOrEmpty()) + { + // Can be set if it's an issue + UserName = req?.RequestedUser?.UserName; + } + + Alias = (req?.RequestedUser?.Alias.HasValue() ?? false) ? req?.RequestedUser?.Alias : req?.RequestedUser?.UserName; + Title = title; + RequestedDate = req?.RequestedDate.ToString("D"); + if (Type.IsNullOrEmpty()) + { + Type = req?.RequestType.Humanize(); + } + Year = req?.ReleaseDate.Year.ToString(); + PosterImage = (req?.Cover.HasValue() ?? false) ? req.Cover : req?.Disk ?? string.Empty; + AdditionalInformation = opts?.AdditionalInformation ?? string.Empty; } diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs new file mode 100644 index 000000000..b40eda06b --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Hangfire; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Ombi.Core.Notifications; +using Ombi.Helpers; +using Ombi.Notifications.Models; +using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Schedule.Jobs.Lidarr +{ + public class LidarrAvailabilityChecker + { + public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository albums, ILogger log, + IBackgroundJobClient job, INotificationService notification) + { + _cachedAlbums = albums; + _requestRepository = requests; + _logger = log; + _job = job; + _notificationService = notification; + } + + private readonly IMusicRequestRepository _requestRepository; + private readonly IRepository _cachedAlbums; + private readonly ILogger _logger; + private readonly IBackgroundJobClient _job; + private readonly INotificationService _notificationService; + + public async Task Start() + { + var allAlbumRequests = _requestRepository.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available); + var albumsToUpdate = new List(); + foreach (var request in allAlbumRequests) + { + // Check if we have it cached + var cachedAlbum = await _cachedAlbums.FirstOrDefaultAsync(x => x.ForeignAlbumId.Equals(request.ForeignAlbumId)); + if (cachedAlbum != null) + { + if (cachedAlbum.Monitored && cachedAlbum.FullyAvailable) + { + request.Available = true; + request.MarkedAsAvailable = DateTime.Now; + albumsToUpdate.Add(request); + } + } + } + + foreach (var albumRequest in albumsToUpdate) + { + await _requestRepository.Update(albumRequest); + var recipient = albumRequest.RequestedUser.Email.HasValue() ? albumRequest.RequestedUser.Email : string.Empty; + + _logger.LogDebug("AlbumId: {0}, RequestUser: {1}", albumRequest.Id, recipient); + + _job.Enqueue(() => _notificationService.Publish(new NotificationOptions + { + DateTime = DateTime.Now, + NotificationType = NotificationType.RequestAvailable, + RequestId = albumRequest.Id, + RequestType = RequestType.Album, + Recipient = recipient, + })); + } + } + } +} \ No newline at end of file diff --git a/src/Ombi.Store/Entities/LidarrAlbumCache.cs b/src/Ombi.Store/Entities/LidarrAlbumCache.cs index 15d0a53da..d9ceab8a3 100644 --- a/src/Ombi.Store/Entities/LidarrAlbumCache.cs +++ b/src/Ombi.Store/Entities/LidarrAlbumCache.cs @@ -13,5 +13,10 @@ namespace Ombi.Store.Entities public bool Monitored { get; set; } public string Title { get; set; } public decimal PercentOfTracks { get; set; } + + [NotMapped] + public bool PartiallyAvailable => PercentOfTracks != 100 && PercentOfTracks > 0; + [NotMapped] + public bool FullyAvailable => PercentOfTracks == 100; } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/search/music/artistsearch.component.html b/src/Ombi/ClientApp/app/search/music/artistsearch.component.html index 5ea5433f1..77a68a841 100644 --- a/src/Ombi/ClientApp/app/search/music/artistsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/artistsearch.component.html @@ -51,7 +51,7 @@ --> - diff --git a/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts b/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts index 76a223d09..852e294e3 100644 --- a/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/artistsearch.component.ts @@ -11,6 +11,7 @@ export class ArtistSearchComponent { @Input() public result: ISearchArtistResult; @Input() public defaultPoster: string; + public searchingAlbums: boolean; @Output() public viewAlbumsResult = new EventEmitter(); @@ -18,6 +19,7 @@ export class ArtistSearchComponent { } public viewAllAlbums() { + this.searchingAlbums = true; this.searchService.getAlbumsForArtist(this.result.forignArtistId).subscribe(x => { this.viewAlbumsResult.emit(x); }); From cda7c0fe4c1ad6473aac476e05981587ee42e3e3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 26 Aug 2018 13:59:10 +0100 Subject: [PATCH 347/495] !wip availability done --- src/Ombi.DependencyInjection/IocExtensions.cs | 1 + .../Jobs/Lidarr/ILidarrAvailabilityChecker.cs | 9 +++++++++ src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs | 10 +++++++++- .../Jobs/Lidarr/LidarrAvailabilityChecker.cs | 2 +- 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 src/Ombi.Schedule/Jobs/Lidarr/ILidarrAvailabilityChecker.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 52f3db919..c4b291936 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -189,6 +189,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } diff --git a/src/Ombi.Schedule/Jobs/Lidarr/ILidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/ILidarrAvailabilityChecker.cs new file mode 100644 index 000000000..f0c679229 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Lidarr/ILidarrAvailabilityChecker.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Schedule.Jobs.Lidarr +{ + public interface ILidarrAvailabilityChecker + { + Task Start(); + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index 2eae36206..9708df589 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Hangfire; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; @@ -19,12 +20,15 @@ namespace Ombi.Schedule.Jobs.Lidarr { public class LidarrAlbumSync : ILidarrAlbumSync { - public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IOmbiContext ctx) + public LidarrAlbumSync(ISettingsService lidarr, ILidarrApi lidarrApi, ILogger log, IOmbiContext ctx, + IBackgroundJobClient job, ILidarrAvailabilityChecker availability) { _lidarrSettings = lidarr; _lidarrApi = lidarrApi; _logger = log; _ctx = ctx; + _job = job; + _availability = availability; _lidarrSettings.ClearCache(); } @@ -32,6 +36,8 @@ namespace Ombi.Schedule.Jobs.Lidarr private readonly ILidarrApi _lidarrApi; private readonly ILogger _logger; private readonly IOmbiContext _ctx; + private readonly IBackgroundJobClient _job; + private readonly ILidarrAvailabilityChecker _availability; public async Task CacheContent() { @@ -74,6 +80,8 @@ namespace Ombi.Schedule.Jobs.Lidarr { _logger.LogError(LoggingEvents.Cacher, ex, "Failed caching queued items from Lidarr Album"); } + + _job.Enqueue(() => _availability.Start()); } } catch (Exception) diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs index b40eda06b..d5ba14a6d 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -15,7 +15,7 @@ using Ombi.Store.Repository.Requests; namespace Ombi.Schedule.Jobs.Lidarr { - public class LidarrAvailabilityChecker + public class LidarrAvailabilityChecker : ILidarrAvailabilityChecker { public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository albums, ILogger log, IBackgroundJobClient job, INotificationService notification) From 861e677151ab5804c3c0f9029a590e9012c2aac1 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Tue, 21 Aug 2018 22:54:08 +0100 Subject: [PATCH 348/495] Add methods to interface and add model class --- .../Engine/Interfaces/IMovieRequestEngine.cs | 2 -- src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs | 2 ++ src/Ombi.Core/Engine/MovieRequestEngine.cs | 9 +++++++++ src/Ombi.Core/Engine/TvRequestEngine.cs | 9 +++++++++ src/Ombi.Core/Models/RequestQuotaCountModel.cs | 11 +++++++++++ src/Ombi/Controllers/SearchController.cs | 13 +++++++++++++ 6 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 src/Ombi.Core/Models/RequestQuotaCountModel.cs diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs index 91cbb9e72..152a1d923 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs @@ -17,7 +17,5 @@ namespace Ombi.Core.Engine.Interfaces Task ApproveMovie(MovieRequests request); Task ApproveMovieById(int requestId); Task DenyMovieById(int modelId); - - } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs index 740428ec7..53111fd95 100644 --- a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Ombi.Core.Models; using Ombi.Core.Models.Requests; using Ombi.Core.Models.UI; using Ombi.Store.Entities; @@ -22,5 +23,6 @@ namespace Ombi.Core.Engine.Interfaces Task GetTotal(); Task UnSubscribeRequest(int requestId, RequestType type); Task SubscribeToRequest(int requestId, RequestType type); + Task GetRemainingRequests(); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index f73c6fda1..7e0b61bd8 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -19,6 +19,7 @@ using Ombi.Core.Settings; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; +using Ombi.Core.Models; namespace Ombi.Core.Engine { @@ -483,5 +484,13 @@ namespace Ombi.Core.Engine return new RequestEngineResult {Result = true, Message = $"{movieName} has been successfully added!"}; } + + public async Task GetRemainingRequests() + { + return new RequestQuotaCountModel() + { + HasLimit = false, + }; + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 90760f759..78a26f82a 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -23,6 +23,7 @@ using Ombi.Core.Settings; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; +using Ombi.Core.Models; namespace Ombi.Core.Engine { @@ -612,5 +613,13 @@ namespace Ombi.Core.Engine return new RequestEngineResult { Result = true }; } + + public async Task GetRemainingRequests() + { + return new RequestQuotaCountModel() + { + HasLimit = false, + }; + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/RequestQuotaCountModel.cs b/src/Ombi.Core/Models/RequestQuotaCountModel.cs new file mode 100644 index 000000000..23a692f41 --- /dev/null +++ b/src/Ombi.Core/Models/RequestQuotaCountModel.cs @@ -0,0 +1,11 @@ +namespace Ombi.Core.Models +{ + public class RequestQuotaCountModel + { + public bool HasLimit { get; set; } + + public int Limit { get; set; } + + public int Remaining { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index fe5399d78..65e9f930b 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging; using Ombi.Core; using Ombi.Core.Engine; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Models; using Ombi.Core.Models.Search; using StackExchange.Profiling; @@ -182,5 +183,17 @@ namespace Ombi.Controllers { return await TvEngine.Trending(); } + + [HttpGet("movie/requestCount")] + public async Task RemainingMovieRequests() + { + return null; + } + + [HttpGet("tv/requestCount")] + public async Task RemainingTvRequests() + { + return null; + } } } From 1bfbfdbe0033afa5ce25faa1b58878a317c46364 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Tue, 21 Aug 2018 22:54:55 +0100 Subject: [PATCH 349/495] Fix scss import for unix systems --- src/Ombi/ClientApp/styles/_imports.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/styles/_imports.scss b/src/Ombi/ClientApp/styles/_imports.scss index 09da286f8..5b22e1ac4 100644 --- a/src/Ombi/ClientApp/styles/_imports.scss +++ b/src/Ombi/ClientApp/styles/_imports.scss @@ -1,2 +1,2 @@ -@import './styles.scss'; -@import './scrollbar.scss'; \ No newline at end of file +@import './Styles.scss'; +@import './scrollbar.scss'; From 7ef2a1679da4ce126c593999018bdf6c33ce6d26 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sat, 25 Aug 2018 01:20:36 +0100 Subject: [PATCH 350/495] Add dummy for request counter --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 4 +++- .../app/interfaces/IRemainingRequests.ts | 5 +++++ .../app/requests/movierequests.component.ts | 4 ++++ .../app/search/moviesearch.component.html | 11 +++++++++-- .../app/search/moviesearch.component.ts | 18 +++++++++++++++--- .../ClientApp/app/services/request.service.ts | 5 +++++ src/Ombi/Controllers/RequestController.cs | 10 ++++++++++ 7 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 7e0b61bd8..a1c0b16cf 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -489,7 +489,9 @@ namespace Ombi.Core.Engine { return new RequestQuotaCountModel() { - HasLimit = false, + HasLimit = true, + Limit = 5, + Remaining = 4, }; } } diff --git a/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts b/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts new file mode 100644 index 000000000..774f3c5e6 --- /dev/null +++ b/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts @@ -0,0 +1,5 @@ +export interface IRemainingRequests { + hasLimit: boolean; + limit: number; + remaining: number; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index db7b400db..9495f0790 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -7,6 +7,7 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; import { NotificationService, RadarrService, RequestService } from "../services"; +import { IRemainingRequests } from "../interfaces/IRemainingRequests"; @Component({ selector: "movie-requests", @@ -38,6 +39,8 @@ export class MovieRequestsComponent implements OnInit { public orderType: OrderType = OrderType.RequestedDateDesc; public OrderType = OrderType; + public remaining: IRemainingRequests; + public totalMovies: number = 100; private currentlyLoaded: number; private amountToLoad: number; @@ -80,6 +83,7 @@ export class MovieRequestsComponent implements OnInit { }; this.loadInit(); this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + } public paginate(event: IPagenator) { diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index 44dc345bc..2e6458eb5 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -1,5 +1,6 @@ 
    +
    @@ -18,8 +19,14 @@
    -
    -
    + +

    + {{remaining.remaining}}/{{remaining.limit}} requests remaining. +

    + +
    +
    +
    diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 824308b21..dd2621ae1 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -8,6 +8,7 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../interfaces"; import { NotificationService, RequestService, SearchService } from "../services"; +import { IRemainingRequests } from "../interfaces/IRemainingRequests"; @Component({ selector: "movie-search", @@ -19,6 +20,7 @@ export class MovieSearchComponent implements OnInit { public searchChanged: Subject = new Subject(); public movieResults: ISearchMovieResult[]; public result: IRequestEngineResult; + public remaining: IRemainingRequests; public searchApplied = false; @Input() public issueCategories: IIssueCategory[]; @@ -35,7 +37,6 @@ export class MovieSearchComponent implements OnInit { private notificationService: NotificationService, private authService: AuthService, private readonly translate: TranslateService, private sanitizer: DomSanitizer, private readonly platformLocation: PlatformLocation) { - this.searchChanged.pipe( debounceTime(600), // Wait Xms after the last event before emitting last event distinctUntilChanged(), // only emit if value is different from previous value @@ -69,10 +70,21 @@ export class MovieSearchComponent implements OnInit { result: false, errorMessage: "", }; - this.popularMovies(); - } + this.remaining = { + hasLimit: false, + limit: 0, + remaining: 0, + }; + this.popularMovies(); + + this.requestService.getRemainingMovieRequests().subscribe(remaining => { + this.remaining = remaining; + }); + + } public search(text: any) { + this.searchChanged.next(text.target.value); } diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 48fa5622d..5345369e7 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -8,6 +8,7 @@ import { TreeNode } from "primeng/primeng"; import { FilterType, IChildRequests, IFilter, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces"; import { ITvRequestViewModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; +import { IRemainingRequests } from "../interfaces/IRemainingRequests"; @Injectable() export class RequestService extends ServiceHelpers { @@ -15,6 +16,10 @@ export class RequestService extends ServiceHelpers { super(http, "/api/v1/Request/", platformLocation); } + public getRemainingMovieRequests(): Observable { + return this.http.get(`${this.url}movie/remaining`, {headers: this.headers}); + } + public requestMovie(movie: IMovieRequestModel): Observable { return this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}); } diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index d794f6001..71d09b2ef 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -12,6 +12,7 @@ using Ombi.Attributes; using Ombi.Core.Models.UI; using Ombi.Models; using Ombi.Store.Entities; +using Ombi.Core.Models; namespace Ombi.Controllers { @@ -464,5 +465,14 @@ namespace Ombi.Controllers await TvRequestEngine.UnSubscribeRequest(requestId, RequestType.TvShow); return true; } + + /// + /// Gets model containing remaining number of requests. + /// + [HttpGet("movie/remaining")] + public async Task GetRemainingRequests() + { + return await MovieRequestEngine.GetRemainingRequests(); + } } } \ No newline at end of file From 3959a79ea8702ceb4776290587e7ec8472f768c2 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 00:04:40 +0100 Subject: [PATCH 351/495] Move to seperate component and display for both TV and movies --- .vscode/launch.json | 46 ++++++++++++++++ .vscode/tasks.json | 15 +++++ src/Ombi.Core/Engine/MovieRequestEngine.cs | 3 +- src/Ombi.Core/Engine/TvRequestEngine.cs | 5 +- .../Models/RequestQuotaCountModel.cs | 4 ++ .../app/interfaces/IRemainingRequests.ts | 1 + .../requests/remainingrequests.component.html | 18 ++++++ .../requests/remainingrequests.component.ts | 55 +++++++++++++++++++ .../app/requests/remainingrequests.module.ts | 32 +++++++++++ .../app/search/moviesearch.component.html | 7 +-- .../app/search/moviesearch.component.ts | 13 +---- .../ClientApp/app/search/search.module.ts | 2 + .../app/search/tvsearch.component.html | 8 +-- .../ClientApp/app/services/request.service.ts | 4 ++ src/Ombi/Controllers/RequestController.cs | 11 +++- 15 files changed, 198 insertions(+), 26 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 src/Ombi/ClientApp/app/requests/remainingrequests.component.html create mode 100644 src/Ombi/ClientApp/app/requests/remainingrequests.component.ts create mode 100644 src/Ombi/ClientApp/app/requests/remainingrequests.module.ts diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..3e98c769e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,46 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/src/Ombi/bin/Debug/netcoreapp2.1/Ombi.dll", + "args": [], + "cwd": "${workspaceFolder}/src/Ombi", + "stopAtEntry": false, + "internalConsoleOptions": "openOnSessionStart", + "launchBrowser": { + "enabled": false, + "args": "${auto-detect-url}", + "windows": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + }, + "osx": { + "command": "open" + }, + "linux": { + "command": "xdg-open" + } + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ,] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..af3542206 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/src/Ombi/Ombi.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index a1c0b16cf..d40c3e7b8 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -489,9 +489,10 @@ namespace Ombi.Core.Engine { return new RequestQuotaCountModel() { - HasLimit = true, + HasLimit = false, Limit = 5, Remaining = 4, + NextRequest = DateTime.Parse("2018-08-27T00:00:00+01"), }; } } diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 78a26f82a..80e627ade 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -618,7 +618,10 @@ namespace Ombi.Core.Engine { return new RequestQuotaCountModel() { - HasLimit = false, + HasLimit = true, + Limit = 5, + Remaining = 4, + NextRequest = DateTime.Parse("2018-08-30T00:00:00+01"), }; } } diff --git a/src/Ombi.Core/Models/RequestQuotaCountModel.cs b/src/Ombi.Core/Models/RequestQuotaCountModel.cs index 23a692f41..1af9ad819 100644 --- a/src/Ombi.Core/Models/RequestQuotaCountModel.cs +++ b/src/Ombi.Core/Models/RequestQuotaCountModel.cs @@ -1,3 +1,5 @@ +using System; + namespace Ombi.Core.Models { public class RequestQuotaCountModel @@ -7,5 +9,7 @@ namespace Ombi.Core.Models public int Limit { get; set; } public int Remaining { get; set; } + + public DateTime NextRequest { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts b/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts index 774f3c5e6..ce1b37427 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts @@ -2,4 +2,5 @@ export interface IRemainingRequests { hasLimit: boolean; limit: number; remaining: number; + nextRequest: Date; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.html b/src/Ombi/ClientApp/app/requests/remainingrequests.component.html new file mode 100644 index 000000000..769cd79c2 --- /dev/null +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.html @@ -0,0 +1,18 @@ +
    +

    + {{remaining.remaining}}/{{remaining.limit}} requests remaining +

    +

    + Another request will be added in {{daysUntil}} {{daysUntil == 1 ? "day" : "days"}} +

    +

    + Another request will be added in {{hoursUntil}} {{hoursUntil == 1 ? "hour" : "hours"}} +

    +

    + Another request will be added in {{minutesUntil}} {{minutesUntil == 1 ? "minute" : "minutes"}} +

    +
    + +
    +
    + diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts new file mode 100644 index 000000000..1279a60e9 --- /dev/null +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -0,0 +1,55 @@ +import { Component, OnInit, Input } from "@angular/core"; +import { RequestService } from "../services"; +import { IRemainingRequests } from "../interfaces/IRemainingRequests"; + +@Component({ + selector: "remaining-requests", + templateUrl: "./remainingrequests.component.html", +}) + +export class RemainingRequestsComponent implements OnInit { + public remaining: IRemainingRequests; + @Input() public movie: boolean; + public daysUntil: number; + public hoursUntil: number; + public minutesUntil: number; + + constructor(private requestService: RequestService) + { + } + + ngOnInit(): void { + var self = this; + this.update(); + setInterval(function(){ + self.update() + }, 10000) + } + + update(): void { + var callback = (remaining => { + this.remaining = remaining; + this.daysUntil = Math.ceil(this.daysUntilNextRequest()); + this.hoursUntil = Math.ceil(this.hoursUntilNextRequest()); + this.minutesUntil = Math.ceil(this.minutesUntilNextRequest()) + }); + + if (this.movie) { + this.requestService.getRemainingMovieRequests().subscribe(callback); + } else { + this.requestService.getRemainingTvRequests().subscribe(callback); + } + } + + daysUntilNextRequest(): number { + return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60 / 24; + } + + hoursUntilNextRequest(): number { + return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60; + } + + minutesUntilNextRequest(): number { + return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60; + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts new file mode 100644 index 000000000..acbbed256 --- /dev/null +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts @@ -0,0 +1,32 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { FormsModule } from "@angular/forms"; +import { RouterModule } from "@angular/router"; + +import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; + +import { SidebarModule, TooltipModule, TreeTableModule } from "primeng/primeng"; +import { RequestService } from "../services"; + +import { SharedModule } from "../shared/shared.module"; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + NgbModule.forRoot(), + TreeTableModule, + SharedModule, + SidebarModule, + TooltipModule, + ], + declarations: [ + ], + exports: [ + RouterModule, + ], + providers: [ + RequestService, + ], +}) +export class SearchModule { } diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index 2e6458eb5..2e5a17559 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -20,12 +20,7 @@
    -

    - {{remaining.remaining}}/{{remaining.limit}} requests remaining. -

    - -
    -
    +
    diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index dd2621ae1..afd217089 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -8,7 +8,6 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../interfaces"; import { NotificationService, RequestService, SearchService } from "../services"; -import { IRemainingRequests } from "../interfaces/IRemainingRequests"; @Component({ selector: "movie-search", @@ -20,7 +19,7 @@ export class MovieSearchComponent implements OnInit { public searchChanged: Subject = new Subject(); public movieResults: ISearchMovieResult[]; public result: IRequestEngineResult; - public remaining: IRemainingRequests; + public searchApplied = false; @Input() public issueCategories: IIssueCategory[]; @@ -70,18 +69,8 @@ export class MovieSearchComponent implements OnInit { result: false, errorMessage: "", }; - this.remaining = { - hasLimit: false, - limit: 0, - remaining: 0, - }; this.popularMovies(); - - this.requestService.getRemainingMovieRequests().subscribe(remaining => { - this.remaining = remaining; - }); - } public search(text: any) { diff --git a/src/Ombi/ClientApp/app/search/search.module.ts b/src/Ombi/ClientApp/app/search/search.module.ts index 855207616..c2a309819 100644 --- a/src/Ombi/ClientApp/app/search/search.module.ts +++ b/src/Ombi/ClientApp/app/search/search.module.ts @@ -19,6 +19,7 @@ import { SearchService } from "../services"; import { AuthGuard } from "../auth/auth.guard"; import { SharedModule } from "../shared/shared.module"; +import { RemainingRequestsComponent } from "../requests/remainingrequests.component"; const routes: Routes = [ { path: "", component: SearchComponent, canActivate: [AuthGuard] }, @@ -41,6 +42,7 @@ const routes: Routes = [ TvSearchComponent, SeriesInformationComponent, MovieSearchGridComponent, + RemainingRequestsComponent, ], exports: [ RouterModule, diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index 48e83578d..37453c97d 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -26,15 +26,13 @@
    -
    -
    + + +
    - -
    -
    diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 5345369e7..4434b7839 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -20,6 +20,10 @@ export class RequestService extends ServiceHelpers { return this.http.get(`${this.url}movie/remaining`, {headers: this.headers}); } + public getRemainingTvRequests(): Observable { + return this.http.get(`${this.url}tv/remaining`, {headers: this.headers}); + } + public requestMovie(movie: IMovieRequestModel): Observable { return this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}); } diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index 71d09b2ef..f2412727f 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -470,9 +470,18 @@ namespace Ombi.Controllers /// Gets model containing remaining number of requests. ///
    [HttpGet("movie/remaining")] - public async Task GetRemainingRequests() + public async Task GetRemainingMovieRequests() { return await MovieRequestEngine.GetRemainingRequests(); } + + /// + /// Gets model containing remaining number of requests. + /// + [HttpGet("tv/remaining")] + public async Task GetRemainingTvRequests() + { + return await TvRequestEngine.GetRemainingRequests(); + } } } \ No newline at end of file From 6ebe2deb52c12e16e33ccec1102a46b2ebc0738b Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 00:43:18 +0100 Subject: [PATCH 352/495] Add logic for retriving request information --- src/Ombi.Core/Engine/TvRequestEngine.cs | 29 ++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 80e627ade..da61b018a 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -616,12 +616,35 @@ namespace Ombi.Core.Engine public async Task GetRemainingRequests() { + OmbiUser user = await GetUser(); + int limit = user.EpisodeRequestLimit ?? 0; + + if (limit <= 0) + { + return new RequestQuotaCountModel() + { + HasLimit = false, + Limit = 0, + Remaining = 0, + NextRequest = DateTime.Now, + }; + } + + IQueryable log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.TvShow); + + int count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)); + + DateTime oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)) + .OrderBy(x => x.RequestDate) + .Select(x => x.RequestDate) + .FirstOrDefaultAsync(); + return new RequestQuotaCountModel() { HasLimit = true, - Limit = 5, - Remaining = 4, - NextRequest = DateTime.Parse("2018-08-30T00:00:00+01"), + Limit = limit, + Remaining = count, + NextRequest = oldestRequestedAt.AddDays(7), }; } } From 0e46e66a6d50400e03c409d292de2ba8027923b6 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 00:50:05 +0100 Subject: [PATCH 353/495] Add logic for movie request count --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 31 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index d40c3e7b8..5cea34627 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -487,12 +487,35 @@ namespace Ombi.Core.Engine public async Task GetRemainingRequests() { + OmbiUser user = await GetUser(); + int limit = user.MovieRequestLimit ?? 0; + + if (limit <= 0) + { + return new RequestQuotaCountModel() + { + HasLimit = false, + Limit = 0, + Remaining = 0, + NextRequest = DateTime.Now, + }; + } + + IQueryable log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.Movie); + + int count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)); + + DateTime oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)) + .OrderBy(x => x.RequestDate) + .Select(x => x.RequestDate) + .FirstOrDefaultAsync(); + return new RequestQuotaCountModel() { - HasLimit = false, - Limit = 5, - Remaining = 4, - NextRequest = DateTime.Parse("2018-08-27T00:00:00+01"), + HasLimit = true, + Limit = limit, + Remaining = count, + NextRequest = oldestRequestedAt.AddDays(7), }; } } From b30a2c09501b05c198221768291961649a8a6777 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 01:34:44 +0100 Subject: [PATCH 354/495] Trigger update of request limit on new request --- .../app/requests/remainingrequests.component.ts | 17 +++++++++++++---- .../app/search/moviesearch.component.html | 2 +- .../app/search/moviesearch.component.ts | 6 ++++-- .../app/search/seriesinformation.component.ts | 3 ++- .../app/search/tvsearch.component.html | 2 +- .../ClientApp/app/search/tvsearch.component.ts | 5 ++++- 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index 1279a60e9..39f6ca200 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -21,17 +21,20 @@ export class RemainingRequestsComponent implements OnInit { ngOnInit(): void { var self = this; this.update(); + + setInterval(function(){ + self.calculateTime(); + }, 10000) + setInterval(function(){ self.update() - }, 10000) + }, 60000) } update(): void { var callback = (remaining => { this.remaining = remaining; - this.daysUntil = Math.ceil(this.daysUntilNextRequest()); - this.hoursUntil = Math.ceil(this.hoursUntilNextRequest()); - this.minutesUntil = Math.ceil(this.minutesUntilNextRequest()) + this.calculateTime(); }); if (this.movie) { @@ -41,6 +44,12 @@ export class RemainingRequestsComponent implements OnInit { } } + calculateTime(): void { + this.daysUntil = Math.ceil(this.daysUntilNextRequest()); + this.hoursUntil = Math.ceil(this.hoursUntilNextRequest()); + this.minutesUntil = Math.ceil(this.minutesUntilNextRequest()) + } + daysUntilNextRequest(): number { return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60 / 24; } diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index 2e5a17559..6d8c040ac 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -20,7 +20,7 @@ - +
    diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index afd217089..a6a009962 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -1,5 +1,5 @@ import { PlatformLocation } from "@angular/common"; -import { Component, Input, OnInit } from "@angular/core"; +import { Component, Input, OnInit, ViewChild } from "@angular/core"; import { DomSanitizer } from "@angular/platform-browser"; import { TranslateService } from "@ngx-translate/core"; import { Subject } from "rxjs"; @@ -8,6 +8,7 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../interfaces"; import { NotificationService, RequestService, SearchService } from "../services"; +import { RemainingRequestsComponent } from "../requests/remainingrequests.component"; @Component({ selector: "movie-search", @@ -24,6 +25,7 @@ export class MovieSearchComponent implements OnInit { @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; + @ViewChild('remainingFilms') public remainingRequestsComponent: RemainingRequestsComponent; public issuesBarVisible = false; public issueRequestTitle: string; public issueRequestId: number; @@ -89,7 +91,7 @@ export class MovieSearchComponent implements OnInit { this.requestService.requestMovie({ theMovieDbId: searchResult.id }) .subscribe(x => { this.result = x; - + this.remainingRequestsComponent.update(); if (this.result.result) { this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { this.notificationService.success(x); diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts index cc8701a5b..27cdaf684 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit} from "@angular/core"; +import { Component, Input, OnInit, ViewChild} from "@angular/core"; import { NotificationService } from "../services"; import { RequestService } from "../services"; @@ -7,6 +7,7 @@ import { SearchService } from "../services"; import { INewSeasonRequests, IRequestEngineResult, ISeasonsViewModel, ITvRequestViewModel } from "../interfaces"; import { IEpisodesRequests } from "../interfaces"; import { ISearchTvResult } from "../interfaces"; +import { RemainingRequestsComponent } from "../requests/remainingrequests.component"; @Component({ selector: "seriesinformation", diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index 37453c97d..5f4938cf1 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -27,7 +27,7 @@
    - +
    diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.ts b/src/Ombi/ClientApp/app/search/tvsearch.component.ts index a41f34586..b18b1343a 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.ts @@ -1,5 +1,5 @@ import { PlatformLocation } from "@angular/common"; -import { Component, Input, OnInit } from "@angular/core"; +import { Component, Input, OnInit, ViewChild } from "@angular/core"; import { DomSanitizer } from "@angular/platform-browser"; import { Subject } from "rxjs"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; @@ -7,6 +7,7 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { IIssueCategory, IRequestEngineResult, ISearchTvResult, ISeasonsViewModel, ITvRequestViewModel } from "../interfaces"; import { ImageService, NotificationService, RequestService, SearchService } from "../services"; +import { RemainingRequestsComponent } from "../requests/remainingrequests.component"; @Component({ selector: "tv-search", @@ -24,6 +25,7 @@ export class TvSearchComponent implements OnInit { @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; + @ViewChild('remainingTvShows') public remainingRequestsComponent: RemainingRequestsComponent; public issuesBarVisible = false; public issueRequestTitle: string; public issueRequestId: number; @@ -162,6 +164,7 @@ export class TvSearchComponent implements OnInit { this.requestService.requestTv(viewModel) .subscribe(x => { this.result = x; + this.remainingRequestsComponent.update(); if (this.result.result) { this.notificationService.success( `Request for ${searchResult.title} has been added successfully`); From c5e396a9e846c71fbf1b4dd5dd77b44bcf27f54b Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 14:19:37 +0100 Subject: [PATCH 355/495] Fix issues with remaining count updating --- .../requests/remainingrequests.component.ts | 4 +++ .../app/search/moviesearch.component.ts | 5 +--- .../app/search/seriesinformation.component.ts | 3 +-- .../app/search/tvsearch.component.ts | 5 +--- .../ClientApp/app/services/request.service.ts | 25 ++++++++++++++++--- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index 39f6ca200..9e64b0013 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -22,6 +22,10 @@ export class RemainingRequestsComponent implements OnInit { var self = this; this.update(); + this.requestService.onRequested().subscribe(m => { + this.update(); + }); + setInterval(function(){ self.calculateTime(); }, 10000) diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index a6a009962..965837bae 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -1,5 +1,5 @@ import { PlatformLocation } from "@angular/common"; -import { Component, Input, OnInit, ViewChild } from "@angular/core"; +import { Component, Input, OnInit } from "@angular/core"; import { DomSanitizer } from "@angular/platform-browser"; import { TranslateService } from "@ngx-translate/core"; import { Subject } from "rxjs"; @@ -8,7 +8,6 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { IIssueCategory, IRequestEngineResult, ISearchMovieResult } from "../interfaces"; import { NotificationService, RequestService, SearchService } from "../services"; -import { RemainingRequestsComponent } from "../requests/remainingrequests.component"; @Component({ selector: "movie-search", @@ -25,7 +24,6 @@ export class MovieSearchComponent implements OnInit { @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; - @ViewChild('remainingFilms') public remainingRequestsComponent: RemainingRequestsComponent; public issuesBarVisible = false; public issueRequestTitle: string; public issueRequestId: number; @@ -91,7 +89,6 @@ export class MovieSearchComponent implements OnInit { this.requestService.requestMovie({ theMovieDbId: searchResult.id }) .subscribe(x => { this.result = x; - this.remainingRequestsComponent.update(); if (this.result.result) { this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { this.notificationService.success(x); diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts index 27cdaf684..5c0088268 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit, ViewChild} from "@angular/core"; +import { Component, Input, OnInit } from "@angular/core"; import { NotificationService } from "../services"; import { RequestService } from "../services"; @@ -7,7 +7,6 @@ import { SearchService } from "../services"; import { INewSeasonRequests, IRequestEngineResult, ISeasonsViewModel, ITvRequestViewModel } from "../interfaces"; import { IEpisodesRequests } from "../interfaces"; import { ISearchTvResult } from "../interfaces"; -import { RemainingRequestsComponent } from "../requests/remainingrequests.component"; @Component({ selector: "seriesinformation", diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.ts b/src/Ombi/ClientApp/app/search/tvsearch.component.ts index b18b1343a..a41f34586 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.ts @@ -1,5 +1,5 @@ import { PlatformLocation } from "@angular/common"; -import { Component, Input, OnInit, ViewChild } from "@angular/core"; +import { Component, Input, OnInit } from "@angular/core"; import { DomSanitizer } from "@angular/platform-browser"; import { Subject } from "rxjs"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; @@ -7,7 +7,6 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { IIssueCategory, IRequestEngineResult, ISearchTvResult, ISeasonsViewModel, ITvRequestViewModel } from "../interfaces"; import { ImageService, NotificationService, RequestService, SearchService } from "../services"; -import { RemainingRequestsComponent } from "../requests/remainingrequests.component"; @Component({ selector: "tv-search", @@ -25,7 +24,6 @@ export class TvSearchComponent implements OnInit { @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; - @ViewChild('remainingTvShows') public remainingRequestsComponent: RemainingRequestsComponent; public issuesBarVisible = false; public issueRequestTitle: string; public issueRequestId: number; @@ -164,7 +162,6 @@ export class TvSearchComponent implements OnInit { this.requestService.requestTv(viewModel) .subscribe(x => { this.result = x; - this.remainingRequestsComponent.update(); if (this.result.result) { this.notificationService.success( `Request for ${searchResult.title} has been added successfully`); diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 4434b7839..7940c43d6 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -2,7 +2,7 @@ import { PlatformLocation } from "@angular/common"; import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; -import { Observable } from "rxjs"; +import { Observable, ReplaySubject } from "rxjs"; import { TreeNode } from "primeng/primeng"; import { FilterType, IChildRequests, IFilter, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces"; @@ -12,10 +12,15 @@ import { IRemainingRequests } from "../interfaces/IRemainingRequests"; @Injectable() export class RequestService extends ServiceHelpers { + private requestEvents = new ReplaySubject(); constructor(http: HttpClient, public platformLocation: PlatformLocation) { super(http, "/api/v1/Request/", platformLocation); } + public onRequested(): Observable { + return this.requestEvents.asObservable(); + } + public getRemainingMovieRequests(): Observable { return this.http.get(`${this.url}movie/remaining`, {headers: this.headers}); } @@ -25,7 +30,14 @@ export class RequestService extends ServiceHelpers { } public requestMovie(movie: IMovieRequestModel): Observable { - return this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}); + var observer = Observable.create(observer => { + this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}).subscribe(m => { + observer.next(m); + this.requestEvents.next(m); + }); + }); + + return observer; } public getTotalMovies(): Observable { @@ -37,7 +49,14 @@ export class RequestService extends ServiceHelpers { } public requestTv(tv: ITvRequestViewModel): Observable { - return this.http.post(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers}); + var observer = Observable.create(observer => { + return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }).subscribe(m => { + observer.next(m); + this.requestEvents.next(m); + }); + }); + + return observer; } public approveMovie(movie: IMovieUpdateModel): Observable { From b7e5e3dfb4b1fc1d727a16b06565e3138b2ca44c Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 17:34:00 +0100 Subject: [PATCH 356/495] Fix bug with TV requests in which requesting a seasion would treat request as single episode --- src/Ombi.Core/Engine/TvRequestEngine.cs | 8 +++++++- src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs | 9 +++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index da61b018a..939b0fe3e 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -609,6 +609,7 @@ namespace Ombi.Core.Engine RequestDate = DateTime.UtcNow, RequestId = model.Id, RequestType = RequestType.TvShow, + EpisodeCount = model.SeasonRequests.Select(m => m.Episodes.Count).Sum(), }); return new RequestEngineResult { Result = true }; @@ -632,7 +633,12 @@ namespace Ombi.Core.Engine IQueryable log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.TvShow); - int count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)); + // Needed, due to a bug which would cause all episode counts to be 0 + int zeroEpisodeCount = await log.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync(); + + int episodeCount = await log.Where(x => x.EpisodeCount != 0).Select(x => x.EpisodeCount).SumAsync(); + + int count = limit - (zeroEpisodeCount + episodeCount); DateTime oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)) .OrderBy(x => x.RequestDate) diff --git a/src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs b/src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs index a19ac1df8..4d5fcf8e2 100644 --- a/src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs @@ -88,8 +88,13 @@ namespace Ombi.Core.Rule.Rules.Request // Count how many requests in the past 7 days var tv = tvLogs.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)); - var count = await tv.Select(x => x.EpisodeCount).CountAsync(); - count += requestCount; // Add the amount of requests in + + // Needed, due to a bug which would cause all episode counts to be 0 + var zeroEpisodeCount = await tv.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync(); + + var episodeCount = await tv.Where(x => x.EpisodeCount != 0).Select(x => x.EpisodeCount).SumAsync(); + + var count = requestCount + episodeCount + zeroEpisodeCount; // Add the amount of requests in if (count > episodeLimit) { return Fail("You have exceeded your Episode request quota!"); From 0b620e9ad4000db5d903544248dad05944f8a12c Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 17:42:28 +0100 Subject: [PATCH 357/495] Fix bug when submitting requests for multiple episodes accross multiple seasons --- src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs b/src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs index 4d5fcf8e2..64cd6c076 100644 --- a/src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/RequestLimitRule.cs @@ -81,7 +81,7 @@ namespace Ombi.Core.Rule.Rules.Request // Get the count of requests to be made foreach (var s in child.SeasonRequests) { - requestCount = s.Episodes.Count; + requestCount += s.Episodes.Count; } var tvLogs = requestLog.Where(x => x.RequestType == RequestType.TvShow); From 62416e3538b7f170a3a491bc78283c2c00fbdd57 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 18:49:33 +0100 Subject: [PATCH 358/495] Remove local vscode files --- .vscode/launch.json | 46 --------------------------------------------- .vscode/tasks.json | 15 --------------- 2 files changed, 61 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 3e98c769e..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "version": "0.2.0", - "configurations": [ - { - "name": ".NET Core Launch (web)", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/src/Ombi/bin/Debug/netcoreapp2.1/Ombi.dll", - "args": [], - "cwd": "${workspaceFolder}/src/Ombi", - "stopAtEntry": false, - "internalConsoleOptions": "openOnSessionStart", - "launchBrowser": { - "enabled": false, - "args": "${auto-detect-url}", - "windows": { - "command": "cmd.exe", - "args": "/C start ${auto-detect-url}" - }, - "osx": { - "command": "open" - }, - "linux": { - "command": "xdg-open" - } - }, - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "sourceFileMap": { - "/Views": "${workspaceFolder}/Views" - } - }, - { - "name": ".NET Core Attach", - "type": "coreclr", - "request": "attach", - "processId": "${command:pickProcess}" - } - ,] -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index af3542206..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "${workspaceFolder}/src/Ombi/Ombi.csproj" - ], - "problemMatcher": "$msCompile" - } - ] -} \ No newline at end of file From d12e46b45103991370a46decd80796e0a59bc7ac Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 18:53:08 +0100 Subject: [PATCH 359/495] Remove unused methods from SearchController --- src/Ombi/Controllers/SearchController.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Ombi/Controllers/SearchController.cs b/src/Ombi/Controllers/SearchController.cs index 65e9f930b..0c3c33244 100644 --- a/src/Ombi/Controllers/SearchController.cs +++ b/src/Ombi/Controllers/SearchController.cs @@ -183,17 +183,5 @@ namespace Ombi.Controllers { return await TvEngine.Trending(); } - - [HttpGet("movie/requestCount")] - public async Task RemainingMovieRequests() - { - return null; - } - - [HttpGet("tv/requestCount")] - public async Task RemainingTvRequests() - { - return null; - } } } From c6bb864be758b6f92baa0005bbc3650c8a5be513 Mon Sep 17 00:00:00 2001 From: David Pooley Date: Sun, 26 Aug 2018 20:57:39 +0100 Subject: [PATCH 360/495] Allow for the ability to set Pushover notification sound and priority from within Ombi. --- src/Ombi.Api.Pushover/IPushoverApi.cs | 2 +- src/Ombi.Api.Pushover/PushoverApi.cs | 4 +- .../Agents/PushoverNotification.cs | 2 +- .../Models/Notifications/PushoverSettings.cs | 2 + .../app/interfaces/INotificationSettings.ts | 2 + .../notifications/pushover.component.html | 42 +++++++++++++++++++ .../notifications/pushover.component.ts | 2 + 7 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Api.Pushover/IPushoverApi.cs b/src/Ombi.Api.Pushover/IPushoverApi.cs index 42e8e9060..554a15b60 100644 --- a/src/Ombi.Api.Pushover/IPushoverApi.cs +++ b/src/Ombi.Api.Pushover/IPushoverApi.cs @@ -5,6 +5,6 @@ namespace Ombi.Api.Pushover { public interface IPushoverApi { - Task PushAsync(string accessToken, string message, string userToken); + Task PushAsync(string accessToken, string message, string userToken, sbyte priority, string sound); } } \ No newline at end of file diff --git a/src/Ombi.Api.Pushover/PushoverApi.cs b/src/Ombi.Api.Pushover/PushoverApi.cs index fd6ca23ea..9f91bc7ca 100644 --- a/src/Ombi.Api.Pushover/PushoverApi.cs +++ b/src/Ombi.Api.Pushover/PushoverApi.cs @@ -16,13 +16,13 @@ namespace Ombi.Api.Pushover private readonly IApi _api; private const string PushoverEndpoint = "https://api.pushover.net/1"; - public async Task PushAsync(string accessToken, string message, string userToken) + public async Task PushAsync(string accessToken, string message, string userToken, sbyte priority, string sound) { if (message.Contains("'")) { message = message.Replace("'", "'"); } - var request = new Request($"messages.json?token={accessToken}&user={userToken}&message={WebUtility.HtmlEncode(message)}", PushoverEndpoint, HttpMethod.Post); + var request = new Request($"messages.json?token={accessToken}&user={userToken}&priority={priority}&sound={sound}&message={WebUtility.HtmlEncode(message)}", PushoverEndpoint, HttpMethod.Post); var result = await _api.Request(request); return result; diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs index 5b82eb8a3..2719c3861 100644 --- a/src/Ombi.Notifications/Agents/PushoverNotification.cs +++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs @@ -177,7 +177,7 @@ namespace Ombi.Notifications.Agents { try { - await Api.PushAsync(settings.AccessToken, model.Message, settings.UserToken); + await Api.PushAsync(settings.AccessToken, model.Message, settings.UserToken, settings.Priority, settings.Sound); } catch (Exception e) { diff --git a/src/Ombi.Settings/Settings/Models/Notifications/PushoverSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/PushoverSettings.cs index d845e8695..3e65d628d 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/PushoverSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/PushoverSettings.cs @@ -8,5 +8,7 @@ namespace Ombi.Settings.Settings.Models.Notifications public bool Enabled { get; set; } public string AccessToken { get; set; } public string UserToken { get; set; } + public sbyte Priority { get; set; } + public string Sound { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts index 8c5fcd5bc..fc8b89f1e 100644 --- a/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/INotificationSettings.ts @@ -88,6 +88,8 @@ export interface IPushoverNotificationSettings extends INotificationSettings { accessToken: string; notificationTemplates: INotificationTemplates[]; userToken: string; + priority: number; + sound: string; } export interface IMattermostNotifcationSettings extends INotificationSettings { diff --git a/src/Ombi/ClientApp/app/settings/notifications/pushover.component.html b/src/Ombi/ClientApp/app/settings/notifications/pushover.component.html index b56467c9f..499263dec 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/pushover.component.html +++ b/src/Ombi/ClientApp/app/settings/notifications/pushover.component.html @@ -28,6 +28,48 @@
    +
    + +
    + +
    +
    + +
    + +
    + +
    +
    +
    diff --git a/src/Ombi/ClientApp/app/settings/notifications/pushover.component.ts b/src/Ombi/ClientApp/app/settings/notifications/pushover.component.ts index 5d208568c..64f339192 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/pushover.component.ts +++ b/src/Ombi/ClientApp/app/settings/notifications/pushover.component.ts @@ -27,6 +27,8 @@ export class PushoverComponent implements OnInit { enabled: [x.enabled], userToken: [x.userToken], accessToken: [x.accessToken, [Validators.required]], + priority: [x.priority], + sound: [x.sound], }); }); } From e770d321eb2b319f2e93215e2d04c98e18ab47a4 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sun, 26 Aug 2018 21:02:23 +0100 Subject: [PATCH 361/495] Fix lint errors --- .../app/interfaces/IRemainingRequests.ts | 2 +- .../app/requests/movierequests.component.ts | 2 +- .../requests/remainingrequests.component.ts | 39 ++++++++++--------- .../ClientApp/app/search/search.module.ts | 2 +- .../ClientApp/app/services/request.service.ts | 5 ++- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts b/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts index ce1b37427..a6ff1a66c 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRemainingRequests.ts @@ -3,4 +3,4 @@ export interface IRemainingRequests { limit: number; remaining: number; nextRequest: Date; -} \ No newline at end of file +} diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 9495f0790..651637308 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -6,8 +6,8 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; -import { NotificationService, RadarrService, RequestService } from "../services"; import { IRemainingRequests } from "../interfaces/IRemainingRequests"; +import { NotificationService, RadarrService, RequestService } from "../services"; @Component({ selector: "movie-requests", diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index 9e64b0013..4f4439c13 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -1,6 +1,7 @@ -import { Component, OnInit, Input } from "@angular/core"; +import { IRemainingRequests } from "../interfaces/IRemainingRequests"; import { RequestService } from "../services"; -import { IRemainingRequests } from "../interfaces/IRemainingRequests"; + +import { Component, Input, OnInit } from "@angular/core"; @Component({ selector: "remaining-requests", @@ -14,29 +15,29 @@ export class RemainingRequestsComponent implements OnInit { public hoursUntil: number; public minutesUntil: number; - constructor(private requestService: RequestService) - { + constructor(private requestService: RequestService) { } - ngOnInit(): void { - var self = this; + public ngOnInit() { + const self = this; + this.update(); this.requestService.onRequested().subscribe(m => { this.update(); }); - setInterval(function(){ + setInterval(() => { self.calculateTime(); - }, 10000) + }, 10000); - setInterval(function(){ - self.update() - }, 60000) + setInterval(() => { + self.update(); + }, 60000); } - update(): void { - var callback = (remaining => { + public update(): void { + const callback = (remaining => { this.remaining = remaining; this.calculateTime(); }); @@ -48,21 +49,21 @@ export class RemainingRequestsComponent implements OnInit { } } - calculateTime(): void { + private calculateTime(): void { this.daysUntil = Math.ceil(this.daysUntilNextRequest()); this.hoursUntil = Math.ceil(this.hoursUntilNextRequest()); - this.minutesUntil = Math.ceil(this.minutesUntilNextRequest()) + this.minutesUntil = Math.ceil(this.minutesUntilNextRequest()); } - daysUntilNextRequest(): number { + private daysUntilNextRequest(): number { return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60 / 24; } - hoursUntilNextRequest(): number { + private hoursUntilNextRequest(): number { return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60 / 60; } - minutesUntilNextRequest(): number { + private minutesUntilNextRequest(): number { return (new Date(this.remaining.nextRequest).getTime() - new Date().getTime()) / 1000 / 60; } -} \ No newline at end of file +} diff --git a/src/Ombi/ClientApp/app/search/search.module.ts b/src/Ombi/ClientApp/app/search/search.module.ts index c2a309819..75c2de5d9 100644 --- a/src/Ombi/ClientApp/app/search/search.module.ts +++ b/src/Ombi/ClientApp/app/search/search.module.ts @@ -18,8 +18,8 @@ import { SearchService } from "../services"; import { AuthGuard } from "../auth/auth.guard"; -import { SharedModule } from "../shared/shared.module"; import { RemainingRequestsComponent } from "../requests/remainingrequests.component"; +import { SharedModule } from "../shared/shared.module"; const routes: Routes = [ { path: "", component: SearchComponent, canActivate: [AuthGuard] }, diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 7940c43d6..a7fbc76bf 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -8,6 +8,7 @@ import { TreeNode } from "primeng/primeng"; import { FilterType, IChildRequests, IFilter, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces"; import { ITvRequestViewModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; + import { IRemainingRequests } from "../interfaces/IRemainingRequests"; @Injectable() @@ -30,7 +31,7 @@ export class RequestService extends ServiceHelpers { } public requestMovie(movie: IMovieRequestModel): Observable { - var observer = Observable.create(observer => { + const observer = Observable.create(observer => { this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}).subscribe(m => { observer.next(m); this.requestEvents.next(m); @@ -49,7 +50,7 @@ export class RequestService extends ServiceHelpers { } public requestTv(tv: ITvRequestViewModel): Observable { - var observer = Observable.create(observer => { + const observer = Observable.create(observer => { return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }).subscribe(m => { observer.next(m); this.requestEvents.next(m); From 067ffae3031601cc8018c880c49a9bc87baeaccf Mon Sep 17 00:00:00 2001 From: David Pooley Date: Sun, 26 Aug 2018 22:48:46 +0100 Subject: [PATCH 362/495] Add default values for Priority and Sound. --- .../Settings/Models/Notifications/PushoverSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Settings/Settings/Models/Notifications/PushoverSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/PushoverSettings.cs index 3e65d628d..9c3dfc350 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/PushoverSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/PushoverSettings.cs @@ -8,7 +8,7 @@ namespace Ombi.Settings.Settings.Models.Notifications public bool Enabled { get; set; } public string AccessToken { get; set; } public string UserToken { get; set; } - public sbyte Priority { get; set; } - public string Sound { get; set; } + public sbyte Priority { get; set; } = 0; + public string Sound { get; set; } = "pushover"; } } \ No newline at end of file From b72905ab4aecc1af30d124806bfad240db3fa3f3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 26 Aug 2018 23:12:21 +0100 Subject: [PATCH 363/495] Got most of the requesting stuff done! !wip #2313 --- src/Ombi.Api.Lidarr/ILidarrApi.cs | 5 + src/Ombi.Api.Lidarr/LidarrApi.cs | 46 ++- src/Ombi.Api.Lidarr/Models/ArtistAdd.cs | 48 +++ .../Models/LanguageProfiles.cs | 8 + src/Ombi.Api.Lidarr/Models/MetadataProfile.cs | 8 + src/Ombi.Core/Engine/MusicRequestEngine.cs | 46 +-- src/Ombi.Core/Senders/IMusicSender.cs | 10 + src/Ombi.Core/Senders/MusicSender.cs | 110 ++++++ src/Ombi.DependencyInjection/IocExtensions.cs | 1 + src/Ombi.Helpers/StringHelper.cs | 5 + .../Models/External/LidarrSettings.cs | 3 + src/Ombi/ClientApp/app/interfaces/IRadarr.ts | 5 + .../ClientApp/app/interfaces/IRequestModel.ts | 3 +- .../ClientApp/app/interfaces/ISettings.ts | 3 + .../music/musicrequests.component.html | 270 ++++++++++++++ .../requests/music/musicrequests.component.ts | 350 ++++++++++++++++++ .../app/requests/request.component.html | 7 + .../app/requests/request.component.ts | 9 + .../ClientApp/app/requests/requests.module.ts | 3 +- .../services/applications/lidarr.service.ts | 9 +- .../ClientApp/app/services/request.service.ts | 4 +- .../app/settings/lidarr/lidarr.component.html | 49 ++- .../app/settings/lidarr/lidarr.component.ts | 77 +++- src/Ombi/ClientApp/styles/base.scss | 21 ++ .../Controllers/External/LidarrController.cs | 21 ++ src/Ombi/wwwroot/translations/en.json | 1 + 26 files changed, 1061 insertions(+), 61 deletions(-) create mode 100644 src/Ombi.Api.Lidarr/Models/ArtistAdd.cs create mode 100644 src/Ombi.Api.Lidarr/Models/LanguageProfiles.cs create mode 100644 src/Ombi.Api.Lidarr/Models/MetadataProfile.cs create mode 100644 src/Ombi.Core/Senders/IMusicSender.cs create mode 100644 src/Ombi.Core/Senders/MusicSender.cs create mode 100644 src/Ombi/ClientApp/app/requests/music/musicrequests.component.html create mode 100644 src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs index d66f9716c..38724f668 100644 --- a/src/Ombi.Api.Lidarr/ILidarrApi.cs +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -16,5 +16,10 @@ namespace Ombi.Api.Lidarr Task GetAlbumByForeignId(string foreignArtistId, string apiKey, string baseUrl); Task> GetArtists(string apiKey, string baseUrl); Task> GetAllAlbums(string apiKey, string baseUrl); + Task AddArtist(ArtistAdd artist, string apiKey, string baseUrl); + Task MontiorAlbum(int albumId, string apiKey, string baseUrl); + Task> GetAllAlbumsByArtistId(int artistId, string apiKey, string baseUrl); + Task> GetMetadataProfile(string apiKey, string baseUrl); + Task> GetLanguageProfile(string apiKey, string baseUrl); } } \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index 84e0d090a..572a2b55c 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -63,13 +63,13 @@ namespace Ombi.Api.Lidarr return Api.Request(request); } - public Task GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl) + public async Task GetArtistByForeignId(string foreignArtistId, string apiKey, string baseUrl) { var request = new Request($"{ApiVersion}/artist/lookup", baseUrl, HttpMethod.Get); request.AddQueryString("term", $"lidarr:{foreignArtistId}"); AddHeaders(request, apiKey); - return Api.Request(request); + return (await Api.Request>(request)).FirstOrDefault(); } public async Task GetAlbumByForeignId(string foreignArtistId, string apiKey, string baseUrl) @@ -105,6 +105,48 @@ namespace Ombi.Api.Lidarr return Api.Request>(request); } + public Task AddArtist(ArtistAdd artist, string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/artist", baseUrl, HttpMethod.Post); + request.AddJsonBody(artist); + AddHeaders(request, apiKey); + return Api.Request(request); + } + + public Task MontiorAlbum(int albumId, string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/album/monitor", baseUrl, HttpMethod.Put); + request.AddJsonBody(new + { + albumIds = new[] { albumId }, + monitored = true + }); + AddHeaders(request, apiKey); + return Api.Request(request); + } + + public Task> GetAllAlbumsByArtistId(int artistId, string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/album", baseUrl, HttpMethod.Get); + request.AddQueryString("artistId", artistId.ToString()); + AddHeaders(request, apiKey); + return Api.Request>(request); + } + + public Task> GetLanguageProfile(string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/languageprofile", baseUrl, HttpMethod.Get); + AddHeaders(request, apiKey); + return Api.Request>(request); + } + + public Task> GetMetadataProfile(string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/metadataprofile", baseUrl, HttpMethod.Get); + AddHeaders(request, apiKey); + return Api.Request>(request); + } + private void AddHeaders(Request request, string key) { request.AddHeader("X-Api-Key", key); diff --git a/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs b/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs new file mode 100644 index 000000000..e77a239e6 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs @@ -0,0 +1,48 @@ +using System; +using System.Net.Mime; + +namespace Ombi.Api.Lidarr.Models +{ + public class ArtistAdd + { + public string status { get; set; } + public bool ended { get; set; } + public string artistName { get; set; } + public string foreignArtistId { get; set; } + public int tadbId { get; set; } + public int discogsId { get; set; } + public string overview { get; set; } + public string disambiguation { get; set; } + public Link[] links { get; set; } + public Image[] images { get; set; } + public string remotePoster { get; set; } + public int qualityProfileId { get; set; } + public int languageProfileId { get; set; } + public int metadataProfileId { get; set; } + public bool albumFolder { get; set; } + public bool monitored { get; set; } + public string cleanName { get; set; } + public string sortName { get; set; } + public object[] tags { get; set; } + public DateTime added { get; set; } + public Ratings ratings { get; set; } + public Statistics statistics { get; set; } + public Addoptions addOptions { get; set; } + public string rootFolderPath { get; set; } + } + + public class Addoptions + { + /// + /// Future = 1 + /// Missing = 2 + /// Existing = 3 + /// First = 5 + /// Latest = 4 + /// None = 6 + /// + public int selectedOption { get; set; } + public bool monitored { get; set; } + public bool searchForMissingAlbums { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/LanguageProfiles.cs b/src/Ombi.Api.Lidarr/Models/LanguageProfiles.cs new file mode 100644 index 000000000..f503fe33f --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/LanguageProfiles.cs @@ -0,0 +1,8 @@ +namespace Ombi.Api.Lidarr.Models +{ + public class LanguageProfiles + { + public string name { get; set; } + public int id { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/Models/MetadataProfile.cs b/src/Ombi.Api.Lidarr/Models/MetadataProfile.cs new file mode 100644 index 000000000..bda3333f1 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/MetadataProfile.cs @@ -0,0 +1,8 @@ +namespace Ombi.Api.Lidarr.Models +{ + public class MetadataProfile + { + public string name { get; set; } + public int id { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index bcf9e8c02..a27b17c38 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -15,6 +15,7 @@ using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.UI; using Ombi.Core.Rule.Interfaces; +using Ombi.Core.Senders; using Ombi.Core.Settings; using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models.External; @@ -29,11 +30,11 @@ namespace Ombi.Core.Engine INotificationHelper helper, IRuleEvaluator r, ILogger log, OmbiUserManager manager, IRepository rl, ICacheService cache, ISettingsService ombiSettings, IRepository sub, ILidarrApi lidarr, - ISettingsService lidarrSettings) + ISettingsService lidarrSettings, IMusicSender sender) : base(user, requestService, r, manager, cache, ombiSettings, sub) { NotificationHelper = helper; - //Sender = sender; + _musicSender = sender; Logger = log; _requestLog = rl; _lidarrApi = lidarr; @@ -46,6 +47,7 @@ namespace Ombi.Core.Engine private readonly IRepository _requestLog; private readonly ISettingsService _lidarrSettings; private readonly ILidarrApi _lidarrApi; + private readonly IMusicSender _musicSender; /// /// Requests the Album. @@ -79,7 +81,8 @@ namespace Ombi.Core.Engine RequestedUserId = userDetails.Id, Title = album.title, Disk = album.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url, - Cover = album.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url + Cover = album.images?.FirstOrDefault(x => x.coverType.Equals("cover"))?.url, + ForeignArtistId = album?.artist?.foreignArtistId ?? string.Empty }; if (requestModel.Cover.IsNullOrEmpty()) { @@ -341,26 +344,25 @@ namespace Ombi.Core.Engine if (request.Approved) { - //TODO - //var result = await Sender.Send(request); - //if (result.Success && result.Sent) - //{ - // return new RequestEngineResult - // { - // Result = true - // }; - //} + var result = await _musicSender.Send(request); + if (result.Success && result.Sent) + { + return new RequestEngineResult + { + Result = true + }; + } - //if (!result.Success) - //{ - // Logger.LogWarning("Tried auto sending movie but failed. Message: {0}", result.Message); - // return new RequestEngineResult - // { - // Message = result.Message, - // ErrorMessage = result.Message, - // Result = false - // }; - //} + if (!result.Success) + { + Logger.LogWarning("Tried auto sending album but failed. Message: {0}", result.Message); + return new RequestEngineResult + { + Message = result.Message, + ErrorMessage = result.Message, + Result = false + }; + } // If there are no providers then it's successful but movie has not been sent } diff --git a/src/Ombi.Core/Senders/IMusicSender.cs b/src/Ombi.Core/Senders/IMusicSender.cs new file mode 100644 index 000000000..abeec5c29 --- /dev/null +++ b/src/Ombi.Core/Senders/IMusicSender.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using Ombi.Store.Entities.Requests; + +namespace Ombi.Core.Senders +{ + public interface IMusicSender + { + Task Send(AlbumRequest model); + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs new file mode 100644 index 000000000..3baa26003 --- /dev/null +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -0,0 +1,110 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Api.Lidarr; +using Ombi.Api.Lidarr.Models; +using Ombi.Api.Radarr; +using Ombi.Core.Settings; +using Ombi.Helpers; +using Ombi.Settings.Settings.Models.External; +using Ombi.Store.Entities.Requests; +using Serilog; + +namespace Ombi.Core.Senders +{ + public class MusicSender : IMusicSender + { + public MusicSender(ISettingsService lidarr, ILidarrApi lidarrApi) + { + _lidarrSettings = lidarr; + _lidarrApi = lidarrApi; + } + + private readonly ISettingsService _lidarrSettings; + private readonly ILidarrApi _lidarrApi; + + public async Task Send(AlbumRequest model) + { + var settings = await _lidarrSettings.GetSettingsAsync(); + if (settings.Enabled) + { + return await SendToLidarr(model, settings); + } + + return new SenderResult { Success = false, Sent = false, Message = "Lidarr is not enabled" }; + } + + private async Task SendToLidarr(AlbumRequest model, LidarrSettings settings) + { + var qualityToUse = int.Parse(settings.DefaultQualityProfile); + //if (model.QualityOverride > 0) + //{ + // qualityToUse = model.QualityOverride; + //} + + var rootFolderPath = /*model.RootPathOverride <= 0 ?*/ settings.DefaultRootPath /*: await RadarrRootPath(model.RootPathOverride, settings)*/; + + // Need to get the artist + var artist = await _lidarrApi.GetArtistByForeignId(model.ForeignArtistId, settings.ApiKey, settings.FullUri); + + if (artist == null || artist.id <= 0) + { + // Create artist + var newArtist = new ArtistAdd + { + foreignArtistId = model.ForeignArtistId, + addOptions = new Addoptions + { + monitored = true, + searchForMissingAlbums = false, + selectedOption = 6 // None + }, + added = DateTime.Now, + monitored = true, + albumFolder = settings.AlbumFolder, + artistName = model.ArtistName, + cleanName = model.ArtistName.ToLowerInvariant().RemoveSpaces(), + images = new Image[] { }, + languageProfileId = settings.LanguageProfileId, + links = new Link[] {}, + metadataProfileId = settings.MetadataProfileId, + qualityProfileId = qualityToUse, + rootFolderPath = rootFolderPath, + }; + + var result = await _lidarrApi.AddArtist(newArtist, settings.ApiKey, settings.FullUri); + if (result != null && result.id > 0) + { + // Setup the albums + await SetupAlbum(model, result, settings); + } + } + else + { + await SetupAlbum(model, artist, settings); + } + + return new SenderResult { Success = false, Sent = false, Message = "Album is already monitored" }; + } + + private async Task SetupAlbum(AlbumRequest model, ArtistResult artist, LidarrSettings settings) + { + // Get the album id + var albums = await _lidarrApi.GetAllAlbumsByArtistId(artist.id, settings.ApiKey, settings.FullUri); + // Get the album we want. + var album = albums.FirstOrDefault(x => + x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + if (album == null) + { + return new SenderResult { Message = "Could not find album in Lidarr", Sent = false, Success = false }; + } + + var result = await _lidarrApi.MontiorAlbum(album.id, settings.ApiKey, settings.FullUri); + if (result.monitored) + { + return new SenderResult {Message = "Album has been requested!", Sent = true, Success = true}; + } + return new SenderResult { Message = "Could not set album to monitored", Sent = false, Success = false }; + } + } +} \ No newline at end of file diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index c4b291936..334b94675 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -88,6 +88,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); } diff --git a/src/Ombi.Helpers/StringHelper.cs b/src/Ombi.Helpers/StringHelper.cs index aba120c65..fe26d0751 100644 --- a/src/Ombi.Helpers/StringHelper.cs +++ b/src/Ombi.Helpers/StringHelper.cs @@ -75,5 +75,10 @@ namespace Ombi.Helpers return -1; } + + public static string RemoveSpaces(this string str) + { + return str.Replace(" ", ""); + } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs index 560a6e2d2..e0bdbdc43 100644 --- a/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs @@ -8,5 +8,8 @@ namespace Ombi.Settings.Settings.Models.External public string ApiKey { get; set; } public string DefaultQualityProfile { get; set; } public string DefaultRootPath { get; set; } + public bool AlbumFolder { get; set; } + public int LanguageProfileId { get; set; } + public int MetadataProfileId { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/IRadarr.ts b/src/Ombi/ClientApp/app/interfaces/IRadarr.ts index ebc92507c..b643993f4 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRadarr.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRadarr.ts @@ -8,6 +8,11 @@ export interface IRadarrProfile { id: number; } +export interface IProfiles { + name: string; + id: number; +} + export interface IMinimumAvailability { value: string; name: string; diff --git a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts index 736f60aa2..f7fe3df87 100644 --- a/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/app/interfaces/IRequestModel.ts @@ -23,13 +23,14 @@ export interface IMovieRequests extends IFullBaseRequest { export interface IAlbumRequest extends IBaseRequest { foreignAlbumId: string; foreignArtistId: string; - Disk: string; + disk: string; cover: string; releaseDate: Date; artistName: string; subscribed: boolean; showSubscribe: boolean; + background: any; } export interface IAlbumRequestModel { diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 202dbf2c2..2fb46a2b7 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -90,6 +90,9 @@ export interface ILidarrSettings extends IExternalSettings { defaultQualityProfile: string; defaultRootPath: string; fullRootPath: string; + metadataProfileId: number; + languageProfileId: number; + albumFolder: boolean; } export interface ILandingPageSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html new file mode 100644 index 000000000..221d829a0 --- /dev/null +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -0,0 +1,270 @@ + +
    + + +
    +
    +
    +
    +
    + +
    + poster +
    + + +
    + + +
    +
    + {{ 'Requests.RequestedBy' | translate }} + {{request.requestedUser.userName}} + {{request.requestedUser.alias}} + {{request.requestedUser.userName}} +
    +
    + {{ 'Requests.Status' | translate }} + {{request.status}} +
    + +
    + {{ 'Requests.RequestStatus' | translate }} + + + + + + + + +
    +
    + {{ 'Requests.Denied' | translate }} + + +
    + + +
    {{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate | date: 'mediumDate'} }}
    +
    {{ 'Requests.DigitalRelease' | translate: {date: request.digitalReleaseDate | date: 'mediumDate'} }}
    +
    {{ 'Requests.RequestDate' | translate }} {{request.requestedDate | date}}
    +
    +
    +
    +
    {{ 'Requests.QualityOverride' | translate }} + {{request.qualityOverrideTitle}} +
    +
    {{ 'Requests.RootFolderOverride' | translate }} + {{request.rootPathOverrideTitle}} +
    +
    + +
    +
    + +
    +
    +
    + + + + + + + + + +
    + +
    +
    +
    + + + +
    + + + + + + +
    + + +
    +
    +
    +
    + + + + +
    + + +
    + + + + + + +

    {{ 'Requests.Filter' | translate }}

    +
    +
    +

    {{ 'Filter.FilterHeaderAvailability' | translate }}

    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +

    {{ 'Filter.FilterHeaderRequestStatus' | translate }}

    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    + + +
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts new file mode 100644 index 000000000..f004b4019 --- /dev/null +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts @@ -0,0 +1,350 @@ +import { PlatformLocation } from "@angular/common"; +import { Component, Input, OnInit } from "@angular/core"; +import { DomSanitizer } from "@angular/platform-browser"; +import { Subject } from "rxjs"; +import { debounceTime, distinctUntilChanged } from "rxjs/operators"; + +import { AuthService } from "../../auth/auth.service"; +import { FilterType, IAlbumRequest, IFilter, IIssueCategory, IPagenator, OrderType } from "../../interfaces"; +import { NotificationService, RequestService } from "../../services"; + +@Component({ + selector: "music-requests", + templateUrl: "./musicrequests.component.html", +}) +export class MusicRequestsComponent implements OnInit { + public albumRequests: IAlbumRequest[]; + public defaultPoster: string; + + public searchChanged: Subject = new Subject(); + public searchText: string; + + public isAdmin: boolean; // Also PowerUser + + @Input() public issueCategories: IIssueCategory[]; + @Input() public issuesEnabled: boolean; + public issuesBarVisible = false; + public issueRequest: IAlbumRequest; + public issueProviderId: string; + public issueCategorySelected: IIssueCategory; + + public filterDisplay: boolean; + public filter: IFilter; + public filterType = FilterType; + + public orderType: OrderType = OrderType.RequestedDateDesc; + public OrderType = OrderType; + + public totalAlbums: number = 100; + private currentlyLoaded: number; + private amountToLoad: number; + + constructor( + private requestService: RequestService, + private auth: AuthService, + private notificationService: NotificationService, + private sanitizer: DomSanitizer, + private readonly platformLocation: PlatformLocation) { + this.searchChanged.pipe( + debounceTime(600), // Wait Xms after the last event before emitting last event + distinctUntilChanged(), // only emit if value is different from previous value + ).subscribe(x => { + this.searchText = x as string; + if (this.searchText === "") { + this.resetSearch(); + return; + } + this.requestService.searchAlbumRequests(this.searchText) + .subscribe(m => { + this.setOverrides(m); + this.albumRequests = m; + }); + }); + this.defaultPoster = "../../../images/default-music-placeholder.png"; + const base = this.platformLocation.getBaseHrefFromDOM(); + if (base) { + this.defaultPoster = "../../.." + base + "/images/default-music-placeholder.png"; + } + } + + public ngOnInit() { + this.amountToLoad = 10; + this.currentlyLoaded = 10; + this.filter = { + availabilityFilter: FilterType.None, + statusFilter: FilterType.None, + }; + this.loadInit(); + this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser"); + } + + public paginate(event: IPagenator) { + const skipAmount = event.first; + this.loadRequests(this.amountToLoad, skipAmount); + } + + public search(text: any) { + this.searchChanged.next(text.target.value); + } + + public removeRequest(request: IAlbumRequest) { + this.requestService.removeAlbumRequest(request); + this.removeRequestFromUi(request); + this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); + } + + public changeAvailability(request: IAlbumRequest, available: boolean) { + request.available = available; + + if (available) { + this.requestService.markAlbumAvailable({ id: request.id }).subscribe(x => { + if (x.result) { + this.notificationService.success( + `${request.title} Is now available`); + } else { + this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); + request.approved = false; + } + }); + } else { + this.requestService.markAlbumUnavailable({ id: request.id }).subscribe(x => { + if (x.result) { + this.notificationService.success( + `${request.title} Is now unavailable`); + } else { + this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage); + request.approved = false; + } + }); + } + } + + public approve(request: IAlbumRequest) { + request.approved = true; + this.approveRequest(request); + } + + public deny(request: IAlbumRequest) { + request.denied = true; + this.denyRequest(request); + } + + // public selectRootFolder(searchResult: IAlbumRequest, rootFolderSelected: IRadarrRootFolder, event: any) { + // event.preventDefault(); + // // searchResult.rootPathOverride = rootFolderSelected.id; + // this.setOverride(searchResult); + // this.updateRequest(searchResult); + // } + + // public selectQualityProfile(searchResult: IMovieRequests, profileSelected: IRadarrProfile, event: any) { + // event.preventDefault(); + // searchResult.qualityOverride = profileSelected.id; + // this.setOverride(searchResult); + // this.updateRequest(searchResult); + // } + + public reportIssue(catId: IIssueCategory, req: IAlbumRequest) { + this.issueRequest = req; + this.issueCategorySelected = catId; + this.issuesBarVisible = true; + this.issueProviderId = req.foreignAlbumId; + } + + public ignore(event: any): void { + event.preventDefault(); + } + + public clearFilter(el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + el = el.parentElement; + el = el.querySelectorAll("INPUT"); + for (el of el) { + el.checked = false; + el.parentElement.classList.remove("active"); + } + + this.filterDisplay = false; + this.filter.availabilityFilter = FilterType.None; + this.filter.statusFilter = FilterType.None; + + this.resetSearch(); + } + + public filterAvailability(filter: FilterType, el: any) { + this.filterActiveStyle(el); + this.filter.availabilityFilter = filter; + this.loadInit(); + } + + public filterStatus(filter: FilterType, el: any) { + this.filterActiveStyle(el); + this.filter.statusFilter = filter; + this.loadInit(); + } + + public setOrder(value: OrderType, el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + const parent = el.parentElement; + const previousFilter = parent.querySelector(".active"); + + previousFilter.className = ""; + el.className = "active"; + + this.orderType = value; + + this.loadInit(); + } + + // public subscribe(request: IAlbumRequest) { + // request.subscribed = true; + // this.requestService.subscribeToMovie(request.id) + // .subscribe(x => { + // this.notificationService.success("Subscribed To Movie!"); + // }); + // } + + // public unSubscribe(request: IMovieRequests) { + // request.subscribed = false; + // this.requestService.unSubscribeToMovie(request.id) + // .subscribe(x => { + // this.notificationService.success("Unsubscribed Movie!"); + // }); + // } + + private filterActiveStyle(el: any) { + el = el.toElement || el.relatedTarget || el.target || el.srcElement; + + el = el.parentElement; //gets radio div + el = el.parentElement; //gets form group div + el = el.parentElement; //gets status filter div + el = el.querySelectorAll("INPUT"); + for (el of el) { + if (el.checked) { + if (!el.parentElement.classList.contains("active")) { + el.parentElement.className += " active"; + } + } else { + el.parentElement.classList.remove("active"); + } + } + } + + private loadRequests(amountToLoad: number, currentlyLoaded: number) { + this.requestService.getAlbumRequests(amountToLoad, currentlyLoaded, this.orderType, this.filter) + .subscribe(x => { + this.setOverrides(x.collection); + if (!this.albumRequests) { + this.albumRequests = []; + } + this.albumRequests = x.collection; + this.totalAlbums = x.total; + this.currentlyLoaded = currentlyLoaded + amountToLoad; + }); + } + + private approveRequest(request: IAlbumRequest) { + this.requestService.approveAlbum({ id: request.id }) + .subscribe(x => { + request.approved = true; + if (x.result) { + this.notificationService.success( + `Request for ${request.title} has been approved successfully`); + } else { + this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage); + request.approved = false; + } + }); + } + + private denyRequest(request: IAlbumRequest) { + this.requestService.denyAlbum({ id: request.id }) + .subscribe(x => { + if (x.result) { + this.notificationService.success( + `Request for ${request.title} has been denied successfully`); + } else { + this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage); + request.denied = false; + } + }); + } + + private loadInit() { + this.requestService.getAlbumRequests(this.amountToLoad, 0, this.orderType, this.filter) + .subscribe(x => { + this.albumRequests = x.collection; + this.totalAlbums = x.total; + + this.setOverrides(this.albumRequests); + + if (this.isAdmin) { + // this.radarrService.getQualityProfilesFromSettings().subscribe(c => { + // this.radarrProfiles = c; + // this.albumRequests.forEach((req) => this.setQualityOverrides(req)); + // }); + // this.radarrService.getRootFoldersFromSettings().subscribe(c => { + // this.radarrRootFolders = c; + // this.albumRequests.forEach((req) => this.setRootFolderOverrides(req)); + // }); + } + }); + } + + private resetSearch() { + this.currentlyLoaded = 5; + this.loadInit(); + } + + private removeRequestFromUi(key: IAlbumRequest) { + const index = this.albumRequests.indexOf(key, 0); + if (index > -1) { + this.albumRequests.splice(index, 1); + } + } + + private setOverrides(requests: IAlbumRequest[]): void { + requests.forEach((req) => { + this.setOverride(req); + }); + } + + // private setQualityOverrides(req: IMovieRequests): void { + // if (this.radarrProfiles) { + // const profile = this.radarrProfiles.filter((p) => { + // return p.id === req.qualityOverride; + // }); + // if (profile.length > 0) { + // req.qualityOverrideTitle = profile[0].name; + // } + // } + // } + // private setRootFolderOverrides(req: IMovieRequests): void { + // if (this.radarrRootFolders) { + // const path = this.radarrRootFolders.filter((folder) => { + // return folder.id === req.rootPathOverride; + // }); + // if (path.length > 0) { + // req.rootPathOverrideTitle = path[0].path; + // } + // } + // } + + private setOverride(req: IAlbumRequest): void { + this.setAlbumBackground(req); + // this.setQualityOverrides(req); + // this.setRootFolderOverrides(req); + } + private setAlbumBackground(req: IAlbumRequest) { + if (req.disk === null) { + if(req.cover === null) { + req.disk = this.defaultPoster; + } else { + req.disk = req.cover; + } + } + req.background = this.sanitizer.bypassSecurityTrustStyle + ("url(" + req.cover + ")"); + } +} diff --git a/src/Ombi/ClientApp/app/requests/request.component.html b/src/Ombi/ClientApp/app/requests/request.component.html index 916d3b774..45509fba3 100644 --- a/src/Ombi/ClientApp/app/requests/request.component.html +++ b/src/Ombi/ClientApp/app/requests/request.component.html @@ -9,6 +9,10 @@ {{ 'Requests.TvTab' | translate }} +
  • + {{ 'Requests.MusicTab' | translate }} + +
  • @@ -19,5 +23,8 @@
    +
    + +
    diff --git a/src/Ombi/ClientApp/app/requests/request.component.ts b/src/Ombi/ClientApp/app/requests/request.component.ts index 557bb7a07..d0fa9d0b1 100644 --- a/src/Ombi/ClientApp/app/requests/request.component.ts +++ b/src/Ombi/ClientApp/app/requests/request.component.ts @@ -11,6 +11,7 @@ export class RequestComponent implements OnInit { public showMovie = true; public showTv = false; + public showAlbums = false; public issueCategories: IIssueCategory[]; public issuesEnabled = false; @@ -28,10 +29,18 @@ export class RequestComponent implements OnInit { public selectMovieTab() { this.showMovie = true; this.showTv = false; + this.showAlbums = false; } public selectTvTab() { this.showMovie = false; this.showTv = true; + this.showAlbums = false; + } + + public selectMusicTab() { + this.showMovie = false; + this.showTv = false; + this.showAlbums = true; } } diff --git a/src/Ombi/ClientApp/app/requests/requests.module.ts b/src/Ombi/ClientApp/app/requests/requests.module.ts index 31a45e07a..63d7117f5 100644 --- a/src/Ombi/ClientApp/app/requests/requests.module.ts +++ b/src/Ombi/ClientApp/app/requests/requests.module.ts @@ -8,6 +8,7 @@ import { InfiniteScrollModule } from "ngx-infinite-scroll"; import { ButtonModule, DialogModule, PaginatorModule } from "primeng/primeng"; import { MovieRequestsComponent } from "./movierequests.component"; +import { MusicRequestsComponent } from "./music/musicrequests.component"; // Request import { RequestComponent } from "./request.component"; import { TvRequestChildrenComponent } from "./tvrequest-children.component"; @@ -23,7 +24,6 @@ import { SharedModule } from "../shared/shared.module"; const routes: Routes = [ { path: "", component: RequestComponent, canActivate: [AuthGuard] }, - { path: ":id", component: TvRequestChildrenComponent, canActivate: [AuthGuard] }, ]; @NgModule({ imports: [ @@ -44,6 +44,7 @@ const routes: Routes = [ MovieRequestsComponent, TvRequestsComponent, TvRequestChildrenComponent, + MusicRequestsComponent, ], exports: [ RouterModule, diff --git a/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts b/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts index ddd7e48ec..9ef36357a 100644 --- a/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/lidarr.service.ts @@ -3,7 +3,7 @@ import { HttpClient } from "@angular/common/http"; import { Injectable } from "@angular/core"; import { Observable } from "rxjs"; -import { ILidarrProfile, ILidarrRootFolder } from "../../interfaces"; +import { ILidarrProfile, ILidarrRootFolder, IProfiles } from "../../interfaces"; import { ILidarrSettings } from "../../interfaces"; import { ServiceHelpers } from "../service.helpers"; @@ -26,4 +26,11 @@ export class LidarrService extends ServiceHelpers { public getQualityProfilesFromSettings(): Observable { return this.http.get(`${this.url}/Profiles/`, {headers: this.headers}); } + + public getMetadataProfiles(settings: ILidarrSettings): Observable { + return this.http.post(`${this.url}/Metadata/`, JSON.stringify(settings), {headers: this.headers}); + } + public getLanguages(settings: ILidarrSettings): Observable { + return this.http.post(`${this.url}/Langauges/`,JSON.stringify(settings), {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 2a9de8b2a..045a73310 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -159,8 +159,8 @@ export class RequestService extends ServiceHelpers { return this.http.post(`${this.url}music/unavailable`, JSON.stringify(Album), {headers: this.headers}); } - public getAlbumRequests(count: number, position: number, order: OrderType, filter: IFilter): Observable> { - return this.http.get>(`${this.url}music/${count}/${position}/${order}/${filter.statusFilter}/${filter.availabilityFilter}`, {headers: this.headers}); + public getAlbumRequests(count: number, position: number, order: OrderType, filter: IFilter): Observable> { + return this.http.get>(`${this.url}music/${count}/${position}/${order}/${filter.statusFilter}/${filter.availabilityFilter}`, {headers: this.headers}); } public searchAlbumRequests(search: string): Observable { diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html index d36295038..aa3dbaa66 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html @@ -50,38 +50,59 @@
    -
    -
    - -
    -
    +
    - + +
    A Default Quality Profile is required
    -
    -
    - - -
    - -
    - + +
    A Default Root Path is required
    + +
    + +
    + + + +
    + A Language profile is required +
    + + +
    + +
    + + + + +
    + + A Metadata profile is required +
    +
    diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts index 91d7ead80..8100c0194 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { ILidarrSettings, IMinimumAvailability, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; +import { ILidarrSettings, IMinimumAvailability, IProfiles, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; import { IRadarrSettings } from "../../interfaces"; import { LidarrService, TesterService } from "../../services"; import { NotificationService } from "../../services"; @@ -13,10 +13,14 @@ import { SettingsService } from "../../services"; export class LidarrComponent implements OnInit { public qualities: IRadarrProfile[]; + public languageProfiles: IProfiles[]; + public metadataProfiles: IProfiles[]; public rootFolders: IRadarrRootFolder[]; public minimumAvailabilityOptions: IMinimumAvailability[]; public profilesRunning: boolean; public rootFoldersRunning: boolean; + public metadataRunning: boolean; + public languageRunning: boolean; public advanced = false; public form: FormGroup; @@ -39,6 +43,9 @@ export class LidarrComponent implements OnInit { subDir: [x.subDir], ip: [x.ip, [Validators.required]], port: [x.port, [Validators.required]], + albumFolder: [x.albumFolder], + languageProfileId: [x.languageProfileId, [Validators.required]], + metadataProfileId: [x.metadataProfileId, [Validators.required]], }); if (x.defaultQualityProfile) { @@ -47,35 +54,69 @@ export class LidarrComponent implements OnInit { if (x.defaultRootPath) { this.getRootFolders(this.form); } + if (x.languageProfileId) { + this.getLanguageProfiles(this.form); + } + if (x.metadataProfileId) { + this.getMetadataProfiles(this.form); + } }); this.qualities = []; this.qualities.push({ name: "Please Select", id: -1 }); - + this.rootFolders = []; this.rootFolders.push({ path: "Please Select", id: -1 }); + + this.languageProfiles = []; + this.languageProfiles.push({ name: "Please Select", id: -1 }); + + this.metadataProfiles = []; + this.metadataProfiles.push({ name: "Please Select", id: -1 }); } public getProfiles(form: FormGroup) { - this.profilesRunning = true; - this.lidarrService.getQualityProfiles(form.value).subscribe(x => { - this.qualities = x; - this.qualities.unshift({ name: "Please Select", id: -1 }); + this.profilesRunning = true; + this.lidarrService.getQualityProfiles(form.value).subscribe(x => { + this.qualities = x; + this.qualities.unshift({ name: "Please Select", id: -1 }); - this.profilesRunning = false; - this.notificationService.success("Successfully retrieved the Quality Profiles"); - }); + this.profilesRunning = false; + this.notificationService.success("Successfully retrieved the Quality Profiles"); + }); } public getRootFolders(form: FormGroup) { - this.rootFoldersRunning = true; - this.lidarrService.getRootFolders(form.value).subscribe(x => { - this.rootFolders = x; - this.rootFolders.unshift({ path: "Please Select", id: -1 }); + this.rootFoldersRunning = true; + this.lidarrService.getRootFolders(form.value).subscribe(x => { + this.rootFolders = x; + this.rootFolders.unshift({ path: "Please Select", id: -1 }); - this.rootFoldersRunning = false; - this.notificationService.success("Successfully retrieved the Root Folders"); - }); + this.rootFoldersRunning = false; + this.notificationService.success("Successfully retrieved the Root Folders"); + }); + } + + public getMetadataProfiles(form: FormGroup) { + this.metadataRunning = true; + this.lidarrService.getMetadataProfiles(form.value).subscribe(x => { + this.metadataProfiles = x; + this.metadataProfiles.unshift({ name: "Please Select", id: -1 }); + + this.metadataRunning = false; + this.notificationService.success("Successfully retrieved the Metadata profiles"); + }); + } + + public getLanguageProfiles(form: FormGroup) { + this.languageRunning = true; + this.lidarrService.getLanguages(form.value).subscribe(x => { + this.languageProfiles = x; + this.languageProfiles.unshift({ name: "Please Select", id: -1 }); + + this.languageRunning = false; + this.notificationService.success("Successfully retrieved the Language profiles"); + }); } public test(form: FormGroup) { @@ -93,12 +134,12 @@ export class LidarrComponent implements OnInit { }); } -public onSubmit(form: FormGroup) { + public onSubmit(form: FormGroup) { if (form.invalid) { this.notificationService.error("Please check your entered values"); return; } - if(form.controls.defaultQualityProfile.value === "-1" || form.controls.defaultRootPath.value === "Please Select") { + if (form.controls.defaultQualityProfile.value === "-1" || form.controls.defaultRootPath.value === "Please Select") { this.notificationService.error("Please check your entered values"); return; } diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 593511316..1afad391c 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -1003,4 +1003,25 @@ a > h4:hover { white-space: normal; vertical-align: baseline; border-radius: .25em; +} + +.form-control-grid { + display: block; + width: inherit !important; + height: 39px; + color: #fefefe; + border-radius: 5px; + padding: 8px 16px; + font-size: 15px; + line-height: 1.42857143; + color: #2b3e50; + background-color: #ffffff; + background-image: none; + border: 1px solid transparent; + border-radius: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075); + box-shadow: inset 0 1px 1px rgba(0,0,0,0.075); + -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; } \ No newline at end of file diff --git a/src/Ombi/Controllers/External/LidarrController.cs b/src/Ombi/Controllers/External/LidarrController.cs index 084d4f258..076d68241 100644 --- a/src/Ombi/Controllers/External/LidarrController.cs +++ b/src/Ombi/Controllers/External/LidarrController.cs @@ -50,6 +50,27 @@ namespace Ombi.Controllers.External return await _lidarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); } + /// + /// Gets the Lidarr metadata profiles. + /// + /// The settings. + /// + [HttpPost("Metadata")] + public async Task> GetMetadataProfiles([FromBody] LidarrSettings settings) + { + return await _lidarrApi.GetMetadataProfile(settings.ApiKey, settings.FullUri); + } + /// + /// Gets the Lidarr Langauge profiles. + /// + /// The settings. + /// + [HttpPost("Langauges")] + public async Task> GetLanguageProfiles([FromBody] LidarrSettings settings) + { + return await _lidarrApi.GetLanguageProfile(settings.ApiKey, settings.FullUri); + } + /// /// Gets the Lidarr profiles using the saved settings /// The data is cached for an hour diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 4fd3ccb1b..74a6fc7cc 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -119,6 +119,7 @@ "Below you can see yours and all other requests, as well as their download and approval status.", "MoviesTab": "Movies", "TvTab": "TV Shows", + "MusicTab":"Music", "RequestedBy": "Requested By:", "Status": "Status:", "RequestStatus": "Request status:", From 0b7a7a6bbbe86e326dc00a1a21c081cc40590219 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 26 Aug 2018 23:26:15 +0100 Subject: [PATCH 364/495] Sorted out the requests page UI !wip #2313 --- src/Ombi.Core/Engine/MusicSearchEngine.cs | 2 +- .../music/musicrequests.component.html | 21 +++++++--------- .../search/music/albumsearch.component.scss | 3 --- .../app/search/music/albumsearch.component.ts | 1 - src/Ombi/ClientApp/styles/base.scss | 24 ++++--------------- src/Ombi/wwwroot/translations/en.json | 1 + 6 files changed, 14 insertions(+), 38 deletions(-) delete mode 100644 src/Ombi/ClientApp/app/search/music/albumsearch.component.scss diff --git a/src/Ombi.Core/Engine/MusicSearchEngine.cs b/src/Ombi.Core/Engine/MusicSearchEngine.cs index 17f1aed54..d0e577801 100644 --- a/src/Ombi.Core/Engine/MusicSearchEngine.cs +++ b/src/Ombi.Core/Engine/MusicSearchEngine.cs @@ -154,7 +154,7 @@ namespace Ombi.Core.Engine Title = a.title, Disk = a.images?.FirstOrDefault(x => x.coverType.Equals("disc"))?.url }; - if (vm.Monitored) + if (a.artistId > 0) { //TODO THEY HAVE FIXED THIS IN DEV // The JSON is different for some stupid reason diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index 221d829a0..85150edeb 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -44,7 +44,7 @@
    -
    +
    @@ -77,10 +77,6 @@ {{request.requestedUser.alias}} {{request.requestedUser.userName}}
    -
    - {{ 'Requests.Status' | translate }} - {{request.status}} -
    {{ 'Requests.RequestStatus' | translate }} @@ -101,19 +97,18 @@
    -
    {{ 'Requests.TheatricalRelease' | translate: {date: request.releaseDate | date: 'mediumDate'} }}
    -
    {{ 'Requests.DigitalRelease' | translate: {date: request.digitalReleaseDate | date: 'mediumDate'} }}
    -
    {{ 'Requests.RequestDate' | translate }} {{request.requestedDate | date}}
    +
    {{ 'Requests.ReleaseDate' | translate: {date: request.releaseDate | date: 'mediumDate'} }}
    +
    {{ 'Requests.RequestDate' | translate }} {{request.requestedDate | date: 'mediumDate'}}

    -
    +
    @@ -130,7 +125,7 @@
    -->
    -
    + @@ -168,13 +163,13 @@
    --> -
    +
    - + diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.scss b/src/Ombi/ClientApp/app/search/music/albumsearch.component.scss deleted file mode 100644 index 799b4957f..000000000 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.album-cover { - width:300px; -} diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts b/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts index 29824a970..0f9a373e2 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts @@ -9,7 +9,6 @@ import { NotificationService, RequestService } from "../../services"; @Component({ selector: "album-search", templateUrl: "./albumsearch.component.html", - styleUrls: ["./albumsearch.component.scss"], }) export class AlbumSearchComponent { diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 1afad391c..a9f3119fa 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -1005,23 +1005,7 @@ a > h4:hover { border-radius: .25em; } -.form-control-grid { - display: block; - width: inherit !important; - height: 39px; - color: #fefefe; - border-radius: 5px; - padding: 8px 16px; - font-size: 15px; - line-height: 1.42857143; - color: #2b3e50; - background-color: #ffffff; - background-image: none; - border: 1px solid transparent; - border-radius: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075); - box-shadow: inset 0 1px 1px rgba(0,0,0,0.075); - -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s; - -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; -} \ No newline at end of file +.album-cover { + width:300px; +} + diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 74a6fc7cc..d5d8969df 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -125,6 +125,7 @@ "RequestStatus": "Request status:", "Denied": " Denied:", "TheatricalRelease": "Theatrical Release: {{date}}", + "ReleaseDate": "Released: {{date}}", "TheatricalReleaseSort": "Theatrical Release", "DigitalRelease": "Digital Release: {{date}}", "RequestDate": "Request Date:", From e02c8e4014aba9c95b822c0c4bae16a29fefa362 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 26 Aug 2018 23:42:53 +0100 Subject: [PATCH 365/495] It works now when we request an album when we do not have the artist in Lidarr. Waiting on https://github.com/lidarr/Lidarr/issues/459 to do when we have the artist --- src/Ombi.Api.Lidarr/LidarrApi.cs | 4 ++-- src/Ombi.Api.Lidarr/Models/ArtistAdd.cs | 1 + src/Ombi.Core/Senders/MusicSender.cs | 22 ++++++++++++++++--- .../requests/music/musicrequests.component.ts | 7 +++--- .../ClientApp/app/services/request.service.ts | 2 +- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index 572a2b55c..cf358699c 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -113,7 +113,7 @@ namespace Ombi.Api.Lidarr return Api.Request(request); } - public Task MontiorAlbum(int albumId, string apiKey, string baseUrl) + public async Task MontiorAlbum(int albumId, string apiKey, string baseUrl) { var request = new Request($"{ApiVersion}/album/monitor", baseUrl, HttpMethod.Put); request.AddJsonBody(new @@ -122,7 +122,7 @@ namespace Ombi.Api.Lidarr monitored = true }); AddHeaders(request, apiKey); - return Api.Request(request); + return (await Api.Request>(request)).FirstOrDefault(); } public Task> GetAllAlbumsByArtistId(int artistId, string apiKey, string baseUrl) diff --git a/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs b/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs index e77a239e6..65aec3ac8 100644 --- a/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs +++ b/src/Ombi.Api.Lidarr/Models/ArtistAdd.cs @@ -44,5 +44,6 @@ namespace Ombi.Api.Lidarr.Models public int selectedOption { get; set; } public bool monitored { get; set; } public bool searchForMissingAlbums { get; set; } + public string[] AlbumsToMonitor { get; set; } // Uses the MusicBrainzAlbumId! } } \ No newline at end of file diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 3baa26003..5e1e44126 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -57,7 +57,8 @@ namespace Ombi.Core.Senders { monitored = true, searchForMissingAlbums = false, - selectedOption = 6 // None + selectedOption = 6, // None + AlbumsToMonitor = new[] {model.ForeignAlbumId} }, added = DateTime.Now, monitored = true, @@ -76,7 +77,7 @@ namespace Ombi.Core.Senders if (result != null && result.id > 0) { // Setup the albums - await SetupAlbum(model, result, settings); + return new SenderResult { Message = "Album has been requested!", Sent = true, Success = true }; } } else @@ -91,9 +92,24 @@ namespace Ombi.Core.Senders { // Get the album id var albums = await _lidarrApi.GetAllAlbumsByArtistId(artist.id, settings.ApiKey, settings.FullUri); - // Get the album we want. var album = albums.FirstOrDefault(x => x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + var maxRetryCount = 10; // 5 seconds + var currentRetry = 0; + while (!albums.Any() || album == null) + { + if (currentRetry >= maxRetryCount) + { + break; + } + currentRetry++; + await Task.Delay(500); + albums = await _lidarrApi.GetAllAlbumsByArtistId(artist.id, settings.ApiKey, settings.FullUri); + album = albums.FirstOrDefault(x => + x.foreignAlbumId.Equals(model.ForeignAlbumId, StringComparison.InvariantCultureIgnoreCase)); + } + // Get the album we want. + if (album == null) { return new SenderResult { Message = "Could not find album in Lidarr", Sent = false, Success = false }; diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts index f004b4019..8f8096acd 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.ts @@ -88,9 +88,10 @@ export class MusicRequestsComponent implements OnInit { } public removeRequest(request: IAlbumRequest) { - this.requestService.removeAlbumRequest(request); - this.removeRequestFromUi(request); - this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); + this.requestService.removeAlbumRequest(request).subscribe(x => { + this.removeRequestFromUi(request); + this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0); + }); } public changeAvailability(request: IAlbumRequest, available: boolean) { diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 045a73310..039939a84 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -167,7 +167,7 @@ export class RequestService extends ServiceHelpers { return this.http.get(`${this.url}music/search/${search}`, {headers: this.headers}); } - public removeAlbumRequest(request: IAlbumRequest) { + public removeAlbumRequest(request: IAlbumRequest): any { this.http.delete(`${this.url}music/${request.id}`, {headers: this.headers}).subscribe(); } From fd8bfeb1e44ff6546d6066c594afece06ca98b33 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 27 Aug 2018 00:04:57 +0100 Subject: [PATCH 366/495] fixed linting !wip --- .../ClientApp/app/requests/music/musicrequests.component.html | 2 +- src/Ombi/ClientApp/app/search/music/albumsearch.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index 85150edeb..43819ad76 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -212,7 +212,7 @@
    - +
    diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html index 6b5cc52a9..b23a73221 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html @@ -75,7 +75,7 @@ -->
    -
    +
    From 91a04f6ca707700c955a9513a04696ba3fd2ad1f Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 12:30:53 +0100 Subject: [PATCH 367/495] Add vscode to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 771a7bacd..587f09568 100644 --- a/.gitignore +++ b/.gitignore @@ -243,3 +243,6 @@ _Pvt_Extensions # CAKE - C# Make /Tools/* *.db-journal + +# Ignore local vscode config +*.vscode From 71009f4942bb5451b5aaf024fd6d5d537e94e829 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 15:05:49 +0100 Subject: [PATCH 368/495] Fix query for fetching requested tv shows --- src/Ombi.Core/Engine/TvRequestEngine.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 939b0fe3e..2d937a377 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -631,7 +631,10 @@ namespace Ombi.Core.Engine }; } - IQueryable log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.TvShow); + IQueryable log = _requestLog.GetAll() + .Where(x => x.UserId == user.Id + && x.RequestType == RequestType.TvShow + && x.RequestDate >= DateTime.UtcNow.AddDays(-7)); // Needed, due to a bug which would cause all episode counts to be 0 int zeroEpisodeCount = await log.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync(); @@ -640,8 +643,7 @@ namespace Ombi.Core.Engine int count = limit - (zeroEpisodeCount + episodeCount); - DateTime oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)) - .OrderBy(x => x.RequestDate) + DateTime oldestRequestedAt = await log.OrderBy(x => x.RequestDate) .Select(x => x.RequestDate) .FirstOrDefaultAsync(); From c12cb10972276d521944dd287e6781b09d0352bf Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 15:40:00 +0100 Subject: [PATCH 369/495] Add text to translation file --- .../app/requests/remainingrequests.component.html | 8 ++++---- src/Ombi/wwwroot/translations/en.json | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.html b/src/Ombi/ClientApp/app/requests/remainingrequests.component.html index 769cd79c2..565de7473 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.html @@ -1,15 +1,15 @@ 

    - {{remaining.remaining}}/{{remaining.limit}} requests remaining + {{'Requests.Remaining.Quota' | translate: {remaining: remaining.remaining, total: remaining.limit} }}

    - Another request will be added in {{daysUntil}} {{daysUntil == 1 ? "day" : "days"}} + {{daysUntil == 1 ? 'Requests.Remaining.NextDay' : "Requests.Remaining.NextDays" | translate: {time: daysUntil} }}

    - Another request will be added in {{hoursUntil}} {{hoursUntil == 1 ? "hour" : "hours"}} + {{hoursUntil == 1 ? 'Requests.Remaining.NextHour' : "Requests.Remaining.NextHours" | translate: {time: hoursUntil} }}

    - Another request will be added in {{minutesUntil}} {{minutesUntil == 1 ? "minute" : "minutes"}} + {{minutesUntil == 1 ? 'Requests.Remaining.NextMinute' : "Requests.Remaining.NextMinutes" | translate: {time: minutesUntil} }}

    diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index b70e065cb..a2c7f20dc 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -145,7 +145,16 @@ "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc":"Status ▲", - "SortStatusDesc":"Status ▼" + "SortStatusDesc":"Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextDay": "Another request will be added in {{time}} day", + "NextHours": "Another request will be added in {{time} hours", + "NextHour": "Another request will be added in {{time} hour", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues":{ "Title":"Issues", From 967109f4b2623dfd843d0d84c66c313ea2a03c5b Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 16:04:46 +0100 Subject: [PATCH 370/495] Refactor code --- .../app/requests/remainingrequests.component.html | 8 ++++---- .../ClientApp/app/requests/remainingrequests.component.ts | 4 ---- src/Ombi/wwwroot/translations/en.json | 4 +--- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.html b/src/Ombi/ClientApp/app/requests/remainingrequests.component.html index 565de7473..11cd28b34 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.html @@ -3,13 +3,13 @@ {{'Requests.Remaining.Quota' | translate: {remaining: remaining.remaining, total: remaining.limit} }}

    - {{daysUntil == 1 ? 'Requests.Remaining.NextDay' : "Requests.Remaining.NextDays" | translate: {time: daysUntil} }} + {{'Requests.Remaining.NextDays' | translate: {time: daysUntil} }}

    - {{hoursUntil == 1 ? 'Requests.Remaining.NextHour' : "Requests.Remaining.NextHours" | translate: {time: hoursUntil} }} + {{'Requests.Remaining.NextHours' | translate: {time: hoursUntil} }}

    -

    - {{minutesUntil == 1 ? 'Requests.Remaining.NextMinute' : "Requests.Remaining.NextMinutes" | translate: {time: minutesUntil} }} +

    + {{(minutesUntil == 1 ? 'Requests.Remaining.NextMinute' : 'Requests.Remaining.NextMinutes') | translate: {time: minutesUntil} }}

    diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index 4f4439c13..980256d69 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -27,10 +27,6 @@ export class RemainingRequestsComponent implements OnInit { this.update(); }); - setInterval(() => { - self.calculateTime(); - }, 10000); - setInterval(() => { self.update(); }, 60000); diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index a2c7f20dc..46be04a6b 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -149,9 +149,7 @@ "Remaining": { "Quota": "{{remaining}}/{{total}} requests remaining", "NextDays": "Another request will be added in {{time}} days", - "NextDay": "Another request will be added in {{time}} day", - "NextHours": "Another request will be added in {{time} hours", - "NextHour": "Another request will be added in {{time} hour", + "NextHours": "Another request will be added in {{time}} hours", "NextMinutes": "Another request will be added in {{time}} minutes", "NextMinute": "Another request will be added in {{time}} minute" } From 93e9b4cd4ccacdb2025dbe04b4cc8d54e06addb4 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 16:08:06 +0100 Subject: [PATCH 371/495] Remove unused module --- src/Ombi/ClientApp/app/requests/remainingrequests.module.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts index acbbed256..70a12bf16 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts @@ -8,15 +8,12 @@ import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { SidebarModule, TooltipModule, TreeTableModule } from "primeng/primeng"; import { RequestService } from "../services"; -import { SharedModule } from "../shared/shared.module"; - @NgModule({ imports: [ CommonModule, FormsModule, NgbModule.forRoot(), TreeTableModule, - SharedModule, SidebarModule, TooltipModule, ], From e6f24eabb45eb38a9e53a4059507addddfc9a458 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 16:52:09 +0100 Subject: [PATCH 372/495] Change way remainingrequests component is notified --- .../requests/remainingrequests.component.ts | 2 +- .../app/search/moviesearch.component.ts | 1 + .../app/search/seriesinformation.component.ts | 1 + .../app/search/tvsearch.component.ts | 1 + .../ClientApp/app/services/request.service.ts | 25 +++---------------- 5 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index 980256d69..8a13d2cfb 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -23,7 +23,7 @@ export class RemainingRequestsComponent implements OnInit { this.update(); - this.requestService.onRequested().subscribe(m => { + this.requestService.requestEvents.subscribe(() => { this.update(); }); diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 965837bae..fece0cc74 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -88,6 +88,7 @@ export class MovieSearchComponent implements OnInit { try { this.requestService.requestMovie({ theMovieDbId: searchResult.id }) .subscribe(x => { + this.requestService.requestEvents.next(); this.result = x; if (this.result.result) { this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts index 5c0088268..91234780d 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts @@ -62,6 +62,7 @@ export class SeriesInformationComponent implements OnInit { this.requestService.requestTv(viewModel) .subscribe(x => { + this.requestService.requestEvents.next(); this.result = x as IRequestEngineResult; if (this.result.result) { this.notificationService.success( diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.ts b/src/Ombi/ClientApp/app/search/tvsearch.component.ts index a41f34586..e08b84567 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.ts @@ -161,6 +161,7 @@ export class TvSearchComponent implements OnInit { this.requestService.requestTv(viewModel) .subscribe(x => { + this.requestService.requestEvents.next(); this.result = x; if (this.result.result) { this.notificationService.success( diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index a7fbc76bf..a8032d5a9 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -13,15 +13,12 @@ import { IRemainingRequests } from "../interfaces/IRemainingRequests"; @Injectable() export class RequestService extends ServiceHelpers { - private requestEvents = new ReplaySubject(); + public readonly requestEvents = new ReplaySubject(); + constructor(http: HttpClient, public platformLocation: PlatformLocation) { super(http, "/api/v1/Request/", platformLocation); } - public onRequested(): Observable { - return this.requestEvents.asObservable(); - } - public getRemainingMovieRequests(): Observable { return this.http.get(`${this.url}movie/remaining`, {headers: this.headers}); } @@ -31,14 +28,7 @@ export class RequestService extends ServiceHelpers { } public requestMovie(movie: IMovieRequestModel): Observable { - const observer = Observable.create(observer => { - this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}).subscribe(m => { - observer.next(m); - this.requestEvents.next(m); - }); - }); - - return observer; + return this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}); } public getTotalMovies(): Observable { @@ -50,14 +40,7 @@ export class RequestService extends ServiceHelpers { } public requestTv(tv: ITvRequestViewModel): Observable { - const observer = Observable.create(observer => { - return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }).subscribe(m => { - observer.next(m); - this.requestEvents.next(m); - }); - }); - - return observer; + return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }); } public approveMovie(movie: IMovieUpdateModel): Observable { From 26904d3947a544d320511011a87c6192931df872 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 16:55:50 +0100 Subject: [PATCH 373/495] Remove import --- src/Ombi/ClientApp/app/requests/remainingrequests.module.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts index 70a12bf16..411a94dfd 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.module.ts @@ -1,5 +1,4 @@ -import { CommonModule } from "@angular/common"; -import { NgModule } from "@angular/core"; +import { NgModule } from "@angular/core"; import { FormsModule } from "@angular/forms"; import { RouterModule } from "@angular/router"; @@ -10,7 +9,6 @@ import { RequestService } from "../services"; @NgModule({ imports: [ - CommonModule, FormsModule, NgbModule.forRoot(), TreeTableModule, From 4cad24f8e95b152358fe67619b2efa62678a8328 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 23:51:44 +0100 Subject: [PATCH 374/495] Move logic for notifying when reuqest is complete --- .../ClientApp/app/requests/remainingrequests.component.ts | 4 +++- src/Ombi/ClientApp/app/search/moviesearch.component.html | 2 +- src/Ombi/ClientApp/app/search/moviesearch.component.ts | 3 ++- .../ClientApp/app/search/seriesinformation.component.ts | 6 ++++-- src/Ombi/ClientApp/app/search/tvsearch.component.html | 4 ++-- src/Ombi/ClientApp/app/search/tvsearch.component.ts | 3 ++- src/Ombi/ClientApp/app/services/request.service.ts | 4 +--- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index 8a13d2cfb..978480e94 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -2,6 +2,7 @@ import { RequestService } from "../services"; import { Component, Input, OnInit } from "@angular/core"; +import { Observable } from "rxjs"; @Component({ selector: "remaining-requests", @@ -14,6 +15,7 @@ export class RemainingRequestsComponent implements OnInit { public daysUntil: number; public hoursUntil: number; public minutesUntil: number; + @Input() quotaRefreshEvents: Observable; constructor(private requestService: RequestService) { } @@ -23,7 +25,7 @@ export class RemainingRequestsComponent implements OnInit { this.update(); - this.requestService.requestEvents.subscribe(() => { + this.quotaRefreshEvents.subscribe(() => { this.update(); }); diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index 6d8c040ac..eb3cb1b87 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -20,7 +20,7 @@
    - +
    diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index fece0cc74..1519941ec 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -17,6 +17,7 @@ export class MovieSearchComponent implements OnInit { public searchText: string; public searchChanged: Subject = new Subject(); + public movieRequested: Subject = new Subject(); public movieResults: ISearchMovieResult[]; public result: IRequestEngineResult; @@ -88,7 +89,7 @@ export class MovieSearchComponent implements OnInit { try { this.requestService.requestMovie({ theMovieDbId: searchResult.id }) .subscribe(x => { - this.requestService.requestEvents.next(); + this.movieRequested.next(); this.result = x; if (this.result.result) { this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts index 91234780d..979afc144 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts @@ -7,6 +7,7 @@ import { SearchService } from "../services"; import { INewSeasonRequests, IRequestEngineResult, ISeasonsViewModel, ITvRequestViewModel } from "../interfaces"; import { IEpisodesRequests } from "../interfaces"; import { ISearchTvResult } from "../interfaces"; +import { Subject } from "rxjs"; @Component({ selector: "seriesinformation", @@ -18,9 +19,10 @@ export class SeriesInformationComponent implements OnInit { public result: IRequestEngineResult; public series: ISearchTvResult; public requestedEpisodes: IEpisodesRequests[] = []; - @Input() private seriesId: number; + @Input() public tvRequested: Subject; + constructor(private searchService: SearchService, private requestService: RequestService, private notificationService: NotificationService) { } public ngOnInit() { @@ -62,7 +64,7 @@ export class SeriesInformationComponent implements OnInit { this.requestService.requestTv(viewModel) .subscribe(x => { - this.requestService.requestEvents.next(); + this.tvRequested.next(); this.result = x as IRequestEngineResult; if (this.result.result) { this.notificationService.success( diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index 5f4938cf1..127077b3b 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -27,7 +27,7 @@
    - +
    @@ -153,7 +153,7 @@
    - +

    diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.ts b/src/Ombi/ClientApp/app/search/tvsearch.component.ts index e08b84567..632900091 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.ts @@ -18,6 +18,7 @@ export class TvSearchComponent implements OnInit { public searchText: string; public searchChanged = new Subject(); public tvResults: ISearchTvResult[]; + public tvRequested: Subject = new Subject(); public result: IRequestEngineResult; public searchApplied = false; public defaultPoster: string; @@ -161,7 +162,7 @@ export class TvSearchComponent implements OnInit { this.requestService.requestTv(viewModel) .subscribe(x => { - this.requestService.requestEvents.next(); + this.tvRequested.next(); this.result = x; if (this.result.result) { this.notificationService.success( diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index a8032d5a9..1ebed5dcd 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -2,7 +2,7 @@ import { PlatformLocation } from "@angular/common"; import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; -import { Observable, ReplaySubject } from "rxjs"; +import { Observable } from "rxjs"; import { TreeNode } from "primeng/primeng"; import { FilterType, IChildRequests, IFilter, IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces"; @@ -13,8 +13,6 @@ import { IRemainingRequests } from "../interfaces/IRemainingRequests"; @Injectable() export class RequestService extends ServiceHelpers { - public readonly requestEvents = new ReplaySubject(); - constructor(http: HttpClient, public platformLocation: PlatformLocation) { super(http, "/api/v1/Request/", platformLocation); } From dcae229a8321fe386d9e0437dfbd802df4a9b98e Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Mon, 27 Aug 2018 23:58:05 +0100 Subject: [PATCH 375/495] Fix lint errors --- .../ClientApp/app/requests/remainingrequests.component.ts | 2 +- src/Ombi/ClientApp/app/search/seriesinformation.component.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index 978480e94..4de649f6a 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -15,7 +15,7 @@ export class RemainingRequestsComponent implements OnInit { public daysUntil: number; public hoursUntil: number; public minutesUntil: number; - @Input() quotaRefreshEvents: Observable; + @Input() public quotaRefreshEvents: Observable; constructor(private requestService: RequestService) { } diff --git a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts index 979afc144..6a918a69a 100644 --- a/src/Ombi/ClientApp/app/search/seriesinformation.component.ts +++ b/src/Ombi/ClientApp/app/search/seriesinformation.component.ts @@ -7,6 +7,7 @@ import { SearchService } from "../services"; import { INewSeasonRequests, IRequestEngineResult, ISeasonsViewModel, ITvRequestViewModel } from "../interfaces"; import { IEpisodesRequests } from "../interfaces"; import { ISearchTvResult } from "../interfaces"; + import { Subject } from "rxjs"; @Component({ @@ -19,9 +20,8 @@ export class SeriesInformationComponent implements OnInit { public result: IRequestEngineResult; public series: ISearchTvResult; public requestedEpisodes: IEpisodesRequests[] = []; - @Input() private seriesId: number; - @Input() public tvRequested: Subject; + @Input() private seriesId: number; constructor(private searchService: SearchService, private requestService: RequestService, private notificationService: NotificationService) { } From 82c353a727f02d2b80fdb651b75d2be4b17e83d0 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 28 Aug 2018 09:29:42 +0100 Subject: [PATCH 376/495] !wip added music into the newsletter and also added issue reporting to the albums --- .../Jobs/Ombi/HtmlTemplateGenerator.cs | 26 ++-- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 113 +++++++++++++++++- .../Notifications/NewsletterSettings.cs | 1 + src/Ombi.Store/Entities/LidarrAlbumCache.cs | 1 + src/Ombi.Store/Entities/RecentlyAddedLog.cs | 7 +- .../music/musicrequests.component.html | 4 +- .../search/music/albumsearch.component.html | 21 ++-- .../app/search/music/albumsearch.component.ts | 20 +++- 8 files changed, 165 insertions(+), 28 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs index 51e920b15..09b7d9858 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/HtmlTemplateGenerator.cs @@ -1,4 +1,5 @@ using System.Text; +using Ombi.Helpers; namespace Ombi.Schedule.Jobs.Ombi { @@ -22,13 +23,20 @@ namespace Ombi.Schedule.Jobs.Ombi protected virtual void AddMediaServerUrl(StringBuilder sb, string mediaurl, string url) { - sb.Append("
    "); - sb.Append(""); - sb.Append(""); + if (url.HasValue()) + { + sb.Append(""); + sb.Append( + ""); + sb.Append(""); + } + sb.Append("
    "); - sb.AppendFormat("", mediaurl); - sb.AppendFormat("", url); - sb.Append(""); - sb.Append("
    "); + sb.AppendFormat("", mediaurl); + sb.AppendFormat( + "", + url); + sb.Append(""); + sb.Append("
    "); sb.Append(""); } @@ -44,9 +52,9 @@ namespace Ombi.Schedule.Jobs.Ombi { sb.Append(""); sb.Append(""); - sb.AppendFormat("", url); + if(url.HasValue()) sb.AppendFormat("", url); sb.AppendFormat("

    {0}

    ", title); - sb.Append("
    "); + if (url.HasValue()) sb.Append(""); sb.Append(""); sb.Append(""); } diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 6e89d167e..f152f6b4b 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -9,6 +9,8 @@ using MailKit; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using Ombi.Api.Lidarr; +using Ombi.Api.Lidarr.Models; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TvMaze; @@ -18,6 +20,7 @@ using Ombi.Notifications; using Ombi.Notifications.Models; using Ombi.Notifications.Templates; using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.Notifications; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -29,7 +32,8 @@ namespace Ombi.Schedule.Jobs.Ombi public NewsletterJob(IPlexContentRepository plex, IEmbyContentRepository emby, IRepository addedLog, IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService custom, ISettingsService emailSettings, INotificationTemplatesRepository templateRepo, - UserManager um, ISettingsService newsletter, ILogger log) + UserManager um, ISettingsService newsletter, ILogger log, + ILidarrApi lidarrApi, IRepository albumCache, ISettingsService lidarrSettings) { _plex = plex; _emby = emby; @@ -46,6 +50,10 @@ namespace Ombi.Schedule.Jobs.Ombi _customizationSettings.ClearCache(); _newsletterSettings.ClearCache(); _log = log; + _lidarrApi = lidarrApi; + _lidarrAlbumRepository = albumCache; + _lidarrSettings = lidarrSettings; + _lidarrSettings.ClearCache(); } private readonly IPlexContentRepository _plex; @@ -60,6 +68,9 @@ namespace Ombi.Schedule.Jobs.Ombi private readonly ISettingsService _newsletterSettings; private readonly UserManager _userManager; private readonly ILogger _log; + private readonly ILidarrApi _lidarrApi; + private readonly IRepository _lidarrAlbumRepository; + private readonly ISettingsService _lidarrSettings; public async Task Start(NewsletterSettings settings, bool test) { @@ -87,21 +98,26 @@ namespace Ombi.Schedule.Jobs.Ombi // Get the Content var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking(); var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking(); + var lidarrContent = _lidarrAlbumRepository.GetAll().AsNoTracking(); var addedLog = _recentlyAddedLog.GetAll(); var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId); var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId); + var addedAlbumLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Lidarr && x.ContentType == ContentType.Album).Select(x => x.AlbumId); var addedPlexEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode); var addedEmbyEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode); + // Filter out the ones that we haven't sent yet var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && x.HasTheMovieDb && !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && x.HasTheMovieDb && !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId))); + var lidarrContentAlbumsToSend = lidarrContent.Where(x => !addedAlbumLogIds.Contains(x.ForeignAlbumId)).ToHashSet(); _log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count()); _log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count()); + _log.LogInformation("Albums to send: {0}", lidarrContentAlbumsToSend.Count()); var plexEpisodesToSend = FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).Where(x => x.Series.HasTvDb).AsNoTracking(), addedPlexEpisodesLogIds); @@ -117,11 +133,12 @@ namespace Ombi.Schedule.Jobs.Ombi var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie ).OrderByDescending(x => x.AddedAt).Take(10); var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); - body = await BuildHtml(plexm, embym, plext, embyt, settings); + var lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); + body = await BuildHtml(plexm, embym, plext, embyt, lidarr, settings); } else { - body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, settings); + body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings); if (body.IsNullOrEmpty()) { return; @@ -298,7 +315,8 @@ namespace Ombi.Schedule.Jobs.Ombi return resolver.ParseMessage(template, curlys); } - private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, HashSet plexEpisodes, HashSet embyEp, NewsletterSettings settings) + private async Task BuildHtml(IQueryable plexContentToSend, IQueryable embyContentToSend, + HashSet plexEpisodes, HashSet embyEp, HashSet albums, NewsletterSettings settings) { var sb = new StringBuilder(); @@ -340,6 +358,24 @@ namespace Ombi.Schedule.Jobs.Ombi sb.Append(""); } + + if (albums.Any() && !settings.DisableMusic) + { + sb.Append("

    New Albums



    "); + sb.Append( + ""); + sb.Append(""); + sb.Append(""); + sb.Append(""); + sb.Append("
    "); + sb.Append(""); + sb.Append(""); + await ProcessAlbums(albums, sb); + sb.Append(""); + sb.Append("
    "); + sb.Append("
    "); + } + return sb.ToString(); } @@ -382,6 +418,40 @@ namespace Ombi.Schedule.Jobs.Ombi } } } + private async Task ProcessAlbums(HashSet albumsToSend, StringBuilder sb) + { + var settings = await _lidarrSettings.GetSettingsAsync(); + int count = 0; + var ordered = albumsToSend.OrderByDescending(x => x.AddedAt); + foreach (var content in ordered) + { + var info = await _lidarrApi.GetAlbumByForeignId(content.ForeignAlbumId, settings.ApiKey, settings.FullUri); + if (info == null) + { + continue; + } + try + { + CreateAlbumHtmlContent(sb, info); + count += 1; + } + catch (Exception e) + { + _log.LogError(e, "Error when Processing Lidarr Album {0}", info.title); + } + finally + { + EndLoopHtml(sb); + } + + if (count == 2) + { + count = 0; + sb.Append(""); + sb.Append(""); + } + } + } private async Task ProcessEmbyMovies(IQueryable embyContent, StringBuilder sb) { @@ -467,6 +537,41 @@ namespace Ombi.Schedule.Jobs.Ombi } } + private void CreateAlbumHtmlContent(StringBuilder sb, AlbumLookup info) + { + var cover = info.images + .FirstOrDefault(x => x.coverType.Equals("cover", StringComparison.InvariantCultureIgnoreCase))?.url; + if (cover.IsNullOrEmpty()) + { + cover = info.remoteCover; + } + AddBackgroundInsideTable(sb, cover); + var disk = info.images + .FirstOrDefault(x => x.coverType.Equals("disc", StringComparison.InvariantCultureIgnoreCase))?.url; + if (disk.IsNullOrEmpty()) + { + disk = info.remoteCover; + } + AddPosterInsideTable(sb, disk); + + AddMediaServerUrl(sb, string.Empty, string.Empty); + AddInfoTable(sb); + + var releaseDate = $"({info.releaseDate.Year})"; + + AddTitle(sb, string.Empty, $"{info.title} {releaseDate}"); + + var summary = info.artist?.artistName ?? string.Empty; + if (summary.Length > 280) + { + summary = summary.Remove(280); + summary = summary + "...

    "; + } + AddParagraph(sb, summary); + + AddGenres(sb, $"Type: {info.albumType}"); + } + private async Task ProcessPlexTv(HashSet plexContent, StringBuilder sb) { var series = new List(); diff --git a/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs b/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs index e79f3182c..3f6416af5 100644 --- a/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs +++ b/src/Ombi.Settings/Settings/Models/Notifications/NewsletterSettings.cs @@ -6,6 +6,7 @@ namespace Ombi.Settings.Settings.Models.Notifications { public bool DisableTv { get; set; } public bool DisableMovies { get; set; } + public bool DisableMusic { get; set; } public bool Enabled { get; set; } public List ExternalEmails { get; set; } = new List(); } diff --git a/src/Ombi.Store/Entities/LidarrAlbumCache.cs b/src/Ombi.Store/Entities/LidarrAlbumCache.cs index d9ceab8a3..03099face 100644 --- a/src/Ombi.Store/Entities/LidarrAlbumCache.cs +++ b/src/Ombi.Store/Entities/LidarrAlbumCache.cs @@ -13,6 +13,7 @@ namespace Ombi.Store.Entities public bool Monitored { get; set; } public string Title { get; set; } public decimal PercentOfTracks { get; set; } + public DateTime AddedAt { get; set; } [NotMapped] public bool PartiallyAvailable => PercentOfTracks != 100 && PercentOfTracks > 0; diff --git a/src/Ombi.Store/Entities/RecentlyAddedLog.cs b/src/Ombi.Store/Entities/RecentlyAddedLog.cs index 1ef091149..782d89e3f 100644 --- a/src/Ombi.Store/Entities/RecentlyAddedLog.cs +++ b/src/Ombi.Store/Entities/RecentlyAddedLog.cs @@ -11,18 +11,21 @@ namespace Ombi.Store.Entities public int ContentId { get; set; } // This is dependant on the type, it's either TMDBID or TVDBID public int? EpisodeNumber { get; set; } public int? SeasonNumber { get; set; } + public string AlbumId { get; set; } public DateTime AddedAt { get; set; } } public enum RecentlyAddedType { Plex = 0, - Emby = 1 + Emby = 1, + Lidarr = 2 } public enum ContentType { Parent = 0, - Episode = 1 + Episode = 1, + Album = 2, } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index 43819ad76..c89c2be0a 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -189,7 +189,7 @@
    - +
    diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html index b23a73221..1581c9a35 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html @@ -68,13 +68,13 @@
    -
    + + +
    -
    +
    -->
    @@ -93,11 +93,9 @@ | translate }}
    - -
    - + - \ No newline at end of file + + + + + diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts b/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts index 0f9a373e2..9dac4aa8b 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts @@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; import { TranslateService } from "@ngx-translate/core"; import { AuthService } from "../../auth/auth.service"; -import { IRequestEngineResult } from "../../interfaces"; +import { IIssueCategory, IRequestEngineResult } from "../../interfaces"; import { ISearchAlbumResult } from "../../interfaces/ISearchMusicResult"; import { NotificationService, RequestService } from "../../services"; @@ -14,7 +14,15 @@ export class AlbumSearchComponent { @Input() public result: ISearchAlbumResult; public engineResult: IRequestEngineResult; - @Input() public defaultPoster: string; + @Input() public defaultPoster: string; + + @Input() public issueCategories: IIssueCategory[]; + @Input() public issuesEnabled: boolean; + public issuesBarVisible = false; + public issueRequestTitle: string; + public issueRequestId: number; + public issueProviderId: string; + public issueCategorySelected: IIssueCategory; @Output() public setSearch = new EventEmitter(); @@ -29,6 +37,14 @@ export class AlbumSearchComponent { this.setSearch.emit(artistId); } + public reportIssue(catId: IIssueCategory, req: ISearchAlbumResult) { + this.issueRequestId = req.id; + this.issueRequestTitle = req.title + `(${req.releaseDate.getFullYear})`; + this.issueCategorySelected = catId; + this.issuesBarVisible = true; + this.issueProviderId = req.id.toString(); + } + public request(searchResult: ISearchAlbumResult) { searchResult.requested = true; searchResult.requestProcessing = true; From 21cb5820dd3441c7afbc4826cd3264e1e2570bf6 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 28 Aug 2018 09:32:40 +0100 Subject: [PATCH 377/495] migrations !wip --- .../20180828083219_MusicIssues.Designer.cs | 1091 +++++++++++++++++ .../Migrations/20180828083219_MusicIssues.cs | 33 + .../Migrations/OmbiContextModelSnapshot.cs | 4 + 3 files changed, 1128 insertions(+) create mode 100644 src/Ombi.Store/Migrations/20180828083219_MusicIssues.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180828083219_MusicIssues.cs diff --git a/src/Ombi.Store/Migrations/20180828083219_MusicIssues.Designer.cs b/src/Ombi.Store/Migrations/20180828083219_MusicIssues.Designer.cs new file mode 100644 index 000000000..52f00c840 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180828083219_MusicIssues.Designer.cs @@ -0,0 +1,1091 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180828083219_MusicIssues")] + partial class MusicIssues + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.1-rtm-30846"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + 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.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + 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 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180828083219_MusicIssues.cs b/src/Ombi.Store/Migrations/20180828083219_MusicIssues.cs new file mode 100644 index 000000000..94a06ff18 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180828083219_MusicIssues.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class MusicIssues : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AlbumId", + table: "RecentlyAddedLog", + nullable: true); + + migrationBuilder.AddColumn( + name: "AddedAt", + table: "LidarrAlbumCache", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AlbumId", + table: "RecentlyAddedLog"); + + migrationBuilder.DropColumn( + name: "AddedAt", + table: "LidarrAlbumCache"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 0e3d1efea..64400e58c 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -249,6 +249,8 @@ namespace Ombi.Store.Migrations b.Property("Id") .ValueGeneratedOnAdd(); + b.Property("AddedAt"); + b.Property("ArtistId"); b.Property("ForeignAlbumId"); @@ -489,6 +491,8 @@ namespace Ombi.Store.Migrations b.Property("AddedAt"); + b.Property("AlbumId"); + b.Property("ContentId"); b.Property("ContentType"); From f709c0acbc32a6d2d2c3e7bad8682877ee76131b Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 28 Aug 2018 09:35:47 +0100 Subject: [PATCH 378/495] Fill in the addedat !wip --- src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs index 9708df589..2e32b6478 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAlbumSync.cs @@ -67,7 +67,8 @@ namespace Ombi.Schedule.Jobs.Lidarr TrackCount = a.currentRelease.trackCount, Monitored = a.monitored, Title = a.title, - PercentOfTracks = a.statistics?.percentOfEpisodes ?? 0m + PercentOfTracks = a.statistics?.percentOfEpisodes ?? 0m, + AddedAt = DateTime.Now, }); } } From 18b48cd0a88d81269da3c45e6cde07b523b99ceb Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 28 Aug 2018 16:19:20 +0100 Subject: [PATCH 379/495] fixed linting !wip --- .../ClientApp/app/search/music/albumsearch.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html index 1581c9a35..fd5f71075 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html @@ -45,11 +45,11 @@ - + - + @@ -79,7 +79,7 @@ -
    +
    +
    +
    + + +
    +
    +
    From 28a1886767eab052eb6a71359b61aa214a3e0e5d Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 28 Aug 2018 20:09:54 +0100 Subject: [PATCH 391/495] Made the test button actually work on the Lidarr settings page !wip --- src/Ombi.Api.Lidarr/ILidarrApi.cs | 1 + src/Ombi.Api.Lidarr/LidarrApi.cs | 7 +++++ src/Ombi.Api.Lidarr/Models/LidarrStatus.cs | 31 +++++++++++++++++++ .../services/applications/tester.service.ts | 5 +++ .../app/settings/lidarr/lidarr.component.ts | 4 +-- .../Controllers/External/TesterController.cs | 30 ++++++++++++++++-- 6 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 src/Ombi.Api.Lidarr/Models/LidarrStatus.cs diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs index 38724f668..15d20fd28 100644 --- a/src/Ombi.Api.Lidarr/ILidarrApi.cs +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -21,5 +21,6 @@ namespace Ombi.Api.Lidarr Task> GetAllAlbumsByArtistId(int artistId, string apiKey, string baseUrl); Task> GetMetadataProfile(string apiKey, string baseUrl); Task> GetLanguageProfile(string apiKey, string baseUrl); + Task Status(string apiKey, string baseUrl); } } \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index cf358699c..2aded7e1a 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -147,6 +147,13 @@ namespace Ombi.Api.Lidarr return Api.Request>(request); } + public Task Status(string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/system/status", baseUrl, HttpMethod.Get); + AddHeaders(request, apiKey); + return Api.Request(request); + } + private void AddHeaders(Request request, string key) { request.AddHeader("X-Api-Key", key); diff --git a/src/Ombi.Api.Lidarr/Models/LidarrStatus.cs b/src/Ombi.Api.Lidarr/Models/LidarrStatus.cs new file mode 100644 index 000000000..27f6c1820 --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/LidarrStatus.cs @@ -0,0 +1,31 @@ +using System; + +namespace Ombi.Api.Lidarr.Models +{ + public class LidarrStatus + { + public string version { get; set; } + public DateTime buildTime { get; set; } + public bool isDebug { get; set; } + public bool isProduction { get; set; } + public bool isAdmin { get; set; } + public bool isUserInteractive { get; set; } + public string startupPath { get; set; } + public string appData { get; set; } + public string osName { get; set; } + public string osVersion { get; set; } + public bool isMonoRuntime { get; set; } + public bool isMono { get; set; } + public bool isLinux { get; set; } + public bool isOsx { get; set; } + public bool isWindows { get; set; } + public string mode { get; set; } + public string branch { get; set; } + public string authentication { get; set; } + public string sqliteVersion { get; set; } + public int migrationVersion { get; set; } + public string urlBase { get; set; } + public string runtimeVersion { get; set; } + public string runtimeName { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/services/applications/tester.service.ts b/src/Ombi/ClientApp/app/services/applications/tester.service.ts index 3fa038888..e692b9196 100644 --- a/src/Ombi/ClientApp/app/services/applications/tester.service.ts +++ b/src/Ombi/ClientApp/app/services/applications/tester.service.ts @@ -11,6 +11,7 @@ import { IDiscordNotifcationSettings, IEmailNotificationSettings, IEmbyServer, + ILidarrSettings, IMattermostNotifcationSettings, IMobileNotificationTestSettings, INewsletterNotificationSettings, @@ -66,6 +67,10 @@ export class TesterService extends ServiceHelpers { return this.http.post(`${this.url}radarr`, JSON.stringify(settings), {headers: this.headers}); } + public lidarrTest(settings: ILidarrSettings): Observable { + return this.http.post(`${this.url}lidarr`, JSON.stringify(settings), {headers: this.headers}); + } + public sonarrTest(settings: ISonarrSettings): Observable { return this.http.post(`${this.url}sonarr`, JSON.stringify(settings), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts index 8100c0194..b124f9d47 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -124,8 +124,8 @@ export class LidarrComponent implements OnInit { this.notificationService.error("Please check your entered values"); return; } - const settings = form.value; - this.testerService.radarrTest(settings).subscribe(x => { + const settings = form.value; + this.testerService.lidarrTest(settings).subscribe(x => { if (x === true) { this.notificationService.success("Successfully connected to Lidarr!"); } else { diff --git a/src/Ombi/Controllers/External/TesterController.cs b/src/Ombi/Controllers/External/TesterController.cs index fca42bb63..5e3156bde 100644 --- a/src/Ombi/Controllers/External/TesterController.cs +++ b/src/Ombi/Controllers/External/TesterController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Ombi.Api.CouchPotato; using Ombi.Api.Emby; +using Ombi.Api.Lidarr; using Ombi.Api.Plex; using Ombi.Api.Radarr; using Ombi.Api.SickRage; @@ -38,7 +39,8 @@ namespace Ombi.Controllers.External public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN, IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm, IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger log, IEmailProvider provider, - ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, IMobileNotification mobileNotification) + ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, IMobileNotification mobileNotification, + ILidarrApi lidarrApi) { Service = service; DiscordNotification = notification; @@ -58,6 +60,7 @@ namespace Ombi.Controllers.External SickRageApi = srApi; Newsletter = newsletter; MobileNotification = mobileNotification; + LidarrApi = lidarrApi; } private INotificationService Service { get; } @@ -78,6 +81,7 @@ namespace Ombi.Controllers.External private ISickRageApi SickRageApi { get; } private INewsletterJob Newsletter { get; } private IMobileNotification MobileNotification { get; } + private ILidarrApi LidarrApi { get; } /// @@ -397,7 +401,7 @@ namespace Ombi.Controllers.External { try { - await MobileNotification.NotifyAsync(new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1, UserId = settings.UserId}, settings.Settings); + await MobileNotification.NotifyAsync(new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1, UserId = settings.UserId }, settings.Settings); return true; } @@ -407,5 +411,27 @@ namespace Ombi.Controllers.External return false; } } + + [HttpPost("lidarr")] + public async Task LidarrTest([FromBody] LidarrSettings settings) + { + try + { + var status = await LidarrApi.Status(settings.ApiKey, settings.FullUri); + if (status != null & status?.version.HasValue() ?? false) + { + return true; + } + else + { + return false; + } + } + catch (Exception e) + { + Log.LogError(LoggingEvents.Api, e, "Could not test Mobile Notifications"); + return false; + } + } } } \ No newline at end of file From 9b3bd1b3fbc01afee259bbb2a3282ff850781310 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 28 Aug 2018 20:12:21 +0100 Subject: [PATCH 392/495] Fixed build !wip --- src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts index b124f9d47..3860b5675 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -2,7 +2,6 @@ import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { ILidarrSettings, IMinimumAvailability, IProfiles, IRadarrProfile, IRadarrRootFolder } from "../../interfaces"; -import { IRadarrSettings } from "../../interfaces"; import { LidarrService, TesterService } from "../../services"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; From 0ff920fdb3d77a84168ea877196906e6e3924f9d Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 28 Aug 2018 20:26:26 +0100 Subject: [PATCH 393/495] Fixed #2475 --- src/Ombi.Core/Engine/TvSearchEngine.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index 253363ec1..bb674a35d 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -54,7 +54,16 @@ namespace Ombi.Core.Engine if (searchResult != null) { - return await ProcessResults(searchResult); + var retVal = new List(); + foreach (var tvMazeSearch in searchResult) + { + if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false)) + { + continue; + } + retVal.Add(await ProcessResult(tvMazeSearch)); + } + return retVal; } return null; } @@ -145,12 +154,16 @@ namespace Ombi.Core.Engine var retVal = new List(); foreach (var tvMazeSearch in items) { - var viewT = Mapper.Map(tvMazeSearch); - retVal.Add(await ProcessResult(viewT)); + retVal.Add(await ProcessResult(tvMazeSearch)); } return retVal; } + private async Task ProcessResult(T tvMazeSearch) + { + return Mapper.Map(tvMazeSearch); + } + private async Task ProcessResult(SearchTvShowViewModel item) { item.TheTvDbId = item.Id.ToString(); From 8b5ae726c0057b84efbb2bbfb586088a0f697b00 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 28 Aug 2018 22:08:15 +0100 Subject: [PATCH 394/495] Add the music roles -.- !wip --- src/Ombi.Store/Context/OmbiContext.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index e93cc89ba..2fdbaa996 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -120,8 +120,8 @@ namespace Ombi.Store.Context Database.ExecuteSqlCommand("VACUUM;"); // Make sure we have the roles - var roles = Roles.Where(x => x.Name == OmbiRoles.ReceivesNewsletter); - if (!roles.Any()) + var newsletterRole = Roles.Where(x => x.Name == OmbiRoles.ReceivesNewsletter); + if (!newsletterRole.Any()) { Roles.Add(new IdentityRole(OmbiRoles.ReceivesNewsletter) { @@ -129,6 +129,19 @@ namespace Ombi.Store.Context }); SaveChanges(); } + var requestMusicRole = Roles.Where(x => x.Name == OmbiRoles.RequestMusic); + if (!requestMusicRole.Any()) + { + Roles.Add(new IdentityRole(OmbiRoles.RequestMusic) + { + NormalizedName = OmbiRoles.RequestMusic.ToUpper() + }); + Roles.Add(new IdentityRole(OmbiRoles.AutoApproveMusic) + { + NormalizedName = OmbiRoles.AutoApproveMusic.ToUpper() + }); + SaveChanges(); + } // Make sure we have the API User var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase)); From a214ecd67ede6f05c2db09eab7ff6f16e14e2660 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 28 Aug 2018 22:12:45 +0100 Subject: [PATCH 395/495] Added more logging into the updater --- src/Ombi.Updater/Installer.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Updater/Installer.cs b/src/Ombi.Updater/Installer.cs index 6a1ae9401..10d574a10 100644 --- a/src/Ombi.Updater/Installer.cs +++ b/src/Ombi.Updater/Installer.cs @@ -50,6 +50,7 @@ namespace Ombi.Updater private void StartOmbi(StartupOptions options) { + var startupArgsBuilder = new StringBuilder(); _log.LogDebug("Starting ombi"); var fileName = "Ombi.exe"; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -73,7 +74,6 @@ namespace Ombi.Updater } else { - var startupArgsBuilder = new StringBuilder(); if (!string.IsNullOrEmpty(options.Host)) { startupArgsBuilder.Append($"--host {options.Host} "); @@ -96,7 +96,10 @@ namespace Ombi.Updater } } - _log.LogDebug("Ombi started, now exiting"); + _log.LogDebug($"Ombi started, now exiting"); + _log.LogDebug($"Working dir: {options.ApplicationPath} (Application Path)"); + _log.LogDebug($"Filename: {Path.Combine(options.ApplicationPath, fileName)}"); + _log.LogDebug($"Startup Args: {startupArgsBuilder.ToString()}"); Environment.Exit(0); } From 5bae5cf096c66a2b9190f376cf9615b332a54656 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 29 Aug 2018 08:13:50 +0100 Subject: [PATCH 396/495] Fixed #2481 --- src/Ombi/ClientApp/app/settings/update/update.component.html | 4 ++-- src/Ombi/ClientApp/app/settings/update/update.component.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/settings/update/update.component.html b/src/Ombi/ClientApp/app/settings/update/update.component.html index c0de9a0a1..e82fcd30d 100644 --- a/src/Ombi/ClientApp/app/settings/update/update.component.html +++ b/src/Ombi/ClientApp/app/settings/update/update.component.html @@ -5,8 +5,8 @@
    Update Settings
    -
    - +
    +
    diff --git a/src/Ombi/ClientApp/app/settings/update/update.component.ts b/src/Ombi/ClientApp/app/settings/update/update.component.ts index b76c9ca22..df0e8b32e 100644 --- a/src/Ombi/ClientApp/app/settings/update/update.component.ts +++ b/src/Ombi/ClientApp/app/settings/update/update.component.ts @@ -63,7 +63,7 @@ export class UpdateComponent implements OnInit { this.notificationService.error("Please check your entered values"); return; } - this.enableUpdateButton = form.value.autoUpdateEnabled || form.value.testMode; + this.enableUpdateButton = form.value.autoUpdateEnabled; this.settingsService.saveUpdateSettings(form.value) .subscribe(x => { if (x) { From f89165314bdff5b5032f5011ef1dc5583b903606 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 29 Aug 2018 11:48:05 +0100 Subject: [PATCH 397/495] Revert request.service.ts to version on upstream/develop --- src/Ombi/ClientApp/app/services/request.service.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 1ebed5dcd..48fa5622d 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -9,22 +9,12 @@ import { FilterType, IChildRequests, IFilter, IMovieRequestModel, IMovieRequests import { ITvRequestViewModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; -import { IRemainingRequests } from "../interfaces/IRemainingRequests"; - @Injectable() export class RequestService extends ServiceHelpers { constructor(http: HttpClient, public platformLocation: PlatformLocation) { super(http, "/api/v1/Request/", platformLocation); } - public getRemainingMovieRequests(): Observable { - return this.http.get(`${this.url}movie/remaining`, {headers: this.headers}); - } - - public getRemainingTvRequests(): Observable { - return this.http.get(`${this.url}tv/remaining`, {headers: this.headers}); - } - public requestMovie(movie: IMovieRequestModel): Observable { return this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}); } @@ -38,7 +28,7 @@ export class RequestService extends ServiceHelpers { } public requestTv(tv: ITvRequestViewModel): Observable { - return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }); + return this.http.post(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers}); } public approveMovie(movie: IMovieUpdateModel): Observable { From a23c1030f487145684f0eab1a57101f422a69f6c Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 29 Aug 2018 11:56:51 +0100 Subject: [PATCH 398/495] Revert "Revert request.service.ts to version on upstream/develop" This reverts commit f89165314bdff5b5032f5011ef1dc5583b903606. --- src/Ombi/ClientApp/app/services/request.service.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 48fa5622d..1ebed5dcd 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -9,12 +9,22 @@ import { FilterType, IChildRequests, IFilter, IMovieRequestModel, IMovieRequests import { ITvRequestViewModel } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; +import { IRemainingRequests } from "../interfaces/IRemainingRequests"; + @Injectable() export class RequestService extends ServiceHelpers { constructor(http: HttpClient, public platformLocation: PlatformLocation) { super(http, "/api/v1/Request/", platformLocation); } + public getRemainingMovieRequests(): Observable { + return this.http.get(`${this.url}movie/remaining`, {headers: this.headers}); + } + + public getRemainingTvRequests(): Observable { + return this.http.get(`${this.url}tv/remaining`, {headers: this.headers}); + } + public requestMovie(movie: IMovieRequestModel): Observable { return this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}); } @@ -28,7 +38,7 @@ export class RequestService extends ServiceHelpers { } public requestTv(tv: ITvRequestViewModel): Observable { - return this.http.post(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers}); + return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }); } public approveMovie(movie: IMovieUpdateModel): Observable { From 7534a634c24561303c9f829571e2735988df96e5 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 29 Aug 2018 12:02:03 +0100 Subject: [PATCH 399/495] Fix formatting error --- src/Ombi/ClientApp/app/services/request.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index 1ebed5dcd..ac8769e71 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -38,7 +38,7 @@ export class RequestService extends ServiceHelpers { } public requestTv(tv: ITvRequestViewModel): Observable { - return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }); + return this.http.post(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers}); } public approveMovie(movie: IMovieUpdateModel): Observable { From bcb193f321177665c882fca5ae79fd9d34687a0f Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 29 Aug 2018 13:25:43 +0100 Subject: [PATCH 400/495] made a start !wip --- src/Ombi.Schedule.Tests/NewsletterTests.cs | 2 +- .../Entities/UserNotificationPreferences.cs | 20 +++++++++++++ src/Ombi/Controllers/IdentityController.cs | 29 ++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/Ombi.Store/Entities/UserNotificationPreferences.cs diff --git a/src/Ombi.Schedule.Tests/NewsletterTests.cs b/src/Ombi.Schedule.Tests/NewsletterTests.cs index fcbd35107..b3c2ce98a 100644 --- a/src/Ombi.Schedule.Tests/NewsletterTests.cs +++ b/src/Ombi.Schedule.Tests/NewsletterTests.cs @@ -18,7 +18,7 @@ namespace Ombi.Schedule.Tests var emailSettings = new Mock>(); var customziation = new Mock>(); var newsletterSettings = new Mock>(); - var newsletter = new NewsletterJob(null, null, null, null, null, null, customziation.Object, emailSettings.Object, null, null, newsletterSettings.Object, null); + var newsletter = new NewsletterJob(null, null, null, null, null, null, customziation.Object, emailSettings.Object, null, null, newsletterSettings.Object, null, null, null, null); var ep = new List(); foreach (var i in episodes) diff --git a/src/Ombi.Store/Entities/UserNotificationPreferences.cs b/src/Ombi.Store/Entities/UserNotificationPreferences.cs new file mode 100644 index 000000000..c779480c8 --- /dev/null +++ b/src/Ombi.Store/Entities/UserNotificationPreferences.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; +using Ombi.Helpers; + +namespace Ombi.Store.Entities +{ + [Table(nameof(UserNotificationPreferences))] + public class UserNotificationPreferences : Entity + { + public string UserId { get; set; } + public NotificationAgent Agent { get; set; } + public bool Enabled { get; set; } + public string Value { get; set; } + + [ForeignKey(nameof(UserId))] + public OmbiUser User { get; set; } + } +} diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 742d75b34..d7e556f26 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -60,7 +60,8 @@ namespace Ombi.Controllers IRepository issueComments, IRepository notificationRepository, IRepository subscriptionRepository, - ISettingsService umSettings) + ISettingsService umSettings, + IRepository notificationPreferences) { UserManager = user; Mapper = mapper; @@ -81,6 +82,7 @@ namespace Ombi.Controllers _requestSubscriptionRepository = subscriptionRepository; _notificationRepository = notificationRepository; _userManagementSettings = umSettings; + _userNotificationPreferences = notificationPreferences; } private OmbiUserManager UserManager { get; } @@ -102,6 +104,7 @@ namespace Ombi.Controllers private readonly IRepository _requestLogRepository; private readonly IRepository _notificationRepository; private readonly IRepository _requestSubscriptionRepository; + private readonly IRepository _userNotificationPreferences; /// @@ -787,6 +790,30 @@ namespace Ombi.Controllers return user.UserAccessToken; } + [HttpGet("notificationpreferences")] + public async Task> GetUserPreferences() + { + //TODO potentially use a view model + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + var userPreferences = await _userNotificationPreferences.GetAll().Where(x => x.UserId == user.Id).ToListAsync(); + + var agents = Enum.GetValues(typeof(NotificationAgent)).Cast(); + foreach (var a in agents) + { + var hasAgent = userPreferences.Any(x => x.Agent == a); + if (!hasAgent) + { + // Create the default + userPreferences.Add(new UserNotificationPreferences + { + Agent = a, + }); + } + } + + return userPreferences; + } + private async Task> AddRoles(IEnumerable roles, OmbiUser ombiUser) { var roleResult = new List(); From 6882209e3c82dc51805b41ced78162c6c57e7541 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 29 Aug 2018 17:48:41 +0100 Subject: [PATCH 401/495] Refactor code --- src/Ombi/ClientApp/app/requests/movierequests.component.ts | 3 --- src/Ombi/ClientApp/app/search/moviesearch.component.ts | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/movierequests.component.ts b/src/Ombi/ClientApp/app/requests/movierequests.component.ts index 651637308..311adeb92 100644 --- a/src/Ombi/ClientApp/app/requests/movierequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/movierequests.component.ts @@ -6,7 +6,6 @@ import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { AuthService } from "../auth/auth.service"; import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces"; -import { IRemainingRequests } from "../interfaces/IRemainingRequests"; import { NotificationService, RadarrService, RequestService } from "../services"; @Component({ @@ -39,8 +38,6 @@ export class MovieRequestsComponent implements OnInit { public orderType: OrderType = OrderType.RequestedDateDesc; public OrderType = OrderType; - public remaining: IRemainingRequests; - public totalMovies: number = 100; private currentlyLoaded: number; private amountToLoad: number; diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 1519941ec..5fd3a37db 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -73,8 +73,8 @@ export class MovieSearchComponent implements OnInit { this.popularMovies(); } - public search(text: any) { + public search(text: any) { this.searchChanged.next(text.target.value); } From 66281d4d9c1b7636401bac70a5030d14661cc8b6 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 29 Aug 2018 18:32:12 +0100 Subject: [PATCH 402/495] Correct path of lidarr component import for unix systems --- src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts index 3860b5675..5d85c3d73 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -7,7 +7,7 @@ import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; @Component({ - templateUrl: "./Lidarr.component.html", + templateUrl: "./lidarr.component.html", }) export class LidarrComponent implements OnInit { From 6bf9b3b064d16e314aa84fddbc4f440e1adf4fe5 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 01:40:38 +0100 Subject: [PATCH 403/495] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index ba48226a0..5e1e4a75a 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -12,8 +12,8 @@ "Common": { "ContinueButton": "Continuar", "Available": "Disponível", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", + "PartiallyAvailable": "Parcialmente Disponível", + "Monitored": "Monitorado", "NotAvailable": "Inisponível", "ProcessingRequest": "Processando Solicitação", "PendingApproval": "Aprovação Pendente", @@ -76,7 +76,7 @@ "Paragraph": "Quer assistir a algo que não está disponível? Não há problema, basta procurar abaixo e solicitar!", "MoviesTab": "Filmes", "TvTab": "Séries", - "MusicTab": "Music", + "MusicTab": "Músicas", "Suggestions": "Sugestões", "NoResults": "Desculpe, não encontramos nenhum resultado!", "DigitalDate": "Lançamento digital: {{date}}", @@ -114,13 +114,13 @@ "Paragraph": "Abaixo, você pode ver o seu e todos os outros pedidos, bem como o seu download e status de aprovação.", "MoviesTab": "Filmes", "TvTab": "Séries", - "MusicTab": "Music", + "MusicTab": "Músicas", "RequestedBy": "Solicitado por:", "Status": "Status:", "RequestStatus": "Status da solicitação:", "Denied": " Negados:", "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", - "ReleaseDate": "Released: {{date}}", + "ReleaseDate": "Lançado: {{date}}", "TheatricalReleaseSort": "Lançamento nos Cinemas", "DigitalRelease": "Lançamento digital: {{date}}", "RequestDate": "Data da Solicitação:", From 3d5e3cdde9e61b0a5bcf0bbbb75ecda8711e6b1c Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:16 +0100 Subject: [PATCH 404/495] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 184a08fb0..324bfccf1 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼" + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Problemer", From 9a197eb69e67691d77a6977679b272607c02d7c9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:17 +0100 Subject: [PATCH 405/495] New translations en.json (Dutch) --- src/Ombi/wwwroot/translations/nl.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 68a8bb606..313d34dcb 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼" + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Problemen", From fd39ead3a56bdd340f808b7fd65f0434771c30dc Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:18 +0100 Subject: [PATCH 406/495] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index de6cf49a5..24080f9f7 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Date de la demande ▲", "SortRequestDateDesc": "Date de la demande ▼", "SortStatusAsc": "Statut ▲", - "SortStatusDesc": "Statut ▼" + "SortStatusDesc": "Statut ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Problèmes", From 402f29685f412fccac9c8fb51c6d15d9814b901e Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:20 +0100 Subject: [PATCH 407/495] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index eaa0009bb..fdd1c6d63 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼" + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Probleme", From e30e59dc25be8cce46c61478f5b1c10e20ef63b8 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:21 +0100 Subject: [PATCH 408/495] New translations en.json (Italian) --- src/Ombi/wwwroot/translations/it.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 97a4a9dbb..647032425 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼" + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Problemi", From 8fb214c3ff9b0e20e08873a104f68b11fd3a7244 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:23 +0100 Subject: [PATCH 409/495] New translations en.json (Norwegian) --- src/Ombi/wwwroot/translations/no.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 27496a68a..b6b162621 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼" + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Mangler", From 7353e03473db1f6d9f5a4329335c2a62d2efa575 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:24 +0100 Subject: [PATCH 410/495] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index b39fb7e82..55c8b8060 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Data zgłoszenia ▲", "SortRequestDateDesc": "Data zgłoszenia ▼", "SortStatusAsc": "Stan ▲", - "SortStatusDesc": "Stan ▼" + "SortStatusDesc": "Stan ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Problemy", From f3954accffed6ca324dd8bce07376634406b7140 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:25 +0100 Subject: [PATCH 411/495] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index 5e1e4a75a..d1d15bcc5 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Data da Solicitação", "SortRequestDateDesc": "Data da Solicitação", "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼" + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Problemas", From b7c2dabe728f74e8ad89647adc9185960197b6a5 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:27 +0100 Subject: [PATCH 412/495] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 7189add03..0dee65f9a 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼" + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Incidencias", From 66adb07957757e54ad07bb177845fe469d21871c Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 31 Aug 2018 14:51:28 +0100 Subject: [PATCH 413/495] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 94c8ee1d8..7885b7e31 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -145,7 +145,14 @@ "SortRequestDateAsc": "Request Date ▲", "SortRequestDateDesc": "Request Date ▼", "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼" + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } }, "Issues": { "Title": "Problem", From fa7a64e1ad69c20366c88b97d189388c65f635f9 Mon Sep 17 00:00:00 2001 From: Stephen Panzer Date: Fri, 31 Aug 2018 11:42:32 -0600 Subject: [PATCH 414/495] Add clearfix class. Closes #2486 --- .../ClientApp/app/requests/tvrequest-children.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html index 12b093bca..f41b17f51 100644 --- a/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html +++ b/src/Ombi/ClientApp/app/requests/tvrequest-children.component.html @@ -1,6 +1,6 @@ 

    -
    +
    From fbb0978dd857966fb2357b66e64fd32a26b9a7a9 Mon Sep 17 00:00:00 2001 From: Stephen Panzer Date: Fri, 31 Aug 2018 12:27:57 -0600 Subject: [PATCH 415/495] Fix displaying year in issue dialog. Closes #2484 --- src/Ombi/ClientApp/app/search/moviesearch.component.ts | 3 ++- src/Ombi/ClientApp/app/search/tvsearch.component.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 5fd3a37db..59e9fc1b8 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -152,7 +152,8 @@ export class MovieSearchComponent implements OnInit { public reportIssue(catId: IIssueCategory, req: ISearchMovieResult) { this.issueRequestId = req.id; - this.issueRequestTitle = req.title + `(${req.releaseDate.getFullYear})`; + const releaseDate = new Date(req.releaseDate); + this.issueRequestTitle = req.title + ` (${releaseDate.getFullYear()})`; this.issueCategorySelected = catId; this.issuesBarVisible = true; this.issueProviderId = req.id.toString(); diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.ts b/src/Ombi/ClientApp/app/search/tvsearch.component.ts index 632900091..92d0d549a 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.ts @@ -197,7 +197,8 @@ export class TvSearchComponent implements OnInit { public reportIssue(catId: IIssueCategory, req: ISearchTvResult) { this.issueRequestId = req.id; - this.issueRequestTitle = req.title + `(${req.firstAired})`; + const firstAiredDate = new Date(req.firstAired); + this.issueRequestTitle = req.title + ` (${firstAiredDate.getFullYear()})`; this.issueCategorySelected = catId; this.issuesBarVisible = true; this.issueProviderId = req.id.toString(); From 243dc99633698f4b6e91b415aeec4c979f55178e Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sat, 1 Sep 2018 02:26:33 +0100 Subject: [PATCH 416/495] bodge fix test to prevent compile error --- src/Ombi.Schedule.Tests/NewsletterTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Schedule.Tests/NewsletterTests.cs b/src/Ombi.Schedule.Tests/NewsletterTests.cs index fcbd35107..b3c2ce98a 100644 --- a/src/Ombi.Schedule.Tests/NewsletterTests.cs +++ b/src/Ombi.Schedule.Tests/NewsletterTests.cs @@ -18,7 +18,7 @@ namespace Ombi.Schedule.Tests var emailSettings = new Mock>(); var customziation = new Mock>(); var newsletterSettings = new Mock>(); - var newsletter = new NewsletterJob(null, null, null, null, null, null, customziation.Object, emailSettings.Object, null, null, newsletterSettings.Object, null); + var newsletter = new NewsletterJob(null, null, null, null, null, null, customziation.Object, emailSettings.Object, null, null, newsletterSettings.Object, null, null, null, null); var ep = new List(); foreach (var i in episodes) From 69cf31f66b2904aecfc8462712c7521f9f0d90ea Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Sat, 1 Sep 2018 02:32:04 +0100 Subject: [PATCH 417/495] fix bug causing wrong time to be displayed for next request --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 2 +- src/Ombi.Core/Engine/TvRequestEngine.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 5a4bc51f5..733ba4b4f 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -516,7 +516,7 @@ namespace Ombi.Core.Engine HasLimit = true, Limit = limit, Remaining = count, - NextRequest = oldestRequestedAt.AddDays(7), + NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc), }; } } diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 2d937a377..f9a6e640d 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -652,7 +652,7 @@ namespace Ombi.Core.Engine HasLimit = true, Limit = limit, Remaining = count, - NextRequest = oldestRequestedAt.AddDays(7), + NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc), }; } } From db5d0c0b08b856c905356ec00129d1901d99f0f7 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 4 Sep 2018 08:36:15 +0100 Subject: [PATCH 418/495] !wip added the api to trigger an album search --- src/Ombi.Api.Lidarr/ILidarrApi.cs | 1 + src/Ombi.Api.Lidarr/LidarrApi.cs | 8 ++++++++ src/Ombi.Api.Lidarr/Models/CommandResult.cs | 15 +++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 src/Ombi.Api.Lidarr/Models/CommandResult.cs diff --git a/src/Ombi.Api.Lidarr/ILidarrApi.cs b/src/Ombi.Api.Lidarr/ILidarrApi.cs index 15d20fd28..4a23c6200 100644 --- a/src/Ombi.Api.Lidarr/ILidarrApi.cs +++ b/src/Ombi.Api.Lidarr/ILidarrApi.cs @@ -22,5 +22,6 @@ namespace Ombi.Api.Lidarr Task> GetMetadataProfile(string apiKey, string baseUrl); Task> GetLanguageProfile(string apiKey, string baseUrl); Task Status(string apiKey, string baseUrl); + Task AlbumSearch(int[] albumIds, string apiKey, string baseUrl); } } \ No newline at end of file diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index 2aded7e1a..8cda49cbf 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -154,6 +154,14 @@ namespace Ombi.Api.Lidarr return Api.Request(request); } + public Task AlbumSearch(int[] albumIds, string apiKey, string baseUrl) + { + var request = new Request($"{ApiVersion}/command/AlbumSearch", baseUrl, HttpMethod.Post); + request.AddJsonBody(albumIds); + AddHeaders(request, apiKey); + return Api.Request(request); + } + private void AddHeaders(Request request, string key) { request.AddHeader("X-Api-Key", key); diff --git a/src/Ombi.Api.Lidarr/Models/CommandResult.cs b/src/Ombi.Api.Lidarr/Models/CommandResult.cs new file mode 100644 index 000000000..7c6483a6a --- /dev/null +++ b/src/Ombi.Api.Lidarr/Models/CommandResult.cs @@ -0,0 +1,15 @@ +using System; + +namespace Ombi.Api.Lidarr.Models +{ + + public class CommandResult + { + public string name { get; set; } + public DateTime startedOn { get; set; } + public DateTime stateChangeTime { get; set; } + public bool sendUpdatesToClient { get; set; } + public string state { get; set; } + public int id { get; set; } + } +} \ No newline at end of file From 85cbc084630ca4ee158aa803fafb2de47e3b4d6d Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 4 Sep 2018 08:52:42 +0100 Subject: [PATCH 419/495] Fixed the issue if in Radarr we only want to add and monitor, if the movie already exists we search for it. --- src/Ombi.Core/Senders/MovieSender.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Core/Senders/MovieSender.cs b/src/Ombi.Core/Senders/MovieSender.cs index e57a5bf2a..aa919e552 100644 --- a/src/Ombi.Core/Senders/MovieSender.cs +++ b/src/Ombi.Core/Senders/MovieSender.cs @@ -123,7 +123,10 @@ namespace Ombi.Core.Senders existingMovie.monitored = true; await RadarrApi.UpdateMovie(existingMovie, settings.ApiKey, settings.FullUri); // Search for it - await RadarrApi.MovieSearch(new[] { existingMovie.id }, settings.ApiKey, settings.FullUri); + if (!settings.AddOnly) + { + await RadarrApi.MovieSearch(new[] {existingMovie.id}, settings.ApiKey, settings.FullUri); + } return new SenderResult { Success = true, Sent = true }; } From 7afcb1749a8a54e53609b05b7dd4f4b9e60f9abc Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 4 Sep 2018 08:55:40 +0100 Subject: [PATCH 420/495] Allow Lidarr to specify if we should search for the album --- src/Ombi.Core/Senders/MusicSender.cs | 4 ++++ .../Settings/Models/External/LidarrSettings.cs | 1 + src/Ombi/ClientApp/app/interfaces/ISettings.ts | 1 + .../app/settings/lidarr/lidarr.component.html | 10 ++++++++++ .../ClientApp/app/settings/lidarr/lidarr.component.ts | 1 + 5 files changed, 17 insertions(+) diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 5e1e44126..937204be5 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -116,6 +116,10 @@ namespace Ombi.Core.Senders } var result = await _lidarrApi.MontiorAlbum(album.id, settings.ApiKey, settings.FullUri); + if (!settings.AddOnly) + { + await _lidarrApi.AlbumSearch(new[] {result.id}, settings.ApiKey, settings.FullUri); + } if (result.monitored) { return new SenderResult {Message = "Album has been requested!", Sent = true, Success = true}; diff --git a/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs b/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs index e0bdbdc43..3a37b7d43 100644 --- a/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/LidarrSettings.cs @@ -11,5 +11,6 @@ namespace Ombi.Settings.Settings.Models.External public bool AlbumFolder { get; set; } public int LanguageProfileId { get; set; } public int MetadataProfileId { get; set; } + public bool AddOnly { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 2fb46a2b7..db4db935e 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -93,6 +93,7 @@ export interface ILidarrSettings extends IExternalSettings { metadataProfileId: number; languageProfileId: number; albumFolder: boolean; + addOnly: boolean; } export interface ILandingPageSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html index 11d9baf2d..c834fbdbd 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html @@ -3,6 +3,10 @@
    Lidarr Settings +
    + Advanced + +
    @@ -110,6 +114,12 @@
    +
    +
    + + +
    +
    diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts index 5d85c3d73..1f372546a 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -45,6 +45,7 @@ export class LidarrComponent implements OnInit { albumFolder: [x.albumFolder], languageProfileId: [x.languageProfileId, [Validators.required]], metadataProfileId: [x.metadataProfileId, [Validators.required]], + addOnly: [x.addOnly] }); if (x.defaultQualityProfile) { From cfd9deb17edde4c0632f57611dc29874db96c222 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 4 Sep 2018 09:29:32 +0100 Subject: [PATCH 421/495] !wip fixed linting --- src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts index 1f372546a..d1e28285f 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.ts @@ -45,7 +45,7 @@ export class LidarrComponent implements OnInit { albumFolder: [x.albumFolder], languageProfileId: [x.languageProfileId, [Validators.required]], metadataProfileId: [x.metadataProfileId, [Validators.required]], - addOnly: [x.addOnly] + addOnly: [x.addOnly], }); if (x.defaultQualityProfile) { From 9c574fb7e901ac16fd9c76e1a5dd3744140632f7 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 5 Sep 2018 00:12:19 +0100 Subject: [PATCH 422/495] Add quota fields to user view model --- .../Engine/Interfaces/IRequestEngine.cs | 2 +- src/Ombi.Core/Engine/MovieRequestEngine.cs | 8 ++++++-- src/Ombi.Core/Engine/TvRequestEngine.cs | 8 ++++++-- src/Ombi.Core/Models/UI/UserViewModel.cs | 2 ++ src/Ombi/ClientApp/app/interfaces/IUser.ts | 4 ++++ .../usermanagement-add.component.ts | 2 ++ src/Ombi/Controllers/IdentityController.cs | 20 +++++++++++++++++-- 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs index 53111fd95..c8b7746f0 100644 --- a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs @@ -23,6 +23,6 @@ namespace Ombi.Core.Engine.Interfaces Task GetTotal(); Task UnSubscribeRequest(int requestId, RequestType type); Task SubscribeToRequest(int requestId, RequestType type); - Task GetRemainingRequests(); + Task GetRemainingRequests(OmbiUser user = null); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 733ba4b4f..0cce7af58 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -486,9 +486,13 @@ namespace Ombi.Core.Engine return new RequestEngineResult {Result = true, Message = $"{movieName} has been successfully added!"}; } - public async Task GetRemainingRequests() + public async Task GetRemainingRequests(OmbiUser user) { - OmbiUser user = await GetUser(); + if (user == null) + { + user = await GetUser(); + } + int limit = user.MovieRequestLimit ?? 0; if (limit <= 0) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index f9a6e640d..a700035a0 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -615,9 +615,13 @@ namespace Ombi.Core.Engine return new RequestEngineResult { Result = true }; } - public async Task GetRemainingRequests() + public async Task GetRemainingRequests(OmbiUser user) { - OmbiUser user = await GetUser(); + if (user == null) + { + user = await GetUser(); + } + int limit = user.EpisodeRequestLimit ?? 0; if (limit <= 0) diff --git a/src/Ombi.Core/Models/UI/UserViewModel.cs b/src/Ombi.Core/Models/UI/UserViewModel.cs index 1c1e6162b..cddc32b90 100644 --- a/src/Ombi.Core/Models/UI/UserViewModel.cs +++ b/src/Ombi.Core/Models/UI/UserViewModel.cs @@ -16,6 +16,8 @@ namespace Ombi.Core.Models.UI public UserType UserType { get; set; } public int MovieRequestLimit { get; set; } public int EpisodeRequestLimit { get; set; } + public RequestQuotaCountModel EpisodeRequestQuota { get; set; } + public RequestQuotaCountModel MovieRequestQuota { get; set; } } public class ClaimCheckboxes diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index cd96848fb..9e14dcfb4 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -1,4 +1,5 @@ import { ICheckbox } from "."; +import { IRemainingRequests } from "./IRemainingRequests"; export interface IUser { id: string; @@ -13,7 +14,10 @@ export interface IUser { movieRequestLimit: number; episodeRequestLimit: number; userAccessToken: string; + // FOR UI + episodeRequestQuota: IRemainingRequests | null; + movieRequestQuota: IRemainingRequests | null; checked: boolean; } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts index 36b187e79..5e0799552 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts @@ -32,6 +32,8 @@ export class UserManagementAddComponent implements OnInit { episodeRequestLimit: 0, movieRequestLimit: 0, userAccessToken: "", + episodeRequestQuota: null, + movieRequestQuota: null, }; } diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 742d75b34..3ecb9c3e7 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -16,6 +16,7 @@ using Ombi.Api.Plex; using Ombi.Attributes; using Ombi.Config; using Ombi.Core.Authentication; +using Ombi.Core.Engine.Interfaces; using Ombi.Core.Helpers; using Ombi.Core.Models.UI; using Ombi.Core.Settings; @@ -60,7 +61,9 @@ namespace Ombi.Controllers IRepository issueComments, IRepository notificationRepository, IRepository subscriptionRepository, - ISettingsService umSettings) + ISettingsService umSettings, + IMovieRequestEngine movieRequestEngine, + ITvRequestEngine tvRequestEngine) { UserManager = user; Mapper = mapper; @@ -81,6 +84,8 @@ namespace Ombi.Controllers _requestSubscriptionRepository = subscriptionRepository; _notificationRepository = notificationRepository; _userManagementSettings = umSettings; + TvRequestEngine = tvRequestEngine; + MovieRequestEngine = movieRequestEngine; } private OmbiUserManager UserManager { get; } @@ -94,6 +99,8 @@ namespace Ombi.Controllers private IWelcomeEmail WelcomeEmail { get; } private IMovieRequestRepository MovieRepo { get; } private ITvRequestRepository TvRepo { get; } + private IMovieRequestEngine MovieRequestEngine { get; } + private ITvRequestEngine TvRequestEngine { get; } private readonly ILogger _log; private readonly IPlexApi _plexApi; private readonly ISettingsService _plexSettings; @@ -103,7 +110,6 @@ namespace Ombi.Controllers private readonly IRepository _notificationRepository; private readonly IRepository _requestSubscriptionRepository; - /// /// This is what the Wizard will call when creating the user for the very first time. /// This should never be called after this. @@ -316,6 +322,16 @@ namespace Ombi.Controllers }); } + if (vm.EpisodeRequestLimit > 0) + { + vm.EpisodeRequestQuota = await TvRequestEngine.GetRemainingRequests(user); + } + + if (vm.MovieRequestLimit > 0) + { + vm.MovieRequestQuota = await MovieRequestEngine.GetRemainingRequests(user); + } + return vm; } From 30c9de818b9a93766a0fdb7145cbe14f0865c13f Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 5 Sep 2018 18:48:03 +0100 Subject: [PATCH 423/495] Add html for displaying remaining requests on users page --- .../usermanagement.component.html | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 519db023f..98bc8749b 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -48,6 +48,12 @@ Roles + + Requests Remaining + + + Next Request Due + Last Logged In @@ -85,6 +91,22 @@
    + +
    + Movies: {{u.movieRequestQuota.remaining}}/{{u.movieRequestLimit}} remaining +
    +
    + TV: {{u.episodeRequestQuota.remaining}}/{{u.episodeRequestLimit}} remaining +
    + + +
    + Movie: {{u.movieRequestQuota.nextRequest | date: 'short'}} +
    +
    + TV: {{u.episodeRequestQuota.nextRequest | date: 'short'}} +
    + {{u.lastLoggedIn | date: 'short'}} From c9b6f5f05eb56f108eac7beff797892fe9f6da26 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 5 Sep 2018 20:25:51 +0100 Subject: [PATCH 424/495] Add to translations --- src/Ombi.Core/Engine/MovieRequestEngine.cs | 6 ++++++ src/Ombi.Core/Engine/TvRequestEngine.cs | 6 ++++++ .../app/usermanagement/usermanagement.component.html | 8 ++++---- .../ClientApp/app/usermanagement/usermanagement.module.ts | 3 +++ src/Ombi/wwwroot/translations/en.json | 6 ++++++ 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 0cce7af58..9fd6033bf 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -491,6 +491,12 @@ namespace Ombi.Core.Engine if (user == null) { user = await GetUser(); + + // If user is still null after attempting to get the logged in user, return null. + if (user == null) + { + return null; + } } int limit = user.MovieRequestLimit ?? 0; diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index a700035a0..6a7f370d9 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -620,6 +620,12 @@ namespace Ombi.Core.Engine if (user == null) { user = await GetUser(); + + // If user is still null after attempting to get the logged in user, return null. + if (user == null) + { + return null; + } } int limit = user.EpisodeRequestLimit ?? 0; diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 98bc8749b..431ea7ddf 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -93,18 +93,18 @@
    - Movies: {{u.movieRequestQuota.remaining}}/{{u.movieRequestLimit}} remaining + {{'UserManagment.MovieRemaining' | translate: {remaining: u.movieRequestQuota.remaining, total: u.movieRequestLimit} }}
    - TV: {{u.episodeRequestQuota.remaining}}/{{u.episodeRequestLimit}} remaining + {{'UserManagment.TvRemaining' | translate: {remaining: u.episodeRequestQuota.remaining, total: u.episodeRequestLimit} }}
    - Movie: {{u.movieRequestQuota.nextRequest | date: 'short'}} + {{'UserManagment.MovieDue' | translate: {date: (u.movieRequestQuota.nextRequest | date: 'short')} }}
    - TV: {{u.episodeRequestQuota.nextRequest | date: 'short'}} + {{'UserManagment.TvDue' | translate: {date: (u.episodeRequestQuota.nextRequest | date: 'short')} }}
    diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index cf25446f5..1a91cf295 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -19,6 +19,8 @@ import { AuthGuard } from "../auth/auth.guard"; import { OrderModule } from "ngx-order-pipe"; import { AddPlexUserComponent } from "./addplexuser.component"; +import { SharedModule } from "../shared/shared.module"; + const routes: Routes = [ { path: "", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "add", component: UserManagementAddComponent, canActivate: [AuthGuard] }, @@ -39,6 +41,7 @@ const routes: Routes = [ TooltipModule, OrderModule, SidebarModule, + SharedModule, ], declarations: [ UserManagementComponent, diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index b38f5fb95..c53229c3d 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -184,5 +184,11 @@ "FilterHeaderRequestStatus":"Status", "Approved":"Approved", "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } From 5c95cf85e11bc96e4941f9cd797e746181837aab Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 5 Sep 2018 20:40:48 +0100 Subject: [PATCH 425/495] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index fdd1c6d63..c3e77d594 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -12,7 +12,7 @@ "Common": { "ContinueButton": "Weiter", "Available": "Verfügbar", - "PartiallyAvailable": "Partially Available", + "PartiallyAvailable": "Teilweise verfügbar", "Monitored": "Monitored", "NotAvailable": "Nicht verfügbar", "ProcessingRequest": "Anfrage wird bearbeitet", @@ -111,7 +111,7 @@ }, "Requests": { "Title": "Anfragen", - "Paragraph": "Unten sehen Sie Ihre und alle anderen Anfragen, sowie deren Download-und Genehmigungsstatus.", + "Paragraph": "Unten sehen Sie Ihre und alle anderen Anfragen, sowie deren Download und Genehmigungsstatus.", "MoviesTab": "Filme", "TvTab": "Serien", "MusicTab": "Music", From 366fa5edaac529137243fa31a66d06ad401ca9c9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 5 Sep 2018 20:51:14 +0100 Subject: [PATCH 426/495] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index c3e77d594..0a3dc2120 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -120,7 +120,7 @@ "RequestStatus": "Anfrage Status:", "Denied": " Abgelehnt:", "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", + "ReleaseDate": "Veröffentlicht: {{date}}", "TheatricalReleaseSort": "Theatrical Release", "DigitalRelease": "Digital Release: {{date}}", "RequestDate": "Datum der Anfrage:", From d081526e3f534c9d0d43ff7f7fd394ea95902d48 Mon Sep 17 00:00:00 2001 From: Kenton Royal Date: Wed, 5 Sep 2018 20:56:41 +0100 Subject: [PATCH 427/495] Fix bug in which requested TV wasn't logging for some users --- src/Ombi.Core/Engine/TvRequestEngine.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index 6a7f370d9..7994b23aa 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -588,6 +588,15 @@ namespace Ombi.Core.Engine NotificationHelper.NewRequest(model); } + await _requestLog.Add(new RequestLog + { + UserId = (await GetUser()).Id, + RequestDate = DateTime.UtcNow, + RequestId = model.Id, + RequestType = RequestType.TvShow, + EpisodeCount = model.SeasonRequests.Select(m => m.Episodes.Count).Sum(), + }); + if (model.Approved) { // Autosend @@ -603,15 +612,6 @@ namespace Ombi.Core.Engine }; } - await _requestLog.Add(new RequestLog - { - UserId = (await GetUser()).Id, - RequestDate = DateTime.UtcNow, - RequestId = model.Id, - RequestType = RequestType.TvShow, - EpisodeCount = model.SeasonRequests.Select(m => m.Episodes.Count).Sum(), - }); - return new RequestEngineResult { Result = true }; } From 9484c84488fe8e1f769b023f4df8459d96a33364 Mon Sep 17 00:00:00 2001 From: Stephen Panzer Date: Sat, 8 Sep 2018 15:06:51 -0600 Subject: [PATCH 428/495] Add href to a tags so that a pointer cursor shows on requests page --- src/Ombi/ClientApp/app/requests/request.component.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi/ClientApp/app/requests/request.component.html b/src/Ombi/ClientApp/app/requests/request.component.html index 45509fba3..d2df3c97a 100644 --- a/src/Ombi/ClientApp/app/requests/request.component.html +++ b/src/Ombi/ClientApp/app/requests/request.component.html @@ -3,14 +3,14 @@ From 8445b458bedb74e5b3e0d66e326c14c4bce2cba2 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 10 Sep 2018 14:52:26 +0100 Subject: [PATCH 429/495] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 90 +++++++++++++-------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 7885b7e31..b512b2568 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -12,8 +12,8 @@ "Common": { "ContinueButton": "Fortsätt", "Available": "Tillgänglig", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", + "PartiallyAvailable": "Delvis tillgänliga", + "Monitored": "Övervakad", "NotAvailable": "Finns ej", "ProcessingRequest": "Bearbetar förfrågan", "PendingApproval": "Väntar på godkännande", @@ -23,7 +23,7 @@ "Request": "Begär", "Denied": "Nekad", "Approve": "Godkän", - "PartlyAvailable": "Partly Available", + "PartlyAvailable": "Delvis tillgänglig", "Errors": { "Validation": "Vänligen kontrollera din angivna värden" } @@ -65,26 +65,26 @@ "Danish": "Danska", "Dutch": "Holländska", "Norwegian": "Norska", - "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish" + "BrazillianPortuguese": "Brazillian portugisiska", + "Polish": "Polska" }, "OpenMobileApp": "Öppna Mobil App", - "RecentlyAdded": "Recently Added" + "RecentlyAdded": "Nyligen tillagda" }, "Search": { "Title": "Sök", "Paragraph": "Vill du titta på något som inte är tillgängligt? Inga problem, Sök efter det nedan och önska det!", "MoviesTab": "Filmer", "TvTab": "TV-serier", - "MusicTab": "Music", + "MusicTab": "Musik", "Suggestions": "Förslag", "NoResults": "Tyvärr, hittade vi inte några resultat!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", + "DigitalDate": "Digitalt släpp: {{date}}", + "TheatricalRelease": "Biopremiär: {{date}}", "ViewOnPlex": "Visa på Plex", "ViewOnEmby": "Visa på Emby", "RequestAdded": "Efterfrågan om {{title}} har lagts till", - "Similar": "Similar", + "Similar": "Liknande", "Movies": { "PopularMovies": "Populära filmer", "UpcomingMovies": "Kommande filmer", @@ -94,19 +94,19 @@ "Trailer": "Trailer" }, "TvShows": { - "Popular": "Popular", - "Trending": "Trending", - "MostWatched": "Most Watched", - "MostAnticipated": "Most Anticipated", - "Results": "Results", - "AirDate": "Air Date:", - "AllSeasons": "All Seasons", - "FirstSeason": "First Season", - "LatestSeason": "Latest Season", - "Select": "Select ...", - "SubmitRequest": "Submit Request", - "Season": "Season: {{seasonNumber}}", - "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + "Popular": "Populära", + "Trending": "Trendar", + "MostWatched": "Mest sedda", + "MostAnticipated": "Mest efterlängtade", + "Results": "Resultat", + "AirDate": "Sändningsdatum:", + "AllSeasons": "Alla Säsonger", + "FirstSeason": "Första säsongen", + "LatestSeason": "Senaste säsongen", + "Select": "Välj...", + "SubmitRequest": "Skicka förfrågan", + "Season": "Säsong: {{seasonNumber}}", + "SelectAllInSeason": "Välj alla i denna säsong {{seasonNumber}}" } }, "Requests": { @@ -114,15 +114,15 @@ "Paragraph": "Nedan kan du se din och andras efterfrågningar, samt nedladdnings och godkännande status.", "MoviesTab": "Filmer", "TvTab": "TV-serier", - "MusicTab": "Music", + "MusicTab": "Musik", "RequestedBy": "Efterfrågats av:", "Status": "Status:", "RequestStatus": "Status för efterfrågan:", "Denied": " Nekad:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", + "TheatricalRelease": "Biopremiär: {{date}}", + "ReleaseDate": "Släppt: {{date}}", + "TheatricalReleaseSort": "Biopremiär", + "DigitalRelease": "Digitalt Releasedatum: {{date}}", "RequestDate": "Datum för efterfrågan:", "QualityOverride": "Kvalité överskridande:", "RootFolderOverride": "Root mapp överskridande:", @@ -136,22 +136,22 @@ "GridTitle": "Titel", "AirDate": "Sändningsdatum", "GridStatus": "Status", - "ReportIssue": "Report Issue", - "Filter": "Filter", - "Sort": "Sort", - "SeasonNumberHeading": "Season: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", + "ReportIssue": "Rapportera Problem", + "Filter": "Filtrera", + "Sort": "Sortera", + "SeasonNumberHeading": "Säsong: {seasonNumber}", + "SortTitleAsc": "Titel ▲", + "SortTitleDesc": "Titel ▼", + "SortRequestDateAsc": "Efterfrågades ▲", + "SortRequestDateDesc": "Efterfrågades ▼", "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Quota": "{{remaining}}/{{total}} återstående förfrågningar", + "NextDays": "En annan begäran kommer att läggas till om {{time}} Dagar", + "NextHours": "En annan begäran kommer att läggas till om {{time}} Timmar", + "NextMinutes": "En annan begäran kommer att läggas till om {{time}} Minuter", + "NextMinute": "En annan begäran kommer att läggas till om {{time}} Minut" } }, "Issues": { @@ -174,10 +174,10 @@ "ReportedBy": "Rapporterad av" }, "Filter": { - "ClearFilter": "Clear Filter", - "FilterHeaderAvailability": "Availability", + "ClearFilter": "Rensa filter", + "FilterHeaderAvailability": "Tillgänglighet", "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval" + "Approved": "Godkänd", + "PendingApproval": "Väntar på godkännande" } } \ No newline at end of file From 7d50a845ccbfc7d8e1ed6bc940b211d2d8d3bd27 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 12 Sep 2018 13:22:15 +0100 Subject: [PATCH 430/495] Users can now see the music search tab #2493 --- src/Ombi/ClientApp/app/search/search.component.ts | 2 +- src/Ombi/ClientApp/app/services/settings.service.ts | 4 ++++ src/Ombi/Controllers/SettingsController.cs | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/search/search.component.ts b/src/Ombi/ClientApp/app/search/search.component.ts index 74221e71c..43d926970 100644 --- a/src/Ombi/ClientApp/app/search/search.component.ts +++ b/src/Ombi/ClientApp/app/search/search.component.ts @@ -20,7 +20,7 @@ export class SearchComponent implements OnInit { } public ngOnInit() { - this.settingsService.getLidarr().subscribe(x => this.musicEnabled = x.enabled); + this.settingsService.lidarrEnabled().subscribe(x => this.musicEnabled = x); this.showMovie = true; this.showTv = false; this.showMusic = false; diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index 2016d10b7..b4611bfa8 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -96,6 +96,10 @@ export class SettingsService extends ServiceHelpers { return this.http.get(`${this.url}/Lidarr`, {headers: this.headers}); } + public lidarrEnabled(): Observable { + return this.http.get(`${this.url}/lidarrenabled`, {headers: this.headers}); + } + public saveLidarr(settings: ILidarrSettings): Observable { return this.http.post(`${this.url}/Lidarr`, JSON.stringify(settings), {headers: this.headers}); } diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 84192c53c..474ae8823 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -328,6 +328,18 @@ namespace Ombi.Controllers return await Get(); } + /// + /// Gets the Lidarr Settings. + /// + /// + [HttpGet("lidarrenabled")] + [AllowAnonymous] + public async Task LidarrEnabled() + { + var settings = await Get(); + return settings.Enabled; + } + /// /// Save the Lidarr settings. /// From f6dd41918de499bd2a9e33b1a8c8dadc03f168bd Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:39 +0100 Subject: [PATCH 431/495] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 324bfccf1..61f8c718d 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Godkendt", "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From 766a63261b3bd16d324aced38d248417fdfa234d Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:41 +0100 Subject: [PATCH 432/495] New translations en.json (Dutch) --- src/Ombi/wwwroot/translations/nl.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 313d34dcb..c32195922 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Goedgekeurd", "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From f40f73a2238f9d7801dcb7658f3ec0cb88f338ee Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:43 +0100 Subject: [PATCH 433/495] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 24080f9f7..7c5201aa9 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Statut", "Approved": "Validée", "PendingApproval": "En attente de validation" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From 3b3dbc3d8000eb5383d5079f111555d9c3ab6aec Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:44 +0100 Subject: [PATCH 434/495] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 0a3dc2120..219de654e 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Bestätigt", "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From 01f104058c0f30eb8f099be9e6945718389e8c0c Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:45 +0100 Subject: [PATCH 435/495] New translations en.json (Italian) --- src/Ombi/wwwroot/translations/it.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 647032425..fc9cec63d 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Approved", "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From e58d07d4a552ef7b01fd54f8288564e008819a90 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:47 +0100 Subject: [PATCH 436/495] New translations en.json (Norwegian) --- src/Ombi/wwwroot/translations/no.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index b6b162621..58c5c93c2 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Godkjent", "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From c7983887036dddf80af7ec2d4bc34d4e68a4b024 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:48 +0100 Subject: [PATCH 437/495] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 55c8b8060..5378c8334 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Stan", "Approved": "Zatwierdzone", "PendingApproval": "Oczekujące na zatwierdzenie" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From 2640b31231ae54346db5f1345dc4c21debed2ecd Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:49 +0100 Subject: [PATCH 438/495] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index d1d15bcc5..62b5d8b1b 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Aprovado", "PendingApproval": "Aprovação Pendente" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From edd7ff4c44e6d5a576cea87c0e5c518e34f2dd23 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:51 +0100 Subject: [PATCH 439/495] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 0dee65f9a..d99050613 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Approved", "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From a5a50530e18b016873a1702c079b7e4b5fb8f08d Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 12 Sep 2018 13:31:52 +0100 Subject: [PATCH 440/495] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index b512b2568..4d2ee773c 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -179,5 +179,11 @@ "FilterHeaderRequestStatus": "Status", "Approved": "Godkänd", "PendingApproval": "Väntar på godkännande" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}" } } \ No newline at end of file From 9903b17764cda764635a173b581b5f7cdbe8a6cf Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 13 Sep 2018 11:40:59 +0100 Subject: [PATCH 441/495] Update the .net core packages to fix "CVE-2018-8409: ASP.NET Core Denial Of Service Vulnerability" --- src/Ombi/Ombi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 6640a8eb8..f01e7c05d 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -71,7 +71,7 @@ - + From 8915e64ff36f8173dd3a2830b98a353f1efffa7e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 13 Sep 2018 11:45:19 +0100 Subject: [PATCH 442/495] Updated all the MS packages --- src/Ombi.Core/Ombi.Core.csproj | 2 +- .../Ombi.DependencyInjection.csproj | 4 ++-- src/Ombi.Helpers/Ombi.Helpers.csproj | 2 +- src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj | 2 +- src/Ombi.Store/Ombi.Store.csproj | 8 ++++---- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index c2aeb1fd0..10e07822a 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj index 6fe083fe3..028c37b43 100644 --- a/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj +++ b/src/Ombi.DependencyInjection/Ombi.DependencyInjection.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/src/Ombi.Helpers/Ombi.Helpers.csproj b/src/Ombi.Helpers/Ombi.Helpers.csproj index e94afc816..2aaaa076f 100644 --- a/src/Ombi.Helpers/Ombi.Helpers.csproj +++ b/src/Ombi.Helpers/Ombi.Helpers.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj index a124f01bd..ea1d17f8c 100644 --- a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj +++ b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/Ombi.Store/Ombi.Store.csproj b/src/Ombi.Store/Ombi.Store.csproj index 2ceb78424..cdbd3fe84 100644 --- a/src/Ombi.Store/Ombi.Store.csproj +++ b/src/Ombi.Store/Ombi.Store.csproj @@ -10,10 +10,10 @@ - - - - + + + + From 3bcaefc24a6b4d20dcf193d71e129ec9b5ef0319 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 18 Sep 2018 12:39:44 +0100 Subject: [PATCH 443/495] Fixed #2516 --- src/Ombi/ClientApp/app/search/music/albumsearch.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html index fd5f71075..d2430bd62 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.html @@ -13,7 +13,7 @@

    - {{result.title}} + {{result.title | truncate: 36}}

    From 2e90edd9c3560c8d90983e3d381019c48d423353 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 18 Sep 2018 12:48:29 +0100 Subject: [PATCH 444/495] Fixed #2485 --- .../ClientApp/app/login/login.component.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Ombi/ClientApp/app/login/login.component.ts b/src/Ombi/ClientApp/app/login/login.component.ts index abf387fa1..0c04edbad 100644 --- a/src/Ombi/ClientApp/app/login/login.component.ts +++ b/src/Ombi/ClientApp/app/login/login.component.ts @@ -127,18 +127,18 @@ export class LoginComponent implements OnDestroy, OnInit { } public oauth() { + const oAuthWindow = window.open(window.location.toString(), "_blank", `toolbar=0, + location=0, + status=0, + menubar=0, + scrollbars=1, + resizable=1, + width=500, + height=500`); this.plexTv.GetPin(this.clientId, this.appName).subscribe((pin: any) => { this.authService.login({ usePlexOAuth: true, password: "", rememberMe: true, username: "", plexTvPin: pin }).subscribe(x => { - - window.open(x.url, "_blank", `toolbar=0, - location=0, - status=0, - menubar=0, - scrollbars=1, - resizable=1, - width=500, - height=500`); + oAuthWindow!.location.replace(x.url); this.pinTimer = setInterval(() => { this.notify.info("Authenticating", "Loading... Please Wait"); From 2886f6e6fa2f81bb2595b4228a7f6368448d71f2 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 18 Sep 2018 13:05:41 +0100 Subject: [PATCH 445/495] Consolodated the usermanagement stuff, still a !wip but it's a start --- .../usermanagement-add.component.html | 79 --------- .../usermanagement-add.component.ts | 70 -------- .../usermanagement-edit.component.html | 70 -------- .../usermanagement-user.component.html | 154 ++++++++++++++++++ ...nt.ts => usermanagement-user.component.ts} | 92 +++++++++-- .../usermanagement.component.html | 4 +- .../usermanagement/usermanagement.module.ts | 4 +- 7 files changed, 235 insertions(+), 238 deletions(-) delete mode 100644 src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.html delete mode 100644 src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts delete mode 100644 src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.html create mode 100644 src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html rename src/Ombi/ClientApp/app/usermanagement/{usermanagement-edit.component.ts => usermanagement-user.component.ts} (51%) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.html deleted file mode 100644 index 683bd5620..000000000 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.html +++ /dev/null @@ -1,79 +0,0 @@ - -

    Create User

    - - - -
    -
    - - -
    -
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts deleted file mode 100644 index 36b187e79..000000000 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-add.component.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Component, OnInit } from "@angular/core"; -import { Router } from "@angular/router"; - -import { ICheckbox, IUser, UserType } from "../interfaces"; -import { IdentityService, NotificationService } from "../services"; - -@Component({ - templateUrl: "./usermanagement-add.component.html", -}) -export class UserManagementAddComponent implements OnInit { - public user: IUser; - public availableClaims: ICheckbox[]; - public confirmPass: ""; - - constructor(private identityService: IdentityService, - private notificationSerivce: NotificationService, - private router: Router) { } - - public ngOnInit() { - this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); - this.user = { - alias: "", - claims: [], - emailAddress: "", - id: "", - password: "", - userName: "", - userType: UserType.LocalUser, - checked: false, - hasLoggedIn: false, - lastLoggedIn: new Date(), - episodeRequestLimit: 0, - movieRequestLimit: 0, - userAccessToken: "", - }; - } - - public create() { - this.user.claims = this.availableClaims; - - if (this.user.password) { - if (this.user.password !== this.confirmPass) { - this.notificationSerivce.error("Passwords do not match"); - return; - } - } - const hasClaims = this.availableClaims.some((item) => { - if (item.enabled) { return true; } - - return false; - }); - - if (!hasClaims) { - this.notificationSerivce.error("Please assign a role"); - return; - } - - this.identityService.createUser(this.user).subscribe(x => { - if (x.successful) { - this.notificationSerivce.success(`The user ${this.user.userName} has been created successfully`); - this.router.navigate(["usermanagement"]); - } else { - x.errors.forEach((val) => { - this.notificationSerivce.error(val); - }); - } - }); - } - -} diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.html deleted file mode 100644 index 95a70cab0..000000000 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.html +++ /dev/null @@ -1,70 +0,0 @@ -
    -
    -

    User: {{user.userName}}

    - - - - - - -
    - - - - -
    -
    -
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html new file mode 100644 index 000000000..0dcb24cb4 --- /dev/null +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -0,0 +1,154 @@ +
    +

    Create User

    + + + +
    +
    + + +
    +
    +
    + +
    + +
    +
    +

    User: {{user.userName}}

    + + + + + + +
    + + + + +
    +
    +
    +
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts similarity index 51% rename from src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.ts rename to src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index a83ef5a97..bca4f1058 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-edit.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -1,32 +1,92 @@ -import { Component } from "@angular/core"; -import { Router } from "@angular/router"; +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { ICheckbox, IUser, UserType } from "../interfaces"; +import { IdentityService, NotificationService } from "../services"; + import { ConfirmationService } from "primeng/primeng"; -import { ActivatedRoute } from "@angular/router"; -import { IUser } from "../interfaces"; -import { IdentityService } from "../services"; -import { NotificationService } from "../services"; - @Component({ - templateUrl: "./usermanagement-edit.component.html", + templateUrl: "./usermanagement-user.component.html", }) -export class UserManagementEditComponent { +export class UserManagementUserComponent implements OnInit { + public user: IUser; public userId: string; + public availableClaims: ICheckbox[]; + public confirmPass: ""; + + public edit: boolean; constructor(private identityService: IdentityService, - private route: ActivatedRoute, private notificationService: NotificationService, private router: Router, + private route: ActivatedRoute, private confirmationService: ConfirmationService) { - this.route.params + this.route.params .subscribe((params: any) => { - this.userId = params.id; - - this.identityService.getUserById(this.userId).subscribe(x => { - this.user = x; - }); + if(params.id) { + this.userId = params.id; + this.edit = true; + this.identityService.getUserById(this.userId).subscribe(x => { + this.user = x; + }); + } }); + + } + + public ngOnInit() { + this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); + if(!this.edit) { + this.user = { + alias: "", + claims: [], + emailAddress: "", + id: "", + password: "", + userName: "", + userType: UserType.LocalUser, + checked: false, + hasLoggedIn: false, + lastLoggedIn: new Date(), + episodeRequestLimit: 0, + movieRequestLimit: 0, + userAccessToken: "", + }; + } + } + + public create() { + this.user.claims = this.availableClaims; + + if (this.user.password) { + if (this.user.password !== this.confirmPass) { + this.notificationService.error("Passwords do not match"); + return; + } + } + const hasClaims = this.availableClaims.some((item) => { + if (item.enabled) { return true; } + + return false; + }); + + if (!hasClaims) { + this.notificationService.error("Please assign a role"); + return; + } + + this.identityService.createUser(this.user).subscribe(x => { + if (x.successful) { + this.notificationService.success(`The user ${this.user.userName} has been created successfully`); + this.router.navigate(["usermanagement"]); + } else { + x.errors.forEach((val) => { + this.notificationService.error(val); + }); + } + }); } public delete() { diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 519db023f..de78f64f8 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -2,7 +2,7 @@ - +
    @@ -94,7 +94,7 @@ Emby User - Details/Edit + Details/Edit diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index cf25446f5..7ff799729 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -10,6 +10,7 @@ import { UpdateDetailsComponent } from "./updatedetails.component"; import { UserManagementAddComponent } from "./usermanagement-add.component"; import { UserManagementEditComponent } from "./usermanagement-edit.component"; import { UserManagementComponent } from "./usermanagement.component"; +import { UserManagementUserComponent } from "./usermanagement-user.component"; import { PipeModule } from "../pipes/pipe.module"; import { IdentityService, PlexService } from "../services"; @@ -22,7 +23,7 @@ import { AddPlexUserComponent } from "./addplexuser.component"; const routes: Routes = [ { path: "", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "add", component: UserManagementAddComponent, canActivate: [AuthGuard] }, - { path: "edit/:id", component: UserManagementEditComponent, canActivate: [AuthGuard] }, + { path: "user", component: UserManagementUserComponent, canActivate: [AuthGuard] }, { path: "updatedetails", component: UpdateDetailsComponent, canActivate: [AuthGuard] }, ]; @@ -46,6 +47,7 @@ const routes: Routes = [ UserManagementEditComponent, UpdateDetailsComponent, AddPlexUserComponent, + UserManagementUserComponent, ], entryComponents:[ AddPlexUserComponent, From de2e3abfe02c70fbe1a61d51b2409ed189138f67 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 18 Sep 2018 14:15:26 +0100 Subject: [PATCH 446/495] Added the API to add user notification preferences --- src/Ombi.Store/Entities/OmbiUser.cs | 1 + .../Entities/UserNotificationPreferences.cs | 7 ++- src/Ombi/Controllers/IdentityController.cs | 50 +++++++++++++++++-- .../Identity/AddNotificationPreference.cs | 12 +++++ 4 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 src/Ombi/Models/Identity/AddNotificationPreference.cs diff --git a/src/Ombi.Store/Entities/OmbiUser.cs b/src/Ombi.Store/Entities/OmbiUser.cs index 9513df818..801a50cb1 100644 --- a/src/Ombi.Store/Entities/OmbiUser.cs +++ b/src/Ombi.Store/Entities/OmbiUser.cs @@ -28,6 +28,7 @@ namespace Ombi.Store.Entities public string UserAccessToken { get; set; } public List NotificationUserIds { get; set; } + public List UserNotificationPreferences { get; set; } [NotMapped] public bool IsEmbyConnect => UserType == UserType.EmbyUser && EmbyConnectUserId.HasValue(); diff --git a/src/Ombi.Store/Entities/UserNotificationPreferences.cs b/src/Ombi.Store/Entities/UserNotificationPreferences.cs index c779480c8..7196d38ca 100644 --- a/src/Ombi.Store/Entities/UserNotificationPreferences.cs +++ b/src/Ombi.Store/Entities/UserNotificationPreferences.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Text; +using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; using Ombi.Helpers; namespace Ombi.Store.Entities @@ -15,6 +13,7 @@ namespace Ombi.Store.Entities public string Value { get; set; } [ForeignKey(nameof(UserId))] + [JsonIgnore] public OmbiUser User { get; set; } } } diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index d7e556f26..71cac7a76 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -793,15 +793,14 @@ namespace Ombi.Controllers [HttpGet("notificationpreferences")] public async Task> GetUserPreferences() { - //TODO potentially use a view model var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); var userPreferences = await _userNotificationPreferences.GetAll().Where(x => x.UserId == user.Id).ToListAsync(); var agents = Enum.GetValues(typeof(NotificationAgent)).Cast(); foreach (var a in agents) { - var hasAgent = userPreferences.Any(x => x.Agent == a); - if (!hasAgent) + var agent = userPreferences.FirstOrDefault(x => x.Agent == a); + if (agent == null) { // Create the default userPreferences.Add(new UserNotificationPreferences @@ -809,11 +808,56 @@ namespace Ombi.Controllers Agent = a, }); } + else + { + userPreferences.Add(agent); + } } return userPreferences; } + [HttpPost("NotificationPreferences")] + public async Task AddUserNotificationPreference([FromBody] AddNotificationPreference pref) + { + // Make sure the user exists + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == pref.UserId); + if (user == null) + { + return NotFound(); + } + // Check if we are editing a different user than ourself, if we are then we need to power user role + var me = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + if (!me.Id.Equals(user.Id, StringComparison.InvariantCultureIgnoreCase)) + { + var isPowerUser = await UserManager.IsInRoleAsync(me, OmbiRoles.PowerUser); + var isAdmin = await UserManager.IsInRoleAsync(me, OmbiRoles.Admin); + if (!isPowerUser && !isAdmin) + { + return Unauthorized(); + } + } + + // Make sure we don't already have a preference for this agent + var existingPreference = await _userNotificationPreferences.GetAll() + .FirstOrDefaultAsync(x => x.UserId == user.Id && x.Agent == pref.Agent); + if (existingPreference != null) + { + // Update it + existingPreference.Value = pref.Value; + existingPreference.Enabled = pref.Enabled; + } + await _userNotificationPreferences.Add(new UserNotificationPreferences + { + Agent = pref.Agent, + Enabled = pref.Enabled, + UserId = pref.UserId, + Value = pref.Value + }); + + return Json(true); + } + private async Task> AddRoles(IEnumerable roles, OmbiUser ombiUser) { var roleResult = new List(); diff --git a/src/Ombi/Models/Identity/AddNotificationPreference.cs b/src/Ombi/Models/Identity/AddNotificationPreference.cs new file mode 100644 index 000000000..51dc7f6fe --- /dev/null +++ b/src/Ombi/Models/Identity/AddNotificationPreference.cs @@ -0,0 +1,12 @@ +using Ombi.Helpers; + +namespace Ombi.Models.Identity +{ + public class AddNotificationPreference + { + public NotificationAgent Agent { get; set; } + public string UserId { get; set; } + public string Value { get; set; } + public bool Enabled { get; set; } + } +} \ No newline at end of file From 8573b7c729aba788bd575cdbf994d33ff8fed53e Mon Sep 17 00:00:00 2001 From: TidusJar Date: Tue, 18 Sep 2018 15:51:22 +0100 Subject: [PATCH 447/495] Did the notification side of things with the custom user defined preference !wip --- .../Agents/DiscordNotification.cs | 5 +++-- .../Agents/EmailNotification.cs | 3 ++- .../Agents/MattermostNotification.cs | 3 ++- .../Agents/MobileNotification.cs | 3 ++- .../Agents/PushbulletNotification.cs | 3 ++- .../Agents/PushoverNotification.cs | 3 ++- .../Agents/SlackNotification.cs | 3 ++- .../Agents/TelegramNotification.cs | 3 ++- src/Ombi.Notifications/BaseNotification.cs | 22 ++++++++++++++----- .../NotificationMessageCurlys.cs | 10 ++++++--- .../usermanagement/usermanagement.module.ts | 3 --- src/Ombi/Ombi.csproj | 2 +- 12 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/Ombi.Notifications/Agents/DiscordNotification.cs b/src/Ombi.Notifications/Agents/DiscordNotification.cs index d788b471c..84e907053 100644 --- a/src/Ombi.Notifications/Agents/DiscordNotification.cs +++ b/src/Ombi.Notifications/Agents/DiscordNotification.cs @@ -20,8 +20,9 @@ namespace Ombi.Notifications.Agents { public DiscordNotification(IDiscordApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, - IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music) - : base(sn, r, m, t, s, log, sub, music) + IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) + : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs index 3ab045e87..cff1f3b80 100644 --- a/src/Ombi.Notifications/Agents/EmailNotification.cs +++ b/src/Ombi.Notifications/Agents/EmailNotification.cs @@ -22,7 +22,8 @@ namespace Ombi.Notifications.Agents public class EmailNotification : BaseNotification, IEmailNotification { public EmailNotification(ISettingsService settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService c, - ILogger log, UserManager um, IRepository sub, IMusicRequestRepository music) : base(settings, r, m, t, c, log, sub, music) + ILogger log, UserManager um, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(settings, r, m, t, c, log, sub, music, userPref) { EmailProvider = prov; Logger = log; diff --git a/src/Ombi.Notifications/Agents/MattermostNotification.cs b/src/Ombi.Notifications/Agents/MattermostNotification.cs index 9e8a34e3b..37e597854 100644 --- a/src/Ombi.Notifications/Agents/MattermostNotification.cs +++ b/src/Ombi.Notifications/Agents/MattermostNotification.cs @@ -21,7 +21,8 @@ namespace Ombi.Notifications.Agents public class MattermostNotification : BaseNotification, IMattermostNotification { public MattermostNotification(IMattermostApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs index c521b99a4..a16785909 100644 --- a/src/Ombi.Notifications/Agents/MobileNotification.cs +++ b/src/Ombi.Notifications/Agents/MobileNotification.cs @@ -22,7 +22,8 @@ namespace Ombi.Notifications.Agents { public MobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, - UserManager um, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + UserManager um, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { _api = api; _logger = log; diff --git a/src/Ombi.Notifications/Agents/PushbulletNotification.cs b/src/Ombi.Notifications/Agents/PushbulletNotification.cs index 0e488bf79..6c6b1f789 100644 --- a/src/Ombi.Notifications/Agents/PushbulletNotification.cs +++ b/src/Ombi.Notifications/Agents/PushbulletNotification.cs @@ -17,7 +17,8 @@ namespace Ombi.Notifications.Agents public class PushbulletNotification : BaseNotification, IPushbulletNotification { public PushbulletNotification(IPushbulletApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs index b5d743cc2..86f91dbaa 100644 --- a/src/Ombi.Notifications/Agents/PushoverNotification.cs +++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs @@ -18,7 +18,8 @@ namespace Ombi.Notifications.Agents public class PushoverNotification : BaseNotification, IPushoverNotification { public PushoverNotification(IPushoverApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/SlackNotification.cs b/src/Ombi.Notifications/Agents/SlackNotification.cs index 6c04f5ea6..ee81e9729 100644 --- a/src/Ombi.Notifications/Agents/SlackNotification.cs +++ b/src/Ombi.Notifications/Agents/SlackNotification.cs @@ -18,7 +18,8 @@ namespace Ombi.Notifications.Agents public class SlackNotification : BaseNotification, ISlackNotification { public SlackNotification(ISlackApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, - ISettingsService s, IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music) + ISettingsService s, IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/TelegramNotification.cs b/src/Ombi.Notifications/Agents/TelegramNotification.cs index 7bcda7c7f..cf463bf99 100644 --- a/src/Ombi.Notifications/Agents/TelegramNotification.cs +++ b/src/Ombi.Notifications/Agents/TelegramNotification.cs @@ -19,7 +19,8 @@ namespace Ombi.Notifications.Agents public TelegramNotification(ITelegramApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s - , IRepository sub, IMusicRequestRepository music) : base(sn, r, m, t,s,log, sub, music) + , IRepository sub, IMusicRequestRepository music, + IRepository userPref) : base(sn, r, m, t,s,log, sub, music, userPref) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index 287f86455..d351c8283 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -19,7 +19,8 @@ namespace Ombi.Notifications.Interfaces public abstract class BaseNotification : INotification where T : Settings.Settings.Models.Settings, new() { protected BaseNotification(ISettingsService settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv, - ISettingsService customization, ILogger> log, IRepository sub, IMusicRequestRepository album) + ISettingsService customization, ILogger> log, IRepository sub, IMusicRequestRepository album, + IRepository notificationUserPreferences) { Settings = settings; TemplateRepository = templateRepo; @@ -31,6 +32,7 @@ namespace Ombi.Notifications.Interfaces RequestSubscription = sub; _log = log; AlbumRepository = album; + UserNotificationPreferences = notificationUserPreferences; } protected ISettingsService Settings { get; } @@ -40,6 +42,7 @@ namespace Ombi.Notifications.Interfaces protected IMusicRequestRepository AlbumRepository { get; } protected CustomizationSettings Customization { get; set; } protected IRepository RequestSubscription { get; set; } + protected IRepository UserNotificationPreferences { get; set; } private ISettingsService CustomizationSettings { get; } private readonly ILogger> _log; @@ -167,7 +170,7 @@ namespace Ombi.Notifications.Interfaces { return new NotificationMessageContent { Disabled = true }; } - var parsed = Parse(model, template); + var parsed = Parse(model, template, agent); return parsed; } @@ -178,25 +181,32 @@ namespace Ombi.Notifications.Interfaces return subs.Select(x => x.User); } - private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template) + protected UserNotificationPreferences GetUserPreference(string userId, NotificationAgent agent) + { + return UserNotificationPreferences.GetAll() + .FirstOrDefault(x => x.Enabled && x.Agent == agent && x.UserId == userId); + } + + private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template, NotificationAgent agent) { var resolver = new NotificationMessageResolver(); var curlys = new NotificationMessageCurlys(); + var preference = GetUserPreference(model.UserId, agent); if (model.RequestType == RequestType.Movie) { _log.LogDebug("Notification options: {@model}, Req: {@MovieRequest}, Settings: {@Customization}", model, MovieRequest, Customization); - curlys.Setup(model, MovieRequest, Customization); + curlys.Setup(model, MovieRequest, Customization, preference); } else if (model.RequestType == RequestType.TvShow) { _log.LogDebug("Notification options: {@model}, Req: {@TvRequest}, Settings: {@Customization}", model, TvRequest, Customization); - curlys.Setup(model, TvRequest, Customization); + curlys.Setup(model, TvRequest, Customization, preference); } else if (model.RequestType == RequestType.Album) { _log.LogDebug("Notification options: {@model}, Req: {@AlbumRequest}, Settings: {@Customization}", model, AlbumRequest, Customization); - curlys.Setup(model, AlbumRequest, Customization); + curlys.Setup(model, AlbumRequest, Customization, preference); } var parsed = resolver.ParseMessage(template, curlys); diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 710f64619..5bc74f68e 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -14,9 +14,10 @@ namespace Ombi.Notifications { public class NotificationMessageCurlys { - public void Setup(NotificationOptions opts, FullBaseRequest req, CustomizationSettings s) + public void Setup(NotificationOptions opts, FullBaseRequest req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); + UserPreference = pref.Enabled ? pref.Value : string.Empty; string title; if (req == null) { @@ -58,9 +59,10 @@ namespace Ombi.Notifications AdditionalInformation = opts?.AdditionalInformation ?? string.Empty; } - public void Setup(NotificationOptions opts, AlbumRequest req, CustomizationSettings s) + public void Setup(NotificationOptions opts, AlbumRequest req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); + UserPreference = pref.Enabled ? pref.Value : string.Empty; string title; if (req == null) { @@ -101,9 +103,10 @@ namespace Ombi.Notifications Alias = username.Alias.HasValue() ? username.Alias : username.UserName; } - public void Setup(NotificationOptions opts, ChildRequests req, CustomizationSettings s) + public void Setup(NotificationOptions opts, ChildRequests req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); + UserPreference = pref.Enabled ? pref.Value : string.Empty; string title; if (req == null) { @@ -221,6 +224,7 @@ namespace Ombi.Notifications public string IssueStatus { get; set; } public string IssueSubject { get; set; } public string NewIssueComment { get; set; } + public string UserPreference { get; set; } // System Defined private string LongDate => DateTime.Now.ToString("D"); diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index 7ff799729..81101978e 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -7,8 +7,6 @@ import { ConfirmationService, ConfirmDialogModule, MultiSelectModule, SidebarMod import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { UpdateDetailsComponent } from "./updatedetails.component"; -import { UserManagementAddComponent } from "./usermanagement-add.component"; -import { UserManagementEditComponent } from "./usermanagement-edit.component"; import { UserManagementComponent } from "./usermanagement.component"; import { UserManagementUserComponent } from "./usermanagement-user.component"; @@ -22,7 +20,6 @@ import { AddPlexUserComponent } from "./addplexuser.component"; const routes: Routes = [ { path: "", component: UserManagementComponent, canActivate: [AuthGuard] }, - { path: "add", component: UserManagementAddComponent, canActivate: [AuthGuard] }, { path: "user", component: UserManagementUserComponent, canActivate: [AuthGuard] }, { path: "updatedetails", component: UpdateDetailsComponent, canActivate: [AuthGuard] }, ]; diff --git a/src/Ombi/Ombi.csproj b/src/Ombi/Ombi.csproj index 6640a8eb8..1ca47d306 100644 --- a/src/Ombi/Ombi.csproj +++ b/src/Ombi/Ombi.csproj @@ -8,7 +8,7 @@ $(SemVer) $(FullVer) - 2.8 + 3.0 false From 2204559b0aee9dfc1ca50ff9336d1e3fa9957001 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 13:38:41 +0100 Subject: [PATCH 448/495] Added the Notification Preferences to the user --- ...24_UserNotificationPreferences.Designer.cs | 1118 +++++++++++++++++ ...80919073124_UserNotificationPreferences.cs | 43 + .../Migrations/OmbiContextModelSnapshot.cs | 29 +- src/Ombi/ClientApp/app/interfaces/IUser.ts | 19 + .../app/services/identity.service.ts | 14 +- .../usermanagement-user.component.html | 285 +++-- .../usermanagement-user.component.ts | 12 +- .../usermanagement/usermanagement.module.ts | 3 +- src/Ombi/Controllers/IdentityController.cs | 98 +- 9 files changed, 1431 insertions(+), 190 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.cs diff --git a/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.Designer.cs b/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.Designer.cs new file mode 100644 index 000000000..d61ea31ba --- /dev/null +++ b/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.Designer.cs @@ -0,0 +1,1118 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180919073124_UserNotificationPreferences")] + partial class UserNotificationPreferences + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + 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.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .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 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.cs b/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.cs new file mode 100644 index 000000000..adb062af7 --- /dev/null +++ b/src/Ombi.Store/Migrations/20180919073124_UserNotificationPreferences.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class UserNotificationPreferences : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "UserNotificationPreferences", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: true), + Agent = table.Column(nullable: false), + Enabled = table.Column(nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserNotificationPreferences", x => x.Id); + table.ForeignKey( + name: "FK_UserNotificationPreferences_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_UserNotificationPreferences_UserId", + table: "UserNotificationPreferences", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "UserNotificationPreferences"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 64400e58c..5e5aa23c6 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.1-rtm-30846"); + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -870,6 +870,26 @@ namespace Ombi.Store.Migrations b.ToTable("Tokens"); }); + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.Property("Id") @@ -1068,6 +1088,13 @@ namespace Ombi.Store.Migrations .HasForeignKey("UserId"); }); + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index cd96848fb..04546abf9 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -66,3 +66,22 @@ export interface IMassEmailModel { body: string; users: IUser[]; } + +export interface INotificationPreferences { + id: number; + userId: string; + agent: INotificationAgent; + enabled: boolean; + value: string; +} + +export enum INotificationAgent { + Email = 0, + Discord = 1, + Pushbullet = 2, + Pushover = 3, + Telegram = 4, + Slack = 5, + Mattermost = 6, + Mobile = 7, +} diff --git a/src/Ombi/ClientApp/app/services/identity.service.ts b/src/Ombi/ClientApp/app/services/identity.service.ts index e3dc1d8ad..bce159ebe 100644 --- a/src/Ombi/ClientApp/app/services/identity.service.ts +++ b/src/Ombi/ClientApp/app/services/identity.service.ts @@ -4,7 +4,7 @@ import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; -import { ICheckbox, ICreateWizardUser, IIdentityResult, IResetPasswordToken, IUpdateLocalUser, IUser, IWizardUserResult } from "../interfaces"; +import { ICheckbox, ICreateWizardUser, IIdentityResult, INotificationPreferences, IResetPasswordToken, IUpdateLocalUser, IUser, IWizardUserResult } from "../interfaces"; import { ServiceHelpers } from "./service.helpers"; @Injectable() @@ -43,6 +43,11 @@ export class IdentityService extends ServiceHelpers { public updateUser(user: IUser): Observable { return this.http.put(this.url, JSON.stringify(user), {headers: this.headers}); } + + public updateNotificationPreferences(pref: INotificationPreferences[]): Observable { + return this.http.post(`${this.url}NotificationPreferences`, JSON.stringify(pref), {headers: this.headers}); + } + public updateLocalUser(user: IUpdateLocalUser): Observable { return this.http.put(this.url + "local", JSON.stringify(user), {headers: this.headers}); } @@ -67,6 +72,13 @@ export class IdentityService extends ServiceHelpers { return this.http.post(`${this.url}welcomeEmail`, JSON.stringify(user), {headers: this.headers}); } + public getNotificationPreferences(): Observable { + return this.http.get(`${this.url}notificationpreferences`, {headers: this.headers}); + } + public getNotificationPreferencesForUser(userId: string): Observable { + return this.http.get(`${this.url}notificationpreferences/${userId}`, {headers: this.headers}); + } + public hasRole(role: string): boolean { const roles = localStorage.getItem("roles") as string[] | null; if (roles) { diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index 0dcb24cb4..da1b4076e 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -1,153 +1,150 @@ -
    -

    Create User

    +

    Create User

    +

    User: {{user.userName}}

    +
    - - -
    - -
    -
    -

    User: {{user.userName}}

    - - - - - - -
    +
    + +
    - - + +
    diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index bca4f1058..e06c7c12b 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { ICheckbox, IUser, UserType } from "../interfaces"; +import { ICheckbox, INotificationAgent, INotificationPreferences, IUser, UserType } from "../interfaces"; import { IdentityService, NotificationService } from "../services"; import { ConfirmationService } from "primeng/primeng"; @@ -15,7 +15,9 @@ export class UserManagementUserComponent implements OnInit { public userId: string; public availableClaims: ICheckbox[]; public confirmPass: ""; - + public notificationPreferences: INotificationPreferences[]; + + public NotificationAgent = INotificationAgent; public edit: boolean; constructor(private identityService: IdentityService, @@ -38,6 +40,11 @@ export class UserManagementUserComponent implements OnInit { public ngOnInit() { this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x); + if(this.edit) { + this.identityService.getNotificationPreferencesForUser(this.userId).subscribe(x => this.notificationPreferences = x); + } else { + this.identityService.getNotificationPreferences().subscribe(x => this.notificationPreferences = x); + } if(!this.edit) { this.user = { alias: "", @@ -142,6 +149,7 @@ export class UserManagementUserComponent implements OnInit { this.identityService.updateUser(this.user).subscribe(x => { if (x.successful) { + this.identityService.updateNotificationPreferences(this.notificationPreferences).subscribe(); this.notificationService.success(`The user ${this.user.userName} has been updated successfully`); this.router.navigate(["usermanagement"]); } else { diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index 81101978e..f12476677 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -21,6 +21,7 @@ import { AddPlexUserComponent } from "./addplexuser.component"; const routes: Routes = [ { path: "", component: UserManagementComponent, canActivate: [AuthGuard] }, { path: "user", component: UserManagementUserComponent, canActivate: [AuthGuard] }, + { path: "user/:id", component: UserManagementUserComponent, canActivate: [AuthGuard] }, { path: "updatedetails", component: UpdateDetailsComponent, canActivate: [AuthGuard] }, ]; @@ -40,8 +41,6 @@ const routes: Routes = [ ], declarations: [ UserManagementComponent, - UserManagementAddComponent, - UserManagementEditComponent, UpdateDetailsComponent, AddPlexUserComponent, UserManagementUserComponent, diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 71cac7a76..9e89a9506 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -125,7 +125,7 @@ namespace Ombi.Controllers if (users.Any(x => !x.UserName.Equals("api", StringComparison.InvariantCultureIgnoreCase))) { // No one should be calling this. Only the wizard - return new SaveWizardResult{ Result = false, Errors = new List {"Looks like there is an existing user!"} }; + return new SaveWizardResult { Result = false, Errors = new List { "Looks like there is an existing user!" } }; } if (user.UsePlexAdminAccount) @@ -562,7 +562,7 @@ namespace Ombi.Controllers // We need to delete all the requests first var moviesUserRequested = MovieRepo.GetAll().Where(x => x.RequestedUserId == userId); var tvUserRequested = TvRepo.GetChild().Where(x => x.RequestedUserId == userId); - + if (moviesUserRequested.Any()) { await MovieRepo.DeleteRange(moviesUserRequested); @@ -588,9 +588,9 @@ namespace Ombi.Controllers { await _issueCommentsRepository.DeleteRange(issueComments); } - + // Delete the Subscriptions and mobile notification ids - var subs = _requestSubscriptionRepository.GetAll().Where(x => x.UserId == userId); + var subs = _requestSubscriptionRepository.GetAll().Where(x => x.UserId == userId); var mobileIds = _notificationRepository.GetAll().Where(x => x.UserId == userId); if (subs.Any()) { @@ -794,9 +794,26 @@ namespace Ombi.Controllers public async Task> GetUserPreferences() { var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + return await GetPreferences(user); + } + + [HttpGet("notificationpreferences/{userId}")] + public async Task> GetUserPreferences(string userId) + { + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == userId); + return await GetPreferences(user); + } + + private readonly List _excludedAgents = new List + { + NotificationAgent.Email, + NotificationAgent.Mobile + }; + private async Task> GetPreferences(OmbiUser user) + { var userPreferences = await _userNotificationPreferences.GetAll().Where(x => x.UserId == user.Id).ToListAsync(); - var agents = Enum.GetValues(typeof(NotificationAgent)).Cast(); + var agents = Enum.GetValues(typeof(NotificationAgent)).Cast().Where(x => !_excludedAgents.Contains(x)); foreach (var a in agents) { var agent = userPreferences.FirstOrDefault(x => x.Agent == a); @@ -806,55 +823,56 @@ namespace Ombi.Controllers userPreferences.Add(new UserNotificationPreferences { Agent = a, + UserId = user.Id, }); } - else - { - userPreferences.Add(agent); - } } return userPreferences; } [HttpPost("NotificationPreferences")] - public async Task AddUserNotificationPreference([FromBody] AddNotificationPreference pref) + public async Task AddUserNotificationPreference([FromBody] List preferences) { - // Make sure the user exists - var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == pref.UserId); - if (user == null) + foreach (var pref in preferences) { - return NotFound(); - } - // Check if we are editing a different user than ourself, if we are then we need to power user role - var me = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); - if (!me.Id.Equals(user.Id, StringComparison.InvariantCultureIgnoreCase)) - { - var isPowerUser = await UserManager.IsInRoleAsync(me, OmbiRoles.PowerUser); - var isAdmin = await UserManager.IsInRoleAsync(me, OmbiRoles.Admin); - if (!isPowerUser && !isAdmin) + + // Make sure the user exists + var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == pref.UserId); + if (user == null) { - return Unauthorized(); + return NotFound(); + } + // Check if we are editing a different user than ourself, if we are then we need to power user role + var me = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name); + if (!me.Id.Equals(user.Id, StringComparison.InvariantCultureIgnoreCase)) + { + var isPowerUser = await UserManager.IsInRoleAsync(me, OmbiRoles.PowerUser); + var isAdmin = await UserManager.IsInRoleAsync(me, OmbiRoles.Admin); + if (!isPowerUser && !isAdmin) + { + return Unauthorized(); + } } - } - // Make sure we don't already have a preference for this agent - var existingPreference = await _userNotificationPreferences.GetAll() - .FirstOrDefaultAsync(x => x.UserId == user.Id && x.Agent == pref.Agent); - if (existingPreference != null) - { - // Update it - existingPreference.Value = pref.Value; - existingPreference.Enabled = pref.Enabled; - } - await _userNotificationPreferences.Add(new UserNotificationPreferences - { - Agent = pref.Agent, - Enabled = pref.Enabled, - UserId = pref.UserId, - Value = pref.Value - }); + // Make sure we don't already have a preference for this agent + var existingPreference = await _userNotificationPreferences.GetAll() + .FirstOrDefaultAsync(x => x.UserId == user.Id && x.Agent == pref.Agent); + if (existingPreference != null) + { + // Update it + existingPreference.Value = pref.Value; + existingPreference.Enabled = pref.Enabled; + } + await _userNotificationPreferences.Add(new UserNotificationPreferences + { + Agent = pref.Agent, + Enabled = pref.Enabled, + UserId = pref.UserId, + Value = pref.Value + }); + } return Json(true); } From dbabb43537f767b4751e58f2bf12bf97043ee3aa Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 13:42:37 +0100 Subject: [PATCH 449/495] Added the music request limits --- src/Ombi.Core/Models/UI/UserViewModel.cs | 1 + src/Ombi/ClientApp/app/interfaces/IUser.ts | 1 + .../usermanagement-user.component.html | 17 ++++++++++++----- src/Ombi/Controllers/IdentityController.cs | 16 ++++++++++++++-- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/Ombi.Core/Models/UI/UserViewModel.cs b/src/Ombi.Core/Models/UI/UserViewModel.cs index 1c1e6162b..62b296009 100644 --- a/src/Ombi.Core/Models/UI/UserViewModel.cs +++ b/src/Ombi.Core/Models/UI/UserViewModel.cs @@ -16,6 +16,7 @@ namespace Ombi.Core.Models.UI public UserType UserType { get; set; } public int MovieRequestLimit { get; set; } public int EpisodeRequestLimit { get; set; } + public int MusicRequestLimit { get; set; } } public class ClaimCheckboxes diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index 04546abf9..6cd1bc1d7 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -12,6 +12,7 @@ export interface IUser { hasLoggedIn: boolean; movieRequestLimit: number; episodeRequestLimit: number; + musicRequestLimit: number; userAccessToken: string; // FOR UI checked: boolean; diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index da1b4076e..f7bf702a0 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -102,12 +102,19 @@
    - -
    - + +
    + +
    -
    +
    + +
    + +
    +
    diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 9e89a9506..2acc1637f 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -61,7 +61,8 @@ namespace Ombi.Controllers IRepository notificationRepository, IRepository subscriptionRepository, ISettingsService umSettings, - IRepository notificationPreferences) + IRepository notificationPreferences, + IMusicRequestRepository musicRepo) { UserManager = user; Mapper = mapper; @@ -71,6 +72,7 @@ namespace Ombi.Controllers CustomizationSettings = c; WelcomeEmail = welcome; MovieRepo = m; + MusicRepo = musicRepo; TvRepo = t; _log = l; _plexApi = plexApi; @@ -96,6 +98,7 @@ namespace Ombi.Controllers private IWelcomeEmail WelcomeEmail { get; } private IMovieRequestRepository MovieRepo { get; } private ITvRequestRepository TvRepo { get; } + private IMusicRequestRepository MusicRepo { get; } private readonly ILogger _log; private readonly IPlexApi _plexApi; private readonly ISettingsService _plexSettings; @@ -295,7 +298,8 @@ namespace Ombi.Controllers LastLoggedIn = user.LastLoggedIn, HasLoggedIn = user.LastLoggedIn.HasValue, EpisodeRequestLimit = user.EpisodeRequestLimit ?? 0, - MovieRequestLimit = user.MovieRequestLimit ?? 0 + MovieRequestLimit = user.MovieRequestLimit ?? 0, + MusicRequestLimit = user.MusicRequestLimit ?? 0, }; foreach (var role in userRoles) @@ -347,6 +351,7 @@ namespace Ombi.Controllers UserType = UserType.LocalUser, MovieRequestLimit = user.MovieRequestLimit, EpisodeRequestLimit = user.EpisodeRequestLimit, + MusicRequestLimit = user.MusicRequestLimit, UserAccessToken = Guid.NewGuid().ToString("N"), }; var userResult = await UserManager.CreateAsync(ombiUser, user.Password); @@ -490,6 +495,7 @@ namespace Ombi.Controllers user.Email = ui.EmailAddress; user.MovieRequestLimit = ui.MovieRequestLimit; user.EpisodeRequestLimit = ui.EpisodeRequestLimit; + user.MusicRequestLimit = ui.MusicRequestLimit; var updateResult = await UserManager.UpdateAsync(user); if (!updateResult.Succeeded) { @@ -562,6 +568,7 @@ namespace Ombi.Controllers // We need to delete all the requests first var moviesUserRequested = MovieRepo.GetAll().Where(x => x.RequestedUserId == userId); var tvUserRequested = TvRepo.GetChild().Where(x => x.RequestedUserId == userId); + var musicRequested = MusicRepo.GetAll().Where(x => x.RequestedUserId == userId); if (moviesUserRequested.Any()) { @@ -572,6 +579,11 @@ namespace Ombi.Controllers await TvRepo.DeleteChildRange(tvUserRequested); } + if (musicRequested.Any()) + { + await MusicRepo.DeleteRange(musicRequested); + } + // Delete any issues and request logs var issues = _issuesRepository.GetAll().Where(x => x.UserReportedId == userId); var issueComments = _issueCommentsRepository.GetAll().Where(x => x.UserId == userId); From 61a06905782a0d7a1be4a970d89fd342370f548c Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 13:43:55 +0100 Subject: [PATCH 450/495] !fixed lint --- .../app/usermanagement/usermanagement-user.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index e06c7c12b..fc79e0201 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -60,6 +60,7 @@ export class UserManagementUserComponent implements OnInit { episodeRequestLimit: 0, movieRequestLimit: 0, userAccessToken: "", + musicRequestLimit: 0, }; } } From 1b103d9784b9798295e668dc4a2a6e76c2c9e653 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 13:56:53 +0100 Subject: [PATCH 451/495] Fixed !wip --- .../app/usermanagement/usermanagement-user.component.ts | 2 ++ src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index fc79e0201..fab37dd59 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -61,6 +61,8 @@ export class UserManagementUserComponent implements OnInit { movieRequestLimit: 0, userAccessToken: "", musicRequestLimit: 0, + episodeRequestQuota: null, + movieRequestQuota: null, }; } } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index 91fa628e4..b28f20f0e 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -7,8 +7,8 @@ import { ConfirmationService, ConfirmDialogModule, MultiSelectModule, SidebarMod import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { UpdateDetailsComponent } from "./updatedetails.component"; -import { UserManagementComponent } from "./usermanagement.component"; import { UserManagementUserComponent } from "./usermanagement-user.component"; +import { UserManagementComponent } from "./usermanagement.component"; import { PipeModule } from "../pipes/pipe.module"; import { IdentityService, PlexService } from "../services"; From a60f6a2c483cb6fd829a9724b8211b56b640cd2f Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 13:59:37 +0100 Subject: [PATCH 452/495] !wip changelog --- CHANGELOG.md | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bd996857..031386283 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,144 @@ # Changelog +## (unreleased) + +### **New Features** + +- Updated all the MS packages. [TidusJar] + +- Update the .net core packages to fix "CVE-2018-8409: ASP.NET Core Denial Of Service Vulnerability" [TidusJar] + +- Change way remainingrequests component is notified. [Kenton Royal] + +- Added the music request limits. [TidusJar] + +- Added the Notification Preferences to the user. [TidusJar] + +- Added the API to add user notification preferences. [TidusJar] + +- Added more logging into the updater. [Jamie] + +- Update CHANGELOG.md. [Jamie] + +### **Fixes** + +- Fixed #2485. [TidusJar] + +- Fixed #2516. [TidusJar] + +- Fix bug in which requested TV wasn't logging for some users. [Kenton Royal] + +- Add to translations. [Kenton Royal] + +- Add html for displaying remaining requests on users page. [Kenton Royal] + +- Add quota fields to user view model. [Kenton Royal] + +- Users can now see the music search tab #2493. [TidusJar] + +- Add href to a tags so that a pointer cursor shows on requests page. [Stephen Panzer] + +- Allow Lidarr to specify if we should search for the album. [TidusJar] + +- Fixed the issue if in Radarr we only want to add and monitor, if the movie already exists we search for it. [TidusJar] + +- Fix bug causing wrong time to be displayed for next request. [Kenton Royal] + +- Bodge fix test to prevent compile error. [Kenton Royal] + +- Fix displaying year in issue dialog. [Stephen Panzer] + +- Add clearfix class. Closes #2486. [Stephen Panzer] + +- Correct path of lidarr component import for unix systems. [Kenton Royal] + +- Refactor code. [Kenton Royal] + +- Fix formatting error. [Kenton Royal] + +- Revert "Revert request.service.ts to version on upstream/develop" [Kenton Royal] + +- Revert request.service.ts to version on upstream/develop. [Kenton Royal] + +- Fix lint errors. [Kenton Royal] + +- Move logic for notifying when reuqest is complete. [Kenton Royal] + +- Remove import. [Kenton Royal] + +- Remove unused module. [Kenton Royal] + +- Refactor code. [Kenton Royal] + +- Add text to translation file. [Kenton Royal] + +- Fix query for fetching requested tv shows. [Kenton Royal] + +- Add vscode to gitignore. [Kenton Royal] + +- Fix lint errors. [Kenton Royal] + +- Remove unused methods from SearchController. [Kenton Royal] + +- Remove local vscode files. [Kenton Royal] + +- Fix bug when submitting requests for multiple episodes accross multiple seasons. [Kenton Royal] + +- Fix bug with TV requests in which requesting a seasion would treat request as single episode. [Kenton Royal] + +- Fix issues with remaining count updating. [Kenton Royal] + +- Trigger update of request limit on new request. [Kenton Royal] + +- Add logic for movie request count. [Kenton Royal] + +- Add logic for retriving request information. [Kenton Royal] + +- Move to seperate component and display for both TV and movies. [Kenton Royal] + +- Add dummy for request counter. [Kenton Royal] + +- Fix scss import for unix systems. [Kenton Royal] + +- Add methods to interface and add model class. [Kenton Royal] + +- !fixed lint. [TidusJar] + +- Fixed #2481. [TidusJar] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Norwegian) [Jamie] + +- New translations en.json (Italian) [Jamie] + +- New translations en.json (German) [Jamie] + +- New translations en.json (French) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Danish) [Jamie] + +- Fixed #2475. [Jamie] + +- Stript out certain characters when sending a pushover message #2385. [TidusJar] + +- Add default values for Priority and Sound. [David Pooley] + +- Allow for the ability to set Pushover notification sound and priority from within Ombi. [David Pooley] + +- It works now when we request an album when we do not have the artist in Lidarr. Waiting on https://github.com/lidarr/Lidarr/issues/459 to do when we have the artist. [Jamie] + +- Fix non-Windows builds. Fixes #2453. [Joe Groocock] + + ## v3.0.3587 (2018-08-19) ### **New Features** @@ -30,6 +169,12 @@ ### **Fixes** +- Now include the release year in the issue title #2381. [TidusJar] + +- Made the OAuth a Popout to work with Org. [Jamie] + +- Fixed #2418. [TidusJar] + - #2408 Added the feature to delete comments on issues. [Jamie] - New translations en.json (Swedish) [Jamie] From cee07bec47cf9a4a7a2d91948ad64c26bfd1cd36 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Wed, 19 Sep 2018 15:09:04 +0100 Subject: [PATCH 453/495] Fixed build (issue from merge) !wip --- src/Ombi/Controllers/IdentityController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index e0b864185..db06c81c7 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -63,7 +63,7 @@ namespace Ombi.Controllers IRepository subscriptionRepository, ISettingsService umSettings, IRepository notificationPreferences, - IMusicRequestRepository musicRepo), + IMusicRequestRepository musicRepo, IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine) { From c473c316ab4cd8578876644895d04bab86471ed2 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 20 Sep 2018 13:47:52 +0100 Subject: [PATCH 454/495] Fixed #2522 --- src/Ombi/Controllers/ImagesController.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Ombi/Controllers/ImagesController.cs b/src/Ombi/Controllers/ImagesController.cs index d7058cede..6c05cdd3a 100644 --- a/src/Ombi/Controllers/ImagesController.cs +++ b/src/Ombi/Controllers/ImagesController.cs @@ -182,8 +182,8 @@ namespace Ombi.Controllers [HttpGet("background")] public async Task GetBackgroundImage() { - var moviesArray = Options.Movies; - var tvArray = Options.TvShows; + var moviesArray = Options.Movies ?? new int[0]; + var tvArray = Options.TvShows ?? new int[0]; var rand = new Random(); var movieUrl = string.Empty; @@ -191,7 +191,7 @@ namespace Ombi.Controllers var key = await _cache.GetOrAdd(CacheKeys.FanartTv, async () => await Config.Get(Store.Entities.ConfigurationTypes.FanartTv), DateTime.Now.AddDays(1)); - if (moviesArray.Any()) + if (moviesArray.Length > 0) { var item = rand.Next(moviesArray.Length); var result = await FanartTvApi.GetMovieImages(moviesArray[item].ToString(), key.Value); @@ -206,7 +206,7 @@ namespace Ombi.Controllers movieUrl = result.moviebackground[res].url; } - if (tvArray.Any()) + if (tvArray.Length > 0) { var item = rand.Next(tvArray.Length); var result = await FanartTvApi.GetTvImages(tvArray[item], key.Value); From afdd80ac7228ffe92c486ddc81292e1d524422eb Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 20 Sep 2018 13:50:14 +0100 Subject: [PATCH 455/495] Fixed #2518 --- src/Ombi/ClientApp/app/app.component.html | 3 +++ src/Ombi/wwwroot/translations/en.json | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index af7315596..24398f088 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -140,6 +140,9 @@
  • +
  • + +
  • diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index c53229c3d..ca8dbcd3e 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -69,7 +69,8 @@ "Dutch": "Dutch", "Norwegian":"Norwegian", "BrazillianPortuguese": "Brazillian Portuguese", - "Polish":"Polish" + "Polish":"Polish", + "Swedish":"Swedish" }, "OpenMobileApp":"Open Mobile App", "RecentlyAdded":"Recently Added" From eb2f51cbabad37c0ea30a3c67ba79435c4ecf504 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:47 +0100 Subject: [PATCH 456/495] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 61f8c718d..cdc6f05ac 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -66,7 +66,8 @@ "Dutch": "Hollandsk", "Norwegian": "Norsk", "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish" + "Polish": "Polish", + "Swedish": "Swedish" }, "OpenMobileApp": "Åbn mobilapp", "RecentlyAdded": "Recently Added" From 2ae32233cde9aa2f3d9fda01d728c1eb5acf5834 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:48 +0100 Subject: [PATCH 457/495] New translations en.json (Dutch) --- src/Ombi/wwwroot/translations/nl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index c32195922..49482b32f 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -66,7 +66,8 @@ "Dutch": "Nederlands", "Norwegian": "Noors", "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish" + "Polish": "Polish", + "Swedish": "Swedish" }, "OpenMobileApp": "Open Mobiele App", "RecentlyAdded": "Recently Added" From 7bab950e0a7bc566777e451eac239a21487e33c9 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:50 +0100 Subject: [PATCH 458/495] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 7c5201aa9..3bd929acb 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -66,7 +66,8 @@ "Dutch": "Néerlandais", "Norwegian": "Norvégien", "BrazillianPortuguese": "Portuguais brésilien", - "Polish": "Polonais" + "Polish": "Polonais", + "Swedish": "Swedish" }, "OpenMobileApp": "Ouvrir l'application mobile", "RecentlyAdded": "Ajouts récents" From 96c3f55c264f820a061d767685ff29d9a2347dd8 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:51 +0100 Subject: [PATCH 459/495] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 219de654e..7ca0aa465 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -66,7 +66,8 @@ "Dutch": "Niederländisch", "Norwegian": "Norwegisch", "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish" + "Polish": "Polish", + "Swedish": "Swedish" }, "OpenMobileApp": "Mobile App", "RecentlyAdded": "Recently Added" From bd927fe508c047eda9f9ed6fc1164da6ca0e4432 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:52 +0100 Subject: [PATCH 460/495] New translations en.json (Italian) --- src/Ombi/wwwroot/translations/it.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index fc9cec63d..374fdd311 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -66,7 +66,8 @@ "Dutch": "Olandese", "Norwegian": "Norvegese", "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish" + "Polish": "Polish", + "Swedish": "Swedish" }, "OpenMobileApp": "Apri l'applicazione mobile", "RecentlyAdded": "Recently Added" From a5123e987c68b0e24412882177081114be2a7364 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:53 +0100 Subject: [PATCH 461/495] New translations en.json (Norwegian) --- src/Ombi/wwwroot/translations/no.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 58c5c93c2..08e42da84 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -66,7 +66,8 @@ "Dutch": "Nederlandsk", "Norwegian": "Norsk", "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish" + "Polish": "Polish", + "Swedish": "Swedish" }, "OpenMobileApp": "Åpne mobilapp", "RecentlyAdded": "Recently Added" From c4fe2d9ad4ff9f7bc26c234b650e93a0c67f1dff Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:54 +0100 Subject: [PATCH 462/495] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 5378c8334..65c31fc68 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -66,7 +66,8 @@ "Dutch": "Holenderski", "Norwegian": "Norweski", "BrazillianPortuguese": "Brazylijski portugalski", - "Polish": "Polski" + "Polish": "Polski", + "Swedish": "Swedish" }, "OpenMobileApp": "Otwórz aplikację mobilną", "RecentlyAdded": "Ostatnio dodane" From 922e02fc26201a5da8100f91d9bedb5814c104d4 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:55 +0100 Subject: [PATCH 463/495] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index 62b5d8b1b..573bb2f9f 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -66,7 +66,8 @@ "Dutch": "Holandês", "Norwegian": "Norueguês", "BrazillianPortuguese": "Português (Brasil)", - "Polish": "Polonês" + "Polish": "Polonês", + "Swedish": "Swedish" }, "OpenMobileApp": "Abrir aplicativo do celular", "RecentlyAdded": "Recentemente adicionado" From f3248edd19202afaddfa5c64b243e7002d8e24ff Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:56 +0100 Subject: [PATCH 464/495] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index d99050613..115ac6aa6 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -66,7 +66,8 @@ "Dutch": "Holandés", "Norwegian": "Norwegian", "BrazillianPortuguese": "Brazillian Portuguese", - "Polish": "Polish" + "Polish": "Polish", + "Swedish": "Swedish" }, "OpenMobileApp": "Open Mobile App", "RecentlyAdded": "Recently Added" From feb907eece1a75dc3e1eb3059371a9b97d8147b4 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 13:57:57 +0100 Subject: [PATCH 465/495] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 4d2ee773c..57467c64c 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -66,7 +66,8 @@ "Dutch": "Holländska", "Norwegian": "Norska", "BrazillianPortuguese": "Brazillian portugisiska", - "Polish": "Polska" + "Polish": "Polska", + "Swedish": "Swedish" }, "OpenMobileApp": "Öppna Mobil App", "RecentlyAdded": "Nyligen tillagda" From 68c43684907fff72cc53d6b79cdb0a5308fdb754 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 20 Sep 2018 14:31:48 +0100 Subject: [PATCH 466/495] Started on custom quality profiles and root paths !wip --- src/Ombi.Core/Models/UI/UserViewModel.cs | 2 + src/Ombi.Core/Senders/TvSender.cs | 33 +++- src/Ombi.Store/Context/OmbiContext.cs | 3 +- .../Entities/UserQualityProfiles.cs | 23 +++ src/Ombi/ClientApp/app/interfaces/IUser.ts | 10 ++ .../usermanagement-user.component.html | 148 ++++++++++++------ .../usermanagement-user.component.ts | 8 + src/Ombi/Controllers/IdentityController.cs | 60 ++++++- 8 files changed, 235 insertions(+), 52 deletions(-) create mode 100644 src/Ombi.Store/Entities/UserQualityProfiles.cs diff --git a/src/Ombi.Core/Models/UI/UserViewModel.cs b/src/Ombi.Core/Models/UI/UserViewModel.cs index 15045bc0a..8d01c066b 100644 --- a/src/Ombi.Core/Models/UI/UserViewModel.cs +++ b/src/Ombi.Core/Models/UI/UserViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Ombi.Store.Entities; namespace Ombi.Core.Models.UI { @@ -19,6 +20,7 @@ namespace Ombi.Core.Models.UI public RequestQuotaCountModel EpisodeRequestQuota { get; set; } public RequestQuotaCountModel MovieRequestQuota { get; set; } public int MusicRequestLimit { get; set; } + public UserQualityProfiles UserQualityProfiles { get; set; } } public class ClaimCheckboxes diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 47d965acc..202edbfa5 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.DogNzb; using Ombi.Api.DogNzb.Models; @@ -12,7 +13,9 @@ using Ombi.Api.Sonarr.Models; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Settings.Settings.Models.External; +using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; namespace Ombi.Core.Senders { @@ -20,7 +23,7 @@ namespace Ombi.Core.Senders { public TvSender(ISonarrApi sonarrApi, ILogger log, ISettingsService sonarrSettings, ISettingsService dog, IDogNzbApi dogApi, ISettingsService srSettings, - ISickRageApi srApi) + ISickRageApi srApi, IRepository userProfiles) { SonarrApi = sonarrApi; Logger = log; @@ -29,6 +32,7 @@ namespace Ombi.Core.Senders DogNzbApi = dogApi; SickRageSettings = srSettings; SickRageApi = srApi; + UserQualityProfiles = userProfiles; } private ISonarrApi SonarrApi { get; } @@ -38,6 +42,7 @@ namespace Ombi.Core.Senders private ISettingsService SonarrSettings { get; } private ISettingsService DogNzbSettings { get; } private ISettingsService SickRageSettings { get; } + private IRepository UserQualityProfiles { get; } public async Task Send(ChildRequests model) { @@ -122,13 +127,25 @@ namespace Ombi.Core.Senders string rootFolderPath; string seriesType; + var profiles = await UserQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId); + if (model.SeriesType == SeriesType.Anime) { // Get the root path from the rootfolder selected. // For some reason, if we haven't got one use the first root folder in Sonarr - // TODO make this overrideable via the UI rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder ?? int.Parse(s.RootPathAnime), s); int.TryParse(s.QualityProfileAnime, out qualityToUse); + if (profiles != null) + { + if (profiles.SonarrRootPathAnime > 0) + { + rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPathAnime, s); + } + if (profiles.SonarrQualityProfileAnime > 0) + { + qualityToUse = profiles.SonarrQualityProfileAnime; + } + } seriesType = "anime"; } @@ -137,8 +154,18 @@ namespace Ombi.Core.Senders int.TryParse(s.QualityProfile, out qualityToUse); // Get the root path from the rootfolder selected. // For some reason, if we haven't got one use the first root folder in Sonarr - // TODO make this overrideable via the UI rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder ?? int.Parse(s.RootPath), s); + if (profiles != null) + { + if (profiles.SonarrRootPath > 0) + { + rootFolderPath = await GetSonarrRootPath(profiles.SonarrRootPath, s); + } + if (profiles.SonarrQualityProfile > 0) + { + qualityToUse = profiles.SonarrQualityProfile; + } + } seriesType = "standard"; } diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs index 2fdbaa996..f34b4c57c 100644 --- a/src/Ombi.Store/Context/OmbiContext.cs +++ b/src/Ombi.Store/Context/OmbiContext.cs @@ -51,7 +51,8 @@ namespace Ombi.Store.Context public DbSet SickRageCache { get; set; } public DbSet SickRageEpisodeCache { get; set; } public DbSet RequestSubscription { get; set; } - + public DbSet UserNotificationPreferences { get; set; } + public DbSet UserQualityProfileses { get; set; } public DbSet ApplicationConfigurations { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) diff --git a/src/Ombi.Store/Entities/UserQualityProfiles.cs b/src/Ombi.Store/Entities/UserQualityProfiles.cs new file mode 100644 index 000000000..d944c81b2 --- /dev/null +++ b/src/Ombi.Store/Entities/UserQualityProfiles.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations.Schema; +using Newtonsoft.Json; +using Ombi.Helpers; + +namespace Ombi.Store.Entities +{ + [Table(nameof(UserQualityProfiles))] + public class UserQualityProfiles : Entity + { + public string UserId { get; set; } + + public int SonarrQualityProfileAnime { get; set; } + public int SonarrRootPathAnime { get; set; } + public int SonarrRootPath { get; set; } + public int SonarrQualityProfile { get; set; } + public int RadarrRootPath { get; set; } + public int RadarrQualityProfile { get; set; } + + [ForeignKey(nameof(UserId))] + [JsonIgnore] + public OmbiUser User { get; set; } + } +} diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index ff1e7f944..9819ca834 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -15,6 +15,7 @@ export interface IUser { episodeRequestLimit: number; musicRequestLimit: number; userAccessToken: string; + userQualityProfiles: IUserQualityProfiles; // FOR UI episodeRequestQuota: IRemainingRequests | null; @@ -22,6 +23,15 @@ export interface IUser { checked: boolean; } +export interface IUserQualityProfiles { + sonarrQualityProfileAnime: string; + sonarrRootPathAnime: string; + sonarrRootPath: string; + sonarrQualityProfile: string; + radarrRootPath: string; + radarrQualityProfile: string; +} + export interface ICreateWizardUser { username: string; password: string; diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index f7bf702a0..bdb277d7e 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -89,55 +89,115 @@ - -
    -
    - -
    - -
    - -
    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    +
    +
    + +
    +
    - -
    - -
    - -
    -
    -
    - -
    - -
    -
    - - - - - -
    -
    -
    -
    - -
    - -
    -
    -
    +
    + + + + + +
    +
    +
    +
    + +
    + +
    - - - +
    +
    + +
    +
    + + +
    +
    + +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    + +
    +
    diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index fab37dd59..fda9df8ea 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -63,6 +63,14 @@ export class UserManagementUserComponent implements OnInit { musicRequestLimit: 0, episodeRequestQuota: null, movieRequestQuota: null, + userQualityProfiles: { + radarrQualityProfile: "", + radarrRootPath: "", + sonarrQualityProfile: "", + sonarrQualityProfileAnime: "", + sonarrRootPath: "", + sonarrRootPathAnime: "", + }, }; } } diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index db06c81c7..37290b45f 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -63,6 +63,7 @@ namespace Ombi.Controllers IRepository subscriptionRepository, ISettingsService umSettings, IRepository notificationPreferences, + IRepository userProfiles, IMusicRequestRepository musicRepo, IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine) @@ -90,6 +91,7 @@ namespace Ombi.Controllers TvRequestEngine = tvRequestEngine; MovieRequestEngine = movieRequestEngine; _userNotificationPreferences = notificationPreferences; + _userQualityProfiles = userProfiles; } private OmbiUserManager UserManager { get; } @@ -115,6 +117,7 @@ namespace Ombi.Controllers private readonly IRepository _notificationRepository; private readonly IRepository _requestSubscriptionRepository; private readonly IRepository _userNotificationPreferences; + private readonly IRepository _userQualityProfiles; /// /// This is what the Wizard will call when creating the user for the very first time. @@ -329,16 +332,26 @@ namespace Ombi.Controllers }); } - if (vm.EpisodeRequestLimit > 0) + if (vm.EpisodeRequestLimit > 0) { vm.EpisodeRequestQuota = await TvRequestEngine.GetRemainingRequests(user); } - if (vm.MovieRequestLimit > 0) + if (vm.MovieRequestLimit > 0) { vm.MovieRequestQuota = await MovieRequestEngine.GetRemainingRequests(user); } + // Get the quality profiles + vm.UserQualityProfiles = await _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == user.Id); + if (vm.UserQualityProfiles == null) + { + vm.UserQualityProfiles = new UserQualityProfiles + { + UserId = user.Id + }; + } + return vm; } @@ -397,6 +410,20 @@ namespace Ombi.Controllers }; } + // Add the quality profiles + if (user.UserQualityProfiles != null) + { + user.UserQualityProfiles.UserId = ombiUser.Id; + await _userQualityProfiles.Add(user.UserQualityProfiles); + } + else + { + user.UserQualityProfiles = new UserQualityProfiles + { + UserId = ombiUser.Id + }; + } + return new OmbiIdentityResult { Successful = true @@ -552,8 +579,24 @@ namespace Ombi.Controllers { Errors = messages }; + } + // Add the quality profiles + if (ui.UserQualityProfiles != null) + { + var currentQualityProfiles = await + _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == user.Id); + + currentQualityProfiles.RadarrQualityProfile = ui.UserQualityProfiles.RadarrQualityProfile; + currentQualityProfiles.RadarrRootPath = ui.UserQualityProfiles.RadarrRootPath; + currentQualityProfiles.SonarrQualityProfile = ui.UserQualityProfiles.SonarrQualityProfile; + currentQualityProfiles.SonarrQualityProfileAnime = ui.UserQualityProfiles.SonarrQualityProfileAnime; + currentQualityProfiles.SonarrRootPath = ui.UserQualityProfiles.SonarrRootPath; + currentQualityProfiles.SonarrRootPathAnime = ui.UserQualityProfiles.SonarrRootPathAnime; + + await _userQualityProfiles.SaveChangesAsync(); } + return new OmbiIdentityResult { Successful = true @@ -585,6 +628,8 @@ namespace Ombi.Controllers var moviesUserRequested = MovieRepo.GetAll().Where(x => x.RequestedUserId == userId); var tvUserRequested = TvRepo.GetChild().Where(x => x.RequestedUserId == userId); var musicRequested = MusicRepo.GetAll().Where(x => x.RequestedUserId == userId); + var notificationPreferences = _userNotificationPreferences.GetAll().Where(x => x.UserId == userId); + var userQuality = await _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == userId); if (moviesUserRequested.Any()) { @@ -594,11 +639,18 @@ namespace Ombi.Controllers { await TvRepo.DeleteChildRange(tvUserRequested); } - if (musicRequested.Any()) { await MusicRepo.DeleteRange(musicRequested); } + if (notificationPreferences.Any()) + { + await _userNotificationPreferences.DeleteRange(notificationPreferences); + } + if (userQuality != null) + { + await _userQualityProfiles.Delete(userQuality); + } // Delete any issues and request logs var issues = _issuesRepository.GetAll().Where(x => x.UserReportedId == userId); @@ -903,7 +955,7 @@ namespace Ombi.Controllers } return Json(true); } - + private async Task> AddRoles(IEnumerable roles, OmbiUser ombiUser) { var roleResult = new List(); From 7b84e9dbbc05f92b69d77c472b7bc7f5117caad0 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 20 Sep 2018 14:44:07 +0100 Subject: [PATCH 467/495] Forgot about this change !wip --- src/Ombi/ClientApp/app/interfaces/IUser.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index 9819ca834..0cb4123a7 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -24,12 +24,12 @@ export interface IUser { } export interface IUserQualityProfiles { - sonarrQualityProfileAnime: string; - sonarrRootPathAnime: string; - sonarrRootPath: string; - sonarrQualityProfile: string; - radarrRootPath: string; - radarrQualityProfile: string; + sonarrQualityProfileAnime: number; + sonarrRootPathAnime: number; + sonarrRootPath: number; + sonarrQualityProfile: number; + radarrRootPath: number; + radarrQualityProfile: number; } export interface ICreateWizardUser { From 78091ff15ee82498673245a77616ab64476d039b Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 20 Sep 2018 16:07:14 +0100 Subject: [PATCH 468/495] pull in the folder into the ui !wip --- .../usermanagement-user.component.ts | 49 ++++++++++++------- .../Controllers/External/RadarrController.cs | 5 +- .../Controllers/External/SonarrController.cs | 4 +- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index fda9df8ea..ee02e53f5 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -1,8 +1,8 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { ICheckbox, INotificationAgent, INotificationPreferences, IUser, UserType } from "../interfaces"; -import { IdentityService, NotificationService } from "../services"; +import { ICheckbox, INotificationAgent, INotificationPreferences, IRadarrProfile, IRadarrRootFolder, ISonarrProfile, ISonarrRootFolder, IUser, UserType } from "../interfaces"; +import { IdentityService, NotificationService, RadarrService, SonarrService } from "../services"; import { ConfirmationService } from "primeng/primeng"; @@ -16,6 +16,11 @@ export class UserManagementUserComponent implements OnInit { public availableClaims: ICheckbox[]; public confirmPass: ""; public notificationPreferences: INotificationPreferences[]; + + public sonarrQualities: ISonarrProfile[]; + public sonarrRootFolders: ISonarrRootFolder[]; + public radarrQualities: IRadarrProfile[]; + public radarrRootFolders: IRadarrRootFolder[]; public NotificationAgent = INotificationAgent; public edit: boolean; @@ -24,18 +29,19 @@ export class UserManagementUserComponent implements OnInit { private notificationService: NotificationService, private router: Router, private route: ActivatedRoute, - private confirmationService: ConfirmationService) { - this.route.params - .subscribe((params: any) => { - if(params.id) { - this.userId = params.id; - this.edit = true; - this.identityService.getUserById(this.userId).subscribe(x => { - this.user = x; + private confirmationService: ConfirmationService, + private sonarrService: SonarrService, + private radarrService: RadarrService) { + + this.route.params.subscribe((params: any) => { + if(params.id) { + this.userId = params.id; + this.edit = true; + this.identityService.getUserById(this.userId).subscribe(x => { + this.user = x; + }); + } }); - } - }); - } public ngOnInit() { @@ -45,6 +51,11 @@ export class UserManagementUserComponent implements OnInit { } else { this.identityService.getNotificationPreferences().subscribe(x => this.notificationPreferences = x); } + this.sonarrService.getQualityProfilesWithoutSettings().subscribe(x => this.sonarrQualities = x); + this.sonarrService.getRootFoldersWithoutSettings().subscribe(x => this.sonarrRootFolders = x); + this.radarrService.getQualityProfilesFromSettings().subscribe(x => this.radarrQualities = x); + this.radarrService.getRootFoldersFromSettings().subscribe(x => this.radarrRootFolders = x); + if(!this.edit) { this.user = { alias: "", @@ -64,12 +75,12 @@ export class UserManagementUserComponent implements OnInit { episodeRequestQuota: null, movieRequestQuota: null, userQualityProfiles: { - radarrQualityProfile: "", - radarrRootPath: "", - sonarrQualityProfile: "", - sonarrQualityProfileAnime: "", - sonarrRootPath: "", - sonarrRootPathAnime: "", + radarrQualityProfile: 0, + radarrRootPath: 0, + sonarrQualityProfile: 0, + sonarrQualityProfileAnime: 0, + sonarrRootPath: 0, + sonarrRootPathAnime: 0, }, }; } diff --git a/src/Ombi/Controllers/External/RadarrController.cs b/src/Ombi/Controllers/External/RadarrController.cs index 8e146be50..128b1a9e2 100644 --- a/src/Ombi/Controllers/External/RadarrController.cs +++ b/src/Ombi/Controllers/External/RadarrController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; using Ombi.Api.Radarr; @@ -12,7 +13,7 @@ using Ombi.Settings.Settings.Models.External; namespace Ombi.Controllers.External { - [PowerUser] + [Authorize] [ApiV1] [Produces("application/json")] public class RadarrController : Controller @@ -34,6 +35,7 @@ namespace Ombi.Controllers.External /// The settings. /// [HttpPost("Profiles")] + [PowerUser] public async Task> GetProfiles([FromBody] RadarrSettings settings) { return await RadarrApi.GetProfiles(settings.ApiKey, settings.FullUri); @@ -45,6 +47,7 @@ namespace Ombi.Controllers.External /// The settings. /// [HttpPost("RootFolders")] + [PowerUser] public async Task> GetRootFolders([FromBody] RadarrSettings settings) { return await RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); diff --git a/src/Ombi/Controllers/External/SonarrController.cs b/src/Ombi/Controllers/External/SonarrController.cs index 6d8c4d805..94d1e3edf 100644 --- a/src/Ombi/Controllers/External/SonarrController.cs +++ b/src/Ombi/Controllers/External/SonarrController.cs @@ -11,7 +11,7 @@ using Ombi.Settings.Settings.Models.External; namespace Ombi.Controllers.External { - [PowerUser] + [Authorize] [ApiV1] [Produces("application/json")] public class SonarrController : Controller @@ -31,6 +31,7 @@ namespace Ombi.Controllers.External /// The settings. /// [HttpPost("Profiles")] + [PowerUser] public async Task> GetProfiles([FromBody] SonarrSettings settings) { return await SonarrApi.GetProfiles(settings.ApiKey, settings.FullUri); @@ -42,6 +43,7 @@ namespace Ombi.Controllers.External /// The settings. /// [HttpPost("RootFolders")] + [PowerUser] public async Task> GetRootFolders([FromBody] SonarrSettings settings) { return await SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri); From 91b6dfe2b7f42dbe1c99f12a1312590e58dfc657 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 21:34:31 +0100 Subject: [PATCH 469/495] Added the root folders and qualities per user! --- src/Ombi.Core/Senders/MovieSender.cs | 31 +- src/Ombi.Core/Senders/TvSender.cs | 1 + ...0920201101_UserQualityProfiles.Designer.cs | 1151 +++++++++++++++++ .../20180920201101_UserQualityProfiles.cs | 46 + .../Migrations/OmbiContextModelSnapshot.cs | 33 + .../app/settings/lidarr/lidarr.component.html | 4 +- .../usermanagement-user.component.html | 69 +- .../usermanagement/usermanagement.module.ts | 4 +- src/Ombi/Controllers/IdentityController.cs | 14 +- 9 files changed, 1313 insertions(+), 40 deletions(-) create mode 100644 src/Ombi.Store/Migrations/20180920201101_UserQualityProfiles.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20180920201101_UserQualityProfiles.cs diff --git a/src/Ombi.Core/Senders/MovieSender.cs b/src/Ombi.Core/Senders/MovieSender.cs index aa919e552..8b89ef7bb 100644 --- a/src/Ombi.Core/Senders/MovieSender.cs +++ b/src/Ombi.Core/Senders/MovieSender.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.CouchPotato; using Ombi.Api.DogNzb.Models; @@ -9,6 +10,8 @@ using Ombi.Helpers; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Entities.Requests; using Ombi.Api.DogNzb; +using Ombi.Store.Entities; +using Ombi.Store.Repository; namespace Ombi.Core.Senders { @@ -16,7 +19,7 @@ namespace Ombi.Core.Senders { public MovieSender(ISettingsService radarrSettings, IRadarrApi api, ILogger log, ISettingsService dogSettings, IDogNzbApi dogApi, ISettingsService cpSettings, - ICouchPotatoApi cpApi) + ICouchPotatoApi cpApi, IRepository userProfiles) { RadarrSettings = radarrSettings; RadarrApi = api; @@ -25,6 +28,7 @@ namespace Ombi.Core.Senders DogNzbApi = dogApi; CouchPotatoSettings = cpSettings; CouchPotatoApi = cpApi; + _userProfiles = userProfiles; } private ISettingsService RadarrSettings { get; } @@ -34,6 +38,7 @@ namespace Ombi.Core.Senders private ISettingsService DogNzbSettings { get; } private ISettingsService CouchPotatoSettings { get; } private ICouchPotatoApi CouchPotatoApi { get; } + private readonly IRepository _userProfiles; public async Task Send(MovieRequests model) { @@ -88,13 +93,33 @@ namespace Ombi.Core.Senders private async Task SendToRadarr(MovieRequests model, RadarrSettings settings) { + var qualityToUse = int.Parse(settings.DefaultQualityProfile); + + var rootFolderPath = settings.DefaultRootPath; + + var profiles = await _userProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == model.RequestedUserId); + if (profiles != null) + { + if (profiles.SonarrRootPathAnime > 0) + { + rootFolderPath = await RadarrRootPath(profiles.SonarrRootPathAnime, settings); + } + if (profiles.SonarrQualityProfileAnime > 0) + { + qualityToUse = profiles.SonarrQualityProfileAnime; + } + } + + // Overrides on the request take priority if (model.QualityOverride > 0) { qualityToUse = model.QualityOverride; } - - var rootFolderPath = model.RootPathOverride <= 0 ? settings.DefaultRootPath : await RadarrRootPath(model.RootPathOverride, settings); + if (model.RootPathOverride > 0) + { + rootFolderPath = await RadarrRootPath(model.RootPathOverride, settings); + } // Check if the movie already exists? Since it could be unmonitored var movies = await RadarrApi.GetMovies(settings.ApiKey, settings.FullUri); diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 202edbfa5..e48e54c1a 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -169,6 +169,7 @@ namespace Ombi.Core.Senders seriesType = "standard"; } + // Overrides on the request take priority if (model.ParentRequest.QualityOverride.HasValue) { qualityToUse = model.ParentRequest.QualityOverride.Value; diff --git a/src/Ombi.Store/Migrations/20180920201101_UserQualityProfiles.Designer.cs b/src/Ombi.Store/Migrations/20180920201101_UserQualityProfiles.Designer.cs new file mode 100644 index 000000000..c9e18ef3a --- /dev/null +++ b/src/Ombi.Store/Migrations/20180920201101_UserQualityProfiles.Designer.cs @@ -0,0 +1,1151 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20180920201101_UserQualityProfiles")] + partial class UserQualityProfiles + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", 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.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + 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.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + 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.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", 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 + } + } +} diff --git a/src/Ombi.Store/Migrations/20180920201101_UserQualityProfiles.cs b/src/Ombi.Store/Migrations/20180920201101_UserQualityProfiles.cs new file mode 100644 index 000000000..bbcc2e79e --- /dev/null +++ b/src/Ombi.Store/Migrations/20180920201101_UserQualityProfiles.cs @@ -0,0 +1,46 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class UserQualityProfiles : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "UserQualityProfiles", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: true), + SonarrQualityProfileAnime = table.Column(nullable: false), + SonarrRootPathAnime = table.Column(nullable: false), + SonarrRootPath = table.Column(nullable: false), + SonarrQualityProfile = table.Column(nullable: false), + RadarrRootPath = table.Column(nullable: false), + RadarrQualityProfile = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserQualityProfiles", x => x.Id); + table.ForeignKey( + name: "FK_UserQualityProfiles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_UserQualityProfiles_UserId", + table: "UserQualityProfiles", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "UserQualityProfiles"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 5e5aa23c6..86694ec23 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -890,6 +890,32 @@ namespace Ombi.Store.Migrations b.ToTable("UserNotificationPreferences"); }); + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => { b.Property("Id") @@ -1095,6 +1121,13 @@ namespace Ombi.Store.Migrations .HasForeignKey("UserId"); }); + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", 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") diff --git a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html index c834fbdbd..50938412f 100644 --- a/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html +++ b/src/Ombi/ClientApp/app/settings/lidarr/lidarr.component.html @@ -63,8 +63,8 @@ + A Default Quality Profile is required
    - A Default Quality Profile is required
    @@ -102,9 +102,9 @@ + A Metadata profile is required
    - A Metadata profile is required
    diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index bdb277d7e..0d13b17c3 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -139,57 +139,60 @@ - +
    -
    - -
    - +
    + +
    +
    -
    + +
    -
    - +
    +
    -
    + +
    -
    - +
    +
    -
    + +
    -
    - +
    +
    -
    - -
    - +
    + +
    +
    -
    +
    -
    - +
    +
    diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts index b28f20f0e..4171fbfbc 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.module.ts @@ -11,7 +11,7 @@ import { UserManagementUserComponent } from "./usermanagement-user.component"; import { UserManagementComponent } from "./usermanagement.component"; import { PipeModule } from "../pipes/pipe.module"; -import { IdentityService, PlexService } from "../services"; +import { IdentityService, PlexService, RadarrService, SonarrService } from "../services"; import { AuthGuard } from "../auth/auth.guard"; @@ -58,6 +58,8 @@ const routes: Routes = [ IdentityService, ConfirmationService, PlexService, + RadarrService, + SonarrService, ], }) diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 37290b45f..33409ed7a 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -585,6 +585,15 @@ namespace Ombi.Controllers { var currentQualityProfiles = await _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == user.Id); + var add = false; + if (currentQualityProfiles == null) + { + currentQualityProfiles = new UserQualityProfiles + { + UserId = user.Id + }; + add = true; + } currentQualityProfiles.RadarrQualityProfile = ui.UserQualityProfiles.RadarrQualityProfile; currentQualityProfiles.RadarrRootPath = ui.UserQualityProfiles.RadarrRootPath; @@ -592,7 +601,10 @@ namespace Ombi.Controllers currentQualityProfiles.SonarrQualityProfileAnime = ui.UserQualityProfiles.SonarrQualityProfileAnime; currentQualityProfiles.SonarrRootPath = ui.UserQualityProfiles.SonarrRootPath; currentQualityProfiles.SonarrRootPathAnime = ui.UserQualityProfiles.SonarrRootPathAnime; - + if (add) + { + await _userQualityProfiles.Add(currentQualityProfiles); + } await _userQualityProfiles.SaveChangesAsync(); } From 550028b9ebabd1608e61b1f009a59da1919b9c6a Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 21:44:30 +0100 Subject: [PATCH 470/495] Fixed a bug with the notification preferences !wip --- src/Ombi/Controllers/IdentityController.cs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 33409ed7a..d9d8be7b1 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -579,11 +579,11 @@ namespace Ombi.Controllers { Errors = messages }; - } + } // Add the quality profiles if (ui.UserQualityProfiles != null) { - var currentQualityProfiles = await + var currentQualityProfiles = await _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == user.Id); var add = false; if (currentQualityProfiles == null) @@ -955,19 +955,23 @@ namespace Ombi.Controllers // Update it existingPreference.Value = pref.Value; existingPreference.Enabled = pref.Enabled; + await _userNotificationPreferences.SaveChangesAsync(); } - await _userNotificationPreferences.Add(new UserNotificationPreferences + else { - Agent = pref.Agent, - Enabled = pref.Enabled, - UserId = pref.UserId, - Value = pref.Value - }); + await _userNotificationPreferences.Add(new UserNotificationPreferences + { + Agent = pref.Agent, + Enabled = pref.Enabled, + UserId = pref.UserId, + Value = pref.Value + }); + } } return Json(true); } - + private async Task> AddRoles(IEnumerable roles, OmbiUser ombiUser) { var roleResult = new List(); From be2d88c9ea79cc8c8b36b3d1e3f59a5ca2184efd Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:18:26 +0100 Subject: [PATCH 471/495] Added the request limits in the ui for music --- src/Ombi.Core/Engine/IMusicRequestEngine.cs | 3 ++ src/Ombi.Core/Engine/MusicRequestEngine.cs | 46 +++++++++++++++++++ src/Ombi.Core/Models/UI/UserViewModel.cs | 1 + src/Ombi/ClientApp/app/interfaces/IUser.ts | 1 + .../requests/remainingrequests.component.ts | 8 +++- .../app/search/moviesearch.component.ts | 2 +- .../app/search/music/albumsearch.component.ts | 7 ++- .../search/music/musicsearch.component.html | 5 +- .../app/search/music/musicsearch.component.ts | 1 + .../app/search/tvsearch.component.html | 2 +- .../ClientApp/app/services/request.service.ts | 4 ++ .../usermanagement-user.component.ts | 1 + .../usermanagement.component.html | 6 +++ src/Ombi/Controllers/IdentityController.cs | 11 ++++- .../Controllers/MusicRequestController.cs | 10 ++++ src/Ombi/Controllers/RequestController.cs | 4 +- src/Ombi/wwwroot/translations/en.json | 4 +- 17 files changed, 107 insertions(+), 9 deletions(-) diff --git a/src/Ombi.Core/Engine/IMusicRequestEngine.cs b/src/Ombi.Core/Engine/IMusicRequestEngine.cs index d81ccb429..5caba8a34 100644 --- a/src/Ombi.Core/Engine/IMusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/IMusicRequestEngine.cs @@ -1,7 +1,9 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Ombi.Core.Models; using Ombi.Core.Models.Requests; using Ombi.Core.Models.UI; +using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; namespace Ombi.Core.Engine @@ -20,5 +22,6 @@ namespace Ombi.Core.Engine Task RequestAlbum(MusicAlbumRequestViewModel model); Task> SearchAlbumRequest(string search); Task UserHasRequest(string userId); + Task GetRemainingRequests(OmbiUser user = null); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MusicRequestEngine.cs b/src/Ombi.Core/Engine/MusicRequestEngine.cs index a27b17c38..89d1a221e 100644 --- a/src/Ombi.Core/Engine/MusicRequestEngine.cs +++ b/src/Ombi.Core/Engine/MusicRequestEngine.cs @@ -13,6 +13,7 @@ using Microsoft.Extensions.Logging; using Ombi.Api.Lidarr; using Ombi.Core.Authentication; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Models; using Ombi.Core.Models.UI; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Senders; @@ -409,6 +410,49 @@ namespace Ombi.Core.Engine Result = true }; } + public async Task GetRemainingRequests(OmbiUser user) + { + if (user == null) + { + user = await GetUser(); + + // If user is still null after attempting to get the logged in user, return null. + if (user == null) + { + return null; + } + } + + int limit = user.MusicRequestLimit ?? 0; + + if (limit <= 0) + { + return new RequestQuotaCountModel() + { + HasLimit = false, + Limit = 0, + Remaining = 0, + NextRequest = DateTime.Now, + }; + } + + IQueryable log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.Album); + + int count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)); + + DateTime oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7)) + .OrderBy(x => x.RequestDate) + .Select(x => x.RequestDate) + .FirstOrDefaultAsync(); + + return new RequestQuotaCountModel() + { + HasLimit = true, + Limit = limit, + Remaining = count, + NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc), + }; + } public async Task MarkAvailable(int modelId) { @@ -453,5 +497,7 @@ namespace Ombi.Core.Engine return new RequestEngineResult { Result = true, Message = $"{model.Title} has been successfully added!" }; } + + } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/UI/UserViewModel.cs b/src/Ombi.Core/Models/UI/UserViewModel.cs index 8d01c066b..ca40c2ec5 100644 --- a/src/Ombi.Core/Models/UI/UserViewModel.cs +++ b/src/Ombi.Core/Models/UI/UserViewModel.cs @@ -19,6 +19,7 @@ namespace Ombi.Core.Models.UI public int EpisodeRequestLimit { get; set; } public RequestQuotaCountModel EpisodeRequestQuota { get; set; } public RequestQuotaCountModel MovieRequestQuota { get; set; } + public RequestQuotaCountModel MusicRequestQuota { get; set; } public int MusicRequestLimit { get; set; } public UserQualityProfiles UserQualityProfiles { get; set; } } diff --git a/src/Ombi/ClientApp/app/interfaces/IUser.ts b/src/Ombi/ClientApp/app/interfaces/IUser.ts index 0cb4123a7..a44750040 100644 --- a/src/Ombi/ClientApp/app/interfaces/IUser.ts +++ b/src/Ombi/ClientApp/app/interfaces/IUser.ts @@ -20,6 +20,7 @@ export interface IUser { // FOR UI episodeRequestQuota: IRemainingRequests | null; movieRequestQuota: IRemainingRequests | null; + musicRequestQuota: IRemainingRequests | null; checked: boolean; } diff --git a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts index 4de649f6a..c88e63009 100644 --- a/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts +++ b/src/Ombi/ClientApp/app/requests/remainingrequests.component.ts @@ -12,6 +12,8 @@ import { Observable } from "rxjs"; export class RemainingRequestsComponent implements OnInit { public remaining: IRemainingRequests; @Input() public movie: boolean; + @Input() public tv: boolean; + @Input() public music: boolean; public daysUntil: number; public hoursUntil: number; public minutesUntil: number; @@ -42,9 +44,13 @@ export class RemainingRequestsComponent implements OnInit { if (this.movie) { this.requestService.getRemainingMovieRequests().subscribe(callback); - } else { + } + if(this.tv) { this.requestService.getRemainingTvRequests().subscribe(callback); } + if(this.music) { + this.requestService.getRemainingMusicRequests().subscribe(callback); + } } private calculateTime(): void { diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.ts b/src/Ombi/ClientApp/app/search/moviesearch.component.ts index 59e9fc1b8..f4d19565a 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.ts +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.ts @@ -89,9 +89,9 @@ export class MovieSearchComponent implements OnInit { try { this.requestService.requestMovie({ theMovieDbId: searchResult.id }) .subscribe(x => { - this.movieRequested.next(); this.result = x; if (this.result.result) { + this.movieRequested.next(); this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { this.notificationService.success(x); searchResult.processed = true; diff --git a/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts b/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts index 9dac4aa8b..1a44e120e 100644 --- a/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/albumsearch.component.ts @@ -1,6 +1,7 @@ import { Component, EventEmitter, Input, Output } from "@angular/core"; import { TranslateService } from "@ngx-translate/core"; +import { Subject } from "rxjs"; import { AuthService } from "../../auth/auth.service"; import { IIssueCategory, IRequestEngineResult } from "../../interfaces"; import { ISearchAlbumResult } from "../../interfaces/ISearchMusicResult"; @@ -18,6 +19,8 @@ export class AlbumSearchComponent { @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; + + @Input() public musicRequested: Subject; public issuesBarVisible = false; public issueRequestTitle: string; public issueRequestId: number; @@ -56,10 +59,12 @@ export class AlbumSearchComponent { try { this.requestService.requestAlbum({ foreignAlbumId: searchResult.foreignAlbumId }) .subscribe(x => { + this.engineResult = x; if (this.engineResult.result) { - this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { + this.musicRequested.next(); + this.translate.get("Search.RequestAdded", { title: searchResult.title }).subscribe(x => { this.notificationService.success(x); searchResult.processed = true; }); diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.html b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html index b73ee553b..e0d95203b 100644 --- a/src/Ombi/ClientApp/app/search/music/musicsearch.component.html +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.html @@ -28,6 +28,9 @@
    + + +

    @@ -35,7 +38,7 @@
    - +

    diff --git a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts index e022ab6c3..54d941da8 100644 --- a/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts +++ b/src/Ombi/ClientApp/app/search/music/musicsearch.component.ts @@ -24,6 +24,7 @@ export class MusicSearchComponent implements OnInit { public searchApplied = false; public searchAlbum: boolean = true; + public musicRequested: Subject = new Subject(); @Input() public issueCategories: IIssueCategory[]; @Input() public issuesEnabled: boolean; public issuesBarVisible = false; diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index 127077b3b..44570687a 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -27,7 +27,7 @@
    - +
    diff --git a/src/Ombi/ClientApp/app/services/request.service.ts b/src/Ombi/ClientApp/app/services/request.service.ts index dd64a14b5..0021dc208 100644 --- a/src/Ombi/ClientApp/app/services/request.service.ts +++ b/src/Ombi/ClientApp/app/services/request.service.ts @@ -26,6 +26,10 @@ export class RequestService extends ServiceHelpers { return this.http.get(`${this.url}tv/remaining`, {headers: this.headers}); } + public getRemainingMusicRequests(): Observable { + return this.http.get(`${this.url}music/remaining`, {headers: this.headers}); + } + public requestMovie(movie: IMovieRequestModel): Observable { return this.http.post(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts index ee02e53f5..5be0a4509 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.ts @@ -82,6 +82,7 @@ export class UserManagementUserComponent implements OnInit { sonarrRootPath: 0, sonarrRootPathAnime: 0, }, + musicRequestQuota: null, }; } } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html index 856e8785c..179709e5d 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement.component.html @@ -98,6 +98,9 @@
    {{'UserManagment.TvRemaining' | translate: {remaining: u.episodeRequestQuota.remaining, total: u.episodeRequestLimit} }}
    +
    + {{'UserManagment.MusicRemaining' | translate: {remaining: u.musicRequestQuota.remaining, total: u.musicRequestLimit} }} +
    @@ -106,6 +109,9 @@
    {{'UserManagment.TvDue' | translate: {date: (u.episodeRequestQuota.nextRequest | date: 'short')} }}
    +
    + {{'UserManagment.MusicDue' | translate: {date: (u.musicRequestQuota.nextRequest | date: 'short')} }} +
    {{u.lastLoggedIn | date: 'short'}} diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index d9d8be7b1..d138e973e 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -16,6 +16,7 @@ using Ombi.Api.Plex; using Ombi.Attributes; using Ombi.Config; using Ombi.Core.Authentication; +using Ombi.Core.Engine; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Helpers; using Ombi.Core.Models.UI; @@ -66,7 +67,8 @@ namespace Ombi.Controllers IRepository userProfiles, IMusicRequestRepository musicRepo, IMovieRequestEngine movieRequestEngine, - ITvRequestEngine tvRequestEngine) + ITvRequestEngine tvRequestEngine, + IMusicRequestEngine musicEngine) { UserManager = user; Mapper = mapper; @@ -92,6 +94,7 @@ namespace Ombi.Controllers MovieRequestEngine = movieRequestEngine; _userNotificationPreferences = notificationPreferences; _userQualityProfiles = userProfiles; + MusicRequestEngine = musicEngine; } private OmbiUserManager UserManager { get; } @@ -106,6 +109,7 @@ namespace Ombi.Controllers private IMovieRequestRepository MovieRepo { get; } private ITvRequestRepository TvRepo { get; } private IMovieRequestEngine MovieRequestEngine { get; } + private IMusicRequestEngine MusicRequestEngine { get; } private ITvRequestEngine TvRequestEngine { get; } private IMusicRequestRepository MusicRepo { get; } private readonly ILogger _log; @@ -342,6 +346,11 @@ namespace Ombi.Controllers vm.MovieRequestQuota = await MovieRequestEngine.GetRemainingRequests(user); } + if (vm.MusicRequestLimit > 0) + { + vm.MusicRequestQuota = await MusicRequestEngine.GetRemainingRequests(user); + } + // Get the quality profiles vm.UserQualityProfiles = await _userQualityProfiles.GetAll().FirstOrDefaultAsync(x => x.UserId == user.Id); if (vm.UserQualityProfiles == null) diff --git a/src/Ombi/Controllers/MusicRequestController.cs b/src/Ombi/Controllers/MusicRequestController.cs index 3758da9d8..0d763cd86 100644 --- a/src/Ombi/Controllers/MusicRequestController.cs +++ b/src/Ombi/Controllers/MusicRequestController.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Ombi.Store.Entities.Requests; using Ombi.Attributes; +using Ombi.Core.Models; using Ombi.Core.Models.UI; namespace Ombi.Controllers @@ -140,5 +141,14 @@ namespace Ombi.Controllers { return await _engine.DenyAlbumById(model.Id); } + + /// + /// Gets model containing remaining number of music requests. + /// + [HttpGet("remaining")] + public async Task GetRemainingMusicRequests() + { + return await _engine.GetRemainingRequests(); + } } } \ No newline at end of file diff --git a/src/Ombi/Controllers/RequestController.cs b/src/Ombi/Controllers/RequestController.cs index f2412727f..25270f9dd 100644 --- a/src/Ombi/Controllers/RequestController.cs +++ b/src/Ombi/Controllers/RequestController.cs @@ -467,7 +467,7 @@ namespace Ombi.Controllers } /// - /// Gets model containing remaining number of requests. + /// Gets model containing remaining number of movie requests. /// [HttpGet("movie/remaining")] public async Task GetRemainingMovieRequests() @@ -476,7 +476,7 @@ namespace Ombi.Controllers } /// - /// Gets model containing remaining number of requests. + /// Gets model containing remaining number of tv requests. /// [HttpGet("tv/remaining")] public async Task GetRemainingTvRequests() diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index ca8dbcd3e..cbe2c034e 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -189,7 +189,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } From cb726a65e68b85eae48d2b543ddb49fedcd8fcf7 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:22 +0100 Subject: [PATCH 472/495] New translations en.json (Danish) --- src/Ombi/wwwroot/translations/da.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index cdc6f05ac..17c671217 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From 44a6b33618ae52d936af953b45236123ed749e99 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:30 +0100 Subject: [PATCH 473/495] New translations en.json (Dutch) --- src/Ombi/wwwroot/translations/nl.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 49482b32f..60d54fe8c 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From e82d163060fffa1a400ed0972ea67bed19a43b4d Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:31 +0100 Subject: [PATCH 474/495] New translations en.json (French) --- src/Ombi/wwwroot/translations/fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 3bd929acb..0834653f8 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From 14a04bd3eba8f4faa222a0674f709e11588af689 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:32 +0100 Subject: [PATCH 475/495] New translations en.json (German) --- src/Ombi/wwwroot/translations/de.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 7ca0aa465..2da1aab4e 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From 219a6412942cee38a9e92665ee7d187e7e1e0c8f Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:33 +0100 Subject: [PATCH 476/495] New translations en.json (Italian) --- src/Ombi/wwwroot/translations/it.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 374fdd311..25f706303 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From ffeeb36debbd55a7ed63c99aae594ee9288505e1 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:35 +0100 Subject: [PATCH 477/495] New translations en.json (Norwegian) --- src/Ombi/wwwroot/translations/no.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 08e42da84..87df0181f 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From fa3b46bf517c9414ed44d9582a9e728e2b12b8ce Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:36 +0100 Subject: [PATCH 478/495] New translations en.json (Polish) --- src/Ombi/wwwroot/translations/pl.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index 65c31fc68..8e180e5bb 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From 62986ffaf7ed905af69ef9e91629155c5febf215 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:37 +0100 Subject: [PATCH 479/495] New translations en.json (Portuguese, Brazilian) --- src/Ombi/wwwroot/translations/pt.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index 573bb2f9f..e547d0066 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From 1916f7756ad7eed4d6192d927b0e93cfd3d8cb2e Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:38 +0100 Subject: [PATCH 480/495] New translations en.json (Spanish) --- src/Ombi/wwwroot/translations/es.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 115ac6aa6..a49ea5140 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From eacfb0ab85bc021610c47a7d555e34ec8a04cade Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 20 Sep 2018 22:21:39 +0100 Subject: [PATCH 481/495] New translations en.json (Swedish) --- src/Ombi/wwwroot/translations/sv.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 57467c64c..26a85fe10 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -184,7 +184,9 @@ "UserManagment": { "TvRemaining": "TV: {{remaining}}/{{total}} remaining", "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}" + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" } } \ No newline at end of file From b5baa5f6e02b17681ff24430620558113d2db9fb Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 21 Sep 2018 17:57:13 +0100 Subject: [PATCH 482/495] Update settingsmenu.component.html --- src/Ombi/ClientApp/app/settings/settingsmenu.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index a8d89ab1c..0465cc8c8 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -53,7 +53,7 @@ Music From 0a150570b4ea51126a27c548f1372f99dd351a31 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 21 Sep 2018 21:00:12 +0100 Subject: [PATCH 483/495] !wip changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 031386283..7d0faf5b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ### **New Features** +- Added the request limits in the ui for music. [Jamie] + +- Added the root folders and qualities per user! [Jamie] + - Updated all the MS packages. [TidusJar] - Update the .net core packages to fix "CVE-2018-8409: ASP.NET Core Denial Of Service Vulnerability" [TidusJar] @@ -22,6 +26,10 @@ ### **Fixes** +- Fixed #2518. [TidusJar] + +- Fixed #2522. [TidusJar] + - Fixed #2485. [TidusJar] - Fixed #2516. [TidusJar] From 86bff311f1e0cfb9e74d94566fc9a607336a1dd2 Mon Sep 17 00:00:00 2001 From: Anojh Date: Sat, 22 Sep 2018 10:34:16 -0700 Subject: [PATCH 484/495] fix #2527 - Music request not triggering search and failing --- src/Ombi.Api.Lidarr/LidarrApi.cs | 4 ++-- src/Ombi.Core/Senders/MusicSender.cs | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Ombi.Api.Lidarr/LidarrApi.cs b/src/Ombi.Api.Lidarr/LidarrApi.cs index 8cda49cbf..a6a283703 100644 --- a/src/Ombi.Api.Lidarr/LidarrApi.cs +++ b/src/Ombi.Api.Lidarr/LidarrApi.cs @@ -156,8 +156,8 @@ namespace Ombi.Api.Lidarr public Task AlbumSearch(int[] albumIds, string apiKey, string baseUrl) { - var request = new Request($"{ApiVersion}/command/AlbumSearch", baseUrl, HttpMethod.Post); - request.AddJsonBody(albumIds); + var request = new Request($"{ApiVersion}/command/", baseUrl, HttpMethod.Post); + request.AddJsonBody(new { name = "AlbumSearch", albumIds }); AddHeaders(request, apiKey); return Api.Request(request); } diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 937204be5..481fe4090 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -82,7 +82,8 @@ namespace Ombi.Core.Senders } else { - await SetupAlbum(model, artist, settings); + SenderResult result = await SetupAlbum(model, artist, settings); + return result; } return new SenderResult { Success = false, Sent = false, Message = "Album is already monitored" }; @@ -122,7 +123,7 @@ namespace Ombi.Core.Senders } if (result.monitored) { - return new SenderResult {Message = "Album has been requested!", Sent = true, Success = true}; + return new SenderResult { Message = "Album has been requested!", Sent = true, Success = true}; } return new SenderResult { Message = "Could not set album to monitored", Sent = false, Success = false }; } From bf33d49dcb257b243fc0339f0b6b999522b39335 Mon Sep 17 00:00:00 2001 From: Anojh Date: Sat, 22 Sep 2018 11:24:37 -0700 Subject: [PATCH 485/495] Fix #2529 - Change data type to long --- src/Ombi.Api.Lidarr/Models/Statistics.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Api.Lidarr/Models/Statistics.cs b/src/Ombi.Api.Lidarr/Models/Statistics.cs index 5d8eb4275..77c6b5217 100644 --- a/src/Ombi.Api.Lidarr/Models/Statistics.cs +++ b/src/Ombi.Api.Lidarr/Models/Statistics.cs @@ -6,7 +6,7 @@ public int trackFileCount { get; set; } public int trackCount { get; set; } public int totalTrackCount { get; set; } - public int sizeOnDisk { get; set; } + public long sizeOnDisk { get; set; } public decimal percentOfEpisodes { get; set; } } } \ No newline at end of file From 68d2c741e9957811836c6daf417ed752fd9c1251 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sat, 22 Sep 2018 22:24:35 +0100 Subject: [PATCH 486/495] !wip changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d0faf5b4..53e90a984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,19 @@ ## (unreleased) +### **Fixes** + +- Fix #2529 - Change data type to long. [Anojh] + +- Fix #2527 - Music request not triggering search and failing. [Anojh] + + +## v3.0.3776 (2018-09-21) + ### **New Features** +- Update settingsmenu.component.html. [Jamie] + - Added the request limits in the ui for music. [Jamie] - Added the root folders and qualities per user! [Jamie] From f8d36d91f70b5f6d4ee21905d9dfd748bb0161a9 Mon Sep 17 00:00:00 2001 From: Qstick Date: Sun, 23 Sep 2018 13:06:43 -0400 Subject: [PATCH 487/495] Fixed: Removes Legacy command result variables --- src/Ombi.Api.Lidarr/Models/CommandResult.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Api.Lidarr/Models/CommandResult.cs b/src/Ombi.Api.Lidarr/Models/CommandResult.cs index 7c6483a6a..5271de91f 100644 --- a/src/Ombi.Api.Lidarr/Models/CommandResult.cs +++ b/src/Ombi.Api.Lidarr/Models/CommandResult.cs @@ -6,10 +6,10 @@ namespace Ombi.Api.Lidarr.Models public class CommandResult { public string name { get; set; } - public DateTime startedOn { get; set; } + public DateTime queued { get; set; } public DateTime stateChangeTime { get; set; } public bool sendUpdatesToClient { get; set; } - public string state { get; set; } + public string status { get; set; } public int id { get; set; } } -} \ No newline at end of file +} From 87cc5d4cc7fbabf46b552fbdf0f27f5a8424d4b3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 23 Sep 2018 21:30:51 +0100 Subject: [PATCH 488/495] Fixed the issue with notifications not sending --- .../NotificationMessageCurlys.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 5bc74f68e..1b655b84d 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -17,7 +17,11 @@ namespace Ombi.Notifications public void Setup(NotificationOptions opts, FullBaseRequest req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); - UserPreference = pref.Enabled ? pref.Value : string.Empty; + if (pref != null) + { + UserPreference = pref.Enabled ? pref.Value : string.Empty; + } + string title; if (req == null) { @@ -62,7 +66,10 @@ namespace Ombi.Notifications public void Setup(NotificationOptions opts, AlbumRequest req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); - UserPreference = pref.Enabled ? pref.Value : string.Empty; + if (pref != null) + { + UserPreference = pref.Enabled ? pref.Value : string.Empty; + } string title; if (req == null) { @@ -106,7 +113,10 @@ namespace Ombi.Notifications public void Setup(NotificationOptions opts, ChildRequests req, CustomizationSettings s, UserNotificationPreferences pref) { LoadIssues(opts); - UserPreference = pref.Enabled ? pref.Value : string.Empty; + if (pref != null) + { + UserPreference = pref.Enabled ? pref.Value : string.Empty; + } string title; if (req == null) { From 03ca0ea0c5eb93f656659d049901d23569db8e4e Mon Sep 17 00:00:00 2001 From: Jamie Date: Sun, 23 Sep 2018 21:32:38 +0100 Subject: [PATCH 489/495] !wip changelog --- CHANGELOG.md | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53e90a984..655689bec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,107 @@ ### **Fixes** +- Fixed the issue with notifications not sending. [Jamie] + +- Removes Legacy command result variables. [Qstick] + + +## v3.0.3786 (2018-09-22) + +### **New Features** + +- Update CHANGELOG.md. [Jamie] + +### **Fixes** + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Norwegian) [Jamie] + +- New translations en.json (Italian) [Jamie] + +- New translations en.json (German) [Jamie] + +- New translations en.json (French) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Danish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Norwegian) [Jamie] + +- New translations en.json (Italian) [Jamie] + +- New translations en.json (German) [Jamie] + +- New translations en.json (French) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Danish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Norwegian) [Jamie] + +- New translations en.json (Italian) [Jamie] + +- New translations en.json (German) [Jamie] + +- New translations en.json (French) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Danish) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (German) [Jamie] + +- New translations en.json (German) [Jamie] + +- New translations en.json (Swedish) [Jamie] + +- New translations en.json (Spanish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + +- New translations en.json (Polish) [Jamie] + +- New translations en.json (Norwegian) [Jamie] + +- New translations en.json (Italian) [Jamie] + +- New translations en.json (German) [Jamie] + +- New translations en.json (French) [Jamie] + +- New translations en.json (Dutch) [Jamie] + +- New translations en.json (Danish) [Jamie] + +- New translations en.json (Portuguese, Brazilian) [Jamie] + - Fix #2529 - Change data type to long. [Anojh] - Fix #2527 - Music request not triggering search and failing. [Anojh] From 745ed9a30f999f519dce1c9591d865a79e487ecf Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 25 Sep 2018 19:51:37 +0100 Subject: [PATCH 490/495] Fixed #2535 --- .../usermanagement-user.component.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index 0d13b17c3..6f3ae63ee 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -144,7 +144,7 @@
    -
    +
    @@ -162,7 +162,7 @@
    -
    +
    @@ -179,7 +179,7 @@
    -
    +
    -
    +
    + +
    +
    + +
    +
    + + +
    +
    +
    diff --git a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts index c8a85e8e1..37ead870a 100644 --- a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts +++ b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts @@ -21,8 +21,10 @@ export class IssuesComponent implements OnInit { public ngOnInit() { this.settingsService.getIssueSettings().subscribe(x => { this.form = this.fb.group({ - enabled: [x.enabled], - enableInProgress: [x.enableInProgress], + enabled: [x.enabled], + enableInProgress: [x.enableInProgress], + deleteIssues: [x.deleteIssues], + daysAfterResolvedToDelete: [x.daysAfterResolvedToDelete], }); }); this.getCategories(); diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index a4dcd6fb3..1365710f0 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -85,12 +85,19 @@
    -
    +
    The Newsletter is required
    + +
    + + + The Issues Purge is required + +
    diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index 756d6ba89..d8ce106ae 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -35,6 +35,7 @@ export class JobsComponent implements OnInit { newsletter: [x.newsletter, Validators.required], plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], lidarrArtistSync: [x.lidarrArtistSync, Validators.required], + issuesPurge: [x.issuesPurge, Validators.required], }); }); } diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index 474ae8823..9785af553 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -519,7 +519,8 @@ namespace Ombi.Controllers j.PlexRecentlyAddedSync = j.PlexRecentlyAddedSync.HasValue() ? j.PlexRecentlyAddedSync : JobSettingsHelper.PlexRecentlyAdded(j); j.Newsletter = j.Newsletter.HasValue() ? j.Newsletter : JobSettingsHelper.Newsletter(j); j.LidarrArtistSync = j.LidarrArtistSync.HasValue() ? j.LidarrArtistSync : JobSettingsHelper.LidarrArtistSync(j); - + j.IssuesPurge = j.IssuesPurge.HasValue() ? j.IssuesPurge : JobSettingsHelper.IssuePurge(j); + return j; } From 7aa2b72c7bd56c1e2f494a997a26679f2ad49f81 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 27 Sep 2018 13:25:06 +0100 Subject: [PATCH 494/495] Adding missing commits !wip --- src/Ombi.Schedule/JobSetup.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index f82c96fba..7ce32de04 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -20,7 +20,8 @@ namespace Ombi.Schedule IOmbiAutomaticUpdater updater, IEmbyContentSync embySync, IPlexUserImporter userImporter, IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache, ISettingsService jobsettings, ISickRageSync srSync, IRefreshMetadata refresh, - INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedPlex, ILidarrArtistSync artist) + INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedPlex, ILidarrArtistSync artist, + IIssuesPurge purge) { _plexContentSync = plexContentSync; _radarrSync = radarrSync; @@ -36,6 +37,7 @@ namespace Ombi.Schedule _newsletter = newsletter; _plexRecentlyAddedSync = recentlyAddedPlex; _lidarrArtistSync = artist; + _issuesPurge = purge; } private readonly IPlexContentSync _plexContentSync; @@ -52,6 +54,7 @@ namespace Ombi.Schedule private readonly IRefreshMetadata _refreshMetadata; private readonly INewsletterJob _newsletter; private readonly ILidarrArtistSync _lidarrArtistSync; + private readonly IIssuesPurge _issuesPurge; public void Setup() { @@ -66,6 +69,7 @@ namespace Ombi.Schedule RecurringJob.AddOrUpdate(() => _srSync.Start(), JobSettingsHelper.SickRageSync(s)); RecurringJob.AddOrUpdate(() => _refreshMetadata.Start(), JobSettingsHelper.RefreshMetadata(s)); RecurringJob.AddOrUpdate(() => _lidarrArtistSync.CacheContent(), JobSettingsHelper.LidarrArtistSync(s)); + RecurringJob.AddOrUpdate(() => _issuesPurge.Start(), JobSettingsHelper.IssuePurge(s)); RecurringJob.AddOrUpdate(() => _updater.Update(null), JobSettingsHelper.Updater(s)); From 66af4999706101a5275def1b1c2087dc67184d89 Mon Sep 17 00:00:00 2001 From: TidusJar Date: Thu, 27 Sep 2018 13:26:41 +0100 Subject: [PATCH 495/495] Search for the Lidarr Album when it's a new artist. --- src/Ombi.Core/Senders/MusicSender.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 481fe4090..9e2dab1bd 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -76,7 +76,11 @@ namespace Ombi.Core.Senders var result = await _lidarrApi.AddArtist(newArtist, settings.ApiKey, settings.FullUri); if (result != null && result.id > 0) { - // Setup the albums + // Search for it + if (!settings.AddOnly) + { + await _lidarrApi.AlbumSearch(new[] { result.id }, settings.ApiKey, settings.FullUri); + } return new SenderResult { Message = "Album has been requested!", Sent = true, Success = true }; } }