예제 #1
0
        public async Task SendAsync(string clientId, string userId, Notification notification)
        {
            if (string.IsNullOrEmpty(clientId))
            {
                throw new ArgumentNullException(nameof(clientId));
            }

            var subscriptions = await _db.SubscriptionSet
                                .AsNoTracking()
                                .Where(s =>
                                       s.ClientId == clientId &&
                                       s.Client.IsEnabled &&
                                       (string.IsNullOrEmpty(userId) || s.UserId == userId)
                                       )
                                .ProjectTo <WebPush.PushSubscription>(_mapper.ConfigurationProvider)
                                .ToListAsync();

            // no subscriptions?
            if (subscriptions.Count == 0)
            {
                // no need to go further
                return;
            }

            string jsonNotification = System.Text.Json.JsonSerializer.Serialize(notification, Pacem.Push.Serialization.JsonSerializer.JsonSerializerOptions);

            VapidDetails vapidData = await _vapid.GetVapidDetailsAsync(clientId);

            WebPush.VapidDetails vapid = _mapper.Map <WebPush.VapidDetails>(vapidData);

            foreach (var subscription in subscriptions)
            {
                try
                {
                    _logger.LogInformation("Sending {p256dh} subscription to encrypt message:\n{message}...", subscription.P256DH, jsonNotification);
                    _client.SendNotification(subscription, jsonNotification, vapid);
                    _logger.LogInformation("...sent!");
                }
                catch (WebPush.WebPushException exc)
                {
                    if (exc.Message == /* This is a magic string from the WebPush lib */ "Subscription no longer valid")
                    {
                        // tidy-up
                        await UnsubscribeAsync(clientId, subscription.P256DH);
                    }
                    else
                    {
                        // what's wrong?
                        _logger.LogError(exc, exc.Message);
                    }
                }
            }
        }
예제 #2
0
        private static void doPushBackgroundWork()
        {
            try
            {
                WebPush.WebPushClient client = new WebPush.WebPushClient();
                while (true)
                {
                    try
                    {
                        if (!newEvents.IsEmpty)
                        {
                            // Accumulate a list of events we want to notify each subscription about.
                            // Map subscriptionkey > event list
                            Dictionary <string, List <EventToNotifyAbout> > accumulatedEvents = new Dictionary <string, List <EventToNotifyAbout> >();
                            List <User> users = Settings.data.GetAllUsers();
                            while (newEvents.TryDequeue(out EventToNotifyAbout en))
                            {
                                foreach (User u in users)
                                {
                                    string[] subscriptionKeys = u.GetPushNotificationSubscriptions(en.projectName, en.ev.FolderId);
                                    foreach (string key in subscriptionKeys)
                                    {
                                        List <EventToNotifyAbout> events;
                                        if (!accumulatedEvents.TryGetValue(key, out events))
                                        {
                                            accumulatedEvents[key] = events = new List <EventToNotifyAbout>();
                                        }
                                        events.Add(en);
                                    }
                                }
                            }

                            if (accumulatedEvents.Count > 0)
                            {
                                WebPush.VapidDetails vapidDetails = new WebPush.VapidDetails(GetVapidSubject(), Settings.data.vapidPublicKey, Settings.data.vapidPrivateKey);
                                // Build and send one notification to each affected subscription.
                                foreach (KeyValuePair <string, List <EventToNotifyAbout> > kvp in accumulatedEvents)
                                {
                                    string subscriptionKey           = kvp.Key;
                                    List <EventToNotifyAbout> events = kvp.Value;

                                    WebPush.PushSubscription subscription = null;
                                    try
                                    {
                                        dynamic dyn = JsonConvert.DeserializeObject(subscriptionKey);
                                        subscription          = new WebPush.PushSubscription();
                                        subscription.Endpoint = dyn.endpoint;
                                        subscription.P256DH   = dyn.keys.p256dh;
                                        subscription.Auth     = dyn.keys.auth;
                                    }
                                    catch { }

                                    // For now, we'll just ignore any unparseable subscription keys.
                                    // I know this is asking for trouble later on, and I'm sorry for that.
                                    if (subscription != null)
                                    {
                                        StringBuilder sb = new StringBuilder();

                                        PushMessage message = new PushMessage(Settings.data.systemName, events.Count + " new events:");
                                        if (events.Count == 1)
                                        {
                                            EventToNotifyAbout en = events[0];
                                            message.message = en.ev.EventType.ToString() + ": " + en.ev.SubType;
                                            message.eventid = en.ev.EventId;
                                        }

                                        // If all events are in the same project, set message.project so that clicking the notification can open the correct project.
                                        string projectName = events[0].projectName;
                                        if (events.All(en => en.projectName == projectName))
                                        {
                                            message.project = projectName;

                                            // If all events are in the same folder, set message.folderid so that clicking the notification can open the correct folder.
                                            int folderId = events[0].ev.FolderId;
                                            if (events.All(en => en.ev.FolderId == folderId))
                                            {
                                                message.folderid = folderId;
                                            }
                                        }

                                        try
                                        {
                                            client.SendNotification(subscription, message.ToString(), vapidDetails);
                                        }
                                        catch (Exception ex)
                                        {
                                            Logger.Debug(ex, "Failed to send push notification.");
                                        }
                                    }
                                }
                            }
                        }
                        Thread.Sleep(1000);
                    }
                    catch (ThreadAbortException) { }
                    catch (Exception ex)
                    {
                        Emailer.SendError(null, "Error in PushManager", ex);
                    }
                }
            }
            catch (ThreadAbortException) { }
            catch (Exception ex)
            {
                Logger.Debug(ex);
            }
        }