diff --git a/src/Ombi.Core/Claims/OmbiClaims.cs b/src/Ombi.Core/Claims/OmbiClaims.cs index 7491c3bdd..0c0c4bb10 100644 --- a/src/Ombi.Core/Claims/OmbiClaims.cs +++ b/src/Ombi.Core/Claims/OmbiClaims.cs @@ -1,30 +1,4 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2017 Jamie Rees -// File: OmbiClaims.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -namespace Ombi.Core.Claims +namespace Ombi.Core.Claims { public static class OmbiClaims { diff --git a/src/Ombi.Core/Engine/BaseMediaEngine.cs b/src/Ombi.Core/Engine/BaseMediaEngine.cs index 4100ee09d..c443df1ce 100644 --- a/src/Ombi.Core/Engine/BaseMediaEngine.cs +++ b/src/Ombi.Core/Engine/BaseMediaEngine.cs @@ -1,20 +1,25 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Principal; -using System.Threading.Tasks; -using Ombi.Core.Claims; -using Ombi.Core.Engine.Interfaces; +using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Requests.Models; +using Ombi.Core.Rules; using Ombi.Helpers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; namespace Ombi.Core.Engine { public abstract class BaseMediaEngine : BaseEngine { - protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService) : base(identity) + private long _cacheTime; + private Dictionary _dbMovies; + private Dictionary _dbTv; + + protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService, + IRuleEvaluator rules) : base(identity, rules) { RequestService = requestService; } @@ -23,13 +28,10 @@ namespace Ombi.Core.Engine protected IRequestService MovieRequestService => RequestService.MovieRequestService; protected IRequestService TvRequestService => RequestService.TvRequestService; - private long _cacheTime = 0; - private Dictionary _dbMovies; - private Dictionary _dbTv; protected async Task> GetMovieRequests() { - long now = DateTime.Now.Ticks; - if (_dbMovies == null || (now - _cacheTime) > 10000) + var now = DateTime.Now.Ticks; + if (_dbMovies == null || now - _cacheTime > 10000) { var allResults = await MovieRequestService.GetAllAsync(); @@ -42,8 +44,8 @@ namespace Ombi.Core.Engine protected async Task> GetTvRequests() { - long now = DateTime.Now.Ticks; - if (_dbTv == null || (now - _cacheTime) > 10000) + var now = DateTime.Now.Ticks; + if (_dbTv == null || now - _cacheTime > 10000) { var allResults = await TvRequestService.GetAllAsync(); diff --git a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs index 2c3a26938..f77dd2153 100644 --- a/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/BaseEngine.cs @@ -1,18 +1,26 @@ -using System.Security.Principal; -using Ombi.Core.Claims; +using Ombi.Core.Claims; +using Ombi.Core.Models.Requests; +using Ombi.Core.Rule; +using Ombi.Core.Rules; using Ombi.Store.Entities; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; namespace Ombi.Core.Engine.Interfaces { public abstract class BaseEngine { - protected BaseEngine(IPrincipal user) + protected BaseEngine(IPrincipal user, IRuleEvaluator rules) { User = user; + Rules = rules; } - + protected IPrincipal User { get; } + protected IRuleEvaluator Rules { get; } + protected string Username => User.Identity.Name; protected bool HasRole(string roleName) @@ -25,10 +33,7 @@ namespace Ombi.Core.Engine.Interfaces var sendNotification = !ShouldAutoApprove(type); /*|| !prSettings.IgnoreNotifyForAutoApprovedRequests;*/ if (HasRole(OmbiClaims.Admin)) - { sendNotification = false; // Don't bother sending a notification if the user is an admin - - } return sendNotification; } @@ -43,13 +48,19 @@ namespace Ombi.Core.Engine.Interfaces { case RequestType.Movie: return HasRole(OmbiClaims.AutoApproveMovie); + case RequestType.TvShow: return HasRole(OmbiClaims.AutoApproveTv); + default: return false; } } - + public IEnumerable RunRules(BaseRequestModel model) + { + var ruleResults = Rules.StartRequestRules(model).ToList(); + return ruleResults; + } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs index 68d4bcd45..75b448372 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieEngine.cs @@ -1,16 +1,21 @@ -using System.Collections.Generic; +using Ombi.Core.Models.Search; +using System.Collections.Generic; using System.Threading.Tasks; -using Ombi.Core.Models.Search; namespace Ombi.Core { public interface IMovieEngine { Task> NowPlayingMovies(); + Task> PopularMovies(); + Task> Search(string search); + Task> TopRatedMovies(); + Task> UpcomingMovies(); + Task> LookupImdbInformation(IEnumerable movies); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs index f6548a73f..a9f3a5a52 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs @@ -1,20 +1,26 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Models.Search; using Ombi.Store.Entities; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Ombi.Core.Engine { public interface IMovieRequestEngine { Task RequestMovie(SearchMovieViewModel model); + bool ShouldAutoApprove(RequestType requestType); + Task> GetMovieRequests(int count, int position); + Task> SearchMovieRequest(string search); + Task RemoveMovieRequest(int requestId); + Task UpdateMovieRequest(MovieRequestModel request); + RequestCountModel RequestCount(); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs index c0c6dcb6c..1adcf556c 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs @@ -1,17 +1,22 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Ombi.Core.Engine { public interface ITvRequestEngine { Task> GetTvRequests(int count, int position); + Task RemoveTvRequest(int requestId); + Task RequestTvShow(SearchTvShowViewModel tv); + Task> SearchTvRequest(string search); + Task UpdateTvRequest(TvRequestModel request); + RequestCountModel RequestCount(); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs index 561088764..50268d4dd 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; +using Ombi.Core.Models.Search; +using System.Collections.Generic; using System.Threading.Tasks; -using Ombi.Core.Models.Search; namespace Ombi.Core.Engine.Interfaces { @@ -9,10 +9,13 @@ namespace Ombi.Core.Engine.Interfaces Task> Search(string searchTerm); Task GetShowInformation(int tvdbId); + Task> Popular(); + Task> Anticipated(); + Task> MostWatches(); - Task> Trending(); + Task> Trending(); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs index 852e15129..a09885174 100644 --- a/src/Ombi.Core/Engine/MovieRequestEngine.cs +++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs @@ -1,62 +1,58 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Security.Principal; -using System.Threading.Tasks; -using Hangfire; +using Hangfire; using Ombi.Api.TheMovieDb; -using Ombi.Api.TvMaze; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Models.Search; -using Ombi.Core.Requests.Models; -using Ombi.Store.Entities; +using Ombi.Core.Rules; using Ombi.Helpers; using Ombi.Notifications; using Ombi.Notifications.Models; +using Ombi.Store.Entities; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; namespace Ombi.Core.Engine { public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine { - public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user, INotificationService notificationService) : base(user, requestService) + public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user, + INotificationService notificationService, IRuleEvaluator r) : base(user, requestService, r) { MovieApi = movieApi; NotificationService = notificationService; } + private IMovieDbApi MovieApi { get; } private INotificationService NotificationService { get; } + public async Task RequestMovie(SearchMovieViewModel model) { 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 //{ - // var content = PlexContentRepository.GetAll(); // var movies = PlexChecker.GetPlexMovies(content); // if (PlexChecker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString())) @@ -88,20 +84,27 @@ namespace Ombi.Core.Engine ImdbId = movieInfo.ImdbId, PosterPath = movieInfo.PosterPath, Title = movieInfo.Title, - ReleaseDate = !string.IsNullOrEmpty(movieInfo.ReleaseDate) ? DateTime.Parse(movieInfo.ReleaseDate) : DateTime.MinValue, + ReleaseDate = !string.IsNullOrEmpty(movieInfo.ReleaseDate) + ? DateTime.Parse(movieInfo.ReleaseDate) + : DateTime.MinValue, Status = movieInfo.Status, RequestedDate = DateTime.UtcNow, Approved = false, - RequestedUsers = new List { Username }, - Issues = IssueState.None, + RequestedUsers = new List {Username}, + Issues = IssueState.None }; try { - if (ShouldAutoApprove(RequestType.Movie)) - { - model.Approved = true; + var ruleResults = RunRules(requestModel).ToList(); + if (ruleResults.Any(x => !x.Success)) + return new RequestEngineResult + { + ErrorMessage = ruleResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message + }; + if (requestModel.Approved) // The rules have auto approved this + { // var result = await MovieSender.Send(model); // if (result.Result) // { @@ -120,7 +123,6 @@ namespace Ombi.Core.Engine // } // if (!result.MovieSendingEnabled) // { - // return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}"); // } @@ -131,10 +133,8 @@ namespace Ombi.Core.Engine // }); } - return await AddMovieRequest(requestModel, /*settings,*/ - $"{fullMovieName} has been successfully added!"); - + $"{fullMovieName} has been successfully added!"); } catch (Exception e) { @@ -160,8 +160,48 @@ namespace Ombi.Core.Engine return null; } - - private IEnumerable GetListDifferences(IEnumerable existing, IEnumerable request) + public async Task> GetMovieRequests(int count, int position) + { + var allRequests = await MovieRequestService.GetAllAsync(count, position); + return allRequests; + } + + public async Task> SearchMovieRequest(string search) + { + var allRequests = await MovieRequestService.GetAllAsync(); + var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)); + return results; + } + + public async Task UpdateMovieRequest(MovieRequestModel request) + { + var allRequests = await MovieRequestService.GetAllAsync(); + var results = allRequests.FirstOrDefault(x => x.Id == request.Id); + + results.Approved = request.Approved; + results.Available = request.Available; + results.Denied = request.Denied; + results.DeniedReason = request.DeniedReason; + results.AdminNote = request.AdminNote; + results.ImdbId = request.ImdbId; + results.IssueId = request.IssueId; + results.Issues = request.Issues; + results.OtherMessage = request.OtherMessage; + results.Overview = request.Overview; + results.PosterPath = request.PosterPath; + results.RequestedUsers = request.RequestedUsers?.ToList() ?? new List(); + + var model = MovieRequestService.UpdateRequest(results); + return model; + } + + public async Task RemoveMovieRequest(int requestId) + { + await MovieRequestService.DeleteRequestAsync(requestId); + } + + private IEnumerable GetListDifferences(IEnumerable existing, + IEnumerable request) { var newRequest = request .Select(r => @@ -169,12 +209,12 @@ namespace Ombi.Core.Engine { SeasonNumber = r.SeasonNumber, EpisodeNumber = r.EpisodeNumber - }).ToList(); + }) + .ToList(); return newRequest.Except(existing); } - private async Task AddMovieRequest(MovieRequestModel model, string message) { await MovieRequestService.AddRequestAsync(model); @@ -188,7 +228,9 @@ namespace Ombi.Core.Engine DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest, RequestType = model.Type, - ImgSrc = model.Type == RequestType.Movie ? $"https://image.tmdb.org/t/p/w300/{model.PosterPath}" : model.PosterPath + ImgSrc = model.Type == RequestType.Movie + ? $"https://image.tmdb.org/t/p/w300/{model.PosterPath}" + : model.PosterPath }; BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel).Wait()); @@ -212,46 +254,7 @@ namespace Ombi.Core.Engine // await RequestLimitRepo.UpdateAsync(usersLimit); //} - return new RequestEngineResult { RequestAdded = true }; - } - - public async Task> GetMovieRequests(int count, int position) - { - var allRequests = await MovieRequestService.GetAllAsync(count, position); - return allRequests; - } - public async Task> SearchMovieRequest(string search) - { - var allRequests = await MovieRequestService.GetAllAsync(); - var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)); - return results; - } - public async Task UpdateMovieRequest(MovieRequestModel request) - { - var allRequests = await MovieRequestService.GetAllAsync(); - var results = allRequests.FirstOrDefault(x => x.Id == request.Id); - - results.Approved = request.Approved; - results.Available = request.Available; - results.Denied = request.Denied; - results.DeniedReason = request.DeniedReason; - results.AdminNote = request.AdminNote; - results.ImdbId = request.ImdbId; - results.IssueId = request.IssueId; - results.Issues = request.Issues; - results.OtherMessage = request.OtherMessage; - results.Overview = request.Overview; - results.PosterPath = request.PosterPath; - results.RequestedUsers = request.RequestedUsers?.ToList() ?? new List(); - - - var model = MovieRequestService.UpdateRequest(results); - return model; - } - - public async Task RemoveMovieRequest(int requestId) - { - await MovieRequestService.DeleteRequestAsync(requestId); + return new RequestEngineResult {RequestAdded = true}; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index 5368a58ee..753f9435f 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -1,30 +1,28 @@ -using System.Collections.Generic; -using System.Linq; -using System.Security.Principal; -using System.Threading.Tasks; -using AutoMapper; +using AutoMapper; using Microsoft.Extensions.Logging; using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb.Models; -using Ombi.Core.IdentityResolver; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Models.Search; -using Ombi.Core.Requests.Models; +using Ombi.Core.Rules; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; -using Ombi.Store.Entities; using Ombi.Store.Repository; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; namespace Ombi.Core.Engine { public class MovieSearchEngine : BaseMediaEngine, IMovieEngine { - - public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ISettingsService plexSettings, + public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, + ISettingsService plexSettings, ISettingsService embySettings, IPlexContentRepository repo, - ILogger logger) - : base(identity, service) + ILogger logger, IRuleEvaluator r) + : base(identity, service, r) { MovieApi = movApi; Mapper = mapper; @@ -41,18 +39,16 @@ namespace Ombi.Core.Engine private ILogger Logger { get; } private IPlexContentRepository PlexContentRepo { get; } - public async Task> LookupImdbInformation(IEnumerable movies) + public async Task> LookupImdbInformation( + IEnumerable movies) { var searchMovieViewModels = movies as IList ?? movies.ToList(); if (searchMovieViewModels == null || !searchMovieViewModels.Any()) - { return new List(); - } var retVal = new List(); - Dictionary dbMovies = await GetMovieRequests(); - + var dbMovies = await GetMovieRequests(); var plexSettings = await PlexSettings.GetSettingsAsync(); var embySettings = await EmbySettings.GetSettingsAsync(); @@ -77,6 +73,7 @@ namespace Ombi.Core.Engine } return null; } + public async Task> PopularMovies() { var result = await MovieApi.PopularMovies(); @@ -109,32 +106,28 @@ namespace Ombi.Core.Engine } return null; } + public async Task> NowPlayingMovies() { var result = await MovieApi.NowPlaying(); if (result != null) { - Logger.LogDebug("Search Result: {result}", result); return await TransformMovieResultsToResponse(result); } return null; } - - private async Task> TransformMovieResultsToResponse(IEnumerable movies) + private async Task> TransformMovieResultsToResponse( + IEnumerable movies) { var viewMovies = new List(); - Dictionary dbMovies = await GetMovieRequests(); + var dbMovies = await GetMovieRequests(); var plexSettings = await PlexSettings.GetSettingsAsync(); var embySettings = await EmbySettings.GetSettingsAsync(); foreach (var movie in movies) - { - viewMovies.Add(await ProcessSingleMovie(movie, dbMovies, plexSettings, embySettings)); - - } return viewMovies; } @@ -144,9 +137,8 @@ namespace Ombi.Core.Engine var showInfo = await MovieApi.GetMovieInformation(viewMovie.Id); if (plexSettings.Enable) { - - var item = await PlexContentRepo.Get(showInfo.ImdbId.ToString()); - if(item != null) + var item = await PlexContentRepo.Get(showInfo.ImdbId); + if (item != null) { viewMovie.Available = true; viewMovie.PlexUrl = item.Url; @@ -186,14 +178,14 @@ namespace Ombi.Core.Engine viewMovie.Available = requestedMovie.Available; } - return viewMovie; } - private async Task ProcessSingleMovie(MovieSearchResult movie, Dictionary existingRequests, PlexSettings plexSettings, EmbySettings embySettings) + private async Task ProcessSingleMovie(MovieSearchResult movie, + Dictionary existingRequests, PlexSettings plexSettings, EmbySettings embySettings) { var viewMovie = Mapper.Map(movie); return await ProcessSingleMovie(viewMovie, existingRequests, 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 639e9cdd0..3d19f0933 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -1,36 +1,36 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Security.Principal; -using System.Threading.Tasks; -using AutoMapper; +using AutoMapper; using Hangfire; using Ombi.Api.TvMaze; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; -using Ombi.Store.Entities; +using Ombi.Core.Rules; using Ombi.Helpers; using Ombi.Notifications; using Ombi.Notifications.Models; -using Ombi.Core.Rules; +using Ombi.Store.Entities; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; namespace Ombi.Core.Engine { public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine { - public TvRequestEngine(ITvMazeApi tvApi, IRequestServiceMain requestService, IPrincipal user, INotificationService notificationService, IMapper map, - IRuleEvaluator rule) : base(user, requestService) + public TvRequestEngine(ITvMazeApi tvApi, IRequestServiceMain requestService, IPrincipal user, + INotificationService notificationService, IMapper map, + IRuleEvaluator rule) : base(user, requestService, rule) { TvApi = tvApi; NotificationService = notificationService; Mapper = map; - Rules = rule; } + private INotificationService NotificationService { get; } private ITvMazeApi TvApi { get; } private IMapper Mapper { get; } - private IRuleEvaluator Rules { get; } public async Task RequestTvShow(SearchTvShowViewModel tv) { @@ -51,11 +51,11 @@ namespace Ombi.Core.Engine Status = showInfo.status, RequestedDate = DateTime.UtcNow, Approved = false, - RequestedUsers = new List { Username }, + RequestedUsers = new List {Username}, Issues = IssueState.None, ProviderId = tv.Id, RequestAll = tv.RequestAll, - SeasonRequests = tv.SeasonRequests, + SeasonRequests = tv.SeasonRequests }; var model = new TvRequestModel @@ -70,8 +70,7 @@ namespace Ombi.Core.Engine Approved = false, ImdbId = showInfo.externals?.imdb ?? string.Empty, TvDbId = tv.Id.ToString(), - ProviderId = tv.Id, - + ProviderId = tv.Id }; model.ChildRequests.Add(childRequest); @@ -88,7 +87,7 @@ namespace Ombi.Core.Engine Url = e.url, Title = e.name, AirDate = DateTime.Parse(e.airstamp), - EpisodeNumber = e.number, + EpisodeNumber = e.number }); } } @@ -97,46 +96,29 @@ namespace Ombi.Core.Engine { var latest = showInfo.Season.OrderBy(x => x.SeasonNumber).FirstOrDefault(); foreach (var modelSeasonRequest in childRequest.SeasonRequests) - { if (modelSeasonRequest.SeasonNumber == latest.SeasonNumber) - { foreach (var episodesRequested in modelSeasonRequest.Episodes) - { episodesRequested.Requested = true; - } - } - } } if (tv.FirstSeason) { var first = showInfo.Season.OrderByDescending(x => x.SeasonNumber).FirstOrDefault(); foreach (var modelSeasonRequest in childRequest.SeasonRequests) - { if (modelSeasonRequest.SeasonNumber == first.SeasonNumber) - { foreach (var episodesRequested in modelSeasonRequest.Episodes) - { episodesRequested.Requested = true; - } - } - } } - - var ruleResults = Rules.StartRequestRules(model); + var ruleResults = RunRules(model).ToList(); if (ruleResults.Any(x => !x.Success)) - { - return new RequestEngineResult() + return new RequestEngineResult { - ErrorMessage = ruleResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message, + ErrorMessage = ruleResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message }; - } var existingRequest = await TvRequestService.CheckRequestAsync(model.Id); if (existingRequest != null) - { return await AddExistingRequest(model, existingRequest); - } // This is a new request return await AddRequest(model); @@ -147,12 +129,14 @@ namespace Ombi.Core.Engine var allRequests = await TvRequestService.GetAllAsync(count, position); return allRequests; } + public async Task> SearchTvRequest(string search) { var allRequests = await TvRequestService.GetAllAsync(); var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)); return results; } + public async Task UpdateTvRequest(TvRequestModel request) { var allRequests = await TvRequestService.GetAllAsync(); @@ -168,25 +152,20 @@ namespace Ombi.Core.Engine await TvRequestService.DeleteRequestAsync(requestId); } - private async Task AddExistingRequest(TvRequestModel newRequest, TvRequestModel existingRequest) + private async Task AddExistingRequest(TvRequestModel newRequest, + TvRequestModel existingRequest) { - var child = newRequest.ChildRequests.FirstOrDefault(); // There will only be 1 var episodeDiff = new List(); foreach (var existingChild in existingRequest.ChildRequests) { var difference = GetListDifferences(existingChild.SeasonRequests, child.SeasonRequests).ToList(); if (difference.Any()) - { episodeDiff = difference; - } } if (episodeDiff.Any()) - { - // This is where there are some episodes that have been requested, but this list contains the 'new' requests child.SeasonRequests = episodeDiff; - } existingRequest.ChildRequests.AddRange(newRequest.ChildRequests); TvRequestService.UpdateRequest(existingRequest); @@ -198,7 +177,8 @@ namespace Ombi.Core.Engine return await AfterRequest(newRequest); } - private IEnumerable GetListDifferences(IEnumerable existing, IEnumerable request) + private IEnumerable GetListDifferences(IEnumerable existing, + IEnumerable request) { var newRequest = request .Select(r => @@ -206,7 +186,8 @@ namespace Ombi.Core.Engine { SeasonNumber = r.SeasonNumber, Episodes = r.Episodes - }).ToList(); + }) + .ToList(); return newRequest.Except(existing); } @@ -253,9 +234,7 @@ namespace Ombi.Core.Engine // await RequestLimitRepo.UpdateAsync(usersLimit); //} - return new RequestEngineResult { RequestAdded = true }; + return new RequestEngineResult {RequestAdded = true}; } - - } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index bfcc1cee7..f8055963e 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -1,29 +1,28 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Principal; -using System.Threading.Tasks; -using AutoMapper; +using AutoMapper; + using Ombi.Api.Trakt; using Ombi.Api.TvMaze; -using Ombi.Api.TvMaze.Models; using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; -using Ombi.Core.Requests.Models; +using Ombi.Core.Rules; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; -using Ombi.Store.Entities; using Ombi.Store.Repository; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Threading.Tasks; + namespace Ombi.Core.Engine { public class TvSearchEngine : BaseMediaEngine, ITvSearchEngine { - public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService plexSettings, - ISettingsService embySettings, IPlexContentRepository repo, ITraktApi trakt) - : base(identity, service) + ISettingsService embySettings, IPlexContentRepository repo, ITraktApi trakt, IRuleEvaluator r) + : base(identity, service, r) { TvMazeApi = tvMaze; Mapper = mapper; @@ -40,7 +39,6 @@ namespace Ombi.Core.Engine private IPlexContentRepository PlexContentRepo { get; } private ITraktApi TraktApi { get; } - public async Task> Search(string searchTerm) { var searchResult = await TvMazeApi.Search(searchTerm); @@ -76,7 +74,6 @@ namespace Ombi.Core.Engine EpisodeNumber = e.number, }); mapped.SeasonRequests.Add(newSeason); - } else { @@ -86,7 +83,6 @@ namespace Ombi.Core.Engine Title = e.name, AirDate = DateTime.Parse(e.airstamp), EpisodeNumber = e.number, - }); } } @@ -108,11 +104,13 @@ namespace Ombi.Core.Engine var result = await TraktApi.GetAnticipatedShows(); return await ProcessResults(result); } + public async Task> MostWatches() { var result = await TraktApi.GetMostWatchesShows(); return await ProcessResults(result); } + public async Task> Trending() { var result = await TraktApi.GetTrendingShows(); @@ -158,7 +156,6 @@ namespace Ombi.Core.Engine if (item.Id > 0 && item.Available) { - // TODO need to check if the episodes are available var tvdbid = item.Id; if (existingRequests.ContainsKey(tvdbid)) @@ -173,7 +170,6 @@ namespace Ombi.Core.Engine { foreach (var existingRequestChildRequest in existingRequest.ChildRequests) { - // Find the existing request season var existingSeason = existingRequestChildRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == season.SeasonNumber); @@ -187,7 +183,6 @@ namespace Ombi.Core.Engine episodeSearching.Approved = ep.Approved; } } - } } //if (sonarrCached.Select(x => x.TvdbId).Contains(tvdbid) || sickRageCache.Contains(tvdbid)) @@ -200,4 +195,4 @@ namespace Ombi.Core.Engine return item; } } -} +} \ No newline at end of file diff --git a/src/Ombi.Core/IdentityResolver/IUserIdentityManager.cs b/src/Ombi.Core/IdentityResolver/IUserIdentityManager.cs index 96a327080..9867a0f92 100644 --- a/src/Ombi.Core/IdentityResolver/IUserIdentityManager.cs +++ b/src/Ombi.Core/IdentityResolver/IUserIdentityManager.cs @@ -1,16 +1,21 @@ -using System.Collections.Generic; +using Ombi.Core.Models; +using System.Collections.Generic; using System.Threading.Tasks; -using Ombi.Core.Models; namespace Ombi.Core.IdentityResolver { public interface IUserIdentityManager { Task CreateUser(UserDto user); + Task CredentialsValid(string username, string password); + Task GetUser(string username); + Task> GetUsers(); + Task DeleteUser(UserDto user); + Task UpdateUser(UserDto userDto); } } \ No newline at end of file diff --git a/src/Ombi.Core/IdentityResolver/UserIdentityManager.cs b/src/Ombi.Core/IdentityResolver/UserIdentityManager.cs index 52312e763..dc8765b93 100644 --- a/src/Ombi.Core/IdentityResolver/UserIdentityManager.cs +++ b/src/Ombi.Core/IdentityResolver/UserIdentityManager.cs @@ -1,40 +1,13 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2017 Jamie Rees -// File: UserIdentityManager.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - +using AutoMapper; +using Microsoft.AspNetCore.Cryptography.KeyDerivation; +using Ombi.Core.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository; using System; using System.Collections.Generic; using System.Security.Claims; using System.Security.Cryptography; using System.Threading.Tasks; -using AutoMapper; -using Microsoft.AspNetCore.Cryptography.KeyDerivation; -using Ombi.Core.Models; -using Ombi.Store.Entities; -using Ombi.Store.Repository; namespace Ombi.Core.IdentityResolver { @@ -46,7 +19,7 @@ namespace Ombi.Core.IdentityResolver Mapper = mapper; } - private IMapper Mapper { get; } + private IMapper Mapper { get; } private IUserRepository UserRepository { get; } public async Task CredentialsValid(string username, string password) @@ -96,7 +69,7 @@ namespace Ombi.Core.IdentityResolver private UserHash HashPassword(string password) { // generate a 128-bit salt using a secure PRNG - byte[] salt = new byte[128 / 8]; + var salt = new byte[128 / 8]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(salt); @@ -104,18 +77,17 @@ namespace Ombi.Core.IdentityResolver return HashPassword(password, salt); } - private UserHash HashPassword(string password, byte[] salt) { // derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations) var hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2( - password: password, - salt: salt, - prf: KeyDerivationPrf.HMACSHA1, - iterationCount: 10000, - numBytesRequested: 256 / 8)); + password, + salt, + KeyDerivationPrf.HMACSHA1, + 10000, + 256 / 8)); - return new UserHash { HashedPass = hashed, Salt = salt }; + return new UserHash {HashedPass = hashed, Salt = salt}; } private class UserHash diff --git a/src/Ombi.Core/Models/Requests/BaseRequestModel.cs b/src/Ombi.Core/Models/Requests/BaseRequestModel.cs index 99099856f..ac4732fa9 100644 --- a/src/Ombi.Core/Models/Requests/BaseRequestModel.cs +++ b/src/Ombi.Core/Models/Requests/BaseRequestModel.cs @@ -1,13 +1,13 @@ -using System; +using Newtonsoft.Json; +using Ombi.Store.Entities; +using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; -using Ombi.Store.Entities; namespace Ombi.Core.Models.Requests { public class BaseRequestModel : Entity - { + { public int ProviderId { get; set; } public string Overview { get; set; } public string Title { get; set; } @@ -29,7 +29,7 @@ namespace Ombi.Core.Models.Requests [JsonIgnore] public bool Released => DateTime.UtcNow > ReleaseDate; - + [JsonIgnore] public IEnumerable AllUsers { @@ -37,16 +37,14 @@ namespace Ombi.Core.Models.Requests { var u = new List(); if (RequestedUsers != null && RequestedUsers.Any()) - { u.AddRange(RequestedUsers); - } return u; } } [JsonIgnore] public bool CanApprove => !Approved && !Available; - + public bool UserHasRequested(string username) { return AllUsers.Any(x => x.Equals(username, StringComparison.OrdinalIgnoreCase)); diff --git a/src/Ombi.Core/Models/Requests/IRequestService.cs b/src/Ombi.Core/Models/Requests/IRequestService.cs index f0825ab40..d4dda7423 100644 --- a/src/Ombi.Core/Models/Requests/IRequestService.cs +++ b/src/Ombi.Core/Models/Requests/IRequestService.cs @@ -1,28 +1,42 @@ -using System.Collections.Generic; +using Ombi.Core.Models.Requests; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Ombi.Core.Models.Requests; -using Ombi.Store.Entities; namespace Ombi.Core.Requests.Models { public interface IRequestService where T : BaseRequestModel { int AddRequest(T model); + Task AddRequestAsync(T model); + void BatchDelete(IEnumerable model); + void BatchUpdate(IEnumerable model); + T CheckRequest(int providerId); + Task CheckRequestAsync(int providerId); + void DeleteRequest(T request); + Task DeleteRequestAsync(int request); + Task DeleteRequestAsync(T request); + T Get(int id); + IEnumerable GetAll(); + Task> GetAllAsync(); + Task> GetAllAsync(int count, int position); + Task GetAsync(int id); + T UpdateRequest(T model); + IQueryable GetAllQueryable(); } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/JsonRequestService.cs b/src/Ombi.Core/Models/Requests/JsonRequestService.cs index 930113f7e..99e825083 100644 --- a/src/Ombi.Core/Models/Requests/JsonRequestService.cs +++ b/src/Ombi.Core/Models/Requests/JsonRequestService.cs @@ -1,11 +1,10 @@ -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; -using Ombi.Core.Requests.Models; +using Ombi.Core.Requests.Models; using Ombi.Helpers; using Ombi.Store.Entities; using Ombi.Store.Repository; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; namespace Ombi.Core.Models.Requests { @@ -16,11 +15,18 @@ namespace Ombi.Core.Models.Requests Repo = repo; RequestType = typeof(T) == typeof(TvRequestModel) ? RequestType.TvShow : RequestType.Movie; } + private RequestType RequestType { get; } private IRequestRepository Repo { get; } + public int AddRequest(T model) { - var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId }; + var entity = new RequestBlobs + { + Type = model.Type, + Content = ByteConverterHelper.ReturnBytes(model), + ProviderId = model.ProviderId + }; var id = Repo.Insert(entity); return id.Id; @@ -28,7 +34,12 @@ namespace Ombi.Core.Models.Requests public async Task AddRequestAsync(T model) { - var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId }; + var entity = new RequestBlobs + { + Type = model.Type, + Content = ByteConverterHelper.ReturnBytes(model), + ProviderId = model.ProviderId + }; var id = await Repo.InsertAsync(entity).ConfigureAwait(false); return id.Id; @@ -40,9 +51,7 @@ namespace Ombi.Core.Models.Requests var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType); if (blob == null) - { return null; - } var model = ByteConverterHelper.ReturnObject(blob.Content); model.Id = blob.Id; return model; @@ -51,10 +60,9 @@ namespace Ombi.Core.Models.Requests public async Task CheckRequestAsync(int providerId) { var blobs = await Repo.GetAllAsync().ConfigureAwait(false); - var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType); if (blob == null) - { + var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType); + if (blob == null) return null; - } var model = ByteConverterHelper.ReturnObject(blob.Content); model.Id = blob.Id; return model; @@ -71,6 +79,7 @@ namespace Ombi.Core.Models.Requests var blob = await Repo.GetAsync(request.Id).ConfigureAwait(false); Repo.Delete(blob); } + public async Task DeleteRequestAsync(int request) { var blob = await Repo.GetAsync(request).ConfigureAwait(false); @@ -83,18 +92,17 @@ namespace Ombi.Core.Models.Requests b.Content = ByteConverterHelper.ReturnBytes(model); var blob = Repo.Update(b); return model; - } public T Get(int id) { var blob = Repo.Get(id); if (blob == null) - { return default(T); - } var model = ByteConverterHelper.ReturnObject(blob.Content); - model.Id = blob.Id; // They should always be the same, but for somereason a user didn't have it in the db https://github.com/tidusjar/Ombi/issues/862#issuecomment-269743847 + model.Id = + blob + .Id; // They should always be the same, but for somereason a user didn't have it in the db https://github.com/tidusjar/Ombi/issues/862#issuecomment-269743847 return model; } @@ -102,9 +110,7 @@ namespace Ombi.Core.Models.Requests { var blob = await Repo.GetAsync(id).ConfigureAwait(false); if (blob == null) - { return default(T); - } var model = ByteConverterHelper.ReturnObject(blob.Content); model.Id = blob.Id; return model; @@ -118,9 +124,7 @@ namespace Ombi.Core.Models.Requests foreach (var b in blobs) { if (b == null) - { continue; - } var model = ByteConverterHelper.ReturnObject(b.Content); model.Id = b.Id; retVal.Add(model); @@ -135,9 +139,7 @@ namespace Ombi.Core.Models.Requests foreach (var b in blobs) { if (b == null) - { continue; - } var model = ByteConverterHelper.ReturnObject(b.Content); model.Id = b.Id; retVal.Add(model); @@ -153,9 +155,7 @@ namespace Ombi.Core.Models.Requests foreach (var b in blobs.Where(x => x.Type == RequestType)) { if (b == null) - { continue; - } var model = ByteConverterHelper.ReturnObject(b.Content); model.Id = b.Id; retVal.Add(model); @@ -171,9 +171,7 @@ namespace Ombi.Core.Models.Requests foreach (var b in blobs.Where(x => x.Type == RequestType)) { if (b == null) - { continue; - } var model = ByteConverterHelper.ReturnObject(b.Content); model.Id = b.Id; retVal.Add(model); @@ -183,13 +181,29 @@ namespace Ombi.Core.Models.Requests public void BatchUpdate(IEnumerable model) { - var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ByteConverterHelper.ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList(); + var entities = model + .Select(m => new RequestBlobs + { + Type = m.Type, + Content = ByteConverterHelper.ReturnBytes(m), + ProviderId = m.ProviderId, + Id = m.Id + }) + .ToList(); Repo.UpdateAll(entities); } public void BatchDelete(IEnumerable model) { - var entities = model.Select(m => new RequestBlobs { Type = m.Type, Content = ByteConverterHelper.ReturnBytes(m), ProviderId = m.ProviderId, Id = m.Id }).ToList(); + var entities = model + .Select(m => new RequestBlobs + { + Type = m.Type, + Content = ByteConverterHelper.ReturnBytes(m), + ProviderId = m.ProviderId, + Id = m.Id + }) + .ToList(); Repo.DeleteAll(entities); } } diff --git a/src/Ombi.Core/Models/Requests/Movie/MovieRequestModel.cs b/src/Ombi.Core/Models/Requests/Movie/MovieRequestModel.cs index 40a2893fd..19165cda2 100644 --- a/src/Ombi.Core/Models/Requests/Movie/MovieRequestModel.cs +++ b/src/Ombi.Core/Models/Requests/Movie/MovieRequestModel.cs @@ -2,8 +2,6 @@ { public class MovieRequestModel : BaseRequestModel { - public string ImdbId { get; set; } - } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/RequestModel.cs b/src/Ombi.Core/Models/Requests/RequestModel.cs index f6885c16e..390ef015c 100644 --- a/src/Ombi.Core/Models/Requests/RequestModel.cs +++ b/src/Ombi.Core/Models/Requests/RequestModel.cs @@ -1,6 +1,6 @@ -using System; +using Ombi.Store.Entities; +using System; using System.Collections.Generic; -using Ombi.Store.Entities; namespace Ombi.Core.Models.Requests { @@ -12,8 +12,10 @@ namespace Ombi.Core.Models.Requests { case RequestType.Movie: return "Movie"; + case RequestType.TvShow: return "TV Show"; + default: return string.Empty; } @@ -27,13 +29,14 @@ namespace Ombi.Core.Models.Requests NoSubtitles = 1, WrongContent = 2, PlaybackIssues = 3, - Other = 4, // Provide a message + Other = 4 // Provide a message } public class EpisodesModel : IEquatable { public int SeasonNumber { get; set; } public int EpisodeNumber { get; set; } + public bool Equals(EpisodesModel other) { // Check whether the compared object is null. @@ -73,5 +76,4 @@ namespace Ombi.Core.Models.Requests public bool Available { get; set; } public bool Approved { get; set; } } - } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/RequestViewModel.cs b/src/Ombi.Core/Models/Requests/RequestViewModel.cs index a7816f777..9440c493a 100644 --- a/src/Ombi.Core/Models/Requests/RequestViewModel.cs +++ b/src/Ombi.Core/Models/Requests/RequestViewModel.cs @@ -1,5 +1,5 @@ -using System; -using Ombi.Store.Entities; +using Ombi.Store.Entities; +using System; namespace Ombi.Core.Models.Requests { diff --git a/src/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs b/src/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs index fb32da24c..ffb604779 100644 --- a/src/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs +++ b/src/Ombi.Core/Models/Requests/Tv/TvRequestModel.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using Ombi.Store.Entities; +using System.Collections.Generic; namespace Ombi.Core.Models.Requests { @@ -10,16 +8,17 @@ namespace Ombi.Core.Models.Requests { ChildRequests = new List(); } + public string ImdbId { get; set; } public string TvDbId { get; set; } public List ChildRequests { get; set; } - + /// - /// For TV Shows with a custom root folder + /// For TV Shows with a custom root folder /// /// - /// The root folder selected. + /// The root folder selected. /// public int RootFolderSelected { get; set; } } @@ -28,6 +27,5 @@ namespace Ombi.Core.Models.Requests { public bool RequestAll { get; set; } public List SeasonRequests { get; set; } = new List(); - } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs b/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs index 66fbf9ea2..ad0688f7d 100644 --- a/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchMovieViewModel.cs @@ -1,31 +1,4 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2017 Jamie Rees -// File: SearchMovieViewModel.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using System; +using System; using System.Collections.Generic; namespace Ombi.Core.Models.Search diff --git a/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs b/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs index f0165014a..fab72e420 100644 --- a/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchTvShowViewModel.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; -using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Requests; +using System.Collections.Generic; namespace Ombi.Core.Models.Search { @@ -25,29 +25,29 @@ namespace Ombi.Core.Models.Search public int SiteRating { get; set; } /// - /// This is used from the Trakt API + /// This is used from the Trakt API /// /// - /// The trailer. + /// The trailer. /// public string Trailer { get; set; } + /// - /// This is used from the Trakt API + /// This is used from the Trakt API /// /// - /// The trailer. + /// The trailer. /// public string Homepage { get; set; } public List SeasonRequests { get; set; } = new List(); /// - /// If we are requesting the entire series + /// If we are requesting the entire series /// public bool RequestAll { get; set; } public bool FirstSeason { get; set; } public bool LatestSeason { get; set; } - } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/SearchViewModel.cs b/src/Ombi.Core/Models/Search/SearchViewModel.cs index 9bbea38eb..b255af4aa 100644 --- a/src/Ombi.Core/Models/Search/SearchViewModel.cs +++ b/src/Ombi.Core/Models/Search/SearchViewModel.cs @@ -1,30 +1,4 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2017 Jamie Rees -// File: SearchViewModel.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -namespace Ombi.Core.Models.Search +namespace Ombi.Core.Models.Search { public class SearchViewModel { diff --git a/src/Ombi.Core/Models/UI/UserViewModel.cs b/src/Ombi.Core/Models/UI/UserViewModel.cs index fdb695b8e..6bb36d548 100644 --- a/src/Ombi.Core/Models/UI/UserViewModel.cs +++ b/src/Ombi.Core/Models/UI/UserViewModel.cs @@ -18,4 +18,4 @@ namespace Ombi.Core.Models.UI public string Value { get; set; } public bool Enabled { get; set; } } -} +} \ No newline at end of file diff --git a/src/Ombi.Core/Models/UserDto.cs b/src/Ombi.Core/Models/UserDto.cs index 6f5f9edc1..5c629fb39 100644 --- a/src/Ombi.Core/Models/UserDto.cs +++ b/src/Ombi.Core/Models/UserDto.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Security.Claims; -using System.Security.Principal; namespace Ombi.Core.Models { @@ -14,16 +13,12 @@ namespace Ombi.Core.Models public string Password { get; set; } public byte[] Salt { get; set; } public UserType UserType { get; set; } - - - } + public enum UserType { LocalUser = 1, PlexUser = 2, - EmbyUser = 3, + EmbyUser = 3 } - - } \ No newline at end of file diff --git a/src/Ombi.Core/MovieSender.cs b/src/Ombi.Core/MovieSender.cs index c29191e11..059c01066 100644 --- a/src/Ombi.Core/MovieSender.cs +++ b/src/Ombi.Core/MovieSender.cs @@ -1,14 +1,12 @@ -using System.Threading.Tasks; -using Ombi.Core.Models.Requests; -using Ombi.Core.Models.Requests.Movie; +using Ombi.Core.Models.Requests.Movie; using Ombi.Core.Settings; using Ombi.Settings.Settings.Models.External; +using System.Threading.Tasks; namespace Ombi.Core { public class MovieSender { - public MovieSender(ISettingsService radarrSettings) { RadarrSettings = radarrSettings; @@ -37,12 +35,17 @@ namespace Ombi.Core //return SendToRadarr(model, radarrSettings, qualityId); } - return new MovieSenderResult { Success = false, MovieSent = false, Message = "There are no movie providers enabled!"}; + return new MovieSenderResult + { + Success = false, + MovieSent = false, + Message = "There are no movie providers enabled!" + }; } - //private MovieSenderResult SendToRadarr(MovieRequestModel model, RadarrSettings settings, string qualityId) - //{ // var qualityProfile = 0; + //{ + //private MovieSenderResult SendToRadarr(MovieRequestModel model, RadarrSettings settings, string qualityId) // if (!string.IsNullOrEmpty(qualityId)) // try to parse the passed in quality, otherwise use the settings default quality // { // int.TryParse(qualityId, out qualityProfile); @@ -67,6 +70,5 @@ namespace Ombi.Core // } // return new MovieSenderResult { Result = false, MovieSendingEnabled = true }; //} - } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/BaseRule.cs b/src/Ombi.Core/Rule/BaseRule.cs index 21b1dafd8..49694b913 100644 --- a/src/Ombi.Core/Rule/BaseRule.cs +++ b/src/Ombi.Core/Rule/BaseRule.cs @@ -1,17 +1,15 @@ -using Ombi.Core.Rules; - -namespace Ombi.Core.Rule +namespace Ombi.Core.Rule { public abstract class BaseRule { public RuleResult Success() { - return new RuleResult { Success = true }; + return new RuleResult {Success = true}; } public RuleResult Fail(string message) { - return new RuleResult { Message = message }; + return new RuleResult {Message = message}; } } -} +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/IRequestRules.cs b/src/Ombi.Core/Rule/Interfaces/IRequestRules.cs similarity index 88% rename from src/Ombi.Core/Rule/IRequestRules.cs rename to src/Ombi.Core/Rule/Interfaces/IRequestRules.cs index ba5a79116..9045a049a 100644 --- a/src/Ombi.Core/Rule/IRequestRules.cs +++ b/src/Ombi.Core/Rule/Interfaces/IRequestRules.cs @@ -1,4 +1,5 @@ using Ombi.Core.Models.Requests; +using Ombi.Core.Rule; namespace Ombi.Core.Rules { @@ -6,4 +7,4 @@ namespace Ombi.Core.Rules { RuleResult Execute(T obj); } -} +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/IRuleEvaluator.cs b/src/Ombi.Core/Rule/Interfaces/IRuleEvaluator.cs similarity index 61% rename from src/Ombi.Core/Rule/IRuleEvaluator.cs rename to src/Ombi.Core/Rule/Interfaces/IRuleEvaluator.cs index a67b3ffc7..8554c8a93 100644 --- a/src/Ombi.Core/Rule/IRuleEvaluator.cs +++ b/src/Ombi.Core/Rule/Interfaces/IRuleEvaluator.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; -using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Requests; +using Ombi.Core.Rule; +using System.Collections.Generic; namespace Ombi.Core.Rules { diff --git a/src/Ombi.Core/Rule/RuleEvaluator.cs b/src/Ombi.Core/Rule/RuleEvaluator.cs index 010cea33c..ba12d0bfd 100644 --- a/src/Ombi.Core/Rule/RuleEvaluator.cs +++ b/src/Ombi.Core/Rule/RuleEvaluator.cs @@ -1,11 +1,11 @@ using Ombi.Core.Models.Requests; -using Ombi.Core.Rule; +using Ombi.Core.Rules; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -namespace Ombi.Core.Rules +namespace Ombi.Core.Rule { public class RuleEvaluator : IRuleEvaluator { @@ -14,26 +14,22 @@ namespace Ombi.Core.Rules RequestRules = new List>(); var baseType = typeof(BaseRule).FullName; - System.Reflection.Assembly ass = typeof(RuleEvaluator).GetTypeInfo().Assembly; + var ass = typeof(RuleEvaluator).GetTypeInfo().Assembly; - foreach (TypeInfo ti in ass.DefinedTypes) - { + foreach (var ti in ass.DefinedTypes) if (ti?.BaseType?.FullName == baseType) { - var type = ti.AsType(); + var type = ti?.AsType(); var ctors = type.GetConstructors(); var ctor = ctors.FirstOrDefault(); var services = new List(); foreach (var param in ctor.GetParameters()) - { services.Add(provider.GetService(param.ParameterType)); - } - var item = Activator.CreateInstance(type, services.ToArray());// ti.GetType is wrong - RequestRules.Add((IRequestRules)item); + var item = Activator.CreateInstance(type, services.ToArray()); // ti.GetType is wrong + RequestRules.Add((IRequestRules) item); } - } } private List> RequestRules { get; } @@ -50,4 +46,4 @@ namespace Ombi.Core.Rules return results; } } -} +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/RuleResult.cs b/src/Ombi.Core/Rule/RuleResult.cs index b8c07bf63..ea73cbd88 100644 --- a/src/Ombi.Core/Rule/RuleResult.cs +++ b/src/Ombi.Core/Rule/RuleResult.cs @@ -1,12 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Ombi.Core.Rules +namespace Ombi.Core.Rule { public class RuleResult { public bool Success { get; set; } public string Message { get; set; } } -} +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/AutoApproveRule.cs index e2463a8dc..9a1e140bb 100644 --- a/src/Ombi.Core/Rule/Rules/AutoApproveRule.cs +++ b/src/Ombi.Core/Rule/Rules/AutoApproveRule.cs @@ -1,10 +1,8 @@ using Ombi.Core.Claims; using Ombi.Core.Models.Requests; using Ombi.Core.Rules; -using System; -using System.Collections.Generic; +using Ombi.Store.Entities; using System.Security.Principal; -using System.Text; namespace Ombi.Core.Rule.Rules { @@ -16,23 +14,20 @@ namespace Ombi.Core.Rule.Rules } private IPrincipal User { get; } + public RuleResult Execute(BaseRequestModel obj) { - if(User.IsInRole(OmbiClaims.Admin)) + if (User.IsInRole(OmbiClaims.Admin)) { obj.Approved = true; return Success(); } - if (obj.Type == Store.Entities.RequestType.Movie && User.IsInRole(OmbiClaims.AutoApproveMovie)) - { + if (obj.Type == RequestType.Movie && User.IsInRole(OmbiClaims.AutoApproveMovie)) obj.Approved = true; - } - if (obj.Type == Store.Entities.RequestType.TvShow && User.IsInRole(OmbiClaims.AutoApproveTv)) - { + 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 } } -} +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/CanRequestRule.cs index f56a0f868..d92449bed 100644 --- a/src/Ombi.Core/Rule/Rules/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/CanRequestRule.cs @@ -1,6 +1,7 @@ using Ombi.Core.Claims; using Ombi.Core.Models.Requests; using Ombi.Core.Rules; +using Ombi.Store.Entities; using System.Security.Principal; namespace Ombi.Core.Rule.Rules @@ -13,29 +14,22 @@ namespace Ombi.Core.Rule.Rules } private IPrincipal User { get; } + public RuleResult Execute(BaseRequestModel obj) { - if(User.IsInRole(OmbiClaims.Admin)) - { + if (User.IsInRole(OmbiClaims.Admin)) return Success(); - } - if (obj.Type == Store.Entities.RequestType.Movie) + if (obj.Type == RequestType.Movie) { if (User.IsInRole(OmbiClaims.RequestMovie)) - { return Success(); - } - return Fail("You do not have permissions to Request a Movie"); - } - else - { - if (User.IsInRole(OmbiClaims.RequestTv)) - { - return Success(); - } return 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"); } } -} +} \ No newline at end of file diff --git a/src/Ombi.Core/TvSender.cs b/src/Ombi.Core/TvSender.cs index 359bde003..820b89b4b 100644 --- a/src/Ombi.Core/TvSender.cs +++ b/src/Ombi.Core/TvSender.cs @@ -1,10 +1,8 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Ombi.Api.Sonarr; -using Ombi.Core.Models.Requests; using Ombi.Core.Settings.Models.External; +using System.Linq; +using System.Threading.Tasks; namespace Ombi.Core { @@ -71,14 +69,10 @@ namespace Ombi.Core private async Task GetSonarrRootPath(int pathId, SonarrSettings sonarrSettings) { var rootFoldersResult = await SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri); - + foreach (var r in rootFoldersResult.Where(r => r.id == pathId)) - { return r.path; - } return string.Empty; } - - } } \ No newline at end of file diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 9183c86c5..5598c0ae5 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -15,6 +15,7 @@ using Ombi.Core.Engine.Interfaces; using Ombi.Core.IdentityResolver; using Ombi.Core.Models.Requests; using Ombi.Core.Requests.Models; +using Ombi.Core.Rule; using Ombi.Core.Settings; using Ombi.Notifications; using Ombi.Schedule; diff --git a/src/Ombi/Controllers/BaseV1ApiController.cs b/src/Ombi/Controllers/BaseV1ApiController.cs index 87d776ae6..f6ea39b27 100644 --- a/src/Ombi/Controllers/BaseV1ApiController.cs +++ b/src/Ombi/Controllers/BaseV1ApiController.cs @@ -1,31 +1,4 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2017 Jamie Rees -// File: BaseV1ApiController.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; namespace Ombi.Controllers { diff --git a/src/Ombi/wwwroot/app/settings/plex/plex.component.html b/src/Ombi/wwwroot/app/settings/plex/plex.component.html index 76f84eccf..85fe1873e 100644 --- a/src/Ombi/wwwroot/app/settings/plex/plex.component.html +++ b/src/Ombi/wwwroot/app/settings/plex/plex.component.html @@ -1,14 +1,12 @@ - - +
Plex Configuration -
- - -
- +
+ + +
@@ -47,27 +45,26 @@
-


-
+
+
- - +
@@ -102,10 +99,8 @@
- -
If enabled then we will lookup all episodes on your Plex server and store them in the local database. This will stop episode requests that already exist on Plex (that might not be in Sonarr). @@ -113,7 +108,6 @@
-
@@ -127,10 +121,6 @@
- - - -

@@ -148,7 +138,6 @@
-
@@ -165,9 +154,6 @@ - - -
diff --git a/src/Ombi/wwwroot/app/settings/plex/plex.component.ts b/src/Ombi/wwwroot/app/settings/plex/plex.component.ts index 71bc459f8..9f87cfcda 100644 --- a/src/Ombi/wwwroot/app/settings/plex/plex.component.ts +++ b/src/Ombi/wwwroot/app/settings/plex/plex.component.ts @@ -5,7 +5,6 @@ import "rxjs/add/operator/takeUntil"; import { IPlexSettings, IPlexLibraries, IPlexServer } from '../../interfaces/ISettings'; import { IPlexServerResponse, IPlexServerViewModel } from '../../interfaces/IPlex' - import { SettingsService } from '../../services/settings.service'; import { PlexService } from '../../services/applications/plex.service'; import { NotificationService } from "../../services/notification.service"; @@ -16,7 +15,6 @@ import { NotificationService } from "../../services/notification.service"; templateUrl: './plex.component.html', }) export class PlexComponent implements OnInit, OnDestroy { - constructor(private settingsService: SettingsService, private notificationService: NotificationService, private plexService: PlexService) { } settings: IPlexSettings; @@ -27,7 +25,6 @@ export class PlexComponent implements OnInit, OnDestroy { advanced = false; serversButton = false; - ngOnInit(): void { this.settingsService.getPlex().subscribe(x => { this.settings = x; @@ -49,8 +46,7 @@ export class PlexComponent implements OnInit, OnDestroy { }); } - selectServer(selectedServer: IPlexServerResponse, server : IPlexServer) - { + selectServer(selectedServer: IPlexServerResponse, server: IPlexServer) { server.ip = selectedServer.localAddresses.split(',')[0]; server.name = selectedServer.name; server.machineIdentifier = selectedServer.machineIdentifier; @@ -75,7 +71,6 @@ export class PlexComponent implements OnInit, OnDestroy { } removeServer(server: IPlexServer) { - this.notificationService.warning("Disabled", "This feature is currently disabled"); //var index = this.settings.servers.indexOf(server, 0); //if (index > -1) { @@ -84,13 +79,11 @@ export class PlexComponent implements OnInit, OnDestroy { } loadLibraries(server: IPlexServer) { - if (server.ip == null) - { + if (server.ip == null) { this.notificationService.error("Not Configured", "Plex is not yet configured correctly") return; } this.plexService.getLibraries(server).subscribe(x => { - server.plexSelectedLibraries = []; x.mediaContainer.directory.forEach((item, index) => { var lib: IPlexLibraries = { @@ -99,7 +92,6 @@ export class PlexComponent implements OnInit, OnDestroy { enabled: false }; server.plexSelectedLibraries.push(lib); - }); }); }