diff --git a/CHANGELOG.md b/CHANGELOG.md
index 91ef9d69d..662b43716 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,13 @@
# Changelog
-## (unreleased)
+## v3.0.3304 (2018-05-09)
### **New Features**
- Updated to prevent security vulnerability as noted here: https://github.com/aspnet/Announcements/issues/300. [Jamie Rees]
+- Update README.md. [Jamie]
+
### **Fixes**
- [LC] - Added classes to root/quality override divs. [Anojh]
diff --git a/README.md b/README.md
index 1c2dc9559..2049af360 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,9 @@ ____
[![Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://patreon.com/tidusjar/Ombi)
[![Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://paypal.me/PlexRequestsNet)
+___
+
+
___
We also now have merch up on Teespring!
diff --git a/src/Ombi.Core/Engine/BaseMediaEngine.cs b/src/Ombi.Core/Engine/BaseMediaEngine.cs
index 552b2ac38..273c71ef0 100644
--- a/src/Ombi.Core/Engine/BaseMediaEngine.cs
+++ b/src/Ombi.Core/Engine/BaseMediaEngine.cs
@@ -9,13 +9,12 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Entities.Requests;
-using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
-using Ombi.Store.Entities;
-using Microsoft.AspNetCore.Identity;
using Ombi.Core.Authentication;
using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models;
+using Ombi.Store.Entities;
+using Ombi.Store.Repository;
namespace Ombi.Core.Engine
{
@@ -26,11 +25,12 @@ namespace Ombi.Core.Engine
private Dictionary _dbTv;
protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService,
- IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService ombiSettings) : base(identity, um, rules)
+ IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService ombiSettings, IRepository sub) : base(identity, um, rules)
{
RequestService = requestService;
Cache = cache;
OmbiSettings = ombiSettings;
+ _subscriptionRepository = sub;
}
protected IRequestServiceMain RequestService { get; }
@@ -38,6 +38,7 @@ namespace Ombi.Core.Engine
protected ITvRequestRepository TvRepository => RequestService.TvRequestService;
protected readonly ICacheService Cache;
protected readonly ISettingsService OmbiSettings;
+ protected readonly IRepository _subscriptionRepository;
protected async Task> GetMovieRequests()
{
@@ -78,7 +79,7 @@ namespace Ombi.Core.Engine
var pendingTv = 0;
var approvedTv = 0;
- var availableTv = 0;
+ var availableTv = 0;
foreach (var tv in tvQuery)
{
foreach (var child in tv.ChildRequests)
@@ -108,21 +109,51 @@ namespace Ombi.Core.Engine
protected async Task HideFromOtherUsers()
{
+ var user = await GetUser();
if (await IsInRole(OmbiRoles.Admin) || await IsInRole(OmbiRoles.PowerUser))
{
- return new HideResult();
+ return new HideResult
+ {
+ UserId = user.Id
+ };
}
var settings = await Cache.GetOrAdd(CacheKeys.OmbiSettings, async () => await OmbiSettings.GetSettingsAsync());
var result = new HideResult
{
- Hide = settings.HideRequestsUsers
+ Hide = settings.HideRequestsUsers,
+ UserId = user.Id
+ };
+ return result;
+ }
+
+ public async Task SubscribeToRequest(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)
+ {
+ return;
+ }
+ var sub = new RequestSubscription
+ {
+ UserId = user.Id,
+ RequestId = requestId,
+ RequestType = type
};
- if (settings.HideRequestsUsers)
+
+ 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)
{
- var user = await GetUser();
- result.UserId = user.Id;
+ await _subscriptionRepository.Delete(existingSub);
}
- return result;
}
public class HideResult
diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs
index 08ec9b594..c1ba76a7c 100644
--- a/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs
+++ b/src/Ombi.Core/Engine/Interfaces/IMovieRequestEngine.cs
@@ -18,6 +18,7 @@ namespace Ombi.Core.Engine.Interfaces
Task ApproveMovieById(int requestId);
Task DenyMovieById(int modelId);
Task> Filter(FilterViewModel vm);
+
}
}
\ No newline at end of file
diff --git a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs
index 5dbf6e449..553ad79dd 100644
--- a/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs
+++ b/src/Ombi.Core/Engine/Interfaces/IRequestEngine.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Core.Models.Requests;
+using Ombi.Store.Entities;
namespace Ombi.Core.Engine.Interfaces
{
@@ -18,5 +19,7 @@ namespace Ombi.Core.Engine.Interfaces
Task MarkUnavailable(int modelId);
Task MarkAvailable(int modelId);
Task GetTotal();
+ Task UnSubscribeRequest(int requestId, RequestType type);
+ Task SubscribeToRequest(int requestId, RequestType type);
}
}
\ No newline at end of file
diff --git a/src/Ombi.Core/Engine/MovieRequestEngine.cs b/src/Ombi.Core/Engine/MovieRequestEngine.cs
index 3d88b7230..460752bb1 100644
--- a/src/Ombi.Core/Engine/MovieRequestEngine.cs
+++ b/src/Ombi.Core/Engine/MovieRequestEngine.cs
@@ -25,7 +25,8 @@ namespace Ombi.Core.Engine
{
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user,
INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger log,
- OmbiUserManager manager, IRepository rl, ICacheService cache, ISettingsService ombiSettings) : base(user, requestService, r, manager, cache, ombiSettings)
+ OmbiUserManager manager, IRepository rl, ICacheService cache, ISettingsService ombiSettings, IRepository sub)
+ : base(user, requestService, r, manager, cache, ombiSettings, sub)
{
MovieApi = movieApi;
NotificationHelper = helper;
@@ -137,9 +138,10 @@ namespace Ombi.Core.Engine
{
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);
+ await CheckForSubscription(shouldHide, x);
});
return allRequests;
}
@@ -173,9 +175,30 @@ namespace Ombi.Core.Engine
{
allRequests = await MovieRepository.GetWithUser().ToListAsync();
}
+
+ allRequests.ForEach(async x =>
+ {
+ x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
+ await CheckForSubscription(shouldHide, x);
+ });
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;
+ }
+ }
+
///
/// Searches the movie request.
///
@@ -194,9 +217,10 @@ namespace Ombi.Core.Engine
allRequests = await MovieRepository.GetWithUser().ToListAsync();
}
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);
+ await CheckForSubscription(shouldHide, x);
});
return results;
}
diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs
index 448ff9235..915eefe02 100644
--- a/src/Ombi.Core/Engine/MovieSearchEngine.cs
+++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs
@@ -15,14 +15,16 @@ using Ombi.Core.Authentication;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
+using Ombi.Store.Entities;
+using Ombi.Store.Repository;
namespace Ombi.Core.Engine
{
public class MovieSearchEngine : BaseMediaEngine, IMovieEngine
{
public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper,
- ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s)
- : base(identity, service, r, um, mem, s)
+ ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub)
+ : base(identity, service, r, um, mem, s, sub)
{
MovieApi = movApi;
Mapper = mapper;
diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs
index 2ce4da292..d74b45e5e 100644
--- a/src/Ombi.Core/Engine/TvRequestEngine.cs
+++ b/src/Ombi.Core/Engine/TvRequestEngine.cs
@@ -29,7 +29,8 @@ namespace Ombi.Core.Engine
{
public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user,
INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager,
- ITvSender sender, IAuditRepository audit, IRepository rl, ISettingsService settings, ICacheService cache) : base(user, requestService, rule, manager, cache, settings)
+ ITvSender sender, IAuditRepository audit, IRepository rl, ISettingsService settings, ICacheService cache,
+ IRepository sub) : base(user, requestService, rule, manager, cache, settings, sub)
{
TvApi = tvApi;
MovieDbApi = movApi;
@@ -156,6 +157,8 @@ namespace Ombi.Core.Engine
.Skip(position).Take(count).OrderByDescending(x => x.ReleaseDate).ToListAsync();
}
+ allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
+
return allRequests;
}
@@ -181,25 +184,28 @@ namespace Ombi.Core.Engine
.ThenInclude(x => x.Episodes)
.Skip(position).Take(count).ToListAsync();
}
+
+ allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
return ParseIntoTreeNode(allRequests);
}
public async Task> GetRequests()
{
var shouldHide = await HideFromOtherUsers();
- IQueryable allRequests;
+ List allRequests;
if (shouldHide.Hide)
{
- allRequests = TvRepository.Get(shouldHide.UserId);
+ allRequests = await TvRepository.Get(shouldHide.UserId).ToListAsync();
FilterChildren(allRequests, shouldHide);
}
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 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.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
+
return allRequests;
}
@@ -248,6 +256,8 @@ namespace Ombi.Core.Engine
allRequests = TvRepository.Get();
}
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
+
+ results.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
return results;
}
@@ -264,6 +274,7 @@ namespace Ombi.Core.Engine
allRequests = TvRepository.Get();
}
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
+ results.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
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 AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest)
{
// Add the child
diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs
index 1664ecfa7..bc5a2e984 100644
--- a/src/Ombi.Core/Engine/TvSearchEngine.cs
+++ b/src/Ombi.Core/Engine/TvSearchEngine.cs
@@ -20,6 +20,7 @@ using Microsoft.Extensions.Caching.Memory;
using Ombi.Core.Authentication;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
+using Ombi.Store.Entities;
namespace Ombi.Core.Engine
{
@@ -27,8 +28,8 @@ namespace Ombi.Core.Engine
{
public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService plexSettings,
ISettingsService embySettings, IPlexContentRepository repo, IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um,
- ICacheService memCache, ISettingsService s)
- : base(identity, service, r, um, memCache, s)
+ ICacheService memCache, ISettingsService s, IRepository sub)
+ : base(identity, service, r, um, memCache, s, sub)
{
TvMazeApi = tvMaze;
Mapper = mapper;
diff --git a/src/Ombi.Notifications/Agents/DiscordNotification.cs b/src/Ombi.Notifications/Agents/DiscordNotification.cs
index 0a5d5dabc..66280ef70 100644
--- a/src/Ombi.Notifications/Agents/DiscordNotification.cs
+++ b/src/Ombi.Notifications/Agents/DiscordNotification.cs
@@ -20,8 +20,8 @@ namespace Ombi.Notifications.Agents
{
public DiscordNotification(IDiscordApi api, ISettingsService sn,
ILogger log, INotificationTemplatesRepository r,
- IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s)
- : base(sn, r, m, t,s,log)
+ IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub)
+ : base(sn, r, m, t,s,log, sub)
{
Api = api;
Logger = log;
diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs
index d8f005e2b..53046ade0 100644
--- a/src/Ombi.Notifications/Agents/EmailNotification.cs
+++ b/src/Ombi.Notifications/Agents/EmailNotification.cs
@@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MimeKit;
using Ombi.Core.Settings;
@@ -21,7 +22,7 @@ namespace Ombi.Notifications.Agents
public class EmailNotification : BaseNotification, IEmailNotification
{
public EmailNotification(ISettingsService settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService c,
- ILogger log, UserManager um) : base(settings, r, m, t, c, log)
+ ILogger log, UserManager um, IRepository sub) : base(settings, r, m, t, c, log, sub)
{
EmailProvider = prov;
Logger = log;
@@ -52,7 +53,7 @@ namespace Ombi.Notifications.Agents
return true;
}
-
+
private async Task LoadTemplate(NotificationType type, NotificationOptions model, EmailNotificationSettings settings)
{
var parsed = await LoadTemplate(NotificationAgent.Email, type, model);
@@ -62,8 +63,8 @@ namespace Ombi.Notifications.Agents
return null;
}
var email = new EmailBasicTemplate();
- var html = email.LoadTemplate(parsed.Subject, parsed.Message,parsed.Image, Customization.Logo);
-
+ var html = email.LoadTemplate(parsed.Subject, parsed.Message, parsed.Image, Customization.Logo);
+
var message = new NotificationMessage
{
@@ -154,7 +155,7 @@ namespace Ombi.Notifications.Agents
{
message.To = model.Recipient;
}
-
+
await Send(message, settings);
}
@@ -176,7 +177,7 @@ namespace Ombi.Notifications.Agents
// Issues resolved should be sent to the user
message.To = model.Recipient;
-
+
await Send(message, settings);
}
@@ -227,10 +228,12 @@ namespace Ombi.Notifications.Agents
var plaintext = await LoadPlainTextMessage(NotificationType.RequestDeclined, model, settings);
message.Other.Add("PlainTextBody", plaintext);
+ await SendToSubscribers(settings, message);
message.To = model.RequestType == RequestType.Movie
? MovieRequest.RequestedUser.Email
: TvRequest.RequestedUser.Email;
await Send(message, 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);
message.Other.Add("PlainTextBody", plaintext);
+ await SendToSubscribers(settings, message);
+
message.To = model.RequestType == RequestType.Movie
? MovieRequest.RequestedUser.Email
: TvRequest.RequestedUser.Email;
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)
{
var message = await LoadTemplate(NotificationType.RequestAvailable, model, settings);
@@ -260,7 +283,7 @@ namespace Ombi.Notifications.Agents
var plaintext = await LoadPlainTextMessage(NotificationType.RequestAvailable, model, settings);
message.Other.Add("PlainTextBody", plaintext);
-
+ await SendToSubscribers(settings, message);
message.To = model.RequestType == RequestType.Movie
? MovieRequest.RequestedUser.Email
: TvRequest.RequestedUser.Email;
diff --git a/src/Ombi.Notifications/Agents/MattermostNotification.cs b/src/Ombi.Notifications/Agents/MattermostNotification.cs
index f07d62b72..8590bfaae 100644
--- a/src/Ombi.Notifications/Agents/MattermostNotification.cs
+++ b/src/Ombi.Notifications/Agents/MattermostNotification.cs
@@ -21,7 +21,7 @@ namespace Ombi.Notifications.Agents
public class MattermostNotification : BaseNotification, IMattermostNotification
{
public MattermostNotification(IMattermostApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
- ISettingsService s) : base(sn, r, m, t,s,log)
+ ISettingsService s, IRepository sub) : base(sn, r, m, t,s,log, sub)
{
Api = api;
Logger = log;
diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs
index 575801bd2..1a716d9d6 100644
--- a/src/Ombi.Notifications/Agents/MobileNotification.cs
+++ b/src/Ombi.Notifications/Agents/MobileNotification.cs
@@ -22,7 +22,7 @@ namespace Ombi.Notifications.Agents
{
public MobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r,
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification,
- UserManager um) : base(sn, r, m, t, s,log)
+ UserManager um, IRepository sub) : base(sn, r, m, t, s,log, sub)
{
_api = api;
_logger = log;
@@ -167,6 +167,7 @@ namespace Ombi.Notifications.Agents
// Send to user
var playerIds = GetUsers(model, NotificationType.RequestDeclined);
+ await AddSubscribedUsers(playerIds);
await Send(playerIds, notification, settings);
}
@@ -185,6 +186,8 @@ namespace Ombi.Notifications.Agents
// Send to user
var playerIds = GetUsers(model, NotificationType.RequestApproved);
+
+ await AddSubscribedUsers(playerIds);
await Send(playerIds, notification, settings);
}
@@ -202,6 +205,8 @@ namespace Ombi.Notifications.Agents
};
// Send to user
var playerIds = GetUsers(model, NotificationType.RequestAvailable);
+
+ await AddSubscribedUsers(playerIds);
await Send(playerIds, notification, settings);
}
protected override Task Send(NotificationMessage model, MobileNotificationSettings settings)
@@ -269,6 +274,20 @@ namespace Ombi.Notifications.Agents
return playerIds;
}
+ private async Task AddSubscribedUsers(List 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));
+ }
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Ombi.Notifications/Agents/PushbulletNotification.cs b/src/Ombi.Notifications/Agents/PushbulletNotification.cs
index 21a384db6..24aa8cd22 100644
--- a/src/Ombi.Notifications/Agents/PushbulletNotification.cs
+++ b/src/Ombi.Notifications/Agents/PushbulletNotification.cs
@@ -17,7 +17,7 @@ namespace Ombi.Notifications.Agents
public class PushbulletNotification : BaseNotification, IPushbulletNotification
{
public PushbulletNotification(IPushbulletApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
- ISettingsService s) : base(sn, r, m, t,s,log)
+ ISettingsService s, IRepository sub) : base(sn, r, m, t,s,log, sub)
{
Api = api;
Logger = log;
diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs
index 505adc44e..5b82eb8a3 100644
--- a/src/Ombi.Notifications/Agents/PushoverNotification.cs
+++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs
@@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents
public class PushoverNotification : BaseNotification, IPushoverNotification
{
public PushoverNotification(IPushoverApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
- ISettingsService s) : base(sn, r, m, t, s, log)
+ ISettingsService s, IRepository sub) : base(sn, r, m, t, s, log, sub)
{
Api = api;
Logger = log;
diff --git a/src/Ombi.Notifications/Agents/SlackNotification.cs b/src/Ombi.Notifications/Agents/SlackNotification.cs
index d723c065a..894758591 100644
--- a/src/Ombi.Notifications/Agents/SlackNotification.cs
+++ b/src/Ombi.Notifications/Agents/SlackNotification.cs
@@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents
public class SlackNotification : BaseNotification, ISlackNotification
{
public SlackNotification(ISlackApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
- ISettingsService s) : base(sn, r, m, t, s, log)
+ ISettingsService s, IRepository sub) : base(sn, r, m, t, s, log, sub)
{
Api = api;
Logger = log;
diff --git a/src/Ombi.Notifications/Agents/TelegramNotification.cs b/src/Ombi.Notifications/Agents/TelegramNotification.cs
index 921fd3ad2..827b0b590 100644
--- a/src/Ombi.Notifications/Agents/TelegramNotification.cs
+++ b/src/Ombi.Notifications/Agents/TelegramNotification.cs
@@ -18,7 +18,8 @@ namespace Ombi.Notifications.Agents
{
public TelegramNotification(ITelegramApi api, ISettingsService sn, ILogger log,
INotificationTemplatesRepository r, IMovieRequestRepository m,
- ITvRequestRepository t, ISettingsService s) : base(sn, r, m, t,s,log)
+ ITvRequestRepository t, ISettingsService s
+ , IRepository sub) : base(sn, r, m, t,s,log, sub)
{
Api = api;
Logger = log;
diff --git a/src/Ombi.Notifications/Interfaces/BaseNotification.cs b/src/Ombi.Notifications/Interfaces/BaseNotification.cs
index f21d3fb12..507b8059b 100644
--- a/src/Ombi.Notifications/Interfaces/BaseNotification.cs
+++ b/src/Ombi.Notifications/Interfaces/BaseNotification.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
@@ -17,7 +19,7 @@ namespace Ombi.Notifications.Interfaces
public abstract class BaseNotification : INotification where T : Settings.Settings.Models.Settings, new()
{
protected BaseNotification(ISettingsService settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv,
- ISettingsService customization, ILogger> log)
+ ISettingsService customization, ILogger> log, IRepository sub)
{
Settings = settings;
TemplateRepository = templateRepo;
@@ -26,21 +28,24 @@ namespace Ombi.Notifications.Interfaces
CustomizationSettings = customization;
Settings.ClearCache();
CustomizationSettings.ClearCache();
+ RequestSubscription = sub;
_log = log;
}
-
+
protected ISettingsService Settings { get; }
protected INotificationTemplatesRepository TemplateRepository { get; }
protected IMovieRequestRepository MovieRepository { get; }
protected ITvRequestRepository TvRepository { get; }
protected CustomizationSettings Customization { get; set; }
+ protected IRepository RequestSubscription { get; set; }
private ISettingsService CustomizationSettings { get; }
private readonly ILogger> _log;
protected ChildRequests TvRequest { get; set; }
protected MovieRequests MovieRequest { get; set; }
-
+ protected IQueryable SubsribedUsers { get; private set; }
+
public abstract string NotificationName { get; }
public async Task NotifyAsync(NotificationOptions model)
@@ -54,20 +59,21 @@ namespace Ombi.Notifications.Interfaces
{
Settings.ClearCache();
if (settings == null) await NotifyAsync(model);
-
+
var notificationSettings = (T)settings;
-
+
if (!ValidateConfiguration(notificationSettings))
{
return;
}
-
+
// Is this a test?
// The request id for tests is -1
// Also issues are 0 since there might not be a request associated
if (model.RequestId > 0)
{
await LoadRequest(model.RequestId, model.RequestType);
+ SubsribedUsers = GetSubscriptions(model.RequestId, model.RequestType);
}
Customization = await CustomizationSettings.GetSettingsAsync();
@@ -126,7 +132,7 @@ namespace Ombi.Notifications.Interfaces
}
else
{
- TvRequest = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
+ TvRequest = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
}
}
@@ -152,13 +158,19 @@ namespace Ombi.Notifications.Interfaces
}
if (!template.Enabled)
{
- return new NotificationMessageContent {Disabled = true};
+ return new NotificationMessageContent { Disabled = true };
}
var parsed = Parse(model, template);
return parsed;
}
+ protected IQueryable 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)
{
var resolver = new NotificationMessageResolver();
@@ -166,7 +178,7 @@ namespace Ombi.Notifications.Interfaces
if (model.RequestType == RequestType.Movie)
{
_log.LogDebug("Notification options: {@model}, Req: {@MovieRequest}, Settings: {@Customization}", model, MovieRequest, Customization);
-
+
curlys.Setup(model, MovieRequest, Customization);
}
else
diff --git a/src/Ombi.Store/Context/IOmbiContext.cs b/src/Ombi.Store/Context/IOmbiContext.cs
index 55d7db563..0c716c7c4 100644
--- a/src/Ombi.Store/Context/IOmbiContext.cs
+++ b/src/Ombi.Store/Context/IOmbiContext.cs
@@ -42,5 +42,6 @@ namespace Ombi.Store.Context
DbSet SickRageEpisodeCache { get; set; }
DbSet RequestLogs { get; set; }
DbSet RecentlyAddedLogs { get; set; }
+ DbSet RequestSubscription { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Ombi.Store/Context/OmbiContext.cs b/src/Ombi.Store/Context/OmbiContext.cs
index d1963e765..8fb05f6ae 100644
--- a/src/Ombi.Store/Context/OmbiContext.cs
+++ b/src/Ombi.Store/Context/OmbiContext.cs
@@ -47,6 +47,7 @@ namespace Ombi.Store.Context
public DbSet SonarrEpisodeCache { get; set; }
public DbSet SickRageCache { get; set; }
public DbSet SickRageEpisodeCache { get; set; }
+ public DbSet RequestSubscription { get; set; }
public DbSet ApplicationConfigurations { get; set; }
diff --git a/src/Ombi.Store/Entities/RequestSubscription.cs b/src/Ombi.Store/Entities/RequestSubscription.cs
new file mode 100644
index 000000000..2f6d530c9
--- /dev/null
+++ b/src/Ombi.Store/Entities/RequestSubscription.cs
@@ -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; }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Store/Entities/Requests/ChildRequests.cs b/src/Ombi.Store/Entities/Requests/ChildRequests.cs
index 64c0bcc5c..3b5156ce5 100644
--- a/src/Ombi.Store/Entities/Requests/ChildRequests.cs
+++ b/src/Ombi.Store/Entities/Requests/ChildRequests.cs
@@ -13,6 +13,15 @@ namespace Ombi.Store.Entities.Requests
public int? IssueId { get; set; }
public SeriesType SeriesType { get; set; }
+ ///
+ /// This is to see if the user is subscribed in the UI
+ ///
+ [NotMapped]
+ public bool Subscribed { get; set; }
+
+ [NotMapped]
+ public bool ShowSubscribe { get; set; }
+
[ForeignKey(nameof(IssueId))]
public List Issues { get; set; }
diff --git a/src/Ombi.Store/Entities/Requests/MovieRequests.cs b/src/Ombi.Store/Entities/Requests/MovieRequests.cs
index 998c27707..675035140 100644
--- a/src/Ombi.Store/Entities/Requests/MovieRequests.cs
+++ b/src/Ombi.Store/Entities/Requests/MovieRequests.cs
@@ -12,6 +12,11 @@ namespace Ombi.Store.Entities.Requests
[ForeignKey(nameof(IssueId))]
public List Issues { get; set; }
+ [NotMapped]
+ public bool Subscribed { get; set; }
+ [NotMapped]
+ public bool ShowSubscribe { get; set; }
+
public int RootPathOverride { get; set; }
public int QualityOverride { get; set; }
}
diff --git a/src/Ombi.Store/Entities/Requests/TvRequests.cs b/src/Ombi.Store/Entities/Requests/TvRequests.cs
index 7a6abc792..432bc88ab 100644
--- a/src/Ombi.Store/Entities/Requests/TvRequests.cs
+++ b/src/Ombi.Store/Entities/Requests/TvRequests.cs
@@ -16,6 +16,7 @@ namespace Ombi.Store.Entities.Requests
public string Background { get; set; }
public DateTime ReleaseDate { get; set; }
public string Status { get; set; }
+
///
/// This is so we can correctly send the right amount of seasons to Sonarr
///
diff --git a/src/Ombi.Store/Migrations/20180516090124_RequestSubscription.Designer.cs b/src/Ombi.Store/Migrations/20180516090124_RequestSubscription.Designer.cs
new file mode 100644
index 000000000..e83458fef
--- /dev/null
+++ b/src/Ombi.Store/Migrations/20180516090124_RequestSubscription.Designer.cs
@@ -0,0 +1,981 @@
+//
+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("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken();
+
+ b.Property("Name")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedName")
+ .HasMaxLength(256);
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName")
+ .IsUnique()
+ .HasName("RoleNameIndex");
+
+ b.ToTable("AspNetRoles");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClaimType");
+
+ b.Property("ClaimValue");
+
+ b.Property("RoleId")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetRoleClaims");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ClaimType");
+
+ b.Property("ClaimValue");
+
+ b.Property("UserId")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserClaims");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("LoginProvider");
+
+ b.Property("ProviderKey");
+
+ b.Property("ProviderDisplayName");
+
+ b.Property("UserId")
+ .IsRequired();
+
+ b.HasKey("LoginProvider", "ProviderKey");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserLogins");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b =>
+ {
+ b.Property("UserId");
+
+ b.Property("RoleId");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetUserRoles");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId");
+
+ b.Property("LoginProvider");
+
+ b.Property("Name");
+
+ b.Property("Value");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AspNetUserTokens");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Type");
+
+ b.Property("Value");
+
+ b.HasKey("Id");
+
+ b.ToTable("ApplicationConfiguration");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.Audit", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AuditArea");
+
+ b.Property("AuditType");
+
+ b.Property("DateTime");
+
+ b.Property("Description");
+
+ b.Property("User");
+
+ b.HasKey("Id");
+
+ b.ToTable("Audit");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("TheMovieDbId");
+
+ b.HasKey("Id");
+
+ b.ToTable("CouchPotatoCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AddedAt");
+
+ b.Property("EmbyId")
+ .IsRequired();
+
+ b.Property("ImdbId");
+
+ b.Property("ProviderId");
+
+ b.Property("TheMovieDbId");
+
+ b.Property("Title");
+
+ b.Property("TvDbId");
+
+ b.Property("Type");
+
+ b.Property("Url");
+
+ b.HasKey("Id");
+
+ b.ToTable("EmbyContent");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AddedAt");
+
+ b.Property("EmbyId");
+
+ b.Property("EpisodeNumber");
+
+ b.Property("ImdbId");
+
+ b.Property("ParentId");
+
+ b.Property("ProviderId");
+
+ b.Property("SeasonNumber");
+
+ b.Property("TheMovieDbId");
+
+ b.Property("Title");
+
+ b.Property("TvDbId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentId");
+
+ b.ToTable("EmbyEpisode");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Content");
+
+ b.Property("SettingsName");
+
+ b.HasKey("Id");
+
+ b.ToTable("GlobalSettings");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Agent");
+
+ b.Property("Enabled");
+
+ b.Property("Message");
+
+ b.Property("NotificationType");
+
+ b.Property("Subject");
+
+ b.HasKey("Id");
+
+ b.ToTable("NotificationTemplates");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AddedAt");
+
+ b.Property("PlayerId");
+
+ b.Property("UserId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("NotificationUserId");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AccessFailedCount");
+
+ b.Property("Alias");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken();
+
+ b.Property("Email")
+ .HasMaxLength(256);
+
+ b.Property("EmailConfirmed");
+
+ b.Property("EmbyConnectUserId");
+
+ b.Property("EpisodeRequestLimit");
+
+ b.Property("LastLoggedIn");
+
+ b.Property("LockoutEnabled");
+
+ b.Property("LockoutEnd");
+
+ b.Property("MovieRequestLimit");
+
+ b.Property("NormalizedEmail")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedUserName")
+ .HasMaxLength(256);
+
+ b.Property("PasswordHash");
+
+ b.Property("PhoneNumber");
+
+ b.Property("PhoneNumberConfirmed");
+
+ b.Property("ProviderUserId");
+
+ b.Property("SecurityStamp");
+
+ b.Property("TwoFactorEnabled");
+
+ b.Property("UserAccessToken");
+
+ b.Property("UserName")
+ .HasMaxLength(256);
+
+ b.Property("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("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("EpisodeNumber");
+
+ b.Property("GrandparentKey");
+
+ b.Property("Key");
+
+ b.Property("ParentKey");
+
+ b.Property("SeasonNumber");
+
+ b.Property("Title");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GrandparentKey");
+
+ b.ToTable("PlexEpisode");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ParentKey");
+
+ b.Property("PlexContentId");
+
+ b.Property("PlexServerContentId");
+
+ b.Property("SeasonKey");
+
+ b.Property("SeasonNumber");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PlexServerContentId");
+
+ b.ToTable("PlexSeasonsContent");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AddedAt");
+
+ b.Property("ImdbId");
+
+ b.Property("Key");
+
+ b.Property("Quality");
+
+ b.Property("ReleaseYear");
+
+ b.Property("TheMovieDbId");
+
+ b.Property("Title");
+
+ b.Property("TvDbId");
+
+ b.Property("Type");
+
+ b.Property("Url");
+
+ b.HasKey("Id");
+
+ b.ToTable("PlexServerContent");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("HasFile");
+
+ b.Property("TheMovieDbId");
+
+ b.HasKey("Id");
+
+ b.ToTable("RadarrCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AddedAt");
+
+ b.Property("ContentId");
+
+ b.Property("ContentType");
+
+ b.Property("EpisodeNumber");
+
+ b.Property("SeasonNumber");
+
+ b.Property("Type");
+
+ b.HasKey("Id");
+
+ b.ToTable("RecentlyAddedLog");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Approved");
+
+ b.Property("Available");
+
+ b.Property("Denied");
+
+ b.Property("DeniedReason");
+
+ b.Property("IssueId");
+
+ b.Property("ParentRequestId");
+
+ b.Property("RequestType");
+
+ b.Property("RequestedDate");
+
+ b.Property("RequestedUserId");
+
+ b.Property