From 974cb1ebb31cf078b1f67b9ee8032185b34c30c3 Mon Sep 17 00:00:00 2001 From: "Jamie.Rees" Date: Mon, 19 Jun 2017 15:03:39 +0100 Subject: [PATCH] Some rules #865 --- .../Rule/Request/AutoApproveRuleTests.cs | 25 ++++----- .../Rule/Request/CanRequestRuleTests.cs | 25 ++++----- .../Rule/Search/ExistingRequestRuleTests.cs | 51 +++++++++++++++++++ .../Rule/Search/PlexAvailabilityRuleTests.cs | 50 ++++++++++++++++++ .../Rule/Search/RadarrCacheRuleTests.cs | 9 ++-- src/Ombi.Core/Engine/Interfaces/BaseEngine.cs | 9 ++-- src/Ombi.Core/Engine/MovieRequestEngine.cs | 14 +++-- src/Ombi.Core/Engine/MovieSearchEngine.cs | 49 +++--------------- src/Ombi.Core/Engine/TvRequestEngine.cs | 8 +-- .../Rule/Interfaces/IRequestRules.cs | 5 +- .../Rule/Interfaces/IRuleEvaluator.cs | 5 +- src/Ombi.Core/Rule/RuleEvaluator.cs | 9 ++-- .../Rule/Rules/Request/AutoApproveRule.cs | 7 +-- .../Rule/Rules/Request/CanRequestRule.cs | 13 ++--- .../Rule/Rules/Search/ExistingRequestRule.cs | 50 ++++++++++++++++++ .../Rule/Rules/Search/PlexAvailabilityRule.cs | 28 ++++++++++ .../Rule/Rules/Search/RadarrCacheRule.cs | 7 ++- src/Ombi.Notifications/NotificationService.cs | 1 + .../notifications/discord.component.ts | 2 +- .../app/settings/sonarr/sonarr.component.ts | 39 ++++++++------ .../app/wizard/emby/emby.component.html | 2 +- .../app/wizard/emby/emby.component.ts | 12 ----- 22 files changed, 289 insertions(+), 131 deletions(-) create mode 100644 src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs create mode 100644 src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs create mode 100644 src/Ombi.Core/Rule/Rules/Search/ExistingRequestRule.cs create mode 100644 src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs diff --git a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs index e2041a57c..5e3896a65 100644 --- a/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/AutoApproveRuleTests.cs @@ -1,4 +1,5 @@ using System.Security.Principal; +using System.Threading.Tasks; using Moq; using Ombi.Core.Claims; using Ombi.Core.Models.Requests; @@ -20,64 +21,64 @@ namespace Ombi.Core.Tests.Rule private Mock PrincipalMock { get; } [Fact] - public void Should_ReturnSuccess_WhenAdminAndRequestMovie() + public async Task Should_ReturnSuccess_WhenAdminAndRequestMovie() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); Assert.Equal(request.Approved, true); } [Fact] - public void Should_ReturnSuccess_WhenAdminAndRequestTV() + public async Task Should_ReturnSuccess_WhenAdminAndRequestTV() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); Assert.Equal(request.Approved, true); } [Fact] - public void Should_ReturnSuccess_WhenAutoApproveMovieAndRequestMovie() + public async Task Should_ReturnSuccess_WhenAutoApproveMovieAndRequestMovie() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveMovie)).Returns(true); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); Assert.Equal(request.Approved, true); } [Fact] - public void Should_ReturnSuccess_WhenAutoApproveTVAndRequestTV() + public async Task Should_ReturnSuccess_WhenAutoApproveTVAndRequestTV() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveTv)).Returns(true); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); Assert.Equal(request.Approved, true); } [Fact] - public void Should_ReturnFail_WhenNoClaimsAndRequestMovie() + public async Task Should_ReturnFail_WhenNoClaimsAndRequestMovie() { var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); Assert.Equal(request.Approved, false); } [Fact] - public void Should_ReturnFail_WhenNoClaimsAndRequestTV() + public async Task Should_ReturnFail_WhenNoClaimsAndRequestTV() { var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); Assert.Equal(request.Approved, false); diff --git a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs index 3ef88f03e..51e2710e8 100644 --- a/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Request/CanRequestRuleTests.cs @@ -1,4 +1,5 @@ using System.Security.Principal; +using System.Threading.Tasks; using Moq; using Ombi.Core.Claims; using Ombi.Core.Models.Requests; @@ -19,62 +20,62 @@ namespace Ombi.Core.Tests.Rule private Mock PrincipalMock { get; } [Fact] - public void Should_ReturnSuccess_WhenRequestingMovieWithMovieRole() + public async Task Should_ReturnSuccess_WhenRequestingMovieWithMovieRole() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(true); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); } [Fact] - public void Should_ReturnFail_WhenRequestingMovieWithoutMovieRole() + public async Task Should_ReturnFail_WhenRequestingMovieWithoutMovieRole() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(false); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, false); Assert.Equal(string.IsNullOrEmpty(result.Message), false); } [Fact] - public void Should_ReturnSuccess_WhenRequestingMovieWithAdminRole() + public async Task Should_ReturnSuccess_WhenRequestingMovieWithAdminRole() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); } [Fact] - public void Should_ReturnSuccess_WhenRequestingTVWithAdminRole() + public async Task Should_ReturnSuccess_WhenRequestingTVWithAdminRole() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); } [Fact] - public void Should_ReturnSuccess_WhenRequestingTVWithTVRole() + public async Task Should_ReturnSuccess_WhenRequestingTVWithTVRole() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(true); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); } [Fact] - public void Should_ReturnFail_WhenRequestingTVWithoutTVRole() + public async Task Should_ReturnFail_WhenRequestingTVWithoutTVRole() { PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(false); var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, false); Assert.Equal(string.IsNullOrEmpty(result.Message), false); diff --git a/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs new file mode 100644 index 000000000..8992c00f6 --- /dev/null +++ b/src/Ombi.Core.Tests/Rule/Search/ExistingRequestRuleTests.cs @@ -0,0 +1,51 @@ +using System.Threading.Tasks; +using Moq; +using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Requests.Movie; +using Ombi.Core.Models.Search; +using Ombi.Core.Requests.Models; +using Ombi.Core.Rule.Rules.Search; +using Ombi.Store.Context; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Xunit; + +namespace Ombi.Core.Tests.Rule.Search +{ + public class ExistignRequestRuleTests + { + public ExistignRequestRuleTests() + { + MovieMock = new Mock>(); + TvMock = new Mock>(); + Rule = new ExistingRequestRule(MovieMock.Object, TvMock.Object); + } + + private ExistingRequestRule Rule { get; } + private Mock> MovieMock { get; } + private Mock> TvMock { get; } + + // TODO continue tests + // https://stackoverflow.com/questions/27483709/testing-ef-async-methods-with-sync-methods-with-moq + public async Task ShouldBe_Requested_WhenExisitngMovie() + { + var list = DbHelper.GetQueryableMockDbSet(new MovieRequestModel + { + ProviderId = 123, + Approved = true + }); + MovieMock.Setup(x => x.GetAllQueryable()).Returns(list); + var search = new SearchMovieViewModel + { + Id = 123, + + }; + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.Equal(search.Approved, true); + } + + + } +} \ No newline at end of file diff --git a/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs new file mode 100644 index 000000000..fd49ee83d --- /dev/null +++ b/src/Ombi.Core.Tests/Rule/Search/PlexAvailabilityRuleTests.cs @@ -0,0 +1,50 @@ +using System.Threading.Tasks; +using Moq; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Rules.Search; +using Ombi.Store.Context; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Xunit; + +namespace Ombi.Core.Tests.Rule.Search +{ + public class PlexAvailabilityRuleTests + { + public PlexAvailabilityRuleTests() + { + ContextMock = new Mock(); + Rule = new PlexAvailabilityRule(ContextMock.Object); + } + + private PlexAvailabilityRule Rule { get; } + private Mock ContextMock { get; } + + [Fact] + public async Task ShouldBe_Available_WhenFoundInPlex() + { + ContextMock.Setup(x => x.Get(It.IsAny())).ReturnsAsync(new PlexContent + { + Url = "TestUrl" + }); + var search = new SearchMovieViewModel(); + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.Equal(search.PlexUrl, "TestUrl"); + Assert.Equal(search.Available, true); + } + + [Fact] + public async Task ShouldBe_NotAvailable_WhenNotFoundInPlex() + { + ContextMock.Setup(x => x.Get(It.IsAny())).Returns(Task.FromResult(default(PlexContent))); + var search = new SearchMovieViewModel(); + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.Equal(search.PlexUrl, null); + Assert.Equal(search.Available, false); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs index 8bea13335..cfa77a3a4 100644 --- a/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs +++ b/src/Ombi.Core.Tests/Rule/Search/RadarrCacheRuleTests.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using Moq; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Rules.Search; @@ -19,7 +20,7 @@ namespace Ombi.Core.Tests.Rule.Search private Mock ContextMock { get; } [Fact] - public void Should_ReturnApproved_WhenMovieIsInRadarr() + public async Task Should_ReturnApproved_WhenMovieIsInRadarr() { var list = DbHelper.GetQueryableMockDbSet(new RadarrCache { @@ -29,7 +30,7 @@ namespace Ombi.Core.Tests.Rule.Search ContextMock.Setup(x => x.RadarrCache).Returns(list); var request = new SearchMovieViewModel { Id = 123 }; - var result = Rule.Execute(request); + var result =await Rule.Execute(request); Assert.Equal(result.Success, true); Assert.Equal(request.Approved, true); @@ -37,7 +38,7 @@ namespace Ombi.Core.Tests.Rule.Search [Fact] - public void Should_ReturnNotApproved_WhenMovieIsNotInRadarr() + public async Task Should_ReturnNotApproved_WhenMovieIsNotInRadarr() { var list = DbHelper.GetQueryableMockDbSet(new RadarrCache { @@ -47,7 +48,7 @@ namespace Ombi.Core.Tests.Rule.Search ContextMock.Setup(x => x.RadarrCache).Returns(list); var request = new SearchMovieViewModel { Id = 123 }; - var result = Rule.Execute(request); + var result = await Rule.Execute(request); Assert.Equal(result.Success, true); Assert.Equal(request.Approved, false); diff --git a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs index 6941acef1..9e9fc5733 100644 --- a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs @@ -7,6 +7,7 @@ using Ombi.Store.Entities; using System.Collections.Generic; using System.Linq; using System.Security.Principal; +using System.Threading.Tasks; using Hangfire; using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Models.Search; @@ -64,15 +65,15 @@ namespace Ombi.Core.Engine.Interfaces } } - public IEnumerable RunRequestRules(BaseRequestModel model) + public async Task> RunRequestRules(BaseRequestModel model) { - var ruleResults = Rules.StartRequestRules(model).ToList(); + var ruleResults = await Rules.StartRequestRules(model); return ruleResults; } - public IEnumerable RunSearchRules(SearchViewModel model) + public async Task> RunSearchRules(SearchViewModel model) { - var ruleResults = Rules.StartSearchRules(model).ToList(); + var ruleResults = await Rules.StartSearchRules(model); return ruleResults; } } diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 71b337cdc..c729ae407 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -14,6 +14,7 @@ using System.Security.Principal; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Rule; namespace Ombi.Core.Engine { @@ -37,22 +38,26 @@ namespace Ombi.Core.Engine { var movieInfo = await MovieApi.GetMovieInformation(model.Id); if (movieInfo == null) + { return new RequestEngineResult { RequestAdded = false, Message = "There was an issue adding this movie!", ErrorMessage = $"TheMovieDb didn't have any information for ID {model.Id}" }; + } var fullMovieName = $"{movieInfo.Title}{(!string.IsNullOrEmpty(movieInfo.ReleaseDate) ? $" ({DateTime.Parse(movieInfo.ReleaseDate).Year})" : string.Empty)}"; var existingRequest = await MovieRequestService.CheckRequestAsync(model.Id); if (existingRequest != null) + { return new RequestEngineResult { RequestAdded = false, Message = $"{fullMovieName} has already been requested" }; + } // TODO //try @@ -99,12 +104,13 @@ namespace Ombi.Core.Engine Issues = IssueState.None }; - var ruleResults = RunRequestRules(requestModel).ToList(); - if (ruleResults.Any(x => !x.Success)) + var ruleResults = await RunRequestRules(requestModel); + var results = ruleResults as RuleResult[] ?? ruleResults.ToArray(); + if (results.Any(x => !x.Success)) { return new RequestEngineResult { - ErrorMessage = ruleResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message + ErrorMessage = results.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message }; } @@ -186,7 +192,7 @@ namespace Ombi.Core.Engine { NotificationHelper.NewRequest(model); } - + //var limit = await RequestLimitRepo.GetAllAsync(); //var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type); //if (usersLimit == null) diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index e94ec8e8e..1cb26fcfb 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -3,7 +3,6 @@ using Microsoft.Extensions.Logging; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Requests; -using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Models.Search; using Ombi.Core.Rules; using Ombi.Core.Settings; @@ -49,7 +48,6 @@ namespace Ombi.Core.Engine return new List(); var retVal = new List(); - var dbMovies = await GetMovieRequests(); var plexSettings = await PlexSettings.GetSettingsAsync(); var embySettings = await EmbySettings.GetSettingsAsync(); @@ -59,22 +57,20 @@ namespace Ombi.Core.Engine var movieInfo = await MovieApi.GetMovieInformationWithVideo(m.Id); var viewMovie = Mapper.Map(movieInfo); - retVal.Add(await ProcessSingleMovie(viewMovie, dbMovies, plexSettings, embySettings)); + retVal.Add(await ProcessSingleMovie(viewMovie, plexSettings, embySettings)); } return retVal; } public async Task LookupImdbInformation(int theMovieDbId) { - var dbMovies = await GetMovieRequests(); - var plexSettings = await PlexSettings.GetSettingsAsync(); var embySettings = await EmbySettings.GetSettingsAsync(); var movieInfo = await MovieApi.GetMovieInformationWithVideo(theMovieDbId); var viewMovie = Mapper.Map(movieInfo); - return await ProcessSingleMovie(viewMovie, dbMovies, plexSettings, embySettings, true); + return await ProcessSingleMovie(viewMovie, plexSettings, embySettings, true); } public async Task> Search(string search) @@ -148,25 +144,22 @@ namespace Ombi.Core.Engine { var viewMovies = new List(); - Dictionary dbMovies; Settings.Models.External.PlexSettings plexSettings; Settings.Models.External.EmbySettings embySettings; using (MiniProfiler.Current.Step("Gettings Movies and Settings")) { - dbMovies = await GetMovieRequests(); - plexSettings = await PlexSettings.GetSettingsAsync(); embySettings = await EmbySettings.GetSettingsAsync(); } foreach (var movie in movies) { - viewMovies.Add(await ProcessSingleMovie(movie, dbMovies, plexSettings, embySettings)); + viewMovies.Add(await ProcessSingleMovie(movie, plexSettings, embySettings)); } return viewMovies; } private async Task ProcessSingleMovie(SearchMovieViewModel viewMovie, - Dictionary existingRequests, PlexSettings plexSettings, EmbySettings embySettings, bool lookupExtraInfo = false) + PlexSettings plexSettings, EmbySettings embySettings, bool lookupExtraInfo = false) { if (plexSettings.Enable) @@ -175,25 +168,7 @@ namespace Ombi.Core.Engine { var showInfo = await MovieApi.GetMovieInformation(viewMovie.Id); viewMovie.Id = showInfo.Id; // TheMovieDbId - var item = await PlexContentRepo.Get(showInfo.ImdbId); - if (item != null) - { - viewMovie.Available = true; - viewMovie.PlexUrl = item.Url; - } } - - // var content = PlexContentRepository.GetAll(); - // var plexMovies = PlexChecker.GetPlexMovies(content); - - // var plexMovie = PlexChecker.GetMovie(plexMovies.ToArray(), movie.Title, - // movie.ReleaseDate?.Year.ToString(), - // viewMovie.ImdbId); - // if (plexMovie != null) - // { - // viewMovie.Available = true; - // viewMovie.PlexUrl = plexMovie.Url; - // } } if (embySettings.Enable) { @@ -208,26 +183,16 @@ namespace Ombi.Core.Engine // } } - if (existingRequests.ContainsKey(viewMovie.Id)) // Do we already have a request for this? - { - var requestedMovie = existingRequests[viewMovie.Id]; - - viewMovie.Requested = true; - viewMovie.Approved = requestedMovie.Approved; - viewMovie.Available = requestedMovie.Available; - } - - RunSearchRules(viewMovie); + await RunSearchRules(viewMovie); return viewMovie; } - private async Task ProcessSingleMovie(MovieSearchResult movie, - Dictionary existingRequests, PlexSettings plexSettings, EmbySettings embySettings) + private async Task ProcessSingleMovie(MovieSearchResult movie, PlexSettings plexSettings, EmbySettings embySettings) { var viewMovie = Mapper.Map(movie); - return await ProcessSingleMovie(viewMovie, existingRequests, plexSettings, embySettings); + return await ProcessSingleMovie(viewMovie, plexSettings, embySettings); } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index c09648881..19b15c80f 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -15,6 +15,7 @@ using System.Linq; using System.Security.Principal; using System.Threading.Tasks; using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Rule; namespace Ombi.Core.Engine { @@ -141,12 +142,13 @@ namespace Ombi.Core.Engine } } - var ruleResults = RunRequestRules(model).ToList(); - if (ruleResults.Any(x => !x.Success)) + var ruleResults = await RunRequestRules(model); + var results = ruleResults as RuleResult[] ?? ruleResults.ToArray(); + if (results.Any(x => !x.Success)) { return new RequestEngineResult { - ErrorMessage = ruleResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message + ErrorMessage = results.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message }; } diff --git a/src/Ombi.Core/Rule/Interfaces/IRequestRules.cs b/src/Ombi.Core/Rule/Interfaces/IRequestRules.cs index 4aab45ae2..6ea0e1510 100644 --- a/src/Ombi.Core/Rule/Interfaces/IRequestRules.cs +++ b/src/Ombi.Core/Rule/Interfaces/IRequestRules.cs @@ -1,9 +1,10 @@ -using Ombi.Core.Models.Requests; +using System.Threading.Tasks; +using Ombi.Core.Models.Requests; namespace Ombi.Core.Rule.Interfaces { public interface IRequestRules where T : new() { - RuleResult Execute(T obj); + Task Execute(T obj); } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Interfaces/IRuleEvaluator.cs b/src/Ombi.Core/Rule/Interfaces/IRuleEvaluator.cs index 2794871a0..de8d372bf 100644 --- a/src/Ombi.Core/Rule/Interfaces/IRuleEvaluator.cs +++ b/src/Ombi.Core/Rule/Interfaces/IRuleEvaluator.cs @@ -1,13 +1,14 @@ using Ombi.Core.Models.Requests; using Ombi.Core.Rule; using System.Collections.Generic; +using System.Threading.Tasks; using Ombi.Core.Models.Search; namespace Ombi.Core.Rules { public interface IRuleEvaluator { - IEnumerable StartRequestRules(BaseRequestModel obj); - IEnumerable StartSearchRules(SearchViewModel obj); + Task> StartRequestRules(BaseRequestModel obj); + Task> StartSearchRules(SearchViewModel obj); } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/RuleEvaluator.cs b/src/Ombi.Core/Rule/RuleEvaluator.cs index 1fe618694..350e78fe8 100644 --- a/src/Ombi.Core/Rule/RuleEvaluator.cs +++ b/src/Ombi.Core/Rule/RuleEvaluator.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; @@ -62,24 +63,24 @@ namespace Ombi.Core.Rule private List> RequestRules { get; } private List> SearchRules { get; } - public IEnumerable StartRequestRules(BaseRequestModel obj) + public async Task> StartRequestRules(BaseRequestModel obj) { var results = new List(); foreach (var rule in RequestRules) { - var result = rule.Execute(obj); + var result = await rule.Execute(obj); results.Add(result); } return results; } - public IEnumerable StartSearchRules(SearchViewModel obj) + public async Task> StartSearchRules(SearchViewModel obj) { var results = new List(); foreach (var rule in SearchRules) { - var result = rule.Execute(obj); + var result = await rule.Execute(obj); results.Add(result); } diff --git a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs index 78291e771..b0d5f254e 100644 --- a/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/AutoApproveRule.cs @@ -1,4 +1,5 @@ using System.Security.Principal; +using System.Threading.Tasks; using Ombi.Core.Claims; using Ombi.Core.Models.Requests; using Ombi.Core.Rule.Interfaces; @@ -15,19 +16,19 @@ namespace Ombi.Core.Rule.Rules.Request private IPrincipal User { get; } - public RuleResult Execute(BaseRequestModel obj) + public Task Execute(BaseRequestModel obj) { if (User.IsInRole(OmbiClaims.Admin)) { obj.Approved = true; - return Success(); + return Task.FromResult(Success()); } if (obj.Type == RequestType.Movie && User.IsInRole(OmbiClaims.AutoApproveMovie)) obj.Approved = true; if (obj.Type == RequestType.TvShow && User.IsInRole(OmbiClaims.AutoApproveTv)) obj.Approved = true; - return Success(); // We don't really care, we just don't set the obj to approve + return Task.FromResult(Success()); // We don't really care, we just don't set the obj to approve } } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs index 7cf8d0b07..887a2fd40 100644 --- a/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/CanRequestRule.cs @@ -3,6 +3,7 @@ using Ombi.Core.Models.Requests; using Ombi.Core.Rules; using Ombi.Store.Entities; using System.Security.Principal; +using System.Threading.Tasks; using Ombi.Core.Rule.Interfaces; namespace Ombi.Core.Rule.Rules @@ -16,21 +17,21 @@ namespace Ombi.Core.Rule.Rules private IPrincipal User { get; } - public RuleResult Execute(BaseRequestModel obj) + public Task Execute(BaseRequestModel obj) { if (User.IsInRole(OmbiClaims.Admin)) - return Success(); + return Task.FromResult(Success()); if (obj.Type == RequestType.Movie) { if (User.IsInRole(OmbiClaims.RequestMovie)) - return Success(); - return Fail("You do not have permissions to Request a Movie"); + return Task.FromResult(Success()); + return Task.FromResult(Fail("You do not have permissions to Request a Movie")); } if (User.IsInRole(OmbiClaims.RequestTv)) - return Success(); - return Fail("You do not have permissions to Request a Movie"); + return Task.FromResult(Success()); + return Task.FromResult(Fail("You do not have permissions to Request a Movie")); } } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/ExistingRequestRule.cs b/src/Ombi.Core/Rule/Rules/Search/ExistingRequestRule.cs new file mode 100644 index 000000000..1492caa8d --- /dev/null +++ b/src/Ombi.Core/Rule/Rules/Search/ExistingRequestRule.cs @@ -0,0 +1,50 @@ +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Requests.Movie; +using Ombi.Core.Models.Search; +using Ombi.Core.Requests.Models; +using Ombi.Core.Rule.Interfaces; + +namespace Ombi.Core.Rule.Rules.Search +{ + public class ExistingRequestRule : BaseSearchRule, IRequestRules + { + public ExistingRequestRule(IRequestService movie, IRequestService tv) + { + Movie = movie; + Tv = tv; + } + + private IRequestService Movie { get; } + private IRequestService Tv { get; } + + public async Task Execute(SearchViewModel obj) + { + var movieRequests = Movie.GetAllQueryable(); + var existing = await movieRequests.FirstOrDefaultAsync(x => x.ProviderId == obj.Id); + if (existing != null) // Do we already have a request for this? + { + + obj.Requested = true; + obj.Approved = existing.Approved; + obj.Available = existing.Available; + + return Success(); + } + + var tvRequests = Tv.GetAllQueryable(); + var movieExisting = await tvRequests.FirstOrDefaultAsync(x => x.ProviderId == obj.Id); + if (movieExisting != null) // Do we already have a request for this? + { + + obj.Requested = true; + obj.Approved = movieExisting.Approved; + obj.Available = movieExisting.Available; + + return Success(); + } + return Success(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs new file mode 100644 index 000000000..82f5f7c8f --- /dev/null +++ b/src/Ombi.Core/Rule/Rules/Search/PlexAvailabilityRule.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Interfaces; +using Ombi.Store.Repository; + +namespace Ombi.Core.Rule.Rules.Search +{ + public class PlexAvailabilityRule : BaseSearchRule, IRequestRules + { + public PlexAvailabilityRule(IPlexContentRepository repo) + { + PlexContentRepository = repo; + } + + private IPlexContentRepository PlexContentRepository { get; } + + public async Task Execute(SearchViewModel obj) + { + var item = await PlexContentRepository.Get(obj.Id.ToString()); + if (item != null) + { + obj.Available = true; + obj.PlexUrl = item.Url; + } + return Success(); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs b/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs index bf56c8d7b..ef20def62 100644 --- a/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/RadarrCacheRule.cs @@ -1,5 +1,5 @@ using System.Linq; -using Ombi.Core.Models.Requests; +using System.Threading.Tasks; using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Store.Context; @@ -15,17 +15,16 @@ namespace Ombi.Core.Rule.Rules.Search private readonly IOmbiContext _ctx; - public RuleResult Execute(SearchViewModel obj) + public Task Execute(SearchViewModel obj) { // Check if it's in Radarr - var result = _ctx.RadarrCache.FirstOrDefault(x => x.TheMovieDbId == obj.Id); if (result != null) { obj.Approved = true; // It's in radarr so it's approved... Maybe have a new property called "Processing" or something? } - return Success(); + return Task.FromResult(Success()); } } } \ No newline at end of file diff --git a/src/Ombi.Notifications/NotificationService.cs b/src/Ombi.Notifications/NotificationService.cs index 263651491..8f93c044d 100644 --- a/src/Ombi.Notifications/NotificationService.cs +++ b/src/Ombi.Notifications/NotificationService.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Ombi.Core.Notifications; using Ombi.Helpers; +using Ombi.Notifications.Interfaces; using Ombi.Notifications.Models; namespace Ombi.Notifications diff --git a/src/Ombi/ClientApp/app/settings/notifications/discord.component.ts b/src/Ombi/ClientApp/app/settings/notifications/discord.component.ts index 5c0da58e3..b2f148a10 100644 --- a/src/Ombi/ClientApp/app/settings/notifications/discord.component.ts +++ b/src/Ombi/ClientApp/app/settings/notifications/discord.component.ts @@ -58,7 +58,7 @@ export class DiscordComponent implements OnInit { return } - this.testerService.discordTest(form.value).subscribex(x => { + this.testerService.discordTest(form.value).subscribe(x => { if (x) { this.notificationService.success("Successful", "Successfully sent a Discord message, please check the discord channel"); } else { diff --git a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts index 36f3aa7df..200eefe44 100644 --- a/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts +++ b/src/Ombi/ClientApp/app/settings/sonarr/sonarr.component.ts @@ -9,7 +9,7 @@ import { SonarrService } from '../../services/applications/sonarr.service'; import { NotificationService } from "../../services/notification.service"; @Component({ - + templateUrl: './sonarr.component.html', }) export class SonarrComponent implements OnInit, OnDestroy { @@ -43,11 +43,11 @@ export class SonarrComponent implements OnInit, OnDestroy { this.sonarrService.getQualityProfiles(this.settings) .takeUntil(this.subscriptions) .subscribe(x => { - this.qualities = x; + this.qualities = x; - this.profilesRunning = false; - this.notificationService.success("Quality Profiles", "Successfully retrevied the Quality Profiles"); - }); + this.profilesRunning = false; + this.notificationService.success("Quality Profiles", "Successfully retrevied the Quality Profiles"); + }); } getRootFolders() { @@ -55,11 +55,11 @@ export class SonarrComponent implements OnInit, OnDestroy { this.sonarrService.getRootFolders(this.settings) .takeUntil(this.subscriptions) .subscribe(x => { - this.rootFolders = x; + this.rootFolders = x; - this.rootFoldersRunning = false; - this.notificationService.success("Settings Saved", "Successfully retrevied the Root Folders"); - }); + this.rootFoldersRunning = false; + this.notificationService.success("Settings Saved", "Successfully retrevied the Root Folders"); + }); } test() { @@ -67,15 +67,24 @@ export class SonarrComponent implements OnInit, OnDestroy { } save() { + + if (!this.qualities || !this.rootFolders) { + + this.notificationService.error("Settings Saved", "Please make sure we have selected a quality profile"); + } + if (!this.rootFolders) { + + this.notificationService.error("Settings Saved", "Please make sure we have a root folder"); + } this.settingsService.saveSonarr(this.settings) .takeUntil(this.subscriptions) .subscribe(x => { - if (x) { - this.notificationService.success("Settings Saved", "Successfully saved Sonarr settings"); - } else { - this.notificationService.success("Settings Saved", "There was an error when saving the Sonarr settings"); - } - }); + if (x) { + this.notificationService.success("Settings Saved", "Successfully saved Sonarr settings"); + } else { + this.notificationService.error("Settings Saved", "There was an error when saving the Sonarr settings"); + } + }); } ngOnDestroy(): void { diff --git a/src/Ombi/ClientApp/app/wizard/emby/emby.component.html b/src/Ombi/ClientApp/app/wizard/emby/emby.component.html index b5f523b50..79a47bc9d 100644 --- a/src/Ombi/ClientApp/app/wizard/emby/emby.component.html +++ b/src/Ombi/ClientApp/app/wizard/emby/emby.component.html @@ -1,6 +1,6 @@ 

Emby Authentication

-
+
diff --git a/src/Ombi/ClientApp/app/wizard/emby/emby.component.ts b/src/Ombi/ClientApp/app/wizard/emby/emby.component.ts index c42b95236..4d7565c5a 100644 --- a/src/Ombi/ClientApp/app/wizard/emby/emby.component.ts +++ b/src/Ombi/ClientApp/app/wizard/emby/emby.component.ts @@ -15,18 +15,6 @@ export class EmbyComponent { constructor(private embyService: EmbyService, private router: Router, private notificationService: NotificationService) { - - this.embySettings = { - administratorId: "", - apiKey: "", - enable: true, - enableEpisodeSearching: true, - id: 0, - ip: "", - port: 8096, - ssl: false, - subDir: "", - } } private embySettings: IEmbySettings;