|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Globalization;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Jellyfin.Data.Entities;
|
|
|
|
using Jellyfin.Data.Enums;
|
|
|
|
using MediaBrowser.Common.Configuration;
|
|
|
|
using MediaBrowser.Common.Extensions;
|
|
|
|
using MediaBrowser.Controller.Configuration;
|
|
|
|
using MediaBrowser.Controller.Entities;
|
|
|
|
using MediaBrowser.Controller.Library;
|
|
|
|
using MediaBrowser.Controller.Notifications;
|
|
|
|
using MediaBrowser.Model.Dto;
|
|
|
|
using MediaBrowser.Model.Notifications;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
|
|
|
namespace Emby.Notifications
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// NotificationManager class.
|
|
|
|
/// </summary>
|
|
|
|
public class NotificationManager : INotificationManager
|
|
|
|
{
|
|
|
|
private readonly ILogger _logger;
|
|
|
|
private readonly IUserManager _userManager;
|
|
|
|
private readonly IServerConfigurationManager _config;
|
|
|
|
|
|
|
|
private INotificationService[] _services = Array.Empty<INotificationService>();
|
|
|
|
private INotificationTypeFactory[] _typeFactories = Array.Empty<INotificationTypeFactory>();
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="NotificationManager" /> class.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="logger">The logger.</param>
|
|
|
|
/// <param name="userManager">The user manager.</param>
|
|
|
|
/// <param name="config">The server configuration manager.</param>
|
|
|
|
public NotificationManager(
|
|
|
|
ILogger<NotificationManager> logger,
|
|
|
|
IUserManager userManager,
|
|
|
|
IServerConfigurationManager config)
|
|
|
|
{
|
|
|
|
_logger = logger;
|
|
|
|
_userManager = userManager;
|
|
|
|
_config = config;
|
|
|
|
}
|
|
|
|
|
|
|
|
private NotificationOptions GetConfiguration()
|
|
|
|
{
|
|
|
|
return _config.GetConfiguration<NotificationOptions>("notifications");
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
public Task SendNotification(NotificationRequest request, CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
return SendNotification(request, null, cancellationToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
public Task SendNotification(NotificationRequest request, BaseItem? relatedItem, CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
var notificationType = request.NotificationType;
|
|
|
|
|
|
|
|
var options = string.IsNullOrEmpty(notificationType) ?
|
|
|
|
null :
|
|
|
|
GetConfiguration().GetOptions(notificationType);
|
|
|
|
|
|
|
|
var users = GetUserIds(request, options)
|
|
|
|
.Select(i => _userManager.GetUserById(i))
|
|
|
|
.Where(i => relatedItem == null || relatedItem.IsVisibleStandalone(i))
|
|
|
|
.ToArray();
|
|
|
|
|
|
|
|
var title = request.Name;
|
|
|
|
var description = request.Description;
|
|
|
|
|
|
|
|
var tasks = _services.Where(i => IsEnabled(i, notificationType))
|
|
|
|
.Select(i => SendNotification(request, i, users, title, description, cancellationToken));
|
|
|
|
|
|
|
|
return Task.WhenAll(tasks);
|
|
|
|
}
|
|
|
|
|
|
|
|
private Task SendNotification(
|
|
|
|
NotificationRequest request,
|
|
|
|
INotificationService service,
|
|
|
|
IEnumerable<User> users,
|
|
|
|
string title,
|
|
|
|
string description,
|
|
|
|
CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
users = users.Where(i => IsEnabledForUser(service, i))
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
var tasks = users.Select(i => SendNotification(request, service, title, description, i, cancellationToken));
|
|
|
|
|
|
|
|
return Task.WhenAll(tasks);
|
|
|
|
}
|
|
|
|
|
|
|
|
private IEnumerable<Guid> GetUserIds(NotificationRequest request, NotificationOption? options)
|
|
|
|
{
|
|
|
|
if (request.SendToUserMode.HasValue)
|
|
|
|
{
|
|
|
|
switch (request.SendToUserMode.Value)
|
|
|
|
{
|
|
|
|
case SendToUserType.Admins:
|
|
|
|
return _userManager.Users.Where(i => i.HasPermission(PermissionKind.IsAdministrator))
|
|
|
|
.Select(i => i.Id);
|
|
|
|
case SendToUserType.All:
|
|
|
|
return _userManager.UsersIds;
|
|
|
|
case SendToUserType.Custom:
|
|
|
|
return request.UserIds;
|
|
|
|
default:
|
|
|
|
throw new ArgumentException("Unrecognized SendToUserMode: " + request.SendToUserMode.Value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options != null && !string.IsNullOrEmpty(request.NotificationType))
|
|
|
|
{
|
|
|
|
var config = GetConfiguration();
|
|
|
|
|
|
|
|
return _userManager.Users
|
|
|
|
.Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N", CultureInfo.InvariantCulture), i))
|
|
|
|
.Select(i => i.Id);
|
|
|
|
}
|
|
|
|
|
|
|
|
return request.UserIds;
|
|
|
|
}
|
|
|
|
|
|
|
|
private async Task SendNotification(
|
|
|
|
NotificationRequest request,
|
|
|
|
INotificationService service,
|
|
|
|
string title,
|
|
|
|
string description,
|
|
|
|
User user,
|
|
|
|
CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
var notification = new UserNotification
|
|
|
|
{
|
|
|
|
Date = request.Date,
|
|
|
|
Description = description,
|
|
|
|
Level = request.Level,
|
|
|
|
Name = title,
|
|
|
|
Url = request.Url,
|
|
|
|
User = user
|
|
|
|
};
|
|
|
|
|
|
|
|
_logger.LogDebug("Sending notification via {0} to user {1}", service.Name, user.Username);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
await service.SendNotification(notification, cancellationToken).ConfigureAwait(false);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
_logger.LogError(ex, "Error sending notification to {0}", service.Name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool IsEnabledForUser(INotificationService service, User user)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return service.IsEnabledForUser(user);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
_logger.LogError(ex, "Error in IsEnabledForUser");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool IsEnabled(INotificationService service, string notificationType)
|
|
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(notificationType))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetConfiguration().IsServiceEnabled(service.Name, notificationType);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
public void AddParts(IEnumerable<INotificationService> services, IEnumerable<INotificationTypeFactory> notificationTypeFactories)
|
|
|
|
{
|
|
|
|
_services = services.ToArray();
|
|
|
|
_typeFactories = notificationTypeFactories.ToArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
public List<NotificationTypeInfo> GetNotificationTypes()
|
|
|
|
{
|
|
|
|
var list = _typeFactories.Select(i =>
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return i.GetNotificationTypes().ToList();
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
_logger.LogError(ex, "Error in GetNotificationTypes");
|
|
|
|
return new List<NotificationTypeInfo>();
|
|
|
|
}
|
|
|
|
}).SelectMany(i => i).ToList();
|
|
|
|
|
|
|
|
var config = GetConfiguration();
|
|
|
|
|
|
|
|
foreach (var i in list)
|
|
|
|
{
|
|
|
|
i.Enabled = config.IsEnabled(i.Type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
public IEnumerable<NameIdPair> GetNotificationServices()
|
|
|
|
{
|
|
|
|
return _services.Select(i => new NameIdPair
|
|
|
|
{
|
|
|
|
Name = i.Name,
|
|
|
|
Id = i.Name.GetMD5().ToString("N", CultureInfo.InvariantCulture)
|
|
|
|
}).OrderBy(i => i.Name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|