public async Task SendBatchNotifications(NotificationType type, bool useHttps, string host, int?count = null) { if (!type.ShouldBeBatched()) { throw new InvalidOperationException($"Notifications of type {type} can't be batched"); } using (var db = _dbService.GetConnection()) { var userIds = await db.QueryAsync <int>($@" Select Id From Users Where {type.GetUserColumnName()} < @now", new { now = DateTime.UtcNow }); var successfulUserIds = new List <int>(); foreach (var userId in userIds) { var message = new Models.Services.PushNotificationMessage( type.GetTitle(count), type.GetUrl(useHttps, host, userId), type.GetBody(), type.ToString(), true); if (await SendNotification(userId, message)) { successfulUserIds.Add(userId); } } await db.ExecuteAsync($@" Update Users Set {type.GetUserColumnName()} = DateAdd(minute, NotificationsIntervalId * NotificationsIntervalValue, @now) Where Id In @successfulUserIds", new { successfulUserIds, columnName = type.GetUserColumnName(), now = DateTime.UtcNow }); } }
private async Task <bool> SendNotification(int userId, Models.Services.PushNotificationMessage message) { using (var db = _dbService.GetConnection()) { var endpointsToRemove = new List <string>(); var success = false; var currentSubscriptions = await GetCurrentSubscriptions(userId, db); var options = new Dictionary <string, object> { ["vapidDetails"] = _vapidDetails }; if (message.Topic.HasValue()) { options["headers"] = new Dictionary <string, object> { ["topic"] = message.Topic }; } foreach (var subscriptionData in currentSubscriptions) { var subscription = new PushSubscription(subscriptionData.Endpoint, subscriptionData.P256dh, subscriptionData.Auth); try { await _webPushClient.SendNotificationAsync(subscription, Jil.JSON.Serialize(message, Jil.Options.CamelCase), options); success = true; } catch (WebPushException exception) { if (exception.StatusCode == HttpStatusCode.NotFound || exception.StatusCode == HttpStatusCode.Gone) { endpointsToRemove.Add(subscriptionData.Endpoint); } } } if (endpointsToRemove.Count > 0) { await SetCurrentSubscriptions(userId, currentSubscriptions.Where(s => !endpointsToRemove.Contains(s.Endpoint)), db); } return(success); } }
public async Task <bool> SendNotification(int userId, NotificationType type, bool useHttps, string host) { if (type.ShouldBeBatched()) { throw new InvalidOperationException($"Notifications of type {type} should be batched"); } using (var db = _dbService.GetConnection()) { var shouldSendIt = await db.QueryFirstOrDefaultAsync <bool>($@" Select Top 1 1 From Users Where Id = @userId And {type.GetUserColumnName()} < @now", new { userId, now = DateTime.UtcNow }); if (shouldSendIt) { var message = new Models.Services.PushNotificationMessage( type.GetTitle(), type.GetUrl(useHttps, host, userId), type.GetBody(), type.ToString(), true); var success = await SendNotification(userId, message); if (success) { await db.ExecuteAsync($@" Update Users Set {type.GetUserColumnName()} = DateAdd(minute, NotificationsIntervalId * NotificationsIntervalValue, @now) Where Id = @userId", new { userId, now = DateTime.UtcNow }); } return(success); } } return(false); }