You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Ombi/src/Ombi.Notifications/BaseNotification.cs

270 lines
12 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Notifications.Exceptions;
using Ombi.Notifications.Models;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
namespace Ombi.Notifications
{
public abstract class BaseNotification<T> : INotification where T : Settings.Settings.Models.Settings, new()
{
protected BaseNotification(ISettingsService<T> settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv,
ISettingsService<CustomizationSettings> customization, ILogger<BaseNotification<T>> log, IRepository<RequestSubscription> sub, IMusicRequestRepository album,
IRepository<UserNotificationPreferences> notificationUserPreferences, UserManager<OmbiUser> um)
{
Settings = settings;
TemplateRepository = templateRepo;
MovieRepository = movie;
TvRepository = tv;
CustomizationSettings = customization;
RequestSubscription = sub;
_log = log;
AlbumRepository = album;
UserNotificationPreferences = notificationUserPreferences;
_userManager = um;
Settings?.ClearCache();
}
protected ISettingsService<T> Settings { get; }
protected INotificationTemplatesRepository TemplateRepository { get; }
protected IMovieRequestRepository MovieRepository { get; }
protected ITvRequestRepository TvRepository { get; }
protected IMusicRequestRepository AlbumRepository { get; }
protected CustomizationSettings Customization { get; set; }
protected IRepository<RequestSubscription> RequestSubscription { get; set; }
protected IRepository<UserNotificationPreferences> UserNotificationPreferences { get; set; }
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
private readonly ILogger<BaseNotification<T>> _log;
private readonly UserManager<OmbiUser> _userManager;
protected ChildRequests TvRequest { get; set; }
protected AlbumRequest AlbumRequest { get; set; }
protected MovieRequests MovieRequest { get; set; }
protected IQueryable<OmbiUser> Subscribed { get; private set; }
public abstract string NotificationName { get; }
public async Task NotifyAsync(NotificationOptions model)
{
var configuration = await GetConfiguration();
await NotifyAsync(model, configuration);
}
public async Task NotifyAsync(NotificationOptions model, Settings.Settings.Models.Settings settings)
{
if (settings == null)
{
await NotifyAsync(model);
return;
}
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);
Subscribed = GetSubscriptions(model.RequestId, model.RequestType);
}
Customization = await CustomizationSettings.GetSettingsAsync();
try
{
switch (model.NotificationType)
{
case NotificationType.NewRequest:
await NewRequest(model, notificationSettings);
break;
case NotificationType.Issue:
await NewIssue(model, notificationSettings);
break;
case NotificationType.RequestAvailable:
await AvailableRequest(model, notificationSettings);
break;
case NotificationType.RequestApproved:
await RequestApproved(model, notificationSettings);
break;
case NotificationType.Test:
await Test(model, notificationSettings);
break;
case NotificationType.RequestDeclined:
await RequestDeclined(model, notificationSettings);
break;
case NotificationType.ItemAddedToFaultQueue:
await AddedToRequestQueue(model, notificationSettings);
break;
case NotificationType.IssueResolved:
await IssueResolved(model, notificationSettings);
break;
case NotificationType.IssueComment:
await IssueComment(model, notificationSettings);
break;
case NotificationType.PartiallyAvailable:
await PartiallyAvailable(model, notificationSettings);
break;
case NotificationType.AdminNote:
case NotificationType.WelcomeEmail:
case NotificationType.Newsletter:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
catch (NotImplementedException)
{
// Do nothing, it's not implimented meaning it might not be ready or even used
}
}
/// <summary>
/// Loads the TV or Movie Request
/// </summary>
/// <param name="requestId"></param>
/// <param name="type"></param>
/// <returns></returns>
protected virtual async Task LoadRequest(int requestId, RequestType type)
{
if (type == RequestType.Movie)
{
MovieRequest = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId);
}
else if (type == RequestType.TvShow)
{
TvRequest = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
}
else if (type == RequestType.Album)
{
AlbumRequest = await AlbumRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId);
}
}
private async Task<T> GetConfiguration()
{
var settings = await Settings.GetSettingsAsync();
return settings;
}
/// <summary>
/// Loads the correct template from the DB
/// </summary>
/// <param name="agent"></param>
/// <param name="type"></param>
/// <param name="model"></param>
/// <returns></returns>
protected virtual async Task<NotificationMessageContent> LoadTemplate(NotificationAgent agent, NotificationType type, NotificationOptions model)
{
var template = await TemplateRepository.GetTemplate(agent, type);
if (template == null)
{
throw new TemplateMissingException($"The template for {agent} and type {type} is missing");
}
if (!template.Enabled)
{
return new NotificationMessageContent { Disabled = true };
}
if (model.UserId.IsNullOrEmpty())
{
if (model.RequestType == RequestType.Movie)
{
model.UserId = MovieRequest.RequestedUserId;
}
if (model.RequestType == RequestType.Album)
{
model.UserId = AlbumRequest.RequestedUserId;
}
if (model.RequestType == RequestType.TvShow)
{
model.UserId = TvRequest.RequestedUserId;
}
}
var parsed = Parse(model, template, agent);
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);
}
protected UserNotificationPreferences GetUserPreference(string userId, NotificationAgent agent)
{
return UserNotificationPreferences.GetAll()
.FirstOrDefault(x => x.Agent == agent && x.UserId == userId);
}
protected async Task<IEnumerable<OmbiUser>> GetAdminUsers()
{
IEnumerable<OmbiUser> recipients = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin);
return recipients;
}
protected async Task<IEnumerable<OmbiUser>> GetPrivilegedUsers()
{
IEnumerable<OmbiUser> recipients = await GetAdminUsers();
recipients = recipients.Concat(await _userManager.GetUsersInRoleAsync(OmbiRoles.PowerUser));
return recipients;
}
private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template, NotificationAgent agent)
{
var resolver = new NotificationMessageResolver();
var curlys = new NotificationMessageCurlys();
var preference = GetUserPreference(model.UserId, agent);
if (model.RequestType == RequestType.Movie)
{
_log.LogDebug("Notification options: {@model}, Req: {@MovieRequest}, Settings: {@Customization}", model, MovieRequest, Customization);
curlys.Setup(model, MovieRequest, Customization, preference);
}
else if (model.RequestType == RequestType.TvShow)
{
_log.LogDebug("Notification options: {@model}, Req: {@TvRequest}, Settings: {@Customization}", model, TvRequest, Customization);
curlys.Setup(model, TvRequest, Customization, preference);
}
else if (model.RequestType == RequestType.Album)
{
_log.LogDebug("Notification options: {@model}, Req: {@AlbumRequest}, Settings: {@Customization}", model, AlbumRequest, Customization);
curlys.Setup(model, AlbumRequest, Customization, preference);
}
var parsed = resolver.ParseMessage(template, curlys);
return parsed;
}
protected abstract bool ValidateConfiguration(T settings);
protected abstract Task NewRequest(NotificationOptions model, T settings);
protected abstract Task NewIssue(NotificationOptions model, T settings);
protected abstract Task IssueComment(NotificationOptions model, T settings);
protected abstract Task IssueResolved(NotificationOptions model, T settings);
protected abstract Task AddedToRequestQueue(NotificationOptions model, T settings);
protected abstract Task RequestDeclined(NotificationOptions model, T settings);
protected abstract Task RequestApproved(NotificationOptions model, T settings);
protected abstract Task AvailableRequest(NotificationOptions model, T settings);
protected abstract Task PartiallyAvailable(NotificationOptions model, T settings);
protected abstract Task Send(NotificationMessage model, T settings);
protected abstract Task Test(NotificationOptions model, T settings);
}
}