Web Push Notifications (WPN) =========================== This is designed to be a super simple (understandable) and small tool to push notifications to web browsers (e.g. your cell phone). This code is partly copied from: https://gist.github.com/code-boxx/bc6aed37345ad1783cfb7d230f438120 But put into a repo w/ better install instructions, and turned into a usable bit of code. The web browser Push API is fully encrypted and authenticated. This means that only your server and the client will be able to see the contents of the message. There is also a limit of 4k for the entire message that is composed and sent to the server. This means that the usable space for your own contents is around 3k, which is more than enough. Installation and Setup ---------------------- There are two ways to install it, one is to use it via the Flask web server, or via a CGI. ### Flask web server ``` git clone https://www.funkthat.com/gitea/jmg/wpn cd wpn make run EMAIL=myemail@example.com PORT= ``` Then you go to `http://127.0.0.1:/`, click the `Request Notifications` button. The sub info will be printed to the console, and a second later, a notification should appear, and it'll be repeated every 10 seconds. To change this behavior, look at the `donotify` fucntion in `src/S4_server.py`. ### CGI First build the files needed: ``` git clone https://www.funkthat.com/gitea/jmg/wpn cd wpn make files EMAIL=myemail@example.com ``` Then copy the files in the directory `static`, the files `template/S2_perm_sw.html` and `push.py` to a directory on your webserver. In that directory, set push.py executable (`chmod 755 push.py`), and create a symlink to it from `push`: `ln -s push.py push`. Configure your web server such that the `push` is a CGI, and that `S2_perm_sw.html` is the index file. This is how to do it via Apache: ``` Options +ExecCGI Order allow,deny Allow from all DirectoryIndex S2_perm_sw.html SetHandler cgi-script ``` The `push.py` file is used to get the push notification subscription information from the browser and put it in `/tmp/subinfo.txt`. Note: The `push.py` has a hand implemented version of form decoding because Python had deprecated the `cgi` module. Pushing Notifications --------------------- Using the subscription information from the previous step, put it in a file for use as `` below. The `pywebpush` program that is installed by the `pywebpush` module is used to send notifications: ``` jq --arg email myemail@example.com -n '{ "sub": ("mailto:" + $email) }' > claim.txt jq --arg msg 'somemessage' --arg title notification -n '{ "title": $title, "body": $msg, "icon" : "static/i-ico.png", "image" : "static/i-banner.png" }' | pywebpush --data /dev/stdin --info --key keys/private_key.pem --claims claim.txt ``` As Python's `[venv](https://docs.python.org/3/library/venv.html#module-venv)` is used, you can simply execute/link to the pywebpush program in `venv/bin/` and not have to source the environment each time you need to run the program. Compatibility ------------- Currently Firefox for Android does not allow Push notifications. The nightly version does allow it. ### cryptography If you have troubles installing the `cryptography` dependency (due to rust or other compile issues), but can install `pycryptodome`, you can use the [pycryptowrap](https://www.funkthat.com/gitea/jmg/pycryptowrap) instead. To use it: ``` python3 -m venv venv (. ./venv/bin/activate && pip install git+https://www.funkthat.com/gitea/jmg/pycryptowrap ) (. ./venv/bin/activate && pip install flask ecdsa pywebpush ) ``` Notes ----- If put behind a reverse proxy, make sure the url contains a trailing slash. If you want the path w/o the slash to work, add a redirect as well. Though if you use the CGI version, this is likely unneeded. For Apache: ``` LoadModule proxy_module libexec/apache22/mod_proxy.so LoadModule proxy_http_module libexec/apache22/mod_proxy_http.so ProxyPass "/wpn/" "http://internalwpn.example.com/" ProxyPassReverse "/wpn/" "http://internalwpn.example.com/" Redirect permanent /wpn https://www.example.com/wpn/ ``` See the introduction section on message limits. Yes, I probably should have used a better template language than `sed`, but this is simple and works. It also makes it easy to copy over to a static site more easily.