-
-
Notifications
You must be signed in to change notification settings - Fork 617
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
James Bligh
committed
Nov 20, 2022
1 parent
a208192
commit 4fb64be
Showing
7 changed files
with
358 additions
and
247 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -122,238 +122,11 @@ For WNS, you need both the ``WNS_PACKAGE_SECURITY_KEY`` and the ``WNS_SECRET_KEY | |
|
||
**WP settings** | ||
|
||
- Install: | ||
|
||
.. code-block:: python | ||
pip install pywebpush | ||
pip install py-vapid (Only for generating key) | ||
- Getting keys: | ||
|
||
- Create file (claim.json) like this: | ||
|
||
.. code-block:: bash | ||
{ | ||
"sub": "mailto: [email protected]", | ||
"aud": "https://android.googleapis.com" | ||
} | ||
- Generate public and private keys: | ||
.. code-block:: bash | ||
vapid --sign claim.json | ||
No private_key.pem file found. | ||
Do you want me to create one for you? (Y/n)Y | ||
Do you want me to create one for you? (Y/n)Y | ||
Generating private_key.pem | ||
Generating public_key.pem | ||
Include the following headers in your request: | ||
Crypto-Key: p256ecdsa=BEFuGfKKEFp-kEBMxAIw7ng8HeH_QwnH5_h55ijKD4FRvgdJU1GVlDo8K5U5ak4cMZdQTUJlkA34llWF0xHya70 | ||
Authorization: WebPush eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL2FuZHJvaWQuZ29vZ2xlYXBpcy5jb20iLCJleHAiOiIxNTA4NDkwODM2Iiwic3ViIjoibWFpbHRvOiBkZXZlbG9wbWVudEBleGFtcGxlLmNvbSJ9.r5CYMs86X3JZ4AEs76pXY5PxsnEhIFJ-0ckbibmFHZuyzfIpf1ZGIJbSI7knA4ufu7Hm8RFfEg5wWN1Yf-dR2A | ||
- Generate client public key (applicationServerKey) | ||
.. code-block:: bash | ||
vapid --applicationServerKey | ||
Application Server Key = BEFuGfKKEFp-kEBMxAIw7ng8HeH_QwnH5_h55ijKD4FRvgdJU1GVlDo8K5U5ak4cMZdQTUJlkA34llWF0xHya70 | ||
- Configure settings: | ||
|
||
- ``WP_PRIVATE_KEY``: Absolute path to your private certificate file: os.path.join(BASE_DIR, "private_key.pem") | ||
- ``WP_CLAIMS``: Dictionary with the same sub info like claims file: {'sub': "mailto: [email protected]"} | ||
- ``WP_ERROR_TIMEOUT``: The timeout on WebPush POSTs. (Optional) | ||
- ``WP_POST_URL``: A dictionary (key per browser supported) with the full url that webpush notifications will be POSTed to. (Optional) | ||
|
||
|
||
- Configure client (javascript): | ||
|
||
.. code-block:: javascript | ||
// Utils functions: | ||
function urlBase64ToUint8Array (base64String) { | ||
var padding = '='.repeat((4 - base64String.length % 4) % 4) | ||
var base64 = (base64String + padding) | ||
.replace(/\-/g, '+') | ||
.replace(/_/g, '/') | ||
var rawData = window.atob(base64) | ||
var outputArray = new Uint8Array(rawData.length) | ||
for (var i = 0; i < rawData.length; ++i) { | ||
outputArray[i] = rawData.charCodeAt(i) | ||
} | ||
return outputArray; | ||
} | ||
function loadVersionBrowser () { | ||
if ("userAgentData" in navigator) { | ||
// navigator.userAgentData is not available in | ||
// Firefox and Safari | ||
const uaData = navigator.userAgentData; | ||
// Outputs of navigator.userAgentData.brands[n].brand are e.g. | ||
// Chrome: 'Google Chrome' | ||
// Edge: 'Microsoft Edge' | ||
// Opera: 'Opera' | ||
let browsername; | ||
let browserversion; | ||
let chromeVersion = null; | ||
for (var i = 0; i < uaData.brands.length; i++) { | ||
let brand = uaData.brands[i].brand; | ||
browserversion = uaData.brands[i].version; | ||
if (brand.match(/opera|chrome|edge|safari|firefox|msie|trident/i) !== null) { | ||
// If we have a chrome match, save the match, but try to find another match | ||
// E.g. Edge can also produce a false Chrome match. | ||
if (brand.match(/chrome/i) !== null) { | ||
chromeVersion = browserversion; | ||
} | ||
// If this is not a chrome match return immediately | ||
else { | ||
browsername = brand.substr(brand.indexOf(' ')+1); | ||
return { | ||
name: browsername, | ||
version: browserversion | ||
} | ||
} | ||
} | ||
} | ||
// No non-Chrome match was found. If we have a chrome match, return it. | ||
if (chromeVersion !== null) { | ||
return { | ||
name: "chrome", | ||
version: chromeVersion | ||
} | ||
} | ||
} | ||
// If no userAgentData is not present, or if no match via userAgentData was found, | ||
// try to extract the browser name and version from userAgent | ||
const userAgent = navigator.userAgent; | ||
var ua = userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; | ||
if (/trident/i.test(M[1])) { | ||
tem = /\brv[ :]+(\d+)/g.exec(ua) || []; | ||
return {name: 'IE', version: (tem[1] || '')}; | ||
} | ||
if (M[1] === 'Chrome') { | ||
tem = ua.match(/\bOPR\/(\d+)/); | ||
if (tem != null) { | ||
return {name: 'Opera', version: tem[1]}; | ||
} | ||
} | ||
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?']; | ||
if ((tem = ua.match(/version\/(\d+)/i)) != null) { | ||
M.splice(1, 1, tem[1]); | ||
} | ||
return { | ||
name: M[0], | ||
version: M[1] | ||
}; | ||
}; | ||
var applicationServerKey = "BEFuGfKKEFp-kEBMxAIw7ng8HeH_QwnH5_h55ijKD4FRvgdJU1GVlDo8K5U5ak4cMZdQTUJlkA34llWF0xHya70"; | ||
.... | ||
// In your ready listener | ||
if ('serviceWorker' in navigator) { | ||
// The service worker has to store in the root of the app | ||
// http://stackoverflow.com/questions/29874068/navigator-serviceworker-is-never-ready | ||
var browser = loadVersionBrowser(); | ||
navigator.serviceWorker.register('navigatorPush.service.js?version=1.0.0').then(function (reg) { | ||
reg.pushManager.subscribe({ | ||
userVisibleOnly: true, | ||
applicationServerKey: urlBase64ToUint8Array(applicationServerKey) | ||
}).then(function (sub) { | ||
var endpointParts = sub.endpoint.split('/'); | ||
var registration_id = endpointParts[endpointParts.length - 1]; | ||
var data = { | ||
'browser': browser.name.toUpperCase(), | ||
'p256dh': btoa(String.fromCharCode.apply(null, new Uint8Array(sub.getKey('p256dh')))), | ||
'auth': btoa(String.fromCharCode.apply(null, new Uint8Array(sub.getKey('auth')))), | ||
'name': 'XXXXX', | ||
'registration_id': registration_id | ||
}; | ||
requestPOSTToServer(data); | ||
}) | ||
}).catch(function (err) { | ||
console.log(':^(', err); | ||
}); | ||
// Example navigatorPush.service.js file | ||
var getTitle = function (title) { | ||
if (title === "") { | ||
title = "TITLE DEFAULT"; | ||
} | ||
return title; | ||
}; | ||
var getNotificationOptions = function (message, message_tag) { | ||
var options = { | ||
body: message, | ||
icon: '/img/icon_120.png', | ||
tag: message_tag, | ||
vibrate: [200, 100, 200, 100, 200, 100, 200] | ||
}; | ||
return options; | ||
}; | ||
self.addEventListener('install', function (event) { | ||
self.skipWaiting(); | ||
}); | ||
self.addEventListener('push', function(event) { | ||
try { | ||
// Push is a JSON | ||
var response_json = event.data.json(); | ||
var title = response_json.title; | ||
var message = response_json.message; | ||
var message_tag = response_json.tag; | ||
} catch (err) { | ||
// Push is a simple text | ||
var title = ""; | ||
var message = event.data.text(); | ||
var message_tag = ""; | ||
} | ||
self.registration.showNotification(getTitle(title), getNotificationOptions(message, message_tag)); | ||
// Optional: Comunicating with our js application. Send a signal | ||
self.clients.matchAll({includeUncontrolled: true, type: 'window'}).then(function (clients) { | ||
clients.forEach(function (client) { | ||
client.postMessage({ | ||
"data": message_tag, | ||
"data_title": title, | ||
"data_body": message}); | ||
}); | ||
}); | ||
}); | ||
// Optional: Added to that the browser opens when you click on the notification push web. | ||
self.addEventListener('notificationclick', function(event) { | ||
// Android doesn't close the notification when you click it | ||
// See http://crbug.com/463146 | ||
event.notification.close(); | ||
// Check if there's already a tab open with this URL. | ||
// If yes: focus on the tab. | ||
// If no: open a tab with the URL. | ||
event.waitUntil(clients.matchAll({type: 'window', includeUncontrolled: true}).then(function(windowClients) { | ||
for (var i = 0; i < windowClients.length; i++) { | ||
var client = windowClients[i]; | ||
if ('focus' in client) { | ||
return client.focus(); | ||
} | ||
} | ||
}) | ||
); | ||
}); | ||
|
||
For more information about how to configure WebPush, see `docs/WebPush <https://github.com/jazzband/django-push-notifications/blob/master/docs/WebPush.rst>`_. | ||
|
||
|
||
Sending messages | ||
|
Oops, something went wrong.