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 { /// /// NotificationManager class. /// public class NotificationManager : INotificationManager { private readonly ILogger _logger; private readonly IUserManager _userManager; private readonly IServerConfigurationManager _config; private INotificationService[] _services = Array.Empty(); private INotificationTypeFactory[] _typeFactories = Array.Empty(); /// /// Initializes a new instance of the class. /// /// The logger. /// The user manager. /// The server configuration manager. public NotificationManager( ILogger logger, IUserManager userManager, IServerConfigurationManager config) { _logger = logger; _userManager = userManager; _config = config; } private NotificationOptions GetConfiguration() { return _config.GetConfiguration("notifications"); } /// public Task SendNotification(NotificationRequest request, CancellationToken cancellationToken) { return SendNotification(request, null, cancellationToken); } /// 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 is 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 users, string title, string description, CancellationToken cancellationToken) { users = users.Where(i => IsEnabledForUser(service, i)); var tasks = users.Select(i => SendNotification(request, service, title, description, i, cancellationToken)); return Task.WhenAll(tasks); } private IEnumerable 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 is not 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); } /// public void AddParts(IEnumerable services, IEnumerable notificationTypeFactories) { _services = services.ToArray(); _typeFactories = notificationTypeFactories.ToArray(); } /// public List GetNotificationTypes() { var list = _typeFactories.Select(i => { try { return i.GetNotificationTypes().ToList(); } catch (Exception ex) { _logger.LogError(ex, "Error in GetNotificationTypes"); return new List(); } }).SelectMany(i => i).ToList(); var config = GetConfiguration(); foreach (var i in list) { i.Enabled = config.IsEnabled(i.Type); } return list; } /// public IEnumerable GetNotificationServices() { return _services.Select(i => new NameIdPair { Name = i.Name, Id = i.Name.GetMD5().ToString("N", CultureInfo.InvariantCulture) }).OrderBy(i => i.Name); } } }