mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
commit
45d1f3488f
64 changed files with 1734 additions and 131 deletions
31
CHANGELOG.md
31
CHANGELOG.md
|
@ -1,5 +1,36 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## (unreleased)
|
||||||
|
|
||||||
|
### **New Features**
|
||||||
|
|
||||||
|
- Finished adding subscriptions for TV Shows. [Jamie Rees]
|
||||||
|
|
||||||
|
- Added the test button for mobile notifications. [Jamie Rees]
|
||||||
|
|
||||||
|
- Added classes to donation html elements. [Anojh]
|
||||||
|
|
||||||
|
- Enhanced newsletter styling to support more mail clients. [Anojh]
|
||||||
|
|
||||||
|
- Improved the way we sync the plex content and then get the metadata. #2243. [Jamie Rees]
|
||||||
|
|
||||||
|
### **Fixes**
|
||||||
|
|
||||||
|
- Fixed #2257. [Jamie Rees]
|
||||||
|
|
||||||
|
- Fixed the issue when enabling the Hide Request Users included system users e.g. API key user #2232. [Jamie Rees]
|
||||||
|
|
||||||
|
- Fix #2167. [Anojh]
|
||||||
|
|
||||||
|
- Fix #2228. [Anojh]
|
||||||
|
|
||||||
|
- Fix #2246. [Anojh]
|
||||||
|
|
||||||
|
- Fix #2234. [Anojh]
|
||||||
|
|
||||||
|
- Fixed that sometimes there would be a hidden error on the login page. [Jamie Rees]
|
||||||
|
|
||||||
|
|
||||||
## v3.0.3304 (2018-05-09)
|
## v3.0.3304 (2018-05-09)
|
||||||
|
|
||||||
### **New Features**
|
### **New Features**
|
||||||
|
|
|
@ -18,6 +18,10 @@ namespace Ombi.Api.Pushover
|
||||||
|
|
||||||
public async Task<PushoverResponse> PushAsync(string accessToken, string message, string userToken)
|
public async Task<PushoverResponse> PushAsync(string accessToken, string message, string userToken)
|
||||||
{
|
{
|
||||||
|
if (message.Contains("'"))
|
||||||
|
{
|
||||||
|
message = message.Replace("'", "'");
|
||||||
|
}
|
||||||
var request = new Request($"messages.json?token={accessToken}&user={userToken}&message={WebUtility.HtmlEncode(message)}", PushoverEndpoint, HttpMethod.Post);
|
var request = new Request($"messages.json?token={accessToken}&user={userToken}&message={WebUtility.HtmlEncode(message)}", PushoverEndpoint, HttpMethod.Post);
|
||||||
|
|
||||||
var result = await _api.Request<PushoverResponse>(request);
|
var result = await _api.Request<PushoverResponse>(request);
|
||||||
|
|
|
@ -9,13 +9,12 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Ombi.Core.Rule.Interfaces;
|
using Ombi.Core.Rule.Interfaces;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
using Ombi.Store.Repository;
|
|
||||||
using Ombi.Store.Repository.Requests;
|
using Ombi.Store.Repository.Requests;
|
||||||
using Ombi.Store.Entities;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Ombi.Core.Authentication;
|
using Ombi.Core.Authentication;
|
||||||
using Ombi.Core.Settings;
|
using Ombi.Core.Settings;
|
||||||
using Ombi.Settings.Settings.Models;
|
using Ombi.Settings.Settings.Models;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
|
@ -26,11 +25,12 @@ namespace Ombi.Core.Engine
|
||||||
private Dictionary<int, TvRequests> _dbTv;
|
private Dictionary<int, TvRequests> _dbTv;
|
||||||
|
|
||||||
protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService,
|
protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService,
|
||||||
IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings) : base(identity, um, rules)
|
IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub) : base(identity, um, rules)
|
||||||
{
|
{
|
||||||
RequestService = requestService;
|
RequestService = requestService;
|
||||||
Cache = cache;
|
Cache = cache;
|
||||||
OmbiSettings = ombiSettings;
|
OmbiSettings = ombiSettings;
|
||||||
|
_subscriptionRepository = sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IRequestServiceMain RequestService { get; }
|
protected IRequestServiceMain RequestService { get; }
|
||||||
|
@ -38,6 +38,7 @@ namespace Ombi.Core.Engine
|
||||||
protected ITvRequestRepository TvRepository => RequestService.TvRequestService;
|
protected ITvRequestRepository TvRepository => RequestService.TvRequestService;
|
||||||
protected readonly ICacheService Cache;
|
protected readonly ICacheService Cache;
|
||||||
protected readonly ISettingsService<OmbiSettings> OmbiSettings;
|
protected readonly ISettingsService<OmbiSettings> OmbiSettings;
|
||||||
|
protected readonly IRepository<RequestSubscription> _subscriptionRepository;
|
||||||
|
|
||||||
protected async Task<Dictionary<int, MovieRequests>> GetMovieRequests()
|
protected async Task<Dictionary<int, MovieRequests>> GetMovieRequests()
|
||||||
{
|
{
|
||||||
|
@ -108,21 +109,51 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
protected async Task<HideResult> HideFromOtherUsers()
|
protected async Task<HideResult> HideFromOtherUsers()
|
||||||
{
|
{
|
||||||
if (await IsInRole(OmbiRoles.Admin) || await IsInRole(OmbiRoles.PowerUser))
|
var user = await GetUser();
|
||||||
|
if (await IsInRole(OmbiRoles.Admin) || await IsInRole(OmbiRoles.PowerUser) || user.IsSystemUser)
|
||||||
{
|
{
|
||||||
return new HideResult();
|
return new HideResult
|
||||||
|
{
|
||||||
|
UserId = user.Id
|
||||||
|
};
|
||||||
}
|
}
|
||||||
var settings = await Cache.GetOrAdd(CacheKeys.OmbiSettings, async () => await OmbiSettings.GetSettingsAsync());
|
var settings = await Cache.GetOrAdd(CacheKeys.OmbiSettings, async () => await OmbiSettings.GetSettingsAsync());
|
||||||
var result = new HideResult
|
var result = new HideResult
|
||||||
{
|
{
|
||||||
Hide = settings.HideRequestsUsers
|
Hide = settings.HideRequestsUsers,
|
||||||
|
UserId = user.Id
|
||||||
};
|
};
|
||||||
if (settings.HideRequestsUsers)
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SubscribeToRequest(int requestId, RequestType type)
|
||||||
{
|
{
|
||||||
var user = await GetUser();
|
var user = await GetUser();
|
||||||
result.UserId = user.Id;
|
var existingSub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(x =>
|
||||||
|
x.UserId.Equals(user.Id) && x.RequestId == requestId && x.RequestType == type);
|
||||||
|
if (existingSub != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var sub = new RequestSubscription
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
RequestId = requestId,
|
||||||
|
RequestType = type
|
||||||
|
};
|
||||||
|
|
||||||
|
await _subscriptionRepository.Add(sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UnSubscribeRequest(int requestId, RequestType type)
|
||||||
|
{
|
||||||
|
var user = await GetUser();
|
||||||
|
var existingSub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(x =>
|
||||||
|
x.UserId.Equals(user.Id) && x.RequestId == requestId && x.RequestType == type);
|
||||||
|
if (existingSub != null)
|
||||||
|
{
|
||||||
|
await _subscriptionRepository.Delete(existingSub);
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HideResult
|
public class HideResult
|
||||||
|
|
|
@ -19,5 +19,6 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<RequestEngineResult> DenyMovieById(int modelId);
|
Task<RequestEngineResult> DenyMovieById(int modelId);
|
||||||
Task<FilterResult<MovieRequests>> Filter(FilterViewModel vm);
|
Task<FilterResult<MovieRequests>> Filter(FilterViewModel vm);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine.Interfaces
|
namespace Ombi.Core.Engine.Interfaces
|
||||||
{
|
{
|
||||||
|
@ -18,5 +19,7 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<RequestEngineResult> MarkUnavailable(int modelId);
|
Task<RequestEngineResult> MarkUnavailable(int modelId);
|
||||||
Task<RequestEngineResult> MarkAvailable(int modelId);
|
Task<RequestEngineResult> MarkAvailable(int modelId);
|
||||||
Task<int> GetTotal();
|
Task<int> GetTotal();
|
||||||
|
Task UnSubscribeRequest(int requestId, RequestType type);
|
||||||
|
Task SubscribeToRequest(int requestId, RequestType type);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,7 +25,8 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user,
|
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user,
|
||||||
INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log,
|
INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log,
|
||||||
OmbiUserManager manager, IRepository<RequestLog> rl, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings) : base(user, requestService, r, manager, cache, ombiSettings)
|
OmbiUserManager manager, IRepository<RequestLog> rl, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub)
|
||||||
|
: base(user, requestService, r, manager, cache, ombiSettings, sub)
|
||||||
{
|
{
|
||||||
MovieApi = movieApi;
|
MovieApi = movieApi;
|
||||||
NotificationHelper = helper;
|
NotificationHelper = helper;
|
||||||
|
@ -137,9 +138,10 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
allRequests = await MovieRepository.GetWithUser().Skip(position).Take(count).OrderByDescending(x => x.ReleaseDate).ToListAsync();
|
allRequests = await MovieRepository.GetWithUser().Skip(position).Take(count).OrderByDescending(x => x.ReleaseDate).ToListAsync();
|
||||||
}
|
}
|
||||||
allRequests.ForEach(x =>
|
allRequests.ForEach(async x =>
|
||||||
{
|
{
|
||||||
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
|
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
|
||||||
|
await CheckForSubscription(shouldHide, x);
|
||||||
});
|
});
|
||||||
return allRequests;
|
return allRequests;
|
||||||
}
|
}
|
||||||
|
@ -173,9 +175,30 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
allRequests = await MovieRepository.GetWithUser().ToListAsync();
|
allRequests = await MovieRepository.GetWithUser().ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allRequests.ForEach(async x =>
|
||||||
|
{
|
||||||
|
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
|
||||||
|
await CheckForSubscription(shouldHide, x);
|
||||||
|
});
|
||||||
return allRequests;
|
return allRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task CheckForSubscription(HideResult shouldHide, MovieRequests x)
|
||||||
|
{
|
||||||
|
if (shouldHide.UserId == x.RequestedUserId)
|
||||||
|
{
|
||||||
|
x.ShowSubscribe = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x.ShowSubscribe = true;
|
||||||
|
var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s =>
|
||||||
|
s.UserId == shouldHide.UserId && s.RequestId == x.Id && s.RequestType == RequestType.Movie);
|
||||||
|
x.Subscribed = sub != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches the movie request.
|
/// Searches the movie request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -194,9 +217,10 @@ namespace Ombi.Core.Engine
|
||||||
allRequests = await MovieRepository.GetWithUser().ToListAsync();
|
allRequests = await MovieRepository.GetWithUser().ToListAsync();
|
||||||
}
|
}
|
||||||
var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList();
|
var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList();
|
||||||
results.ForEach(x =>
|
results.ForEach(async x =>
|
||||||
{
|
{
|
||||||
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
|
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
|
||||||
|
await CheckForSubscription(shouldHide, x);
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,16 @@ using Ombi.Core.Authentication;
|
||||||
using Ombi.Core.Settings;
|
using Ombi.Core.Settings;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Settings.Settings.Models;
|
using Ombi.Settings.Settings.Models;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
public class MovieSearchEngine : BaseMediaEngine, IMovieEngine
|
public class MovieSearchEngine : BaseMediaEngine, IMovieEngine
|
||||||
{
|
{
|
||||||
public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper,
|
public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper,
|
||||||
ILogger<MovieSearchEngine> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s)
|
ILogger<MovieSearchEngine> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub)
|
||||||
: base(identity, service, r, um, mem, s)
|
: base(identity, service, r, um, mem, s, sub)
|
||||||
{
|
{
|
||||||
MovieApi = movApi;
|
MovieApi = movApi;
|
||||||
Mapper = mapper;
|
Mapper = mapper;
|
||||||
|
|
|
@ -29,7 +29,8 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user,
|
public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user,
|
||||||
INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager,
|
INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager,
|
||||||
ITvSender sender, IAuditRepository audit, IRepository<RequestLog> rl, ISettingsService<OmbiSettings> settings, ICacheService cache) : base(user, requestService, rule, manager, cache, settings)
|
ITvSender sender, IAuditRepository audit, IRepository<RequestLog> rl, ISettingsService<OmbiSettings> settings, ICacheService cache,
|
||||||
|
IRepository<RequestSubscription> sub) : base(user, requestService, rule, manager, cache, settings, sub)
|
||||||
{
|
{
|
||||||
TvApi = tvApi;
|
TvApi = tvApi;
|
||||||
MovieDbApi = movApi;
|
MovieDbApi = movApi;
|
||||||
|
@ -156,6 +157,8 @@ namespace Ombi.Core.Engine
|
||||||
.Skip(position).Take(count).OrderByDescending(x => x.ReleaseDate).ToListAsync();
|
.Skip(position).Take(count).OrderByDescending(x => x.ReleaseDate).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
|
||||||
|
|
||||||
return allRequests;
|
return allRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,25 +184,28 @@ namespace Ombi.Core.Engine
|
||||||
.ThenInclude(x => x.Episodes)
|
.ThenInclude(x => x.Episodes)
|
||||||
.Skip(position).Take(count).ToListAsync();
|
.Skip(position).Take(count).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
|
||||||
return ParseIntoTreeNode(allRequests);
|
return ParseIntoTreeNode(allRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<TvRequests>> GetRequests()
|
public async Task<IEnumerable<TvRequests>> GetRequests()
|
||||||
{
|
{
|
||||||
var shouldHide = await HideFromOtherUsers();
|
var shouldHide = await HideFromOtherUsers();
|
||||||
IQueryable<TvRequests> allRequests;
|
List<TvRequests> allRequests;
|
||||||
if (shouldHide.Hide)
|
if (shouldHide.Hide)
|
||||||
{
|
{
|
||||||
allRequests = TvRepository.Get(shouldHide.UserId);
|
allRequests = await TvRepository.Get(shouldHide.UserId).ToListAsync();
|
||||||
|
|
||||||
FilterChildren(allRequests, shouldHide);
|
FilterChildren(allRequests, shouldHide);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
allRequests = TvRepository.Get();
|
allRequests = await TvRepository.Get().ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
return await allRequests.ToListAsync();
|
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
|
||||||
|
return allRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void FilterChildren(IEnumerable<TvRequests> allRequests, HideResult shouldHide)
|
private static void FilterChildren(IEnumerable<TvRequests> allRequests, HideResult shouldHide)
|
||||||
|
@ -232,6 +238,8 @@ namespace Ombi.Core.Engine
|
||||||
allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync();
|
allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
|
||||||
|
|
||||||
return allRequests;
|
return allRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +256,8 @@ namespace Ombi.Core.Engine
|
||||||
allRequests = TvRepository.Get();
|
allRequests = TvRepository.Get();
|
||||||
}
|
}
|
||||||
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
|
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
|
||||||
|
|
||||||
|
results.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,6 +274,7 @@ namespace Ombi.Core.Engine
|
||||||
allRequests = TvRepository.Get();
|
allRequests = TvRepository.Get();
|
||||||
}
|
}
|
||||||
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
|
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
|
||||||
|
results.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
|
||||||
return ParseIntoTreeNode(results);
|
return ParseIntoTreeNode(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,6 +456,29 @@ namespace Ombi.Core.Engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task CheckForSubscription(HideResult shouldHide, TvRequests x)
|
||||||
|
{
|
||||||
|
foreach (var tv in x.ChildRequests)
|
||||||
|
{
|
||||||
|
await CheckForSubscription(shouldHide, tv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckForSubscription(HideResult shouldHide, ChildRequests x)
|
||||||
|
{
|
||||||
|
if (shouldHide.UserId == x.RequestedUserId)
|
||||||
|
{
|
||||||
|
x.ShowSubscribe = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x.ShowSubscribe = true;
|
||||||
|
var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s =>
|
||||||
|
s.UserId == shouldHide.UserId && s.RequestId == x.Id && s.RequestType == RequestType.TvShow);
|
||||||
|
x.Subscribed = sub != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest)
|
private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest)
|
||||||
{
|
{
|
||||||
// Add the child
|
// Add the child
|
||||||
|
|
|
@ -20,6 +20,7 @@ using Microsoft.Extensions.Caching.Memory;
|
||||||
using Ombi.Core.Authentication;
|
using Ombi.Core.Authentication;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Settings.Settings.Models;
|
using Ombi.Settings.Settings.Models;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
|
@ -27,8 +28,8 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService<PlexSettings> plexSettings,
|
public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService<PlexSettings> plexSettings,
|
||||||
ISettingsService<EmbySettings> embySettings, IPlexContentRepository repo, IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um,
|
ISettingsService<EmbySettings> embySettings, IPlexContentRepository repo, IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um,
|
||||||
ICacheService memCache, ISettingsService<OmbiSettings> s)
|
ICacheService memCache, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub)
|
||||||
: base(identity, service, r, um, memCache, s)
|
: base(identity, service, r, um, memCache, s, sub)
|
||||||
{
|
{
|
||||||
TvMazeApi = tvMaze;
|
TvMazeApi = tvMaze;
|
||||||
Mapper = mapper;
|
Mapper = mapper;
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace Ombi.Core.Helpers
|
||||||
RequestedUserId = userId,
|
RequestedUserId = userId,
|
||||||
SeasonRequests = new List<SeasonRequests>(),
|
SeasonRequests = new List<SeasonRequests>(),
|
||||||
Title = ShowInfo.name,
|
Title = ShowInfo.name,
|
||||||
SeriesType = ShowInfo.type.Equals("Animation", StringComparison.CurrentCultureIgnoreCase) ? SeriesType.Anime : SeriesType.Standard
|
SeriesType = ShowInfo.genres.Any( s => s.Equals("Anime", StringComparison.OrdinalIgnoreCase)) ? SeriesType.Anime : SeriesType.Standard
|
||||||
};
|
};
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -152,6 +152,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IMattermostNotification, MattermostNotification>();
|
services.AddTransient<IMattermostNotification, MattermostNotification>();
|
||||||
services.AddTransient<IPushoverNotification, PushoverNotification>();
|
services.AddTransient<IPushoverNotification, PushoverNotification>();
|
||||||
services.AddTransient<ITelegramNotification, TelegramNotification>();
|
services.AddTransient<ITelegramNotification, TelegramNotification>();
|
||||||
|
services.AddTransient<IMobileNotification, MobileNotification>();
|
||||||
services.AddTransient<IChangeLogProcessor, ChangeLogProcessor>();
|
services.AddTransient<IChangeLogProcessor, ChangeLogProcessor>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,12 +157,12 @@
|
||||||
|
|
||||||
<!-- START CENTERED WHITE CONTAINER -->
|
<!-- START CENTERED WHITE CONTAINER -->
|
||||||
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">Ombi Recently Added</span>
|
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">Ombi Recently Added</span>
|
||||||
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; border-radius: 3px;" width="100%">
|
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-radius: 3px;">
|
||||||
|
|
||||||
<!-- START MAIN CONTENT AREA -->
|
<!-- START MAIN CONTENT AREA -->
|
||||||
<tr>
|
<tr>
|
||||||
<td class="wrapper" style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;" valign="top">
|
<td class="wrapper" style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;" valign="top">
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
|
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; max-width: 1042px; width: 100%;">
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<img src="{@LOGO}" width="400px" text-align="center"/>
|
<img src="{@LOGO}" width="400px" text-align="center"/>
|
||||||
|
|
|
@ -20,8 +20,8 @@ namespace Ombi.Notifications.Agents
|
||||||
{
|
{
|
||||||
public DiscordNotification(IDiscordApi api, ISettingsService<DiscordNotificationSettings> sn,
|
public DiscordNotification(IDiscordApi api, ISettingsService<DiscordNotificationSettings> sn,
|
||||||
ILogger<DiscordNotification> log, INotificationTemplatesRepository r,
|
ILogger<DiscordNotification> log, INotificationTemplatesRepository r,
|
||||||
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s)
|
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub)
|
||||||
: base(sn, r, m, t,s,log)
|
: base(sn, r, m, t,s,log, sub)
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MailKit.Net.Smtp;
|
using MailKit.Net.Smtp;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MimeKit;
|
using MimeKit;
|
||||||
using Ombi.Core.Settings;
|
using Ombi.Core.Settings;
|
||||||
|
@ -21,7 +22,7 @@ namespace Ombi.Notifications.Agents
|
||||||
public class EmailNotification : BaseNotification<EmailNotificationSettings>, IEmailNotification
|
public class EmailNotification : BaseNotification<EmailNotificationSettings>, IEmailNotification
|
||||||
{
|
{
|
||||||
public EmailNotification(ISettingsService<EmailNotificationSettings> settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService<CustomizationSettings> c,
|
public EmailNotification(ISettingsService<EmailNotificationSettings> settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService<CustomizationSettings> c,
|
||||||
ILogger<EmailNotification> log, UserManager<OmbiUser> um) : base(settings, r, m, t, c, log)
|
ILogger<EmailNotification> log, UserManager<OmbiUser> um, IRepository<RequestSubscription> sub) : base(settings, r, m, t, c, log, sub)
|
||||||
{
|
{
|
||||||
EmailProvider = prov;
|
EmailProvider = prov;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
|
@ -227,10 +228,12 @@ namespace Ombi.Notifications.Agents
|
||||||
var plaintext = await LoadPlainTextMessage(NotificationType.RequestDeclined, model, settings);
|
var plaintext = await LoadPlainTextMessage(NotificationType.RequestDeclined, model, settings);
|
||||||
message.Other.Add("PlainTextBody", plaintext);
|
message.Other.Add("PlainTextBody", plaintext);
|
||||||
|
|
||||||
|
await SendToSubscribers(settings, message);
|
||||||
message.To = model.RequestType == RequestType.Movie
|
message.To = model.RequestType == RequestType.Movie
|
||||||
? MovieRequest.RequestedUser.Email
|
? MovieRequest.RequestedUser.Email
|
||||||
: TvRequest.RequestedUser.Email;
|
: TvRequest.RequestedUser.Email;
|
||||||
await Send(message, settings);
|
await Send(message, settings);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task RequestApproved(NotificationOptions model, EmailNotificationSettings settings)
|
protected override async Task RequestApproved(NotificationOptions model, EmailNotificationSettings settings)
|
||||||
|
@ -244,12 +247,32 @@ namespace Ombi.Notifications.Agents
|
||||||
var plaintext = await LoadPlainTextMessage(NotificationType.RequestApproved, model, settings);
|
var plaintext = await LoadPlainTextMessage(NotificationType.RequestApproved, model, settings);
|
||||||
message.Other.Add("PlainTextBody", plaintext);
|
message.Other.Add("PlainTextBody", plaintext);
|
||||||
|
|
||||||
|
await SendToSubscribers(settings, message);
|
||||||
|
|
||||||
message.To = model.RequestType == RequestType.Movie
|
message.To = model.RequestType == RequestType.Movie
|
||||||
? MovieRequest.RequestedUser.Email
|
? MovieRequest.RequestedUser.Email
|
||||||
: TvRequest.RequestedUser.Email;
|
: TvRequest.RequestedUser.Email;
|
||||||
await Send(message, settings);
|
await Send(message, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SendToSubscribers(EmailNotificationSettings settings, NotificationMessage message)
|
||||||
|
{
|
||||||
|
if (await SubsribedUsers.AnyAsync())
|
||||||
|
{
|
||||||
|
foreach (var user in SubsribedUsers)
|
||||||
|
{
|
||||||
|
if (user.Email.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.To = user.Email;
|
||||||
|
|
||||||
|
await Send(message, settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task AvailableRequest(NotificationOptions model, EmailNotificationSettings settings)
|
protected override async Task AvailableRequest(NotificationOptions model, EmailNotificationSettings settings)
|
||||||
{
|
{
|
||||||
var message = await LoadTemplate(NotificationType.RequestAvailable, model, settings);
|
var message = await LoadTemplate(NotificationType.RequestAvailable, model, settings);
|
||||||
|
@ -260,7 +283,7 @@ namespace Ombi.Notifications.Agents
|
||||||
|
|
||||||
var plaintext = await LoadPlainTextMessage(NotificationType.RequestAvailable, model, settings);
|
var plaintext = await LoadPlainTextMessage(NotificationType.RequestAvailable, model, settings);
|
||||||
message.Other.Add("PlainTextBody", plaintext);
|
message.Other.Add("PlainTextBody", plaintext);
|
||||||
|
await SendToSubscribers(settings, message);
|
||||||
message.To = model.RequestType == RequestType.Movie
|
message.To = model.RequestType == RequestType.Movie
|
||||||
? MovieRequest.RequestedUser.Email
|
? MovieRequest.RequestedUser.Email
|
||||||
: TvRequest.RequestedUser.Email;
|
: TvRequest.RequestedUser.Email;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Ombi.Notifications.Agents
|
||||||
|
{
|
||||||
|
public interface IMobileNotification : INotification
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ namespace Ombi.Notifications.Agents
|
||||||
public class MattermostNotification : BaseNotification<MattermostNotificationSettings>, IMattermostNotification
|
public class MattermostNotification : BaseNotification<MattermostNotificationSettings>, IMattermostNotification
|
||||||
{
|
{
|
||||||
public MattermostNotification(IMattermostApi api, ISettingsService<MattermostNotificationSettings> sn, ILogger<MattermostNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
public MattermostNotification(IMattermostApi api, ISettingsService<MattermostNotificationSettings> sn, ILogger<MattermostNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||||
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s,log)
|
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) : base(sn, r, m, t,s,log, sub)
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
|
|
|
@ -18,11 +18,11 @@ using Ombi.Store.Repository.Requests;
|
||||||
|
|
||||||
namespace Ombi.Notifications.Agents
|
namespace Ombi.Notifications.Agents
|
||||||
{
|
{
|
||||||
public class MobileNotification : BaseNotification<MobileNotificationSettings>
|
public class MobileNotification : BaseNotification<MobileNotificationSettings>, IMobileNotification
|
||||||
{
|
{
|
||||||
public MobileNotification(IOneSignalApi api, ISettingsService<MobileNotificationSettings> sn, ILogger<MobileNotification> log, INotificationTemplatesRepository r,
|
public MobileNotification(IOneSignalApi api, ISettingsService<MobileNotificationSettings> sn, ILogger<MobileNotification> log, INotificationTemplatesRepository r,
|
||||||
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<NotificationUserId> notification,
|
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<NotificationUserId> notification,
|
||||||
UserManager<OmbiUser> um) : base(sn, r, m, t, s,log)
|
UserManager<OmbiUser> um, IRepository<RequestSubscription> sub) : base(sn, r, m, t, s,log, sub)
|
||||||
{
|
{
|
||||||
_api = api;
|
_api = api;
|
||||||
_logger = log;
|
_logger = log;
|
||||||
|
@ -167,6 +167,7 @@ namespace Ombi.Notifications.Agents
|
||||||
|
|
||||||
// Send to user
|
// Send to user
|
||||||
var playerIds = GetUsers(model, NotificationType.RequestDeclined);
|
var playerIds = GetUsers(model, NotificationType.RequestDeclined);
|
||||||
|
await AddSubscribedUsers(playerIds);
|
||||||
await Send(playerIds, notification, settings);
|
await Send(playerIds, notification, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +186,8 @@ namespace Ombi.Notifications.Agents
|
||||||
|
|
||||||
// Send to user
|
// Send to user
|
||||||
var playerIds = GetUsers(model, NotificationType.RequestApproved);
|
var playerIds = GetUsers(model, NotificationType.RequestApproved);
|
||||||
|
|
||||||
|
await AddSubscribedUsers(playerIds);
|
||||||
await Send(playerIds, notification, settings);
|
await Send(playerIds, notification, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +205,8 @@ namespace Ombi.Notifications.Agents
|
||||||
};
|
};
|
||||||
// Send to user
|
// Send to user
|
||||||
var playerIds = GetUsers(model, NotificationType.RequestAvailable);
|
var playerIds = GetUsers(model, NotificationType.RequestAvailable);
|
||||||
|
|
||||||
|
await AddSubscribedUsers(playerIds);
|
||||||
await Send(playerIds, notification, settings);
|
await Send(playerIds, notification, settings);
|
||||||
}
|
}
|
||||||
protected override Task Send(NotificationMessage model, MobileNotificationSettings settings)
|
protected override Task Send(NotificationMessage model, MobileNotificationSettings settings)
|
||||||
|
@ -227,7 +232,13 @@ namespace Ombi.Notifications.Agents
|
||||||
Message = message,
|
Message = message,
|
||||||
};
|
};
|
||||||
// Send to user
|
// Send to user
|
||||||
var playerIds = await GetAdmins(NotificationType.RequestAvailable);
|
var user = await _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefaultAsync(x => x.Id.Equals(model.UserId));
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerIds = user.NotificationUserIds.Select(x => x.PlayerId).ToList();
|
||||||
await Send(playerIds, notification, settings);
|
await Send(playerIds, notification, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,6 +280,20 @@ namespace Ombi.Notifications.Agents
|
||||||
return playerIds;
|
return playerIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task AddSubscribedUsers(List<string> playerIds)
|
||||||
|
{
|
||||||
|
if (await SubsribedUsers.AnyAsync())
|
||||||
|
{
|
||||||
|
foreach (var user in SubsribedUsers.Include(x => x.NotificationUserIds))
|
||||||
|
{
|
||||||
|
var notificationId = user.NotificationUserIds;
|
||||||
|
if (notificationId.Any())
|
||||||
|
{
|
||||||
|
playerIds.AddRange(notificationId.Select(x => x.PlayerId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,7 +17,7 @@ namespace Ombi.Notifications.Agents
|
||||||
public class PushbulletNotification : BaseNotification<PushbulletSettings>, IPushbulletNotification
|
public class PushbulletNotification : BaseNotification<PushbulletSettings>, IPushbulletNotification
|
||||||
{
|
{
|
||||||
public PushbulletNotification(IPushbulletApi api, ISettingsService<PushbulletSettings> sn, ILogger<PushbulletNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
public PushbulletNotification(IPushbulletApi api, ISettingsService<PushbulletSettings> sn, ILogger<PushbulletNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||||
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s,log)
|
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) : base(sn, r, m, t,s,log, sub)
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents
|
||||||
public class PushoverNotification : BaseNotification<PushoverSettings>, IPushoverNotification
|
public class PushoverNotification : BaseNotification<PushoverSettings>, IPushoverNotification
|
||||||
{
|
{
|
||||||
public PushoverNotification(IPushoverApi api, ISettingsService<PushoverSettings> sn, ILogger<PushoverNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
public PushoverNotification(IPushoverApi api, ISettingsService<PushoverSettings> sn, ILogger<PushoverNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||||
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t, s, log)
|
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) : base(sn, r, m, t, s, log, sub)
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents
|
||||||
public class SlackNotification : BaseNotification<SlackNotificationSettings>, ISlackNotification
|
public class SlackNotification : BaseNotification<SlackNotificationSettings>, ISlackNotification
|
||||||
{
|
{
|
||||||
public SlackNotification(ISlackApi api, ISettingsService<SlackNotificationSettings> sn, ILogger<SlackNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
public SlackNotification(ISlackApi api, ISettingsService<SlackNotificationSettings> sn, ILogger<SlackNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
|
||||||
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t, s, log)
|
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) : base(sn, r, m, t, s, log, sub)
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
|
|
|
@ -18,7 +18,8 @@ namespace Ombi.Notifications.Agents
|
||||||
{
|
{
|
||||||
public TelegramNotification(ITelegramApi api, ISettingsService<TelegramSettings> sn, ILogger<TelegramNotification> log,
|
public TelegramNotification(ITelegramApi api, ISettingsService<TelegramSettings> sn, ILogger<TelegramNotification> log,
|
||||||
INotificationTemplatesRepository r, IMovieRequestRepository m,
|
INotificationTemplatesRepository r, IMovieRequestRepository m,
|
||||||
ITvRequestRepository t, ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s,log)
|
ITvRequestRepository t, ISettingsService<CustomizationSettings> s
|
||||||
|
, IRepository<RequestSubscription> sub) : base(sn, r, m, t,s,log, sub)
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
Logger = log;
|
Logger = log;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
@ -17,7 +19,7 @@ namespace Ombi.Notifications.Interfaces
|
||||||
public abstract class BaseNotification<T> : INotification where T : Settings.Settings.Models.Settings, new()
|
public abstract class BaseNotification<T> : INotification where T : Settings.Settings.Models.Settings, new()
|
||||||
{
|
{
|
||||||
protected BaseNotification(ISettingsService<T> settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv,
|
protected BaseNotification(ISettingsService<T> settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv,
|
||||||
ISettingsService<CustomizationSettings> customization, ILogger<BaseNotification<T>> log)
|
ISettingsService<CustomizationSettings> customization, ILogger<BaseNotification<T>> log, IRepository<RequestSubscription> sub)
|
||||||
{
|
{
|
||||||
Settings = settings;
|
Settings = settings;
|
||||||
TemplateRepository = templateRepo;
|
TemplateRepository = templateRepo;
|
||||||
|
@ -26,6 +28,7 @@ namespace Ombi.Notifications.Interfaces
|
||||||
CustomizationSettings = customization;
|
CustomizationSettings = customization;
|
||||||
Settings.ClearCache();
|
Settings.ClearCache();
|
||||||
CustomizationSettings.ClearCache();
|
CustomizationSettings.ClearCache();
|
||||||
|
RequestSubscription = sub;
|
||||||
_log = log;
|
_log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,12 +37,14 @@ namespace Ombi.Notifications.Interfaces
|
||||||
protected IMovieRequestRepository MovieRepository { get; }
|
protected IMovieRequestRepository MovieRepository { get; }
|
||||||
protected ITvRequestRepository TvRepository { get; }
|
protected ITvRequestRepository TvRepository { get; }
|
||||||
protected CustomizationSettings Customization { get; set; }
|
protected CustomizationSettings Customization { get; set; }
|
||||||
|
protected IRepository<RequestSubscription> RequestSubscription { get; set; }
|
||||||
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
|
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
|
||||||
private readonly ILogger<BaseNotification<T>> _log;
|
private readonly ILogger<BaseNotification<T>> _log;
|
||||||
|
|
||||||
|
|
||||||
protected ChildRequests TvRequest { get; set; }
|
protected ChildRequests TvRequest { get; set; }
|
||||||
protected MovieRequests MovieRequest { get; set; }
|
protected MovieRequests MovieRequest { get; set; }
|
||||||
|
protected IQueryable<OmbiUser> SubsribedUsers { get; private set; }
|
||||||
|
|
||||||
public abstract string NotificationName { get; }
|
public abstract string NotificationName { get; }
|
||||||
|
|
||||||
|
@ -68,6 +73,7 @@ namespace Ombi.Notifications.Interfaces
|
||||||
if (model.RequestId > 0)
|
if (model.RequestId > 0)
|
||||||
{
|
{
|
||||||
await LoadRequest(model.RequestId, model.RequestType);
|
await LoadRequest(model.RequestId, model.RequestType);
|
||||||
|
SubsribedUsers = GetSubscriptions(model.RequestId, model.RequestType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Customization = await CustomizationSettings.GetSettingsAsync();
|
Customization = await CustomizationSettings.GetSettingsAsync();
|
||||||
|
@ -159,6 +165,12 @@ namespace Ombi.Notifications.Interfaces
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected IQueryable<OmbiUser> GetSubscriptions(int requestId, RequestType type)
|
||||||
|
{
|
||||||
|
var subs = RequestSubscription.GetAll().Include(x => x.User).Where(x => x.RequestId == requestId && type == x.RequestType);
|
||||||
|
return subs.Select(x => x.User);
|
||||||
|
}
|
||||||
|
|
||||||
private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template)
|
private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template)
|
||||||
{
|
{
|
||||||
var resolver = new NotificationMessageResolver();
|
var resolver = new NotificationMessageResolver();
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
protected virtual void AddBackgroundInsideTable(StringBuilder sb, string url)
|
protected virtual void AddBackgroundInsideTable(StringBuilder sb, string url)
|
||||||
{
|
{
|
||||||
sb.Append("<td align=\"center\" valign=\"top\" class=\"media-card\" style=\"font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 12px; vertical-align: top; padding: 3px; width: 502px; min-width: 500px; max-width: 500px; height: 235px; \">");
|
sb.Append("<td align=\"center\" valign=\"top\" class=\"media-card\" style=\"font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 12px; vertical-align: top; padding: 3px; width: 502px; min-width: 500px; max-width: 500px; height: 235px; \">");
|
||||||
sb.AppendFormat("<table class=\"card-bg\" style=\"background-image: url({0}); border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #1f1f1f; background-position: center; background-size: cover; background-repeat: no-repeat; background-clip: padding-box; border: 2px solid rgba(255,118,27,.4); \">", url);
|
sb.AppendFormat("<table class=\"card-bg\" style=\"background-image: url({0}); border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #1f1f1f; background-position: center; background-size: cover; background-repeat: no-repeat; background-clip: padding-box; border: 2px solid rgba(255,118,27,.4); height: 248px; max-height: 500px; \">", url);
|
||||||
sb.Append("<tr>");
|
sb.Append("<tr>");
|
||||||
sb.Append("<td>");
|
sb.Append("<td>");
|
||||||
sb.Append("<table class=\"bg-tint\" style=\"background-color: rgba(0, 0, 0, .6); position: absolute; width: 490px; height: 239px; \">");
|
sb.Append("<table class=\"bg-tint\" style=\"background-color: rgba(0, 0, 0, .6); position: absolute; width: 490px; height: 239px; \">");
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
using System.Threading.Tasks;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ombi.Schedule.Jobs.Ombi
|
namespace Ombi.Schedule.Jobs.Ombi
|
||||||
{
|
{
|
||||||
public interface IRefreshMetadata : IBaseJob
|
public interface IRefreshMetadata : IBaseJob
|
||||||
{
|
{
|
||||||
Task Start();
|
Task Start();
|
||||||
|
Task ProcessPlexServerContent(IEnumerable<int> contentIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -306,7 +306,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie);
|
var embyMovies = embyContentToSend.Where(x => x.Type == EmbyMediaType.Movie);
|
||||||
if ((plexMovies.Any() || embyMovies.Any()) && !settings.DisableMovies)
|
if ((plexMovies.Any() || embyMovies.Any()) && !settings.DisableMovies)
|
||||||
{
|
{
|
||||||
sb.Append("<h1 style=\"text-align: center;\">New Movies</h1><br /><br />");
|
sb.Append("<h1 style=\"text-align: center; max-width: 1042px;\">New Movies</h1><br /><br />");
|
||||||
sb.Append(
|
sb.Append(
|
||||||
"<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
|
"<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
|
||||||
sb.Append("<tr>");
|
sb.Append("<tr>");
|
||||||
|
@ -324,7 +324,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
|
|
||||||
if ((plexEpisodes.Any() || embyEp.Any()) && !settings.DisableTv)
|
if ((plexEpisodes.Any() || embyEp.Any()) && !settings.DisableTv)
|
||||||
{
|
{
|
||||||
sb.Append("<br /><br /><h1 style=\"text-align: center;\">New TV</h1><br /><br />");
|
sb.Append("<br /><br /><h1 style=\"text-align: center; max-width: 1042px;\">New TV</h1><br /><br />");
|
||||||
sb.Append(
|
sb.Append(
|
||||||
"<table class=\"tv-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
|
"<table class=\"tv-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
|
||||||
sb.Append("<tr>");
|
sb.Append("<tr>");
|
||||||
|
@ -588,7 +588,6 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
{
|
{
|
||||||
AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}");
|
AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}");
|
||||||
}
|
}
|
||||||
count += 1;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -598,6 +597,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
EndLoopHtml(sb);
|
EndLoopHtml(sb);
|
||||||
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count == 2)
|
if (count == 2)
|
||||||
|
@ -752,7 +752,6 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
{
|
{
|
||||||
AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}");
|
AddGenres(sb, $"Genres: {string.Join(", ", info.genres.Select(x => x.ToString()).ToArray())}");
|
||||||
}
|
}
|
||||||
count += 1;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -762,6 +761,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
EndLoopHtml(sb);
|
EndLoopHtml(sb);
|
||||||
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count == 2)
|
if (count == 2)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
@ -17,7 +18,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
{
|
{
|
||||||
public RefreshMetadata(IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo,
|
public RefreshMetadata(IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo,
|
||||||
ILogger<RefreshMetadata> log, ITvMazeApi tvApi, ISettingsService<PlexSettings> plexSettings,
|
ILogger<RefreshMetadata> log, ITvMazeApi tvApi, ISettingsService<PlexSettings> plexSettings,
|
||||||
IMovieDbApi movieApi)
|
IMovieDbApi movieApi, ISettingsService<EmbySettings> embySettings)
|
||||||
{
|
{
|
||||||
_plexRepo = plexRepo;
|
_plexRepo = plexRepo;
|
||||||
_embyRepo = embyRepo;
|
_embyRepo = embyRepo;
|
||||||
|
@ -25,6 +26,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
_movieApi = movieApi;
|
_movieApi = movieApi;
|
||||||
_tvApi = tvApi;
|
_tvApi = tvApi;
|
||||||
_plexSettings = plexSettings;
|
_plexSettings = plexSettings;
|
||||||
|
_embySettings = embySettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IPlexContentRepository _plexRepo;
|
private readonly IPlexContentRepository _plexRepo;
|
||||||
|
@ -33,6 +35,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
private readonly IMovieDbApi _movieApi;
|
private readonly IMovieDbApi _movieApi;
|
||||||
private readonly ITvMazeApi _tvApi;
|
private readonly ITvMazeApi _tvApi;
|
||||||
private readonly ISettingsService<PlexSettings> _plexSettings;
|
private readonly ISettingsService<PlexSettings> _plexSettings;
|
||||||
|
private readonly ISettingsService<EmbySettings> _embySettings;
|
||||||
|
|
||||||
public async Task Start()
|
public async Task Start()
|
||||||
{
|
{
|
||||||
|
@ -43,6 +46,11 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
if (settings.Enable)
|
if (settings.Enable)
|
||||||
{
|
{
|
||||||
await StartPlex();
|
await StartPlex();
|
||||||
|
}
|
||||||
|
|
||||||
|
var embySettings = await _embySettings.GetSettingsAsync();
|
||||||
|
if (embySettings.Enable)
|
||||||
|
{
|
||||||
await StartEmby();
|
await StartEmby();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,12 +61,45 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartPlex()
|
public async Task ProcessPlexServerContent(IEnumerable<int> contentIds)
|
||||||
{
|
{
|
||||||
await StartPlexMovies();
|
_log.LogInformation("Starting the Metadata refresh from RecentlyAddedSync");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var settings = await _plexSettings.GetSettingsAsync();
|
||||||
|
if (settings.Enable)
|
||||||
|
{
|
||||||
|
await StartPlexWithKnownContent(contentIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_log.LogError(e, "Exception when refreshing the Plex Metadata");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartPlexWithKnownContent(IEnumerable<int> contentids)
|
||||||
|
{
|
||||||
|
var everything = _plexRepo.GetAll().Where(x => contentids.Contains(x.Id));
|
||||||
|
var allMovies = everything.Where(x => x.Type == PlexMediaTypeEntity.Movie);
|
||||||
|
await StartPlexMovies(allMovies);
|
||||||
|
|
||||||
// Now Tv
|
// Now Tv
|
||||||
await StartPlexTv();
|
var allTv = everything.Where(x => x.Type == PlexMediaTypeEntity.Show);
|
||||||
|
await StartPlexTv(allTv);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartPlex()
|
||||||
|
{
|
||||||
|
var allMovies = _plexRepo.GetAll().Where(x =>
|
||||||
|
x.Type == PlexMediaTypeEntity.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue()));
|
||||||
|
await StartPlexMovies(allMovies);
|
||||||
|
|
||||||
|
// Now Tv
|
||||||
|
var allTv = _plexRepo.GetAll().Where(x =>
|
||||||
|
x.Type == PlexMediaTypeEntity.Show && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue()));
|
||||||
|
await StartPlexTv(allTv);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartEmby()
|
private async Task StartEmby()
|
||||||
|
@ -67,10 +108,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
await StartEmbyTv();
|
await StartEmbyTv();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartPlexTv()
|
private async Task StartPlexTv(IQueryable<PlexServerContent> allTv)
|
||||||
{
|
{
|
||||||
var allTv = _plexRepo.GetAll().Where(x =>
|
|
||||||
x.Type == PlexMediaTypeEntity.Show && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue()));
|
|
||||||
var tvCount = 0;
|
var tvCount = 0;
|
||||||
foreach (var show in allTv)
|
foreach (var show in allTv)
|
||||||
{
|
{
|
||||||
|
@ -147,10 +186,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
await _embyRepo.SaveChangesAsync();
|
await _embyRepo.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartPlexMovies()
|
private async Task StartPlexMovies(IQueryable<PlexServerContent> allMovies)
|
||||||
{
|
{
|
||||||
var allMovies = _plexRepo.GetAll().Where(x =>
|
|
||||||
x.Type == PlexMediaTypeEntity.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue()));
|
|
||||||
int movieCount = 0;
|
int movieCount = 0;
|
||||||
foreach (var movie in allMovies)
|
foreach (var movie in allMovies)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.Plex.Models;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Schedule.Jobs.Plex.Interfaces
|
namespace Ombi.Schedule.Jobs.Plex.Interfaces
|
||||||
{
|
{
|
||||||
public interface IPlexEpisodeSync : IBaseJob
|
public interface IPlexEpisodeSync : IBaseJob
|
||||||
{
|
{
|
||||||
Task Start();
|
Task Start();
|
||||||
|
Task ProcessEpsiodes(Metadata[] episodes, IQueryable<PlexEpisode> currentEpisodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -77,46 +77,86 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
Logger.LogError("Plex Settings are not valid");
|
Logger.LogError("Plex Settings are not valid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var processedContent = new HashSet<int>();
|
||||||
Logger.LogInformation("Starting Plex Content Cacher");
|
Logger.LogInformation("Starting Plex Content Cacher");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await StartTheCache(plexSettings, recentlyAddedSearch);
|
if (recentlyAddedSearch)
|
||||||
|
{
|
||||||
|
var result = await StartTheCache(plexSettings, true);
|
||||||
|
foreach (var r in result)
|
||||||
|
{
|
||||||
|
processedContent.Add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await StartTheCache(plexSettings, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.LogWarning(LoggingEvents.PlexContentCacher, e, "Exception thrown when attempting to cache the Plex Content");
|
Logger.LogWarning(LoggingEvents.PlexContentCacher, e, "Exception thrown when attempting to cache the Plex Content");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!recentlyAddedSearch)
|
||||||
|
{
|
||||||
Logger.LogInformation("Starting EP Cacher");
|
Logger.LogInformation("Starting EP Cacher");
|
||||||
BackgroundJob.Enqueue(() => EpisodeSync.Start());
|
BackgroundJob.Enqueue(() => EpisodeSync.Start());
|
||||||
BackgroundJob.Enqueue(() => Metadata.Start());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartTheCache(PlexSettings plexSettings, bool recentlyAddedSearch)
|
if (processedContent.Any() && recentlyAddedSearch)
|
||||||
{
|
{
|
||||||
|
// Just check what we send it
|
||||||
|
BackgroundJob.Enqueue(() => Metadata.ProcessPlexServerContent(processedContent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<int>> StartTheCache(PlexSettings plexSettings, bool recentlyAddedSearch)
|
||||||
|
{
|
||||||
|
var processedContent = new HashSet<int>();
|
||||||
foreach (var servers in plexSettings.Servers ?? new List<PlexServers>())
|
foreach (var servers in plexSettings.Servers ?? new List<PlexServers>())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Logger.LogInformation("Starting to cache the content on server {0}", servers.Name);
|
Logger.LogInformation("Starting to cache the content on server {0}", servers.Name);
|
||||||
await ProcessServer(servers, recentlyAddedSearch);
|
|
||||||
|
if (recentlyAddedSearch)
|
||||||
|
{
|
||||||
|
// If it's recently added search then we want the results to pass to the metadata job
|
||||||
|
// This way the metadata job is smaller in size to process, it only need to look at newly added shit
|
||||||
|
var result = await ProcessServer(servers, true);
|
||||||
|
foreach (var plexServerContent in result)
|
||||||
|
{
|
||||||
|
processedContent.Add(plexServerContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ProcessServer(servers, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.LogWarning(LoggingEvents.PlexContentCacher, e, "Exception thrown when attempting to cache the Plex Content in server {0}", servers.Name);
|
Logger.LogWarning(LoggingEvents.PlexContentCacher, e, "Exception thrown when attempting to cache the Plex Content in server {0}", servers.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return processedContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessServer(PlexServers servers, bool recentlyAddedSearch)
|
private async Task<IEnumerable<int>> ProcessServer(PlexServers servers, bool recentlyAddedSearch)
|
||||||
{
|
{
|
||||||
|
var processedContent = new HashSet<int>();
|
||||||
Logger.LogInformation("Getting all content from server {0}", servers.Name);
|
Logger.LogInformation("Getting all content from server {0}", servers.Name);
|
||||||
var allContent = await GetAllContent(servers, recentlyAddedSearch);
|
var allContent = await GetAllContent(servers, recentlyAddedSearch);
|
||||||
Logger.LogInformation("We found {0} items", allContent.Count);
|
Logger.LogInformation("We found {0} items", allContent.Count);
|
||||||
|
|
||||||
// Let's now process this.
|
// Let's now process this.
|
||||||
var contentToAdd = new HashSet<PlexServerContent>();
|
var contentToAdd = new HashSet<PlexServerContent>();
|
||||||
|
|
||||||
|
var allEps = Repo.GetAllEpisodes();
|
||||||
|
|
||||||
foreach (var content in allContent)
|
foreach (var content in allContent)
|
||||||
{
|
{
|
||||||
if (content.viewGroup.Equals(PlexMediaType.Episode.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
if (content.viewGroup.Equals(PlexMediaType.Episode.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
@ -133,8 +173,10 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ProcessTvShow(servers, show, contentToAdd, recentlyAddedSearch);
|
await ProcessTvShow(servers, show, contentToAdd, recentlyAddedSearch, processedContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await EpisodeSync.ProcessEpsiodes(content.Metadata, allEps);
|
||||||
}
|
}
|
||||||
if (content.viewGroup.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
if (content.viewGroup.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
|
@ -142,7 +184,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
Logger.LogInformation("Processing TV Shows");
|
Logger.LogInformation("Processing TV Shows");
|
||||||
foreach (var show in content.Metadata ?? new Metadata[] { })
|
foreach (var show in content.Metadata ?? new Metadata[] { })
|
||||||
{
|
{
|
||||||
await ProcessTvShow(servers, show, contentToAdd, recentlyAddedSearch);
|
await ProcessTvShow(servers, show, contentToAdd, recentlyAddedSearch, processedContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (content.viewGroup.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
if (content.viewGroup.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
@ -212,6 +254,10 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
if (contentToAdd.Count > 500)
|
if (contentToAdd.Count > 500)
|
||||||
{
|
{
|
||||||
await Repo.AddRange(contentToAdd);
|
await Repo.AddRange(contentToAdd);
|
||||||
|
foreach (var c in contentToAdd)
|
||||||
|
{
|
||||||
|
processedContent.Add(c.Id);
|
||||||
|
}
|
||||||
contentToAdd.Clear();
|
contentToAdd.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,6 +265,10 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
if (contentToAdd.Count > 500)
|
if (contentToAdd.Count > 500)
|
||||||
{
|
{
|
||||||
await Repo.AddRange(contentToAdd);
|
await Repo.AddRange(contentToAdd);
|
||||||
|
foreach (var c in contentToAdd)
|
||||||
|
{
|
||||||
|
processedContent.Add(c.Id);
|
||||||
|
}
|
||||||
contentToAdd.Clear();
|
contentToAdd.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,10 +276,16 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
if (contentToAdd.Any())
|
if (contentToAdd.Any())
|
||||||
{
|
{
|
||||||
await Repo.AddRange(contentToAdd);
|
await Repo.AddRange(contentToAdd);
|
||||||
|
foreach (var c in contentToAdd)
|
||||||
|
{
|
||||||
|
processedContent.Add(c.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessTvShow(PlexServers servers, Metadata show, HashSet<PlexServerContent> contentToAdd, bool recentlyAdded)
|
return processedContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ProcessTvShow(PlexServers servers, Metadata show, HashSet<PlexServerContent> contentToAdd, bool recentlyAdded, HashSet<int> contentProcessed)
|
||||||
{
|
{
|
||||||
var seasonList = await PlexApi.GetSeasons(servers.PlexAuthToken, servers.FullUri,
|
var seasonList = await PlexApi.GetSeasons(servers.PlexAuthToken, servers.FullUri,
|
||||||
show.ratingKey);
|
show.ratingKey);
|
||||||
|
@ -412,8 +468,17 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
if (contentToAdd.Count > 500 || recentlyAdded)
|
if (contentToAdd.Count > 500 || recentlyAdded)
|
||||||
{
|
{
|
||||||
await Repo.AddRange(contentToAdd);
|
await Repo.AddRange(contentToAdd);
|
||||||
|
foreach (var plexServerContent in contentToAdd)
|
||||||
|
{
|
||||||
|
contentProcessed.Add(plexServerContent.Id);
|
||||||
|
}
|
||||||
contentToAdd.Clear();
|
contentToAdd.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (contentToAdd.Any())
|
||||||
|
{
|
||||||
|
await Repo.AddRange(contentToAdd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -111,7 +111,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
// 12.03.2017 - I think we should be able to match them now
|
// 12.03.2017 - I think we should be able to match them now
|
||||||
//await _repo.ExecuteSql("DELETE FROM PlexEpisode");
|
//await _repo.ExecuteSql("DELETE FROM PlexEpisode");
|
||||||
|
|
||||||
await ProcessEpsiodes(episodes, currentEpisodes);
|
await ProcessEpsiodes(episodes?.MediaContainer?.Metadata ?? new Metadata[] { }, currentEpisodes);
|
||||||
currentPosition += resultCount;
|
currentPosition += resultCount;
|
||||||
|
|
||||||
while (currentPosition < episodes.MediaContainer.totalSize)
|
while (currentPosition < episodes.MediaContainer.totalSize)
|
||||||
|
@ -119,7 +119,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
var ep = await _api.GetAllEpisodes(settings.PlexAuthToken, settings.FullUri, section.key, currentPosition,
|
var ep = await _api.GetAllEpisodes(settings.PlexAuthToken, settings.FullUri, section.key, currentPosition,
|
||||||
resultCount);
|
resultCount);
|
||||||
|
|
||||||
await ProcessEpsiodes(ep, currentEpisodes);
|
await ProcessEpsiodes(ep?.MediaContainer?.Metadata ?? new Metadata[] { }, currentEpisodes);
|
||||||
_log.LogInformation(LoggingEvents.PlexEpisodeCacher, $"Processed {resultCount} more episodes. Total Remaining {episodes.MediaContainer.totalSize - currentPosition}");
|
_log.LogInformation(LoggingEvents.PlexEpisodeCacher, $"Processed {resultCount} more episodes. Total Remaining {episodes.MediaContainer.totalSize - currentPosition}");
|
||||||
currentPosition += resultCount;
|
currentPosition += resultCount;
|
||||||
}
|
}
|
||||||
|
@ -129,12 +129,12 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
await _repo.SaveChangesAsync();
|
await _repo.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessEpsiodes(PlexContainer episodes, IQueryable<PlexEpisode> currentEpisodes)
|
public async Task ProcessEpsiodes(Metadata[] episodes, IQueryable<PlexEpisode> currentEpisodes)
|
||||||
{
|
{
|
||||||
var ep = new HashSet<PlexEpisode>();
|
var ep = new HashSet<PlexEpisode>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (var episode in episodes?.MediaContainer?.Metadata ?? new Metadata[] { })
|
foreach (var episode in episodes)
|
||||||
{
|
{
|
||||||
// I don't think we need to get the metadata, we only need to get the metadata if we need the provider id (TheTvDbid). Why do we need it for episodes?
|
// I don't think we need to get the metadata, we only need to get the metadata if we need the provider id (TheTvDbid). Why do we need it for episodes?
|
||||||
// We have the parent and grandparent rating keys to link up to the season and series
|
// We have the parent and grandparent rating keys to link up to the season and series
|
||||||
|
|
|
@ -90,15 +90,15 @@ namespace Ombi.Schedule.Processor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return TransformUpdate(release);
|
return TransformUpdate(release,!masterBranch);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private UpdateModel TransformUpdate(Release release)
|
private UpdateModel TransformUpdate(Release release, bool develop)
|
||||||
{
|
{
|
||||||
var newUpdate = new UpdateModel
|
var newUpdate = new UpdateModel
|
||||||
{
|
{
|
||||||
UpdateVersionString = release.Version.Substring(1,8),
|
UpdateVersionString = develop ? release.Version : release.Version.Substring(1,8),
|
||||||
UpdateVersion = release.Version == "(unreleased)" ? 0 : int.Parse(release.Version.Substring(1, 5).Replace(".", "")),
|
UpdateVersion = release.Version == "(unreleased)" ? 0 : int.Parse(release.Version.Substring(1, 5).Replace(".", "")),
|
||||||
UpdateDate = DateTime.Now,
|
UpdateDate = DateTime.Now,
|
||||||
ChangeLogs = new List<ChangeLog>(),
|
ChangeLogs = new List<ChangeLog>(),
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Ombi.Settings.Settings.Models
|
||||||
}
|
}
|
||||||
public static string PlexRecentlyAdded(JobSettings s)
|
public static string PlexRecentlyAdded(JobSettings s)
|
||||||
{
|
{
|
||||||
return Get(s.PlexRecentlyAddedSync, Cron.Hourly(0));
|
return Get(s.PlexRecentlyAddedSync, Cron.MinuteInterval(30));
|
||||||
}
|
}
|
||||||
public static string CouchPotato(JobSettings s)
|
public static string CouchPotato(JobSettings s)
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ namespace Ombi.Settings.Settings.Models
|
||||||
}
|
}
|
||||||
public static string RefreshMetadata(JobSettings s)
|
public static string RefreshMetadata(JobSettings s)
|
||||||
{
|
{
|
||||||
return Get(s.RefreshMetadata, Cron.DayInterval(2));
|
return Get(s.RefreshMetadata, Cron.DayInterval(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string Get(string settings, string defaultCron)
|
private static string Get(string settings, string defaultCron)
|
||||||
|
|
|
@ -42,5 +42,6 @@ namespace Ombi.Store.Context
|
||||||
DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
||||||
DbSet<RequestLog> RequestLogs { get; set; }
|
DbSet<RequestLog> RequestLogs { get; set; }
|
||||||
DbSet<RecentlyAddedLog> RecentlyAddedLogs { get; set; }
|
DbSet<RecentlyAddedLog> RecentlyAddedLogs { get; set; }
|
||||||
|
DbSet<RequestSubscription> RequestSubscription { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -47,6 +47,7 @@ namespace Ombi.Store.Context
|
||||||
public DbSet<SonarrEpisodeCache> SonarrEpisodeCache { get; set; }
|
public DbSet<SonarrEpisodeCache> SonarrEpisodeCache { get; set; }
|
||||||
public DbSet<SickRageCache> SickRageCache { get; set; }
|
public DbSet<SickRageCache> SickRageCache { get; set; }
|
||||||
public DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
public DbSet<SickRageEpisodeCache> SickRageEpisodeCache { get; set; }
|
||||||
|
public DbSet<RequestSubscription> RequestSubscription { get; set; }
|
||||||
|
|
||||||
public DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
public DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace Ombi.Store.Entities
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public bool EmailLogin { get; set; }
|
public bool EmailLogin { get; set; }
|
||||||
|
|
||||||
|
[NotMapped] public bool IsSystemUser => UserType == UserType.SystemUser;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public override string PasswordHash
|
public override string PasswordHash
|
||||||
{
|
{
|
||||||
|
|
15
src/Ombi.Store/Entities/RequestSubscription.cs
Normal file
15
src/Ombi.Store/Entities/RequestSubscription.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Entities
|
||||||
|
{
|
||||||
|
[Table("RequestSubscription")]
|
||||||
|
public class RequestSubscription : Entity
|
||||||
|
{
|
||||||
|
public string UserId { get; set; }
|
||||||
|
public int RequestId { get; set; }
|
||||||
|
public RequestType RequestType { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey(nameof(UserId))]
|
||||||
|
public OmbiUser User { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,15 @@ namespace Ombi.Store.Entities.Requests
|
||||||
public int? IssueId { get; set; }
|
public int? IssueId { get; set; }
|
||||||
public SeriesType SeriesType { get; set; }
|
public SeriesType SeriesType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is to see if the user is subscribed in the UI
|
||||||
|
/// </summary>
|
||||||
|
[NotMapped]
|
||||||
|
public bool Subscribed { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public bool ShowSubscribe { get; set; }
|
||||||
|
|
||||||
|
|
||||||
[ForeignKey(nameof(IssueId))]
|
[ForeignKey(nameof(IssueId))]
|
||||||
public List<Issues> Issues { get; set; }
|
public List<Issues> Issues { get; set; }
|
||||||
|
|
|
@ -12,6 +12,11 @@ namespace Ombi.Store.Entities.Requests
|
||||||
[ForeignKey(nameof(IssueId))]
|
[ForeignKey(nameof(IssueId))]
|
||||||
public List<Issues> Issues { get; set; }
|
public List<Issues> Issues { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public bool Subscribed { get; set; }
|
||||||
|
[NotMapped]
|
||||||
|
public bool ShowSubscribe { get; set; }
|
||||||
|
|
||||||
public int RootPathOverride { get; set; }
|
public int RootPathOverride { get; set; }
|
||||||
public int QualityOverride { get; set; }
|
public int QualityOverride { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace Ombi.Store.Entities.Requests
|
||||||
public string Background { get; set; }
|
public string Background { get; set; }
|
||||||
public DateTime ReleaseDate { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
public string Status { get; set; }
|
public string Status { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is so we can correctly send the right amount of seasons to Sonarr
|
/// This is so we can correctly send the right amount of seasons to Sonarr
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
981
src/Ombi.Store/Migrations/20180516090124_RequestSubscription.Designer.cs
generated
Normal file
981
src/Ombi.Store/Migrations/20180516090124_RequestSubscription.Designer.cs
generated
Normal file
|
@ -0,0 +1,981 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.Internal;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(OmbiContext))]
|
||||||
|
[Migration("20180516090124_RequestSubscription")]
|
||||||
|
partial class RequestSubscription
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.0.3-rtm-10026");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("RoleNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ApplicationConfiguration");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Audit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AuditArea");
|
||||||
|
|
||||||
|
b.Property<int>("AuditType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateTime");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("User");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Audit");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CouchPotatoCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("EmbyContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ParentId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentId");
|
||||||
|
|
||||||
|
b.ToTable("EmbyEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content");
|
||||||
|
|
||||||
|
b.Property<string>("SettingsName");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("GlobalSettings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Agent");
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<int>("NotificationType");
|
||||||
|
|
||||||
|
b.Property<string>("Subject");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("NotificationTemplates");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("PlayerId");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount");
|
||||||
|
|
||||||
|
b.Property<string>("Alias");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyConnectUserId");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeRequestLimit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastLoggedIn");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||||
|
|
||||||
|
b.Property<int?>("MovieRequestLimit");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderUserId");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled");
|
||||||
|
|
||||||
|
b.Property<string>("UserAccessToken");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<int>("UserType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("UserNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("GrandparentKey");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GrandparentKey");
|
||||||
|
|
||||||
|
b.ToTable("PlexEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("PlexContentId");
|
||||||
|
|
||||||
|
b.Property<int?>("PlexServerContentId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlexServerContentId");
|
||||||
|
|
||||||
|
b.ToTable("PlexSeasonsContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<string>("Quality");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseYear");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PlexServerContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RadarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<int>("ContentId");
|
||||||
|
|
||||||
|
b.Property<int>("ContentType");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int?>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RecentlyAddedLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<bool?>("Denied");
|
||||||
|
|
||||||
|
b.Property<string>("DeniedReason");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<int>("ParentRequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestedDate");
|
||||||
|
|
||||||
|
b.Property<string>("RequestedUserId");
|
||||||
|
|
||||||
|
b.Property<int>("SeriesType");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentRequestId");
|
||||||
|
|
||||||
|
b.HasIndex("RequestedUserId");
|
||||||
|
|
||||||
|
b.ToTable("ChildRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("IssueCategory");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Comment");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Date");
|
||||||
|
|
||||||
|
b.Property<int?>("IssuesId");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IssuesId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("IssueComments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<int>("IssueCategoryId");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int?>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ResovledDate");
|
||||||
|
|
||||||
|
b.Property<int>("Status");
|
||||||
|
|
||||||
|
b.Property<string>("Subject");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("UserReportedId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IssueCategoryId");
|
||||||
|
|
||||||
|
b.HasIndex("IssueId");
|
||||||
|
|
||||||
|
b.HasIndex("UserReportedId");
|
||||||
|
|
||||||
|
b.ToTable("Issues");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<string>("Background");
|
||||||
|
|
||||||
|
b.Property<bool?>("Denied");
|
||||||
|
|
||||||
|
b.Property<string>("DeniedReason");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DigitalReleaseDate");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<string>("Overview");
|
||||||
|
|
||||||
|
b.Property<string>("PosterPath");
|
||||||
|
|
||||||
|
b.Property<int>("QualityOverride");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestedDate");
|
||||||
|
|
||||||
|
b.Property<string>("RequestedUserId");
|
||||||
|
|
||||||
|
b.Property<int>("RootPathOverride");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RequestedUserId");
|
||||||
|
|
||||||
|
b.ToTable("MovieRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeCount");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestDate");
|
||||||
|
|
||||||
|
b.Property<int>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("RequestLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Background");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("Overview");
|
||||||
|
|
||||||
|
b.Property<string>("PosterPath");
|
||||||
|
|
||||||
|
b.Property<int?>("QualityOverride");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<int?>("RootFolder");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("TvRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("RequestSubscription");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Token");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AirDate");
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("Requested");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SeasonId");
|
||||||
|
|
||||||
|
b.ToTable("EpisodeRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ChildRequestId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ChildRequestId");
|
||||||
|
|
||||||
|
b.ToTable("SeasonRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("ParentId")
|
||||||
|
.HasPrincipalKey("EmbyId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany("NotificationUserIds")
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("GrandparentKey")
|
||||||
|
.HasPrincipalKey("Key")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent")
|
||||||
|
.WithMany("Seasons")
|
||||||
|
.HasForeignKey("PlexServerContentId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest")
|
||||||
|
.WithMany("ChildRequests")
|
||||||
|
.HasForeignKey("ParentRequestId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RequestedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues")
|
||||||
|
.WithMany("Comments")
|
||||||
|
.HasForeignKey("IssuesId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IssueCategoryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests")
|
||||||
|
.WithMany("Issues")
|
||||||
|
.HasForeignKey("IssueId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.MovieRequests")
|
||||||
|
.WithMany("Issues")
|
||||||
|
.HasForeignKey("IssueId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserReportedId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RequestedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "user")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("SeasonId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest")
|
||||||
|
.WithMany("SeasonRequests")
|
||||||
|
.HasForeignKey("ChildRequestId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations
|
||||||
|
{
|
||||||
|
public partial class RequestSubscription : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "RequestSubscription",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
RequestId = table.Column<int>(nullable: false),
|
||||||
|
RequestType = table.Column<int>(nullable: false),
|
||||||
|
UserId = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_RequestSubscription", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_RequestSubscription_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_RequestSubscription_UserId",
|
||||||
|
table: "RequestSubscription",
|
||||||
|
column: "UserId");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "RequestSubscription");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ namespace Ombi.Store.Migrations
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
|
.HasAnnotation("ProductVersion", "2.0.3-rtm-10026");
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
{
|
{
|
||||||
|
@ -676,6 +676,24 @@ namespace Ombi.Store.Migrations
|
||||||
b.ToTable("TvRequests");
|
b.ToTable("TvRequests");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("RequestSubscription");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
@ -927,6 +945,13 @@ namespace Ombi.Store.Migrations
|
||||||
.HasForeignKey("UserId");
|
.HasForeignKey("UserId");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "user")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
|
|
@ -55,13 +55,13 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul *ngIf="hasRole('Admin') || hasRole('PowerUser')" class="nav navbar-nav">
|
<ul *ngIf="hasRole('Admin') || hasRole('PowerUser')" class="nav navbar-nav donation">
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.paypal.me/PlexRequestsNet" target="_blank" pTooltip="{{ 'NavigationBar.DonateTooltip' | translate }}">
|
<a href="https://www.paypal.me/PlexRequestsNet" target="_blank" pTooltip="{{ 'NavigationBar.DonateTooltip' | translate }}">
|
||||||
<i class="fa fa-heart" style="color:red"></i> {{ 'NavigationBar.Donate' | translate }}</a>
|
<i class="fa fa-heart" style="color:red"></i> {{ 'NavigationBar.Donate' | translate }}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div *ngIf="customizationSettings">
|
<div *ngIf="customizationSettings" class="custom-donation">
|
||||||
<ul *ngIf="customizationSettings.enableCustomDonations" class="nav navbar-nav">
|
<ul *ngIf="customizationSettings.enableCustomDonations" class="nav navbar-nav">
|
||||||
<li>
|
<li>
|
||||||
<a href="{{customizationSettings.customDonationUrl}}" target="_blank">
|
<a href="{{customizationSettings.customDonationUrl}}" target="_blank">
|
||||||
|
|
|
@ -101,3 +101,8 @@ export interface IMattermostNotifcationSettings extends INotificationSettings {
|
||||||
export interface IMobileNotifcationSettings extends INotificationSettings {
|
export interface IMobileNotifcationSettings extends INotificationSettings {
|
||||||
notificationTemplates: INotificationTemplates[];
|
notificationTemplates: INotificationTemplates[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IMobileNotificationTestSettings {
|
||||||
|
settings: IMobileNotifcationSettings;
|
||||||
|
userId: string;
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ export interface IMovieRequests extends IFullBaseRequest {
|
||||||
rootPathOverride: number;
|
rootPathOverride: number;
|
||||||
qualityOverride: number;
|
qualityOverride: number;
|
||||||
digitalReleaseDate: Date;
|
digitalReleaseDate: Date;
|
||||||
|
subscribed: boolean;
|
||||||
|
showSubscribe: boolean;
|
||||||
|
|
||||||
// For the UI
|
// For the UI
|
||||||
rootPathOverrideTitle: string;
|
rootPathOverrideTitle: string;
|
||||||
|
@ -77,6 +79,8 @@ export interface ITvRequests {
|
||||||
|
|
||||||
export interface IChildRequests extends IBaseRequest {
|
export interface IChildRequests extends IBaseRequest {
|
||||||
seasonRequests: INewSeasonRequests[];
|
seasonRequests: INewSeasonRequests[];
|
||||||
|
subscribed: boolean;
|
||||||
|
showSubscribe: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITvUpdateModel {
|
export interface ITvUpdateModel {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { PlatformLocation } from "@angular/common";
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute } from "@angular/router";
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ export class IssueDetailsComponent implements OnInit {
|
||||||
public settings: IIssueSettings;
|
public settings: IIssueSettings;
|
||||||
public backgroundPath: any;
|
public backgroundPath: any;
|
||||||
public posterPath: any;
|
public posterPath: any;
|
||||||
|
public defaultPoster: string;
|
||||||
|
|
||||||
private issueId: number;
|
private issueId: number;
|
||||||
|
|
||||||
|
@ -34,7 +36,8 @@ export class IssueDetailsComponent implements OnInit {
|
||||||
private settingsService: SettingsService,
|
private settingsService: SettingsService,
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
private imageService: ImageService,
|
private imageService: ImageService,
|
||||||
private sanitizer: DomSanitizer) {
|
private sanitizer: DomSanitizer,
|
||||||
|
private readonly platformLocation: PlatformLocation) {
|
||||||
this.route.params
|
this.route.params
|
||||||
.subscribe((params: any) => {
|
.subscribe((params: any) => {
|
||||||
this.issueId = parseInt(params.id);
|
this.issueId = parseInt(params.id);
|
||||||
|
@ -42,6 +45,13 @@ export class IssueDetailsComponent implements OnInit {
|
||||||
|
|
||||||
this.isAdmin = this.authService.hasRole("Admin") || this.authService.hasRole("PowerUser");
|
this.isAdmin = this.authService.hasRole("Admin") || this.authService.hasRole("PowerUser");
|
||||||
this.settingsService.getIssueSettings().subscribe(x => this.settings = x);
|
this.settingsService.getIssueSettings().subscribe(x => this.settings = x);
|
||||||
|
|
||||||
|
const base = this.platformLocation.getBaseHrefFromDOM();
|
||||||
|
if (base) {
|
||||||
|
this.defaultPoster = "../../.." + base + "/images/";
|
||||||
|
} else {
|
||||||
|
this.defaultPoster = "../../../images/";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
|
@ -99,7 +109,7 @@ export class IssueDetailsComponent implements OnInit {
|
||||||
});
|
});
|
||||||
this.imageService.getMoviePoster(issue.providerId).subscribe(x => {
|
this.imageService.getMoviePoster(issue.providerId).subscribe(x => {
|
||||||
if (x.length === 0) {
|
if (x.length === 0) {
|
||||||
this.posterPath = "../../../images/default_movie_poster.png";
|
this.posterPath = this.defaultPoster + "default_movie_poster.png";
|
||||||
} else {
|
} else {
|
||||||
this.posterPath = x.toString();
|
this.posterPath = x.toString();
|
||||||
}
|
}
|
||||||
|
@ -112,7 +122,7 @@ export class IssueDetailsComponent implements OnInit {
|
||||||
});
|
});
|
||||||
this.imageService.getTvPoster(Number(issue.providerId)).subscribe(x => {
|
this.imageService.getTvPoster(Number(issue.providerId)).subscribe(x => {
|
||||||
if (x.length === 0) {
|
if (x.length === 0) {
|
||||||
this.posterPath = "../../../images/default_tv_poster.png";
|
this.posterPath = this.defaultPoster + "default_tv_poster.png";
|
||||||
} else {
|
} else {
|
||||||
this.posterPath = x.toString();
|
this.posterPath = x.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 col-sm-push-3 small-padding">
|
<div class="col-sm-2 col-sm-push-3 small-padding">
|
||||||
|
|
||||||
|
<div style="float:right">
|
||||||
|
|
||||||
|
<a *ngIf="request.showSubscribe && !request.subscribed" style="color:white" (click)="subscribe(request)" pTooltip="Subscribe for notifications"> <i class="fa fa-rss"></i></a>
|
||||||
|
<a *ngIf="request.showSubscribe && request.subscribed" style="color:red" (click)="unSubscribe(request)" pTooltip="Unsubscribe notification"> <i class="fa fa-rss"></i></a>
|
||||||
|
</div>
|
||||||
<div *ngIf="isAdmin">
|
<div *ngIf="isAdmin">
|
||||||
<div *ngIf="!request.approved" id="approveBtn">
|
<div *ngIf="!request.approved" id="approveBtn">
|
||||||
<form>
|
<form>
|
||||||
|
@ -189,7 +195,6 @@
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn">
|
<div class="dropdown" *ngIf="issueCategories && issuesEnabled" id="issuesBtn">
|
||||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true"
|
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true"
|
||||||
aria-expanded="true">
|
aria-expanded="true">
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, Input, OnInit } from "@angular/core";
|
import { PlatformLocation } from "@angular/common";
|
||||||
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
import { DomSanitizer } from "@angular/platform-browser";
|
import { DomSanitizer } from "@angular/platform-browser";
|
||||||
import "rxjs/add/operator/debounceTime";
|
import "rxjs/add/operator/debounceTime";
|
||||||
import "rxjs/add/operator/distinctUntilChanged";
|
import "rxjs/add/operator/distinctUntilChanged";
|
||||||
|
@ -16,6 +17,7 @@ import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadar
|
||||||
})
|
})
|
||||||
export class MovieRequestsComponent implements OnInit {
|
export class MovieRequestsComponent implements OnInit {
|
||||||
public movieRequests: IMovieRequests[];
|
public movieRequests: IMovieRequests[];
|
||||||
|
public defaultPoster: string;
|
||||||
|
|
||||||
public searchChanged: Subject<string> = new Subject<string>();
|
public searchChanged: Subject<string> = new Subject<string>();
|
||||||
public searchText: string;
|
public searchText: string;
|
||||||
|
@ -47,7 +49,8 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
private auth: AuthService,
|
private auth: AuthService,
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
private radarrService: RadarrService,
|
private radarrService: RadarrService,
|
||||||
private sanitizer: DomSanitizer) {
|
private sanitizer: DomSanitizer,
|
||||||
|
private readonly platformLocation: PlatformLocation) {
|
||||||
this.searchChanged
|
this.searchChanged
|
||||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||||
.distinctUntilChanged() // only emit if value is different from previous value
|
.distinctUntilChanged() // only emit if value is different from previous value
|
||||||
|
@ -63,6 +66,11 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
this.movieRequests = m;
|
this.movieRequests = m;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
this.defaultPoster = "../../../images/default_movie_poster.png";
|
||||||
|
const base = this.platformLocation.getBaseHrefFromDOM();
|
||||||
|
if (base) {
|
||||||
|
this.defaultPoster = "../../.." + base + "/images/default_movie_poster.png";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
|
@ -209,6 +217,22 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
this.order = value;
|
this.order = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public subscribe(request: IMovieRequests) {
|
||||||
|
request.subscribed = true;
|
||||||
|
this.requestService.subscribeToMovie(request.id)
|
||||||
|
.subscribe(x => {
|
||||||
|
this.notificationService.success("Subscribed To Movie!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public unSubscribe(request: IMovieRequests) {
|
||||||
|
request.subscribed = false;
|
||||||
|
this.requestService.unSubscribeToMovie(request.id)
|
||||||
|
.subscribe(x => {
|
||||||
|
this.notificationService.success("Unsubscribed Movie!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private filterActiveStyle(el: any) {
|
private filterActiveStyle(el: any) {
|
||||||
el = el.toElement || el.relatedTarget || el.target || el.srcElement;
|
el = el.toElement || el.relatedTarget || el.target || el.srcElement;
|
||||||
|
|
||||||
|
@ -354,7 +378,7 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
|
|
||||||
private setPoster(req: IMovieRequests): void {
|
private setPoster(req: IMovieRequests): void {
|
||||||
if (req.posterPath === null) {
|
if (req.posterPath === null) {
|
||||||
req.posterPath = "../../../images/default_movie_poster.png";
|
req.posterPath = this.defaultPoster;
|
||||||
} else {
|
} else {
|
||||||
req.posterPath = "https://image.tmdb.org/t/p/w300/" + req.posterPath;
|
req.posterPath = "https://image.tmdb.org/t/p/w300/" + req.posterPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { RequestComponent } from "./request.component";
|
||||||
import { TvRequestChildrenComponent } from "./tvrequest-children.component";
|
import { TvRequestChildrenComponent } from "./tvrequest-children.component";
|
||||||
import { TvRequestsComponent } from "./tvrequests.component";
|
import { TvRequestsComponent } from "./tvrequests.component";
|
||||||
|
|
||||||
import { SidebarModule, TreeTableModule } from "primeng/primeng";
|
import { SidebarModule, TooltipModule, TreeTableModule } from "primeng/primeng";
|
||||||
|
|
||||||
import { IdentityService, RadarrService, RequestService, SonarrService } from "../services";
|
import { IdentityService, RadarrService, RequestService, SonarrService } from "../services";
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ const routes: Routes = [
|
||||||
SidebarModule,
|
SidebarModule,
|
||||||
OrderModule,
|
OrderModule,
|
||||||
PaginatorModule,
|
PaginatorModule,
|
||||||
|
TooltipModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
RequestComponent,
|
RequestComponent,
|
||||||
|
|
|
@ -11,8 +11,11 @@
|
||||||
<span *ngIf="isAdmin && !child.requestedUser.alias">{{child.requestedUser.userName}}</span>
|
<span *ngIf="isAdmin && !child.requestedUser.alias">{{child.requestedUser.userName}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="col-md-1 col-md-push-9">
|
<div class="col-md-1 col-md-push-9">
|
||||||
|
<button id="subscribeBtn" *ngIf="child.showSubscribe && !child.subscribed" (click)="subscribe(child)" class="btn btn-sm btn-primary-outline" pTooltip="Subscribe for notifications" type="submit"><i class="fa fa-rss"></i> Subscribe</button>
|
||||||
|
<button id="subscribeBtn" *ngIf="child.showSubscribe && child.subscribed" (click)="unSubscribe(child)" class="btn btn-sm btn-danger-outline" pTooltip="UnSubscribe for notifications" type="submit"><i class="fa fa-rss"></i> UnSubscribe</button>
|
||||||
|
|
||||||
|
|
||||||
<div *ngIf="isAdmin">
|
<div *ngIf="isAdmin">
|
||||||
<button id="approveBtn" *ngIf="child.canApprove && !child.approved" (click)="approve(child)" class="btn btn-sm btn-success-outline" type="submit"><i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }}</button>
|
<button id="approveBtn" *ngIf="child.canApprove && !child.approved" (click)="approve(child)" class="btn btn-sm btn-success-outline" type="submit"><i class="fa fa-plus"></i> {{ 'Common.Approve' | translate }}</button>
|
||||||
<button id="unavailableBtn" *ngIf="child.available" (click)="changeAvailability(child, false)" style="text-align: right" value="false" class="btn btn-sm btn-info-outline change"><i class="fa fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}</button>
|
<button id="unavailableBtn" *ngIf="child.available" (click)="changeAvailability(child, false)" style="text-align: right" value="false" class="btn btn-sm btn-info-outline change"><i class="fa fa-minus"></i> {{ 'Requests.MarkUnavailable' | translate }}</button>
|
||||||
|
|
|
@ -94,6 +94,22 @@ export class TvRequestChildrenComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public subscribe(request: IChildRequests) {
|
||||||
|
request.subscribed = true;
|
||||||
|
this.requestService.subscribeToTv(request.id)
|
||||||
|
.subscribe(x => {
|
||||||
|
this.notificationService.success("Subscribed To TV Show!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public unSubscribe(request: IChildRequests) {
|
||||||
|
request.subscribed = false;
|
||||||
|
this.requestService.unSubscribeToTv(request.id)
|
||||||
|
.subscribe(x => {
|
||||||
|
this.notificationService.success("Unsubscribed TV Show!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private removeRequestFromUi(key: IChildRequests) {
|
private removeRequestFromUi(key: IChildRequests) {
|
||||||
const index = this.childRequests.indexOf(key, 0);
|
const index = this.childRequests.indexOf(key, 0);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, Input, OnInit } from "@angular/core";
|
import { PlatformLocation } from "@angular/common";
|
||||||
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
import { DomSanitizer } from "@angular/platform-browser";
|
import { DomSanitizer } from "@angular/platform-browser";
|
||||||
import "rxjs/add/operator/debounceTime";
|
import "rxjs/add/operator/debounceTime";
|
||||||
import "rxjs/add/operator/distinctUntilChanged";
|
import "rxjs/add/operator/distinctUntilChanged";
|
||||||
|
@ -29,6 +30,7 @@ export class TvRequestsComponent implements OnInit {
|
||||||
public isAdmin: boolean;
|
public isAdmin: boolean;
|
||||||
public showChildDialogue = false; // This is for the child modal popup
|
public showChildDialogue = false; // This is for the child modal popup
|
||||||
public selectedSeason: ITvRequests;
|
public selectedSeason: ITvRequests;
|
||||||
|
public defaultPoster: string;
|
||||||
|
|
||||||
@Input() public issueCategories: IIssueCategory[];
|
@Input() public issueCategories: IIssueCategory[];
|
||||||
@Input() public issuesEnabled: boolean;
|
@Input() public issuesEnabled: boolean;
|
||||||
|
@ -49,7 +51,8 @@ export class TvRequestsComponent implements OnInit {
|
||||||
private sanitizer: DomSanitizer,
|
private sanitizer: DomSanitizer,
|
||||||
private imageService: ImageService,
|
private imageService: ImageService,
|
||||||
private sonarrService: SonarrService,
|
private sonarrService: SonarrService,
|
||||||
private notificationService: NotificationService) {
|
private notificationService: NotificationService,
|
||||||
|
private readonly platformLocation: PlatformLocation) {
|
||||||
this.searchChanged
|
this.searchChanged
|
||||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||||
.distinctUntilChanged() // only emit if value is different from previous value
|
.distinctUntilChanged() // only emit if value is different from previous value
|
||||||
|
@ -66,6 +69,11 @@ export class TvRequestsComponent implements OnInit {
|
||||||
this.tvRequests.forEach((val) => this.setOverride(val.data));
|
this.tvRequests.forEach((val) => this.setOverride(val.data));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
this.defaultPoster = "../../../images/default_tv_poster.png";
|
||||||
|
const base = this.platformLocation.getBaseHrefFromDOM();
|
||||||
|
if (base) {
|
||||||
|
this.defaultPoster = "../../.." + base + "/images/default_tv_poster.png";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public openClosestTab(el: any) {
|
public openClosestTab(el: any) {
|
||||||
|
@ -222,7 +230,7 @@ export class TvRequestsComponent implements OnInit {
|
||||||
|
|
||||||
private setDefaults(val: any) {
|
private setDefaults(val: any) {
|
||||||
if (val.data.posterPath === null) {
|
if (val.data.posterPath === null) {
|
||||||
val.data.posterPath = "../../../images/default_tv_poster.png";
|
val.data.posterPath = this.defaultPoster;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, Input, OnInit } from "@angular/core";
|
import { PlatformLocation } from "@angular/common";
|
||||||
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
import { DomSanitizer } from "@angular/platform-browser";
|
import { DomSanitizer } from "@angular/platform-browser";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
import "rxjs/add/operator/debounceTime";
|
import "rxjs/add/operator/debounceTime";
|
||||||
|
@ -29,10 +30,12 @@ export class MovieSearchComponent implements OnInit {
|
||||||
public issueRequestId: number;
|
public issueRequestId: number;
|
||||||
public issueProviderId: string;
|
public issueProviderId: string;
|
||||||
public issueCategorySelected: IIssueCategory;
|
public issueCategorySelected: IIssueCategory;
|
||||||
|
public defaultPoster: string;
|
||||||
|
|
||||||
constructor(private searchService: SearchService, private requestService: RequestService,
|
constructor(private searchService: SearchService, private requestService: RequestService,
|
||||||
private notificationService: NotificationService, private authService: AuthService,
|
private notificationService: NotificationService, private authService: AuthService,
|
||||||
private readonly translate: TranslateService, private sanitizer: DomSanitizer) {
|
private readonly translate: TranslateService, private sanitizer: DomSanitizer,
|
||||||
|
private readonly platformLocation: PlatformLocation) {
|
||||||
|
|
||||||
this.searchChanged
|
this.searchChanged
|
||||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||||
|
@ -52,6 +55,11 @@ export class MovieSearchComponent implements OnInit {
|
||||||
this.getExtraInfo();
|
this.getExtraInfo();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
this.defaultPoster = "../../../images/default_movie_poster.png";
|
||||||
|
const base = this.platformLocation.getBaseHrefFromDOM();
|
||||||
|
if (base) {
|
||||||
|
this.defaultPoster = "../../.." + base + "/images/default_movie_poster.png";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
|
@ -159,7 +167,7 @@ export class MovieSearchComponent implements OnInit {
|
||||||
|
|
||||||
this.movieResults.forEach((val, index) => {
|
this.movieResults.forEach((val, index) => {
|
||||||
if (val.posterPath === null) {
|
if (val.posterPath === null) {
|
||||||
val.posterPath = "../../../images/default_movie_poster.png";
|
val.posterPath = this.defaultPoster;
|
||||||
} else {
|
} else {
|
||||||
val.posterPath = "https://image.tmdb.org/t/p/w300/" + val.posterPath;
|
val.posterPath = "https://image.tmdb.org/t/p/w300/" + val.posterPath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, Input, OnInit } from "@angular/core";
|
import { PlatformLocation } from "@angular/common";
|
||||||
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
import { DomSanitizer } from "@angular/platform-browser";
|
import { DomSanitizer } from "@angular/platform-browser";
|
||||||
import { Subject } from "rxjs/Subject";
|
import { Subject } from "rxjs/Subject";
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ export class TvSearchComponent implements OnInit {
|
||||||
public tvResults: TreeNode[];
|
public tvResults: TreeNode[];
|
||||||
public result: IRequestEngineResult;
|
public result: IRequestEngineResult;
|
||||||
public searchApplied = false;
|
public searchApplied = false;
|
||||||
|
public defaultPoster: string;
|
||||||
|
|
||||||
@Input() public issueCategories: IIssueCategory[];
|
@Input() public issueCategories: IIssueCategory[];
|
||||||
@Input() public issuesEnabled: boolean;
|
@Input() public issuesEnabled: boolean;
|
||||||
|
@ -32,7 +34,8 @@ export class TvSearchComponent implements OnInit {
|
||||||
|
|
||||||
constructor(private searchService: SearchService, private requestService: RequestService,
|
constructor(private searchService: SearchService, private requestService: RequestService,
|
||||||
private notificationService: NotificationService, private authService: AuthService,
|
private notificationService: NotificationService, private authService: AuthService,
|
||||||
private imageService: ImageService, private sanitizer: DomSanitizer) {
|
private imageService: ImageService, private sanitizer: DomSanitizer,
|
||||||
|
private readonly platformLocation: PlatformLocation) {
|
||||||
|
|
||||||
this.searchChanged
|
this.searchChanged
|
||||||
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||||
|
@ -50,6 +53,11 @@ export class TvSearchComponent implements OnInit {
|
||||||
this.getExtraInfo();
|
this.getExtraInfo();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
this.defaultPoster = "../../../images/default_tv_poster.png";
|
||||||
|
const base = this.platformLocation.getBaseHrefFromDOM();
|
||||||
|
if(base) {
|
||||||
|
this.defaultPoster = "../../.." + base + "/images/default_tv_poster.png";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public openClosestTab(el: any) {
|
public openClosestTab(el: any) {
|
||||||
el.preventDefault();
|
el.preventDefault();
|
||||||
|
@ -228,7 +236,7 @@ export class TvSearchComponent implements OnInit {
|
||||||
|
|
||||||
private setDefaults(x: any) {
|
private setDefaults(x: any) {
|
||||||
if (x.data.banner === null) {
|
if (x.data.banner === null) {
|
||||||
x.data.banner = "../../../images/default_tv_poster.png";
|
x.data.banner = this.defaultPoster;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x.data.imdbId === null) {
|
if (x.data.imdbId === null) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
IEmailNotificationSettings,
|
IEmailNotificationSettings,
|
||||||
IEmbyServer,
|
IEmbyServer,
|
||||||
IMattermostNotifcationSettings,
|
IMattermostNotifcationSettings,
|
||||||
|
IMobileNotificationTestSettings,
|
||||||
INewsletterNotificationSettings,
|
INewsletterNotificationSettings,
|
||||||
IPlexServer,
|
IPlexServer,
|
||||||
IPushbulletNotificationSettings,
|
IPushbulletNotificationSettings,
|
||||||
|
@ -82,4 +83,7 @@ export class TesterService extends ServiceHelpers {
|
||||||
public newsletterTest(settings: INewsletterNotificationSettings): Observable<boolean> {
|
public newsletterTest(settings: INewsletterNotificationSettings): Observable<boolean> {
|
||||||
return this.http.post<boolean>(`${this.url}newsletter`, JSON.stringify(settings), {headers: this.headers});
|
return this.http.post<boolean>(`${this.url}newsletter`, JSON.stringify(settings), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
public mobileNotificationTest(settings: IMobileNotificationTestSettings): Observable<boolean> {
|
||||||
|
return this.http.post<boolean>(`${this.url}mobile`, JSON.stringify(settings), {headers: this.headers});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,4 +117,17 @@ export class RequestService extends ServiceHelpers {
|
||||||
public filterMovies(filter: IFilter): Observable<IFilterResult<IMovieRequests>> {
|
public filterMovies(filter: IFilter): Observable<IFilterResult<IMovieRequests>> {
|
||||||
return this.http.post<IFilterResult<IMovieRequests>>(`${this.url}movie/filter`, JSON.stringify(filter), {headers: this.headers});
|
return this.http.post<IFilterResult<IMovieRequests>>(`${this.url}movie/filter`, JSON.stringify(filter), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public subscribeToMovie(requestId: number): Observable<boolean> {
|
||||||
|
return this.http.post<boolean>(`${this.url}movie/subscribe/${requestId}`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
public unSubscribeToMovie(requestId: number): Observable<boolean> {
|
||||||
|
return this.http.post<boolean>(`${this.url}movie/unsubscribe/${requestId}`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
public subscribeToTv(requestId: number): Observable<boolean> {
|
||||||
|
return this.http.post<boolean>(`${this.url}tv/subscribe/${requestId}`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
public unSubscribeToTv(requestId: number): Observable<boolean> {
|
||||||
|
return this.http.post<boolean>(`${this.url}tv/unsubscribe/${requestId}`, {headers: this.headers});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,20 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
<label for="select" class="control-label">User to send test notification to</label>
|
||||||
<div>
|
<div>
|
||||||
<button [disabled]="form.invalid" type="button" (click)="test(form)" class="btn btn-primary-outline">
|
<select class="form-control form-control-custom" id="select" [(ngModel)]="testUserId" [ngModelOptions]="{standalone: true}">
|
||||||
Test
|
<option value="">Please select</option>
|
||||||
<div id="spinner"></div>
|
<option *ngFor="let x of userList" [value]="x.id">{{x.username}}</option>
|
||||||
</button>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button [disabled]="form.invalid" type="button" (click)="test(form)" class="btn btn-danger-outline">Test</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
|
@ -15,6 +15,7 @@ export class MobileComponent implements OnInit {
|
||||||
public templates: INotificationTemplates[];
|
public templates: INotificationTemplates[];
|
||||||
public form: FormGroup;
|
public form: FormGroup;
|
||||||
public userList: IMobileUsersViewModel[];
|
public userList: IMobileUsersViewModel[];
|
||||||
|
public testUserId: string;
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService,
|
constructor(private settingsService: SettingsService,
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
|
@ -64,8 +65,12 @@ export class MobileComponent implements OnInit {
|
||||||
this.notificationService.error("Please check your entered values");
|
this.notificationService.error("Please check your entered values");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!this.testUserId) {
|
||||||
|
this.notificationService.warning("Warning","Please select a user to send the test notification");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.testerService.discordTest(form.value).subscribe(x => {
|
this.testerService.mobileNotificationTest({settings: form.value, userId: this.testUserId}).subscribe(x => {
|
||||||
if (x) {
|
if (x) {
|
||||||
this.notificationService.success("Successfully sent a Mobile message, please check the admin mobile device");
|
this.notificationService.success("Successfully sent a Mobile message, please check the admin mobile device");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,6 +14,7 @@ using Ombi.Core.Models.UI;
|
||||||
using Ombi.Core.Notifications;
|
using Ombi.Core.Notifications;
|
||||||
using Ombi.Core.Settings.Models.External;
|
using Ombi.Core.Settings.Models.External;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Models;
|
||||||
using Ombi.Notifications;
|
using Ombi.Notifications;
|
||||||
using Ombi.Notifications.Agents;
|
using Ombi.Notifications.Agents;
|
||||||
using Ombi.Notifications.Models;
|
using Ombi.Notifications.Models;
|
||||||
|
@ -37,7 +38,7 @@ namespace Ombi.Controllers.External
|
||||||
public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN,
|
public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN,
|
||||||
IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm,
|
IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm,
|
||||||
IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger<TesterController> log, IEmailProvider provider,
|
IPlexApi plex, IEmbyApi emby, IRadarrApi radarr, ISonarrApi sonarr, ILogger<TesterController> log, IEmailProvider provider,
|
||||||
ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter)
|
ICouchPotatoApi cpApi, ITelegramNotification telegram, ISickRageApi srApi, INewsletterJob newsletter, IMobileNotification mobileNotification)
|
||||||
{
|
{
|
||||||
Service = service;
|
Service = service;
|
||||||
DiscordNotification = notification;
|
DiscordNotification = notification;
|
||||||
|
@ -56,6 +57,7 @@ namespace Ombi.Controllers.External
|
||||||
TelegramNotification = telegram;
|
TelegramNotification = telegram;
|
||||||
SickRageApi = srApi;
|
SickRageApi = srApi;
|
||||||
Newsletter = newsletter;
|
Newsletter = newsletter;
|
||||||
|
MobileNotification = mobileNotification;
|
||||||
}
|
}
|
||||||
|
|
||||||
private INotificationService Service { get; }
|
private INotificationService Service { get; }
|
||||||
|
@ -75,6 +77,7 @@ namespace Ombi.Controllers.External
|
||||||
private ITelegramNotification TelegramNotification { get; }
|
private ITelegramNotification TelegramNotification { get; }
|
||||||
private ISickRageApi SickRageApi { get; }
|
private ISickRageApi SickRageApi { get; }
|
||||||
private INewsletterJob Newsletter { get; }
|
private INewsletterJob Newsletter { get; }
|
||||||
|
private IMobileNotification MobileNotification { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -388,5 +391,21 @@ namespace Ombi.Controllers.External
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("mobile")]
|
||||||
|
public async Task<bool> MobileNotificationTest([FromBody] MobileNotificationTestViewModel settings)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await MobileNotification.NotifyAsync(new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1, UserId = settings.UserId}, settings.Settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.LogError(LoggingEvents.Api, e, "Could not test Mobile Notifications");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Ombi.Models;
|
using Ombi.Models;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Controllers
|
namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
|
@ -356,5 +357,45 @@ namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
return await MovieRequestEngine.Filter(vm);
|
return await MovieRequestEngine.Filter(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Subscribes for notifications to a movie request
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("movie/subscribe/{requestId:int}")]
|
||||||
|
public async Task<bool> SubscribeToMovie(int requestId)
|
||||||
|
{
|
||||||
|
await MovieRequestEngine.SubscribeToRequest(requestId, RequestType.Movie);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Subscribes for notifications to a TV request
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("tv/subscribe/{requestId:int}")]
|
||||||
|
public async Task<bool> SubscribeToTv(int requestId)
|
||||||
|
{
|
||||||
|
await TvRequestEngine.SubscribeToRequest(requestId, RequestType.TvShow);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UnSubscribes for notifications to a movie request
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("movie/unsubscribe/{requestId:int}")]
|
||||||
|
public async Task<bool> UnSubscribeToMovie(int requestId)
|
||||||
|
{
|
||||||
|
await MovieRequestEngine.UnSubscribeRequest(requestId, RequestType.Movie);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UnSubscribes for notifications to a TV request
|
||||||
|
/// </summary>
|
||||||
|
[HttpPost("tv/unsubscribe/{requestId:int}")]
|
||||||
|
public async Task<bool> UnSubscribeToTv(int requestId)
|
||||||
|
{
|
||||||
|
await TvRequestEngine.UnSubscribeRequest(requestId, RequestType.TvShow);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
10
src/Ombi/Models/MobileNotificationTestViewModel.cs
Normal file
10
src/Ombi/Models/MobileNotificationTestViewModel.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using Ombi.Settings.Settings.Models.Notifications;
|
||||||
|
|
||||||
|
namespace Ombi.Models
|
||||||
|
{
|
||||||
|
public class MobileNotificationTestViewModel
|
||||||
|
{
|
||||||
|
public string UserId { get; set; }
|
||||||
|
public MobileNotificationSettings Settings { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -191,11 +191,15 @@ namespace Ombi
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)});
|
app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)});
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire",
|
app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire",
|
||||||
new DashboardOptions
|
new DashboardOptions
|
||||||
{
|
{
|
||||||
Authorization = new[] {new HangfireAuthorizationFilter()}
|
Authorization = new[] {new HangfireAuthorizationFilter()}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 3 });
|
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 3 });
|
||||||
|
|
||||||
// Setup the scheduler
|
// Setup the scheduler
|
||||||
|
|
|
@ -58,6 +58,21 @@
|
||||||
|
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
@*<!-- Start SmartBanner configuration -->
|
||||||
|
<meta name="smartbanner:title" content="Smart Application">
|
||||||
|
<meta name="smartbanner:author" content="SmartBanner Contributors">
|
||||||
|
<meta name="smartbanner:price" content=" ">
|
||||||
|
<meta name="smartbanner:price-suffix-apple" content=" On the App Store">
|
||||||
|
<meta name="smartbanner:price-suffix-google" content=" In Google Play">
|
||||||
|
<meta name="smartbanner:icon-apple" content="http://a3.mzstatic.com/us/r30/Purple60/v4/c1/3b/b0/c13bb085-64c0-cc90-f97a-521b96963986/icon350x350.jpeg">
|
||||||
|
<meta name="smartbanner:icon-google" content="http://lh3.ggpht.com/f4oX61ljZ6x8aYDELZOgxlvdUEu73-wSQ4fy5bx6fCRISnZP8T353wdaM43RO_DbGg=w300">
|
||||||
|
<meta name="smartbanner:button" content="View">
|
||||||
|
<meta name="smartbanner:button-url-apple" content="https://itunes.apple.com/us/genre/ios/id36?mt=8">
|
||||||
|
<meta name="smartbanner:button-url-google" content="https://play.google.com/store">
|
||||||
|
<meta name="smartbanner:enabled-platforms" content="android,ios">e.com/store/apps/details?id=com.tidusjar.Ombi">
|
||||||
|
<meta name="smartbanner:enabled-platforms" content="android,ios">
|
||||||
|
<!-- End SmartBanner configuration -->*@
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
<meta name="description" content="Ombi, media request tool">
|
<meta name="description" content="Ombi, media request tool">
|
||||||
|
@ -78,6 +93,7 @@
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
|
|
||||||
<link rel="stylesheet" href="~/loading.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/loading.css" asp-append-version="true" />
|
||||||
|
|
|
@ -67,6 +67,8 @@ module.exports = (env: any) => {
|
||||||
"@ngx-translate/core",
|
"@ngx-translate/core",
|
||||||
"@ngx-translate/http-loader",
|
"@ngx-translate/http-loader",
|
||||||
"ngx-order-pipe",
|
"ngx-order-pipe",
|
||||||
|
//"smartbanner.js/dist/smartbanner.js",
|
||||||
|
//"smartbanner.js/dist/smartbanner.css",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue