Started adding requesting

pull/1350/head^2
Jamie.Rees 8 years ago
parent e80f0bc601
commit b7f63ed1ce

@ -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

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>-->
</PropertyGroup>
<ItemGroup>

@ -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<RequestEngineResult> RequestMovie(SearchMovieViewModel model);
bool ShouldAutoApprove(RequestType requestType);
}
}

@ -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<IEnumerable<SearchMovieViewModel>> ProcessMovieSearch(string search)
{
var api = new TheMovieDbApi.TheMovieDbApi();
@ -67,8 +77,8 @@ namespace Ombi.Core
{
await Task.Yield();
var viewMovies = new List<SearchMovieViewModel>();
var counter = 0;
//Dictionary<int, RequestedModel> dbMovies = await RequestedMovies();
//var counter = 0;
Dictionary<int, RequestModel> 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<int, RequestModel> _dbMovies;
private async Task<Dictionary<int, RequestModel>> 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;
}
}
}

@ -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<RequestEngineResult> 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<string> { 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<RequestEngineResult> 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};
}
}
}

@ -0,0 +1,8 @@
namespace Ombi.Core.Engine
{
public class RequestEngineResult
{
public bool RequestAdded { get; set; }
public string Message { get; set; }
}
}

@ -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<int> AddRequestAsync(RequestModel model);
void BatchDelete(IEnumerable<RequestModel> model);
void BatchUpdate(IEnumerable<RequestModel> model);
RequestModel CheckRequest(int providerId);
RequestModel CheckRequest(string musicId);
Task<RequestModel> CheckRequestAsync(int providerId);
Task<RequestModel> CheckRequestAsync(string musicId);
void DeleteRequest(RequestModel request);
Task DeleteRequestAsync(RequestModel request);
RequestModel Get(int id);
IEnumerable<RequestModel> GetAll();
Task<IEnumerable<RequestModel>> GetAllAsync();
Task<RequestModel> GetAsync(int id);
RequestBlobs UpdateRequest(RequestModel model);
}
}

@ -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<int> 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<RequestModel>(blob.Content);
model.Id = blob.Id;
return model;
}
public async Task<RequestModel> 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<RequestModel>(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<RequestModel>(blob.Content);
model.Id = blob.Id;
return model;
}
public async Task<RequestModel> 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<RequestModel>(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<RequestModel>(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<RequestModel> GetAsync(int id)
{
var blob = await Repo.GetAsync(id).ConfigureAwait(false);
if (blob == null)
{
return new RequestModel();
}
var model = ByteConverterHelper.ReturnObject<RequestModel>(blob.Content);
model.Id = blob.Id;
return model;
}
public IEnumerable<RequestModel> GetAll()
{
var blobs = Repo.GetAll().ToList();
var retVal = new List<RequestModel>();
foreach (var b in blobs)
{
if (b == null)
{
continue;
}
var model = ByteConverterHelper.ReturnObject<RequestModel>(b.Content);
model.Id = b.Id;
retVal.Add(model);
}
return retVal;
}
public async Task<IEnumerable<RequestModel>> GetAllAsync()
{
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
var retVal = new List<RequestModel>();
foreach (var b in blobs)
{
if (b == null)
{
continue;
}
var model = ByteConverterHelper.ReturnObject<RequestModel>(b.Content);
model.Id = b.Id;
retVal.Add(model);
}
return retVal;
}
public void BatchUpdate(IEnumerable<RequestModel> 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<RequestModel> 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);
}
}
}

@ -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<string>();
Episodes = new List<EpisodesModel>();
}
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<string> RequestedUsers { get; set; }
public string ArtistName { get; set; }
public string ArtistId { get; set; }
public int IssueId { get; set; }
public List<EpisodesModel> Episodes { get; set; }
public bool Denied { get; set; }
public string DeniedReason { get; set; }
/// <summary>
/// For TV Shows with a custom root folder
/// </summary>
/// <value>
/// The root folder selected.
/// </value>
public int RootFolderSelected { get; set; }
[JsonIgnore]
public List<string> AllUsers
{
get
{
var u = new List<string>();
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<EpisodesModel>
{
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;
}
}
}

@ -2,9 +2,18 @@
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>-->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" />
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.TheMovieDbApi.csproj" />
</ItemGroup>

@ -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<T>(byte[] bytes)
{
var json = Encoding.UTF8.GetString(bytes);
var model = JsonConvert.DeserializeObject<T>(json);
return model;
}
public static string ReturnFromBytes(byte[] bytes)
{
return Encoding.UTF8.GetString(bytes);
}
}
}

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
namespace Ombi.Helpers
{
public static class LinqHelpers
{
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> knownKeys = new HashSet<TKey>();
foreach (TSource source1 in source)
{
if (knownKeys.Add(keySelector(source1)))
yield return source1;
}
}
}
}

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
</ItemGroup>
</Project>

@ -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<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
DbSet<RequestBlobs> Requests { get; set; }
}
}

@ -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<RequestBlobs> Requests { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=Ombi.db");
}
}
}

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace Ombi.Store.Entities
{
public abstract class Entity
{
[Key]
public int Id { get; set; }
}
}

@ -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
}
}

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>-->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
</ItemGroup>
</Project>

@ -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<RequestBlobs> entity);
RequestBlobs Get(int id);
IEnumerable<RequestBlobs> GetAll();
Task<IEnumerable<RequestBlobs>> GetAllAsync();
Task<RequestBlobs> GetAsync(int id);
RequestBlobs Insert(RequestBlobs entity);
Task<RequestBlobs> InsertAsync(RequestBlobs entity);
RequestBlobs Update(RequestBlobs entity);
void UpdateAll(IEnumerable<RequestBlobs> entity);
}
}

@ -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<RequestBlobs> InsertAsync(RequestBlobs entity)
{
var id = await Db.Requests.AddAsync(entity).ConfigureAwait(false);
await Db.SaveChangesAsync();
return id.Entity;
}
public IEnumerable<RequestBlobs> GetAll()
{
//var key = "GetAll";
//var item = Cache.GetOrSet(key, () =>
//{
var page = Db.Requests.ToList();
return page;
//}, 5);
//return item;
}
public async Task<IEnumerable<RequestBlobs>> 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<RequestBlobs> 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<RequestBlobs> entity)
{
Db.Requests.UpdateRange(entity);
Db.SaveChanges();
}
public void DeleteAll(IEnumerable<RequestBlobs> entity)
{
Db.Requests.RemoveRange(entity);
Db.SaveChanges();
}
}
}

@ -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<MovieResponse> GetMovieInformation(int movieId);
Task<TheMovieDbContainer<SearchResult>> NowPlaying();
Task<TheMovieDbContainer<SearchResult>> PopularMovies();
Task<TheMovieDbContainer<SearchResult>> SearchMovie(string searchTerm);
Task<TheMovieDbContainer<SearchResult>> TopRated();
Task<TheMovieDbContainer<SearchResult>> Upcoming();
}
}

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>-->
</PropertyGroup>
<ItemGroup>

@ -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<MovieResponse> GetMovieInformation(int movieId)
{
var url = BaseUri.ChangePath("movie/{0}", movieId.ToString());
AddHeaders(url);
url = AddHeaders(url);
return await Api.Get<MovieResponse>(url);
}

@ -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

@ -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<RequestEngineResult> SearchMovie([FromBody]SearchMovieViewModel movie)
{
return await RequestEngine.RequestMovie(movie);
}
}
}

@ -12,6 +12,8 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />
</ItemGroup>

@ -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<OmbiContext>();
services.AddTransient<IMovieEngine, MovieEngine>();
services.AddTransient<IRequestEngine, RequestEngine>();
services.AddTransient<IMovieDbApi, TheMovieDbApi.TheMovieDbApi>();
services.AddTransient<IRequestService, JsonRequestService>();
services.AddTransient<IOmbiContext, OmbiContext>();
services.AddTransient<IRequestRepository, RequestJsonRepository>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

@ -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]
})

@ -0,0 +1,4 @@
export interface IRequestEngineResult {
requestAdded: boolean,
message: string
}

@ -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<string> = new Subject<string>();
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() {

@ -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<IRequestEngineResult> {
return this.http.post('/api/Request/Movie/', JSON.stringify(movie), ServiceHelpers.RequestOptions).map(ServiceHelpers.extractData);
}
}

@ -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 {

@ -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

Loading…
Cancel
Save