public async Task SendNotification(NotificationScope scope, BaseNotification notification) { if (scope == null) { throw new ArgumentNullException(nameof(scope)); } if (notification == null) { throw new ArgumentNullException(nameof(notification)); } var users = await GetUsers(scope); using (var db = _contextFactory.CreateContext()) { foreach (var uid in users) { var obj = JsonConvert.SerializeObject(notification); var data = new NotificationData { Id = Guid.NewGuid().ToString(), Created = DateTimeOffset.UtcNow, ApplicationUserId = uid, NotificationType = GetNotificationTypeString(notification.GetType()), Blob = ZipUtils.Zip(obj), Seen = false }; db.Notifications.Add(data); } await db.SaveChangesAsync(); } }
public async Task SendNotification(NotificationScope scope, BaseNotification notification) { ArgumentNullException.ThrowIfNull(scope); ArgumentNullException.ThrowIfNull(notification); var users = await GetUsers(scope, notification.Identifier); await using (var db = _contextFactory.CreateContext()) { foreach (var uid in users) { var obj = JsonConvert.SerializeObject(notification); var data = new NotificationData { Id = Guid.NewGuid().ToString(), Created = DateTimeOffset.UtcNow, ApplicationUserId = uid, NotificationType = notification.NotificationType, Blob = ZipUtils.Zip(obj), Seen = false }; await db.Notifications.AddAsync(data); } await db.SaveChangesAsync(); } foreach (string user in users) { _notificationManager.InvalidateNotificationCache(user); } }
private IEnumerator AddNotification(int lines, NotificationScope scope) { string message = string.Join("\n", Enumerable.Range(0, lines).Select(i => "asdf" + i)); NotificationBox.Add(new Notification() { Message = message, Type = GetNotificationType(), Scope = scope, }); yield break; }
private async Task <string[]> GetUsers(NotificationScope scope, string notificationIdentifier) { await using var ctx = _contextFactory.CreateContext(); var split = notificationIdentifier.Split('_', StringSplitOptions.None); var terms = new List <string>(); foreach (var t in split) { terms.Add(terms.Any() ? $"{terms.Last().TrimEnd(';')}_{t};" : $"{t};"); } IQueryable <ApplicationUser> query; switch (scope) { case AdminScope _: { query = _userManager.GetUsersInRoleAsync(Roles.ServerAdmin).Result.AsQueryable(); break; } case StoreScope s: query = ctx.UserStore .Include(store => store.ApplicationUser) .Where(u => u.StoreDataId == s.StoreId) .Select(u => u.ApplicationUser); break; case UserScope userScope: query = ctx.Users .Where(user => user.Id == userScope.UserId); break; default: throw new NotSupportedException("Notification scope not supported"); } query = query.Where(store => store.DisabledNotifications != "all"); foreach (string term in terms) { // Cannot specify StringComparison as EF core does not support it and would attempt client-side evaluation // ReSharper disable once CA1307 #pragma warning disable CA1307 // Specify StringComparison query = query.Where(user => user.DisabledNotifications == null || !user.DisabledNotifications.Contains(term)); #pragma warning restore CA1307 // Specify StringComparison } return(query.Select(user => user.Id).ToArray()); }
private async Task <string[]> GetUsers(NotificationScope scope) { if (scope is AdminScope) { var admins = await _userManager.GetUsersInRoleAsync(Roles.ServerAdmin); return(admins.Select(a => a.Id).ToArray()); } if (scope is StoreScope s) { using var ctx = _contextFactory.CreateContext(); return(ctx.UserStore .Where(u => u.StoreDataId == s.StoreId) .Select(u => u.ApplicationUserId) .ToArray()); } throw new NotSupportedException("Notification scope not supported"); }
public static void Send(Notification notification, NotificationScope scope) { // test inputs //Validate.IsNotNull<ArgumentNullException>(notification, "Must pass a valid notification"); // adds the sender (current named instance of NB) to the notification // to find out that a certain notification was sent by yourself! if (string.IsNullOrEmpty(notification.Sender)) { // only the initial sender is important. Do not overwrite by intermediary service callback // implementations calling this Send() too. notification.Sender = Id; } // fire locally. Get a copied list of subscription references. lock (subscriptions) { IList <Subscription> copiedSubscriptions = subscriptions.Get(notification.GetType()); foreach (Subscription subscription in copiedSubscriptions) { try { // fire when no filter specified if (subscription.Filters == null) { SendAsync(subscription, notification, scope); continue; } if (subscription.Filters.Count == 0) { SendAsync(subscription, notification, scope); continue; } // fire when one of the filters evaluates to true bool filterIncluded = true; bool filterExcluded = false; foreach (ISubscriptionFilter subscriptionFilter in subscription.Filters) { // fire when one (and only when; not and/or logic) filter include evaluates true if (subscriptionFilter.FilterOperation == SubscriptionFilterOperation.Include && !subscriptionFilter.IsMatch(notification)) { filterIncluded = false; // filter out } // however, does not fire when one (and only when; not and/or logic) filter exclude evaluates true if (subscriptionFilter.FilterOperation == SubscriptionFilterOperation.Exclude && subscriptionFilter.IsMatch(notification)) { filterExcluded = true; // filter out } if (filterIncluded && !filterExcluded) { SendAsync(subscription, notification, scope); } } } catch (Exception ex) { logger.Warn("One of the subscription handler invocations failed.", ex); } } } }
private static void SendAsync(Subscription subscription, Notification notification, NotificationScope scope) { if (subscription.Scope == scope || scope == NotificationScope.Remote) { // go to another thread to execute delegate! ThreadPool.QueueUserWorkItem( delegate(object state) { try { // invoke one separate invocation handler on pool thread to decouple. subscription.Send(notification); } catch (Exception ex) { logger.Warn(string.Format(CultureInfo.InvariantCulture, "{0} subscription handler {1} invocations failed.", subscription.Scope, subscription.NotificationType.FullName), ex); } }, null); } }