This commit is contained in:
Jamie.Rees 2017-06-19 15:03:39 +01:00
parent d73899fc53
commit 974cb1ebb3
22 changed files with 289 additions and 131 deletions

View file

@ -1,4 +1,5 @@
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks;
using Moq; using Moq;
using Ombi.Core.Claims; using Ombi.Core.Claims;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
@ -20,64 +21,64 @@ namespace Ombi.Core.Tests.Rule
private Mock<IPrincipal> PrincipalMock { get; } private Mock<IPrincipal> PrincipalMock { get; }
[Fact] [Fact]
public void Should_ReturnSuccess_WhenAdminAndRequestMovie() public async Task Should_ReturnSuccess_WhenAdminAndRequestMovie()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; 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(result.Success, true);
Assert.Equal(request.Approved, true); Assert.Equal(request.Approved, true);
} }
[Fact] [Fact]
public void Should_ReturnSuccess_WhenAdminAndRequestTV() public async Task Should_ReturnSuccess_WhenAdminAndRequestTV()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; 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(result.Success, true);
Assert.Equal(request.Approved, true); Assert.Equal(request.Approved, true);
} }
[Fact] [Fact]
public void Should_ReturnSuccess_WhenAutoApproveMovieAndRequestMovie() public async Task Should_ReturnSuccess_WhenAutoApproveMovieAndRequestMovie()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveMovie)).Returns(true); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveMovie)).Returns(true);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; 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(result.Success, true);
Assert.Equal(request.Approved, true); Assert.Equal(request.Approved, true);
} }
[Fact] [Fact]
public void Should_ReturnSuccess_WhenAutoApproveTVAndRequestTV() public async Task Should_ReturnSuccess_WhenAutoApproveTVAndRequestTV()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveTv)).Returns(true); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveTv)).Returns(true);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; 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(result.Success, true);
Assert.Equal(request.Approved, true); Assert.Equal(request.Approved, true);
} }
[Fact] [Fact]
public void Should_ReturnFail_WhenNoClaimsAndRequestMovie() public async Task Should_ReturnFail_WhenNoClaimsAndRequestMovie()
{ {
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; 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(result.Success, true);
Assert.Equal(request.Approved, false); Assert.Equal(request.Approved, false);
} }
[Fact] [Fact]
public void Should_ReturnFail_WhenNoClaimsAndRequestTV() public async Task Should_ReturnFail_WhenNoClaimsAndRequestTV()
{ {
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; 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(result.Success, true);
Assert.Equal(request.Approved, false); Assert.Equal(request.Approved, false);

View file

@ -1,4 +1,5 @@
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks;
using Moq; using Moq;
using Ombi.Core.Claims; using Ombi.Core.Claims;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
@ -19,62 +20,62 @@ namespace Ombi.Core.Tests.Rule
private Mock<IPrincipal> PrincipalMock { get; } private Mock<IPrincipal> PrincipalMock { get; }
[Fact] [Fact]
public void Should_ReturnSuccess_WhenRequestingMovieWithMovieRole() public async Task Should_ReturnSuccess_WhenRequestingMovieWithMovieRole()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(true); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(true);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; 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(result.Success, true);
} }
[Fact] [Fact]
public void Should_ReturnFail_WhenRequestingMovieWithoutMovieRole() public async Task Should_ReturnFail_WhenRequestingMovieWithoutMovieRole()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(false); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(false);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; 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(result.Success, false);
Assert.Equal(string.IsNullOrEmpty(result.Message), false); Assert.Equal(string.IsNullOrEmpty(result.Message), false);
} }
[Fact] [Fact]
public void Should_ReturnSuccess_WhenRequestingMovieWithAdminRole() public async Task Should_ReturnSuccess_WhenRequestingMovieWithAdminRole()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; 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(result.Success, true);
} }
[Fact] [Fact]
public void Should_ReturnSuccess_WhenRequestingTVWithAdminRole() public async Task Should_ReturnSuccess_WhenRequestingTVWithAdminRole()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; 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(result.Success, true);
} }
[Fact] [Fact]
public void Should_ReturnSuccess_WhenRequestingTVWithTVRole() public async Task Should_ReturnSuccess_WhenRequestingTVWithTVRole()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(true); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(true);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; 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(result.Success, true);
} }
[Fact] [Fact]
public void Should_ReturnFail_WhenRequestingTVWithoutTVRole() public async Task Should_ReturnFail_WhenRequestingTVWithoutTVRole()
{ {
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(false); PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(false);
var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; 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(result.Success, false);
Assert.Equal(string.IsNullOrEmpty(result.Message), false); Assert.Equal(string.IsNullOrEmpty(result.Message), false);

View file

@ -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<IRequestService<MovieRequestModel>>();
TvMock = new Mock<IRequestService<TvRequestModel>>();
Rule = new ExistingRequestRule(MovieMock.Object, TvMock.Object);
}
private ExistingRequestRule Rule { get; }
private Mock<IRequestService<MovieRequestModel>> MovieMock { get; }
private Mock<IRequestService<TvRequestModel>> 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);
}
}
}

View file

@ -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<IPlexContentRepository>();
Rule = new PlexAvailabilityRule(ContextMock.Object);
}
private PlexAvailabilityRule Rule { get; }
private Mock<IPlexContentRepository> ContextMock { get; }
[Fact]
public async Task ShouldBe_Available_WhenFoundInPlex()
{
ContextMock.Setup(x => x.Get(It.IsAny<string>())).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<string>())).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);
}
}
}

View file

@ -1,3 +1,4 @@
using System.Threading.Tasks;
using Moq; using Moq;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Rules.Search; using Ombi.Core.Rule.Rules.Search;
@ -19,7 +20,7 @@ namespace Ombi.Core.Tests.Rule.Search
private Mock<IOmbiContext> ContextMock { get; } private Mock<IOmbiContext> ContextMock { get; }
[Fact] [Fact]
public void Should_ReturnApproved_WhenMovieIsInRadarr() public async Task Should_ReturnApproved_WhenMovieIsInRadarr()
{ {
var list = DbHelper.GetQueryableMockDbSet(new RadarrCache var list = DbHelper.GetQueryableMockDbSet(new RadarrCache
{ {
@ -29,7 +30,7 @@ namespace Ombi.Core.Tests.Rule.Search
ContextMock.Setup(x => x.RadarrCache).Returns(list); ContextMock.Setup(x => x.RadarrCache).Returns(list);
var request = new SearchMovieViewModel { Id = 123 }; var request = new SearchMovieViewModel { Id = 123 };
var result = Rule.Execute(request); var result =await Rule.Execute(request);
Assert.Equal(result.Success, true); Assert.Equal(result.Success, true);
Assert.Equal(request.Approved, true); Assert.Equal(request.Approved, true);
@ -37,7 +38,7 @@ namespace Ombi.Core.Tests.Rule.Search
[Fact] [Fact]
public void Should_ReturnNotApproved_WhenMovieIsNotInRadarr() public async Task Should_ReturnNotApproved_WhenMovieIsNotInRadarr()
{ {
var list = DbHelper.GetQueryableMockDbSet(new RadarrCache var list = DbHelper.GetQueryableMockDbSet(new RadarrCache
{ {
@ -47,7 +48,7 @@ namespace Ombi.Core.Tests.Rule.Search
ContextMock.Setup(x => x.RadarrCache).Returns(list); ContextMock.Setup(x => x.RadarrCache).Returns(list);
var request = new SearchMovieViewModel { Id = 123 }; var request = new SearchMovieViewModel { Id = 123 };
var result = Rule.Execute(request); var result = await Rule.Execute(request);
Assert.Equal(result.Success, true); Assert.Equal(result.Success, true);
Assert.Equal(request.Approved, false); Assert.Equal(request.Approved, false);

View file

@ -7,6 +7,7 @@ using Ombi.Store.Entities;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks;
using Hangfire; using Hangfire;
using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Models.Requests.Movie;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
@ -64,15 +65,15 @@ namespace Ombi.Core.Engine.Interfaces
} }
} }
public IEnumerable<RuleResult> RunRequestRules(BaseRequestModel model) public async Task<IEnumerable<RuleResult>> RunRequestRules(BaseRequestModel model)
{ {
var ruleResults = Rules.StartRequestRules(model).ToList(); var ruleResults = await Rules.StartRequestRules(model);
return ruleResults; return ruleResults;
} }
public IEnumerable<RuleResult> RunSearchRules(SearchViewModel model) public async Task<IEnumerable<RuleResult>> RunSearchRules(SearchViewModel model)
{ {
var ruleResults = Rules.StartSearchRules(model).ToList(); var ruleResults = await Rules.StartSearchRules(model);
return ruleResults; return ruleResults;
} }
} }

View file

@ -14,6 +14,7 @@ using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Rule;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
@ -37,22 +38,26 @@ namespace Ombi.Core.Engine
{ {
var movieInfo = await MovieApi.GetMovieInformation(model.Id); var movieInfo = await MovieApi.GetMovieInformation(model.Id);
if (movieInfo == null) if (movieInfo == null)
{
return new RequestEngineResult return new RequestEngineResult
{ {
RequestAdded = false, RequestAdded = false,
Message = "There was an issue adding this movie!", Message = "There was an issue adding this movie!",
ErrorMessage = $"TheMovieDb didn't have any information for ID {model.Id}" ErrorMessage = $"TheMovieDb didn't have any information for ID {model.Id}"
}; };
}
var fullMovieName = var fullMovieName =
$"{movieInfo.Title}{(!string.IsNullOrEmpty(movieInfo.ReleaseDate) ? $" ({DateTime.Parse(movieInfo.ReleaseDate).Year})" : string.Empty)}"; $"{movieInfo.Title}{(!string.IsNullOrEmpty(movieInfo.ReleaseDate) ? $" ({DateTime.Parse(movieInfo.ReleaseDate).Year})" : string.Empty)}";
var existingRequest = await MovieRequestService.CheckRequestAsync(model.Id); var existingRequest = await MovieRequestService.CheckRequestAsync(model.Id);
if (existingRequest != null) if (existingRequest != null)
{
return new RequestEngineResult return new RequestEngineResult
{ {
RequestAdded = false, RequestAdded = false,
Message = $"{fullMovieName} has already been requested" Message = $"{fullMovieName} has already been requested"
}; };
}
// TODO // TODO
//try //try
@ -99,12 +104,13 @@ namespace Ombi.Core.Engine
Issues = IssueState.None Issues = IssueState.None
}; };
var ruleResults = RunRequestRules(requestModel).ToList(); var ruleResults = await RunRequestRules(requestModel);
if (ruleResults.Any(x => !x.Success)) var results = ruleResults as RuleResult[] ?? ruleResults.ToArray();
if (results.Any(x => !x.Success))
{ {
return new RequestEngineResult 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); NotificationHelper.NewRequest(model);
} }
//var limit = await RequestLimitRepo.GetAllAsync(); //var limit = await RequestLimitRepo.GetAllAsync();
//var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type); //var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type);
//if (usersLimit == null) //if (usersLimit == null)

View file

@ -3,7 +3,6 @@ using Microsoft.Extensions.Logging;
using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TheMovieDb.Models;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Requests.Movie;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rules; using Ombi.Core.Rules;
using Ombi.Core.Settings; using Ombi.Core.Settings;
@ -49,7 +48,6 @@ namespace Ombi.Core.Engine
return new List<SearchMovieViewModel>(); return new List<SearchMovieViewModel>();
var retVal = new List<SearchMovieViewModel>(); var retVal = new List<SearchMovieViewModel>();
var dbMovies = await GetMovieRequests();
var plexSettings = await PlexSettings.GetSettingsAsync(); var plexSettings = await PlexSettings.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync(); var embySettings = await EmbySettings.GetSettingsAsync();
@ -59,22 +57,20 @@ namespace Ombi.Core.Engine
var movieInfo = await MovieApi.GetMovieInformationWithVideo(m.Id); var movieInfo = await MovieApi.GetMovieInformationWithVideo(m.Id);
var viewMovie = Mapper.Map<SearchMovieViewModel>(movieInfo); var viewMovie = Mapper.Map<SearchMovieViewModel>(movieInfo);
retVal.Add(await ProcessSingleMovie(viewMovie, dbMovies, plexSettings, embySettings)); retVal.Add(await ProcessSingleMovie(viewMovie, plexSettings, embySettings));
} }
return retVal; return retVal;
} }
public async Task<SearchMovieViewModel> LookupImdbInformation(int theMovieDbId) public async Task<SearchMovieViewModel> LookupImdbInformation(int theMovieDbId)
{ {
var dbMovies = await GetMovieRequests();
var plexSettings = await PlexSettings.GetSettingsAsync(); var plexSettings = await PlexSettings.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync(); var embySettings = await EmbySettings.GetSettingsAsync();
var movieInfo = await MovieApi.GetMovieInformationWithVideo(theMovieDbId); var movieInfo = await MovieApi.GetMovieInformationWithVideo(theMovieDbId);
var viewMovie = Mapper.Map<SearchMovieViewModel>(movieInfo); var viewMovie = Mapper.Map<SearchMovieViewModel>(movieInfo);
return await ProcessSingleMovie(viewMovie, dbMovies, plexSettings, embySettings, true); return await ProcessSingleMovie(viewMovie, plexSettings, embySettings, true);
} }
public async Task<IEnumerable<SearchMovieViewModel>> Search(string search) public async Task<IEnumerable<SearchMovieViewModel>> Search(string search)
@ -148,25 +144,22 @@ namespace Ombi.Core.Engine
{ {
var viewMovies = new List<SearchMovieViewModel>(); var viewMovies = new List<SearchMovieViewModel>();
Dictionary<int, MovieRequestModel> dbMovies;
Settings.Models.External.PlexSettings plexSettings; Settings.Models.External.PlexSettings plexSettings;
Settings.Models.External.EmbySettings embySettings; Settings.Models.External.EmbySettings embySettings;
using (MiniProfiler.Current.Step("Gettings Movies and Settings")) using (MiniProfiler.Current.Step("Gettings Movies and Settings"))
{ {
dbMovies = await GetMovieRequests();
plexSettings = await PlexSettings.GetSettingsAsync(); plexSettings = await PlexSettings.GetSettingsAsync();
embySettings = await EmbySettings.GetSettingsAsync(); embySettings = await EmbySettings.GetSettingsAsync();
} }
foreach (var movie in movies) foreach (var movie in movies)
{ {
viewMovies.Add(await ProcessSingleMovie(movie, dbMovies, plexSettings, embySettings)); viewMovies.Add(await ProcessSingleMovie(movie, plexSettings, embySettings));
} }
return viewMovies; return viewMovies;
} }
private async Task<SearchMovieViewModel> ProcessSingleMovie(SearchMovieViewModel viewMovie, private async Task<SearchMovieViewModel> ProcessSingleMovie(SearchMovieViewModel viewMovie,
Dictionary<int, MovieRequestModel> existingRequests, PlexSettings plexSettings, EmbySettings embySettings, bool lookupExtraInfo = false) PlexSettings plexSettings, EmbySettings embySettings, bool lookupExtraInfo = false)
{ {
if (plexSettings.Enable) if (plexSettings.Enable)
@ -175,25 +168,7 @@ namespace Ombi.Core.Engine
{ {
var showInfo = await MovieApi.GetMovieInformation(viewMovie.Id); var showInfo = await MovieApi.GetMovieInformation(viewMovie.Id);
viewMovie.Id = showInfo.Id; // TheMovieDbId 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) if (embySettings.Enable)
{ {
@ -208,26 +183,16 @@ namespace Ombi.Core.Engine
// } // }
} }
if (existingRequests.ContainsKey(viewMovie.Id)) // Do we already have a request for this? await RunSearchRules(viewMovie);
{
var requestedMovie = existingRequests[viewMovie.Id];
viewMovie.Requested = true;
viewMovie.Approved = requestedMovie.Approved;
viewMovie.Available = requestedMovie.Available;
}
RunSearchRules(viewMovie);
return viewMovie; return viewMovie;
} }
private async Task<SearchMovieViewModel> ProcessSingleMovie(MovieSearchResult movie, private async Task<SearchMovieViewModel> ProcessSingleMovie(MovieSearchResult movie, PlexSettings plexSettings, EmbySettings embySettings)
Dictionary<int, MovieRequestModel> existingRequests, PlexSettings plexSettings, EmbySettings embySettings)
{ {
var viewMovie = Mapper.Map<SearchMovieViewModel>(movie); var viewMovie = Mapper.Map<SearchMovieViewModel>(movie);
return await ProcessSingleMovie(viewMovie, existingRequests, plexSettings, embySettings); return await ProcessSingleMovie(viewMovie, plexSettings, embySettings);
} }
} }
} }

View file

@ -15,6 +15,7 @@ using System.Linq;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Rule;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
@ -141,12 +142,13 @@ namespace Ombi.Core.Engine
} }
} }
var ruleResults = RunRequestRules(model).ToList(); var ruleResults = await RunRequestRules(model);
if (ruleResults.Any(x => !x.Success)) var results = ruleResults as RuleResult[] ?? ruleResults.ToArray();
if (results.Any(x => !x.Success))
{ {
return new RequestEngineResult return new RequestEngineResult
{ {
ErrorMessage = ruleResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message ErrorMessage = results.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message
}; };
} }

View file

@ -1,9 +1,10 @@
using Ombi.Core.Models.Requests; using System.Threading.Tasks;
using Ombi.Core.Models.Requests;
namespace Ombi.Core.Rule.Interfaces namespace Ombi.Core.Rule.Interfaces
{ {
public interface IRequestRules<T> where T : new() public interface IRequestRules<T> where T : new()
{ {
RuleResult Execute(T obj); Task<RuleResult> Execute(T obj);
} }
} }

View file

@ -1,13 +1,14 @@
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Rule; using Ombi.Core.Rule;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
namespace Ombi.Core.Rules namespace Ombi.Core.Rules
{ {
public interface IRuleEvaluator public interface IRuleEvaluator
{ {
IEnumerable<RuleResult> StartRequestRules(BaseRequestModel obj); Task<IEnumerable<RuleResult>> StartRequestRules(BaseRequestModel obj);
IEnumerable<RuleResult> StartSearchRules(SearchViewModel obj); Task<IEnumerable<RuleResult>> StartSearchRules(SearchViewModel obj);
} }
} }

View file

@ -4,6 +4,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
@ -62,24 +63,24 @@ namespace Ombi.Core.Rule
private List<IRequestRules<BaseRequestModel>> RequestRules { get; } private List<IRequestRules<BaseRequestModel>> RequestRules { get; }
private List<IRequestRules<SearchViewModel>> SearchRules { get; } private List<IRequestRules<SearchViewModel>> SearchRules { get; }
public IEnumerable<RuleResult> StartRequestRules(BaseRequestModel obj) public async Task<IEnumerable<RuleResult>> StartRequestRules(BaseRequestModel obj)
{ {
var results = new List<RuleResult>(); var results = new List<RuleResult>();
foreach (var rule in RequestRules) foreach (var rule in RequestRules)
{ {
var result = rule.Execute(obj); var result = await rule.Execute(obj);
results.Add(result); results.Add(result);
} }
return results; return results;
} }
public IEnumerable<RuleResult> StartSearchRules(SearchViewModel obj) public async Task<IEnumerable<RuleResult>> StartSearchRules(SearchViewModel obj)
{ {
var results = new List<RuleResult>(); var results = new List<RuleResult>();
foreach (var rule in SearchRules) foreach (var rule in SearchRules)
{ {
var result = rule.Execute(obj); var result = await rule.Execute(obj);
results.Add(result); results.Add(result);
} }

View file

@ -1,4 +1,5 @@
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks;
using Ombi.Core.Claims; using Ombi.Core.Claims;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
@ -15,19 +16,19 @@ namespace Ombi.Core.Rule.Rules.Request
private IPrincipal User { get; } private IPrincipal User { get; }
public RuleResult Execute(BaseRequestModel obj) public Task<RuleResult> Execute(BaseRequestModel obj)
{ {
if (User.IsInRole(OmbiClaims.Admin)) if (User.IsInRole(OmbiClaims.Admin))
{ {
obj.Approved = true; obj.Approved = true;
return Success(); return Task.FromResult(Success());
} }
if (obj.Type == RequestType.Movie && User.IsInRole(OmbiClaims.AutoApproveMovie)) if (obj.Type == RequestType.Movie && User.IsInRole(OmbiClaims.AutoApproveMovie))
obj.Approved = true; obj.Approved = true;
if (obj.Type == RequestType.TvShow && User.IsInRole(OmbiClaims.AutoApproveTv)) if (obj.Type == RequestType.TvShow && User.IsInRole(OmbiClaims.AutoApproveTv))
obj.Approved = true; 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
} }
} }
} }

View file

@ -3,6 +3,7 @@ using Ombi.Core.Models.Requests;
using Ombi.Core.Rules; using Ombi.Core.Rules;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
namespace Ombi.Core.Rule.Rules namespace Ombi.Core.Rule.Rules
@ -16,21 +17,21 @@ namespace Ombi.Core.Rule.Rules
private IPrincipal User { get; } private IPrincipal User { get; }
public RuleResult Execute(BaseRequestModel obj) public Task<RuleResult> Execute(BaseRequestModel obj)
{ {
if (User.IsInRole(OmbiClaims.Admin)) if (User.IsInRole(OmbiClaims.Admin))
return Success(); return Task.FromResult(Success());
if (obj.Type == RequestType.Movie) if (obj.Type == RequestType.Movie)
{ {
if (User.IsInRole(OmbiClaims.RequestMovie)) if (User.IsInRole(OmbiClaims.RequestMovie))
return Success(); return Task.FromResult(Success());
return Fail("You do not have permissions to Request a Movie"); return Task.FromResult(Fail("You do not have permissions to Request a Movie"));
} }
if (User.IsInRole(OmbiClaims.RequestTv)) if (User.IsInRole(OmbiClaims.RequestTv))
return Success(); return Task.FromResult(Success());
return Fail("You do not have permissions to Request a Movie"); return Task.FromResult(Fail("You do not have permissions to Request a Movie"));
} }
} }
} }

View file

@ -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<SearchViewModel>
{
public ExistingRequestRule(IRequestService<MovieRequestModel> movie, IRequestService<TvRequestModel> tv)
{
Movie = movie;
Tv = tv;
}
private IRequestService<MovieRequestModel> Movie { get; }
private IRequestService<TvRequestModel> Tv { get; }
public async Task<RuleResult> 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();
}
}
}

View file

@ -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<SearchViewModel>
{
public PlexAvailabilityRule(IPlexContentRepository repo)
{
PlexContentRepository = repo;
}
private IPlexContentRepository PlexContentRepository { get; }
public async Task<RuleResult> Execute(SearchViewModel obj)
{
var item = await PlexContentRepository.Get(obj.Id.ToString());
if (item != null)
{
obj.Available = true;
obj.PlexUrl = item.Url;
}
return Success();
}
}
}

View file

@ -1,5 +1,5 @@
using System.Linq; using System.Linq;
using Ombi.Core.Models.Requests; using System.Threading.Tasks;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Context; using Ombi.Store.Context;
@ -15,17 +15,16 @@ namespace Ombi.Core.Rule.Rules.Search
private readonly IOmbiContext _ctx; private readonly IOmbiContext _ctx;
public RuleResult Execute(SearchViewModel obj) public Task<RuleResult> Execute(SearchViewModel obj)
{ {
// Check if it's in Radarr // Check if it's in Radarr
var result = _ctx.RadarrCache.FirstOrDefault(x => x.TheMovieDbId == obj.Id); var result = _ctx.RadarrCache.FirstOrDefault(x => x.TheMovieDbId == obj.Id);
if (result != null) if (result != null)
{ {
obj.Approved = true; // It's in radarr so it's approved... Maybe have a new property called "Processing" or something? 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());
} }
} }
} }

View file

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Notifications.Interfaces;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
namespace Ombi.Notifications namespace Ombi.Notifications

View file

@ -58,7 +58,7 @@ export class DiscordComponent implements OnInit {
return return
} }
this.testerService.discordTest(form.value).subscribex(x => { this.testerService.discordTest(form.value).subscribe(x => {
if (x) { if (x) {
this.notificationService.success("Successful", "Successfully sent a Discord message, please check the discord channel"); this.notificationService.success("Successful", "Successfully sent a Discord message, please check the discord channel");
} else { } else {

View file

@ -9,7 +9,7 @@ import { SonarrService } from '../../services/applications/sonarr.service';
import { NotificationService } from "../../services/notification.service"; import { NotificationService } from "../../services/notification.service";
@Component({ @Component({
templateUrl: './sonarr.component.html', templateUrl: './sonarr.component.html',
}) })
export class SonarrComponent implements OnInit, OnDestroy { export class SonarrComponent implements OnInit, OnDestroy {
@ -43,11 +43,11 @@ export class SonarrComponent implements OnInit, OnDestroy {
this.sonarrService.getQualityProfiles(this.settings) this.sonarrService.getQualityProfiles(this.settings)
.takeUntil(this.subscriptions) .takeUntil(this.subscriptions)
.subscribe(x => { .subscribe(x => {
this.qualities = x; this.qualities = x;
this.profilesRunning = false; this.profilesRunning = false;
this.notificationService.success("Quality Profiles", "Successfully retrevied the Quality Profiles"); this.notificationService.success("Quality Profiles", "Successfully retrevied the Quality Profiles");
}); });
} }
getRootFolders() { getRootFolders() {
@ -55,11 +55,11 @@ export class SonarrComponent implements OnInit, OnDestroy {
this.sonarrService.getRootFolders(this.settings) this.sonarrService.getRootFolders(this.settings)
.takeUntil(this.subscriptions) .takeUntil(this.subscriptions)
.subscribe(x => { .subscribe(x => {
this.rootFolders = x; this.rootFolders = x;
this.rootFoldersRunning = false; this.rootFoldersRunning = false;
this.notificationService.success("Settings Saved", "Successfully retrevied the Root Folders"); this.notificationService.success("Settings Saved", "Successfully retrevied the Root Folders");
}); });
} }
test() { test() {
@ -67,15 +67,24 @@ export class SonarrComponent implements OnInit, OnDestroy {
} }
save() { 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) this.settingsService.saveSonarr(this.settings)
.takeUntil(this.subscriptions) .takeUntil(this.subscriptions)
.subscribe(x => { .subscribe(x => {
if (x) { if (x) {
this.notificationService.success("Settings Saved", "Successfully saved Sonarr settings"); this.notificationService.success("Settings Saved", "Successfully saved Sonarr settings");
} else { } else {
this.notificationService.success("Settings Saved", "There was an error when saving the Sonarr settings"); this.notificationService.error("Settings Saved", "There was an error when saving the Sonarr settings");
} }
}); });
} }
ngOnDestroy(): void { ngOnDestroy(): void {

View file

@ -1,6 +1,6 @@
 
<h4 class="media-heading landing-title">Emby Authentication</h4> <h4 class="media-heading landing-title">Emby Authentication</h4>
<div class="form-group"> <div class="form-group" *ngIf="embySettings">
<label for="Ip" class="control-label">Emby Hostname or IP Address</label> <label for="Ip" class="control-label">Emby Hostname or IP Address</label>
<div> <div>
<input type="text" [(ngModel)]="embySettings.ip" class="form-control form-control-custom " id="Ip" name="Ip" placeholder="192.168.1.1"> <input type="text" [(ngModel)]="embySettings.ip" class="form-control form-control-custom " id="Ip" name="Ip" placeholder="192.168.1.1">

View file

@ -15,18 +15,6 @@ export class EmbyComponent {
constructor(private embyService: EmbyService, constructor(private embyService: EmbyService,
private router: Router, private router: Router,
private notificationService: NotificationService) { private notificationService: NotificationService) {
this.embySettings = {
administratorId: "",
apiKey: "",
enable: true,
enableEpisodeSearching: true,
id: 0,
ip: "",
port: 8096,
ssl: false,
subDir: "",
}
} }
private embySettings: IEmbySettings; private embySettings: IEmbySettings;