From b7f63ed1cee3f42256925c7f9dcfd85b4819c9d5 Mon Sep 17 00:00:00 2001 From: "Jamie.Rees" Date: Thu, 6 Apr 2017 14:51:18 +0100 Subject: [PATCH] Started adding requesting --- Ombi/Build/publish windows.bat | 2 +- Ombi/Ombi.Api/Ombi.Api.csproj | 1 + .../{ => Engine/Interfaces}/IMovieEngine.cs | 0 .../Engine/Interfaces/IRequestEngine.cs | 12 + Ombi/Ombi.Core/{ => Engine}/MovieEngine.cs | 48 +++- Ombi/Ombi.Core/Engine/RequestEngine.cs | 232 ++++++++++++++++++ Ombi/Ombi.Core/Engine/RequestEngineResult.cs | 8 + .../Models/Requests/IRequestService.cs | 26 ++ .../Models/Requests/JsonRequestService.cs | 174 +++++++++++++ .../Ombi.Core/Models/Requests/RequestModel.cs | 132 ++++++++++ Ombi/Ombi.Core/Ombi.Core.csproj | 9 + Ombi/Ombi.Helpers/ByteConverterHelper.cs | 28 +++ Ombi/Ombi.Helpers/LinqHelpers.cs | 18 ++ Ombi/Ombi.Helpers/Ombi.Helpers.csproj | 11 + Ombi/Ombi.Store/Context/IOmbiContext.cs | 15 ++ Ombi/Ombi.Store/Context/OmbiContext.cs | 25 ++ Ombi/Ombi.Store/Entities/Entity.cs | 10 + Ombi/Ombi.Store/Entities/RequestBlobs.cs | 20 ++ Ombi/Ombi.Store/Ombi.Store.csproj | 16 ++ .../Repository/IRequestRepository.cs | 20 ++ .../Repository/RequestJsonRepository.cs | 126 ++++++++++ Ombi/Ombi.TheMovieDbApi/IMovieDbApi.cs | 37 +-- .../Ombi.TheMovieDbApi.csproj | 1 + Ombi/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 4 +- Ombi/Ombi.sln | 14 +- Ombi/Ombi/Controllers/RequestController.cs | 23 ++ Ombi/Ombi/Ombi.csproj | 2 + Ombi/Ombi/Startup.cs | 20 ++ Ombi/Ombi/app/app.module.ts | 4 +- .../app/interfaces/IRequestEngineResult.ts | 4 + .../interfaces/ISearchMovieResult.ts | 0 Ombi/Ombi/app/search/search.component.ts | 15 +- Ombi/Ombi/app/services/request.service.ts | 18 ++ Ombi/Ombi/app/services/search.service.ts | 2 +- appveyor.yml | 8 +- 35 files changed, 1034 insertions(+), 51 deletions(-) rename Ombi/Ombi.Core/{ => Engine/Interfaces}/IMovieEngine.cs (100%) create mode 100644 Ombi/Ombi.Core/Engine/Interfaces/IRequestEngine.cs rename Ombi/Ombi.Core/{ => Engine}/MovieEngine.cs (80%) create mode 100644 Ombi/Ombi.Core/Engine/RequestEngine.cs create mode 100644 Ombi/Ombi.Core/Engine/RequestEngineResult.cs create mode 100644 Ombi/Ombi.Core/Models/Requests/IRequestService.cs create mode 100644 Ombi/Ombi.Core/Models/Requests/JsonRequestService.cs create mode 100644 Ombi/Ombi.Core/Models/Requests/RequestModel.cs create mode 100644 Ombi/Ombi.Helpers/ByteConverterHelper.cs create mode 100644 Ombi/Ombi.Helpers/LinqHelpers.cs create mode 100644 Ombi/Ombi.Helpers/Ombi.Helpers.csproj create mode 100644 Ombi/Ombi.Store/Context/IOmbiContext.cs create mode 100644 Ombi/Ombi.Store/Context/OmbiContext.cs create mode 100644 Ombi/Ombi.Store/Entities/Entity.cs create mode 100644 Ombi/Ombi.Store/Entities/RequestBlobs.cs create mode 100644 Ombi/Ombi.Store/Ombi.Store.csproj create mode 100644 Ombi/Ombi.Store/Repository/IRequestRepository.cs create mode 100644 Ombi/Ombi.Store/Repository/RequestJsonRepository.cs create mode 100644 Ombi/Ombi/Controllers/RequestController.cs create mode 100644 Ombi/Ombi/app/interfaces/IRequestEngineResult.ts rename Ombi/Ombi/app/{search => }/interfaces/ISearchMovieResult.ts (100%) create mode 100644 Ombi/Ombi/app/services/request.service.ts diff --git a/Ombi/Build/publish windows.bat b/Ombi/Build/publish windows.bat index e94f1864d..f984ee1ba 100644 --- a/Ombi/Build/publish windows.bat +++ b/Ombi/Build/publish windows.bat @@ -1,6 +1,6 @@ ;https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/ cd .. dotnet restore -dotnet publish -c Release -r win10-x64 +dotnet publish -c Release /p:AppRuntimeIdentifier=win10-x64 exit \ No newline at end of file diff --git a/Ombi/Ombi.Api/Ombi.Api.csproj b/Ombi/Ombi.Api/Ombi.Api.csproj index 498e443c1..80457725a 100644 --- a/Ombi/Ombi.Api/Ombi.Api.csproj +++ b/Ombi/Ombi.Api/Ombi.Api.csproj @@ -2,6 +2,7 @@ netstandard1.4 + diff --git a/Ombi/Ombi.Core/IMovieEngine.cs b/Ombi/Ombi.Core/Engine/Interfaces/IMovieEngine.cs similarity index 100% rename from Ombi/Ombi.Core/IMovieEngine.cs rename to Ombi/Ombi.Core/Engine/Interfaces/IMovieEngine.cs diff --git a/Ombi/Ombi.Core/Engine/Interfaces/IRequestEngine.cs b/Ombi/Ombi.Core/Engine/Interfaces/IRequestEngine.cs new file mode 100644 index 000000000..f23604468 --- /dev/null +++ b/Ombi/Ombi.Core/Engine/Interfaces/IRequestEngine.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using Ombi.Core.Models.Search; +using Ombi.Store.Entities; + +namespace Ombi.Core.Engine +{ + public interface IRequestEngine + { + Task RequestMovie(SearchMovieViewModel model); + bool ShouldAutoApprove(RequestType requestType); + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Core/MovieEngine.cs b/Ombi/Ombi.Core/Engine/MovieEngine.cs similarity index 80% rename from Ombi/Ombi.Core/MovieEngine.cs rename to Ombi/Ombi.Core/Engine/MovieEngine.cs index b0e1d52ec..219f65d11 100644 --- a/Ombi/Ombi.Core/MovieEngine.cs +++ b/Ombi/Ombi.Core/Engine/MovieEngine.cs @@ -1,14 +1,24 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; +using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; +using Ombi.Core.Requests.Models; +using Ombi.Helpers; +using Ombi.Store.Entities; using Ombi.TheMovieDbApi.Models; -namespace Ombi.Core +namespace Ombi.Core.Engine { public class MovieEngine : IMovieEngine { + public MovieEngine(IRequestService service) + { + RequestService = service; + } + private IRequestService RequestService { get; } public async Task> ProcessMovieSearch(string search) { var api = new TheMovieDbApi.TheMovieDbApi(); @@ -67,8 +77,8 @@ namespace Ombi.Core { await Task.Yield(); var viewMovies = new List(); - var counter = 0; - //Dictionary dbMovies = await RequestedMovies(); + //var counter = 0; + Dictionary dbMovies = await RequestedMovies(); foreach (var movie in movies) { var viewMovie = new SearchMovieViewModel @@ -138,14 +148,14 @@ namespace Ombi.Core // viewMovie.Available = true; // } // } - // if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db - // { - // var dbm = dbMovies[movie.Id]; + if (dbMovies.ContainsKey(movie.id) /*&& canSee*/) // compare to the requests db + { + var dbm = dbMovies[movie.id]; - // viewMovie.Requested = true; - // viewMovie.Approved = dbm.Approved; - // viewMovie.Available = dbm.Available; - // } + viewMovie.Requested = true; + viewMovie.Approved = dbm.Approved; + viewMovie.Available = dbm.Available; + } // else if (canSee) // { // bool exists = IsMovieInCache(movie, viewMovie.ImdbId); @@ -159,5 +169,23 @@ namespace Ombi.Core } return viewMovies; } + + + private long _dbMovieCacheTime = 0; + private Dictionary _dbMovies; + private async Task> RequestedMovies() + { + long now = DateTime.Now.Ticks; + if (_dbMovies == null || (now - _dbMovieCacheTime) > 10000) + { + var allResults = await RequestService.GetAllAsync(); + allResults = allResults.Where(x => x.Type == RequestType.Movie); + + var distinctResults = allResults.DistinctBy(x => x.ProviderId); + _dbMovies = distinctResults.ToDictionary(x => x.ProviderId); + _dbMovieCacheTime = now; + } + return _dbMovies; + } } } diff --git a/Ombi/Ombi.Core/Engine/RequestEngine.cs b/Ombi/Ombi.Core/Engine/RequestEngine.cs new file mode 100644 index 000000000..eeaecfa86 --- /dev/null +++ b/Ombi/Ombi.Core/Engine/RequestEngine.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Core.Models.Requests; +using Ombi.Core.Models.Search; +using Ombi.Core.Requests.Models; +using Ombi.Store.Entities; +using Ombi.TheMovieDbApi; + +namespace Ombi.Core.Engine +{ + public class RequestEngine : IRequestEngine + { + public RequestEngine(IMovieDbApi movieApi, IRequestService requestService) + { + MovieApi = movieApi; + RequestService = requestService; + } + private IMovieDbApi MovieApi { get; } + private IRequestService RequestService { 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!" + }; + //Response.AsJson(new JsonResponseModel + //{ + // Result = false, + // Message = "There was an issue adding this movie!" + //}); + } + var fullMovieName = + $"{movieInfo.title}{(!string.IsNullOrEmpty(movieInfo.release_date) ? $" ({DateTime.Parse(movieInfo.release_date).Year})" : string.Empty)}"; + + var existingRequest = await RequestService.CheckRequestAsync(model.Id); + if (existingRequest != null) + { + // check if the current user is already marked as a requester for this movie, if not, add them + //if (!existingRequest.UserHasRequested(Username)) + //{ + // existingRequest.RequestedUsers.Add(Username); + // await RequestService.UpdateRequestAsync(existingRequest); + //} + + return new RequestEngineResult + { + RequestAdded = true, + + }; + //Response.AsJson(new JsonResponseModel + //{ + // Result = true, + // Message = + // Security.HasPermissions(User, Permissions.UsersCanViewOnlyOwnRequests) + // ? $"{fullMovieName} {Ombi.UI.Resources.UI.Search_SuccessfullyAdded}" + // : $"{fullMovieName} {Resources.UI.Search_AlreadyRequested}" + //}); + } + + + // TODO + //try + //{ + + // var content = PlexContentRepository.GetAll(); + // var movies = PlexChecker.GetPlexMovies(content); + // if (PlexChecker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString())) + // { + // return + // Response.AsJson(new JsonResponseModel + // { + // Result = false, + // Message = $"{fullMovieName} is already in Plex!" + // }); + // } + //} + //catch (Exception e) + //{ + // Log.Error(e); + // return + // Response.AsJson(new JsonResponseModel + // { + // Result = false, + // Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullMovieName, GetMediaServerName()) + // }); + //} + + var requestModel = new RequestModel + { + ProviderId = movieInfo.id, + Type = RequestType.Movie, + Overview = movieInfo.overview, + ImdbId = movieInfo.imdb_id, + PosterPath = movieInfo.poster_path, + Title = movieInfo.title, + ReleaseDate = !string.IsNullOrEmpty(movieInfo.release_date) ? DateTime.Parse(movieInfo.release_date) : DateTime.MinValue, + Status = movieInfo.status, + RequestedDate = DateTime.UtcNow, + Approved = false, + //RequestedUsers = new List { Username }, + Issues = IssueState.None, + }; + + try + { + if (ShouldAutoApprove(RequestType.Movie)) + { + // model.Approved = true; + + // var result = await MovieSender.Send(model); + // if (result.Result) + // { + // return await AddRequest(model, settings, + // $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}"); + // } + // if (result.Error) + + // { + // return + // Response.AsJson(new JsonResponseModel + // { + // Message = "Could not add movie, please contact your administrator", + // Result = false + // }); + // } + // if (!result.MovieSendingEnabled) + // { + + // return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}"); + // } + + // return Response.AsJson(new JsonResponseModel + // { + // Result = false, + // Message = Resources.UI.Search_CouchPotatoError + // }); + } + + + return await AddRequest(requestModel, /*settings,*/ + $"{fullMovieName} has been successfully added!"); + + } + catch (Exception e) + { + //Log.Fatal(e); + //await FaultQueue.QueueItemAsync(model, movieInfo.Id.ToString(), RequestType.Movie, FaultType.RequestFault, e.Message); + + //await NotificationService.Publish(new NotificationModel + //{ + // DateTime = DateTime.Now, + // User = Username, + // RequestType = RequestType.Movie, + // Title = model.Title, + // NotificationType = NotificationType.ItemAddedToFaultQueue + //}); + + //return Response.AsJson(new JsonResponseModel + //{ + // Result = true, + // Message = $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}" + //}); + } + + return null; + } + + public bool ShouldAutoApprove(RequestType requestType) + { + //var admin = Security.HasPermissions(Context.CurrentUser, Permissions.Administrator); + //// if the user is an admin, they go ahead and allow auto-approval + //if (admin) return true; + + //// check by request type if the category requires approval or not + //switch (requestType) + //{ + // case RequestType.Movie: + // return Security.HasPermissions(User, Permissions.AutoApproveMovie); + // case RequestType.TvShow: + // return Security.HasPermissions(User, Permissions.AutoApproveTv); + // case RequestType.Album: + // return Security.HasPermissions(User, Permissions.AutoApproveAlbum); + // default: + // return false; + return false; + } + + private async Task AddRequest(RequestModel model, /*PlexRequestSettings settings,*/ string message) + { + await RequestService.AddRequestAsync(model); + + //if (ShouldSendNotification(model.Type, settings)) + //{ + // var notificationModel = new NotificationModel + // { + // Title = model.Title, + // User = Username, + // 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 + // }; + // await NotificationService.Publish(notificationModel); + //} + + //var limit = await RequestLimitRepo.GetAllAsync(); + //var usersLimit = limit.FirstOrDefault(x => x.Username == Username && x.RequestType == model.Type); + //if (usersLimit == null) + //{ + // await RequestLimitRepo.InsertAsync(new RequestLimit + // { + // Username = Username, + // RequestType = model.Type, + // FirstRequestDate = DateTime.UtcNow, + // RequestCount = 1 + // }); + //} + //else + //{ + // usersLimit.RequestCount++; + // await RequestLimitRepo.UpdateAsync(usersLimit); + //} + + return new RequestEngineResult{RequestAdded = true}; + } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Core/Engine/RequestEngineResult.cs b/Ombi/Ombi.Core/Engine/RequestEngineResult.cs new file mode 100644 index 000000000..f2f2329a7 --- /dev/null +++ b/Ombi/Ombi.Core/Engine/RequestEngineResult.cs @@ -0,0 +1,8 @@ +namespace Ombi.Core.Engine +{ + public class RequestEngineResult + { + public bool RequestAdded { get; set; } + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Core/Models/Requests/IRequestService.cs b/Ombi/Ombi.Core/Models/Requests/IRequestService.cs new file mode 100644 index 000000000..1cc56dea8 --- /dev/null +++ b/Ombi/Ombi.Core/Models/Requests/IRequestService.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Core.Models.Requests; +using Ombi.Store.Entities; + +namespace Ombi.Core.Requests.Models +{ + public interface IRequestService + { + int AddRequest(RequestModel model); + Task AddRequestAsync(RequestModel model); + void BatchDelete(IEnumerable model); + void BatchUpdate(IEnumerable model); + RequestModel CheckRequest(int providerId); + RequestModel CheckRequest(string musicId); + Task CheckRequestAsync(int providerId); + Task CheckRequestAsync(string musicId); + void DeleteRequest(RequestModel request); + Task DeleteRequestAsync(RequestModel request); + RequestModel Get(int id); + IEnumerable GetAll(); + Task> GetAllAsync(); + Task GetAsync(int id); + RequestBlobs UpdateRequest(RequestModel model); + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Core/Models/Requests/JsonRequestService.cs b/Ombi/Ombi.Core/Models/Requests/JsonRequestService.cs new file mode 100644 index 000000000..f5418e74a --- /dev/null +++ b/Ombi/Ombi.Core/Models/Requests/JsonRequestService.cs @@ -0,0 +1,174 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Core.Requests.Models; +using Ombi.Helpers; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Core.Models.Requests +{ + public class JsonRequestService : IRequestService + { + public JsonRequestService(IRequestRepository repo) + { + Repo = repo; + } + private IRequestRepository Repo { get; } + public int AddRequest(RequestModel model) + { + var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId }; + var id = Repo.Insert(entity); + + return id.Id; + } + + public async Task AddRequestAsync(RequestModel model) + { + 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; + } + + public RequestModel CheckRequest(int providerId) + { + var blobs = Repo.GetAll(); + var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId); if (blob == null) + { + return null; + } + var model = ByteConverterHelper.ReturnObject(blob.Content); + model.Id = blob.Id; + return model; + } + + public async Task CheckRequestAsync(int providerId) + { + var blobs = await Repo.GetAllAsync().ConfigureAwait(false); + var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId); if (blob == null) + { + return null; + } + var model = ByteConverterHelper.ReturnObject(blob.Content); + model.Id = blob.Id; + return model; + } + + public RequestModel CheckRequest(string musicId) + { + var blobs = Repo.GetAll(); + var blob = blobs.FirstOrDefault(x => x.MusicId == musicId); if (blob == null) + { + return null; + } + var model = ByteConverterHelper.ReturnObject(blob.Content); + model.Id = blob.Id; + return model; + } + + public async Task CheckRequestAsync(string musicId) + { + var blobs = await Repo.GetAllAsync().ConfigureAwait(false); + var blob = blobs.FirstOrDefault(x => x.MusicId == musicId); + + if (blob == null) + { + return null; + } + var model = ByteConverterHelper.ReturnObject(blob.Content); + model.Id = blob.Id; + return model; + } + + public void DeleteRequest(RequestModel request) + { + var blob = Repo.Get(request.Id); + Repo.Delete(blob); + } + + public async Task DeleteRequestAsync(RequestModel request) + { + var blob = await Repo.GetAsync(request.Id).ConfigureAwait(false); + Repo.Delete(blob); + } + + public RequestBlobs UpdateRequest(RequestModel model) + { + var entity = new RequestBlobs { Type = model.Type, Content = ByteConverterHelper.ReturnBytes(model), ProviderId = model.ProviderId, Id = model.Id }; + return Repo.Update(entity); + } + + public RequestModel Get(int id) + { + var blob = Repo.Get(id); + if (blob == null) + { + return new RequestModel(); + } + 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 + return model; + } + + public async Task GetAsync(int id) + { + var blob = await Repo.GetAsync(id).ConfigureAwait(false); + if (blob == null) + { + return new RequestModel(); + } + var model = ByteConverterHelper.ReturnObject(blob.Content); + model.Id = blob.Id; + return model; + } + + public IEnumerable GetAll() + { + var blobs = Repo.GetAll().ToList(); + var retVal = new List(); + + foreach (var b in blobs) + { + if (b == null) + { + continue; + } + var model = ByteConverterHelper.ReturnObject(b.Content); + model.Id = b.Id; + retVal.Add(model); + } + return retVal; + } + + public async Task> GetAllAsync() + { + var blobs = await Repo.GetAllAsync().ConfigureAwait(false); + var retVal = new List(); + + foreach (var b in blobs) + { + if (b == null) + { + continue; + } + var model = ByteConverterHelper.ReturnObject(b.Content); + model.Id = b.Id; + retVal.Add(model); + } + return retVal; + } + + 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(); + 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(); + Repo.DeleteAll(entities); + } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Core/Models/Requests/RequestModel.cs b/Ombi/Ombi.Core/Models/Requests/RequestModel.cs new file mode 100644 index 000000000..1eb9442e6 --- /dev/null +++ b/Ombi/Ombi.Core/Models/Requests/RequestModel.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Ombi.Store.Entities; + +namespace Ombi.Core.Models.Requests +{ + public class RequestModel : Entity + { + public RequestModel() + { + RequestedUsers = new List(); + Episodes = new List(); + } + + public int ProviderId { get; set; } + public string ImdbId { get; set; } + public string TvDbId { get; set; } + public string Overview { get; set; } + public string Title { get; set; } + public string PosterPath { get; set; } + public DateTime ReleaseDate { get; set; } + public RequestType Type { get; set; } + public string Status { get; set; } + public bool Approved { get; set; } + + public DateTime RequestedDate { get; set; } + public bool Available { get; set; } + public IssueState Issues { get; set; } + public string OtherMessage { get; set; } + public string AdminNote { get; set; } + public int[] SeasonList { get; set; } + public int SeasonCount { get; set; } + public string SeasonsRequested { get; set; } + public string MusicBrainzId { get; set; } + public List RequestedUsers { get; set; } + public string ArtistName { get; set; } + public string ArtistId { get; set; } + public int IssueId { get; set; } + public List Episodes { get; set; } + public bool Denied { get; set; } + public string DeniedReason { get; set; } + /// + /// For TV Shows with a custom root folder + /// + /// + /// The root folder selected. + /// + public int RootFolderSelected { get; set; } + + [JsonIgnore] + public List AllUsers + { + get + { + var u = new List(); + if (RequestedUsers != null && RequestedUsers.Any()) + { + u.AddRange(RequestedUsers); + } + return u; + } + } + + [JsonIgnore] + public bool CanApprove => !Approved && !Available; + + public string ReleaseId { get; set; } + + public bool UserHasRequested(string username) + { + return AllUsers.Any(x => x.Equals(username, StringComparison.OrdinalIgnoreCase)); + } + } + + + + public static class RequestTypeDisplay + { + public static string GetString(this RequestType type) + { + switch (type) + { + case RequestType.Movie: + return "Movie"; + case RequestType.TvShow: + return "TV Show"; + case RequestType.Album: + return "Album"; + default: + return string.Empty; + } + } + } + + public enum IssueState + { + None = 99, + WrongAudio = 0, + NoSubtitles = 1, + WrongContent = 2, + PlaybackIssues = 3, + 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. + if (ReferenceEquals(other, null)) return false; + + //Check whether the compared object references the same data. + if (ReferenceEquals(this, other)) return true; + + //Check whether the properties are equal. + return SeasonNumber.Equals(other.SeasonNumber) && EpisodeNumber.Equals(other.EpisodeNumber); + } + + public override int GetHashCode() + { + var hashSeason = SeasonNumber.GetHashCode(); + var hashEp = EpisodeNumber.GetHashCode(); + + //Calculate the hash code. + return hashSeason + hashEp; + } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Core/Ombi.Core.csproj b/Ombi/Ombi.Core/Ombi.Core.csproj index 714b40cd8..078f56b95 100644 --- a/Ombi/Ombi.Core/Ombi.Core.csproj +++ b/Ombi/Ombi.Core/Ombi.Core.csproj @@ -2,9 +2,18 @@ netstandard1.4 + + + + + + + + + diff --git a/Ombi/Ombi.Helpers/ByteConverterHelper.cs b/Ombi/Ombi.Helpers/ByteConverterHelper.cs new file mode 100644 index 000000000..07db8fd7d --- /dev/null +++ b/Ombi/Ombi.Helpers/ByteConverterHelper.cs @@ -0,0 +1,28 @@ +using System; +using System.Text; +using Newtonsoft.Json; + +namespace Ombi.Helpers +{ + public class ByteConverterHelper + { + public static byte[] ReturnBytes(object obj) + { + var json = JsonConvert.SerializeObject(obj); + var bytes = Encoding.UTF8.GetBytes(json); + + return bytes; + } + + public static T ReturnObject(byte[] bytes) + { + var json = Encoding.UTF8.GetString(bytes); + var model = JsonConvert.DeserializeObject(json); + return model; + } + public static string ReturnFromBytes(byte[] bytes) + { + return Encoding.UTF8.GetString(bytes); + } + } +} diff --git a/Ombi/Ombi.Helpers/LinqHelpers.cs b/Ombi/Ombi.Helpers/LinqHelpers.cs new file mode 100644 index 000000000..279d161b7 --- /dev/null +++ b/Ombi/Ombi.Helpers/LinqHelpers.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace Ombi.Helpers +{ + public static class LinqHelpers + { + public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector) + { + HashSet knownKeys = new HashSet(); + foreach (TSource source1 in source) + { + if (knownKeys.Add(keySelector(source1))) + yield return source1; + } + } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Helpers/Ombi.Helpers.csproj b/Ombi/Ombi.Helpers/Ombi.Helpers.csproj new file mode 100644 index 000000000..498e443c1 --- /dev/null +++ b/Ombi/Ombi.Helpers/Ombi.Helpers.csproj @@ -0,0 +1,11 @@ + + + + netstandard1.4 + + + + + + + \ No newline at end of file diff --git a/Ombi/Ombi.Store/Context/IOmbiContext.cs b/Ombi/Ombi.Store/Context/IOmbiContext.cs new file mode 100644 index 000000000..c9dff7bca --- /dev/null +++ b/Ombi/Ombi.Store/Context/IOmbiContext.cs @@ -0,0 +1,15 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Entities; + +namespace Ombi.Store.Context +{ + public interface IOmbiContext : IDisposable + { + int SaveChanges(); + Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); + DbSet Requests { get; set; } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Store/Context/OmbiContext.cs b/Ombi/Ombi.Store/Context/OmbiContext.cs new file mode 100644 index 000000000..ec8903d3a --- /dev/null +++ b/Ombi/Ombi.Store/Context/OmbiContext.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Entities; + +namespace Ombi.Store.Context +{ + public class OmbiContext : DbContext, IOmbiContext + { + private static bool _created = false; + public OmbiContext() + { + if(!_created) + { + _created = true; + //Database.EnsureDeleted(); + Database.EnsureCreated(); + } + } + public DbSet Requests { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlite("Data Source=Ombi.db"); + } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Store/Entities/Entity.cs b/Ombi/Ombi.Store/Entities/Entity.cs new file mode 100644 index 000000000..8e1cd2887 --- /dev/null +++ b/Ombi/Ombi.Store/Entities/Entity.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace Ombi.Store.Entities +{ + public abstract class Entity + { + [Key] + public int Id { get; set; } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Store/Entities/RequestBlobs.cs b/Ombi/Ombi.Store/Entities/RequestBlobs.cs new file mode 100644 index 000000000..16ecff989 --- /dev/null +++ b/Ombi/Ombi.Store/Entities/RequestBlobs.cs @@ -0,0 +1,20 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Ombi.Store.Entities +{ + [Table("RequestBlobs")] + public class RequestBlobs : Entity + { + public int ProviderId { get; set; } + public byte[] Content { get; set; } + public RequestType Type { get; set; } + public string MusicId { get; set; } + + } + public enum RequestType + { + Movie, + TvShow, + Album + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Store/Ombi.Store.csproj b/Ombi/Ombi.Store/Ombi.Store.csproj new file mode 100644 index 000000000..7d9da619e --- /dev/null +++ b/Ombi/Ombi.Store/Ombi.Store.csproj @@ -0,0 +1,16 @@ + + + + netstandard1.4 + + + + + + + + + + + + \ No newline at end of file diff --git a/Ombi/Ombi.Store/Repository/IRequestRepository.cs b/Ombi/Ombi.Store/Repository/IRequestRepository.cs new file mode 100644 index 000000000..4e1ac2798 --- /dev/null +++ b/Ombi/Ombi.Store/Repository/IRequestRepository.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Ombi.Store.Entities; + +namespace Ombi.Store.Repository +{ + public interface IRequestRepository + { + void Delete(RequestBlobs entity); + void DeleteAll(IEnumerable entity); + RequestBlobs Get(int id); + IEnumerable GetAll(); + Task> GetAllAsync(); + Task GetAsync(int id); + RequestBlobs Insert(RequestBlobs entity); + Task InsertAsync(RequestBlobs entity); + RequestBlobs Update(RequestBlobs entity); + void UpdateAll(IEnumerable entity); + } +} \ No newline at end of file diff --git a/Ombi/Ombi.Store/Repository/RequestJsonRepository.cs b/Ombi/Ombi.Store/Repository/RequestJsonRepository.cs new file mode 100644 index 000000000..f16b96d51 --- /dev/null +++ b/Ombi/Ombi.Store/Repository/RequestJsonRepository.cs @@ -0,0 +1,126 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Ombi.Store.Context; +using Ombi.Store.Entities; + +namespace Ombi.Store.Repository +{ + public class RequestJsonRepository : IRequestRepository + { + //private ICacheProvider Cache { get; } + + public RequestJsonRepository(IOmbiContext ctx) + { + Db = ctx; + } + + private IOmbiContext Db { get; } + + public RequestBlobs Insert(RequestBlobs entity) + { + + var id = Db.Requests.Add(entity); + Db.SaveChanges(); + return id.Entity; + + } + + public async Task InsertAsync(RequestBlobs entity) + { + + var id = await Db.Requests.AddAsync(entity).ConfigureAwait(false); + await Db.SaveChangesAsync(); + return id.Entity; + + } + + public IEnumerable GetAll() + { + //var key = "GetAll"; + //var item = Cache.GetOrSet(key, () => + //{ + + var page = Db.Requests.ToList(); + return page; + + //}, 5); + //return item; + } + + public async Task> GetAllAsync() + { + //var key = "GetAll"; + //var item = await Cache.GetOrSetAsync(key, async () => + //{ + + var page = await Db.Requests.ToListAsync().ConfigureAwait(false); + return page; + + //}, 5); + //return item; + } + + public RequestBlobs Get(int id) + { + //var key = "Get" + id; + //var item = Cache.GetOrSet(key, () => + //{ + + var page = Db.Requests.Find(id); + return page; + + //}, 5); + //return item; + } + + public async Task GetAsync(int id) + { + //var key = "Get" + id; + //var item = await Cache.GetOrSetAsync(key, async () => + //{ + + var page = await Db.Requests.FindAsync(id).ConfigureAwait(false); + return page; + + //}, 5); + //return item; + } + + public void Delete(RequestBlobs entity) + { + //ResetCache(); + + Db.Requests.Remove(entity); + Db.SaveChanges(); + + } + + public RequestBlobs Update(RequestBlobs entity) + { + + return Db.Requests.Update(entity).Entity; + Db.SaveChanges(); + + } + + public void UpdateAll(IEnumerable entity) + { + + Db.Requests.UpdateRange(entity); + Db.SaveChanges(); + + } + + + + public void DeleteAll(IEnumerable entity) + { + + Db.Requests.RemoveRange(entity); + Db.SaveChanges(); + + } + } +} \ No newline at end of file diff --git a/Ombi/Ombi.TheMovieDbApi/IMovieDbApi.cs b/Ombi/Ombi.TheMovieDbApi/IMovieDbApi.cs index 3be66d0c1..219bc5a41 100644 --- a/Ombi/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/Ombi/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -1,33 +1,16 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2017 Jamie Rees -// File: IMovieDbApi.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.Threading.Tasks; +using Ombi.Api; +using Ombi.TheMovieDbApi.Models; + namespace Ombi.TheMovieDbApi { public interface IMovieDbApi { - + Task GetMovieInformation(int movieId); + Task> NowPlaying(); + Task> PopularMovies(); + Task> SearchMovie(string searchTerm); + Task> TopRated(); + Task> Upcoming(); } } \ No newline at end of file diff --git a/Ombi/Ombi.TheMovieDbApi/Ombi.TheMovieDbApi.csproj b/Ombi/Ombi.TheMovieDbApi/Ombi.TheMovieDbApi.csproj index 3197c51cf..16516740e 100644 --- a/Ombi/Ombi.TheMovieDbApi/Ombi.TheMovieDbApi.csproj +++ b/Ombi/Ombi.TheMovieDbApi/Ombi.TheMovieDbApi.csproj @@ -2,6 +2,7 @@ netstandard1.4 + diff --git a/Ombi/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/Ombi/Ombi.TheMovieDbApi/TheMovieDbApi.cs index d8e4e5709..dc68c5f52 100644 --- a/Ombi/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/Ombi/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -6,7 +6,7 @@ using Ombi.TheMovieDbApi.Models; namespace Ombi.TheMovieDbApi { - public class TheMovieDbApi + public class TheMovieDbApi : IMovieDbApi { public TheMovieDbApi() { @@ -19,7 +19,7 @@ namespace Ombi.TheMovieDbApi public async Task GetMovieInformation(int movieId) { var url = BaseUri.ChangePath("movie/{0}", movieId.ToString()); - AddHeaders(url); + url = AddHeaders(url); return await Api.Get(url); } diff --git a/Ombi/Ombi.sln b/Ombi/Ombi.sln index d4488bfca..8857dcc07 100644 --- a/Ombi/Ombi.sln +++ b/Ombi/Ombi.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.9 +VisualStudioVersion = 15.0.26228.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}" EndProject @@ -20,6 +20,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.TheMovieDbApi", "Ombi. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api", "Ombi.Api\Ombi.Api.csproj", "{EA31F915-31F9-4318-B521-1500CDF40DDF}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Helpers", "Ombi.Helpers\Ombi.Helpers.csproj", "{C182B435-1FAB-49C5-9BF9-F7F5C6EF3C94}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Store", "Ombi.Store\Ombi.Store.csproj", "{68086581-1EFD-4390-8100-47F87D1CB628}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -42,6 +46,14 @@ Global {EA31F915-31F9-4318-B521-1500CDF40DDF}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA31F915-31F9-4318-B521-1500CDF40DDF}.Release|Any CPU.ActiveCfg = Release|Any CPU {EA31F915-31F9-4318-B521-1500CDF40DDF}.Release|Any CPU.Build.0 = Release|Any CPU + {C182B435-1FAB-49C5-9BF9-F7F5C6EF3C94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C182B435-1FAB-49C5-9BF9-F7F5C6EF3C94}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C182B435-1FAB-49C5-9BF9-F7F5C6EF3C94}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C182B435-1FAB-49C5-9BF9-F7F5C6EF3C94}.Release|Any CPU.Build.0 = Release|Any CPU + {68086581-1EFD-4390-8100-47F87D1CB628}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68086581-1EFD-4390-8100-47F87D1CB628}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68086581-1EFD-4390-8100-47F87D1CB628}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68086581-1EFD-4390-8100-47F87D1CB628}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Ombi/Ombi/Controllers/RequestController.cs b/Ombi/Ombi/Controllers/RequestController.cs new file mode 100644 index 000000000..34e4465d2 --- /dev/null +++ b/Ombi/Ombi/Controllers/RequestController.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Ombi.Core.Engine; +using Ombi.Core.Models.Search; + +namespace Ombi.Controllers +{ + public class RequestController : BaseApiController + { + public RequestController(IRequestEngine engine) + { + RequestEngine = engine; + } + + private IRequestEngine RequestEngine { get; } + + [HttpPost("movie")] + public async Task SearchMovie([FromBody]SearchMovieViewModel movie) + { + return await RequestEngine.RequestMovie(movie); + } + } +} diff --git a/Ombi/Ombi/Ombi.csproj b/Ombi/Ombi/Ombi.csproj index 6dd5183f2..bfb0278da 100644 --- a/Ombi/Ombi/Ombi.csproj +++ b/Ombi/Ombi/Ombi.csproj @@ -12,6 +12,8 @@ + + diff --git a/Ombi/Ombi/Startup.cs b/Ombi/Ombi/Startup.cs index a4ed7be34..7fb5c4e52 100644 --- a/Ombi/Ombi/Startup.cs +++ b/Ombi/Ombi/Startup.cs @@ -7,11 +7,18 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.StaticFiles; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; using Ombi.Core; +using Ombi.Core.Engine; +using Ombi.Core.Models.Requests; +using Ombi.Core.Requests.Models; +using Ombi.Store.Context; +using Ombi.Store.Repository; +using Ombi.TheMovieDbApi; namespace Ombi { @@ -25,6 +32,13 @@ namespace Ombi .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); + + using (var ctx = new OmbiContext()) + { + ctx.Database.EnsureCreated(); + ctx.Database.Migrate(); + } + } public IConfigurationRoot Configuration { get; } @@ -34,7 +48,13 @@ namespace Ombi { // Add framework services. services.AddMvc(); + services.AddEntityFrameworkSqlite().AddDbContext(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/Ombi/Ombi/app/app.module.ts b/Ombi/Ombi/app/app.module.ts index 8741b8fb9..2bc3967a6 100644 --- a/Ombi/Ombi/app/app.module.ts +++ b/Ombi/Ombi/app/app.module.ts @@ -13,6 +13,7 @@ import { PageNotFoundComponent } from './errors/not-found.component'; // Services import { SearchService } from './services/search.service'; +import { RequestService } from './services/request.service'; import { ButtonModule } from 'primeng/primeng'; import { MenubarModule } from 'primeng/components/menubar/menubar'; @@ -40,7 +41,8 @@ const routes: Routes = [ SearchComponent ], providers: [ - SearchService + SearchService, + RequestService ], bootstrap: [AppComponent] }) diff --git a/Ombi/Ombi/app/interfaces/IRequestEngineResult.ts b/Ombi/Ombi/app/interfaces/IRequestEngineResult.ts new file mode 100644 index 000000000..b29f3509d --- /dev/null +++ b/Ombi/Ombi/app/interfaces/IRequestEngineResult.ts @@ -0,0 +1,4 @@ +export interface IRequestEngineResult { + requestAdded: boolean, + message: string +} \ No newline at end of file diff --git a/Ombi/Ombi/app/search/interfaces/ISearchMovieResult.ts b/Ombi/Ombi/app/interfaces/ISearchMovieResult.ts similarity index 100% rename from Ombi/Ombi/app/search/interfaces/ISearchMovieResult.ts rename to Ombi/Ombi/app/interfaces/ISearchMovieResult.ts diff --git a/Ombi/Ombi/app/search/search.component.ts b/Ombi/Ombi/app/search/search.component.ts index ccee48c79..c7152dcea 100644 --- a/Ombi/Ombi/app/search/search.component.ts +++ b/Ombi/Ombi/app/search/search.component.ts @@ -5,22 +5,25 @@ import 'rxjs/add/operator/distinctUntilChanged'; import 'rxjs/add/operator/map'; import { SearchService } from '../services/search.service'; +import { RequestService } from '../services/request.service'; -import { ISearchMovieResult } from './interfaces/ISearchMovieResult'; +import { ISearchMovieResult } from '../interfaces/ISearchMovieResult'; +import { IRequestEngineResult } from '../interfaces/IRequestEngineResult'; @Component({ selector: 'ombi', moduleId: module.id, templateUrl: './search.component.html', - providers: [SearchService] + providers: [SearchService, RequestService] }) export class SearchComponent implements OnInit { searchText: string; searchChanged: Subject = new Subject(); movieResults: ISearchMovieResult[]; + result: IRequestEngineResult; - constructor(private searchService: SearchService) { + constructor(private searchService: SearchService, private requestService: RequestService) { this.searchChanged .debounceTime(600) // Wait Xms afterthe last event before emitting last event .distinctUntilChanged() // only emit if value is different from previous value @@ -37,6 +40,10 @@ export class SearchComponent implements OnInit { ngOnInit(): void { this.searchText = ""; this.movieResults = []; + this.result = { + message: "", + requestAdded:false + } } search(text: any) { @@ -44,7 +51,7 @@ export class SearchComponent implements OnInit { } request(searchResult: ISearchMovieResult) { - console.log(searchResult); + this.requestService.requestMovie(searchResult).subscribe(x => this.result = x); } popularMovies() { diff --git a/Ombi/Ombi/app/services/request.service.ts b/Ombi/Ombi/app/services/request.service.ts new file mode 100644 index 000000000..4af6c70b7 --- /dev/null +++ b/Ombi/Ombi/app/services/request.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@angular/core'; +import { Http } from '@angular/http'; +import { Observable } from 'rxjs/Rx'; + +import { ServiceHelpers } from './service.helpers'; +import { IRequestEngineResult } from '../interfaces/IRequestEngineResult'; +import { ISearchMovieResult } from '../interfaces/ISearchMovieResult'; + +@Injectable() +export class RequestService { + constructor(private http: Http) { + } + + requestMovie(movie: ISearchMovieResult): Observable { + return this.http.post('/api/Request/Movie/', JSON.stringify(movie), ServiceHelpers.RequestOptions).map(ServiceHelpers.extractData); + } + +} \ No newline at end of file diff --git a/Ombi/Ombi/app/services/search.service.ts b/Ombi/Ombi/app/services/search.service.ts index 6e401abe7..f684fa235 100644 --- a/Ombi/Ombi/app/services/search.service.ts +++ b/Ombi/Ombi/app/services/search.service.ts @@ -3,7 +3,7 @@ import { Http } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import { ServiceHelpers } from './service.helpers'; -import { ISearchMovieResult } from '../search/interfaces/ISearchMovieResult'; +import { ISearchMovieResult } from '../interfaces/ISearchMovieResult'; @Injectable() export class SearchService { diff --git a/appveyor.yml b/appveyor.yml index 6c0f2e7eb..46f31155b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,10 +21,10 @@ before_build: build_script: - dotnet build after_build: -- dotnet publish -c Release -r win10-x64 -- dotnet publish -c Release -r osx.10.12-x64 -- dotnet publish -c Release -r ubuntu.16.10-x64 -- dotnet publish -c Release -r debian.8-x64 +- dotnet publish -c Release /p:AppRuntimeIdentifier=win10-x64 +- dotnet publish -c Release /p:AppRuntimeIdentifier=osx.10.12-x64 +- dotnet publish -c Release /p:AppRuntimeIdentifier=ubuntu.16.10-x64 +- dotnet publish -c Release /p:AppRuntimeIdentifier=debian.8-x64 - cmd: >- 7z a Ombi_windows.zip %APPVEYOR_BUILD_FOLDER%\Ombi\Ombi\bin\Release\netcoreapp1.1\win10-x64\publish