


//    web-push,      //      push. //     // . https://tools.ietf.org/html/draft-ietf-webpush-protocol //  https://tools.ietf.org/html/draft-ietf-webpush-encryption. var webPush = require('web-push'); //  GCM_API_KEY      // https://developers.google.com/cloud-messaging/ webPush.setGCMAPIKey(process.env.GCM_API_KEY || null); //        route'  express.js module.exports = function(app, route) { app.post(route + 'register', function(req, res) { res.sendStatus(201); }); app.post(route + 'sendNotification', function(req, res) { setTimeout(function() { //     payload,     'auth'  'p256dh'. webPush.sendNotification({ endpoint: req.body.endpoint, TTL: req.body.ttl, keys: { p256dh: req.body.key, auth: req.body.authSecret } }, req.body.payload) .then(function() { res.sendStatus(201); }) .catch(function(error) { res.sendStatus(500); console.log(error); }); }, req.query.delay * 1000); }); };  var endpoint; var key; var authSecret; navigator.serviceWorker.register('service-worker.js') .then(function(registration) { //  PushManager,      -. return registration.pushManager.getSubscription() .then(function(subscription) { //      . if (subscription) { return subscription; } //   ,  . // userVisibleOnly -   ,   push- //     , //      . return registration.pushManager.subscribe({ userVisibleOnly: true }); }); }).then(function(subscription) { //  public key  . var rawKey = subscription.getKey ? subscription.getKey('p256dh') : ''; key = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : ''; var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : ''; authSecret = rawAuthSecret ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) : ''; endpoint = subscription.endpoint; //        Fetch API fetch('./register', { method: 'post', headers: { 'Content-type': 'application/json' }, body: JSON.stringify({ endpoint: subscription.endpoint, key, authSecret, }), }); }); //   . //    ""   , ..      . document.getElementById('doIt').onclick = function() { var payload = document.getElementById('notification-payload').value; var delay = document.getElementById('notification-delay').value; var ttl = document.getElementById('notification-ttl').value; fetch('./sendNotification', { method: 'post', headers: { 'Content-type': 'application/json' }, body: JSON.stringify({ endpoint: endpoint, payload: payload, delay: delay, ttl: ttl, key: key, authSecret: authSecret }), }); };  //     'push' self.addEventListener('push', function(event) { var payload = event.data ? event.data.text() : 'Alohomora'; event.waitUntil( //       . self.registration.showNotification('My first spell', { body: payload, }) ); });  //      Push Payload    // Notitfication API  SW self.addEventListener('push', function(event) { var payload = event.data //   -     ,  // try.. catch    ¯\_(ツ)_/¯ ? JSON.parse(event.data) : { name: 'Expecto patronum!', icon: 'buck.jpg', locale: 'en' }; event.waitUntil( //       . //   : // *  // *   // *  //    ,       // https://notifications.spec.whatwg.org/ self.registration.showNotification('Summoning spell', { lang: payload.locale, body: payload.name, icon: payload.icon, vibrate: [500, 100, 500], }) ); });  var num = 1; self.addEventListener('push', function(event) { event.waitUntil( //       . // ,      . //         // (       ) self.registration.showNotification('Attacking Spell', { body: ++num > 1 ? 'Bombarda Maxima' : 'Bombarda', tag: 'spell', }) ); });  self.addEventListener('install', function(event) { event.waitUntil(self.skipWaiting()); }); self.addEventListener('activate', function(event) { event.waitUntil(self.clients.claim()); }); self.addEventListener('push', function(event) { event.waitUntil( //     SW self.clients.matchAll().then(function(clientList) { // ,       . var focused = clientList.some(function(client) { return client.focused; }); var notificationMessage; if (focused) { notificationMessage = 'Imperio! You\'re still here, thanks!'; } else if (clientList.length > 0) { notificationMessage = 'Imperio! You haven\'t closed the page, ' + 'click here to focus it!'; } else { notificationMessage = 'Imperio! You have closed the page, ' + 'click here to re-open it!'; } //     «Unforgiveable Curses» //        SW // (  : // * 1,  ; // * 2,  - ,   ; // * 3,  ). return self.registration.showNotification('Unforgiveable Curses', { body: notificationMessage, }); }) ); }); //    'notificationclick'. self.addEventListener('notificationclick', function(event) { event.waitUntil( //    SW. self.clients.matchAll().then(function(clientList) { //      ,  . if (clientList.length > 0) { return clientList[0].focus(); } //      . return self.clients.openWindow('our/url/page'); }) ); });  //     . //      . var subscriptionButton = document.getElementById('subscriptionButton'); //       ,   , //   Promise. function getSubscription() { return navigator.serviceWorker.ready .then(function(registration) { return registration.pushManager.getSubscription(); }); } if ('serviceWorker' in navigator) { navigator.serviceWorker.register('service-worker.js') .then(function() { console.log('SW registered'); subscriptionButton.removeAttribute('disabled'); }); getSubscription() .then(function(subscription) { if (subscription) { console.log('Already invaded', subscription.endpoint); setUnsubscribeButton(); } else { setSubscribeButton(); } }); } //  «registration»  SW    //    `registration.pushManager.subscribe`. //    ,  POST-. function subscribe() { navigator.serviceWorker.ready.then(function(registration) { return registration.pushManager.subscribe({ userVisibleOnly: true }); }).then(function(subscription) { console.log('Legilimens!', subscription.endpoint); return fetch('register', { method: 'post', headers: { 'Content-type': 'application/json' }, body: JSON.stringify({ endpoint: subscription.endpoint }) }); }).then(setUnsubscribeButton); } //     SW, //   (`subscription.unsubscribe ()`)  //       POST- //    push-. function unsubscribe() { getSubscription().then(function(subscription) { return subscription.unsubscribe() .then(function() { console.log('Unsubscribed', subscription.endpoint); return fetch('unregister', { method: 'post', headers: { 'Content-type': 'application/json' }, body: JSON.stringify({ endpoint: subscription.endpoint }) }); }); }).then(setSubscribeButton); } //   ( ).   . function setSubscribeButton() { subscriptionButton.onclick = subscribe; subscriptionButton.textContent = 'Open mind!'; } function setUnsubscribeButton() { subscriptionButton.onclick = unsubscribe; subscriptionButton.textContent = 'Protego!'; }  //   'push'. self.addEventListener('push', function(event) { event.waitUntil(self.registration.showNotification('Your mind', { body: 'Wizard invaded to your mind!' })); }); //   'pushsubscriptionchange',  , //    . //        , //  POST-. //        ID  token //   . self.addEventListener('pushsubscriptionchange', function(event) { console.log('Spell expired'); event.waitUntil( self.registration.pushManager.subscribe({ userVisibleOnly: true }) .then(function(subscription) { console.log('Another invade! Legilimens!', subscription.endpoint); return fetch('register', { method: 'post', headers: { 'Content-type': 'application/json' }, body: JSON.stringify({ endpoint: subscription.endpoint }) }); }) ); });  var webPush = require('web-push'); var subscriptions = []; var pushInterval = 10; webPush.setGCMAPIKey(process.env.GCM_API_KEY || null); //   push-. //      `subscriptions`, //  push-        . function sendNotification(endpoint) { webPush.sendNotification({ endpoint: endpoint }).then(function() { }).catch(function() { subscriptions.splice(subscriptions.indexOf(endpoint), 1); }); } //          //  . //   ,     `pushInterval`  //   setInterval(function() { subscriptions.forEach(sendNotification); }, pushInterval * 1000); function isSubscribed(endpoint) { return (subscriptions.indexOf(endpoint) >= 0); } module.exports = function(app, route) { app.post(route + 'register', function(req, res) { var endpoint = req.body.endpoint; if (!isSubscribed(endpoint)) { console.log('We invaded into mind ' + endpoint); subscriptions.push(endpoint); } res.type('js').send('{"success":true}'); }); // Unregister a subscription by removing it from the `subscriptions` array app.post(route + 'unregister', function(req, res) { var endpoint = req.body.endpoint; if (isSubscribed(endpoint)) { console.log('It was counterspell from ' + endpoint); subscriptions.splice(subscriptions.indexOf(endpoint), 1); } res.type('js').send('{"success":true}'); }); }; Source: https://habr.com/ru/post/350034/
All Articles