// 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