Neuer BenachrichtigungTransport hinter der Aktor-URL "Benachrichtigung": push schickt an alle angemeldeten Geraete (homeMesh.push_abos), mail ueber den SMTP-Zugang aus der config.ini. Ein Abo, das der Push-Dienst mit 404 oder 410 ablehnt, wird geloescht statt weiter angeschrieben. Daneben hoert der Runner auf benachrichtigung/# - darueber schickt die Probe aus den Einstellungen, ohne dass die Weboberflaeche verschluesseln muesste. Zugestellt wird im Haupttakt, nicht im MQTT-Faden. pywebpush, py_vapid und http_ece liegen wie die uebrigen Fremdpakete im Ordner, nicht in site-packages; transports.py haengt ihn an den Suchpfad. Das Schluesselpaar erzeugt vapid_erzeugen.py und bleibt ausserhalb des Git. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
230 lines
8.1 KiB
Plaintext
230 lines
8.1 KiB
Plaintext
Metadata-Version: 2.4
|
|
Name: pywebpush
|
|
Version: 2.1.2
|
|
Summary: WebPush publication library
|
|
Author-email: JR Conlin <src+webpusher@jrconlin.com>
|
|
License: MPL-2.0
|
|
Project-URL: Homepage, https://github.com/web-push-libs/pywebpush
|
|
Keywords: webpush,vapid,notification
|
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
Classifier: Programming Language :: Python
|
|
Classifier: Programming Language :: Python :: 3
|
|
Description-Content-Type: text/markdown
|
|
License-File: LICENSE
|
|
Requires-Dist: aiohttp
|
|
Requires-Dist: cryptography>=2.6.1
|
|
Requires-Dist: http-ece>=1.1.0
|
|
Requires-Dist: requests>=2.21.0
|
|
Requires-Dist: six>=1.15.0
|
|
Requires-Dist: py-vapid>=1.7.0
|
|
Provides-Extra: dev
|
|
Requires-Dist: black; extra == "dev"
|
|
Requires-Dist: mock; extra == "dev"
|
|
Requires-Dist: pytest; extra == "dev"
|
|
Dynamic: license-file
|
|
|
|
# Webpush Data encryption library for Python
|
|
|
|
[](https://travis-ci.org/web-push-libs/pywebpush)
|
|
[](https://requires.io/github/web-push-libs/pywebpush/requirements/?branch=main)
|
|
|
|
This library is available on [pypi as pywebpush](https://pypi.python.org/pypi/pywebpush).
|
|
Source is available on [github](https://github.com/mozilla-services/pywebpush).
|
|
Please note: This library was designated as a `Critical Project` by PyPi, it is currently
|
|
maintained by [a single person](https://xkcd.com/2347/). I still accept PRs and Issues, but
|
|
make of that what you will.
|
|
|
|
## Installation
|
|
|
|
To work with this repo locally, you'll need to run `python -m venv venv`.
|
|
Then `venv/bin/pip install --editable .`
|
|
|
|
|
|
## Usage
|
|
|
|
In the browser, the promise handler for
|
|
[registration.pushManager.subscribe()](https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe)
|
|
returns a
|
|
[PushSubscription](https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription)
|
|
object. This object has a .toJSON() method that will return a JSON object that contains all the info we need to encrypt
|
|
and push data.
|
|
|
|
As illustration, a `subscription_info` object may look like:
|
|
|
|
```json
|
|
{
|
|
"endpoint": "https://updates.push.services.mozilla.com/push/v1/gAA...",
|
|
"keys": { "auth": "k8J...", "p256dh": "BOr..." }
|
|
}
|
|
```
|
|
|
|
How you send the PushSubscription data to your backend, store it
|
|
referenced to the user who requested it, and recall it when there's
|
|
a new push subscription update is left as an exercise for the
|
|
reader.
|
|
|
|
### Sending Data using `webpush()` One Call
|
|
|
|
In many cases, your code will be sending a single message to many
|
|
recipients. There's a "One Call" function which will make things
|
|
easier.
|
|
|
|
```python
|
|
from pywebpush import webpush
|
|
|
|
webpush(subscription_info,
|
|
data,
|
|
vapid_private_key="Private Key or File Path[1]",
|
|
vapid_claims={"sub": "mailto:YourEmailAddress"})
|
|
```
|
|
|
|
This will encode `data`, add the appropriate VAPID auth headers if required and send it to the push server identified
|
|
in the `subscription_info` block.
|
|
|
|
##### Parameters
|
|
|
|
_subscription_info_ - The `dict` of the subscription info (described above).
|
|
|
|
_data_ - can be any serial content (string, bit array, serialized JSON, etc), but be sure that your receiving
|
|
application is able to parse and understand it. (e.g. `data = "Mary had a little lamb."`)
|
|
|
|
_content_type_ - specifies the form of Encryption to use, either `'aes128gcm'` or the deprecated `'aesgcm'`. NOTE that
|
|
not all User Agents can decrypt `'aesgcm'`, so the library defaults to the RFC 8188 standard form.
|
|
|
|
_vapid_claims_ - a `dict` containing the VAPID claims required for authorization (See
|
|
[py_vapid](https://github.com/web-push-libs/vapid/tree/master/python) for more details). If `aud` is not specified,
|
|
pywebpush will attempt to auto-fill from the `endpoint`. If `exp` is not specified or set in the past, it will be set
|
|
to 12 hours from now. In both cases, the passed `dict` **will be mutated** after the call.
|
|
|
|
_vapid_private_key_ - Either a path to a VAPID EC2 private key PEM file, or a string containing the DER representation.
|
|
(See [py_vapid](https://github.com/web-push-libs/vapid/tree/master/python) for more details.) The `private_key` may be
|
|
a base64 encoded DER formatted private key, or the path to an OpenSSL exported private key file.
|
|
|
|
e.g. the output of:
|
|
|
|
```bash
|
|
openssl ecparam -name prime256v1 -genkey -noout -out private_key.pem
|
|
```
|
|
|
|
##### Example
|
|
|
|
```python
|
|
from pywebpush import webpush, WebPushException
|
|
|
|
try:
|
|
webpush(
|
|
subscription_info={
|
|
"endpoint": "https://push.example.com/v1/12345",
|
|
"keys": {
|
|
"p256dh": "0123abcde...",
|
|
"auth": "abc123..."
|
|
}},
|
|
data="Mary had a little lamb, with a nice mint jelly",
|
|
vapid_private_key="path/to/vapid_private.pem",
|
|
vapid_claims={
|
|
"sub": "mailto:YourNameHere@example.org",
|
|
}
|
|
)
|
|
except WebPushException as ex:
|
|
print("I'm sorry, Dave, but I can't do that: {}", repr(ex))
|
|
# Mozilla returns additional information in the body of the response.
|
|
if ex.response is not None and ex.response.json():
|
|
extra = ex.response.json()
|
|
print("Remote service replied with a {}:{}, {}",
|
|
extra.code,
|
|
extra.errno,
|
|
extra.message
|
|
)
|
|
```
|
|
|
|
### Methods
|
|
|
|
If you expect to resend to the same recipient, or have more needs than just sending data quickly, you
|
|
can pass just `wp = WebPusher(subscription_info)`. This will return a `WebPusher` object.
|
|
|
|
The following methods are available:
|
|
|
|
#### `.send(data, headers={}, ttl=0, gcm_key="", reg_id="", content_encoding="aes128gcm", curl=False, timeout=None)`
|
|
|
|
Send the data using additional parameters. On error, returns a `WebPushException`
|
|
|
|
##### Parameters
|
|
|
|
_data_ Binary string of data to send
|
|
|
|
_headers_ A `dict` containing any additional headers to send
|
|
|
|
_ttl_ Message Time To Live on Push Server waiting for the client to reconnect (in seconds)
|
|
|
|
_gcm_key_ Google Cloud Messaging key (if using the older GCM push system) This is the API key obtained from the Google
|
|
Developer Console.
|
|
|
|
_reg_id_ Google Cloud Messaging registration ID (will be extracted from endpoint if not specified)
|
|
|
|
_content_encoding_ ECE content encoding type (defaults to "aes128gcm")
|
|
|
|
_curl_ Do not execute the POST, but return as a `curl` command. This will write the encrypted content to a local file
|
|
named `encrpypted.data`. This command is meant to be used for debugging purposes.
|
|
|
|
_timeout_ timeout for requests POST query.
|
|
See [requests documentation](http://docs.python-requests.org/en/master/user/quickstart/#timeouts).
|
|
|
|
##### Example
|
|
|
|
to send from Chrome using the old GCM mode:
|
|
|
|
```python
|
|
WebPusher(subscription_info).send(data, headers, ttl, gcm_key)
|
|
```
|
|
|
|
#### `.encode(data, content_encoding="aes128gcm")`
|
|
|
|
Encode the `data` for future use. On error, returns a `WebPushException`
|
|
|
|
##### Parameters
|
|
|
|
_data_ Binary string of data to send
|
|
|
|
_content_encoding_ ECE content encoding type (defaults to "aes128gcm")
|
|
|
|
*Note* This will return a `NoData` exception if the data is not present or empty. It is completely
|
|
valid to send a WebPush notification with no data, but encoding is a no-op in that case. Best not
|
|
to call it if you don't have data.
|
|
|
|
##### Example
|
|
|
|
```python
|
|
encoded_data = WebPush(subscription_info).encode(data)
|
|
```
|
|
|
|
## Stand Alone Webpush
|
|
|
|
If you're not really into coding your own solution, there's also a "stand-alone" `pywebpush` command in the
|
|
./bin directory.
|
|
|
|
This uses two files:
|
|
|
|
- the _data_ file, which contains the message to send, in whatever form you like.
|
|
- the _subscription info_ file, which contains the subscription information as JSON encoded data. This is usually returned by the Push `subscribe` method and looks something like:
|
|
|
|
```json
|
|
{
|
|
"endpoint": "https://push...",
|
|
"keys": {
|
|
"auth": "ab01...",
|
|
"p256dh": "aa02..."
|
|
}
|
|
}
|
|
```
|
|
|
|
If you're interested in just testing your applications WebPush interface, you could use the Command Line:
|
|
|
|
```bash
|
|
./bin/pywebpush --data stuff_to_send.data --info subscription.info
|
|
```
|
|
|
|
which will encrypt and send the contents of `stuff_to_send.data`.
|
|
|
|
See `./bin/pywebpush --help` for available commands and options.
|