├── .gitignore
├── LICENSE
├── MANIFEST.in
├── README.rst
├── chromeos.png
├── chromeos.webm
├── client-src
├── .gitignore
├── index.css
├── index.html
├── index.js
├── ntfy.png
├── package-lock.json
├── package.json
└── sw.js
├── docs
├── client-src.2242359d.js
├── client-src.2242359d.js.map
├── client-src.b05516cc.css
├── client-src.b05516cc.css.map
├── index.html
├── ntfy.7aae8baa.png
├── sw.js
└── sw.js.map
├── ntfy_webpush.py
├── screenshot.png
└── setup.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 |
27 | # PyInstaller
28 | # Usually these files are written by a python script from a template
29 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
30 | *.manifest
31 | *.spec
32 |
33 | # Installer logs
34 | pip-log.txt
35 | pip-delete-this-directory.txt
36 |
37 | # Unit test / coverage reports
38 | htmlcov/
39 | .tox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *,cover
46 | .hypothesis/
47 |
48 | # Translations
49 | *.mo
50 | *.pot
51 |
52 | # Django stuff:
53 | *.log
54 | local_settings.py
55 |
56 | # Flask stuff:
57 | instance/
58 | .webassets-cache
59 |
60 | # Scrapy stuff:
61 | .scrapy
62 |
63 | # Sphinx documentation
64 | docs/_build/
65 |
66 | # PyBuilder
67 | target/
68 |
69 | # IPython Notebook
70 | .ipynb_checkpoints
71 |
72 | # pyenv
73 | .python-version
74 |
75 | # celery beat schedule file
76 | celerybeat-schedule
77 |
78 | # dotenv
79 | .env
80 |
81 | # virtualenv
82 | venv/
83 | ENV/
84 |
85 | # Spyder project settings
86 | .spyderproject
87 |
88 | # Rope project settings
89 | .ropeproject
90 | *.npy
91 | *.pkl
92 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README.rst LICENSE
2 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | ``ntfy-webpush``
2 | ================
3 |
4 | Brining webpush notifications to `ntfy `_.
5 |
6 | .. image:: screenshot.png
7 |
8 | Quick start
9 | ~~~~~~~~~~~
10 |
11 | ::
12 |
13 | sudo pip install ntfy-webpush
14 | ntfy-webpush
15 |
16 | Then follow the directions.
17 |
18 | Config Options
19 | ~~~~~~~~~~~~~~
20 | - ``subscription_info`` - A `PushSubscription `_ Object
21 | - ``private_key`` - the path to private key file or anything else that works with `pywebpush `_.
22 |
23 | Example config:
24 | ~~~~~~~~~~~~~~~
25 | .. code:: yaml
26 |
27 | ---
28 | backends:
29 | - ntfy_webpush
30 | ntfy_webpush:
31 | subscription_info:
32 | endpoint: >-
33 | https://updates.push.services.mozilla.com/wpush/v2/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
34 | keys:
35 | auth: xXXxXXxxxXXXXxxxXXxxXX
36 | p256dh: >-
37 | xXXxXXxxxXXXXxxxXXxxXxXXxXXxxxXXXXxxxXXxxXxXXxXXxxxXXXXxxxXXxxXxXXxXXxxxXXXXxxxXXxxXXXX
38 | private_key: /home/user/.local/share/ntfy/private_key.pem
39 |
40 | Video
41 | ~~~~~
42 | Click the screenshot below for a video demonstrating ``ntfy-webpush`` on ChromeOS with Google Cloud
43 | Shell.
44 |
45 | |Video|_
46 |
47 | .. |Video| image:: ./chromeos.png
48 | .. _Video: https://raw.githubusercontent.com/dschep/ntfy-webpush/master/chromeos.webm
49 |
--------------------------------------------------------------------------------
/chromeos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschep/ntfy-webpush/090d3daa10832fa1257ff0e0726441b3fa387087/chromeos.png
--------------------------------------------------------------------------------
/chromeos.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschep/ntfy-webpush/090d3daa10832fa1257ff0e0726441b3fa387087/chromeos.webm
--------------------------------------------------------------------------------
/client-src/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/client-src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 20px auto;
3 | max-width: 800px;
4 | font-family: sans;
5 | }
6 | code {
7 | white-space: pre-wrap;
8 | background: #222;
9 | color: #eee;
10 | display: block;
11 | margin: 10px;
12 | padding: 10px;
13 | border-radius: 5px;
14 | }
15 | .logo {
16 | height: 1em;
17 | margin-bottom: -0.2em;
18 | margin-right: .2em;
19 | }
20 | .pre {
21 | font-family: monospace;
22 | }
23 |
--------------------------------------------------------------------------------
/client-src/index.html:
--------------------------------------------------------------------------------
1 | ntfy web-push
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/client-src/index.js:
--------------------------------------------------------------------------------
1 | import {h, app} from 'hyperapp';
2 | import yaml from 'js-yaml';
3 | import logoURL from './ntfy.png';
4 |
5 | // cribbed from https://github.com/web-push-libs/web-push/tree/f18c2f36472197b3273eb42ac1f5430c35acc120#using-vapid-key-for-applicationserverkey
6 | function urlBase64ToUint8Array(base64String) {
7 | const padding = '='.repeat((4 - base64String.length % 4) % 4);
8 | const base64 = (base64String + padding)
9 | .replace(/\-/g, '+')
10 | .replace(/_/g, '/');
11 |
12 | const rawData = window.atob(base64);
13 | const outputArray = new Uint8Array(rawData.length);
14 |
15 | for (let i = 0; i < rawData.length; ++i) {
16 | outputArray[i] = rawData.charCodeAt(i);
17 | }
18 | return outputArray;
19 | }
20 |
21 | const subscriptionToConfig = (subscription, privateKeyPath) => yaml.dump({
22 | ntfy_webpush: {
23 | subscription_info: JSON.parse(JSON.stringify(subscription)),
24 | private_key: privateKeyPath || '/path/to/private_key.pem',
25 | },
26 | });
27 |
28 | const Usage = () => (
29 |
30 |
31 | Then send a test notification with:
32 |
33 |
ntfy -b ntfy_webpush send 'testing webpush!'
34 |
35 | );
36 |
37 | const QrCode = ({publicKey}) => {
38 | if (publicKey)
39 | return (
40 |
41 |
Subscribing on your phone
42 |
43 | To subscribe on notifications on your phone, open this same page with the full url on your phone.
44 | Here's a QR code to scan for convinence.
45 |
46 |
47 |
48 | );
49 | }
50 |
51 | const GithubCorner = () => (
52 |
55 | );
56 |
57 | const Header = () => (
58 |
59 | ntfy web-push
60 |
61 | );
62 |
63 | const Info = () => (
64 |
65 | To get started, install ntfy-webpush and run it to generate keys,
66 | then follow the link in the output to reload this page with a public key.
67 |
68 | $ sudo pip install ntfy-webpush
69 |
70 | $ ntfy-webpush
71 |
72 | ....
73 |
74 |
75 | );
76 |
77 | const Subscribe = () => ({publicKey, privateKeyPath, subscription}, {subscribe, unsubscribe}) => {
78 | const isSubscribed = Boolean(subscription);
79 | const config = isSubscribed?subscriptionToConfig(subscription, privateKeyPath):'';
80 | return (
81 |
82 | When a key is loaded, click subscribe to subscribe to notifications in this browser and then
83 | copy the config below into your ntfy.yml
84 |
85 | (subscription?unsubscribe():subscribe())}>
86 | {subscription?'Unsubscribe':'Subscribe'}
87 |
88 |
89 | {config}
90 |
91 | Sorry, your browser doesn't support web-push.
92 |
93 |
94 | );
95 | };
96 |
97 | const {publicKey, privateKeyPath} = window.location.hash
98 | .split(/[#&]/).
99 | slice(1).map(s => s.split('='))
100 | .reduce((obj, [k, v]) => Object.assign(obj, {[k]: v}), {});
101 |
102 | const state = {
103 | publicKey,
104 | privateKeyPath,
105 | subscription: null,
106 | }
107 |
108 | const actions = {
109 | getSubscription: () => (state, actions) => navigator.serviceWorker.register('./sw.js')
110 | .then((registration) => registration.pushManager.getSubscription())
111 | .then(actions.setSubscription),
112 | subscribe: () => (state, actions) => navigator.serviceWorker.register('./sw.js')
113 | .then((registration) => registration.pushManager.subscribe({
114 | userVisibleOnly: true,
115 | applicationServerKey: urlBase64ToUint8Array(publicKey),
116 | }))
117 | .then(actions.setSubscription),
118 | unsubscribe: () => (state, actions) => state.subscription.unsubscribe()
119 | .then(() => actions.setSubscription(undefined)),
120 | setSubscription: value => state => Object.assign({}, state, {subscription: value}),
121 | };
122 |
123 | const view = (state, actions) => (
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | );
138 |
139 | const main = app(state, actions, view, document.body);
140 | main.getSubscription();
141 |
--------------------------------------------------------------------------------
/client-src/ntfy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschep/ntfy-webpush/090d3daa10832fa1257ff0e0726441b3fa387087/client-src/ntfy.png
--------------------------------------------------------------------------------
/client-src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ntfy-webapp",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "parcel build -d ../docs --public-url . index.html"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "hyperapp": "^1.2.5",
13 | "js-yaml": "^3.11.0",
14 | "parcel-bundler": "^1.12.5"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/client-src/sw.js:
--------------------------------------------------------------------------------
1 | import icon from './ntfy.png';
2 |
3 | self.addEventListener('push', function(event) {
4 | var payload = event.data ? event.data.json() : {};
5 | event.waitUntil(
6 | self.registration.showNotification(payload.title, {
7 | body: payload.message,
8 | icon,
9 | requireInteraction: true,
10 | })
11 | );
12 | });
13 |
--------------------------------------------------------------------------------
/docs/client-src.2242359d.js:
--------------------------------------------------------------------------------
1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c2;)t.push(arguments[o]);for(;t.length;){var u=t.pop();if(u&&u.pop)for(o=u.length;o--;)t.push(u[o]);else null!=u&&!0!==u&&!1!==u&&r.push(u)}return"function"==typeof e?e(n||{},r):{nodeName:e,attributes:n||{},children:r,key:n&&n.key}}function n(e,n,t,r){var o,u=[].map,l=r&&r.children[0]||null,i=l&&function e(n){return{nodeName:n.nodeName.toLowerCase(),attributes:{},children:u.call(n.childNodes,function(n){return 3===n.nodeType?n.nodeValue:e(n)})}}(l),a=[],f=!0,c=p(e),s=function e(n,t,r){for(var o in r)"function"==typeof r[o]?function(e,o){r[e]=function(e){var u=o(e);return"function"==typeof u&&(u=u(g(n,c),r)),u&&u!==(t=g(n,c))&&!u.then&&h(c=m(n,p(t,u),c)),u}}(o,r[o]):e(n.concat(o),t[o]=p(t[o]),r[o]=p(r[o]));return r}([],c,p(n));return h(),s;function v(e){return"function"==typeof e?v(e(c,s)):null!=e?e:""}function d(){o=!o;var e=v(t);for(r&&!o&&(l=function e(n,t,r,o,u){if(o===r);else if(null==r||r.nodeName!==o.nodeName){var l=function e(n,t){var r="string"==typeof n||"number"==typeof n?document.createTextNode(n):(t=t||"svg"===n.nodeName)?document.createElementNS("http://www.w3.org/2000/svg",n.nodeName):document.createElement(n.nodeName);var o=n.attributes;if(o){o.oncreate&&a.push(function(){o.oncreate(r)});for(var u=0;u1?m(e.slice(1),n,t[e[0]]):n,p(t,r)):n}function g(e,n){for(var t=0;t0&&-1==="\0\r\n
\u2028\u2029".indexOf(this.buffer.charAt(r-1));)if(r-=1,this.position-r>n/2-1){e=" ... ",r+=5;break}for(s="",o=this.position;on/2-1){s=" ... ",o-=5;break}return h=this.buffer.slice(r,o),t.repeat(" ",i)+e+h+s+"\n"+t.repeat(" ",i+this.position-r+e.length)+"^"},i.prototype.toString=function(t){var i,n="";return this.name&&(n+='in "'+this.name+'" '),n+="at line "+(this.line+1)+", column "+(this.column+1),t||(i=this.getSnippet())&&(n+=":\n"+i),n},module.exports=i;
9 | },{"./common":"wrEo"}],"S29r":[function(require,module,exports) {
10 | "use strict";var e=require("./exception"),n=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],t=["scalar","sequence","mapping"];function i(e){var n={};return null!==e&&Object.keys(e).forEach(function(t){e[t].forEach(function(e){n[String(e)]=t})}),n}function s(s,r){if(r=r||{},Object.keys(r).forEach(function(t){if(-1===n.indexOf(t))throw new e('Unknown option "'+t+'" is met in definition of "'+s+'" YAML type.')}),this.tag=s,this.kind=r.kind||null,this.resolve=r.resolve||function(){return!0},this.construct=r.construct||function(e){return e},this.instanceOf=r.instanceOf||null,this.predicate=r.predicate||null,this.represent=r.represent||null,this.defaultStyle=r.defaultStyle||null,this.styleAliases=i(r.styleAliases||null),-1===t.indexOf(this.kind))throw new e('Unknown kind "'+this.kind+'" is specified for "'+s+'" YAML type.')}module.exports=s;
11 | },{"./exception":"GbD2"}],"nA5r":[function(require,module,exports) {
12 | "use strict";var i=require("./common"),e=require("./exception"),t=require("./type");function n(i,e,t){var c=[];return i.include.forEach(function(i){t=n(i,e,t)}),i[e].forEach(function(i){t.forEach(function(e,t){e.tag===i.tag&&e.kind===i.kind&&c.push(t)}),t.push(i)}),t.filter(function(i,e){return-1===c.indexOf(e)})}function c(){var i,e,t={scalar:{},sequence:{},mapping:{},fallback:{}};function n(i){t[i.kind][i.tag]=t.fallback[i.tag]=i}for(i=0,e=arguments.length;i=0?"0b"+r.toString(2):"-0b"+r.toString(2).slice(1)},octal:function(r){return r>=0?"0"+r.toString(8):"-0"+r.toString(8).slice(1)},decimal:function(r){return r.toString(10)},hexadecimal:function(r){return r>=0?"0x"+r.toString(16).toUpperCase():"-0x"+r.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}});
27 | },{"../common":"wrEo","../type":"S29r"}],"edy5":[function(require,module,exports) {
28 | "use strict";var e=require("../common"),r=require("../type"),t=new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function a(e){return null!==e&&!(!t.test(e)||"_"===e[e.length-1])}function n(e){var r,t,a,n;return t="-"===(r=e.replace(/_/g,"").toLowerCase())[0]?-1:1,n=[],"+-".indexOf(r[0])>=0&&(r=r.slice(1)),".inf"===r?1===t?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===r?NaN:r.indexOf(":")>=0?(r.split(":").forEach(function(e){n.unshift(parseFloat(e,10))}),r=0,a=1,n.forEach(function(e){r+=e*a,a*=60}),t*r):t*parseFloat(r,10)}var c=/^[-+]?[0-9]+e/;function s(r,t){var a;if(isNaN(r))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===r)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===r)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(e.isNegativeZero(r))return"-0.0";return a=r.toString(10),c.test(a)?a.replace("e",".e"):a}function u(r){return"[object Number]"===Object.prototype.toString.call(r)&&(r%1!=0||e.isNegativeZero(r))}module.exports=new r("tag:yaml.org,2002:float",{kind:"scalar",resolve:a,construct:n,predicate:u,represent:s,defaultStyle:"lowercase"});
29 | },{"../common":"wrEo","../type":"S29r"}],"BlxH":[function(require,module,exports) {
30 | "use strict";var e=require("../schema");module.exports=new e({include:[require("./failsafe")],implicit:[require("../type/null"),require("../type/bool"),require("../type/int"),require("../type/float")]});
31 | },{"../schema":"nA5r","./failsafe":"LO4j","../type/null":"L75B","../type/bool":"KDjs","../type/int":"A7Qt","../type/float":"edy5"}],"SBGn":[function(require,module,exports) {
32 | "use strict";var e=require("../schema");module.exports=new e({include:[require("./json")]});
33 | },{"../schema":"nA5r","./json":"BlxH"}],"U7sF":[function(require,module,exports) {
34 | "use strict";var e=require("../type"),t=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),r=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function n(e){return null!==e&&(null!==t.exec(e)||null!==r.exec(e))}function l(e){var n,l,u,i,a,o,c,s,f=0,g=null;if(null===(n=t.exec(e))&&(n=r.exec(e)),null===n)throw new Error("Date resolve error");if(l=+n[1],u=+n[2]-1,i=+n[3],!n[4])return new Date(Date.UTC(l,u,i));if(a=+n[4],o=+n[5],c=+n[6],n[7]){for(f=n[7].slice(0,3);f.length<3;)f+="0";f=+f}return n[9]&&(g=6e4*(60*+n[10]+ +(n[11]||0)),"-"===n[9]&&(g=-g)),s=new Date(Date.UTC(l,u,i,a,o,c,f)),g&&s.setTime(s.getTime()-g),s}function u(e){return e.toISOString()}module.exports=new e("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:n,construct:l,instanceOf:Date,represent:u});
35 | },{"../type":"S29r"}],"aNIm":[function(require,module,exports) {
36 | "use strict";var e=require("../type");function r(e){return"<<"===e||null===e}module.exports=new e("tag:yaml.org,2002:merge",{kind:"scalar",resolve:r});
37 | },{"../type":"S29r"}],"Fp68":[function(require,module,exports) {
38 | "use strict";var r;try{var e=require;r=e("buffer").Buffer}catch(i){}var n=require("../type"),u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";function t(r){if(null===r)return!1;var e,n,t=0,f=r.length,s=u;for(n=0;n64)){if(e<0)return!1;t+=6}return t%8==0}function f(e){var n,t,f=e.replace(/[\r\n=]/g,""),s=f.length,a=u,i=0,h=[];for(n=0;n>16&255),h.push(i>>8&255),h.push(255&i)),i=i<<6|a.indexOf(f.charAt(n));return 0===(t=s%4*6)?(h.push(i>>16&255),h.push(i>>8&255),h.push(255&i)):18===t?(h.push(i>>10&255),h.push(i>>2&255)):12===t&&h.push(i>>4&255),r?r.from?r.from(h):new r(h):h}function s(r){var e,n,t="",f=0,s=r.length,a=u;for(e=0;e>18&63],t+=a[f>>12&63],t+=a[f>>6&63],t+=a[63&f]),f=(f<<8)+r[e];return 0===(n=s%3)?(t+=a[f>>18&63],t+=a[f>>12&63],t+=a[f>>6&63],t+=a[63&f]):2===n?(t+=a[f>>10&63],t+=a[f>>4&63],t+=a[f<<2&63],t+=a[64]):1===n&&(t+=a[f>>2&63],t+=a[f<<4&63],t+=a[64],t+=a[64]),t}function a(e){return r&&r.isBuffer(e)}module.exports=new n("tag:yaml.org,2002:binary",{kind:"scalar",resolve:t,construct:f,predicate:a,represent:s});
39 | },{"../type":"S29r"}],"Y0L4":[function(require,module,exports) {
40 | "use strict";var r=require("../type"),e=Object.prototype.hasOwnProperty,t=Object.prototype.toString;function n(r){if(null===r)return!0;var n,o,u,i,c,l=[],f=r;for(n=0,o=f.length;n3)return!1;if("/"!==r[r.length-n.length-1])return!1}return!0}function t(e){var r=e,t=/\/([gim]*)$/.exec(e),n="";return"/"===r[0]&&(t&&(n=t[1]),r=r.slice(1,r.length-n.length-1)),new RegExp(r,n)}function n(e){var r="/"+e.source+"/";return e.global&&(r+="g"),e.multiline&&(r+="m"),e.ignoreCase&&(r+="i"),r}function i(e){return"[object RegExp]"===Object.prototype.toString.call(e)}module.exports=new e("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:r,construct:t,predicate:i,represent:n});
51 | },{"../../type":"S29r"}],"ARmi":[function(require,module,exports) {
52 | "use strict";var e;try{var r=require;e=r("esprima")}catch(p){"undefined"!=typeof window&&(e=window.esprima)}var n=require("../../type");function t(r){if(null===r)return!1;try{var n="("+r+")",t=e.parse(n,{range:!0});return"Program"===t.type&&1===t.body.length&&"ExpressionStatement"===t.body[0].type&&("ArrowFunctionExpression"===t.body[0].expression.type||"FunctionExpression"===t.body[0].expression.type)}catch(o){return!1}}function o(r){var n,t="("+r+")",o=e.parse(t,{range:!0}),i=[];if("Program"!==o.type||1!==o.body.length||"ExpressionStatement"!==o.body[0].type||"ArrowFunctionExpression"!==o.body[0].expression.type&&"FunctionExpression"!==o.body[0].expression.type)throw new Error("Failed to resolve function");return o.body[0].expression.params.forEach(function(e){i.push(e.name)}),n=o.body[0].expression.body.range,new Function(i,t.slice(n[0]+1,n[1]-1))}function i(e){return e.toString()}function s(e){return"[object Function]"===Object.prototype.toString.call(e)}module.exports=new n("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:t,construct:o,predicate:s,represent:i});
53 | },{"../../type":"S29r"}],"J9C0":[function(require,module,exports) {
54 | "use strict";var e=require("../schema");module.exports=e.DEFAULT=new e({include:[require("./default_safe")],explicit:[require("../type/js/undefined"),require("../type/js/regexp"),require("../type/js/function")]});
55 | },{"../schema":"nA5r","./default_safe":"NFVW","../type/js/undefined":"bXR1","../type/js/regexp":"sFtu","../type/js/function":"ARmi"}],"Cxmq":[function(require,module,exports) {
56 | "use strict";var n=require("./common"),t=require("./exception"),i=require("./mark"),e=require("./schema/default_safe"),o=require("./schema/default_full"),r=Object.prototype.hasOwnProperty,a=1,s=2,l=3,p=4,u=1,c=2,d=3,h=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,f=/[\x85\u2028\u2029]/,g=/[,\[\]\{\}]/,A=/^(?:!|!!|![a-z\-]+!)$/i,m=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function C(n){return 10===n||13===n}function k(n){return 9===n||32===n}function v(n){return 9===n||32===n||10===n||13===n}function x(n){return 44===n||91===n||93===n||123===n||125===n}function b(n){var t;return 48<=n&&n<=57?n-48:97<=(t=32|n)&&t<=102?t-97+10:-1}function y(n){return 120===n?2:117===n?4:85===n?8:0}function w(n){return 48<=n&&n<=57?n-48:-1}function I(n){return 48===n?"\0":97===n?"":98===n?"\b":116===n?"\t":9===n?"\t":110===n?"\n":118===n?"\v":102===n?"\f":114===n?"\r":101===n?"":32===n?" ":34===n?'"':47===n?"/":92===n?"\\":78===n?"
":95===n?" ":76===n?"\u2028":80===n?"\u2029":""}function M(n){return n<=65535?String.fromCharCode(n):String.fromCharCode(55296+(n-65536>>10),56320+(n-65536&1023))}for(var F=new Array(256),S=new Array(256),q=0;q<256;q++)F[q]=I(q)?1:0,S[q]=I(q);function L(n,t){this.input=n,this.filename=t.filename||null,this.schema=t.schema||o,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=n.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function D(n,e){return new t(e,new i(n.filename,n.input,n.position,n.line,n.position-n.lineStart))}function T(n,t){throw D(n,t)}function j(n,t){n.onWarning&&n.onWarning.call(null,D(n,t))}var B={YAML:function(n,t,i){var e,o,r;null!==n.version&&T(n,"duplication of %YAML directive"),1!==i.length&&T(n,"YAML directive accepts exactly one argument"),null===(e=/^([0-9]+)\.([0-9]+)$/.exec(i[0]))&&T(n,"ill-formed argument of the YAML directive"),o=parseInt(e[1],10),r=parseInt(e[2],10),1!==o&&T(n,"unacceptable YAML version of the document"),n.version=i[0],n.checkLineBreaks=r<2,1!==r&&2!==r&&j(n,"unsupported YAML version of the document")},TAG:function(n,t,i){var e,o;2!==i.length&&T(n,"TAG directive accepts exactly two arguments"),e=i[0],o=i[1],A.test(e)||T(n,"ill-formed tag handle (first argument) of the TAG directive"),r.call(n.tagMap,e)&&T(n,'there is a previously declared suffix for "'+e+'" tag handle'),m.test(o)||T(n,"ill-formed tag prefix (second argument) of the TAG directive"),n.tagMap[e]=o}};function O(n,t,i,e){var o,r,a,s;if(t1&&(t.result+=n.repeat("\n",i-1))}function E(n,t,i){var e,o,r,a,s,l,p,u,c=n.kind,d=n.result;if(v(u=n.input.charCodeAt(n.position))||x(u)||35===u||38===u||42===u||33===u||124===u||62===u||39===u||34===u||37===u||64===u||96===u)return!1;if((63===u||45===u)&&(v(e=n.input.charCodeAt(n.position+1))||i&&x(e)))return!1;for(n.kind="scalar",n.result="",o=r=n.position,a=!1;0!==u;){if(58===u){if(v(e=n.input.charCodeAt(n.position+1))||i&&x(e))break}else if(35===u){if(v(n.input.charCodeAt(n.position-1)))break}else{if(n.position===n.lineStart&&_(n)||i&&x(u))break;if(C(u)){if(s=n.line,l=n.lineStart,p=n.lineIndent,$(n,!1,-1),n.lineIndent>=t){a=!0,u=n.input.charCodeAt(n.position);continue}n.position=r,n.line=s,n.lineStart=l,n.lineIndent=p;break}}a&&(O(n,o,r,!1),z(n,n.line-s),o=r=n.position,a=!1),k(u)||(r=n.position+1),u=n.input.charCodeAt(++n.position)}return O(n,o,r,!1),!!n.result||(n.kind=c,n.result=d,!1)}function P(n,t){var i,e,o;if(39!==(i=n.input.charCodeAt(n.position)))return!1;for(n.kind="scalar",n.result="",n.position++,e=o=n.position;0!==(i=n.input.charCodeAt(n.position));)if(39===i){if(O(n,e,n.position,!0),39!==(i=n.input.charCodeAt(++n.position)))return!0;e=n.position,n.position++,o=n.position}else C(i)?(O(n,e,o,!0),z(n,$(n,!1,t)),e=o=n.position):n.position===n.lineStart&&_(n)?T(n,"unexpected end of the document within a single quoted scalar"):(n.position++,o=n.position);T(n,"unexpected end of the stream within a single quoted scalar")}function J(n,t){var i,e,o,r,a,s;if(34!==(s=n.input.charCodeAt(n.position)))return!1;for(n.kind="scalar",n.result="",n.position++,i=e=n.position;0!==(s=n.input.charCodeAt(n.position));){if(34===s)return O(n,i,n.position,!0),n.position++,!0;if(92===s){if(O(n,i,n.position,!0),C(s=n.input.charCodeAt(++n.position)))$(n,!1,t);else if(s<256&&F[s])n.result+=S[s],n.position++;else if((a=y(s))>0){for(o=a,r=0;o>0;o--)(a=b(s=n.input.charCodeAt(++n.position)))>=0?r=(r<<4)+a:T(n,"expected hexadecimal character");n.result+=M(r),n.position++}else T(n,"unknown escape sequence");i=e=n.position}else C(s)?(O(n,i,e,!0),z(n,$(n,!1,t)),i=e=n.position):n.position===n.lineStart&&_(n)?T(n,"unexpected end of the document within a double quoted scalar"):(n.position++,e=n.position)}T(n,"unexpected end of the stream within a double quoted scalar")}function N(n,t){var i,e,o,r,s,l,p,u,c,d,h=!0,f=n.tag,g=n.anchor,A={};if(91===(d=n.input.charCodeAt(n.position)))o=93,l=!1,e=[];else{if(123!==d)return!1;o=125,l=!0,e={}}for(null!==n.anchor&&(n.anchorMap[n.anchor]=e),d=n.input.charCodeAt(++n.position);0!==d;){if($(n,!0,t),(d=n.input.charCodeAt(n.position))===o)return n.position++,n.tag=f,n.anchor=g,n.kind=l?"mapping":"sequence",n.result=e,!0;h||T(n,"missed comma between flow collection entries"),c=null,r=s=!1,63===d&&v(n.input.charCodeAt(n.position+1))&&(r=s=!0,n.position++,$(n,!0,t)),i=n.line,X(n,t,a,!1,!0),u=n.tag,p=n.result,$(n,!0,t),d=n.input.charCodeAt(n.position),!s&&n.line!==i||58!==d||(r=!0,d=n.input.charCodeAt(++n.position),$(n,!0,t),X(n,t,a,!1,!0),c=n.result),l?G(n,e,A,u,p,c):r?e.push(G(n,null,A,u,p,c)):e.push(p),$(n,!0,t),44===(d=n.input.charCodeAt(n.position))?(h=!0,d=n.input.charCodeAt(++n.position)):h=!1}T(n,"unexpected end of the stream within a flow collection")}function H(t,i){var e,o,r,a,s=u,l=!1,p=!1,h=i,f=0,g=!1;if(124===(a=t.input.charCodeAt(t.position)))o=!1;else{if(62!==a)return!1;o=!0}for(t.kind="scalar",t.result="";0!==a;)if(43===(a=t.input.charCodeAt(++t.position))||45===a)u===s?s=43===a?d:c:T(t,"repeat of a chomping mode identifier");else{if(!((r=w(a))>=0))break;0===r?T(t,"bad explicit indentation width of a block scalar; it cannot be less than one"):p?T(t,"repeat of an indentation width identifier"):(h=i+r-1,p=!0)}if(k(a)){do{a=t.input.charCodeAt(++t.position)}while(k(a));if(35===a)do{a=t.input.charCodeAt(++t.position)}while(!C(a)&&0!==a)}for(;0!==a;){for(W(t),t.lineIndent=0,a=t.input.charCodeAt(t.position);(!p||t.lineIndenth&&(h=t.lineIndent),C(a))f++;else{if(t.lineIndentt)&&0!==e)T(n,"bad indentation of a sequence entry");else if(n.lineIndentt)&&(X(n,t,p,!0,o)&&(m?g=n.result:A=n.result),m||(G(n,d,h,f,g,A,r,a),f=g=A=null),$(n,!0,-1),l=n.input.charCodeAt(n.position)),n.lineIndent>t&&0!==l)T(n,"bad indentation of a mapping entry");else if(n.lineIndentt?C=1:n.lineIndent===t?C=0:n.lineIndentt?C=1:n.lineIndent===t?C=0:n.lineIndent tag; it should be "'+g.kind+'", not "'+n.kind+'"'),g.resolve(n.result)?(n.result=g.construct(n.result),null!==n.anchor&&(n.anchorMap[n.anchor]=n.result)):T(n,"cannot resolve a node with !<"+n.tag+"> explicit tag")):T(n,"unknown tag !<"+n.tag+">");return null!==n.listener&&n.listener("close",n),null!==n.tag||null!==n.anchor||v}function Z(n){var t,i,e,o,a=n.position,s=!1;for(n.version=null,n.checkLineBreaks=n.legacy,n.tagMap={},n.anchorMap={};0!==(o=n.input.charCodeAt(n.position))&&($(n,!0,-1),o=n.input.charCodeAt(n.position),!(n.lineIndent>0||37!==o));){for(s=!0,o=n.input.charCodeAt(++n.position),t=n.position;0!==o&&!v(o);)o=n.input.charCodeAt(++n.position);for(e=[],(i=n.input.slice(t,n.position)).length<1&&T(n,"directive name must not be less than one character in length");0!==o;){for(;k(o);)o=n.input.charCodeAt(++n.position);if(35===o){do{o=n.input.charCodeAt(++n.position)}while(0!==o&&!C(o));break}if(C(o))break;for(t=n.position;0!==o&&!v(o);)o=n.input.charCodeAt(++n.position);e.push(n.input.slice(t,n.position))}0!==o&&W(n),r.call(B,i)?B[i](n,i,e):j(n,'unknown document directive "'+i+'"')}$(n,!0,-1),0===n.lineIndent&&45===n.input.charCodeAt(n.position)&&45===n.input.charCodeAt(n.position+1)&&45===n.input.charCodeAt(n.position+2)?(n.position+=3,$(n,!0,-1)):s&&T(n,"directives end mark is expected"),X(n,n.lineIndent-1,p,!1,!0),$(n,!0,-1),n.checkLineBreaks&&f.test(n.input.slice(a,n.position))&&j(n,"non-ASCII line breaks are interpreted as content"),n.documents.push(n.result),n.position===n.lineStart&&_(n)?46===n.input.charCodeAt(n.position)&&(n.position+=3,$(n,!0,-1)):n.positionr&&" "!==e[f+1],f=l);else if(!W(s))return z;p=p&&q(s)}a=a||c&&l-f-1>r&&" "!==e[f+1]}return u||a?" "===e[0]&&n>9?z:a?U:P:p&&!i(e)?Y:E}function G(e,n,r,i){e.dump=function(){if(0===n.length)return"''";if(!e.noCompatMode&&-1!==L.indexOf(n))return"'"+n+"'";var l=e.indent*Math.max(1,r),s=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-l),o=i||e.flowLevel>-1&&r>=e.flowLevel;switch(B(n,o,e.indent,s,function(t){return N(e,t)})){case Y:return n;case E:return"'"+n.replace(/'/g,"''")+"'";case P:return"|"+H(n,e.indent)+J(T(n,l));case U:return">"+H(n,e.indent)+J(T(Q(n,s),l));case z:return'"'+X(n,s)+'"';default:throw new t("impossible error: invalid scalar style")}}()}function H(e,t){var n=" "===e[0]?String(t):"",r="\n"===e[e.length-1];return n+(r&&("\n"===e[e.length-2]||"\n"===e)?"+":r?"":"-")+"\n"}function J(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function Q(e,t){for(var n,r,i,l=/(\n+)([^\n]*)/g,s=(n=-1!==(n=e.indexOf("\n"))?n:e.length,l.lastIndex=n,V(e.slice(0,n),t)),o="\n"===e[0]||" "===e[0];i=l.exec(e);){var u=i[1],a=i[2];r=" "===a[0],s+=u+(o||r||""===a?"":"\n")+V(a,t),o=r}return s}function V(e,t){if(""===e||" "===e[0])return e;for(var n,r,i=/ [^ ]/g,l=0,s=0,o=0,u="";n=i.exec(e);)(o=n.index)-l>t&&(r=s>l?s:o,u+="\n"+e.slice(l,r),l=r+1),s=o;return u+="\n",e.length-l>t&&s>l?u+=e.slice(l,s)+"\n"+e.slice(s+1):u+=e.slice(l),u.slice(1)}function X(e){for(var t,n,r,i="",l=0;l=55296&&t<=56319&&(n=e.charCodeAt(l+1))>=56320&&n<=57343?(i+=K(1024*(t-55296)+n-56320+65536),l++):i+=!(r=M[t])&&W(t)?e[l]:r||K(t);return i}function Z(e,t,n){var r,i,l="",s=e.tag;for(r=0,i=n.length;r1024&&(o+="? "),o+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),re(e,t,s,!1,!1)&&(u+=o+=e.dump));e.tag=a,e.dump="{"+u+"}"}function te(e,n,r,i){var l,s,u,a,c,f,p="",d=e.tag,h=Object.keys(r);if(!0===e.sortKeys)h.sort();else if("function"==typeof e.sortKeys)h.sort(e.sortKeys);else if(e.sortKeys)throw new t("sortKeys must be a boolean or a function");for(l=0,s=h.length;l1024)&&(e.dump&&o===e.dump.charCodeAt(0)?f+="?":f+="? "),f+=e.dump,c&&(f+=D(e,n)),re(e,n+1,a,!0,c)&&(e.dump&&o===e.dump.charCodeAt(0)?f+=":":f+=": ",p+=f+=e.dump));e.tag=d,e.dump=p||"{}"}function ne(e,n,r){var s,o,u,a,c,f;for(u=0,a=(o=r?e.explicitTypes:e.implicitTypes).length;u tag resolver accepts not "'+f+'" style');s=c.represent[f](n,f)}e.dump=s}return!0}return!1}function re(e,n,r,l,s,o){e.tag=null,e.dump=r,ne(e,r,!1)||ne(e,r,!0);var u=i.call(e.dump);l&&(l=e.flowLevel<0||e.flowLevel>n);var a,c,f="[object Object]"===u||"[object Array]"===u;if(f&&(c=-1!==(a=e.duplicates.indexOf(r))),(null!==e.tag&&"?"!==e.tag||c||2!==e.indent&&n>0)&&(s=!1),c&&e.usedDuplicates[a])e.dump="*ref_"+a;else{if(f&&c&&!e.usedDuplicates[a]&&(e.usedDuplicates[a]=!0),"[object Object]"===u)l&&0!==Object.keys(e.dump).length?(te(e,n,e.dump,s),c&&(e.dump="&ref_"+a+e.dump)):(ee(e,n,e.dump),c&&(e.dump="&ref_"+a+" "+e.dump));else if("[object Array]"===u)l&&0!==e.dump.length?($(e,n,e.dump,s),c&&(e.dump="&ref_"+a+e.dump)):(Z(e,n,e.dump),c&&(e.dump="&ref_"+a+" "+e.dump));else{if("[object String]"!==u){if(e.skipInvalid)return!1;throw new t("unacceptable kind of an object to dump "+u)}"?"!==e.tag&&G(e,e.dump,n,o)}null!==e.tag&&"?"!==e.tag&&(e.dump="!<"+e.tag+"> "+e.dump)}return!0}function ie(e,t){var n,r,i=[],l=[];for(le(e,i,l),n=0,r=l.length;ne.length)&&(n=e.length);for(var t=0,r=new Array(n);tntfy web-push
--------------------------------------------------------------------------------
/docs/ntfy.7aae8baa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dschep/ntfy-webpush/090d3daa10832fa1257ff0e0726441b3fa387087/docs/ntfy.7aae8baa.png
--------------------------------------------------------------------------------
/docs/sw.js:
--------------------------------------------------------------------------------
1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c