├── .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 |
53 |