public SqlServerPushService(PushDbContext db, IMapper mapper, IVapidDetailsStore vapid, ILogger <SqlServerPushService> logger)
 {
     _db     = db;
     _vapid  = vapid;
     _mapper = mapper;
     _client = new WebPush.WebPushClient();
     _logger = logger;
 }
Beispiel #2
0
        public async Task <ActionResult> SendNotification(int id)
        {
            var sub = db.PushSubscriptions.Find(id);

            if (sub == null)
            {
                return(HttpNotFound());
            }
            else
            {
                var publicKey  = ConfigurationManager.AppSettings["VapidPublicKey"];
                var privateKey = ConfigurationManager.AppSettings["VapidPrivateKey"];
                var subject    = @"mailto: [email protected]";

                Uri    uri      = new Uri(sub.Url);
                string audience = $"{uri.Scheme}{Uri.SchemeDelimiter}{uri.Host}";

                var subscription = new WebPush.PushSubscription(sub.Url, sub.P256dh, sub.Auth);
                var vapidDetails = new WebPush.VapidDetails(subject, publicKey, privateKey);

                var client = new WebPush.WebPushClient();
                try
                {
                    var opts = new Dictionary <string, object>();
                    opts["vapidDetails"] = vapidDetails;

                    var notification = new PushNotification();
                    notification.Title          = "Something New Happened!";
                    notification.Body           = "There was some activity on your account and you should go do something about it.";
                    notification.Icon           = "https://s3.amazonaws.com/images.productionhub.com/icons/asterisk.png";
                    notification.Data.Url       = "/";
                    notification.Data.ListingId = "142484";
                    notification.Actions.Add(new NotificationAction {
                        Action = "ignore", Title = "Ignore Lead", Icon = "https://s3.amazonaws.com/images.productionhub.com/icons/icon_remove_red.png"
                    });
                    notification.Actions.Add(new NotificationAction {
                        Action = "buy", Title = "Purchase Lead", Icon = "https://s3.amazonaws.com/images.productionhub.com/icons/icon_credit.png"
                    });

                    var payload = JsonConvert.SerializeObject(notification, new JsonSerializerSettings {
                        ContractResolver = new CamelCasePropertyNamesContractResolver()
                    });

                    var requestDetails = client.GenerateRequestDetails(subscription, payload, opts);


                    //await client.SendNotificationAsync(subscription, "payload", vapidDetails);
                    var httpClient = new HttpClient();
                    await httpClient.SendAsync(requestDetails);

                    return(Json(true));
                }
                catch (WebPush.WebPushException exc)
                {
                    return(new HttpStatusCodeResult(exc.StatusCode));
                }
            }
        }
        private static async Task SendNotificationToRecipients(IEnumerable <PushSubscription> recipients, PushNotification notification, string senderEmail, string publicKey, string privateKey, ILogger logger, CancellationToken cancelToken)
        {
            // This is run in a background thread. We should not access or update any mutable state.
            var vapidDetails = new WebPush.VapidDetails($"mailto:{senderEmail}", publicKey, privateKey);
            var client       = new WebPush.WebPushClient();
            var jsonSettings = new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };

            foreach (var subscription in recipients)
            {
                if (!cancelToken.IsCancellationRequested)
                {
                    await TrySendPushNotification(notification, subscription, vapidDetails, client, jsonSettings, logger);
                }
            }
        }
 private static async Task TrySendPushNotification(PushNotification notification, PushSubscription recipient, WebPush.VapidDetails details, WebPush.WebPushClient client, JsonSerializerSettings serializerSettings, ILogger logger)
 {
     // This is run in a background thread. We should not access or update mutable state.
     try
     {
         var payload      = JsonConvert.SerializeObject(notification, serializerSettings);
         var subscription = new WebPush.PushSubscription(recipient.Endpoint, recipient.Keys["p256dh"], recipient.Keys["auth"]);
         await client.SendNotificationAsync(subscription, payload, details);
     }
     catch (Exception error)
     {
         using (logger.BeginKeyValueScope("recipient", recipient))
             using (logger.BeginKeyValueScope("publicKey", details.PublicKey))
                 using (logger.BeginKeyValueScope("publicKey", details.PrivateKey))
                 {
                     logger.LogError(error, "Error sending push notification");
                 }
     }
 }
        public async Task <ContentResult> Push([Required, FromBody] string name)
        {
            var user = await _userMgr.GetUserAsync(User);

            string ret;

            try
            {
                if (user.InGroupId == null)
                {
                    ret = "not_in_group";
                }
                else
                {
                    if (user.WebSubscription == null)
                    {
                        ret = "s_not_subscribed";
                    }
                    else
                    {
                        var rcvr = _groupsDb.Users.Where(c => c.InGroupId == user.InGroupId).SingleOrDefault(c => c.UserName == name);
                        if (rcvr == null)
                        {
                            ret = "not_found";
                        }
                        else
                        {
                            if (rcvr.InGroupId != user.InGroupId)
                            {
                                ret = "not_same_group";
                            }
                            else
                            {
                                var web_subscription = StaticData.GetPushSubscription(rcvr.WebSubscription);
                                if (web_subscription == null)
                                {
                                    ret = "r_not_subscribed";
                                }
                                else
                                {
                                    if (rcvr.LastNotified > DateTime.UtcNow.Subtract(TimeSpan.FromHours(1)).Ticks)
                                    {
                                        ret = "is_notified_hour";
                                    }
                                    else
                                    {
                                        if (rcvr.ConnectionId != null)
                                        {
                                            ret = "usr_active";
                                        }
                                        else
                                        {
                                            ValueTask <Chatterer> groupN = _groupsDb.Users.FindAsync(rcvr.InGroupId);
                                            WebPush.WebPushClient client = new WebPush.WebPushClient();
                                            WebPush.VapidDetails  det    = new WebPush.VapidDetails("mailto:[email protected]",
                                                                                                    _connections.vapidPublic, _connections.vapidPrivate);
                                            client.SetVapidDetails(det);
                                            var groupName = (await groupN).Group;
                                            var send_task = client.SendNotificationAsync(web_subscription, $"\"{groupName}\" by {user.UserName}");
                                            rcvr.LastNotified = DateTime.UtcNow.Ticks;
                                            var save_task = _groupsDb.SaveChangesAsync();
                                            await Task.WhenAll(send_task, save_task);

                                            ret = "OK";
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                ret = e.Message;
            }
            return(Content(ret, "text/plain"));
        }
Beispiel #6
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);
            }
        }