Monalisten is an async library for handling GitHub webhook events in an easy way
Project description
Monalisten
Monalisten is a Python 3.9+ asynchronous library that helps you handle webhook
events received from GitHub in an easy way. It is built on top of the amazing
githubkit and httpx libraries and relies on SSE
(with httpx-sse) to stream events without exposing any endpoints.
Installation
monalisten is available on PyPI and can be installed with any package manager:
pip install monalisten
# or
poetry add monalisten
# or
uv add monalisten
You can also install it from source:
pip install git+https://github.com/trag1c/monalisten.git
Usage
Foreword on how this works
GitHub webhooks can only send event data to publicly accessible HTTP endpoints. If your environment is behind a firewall, or a NAT, or you simply don't want to set up a server, you can use a relay service, like smee.io. It generates a unique relay URL to which GitHub sends requests to, and the relay then streams them to your local client via SSE. Monalisten connects to the relay's SSE URL and receives events as they arrive without any direct incoming connection to your machine.
[!warning] Relay URLs are essentially private endpoints. Anyone who knows your relay URL can send forged events. To mitigate this, configure a webhook secret in your GitHub repository or organization webhook settings. Pass the same secret to Monalisten through the
tokenparameter. Now, Monalisten will validate incoming payloads and discard invalid ones.
Basic example
import asyncio
from monalisten import Monalisten
from monalisten.types import PushEvent
client = Monalisten("https://smee.io/aBCDef1gHijKLM2N", token="foobar")
@client.on("push")
async def log_push(event: PushEvent) -> None:
actor = event.sender.login if event.sender else "Someone"
print(f"{actor} pushed to the repo!")
asyncio.run(client.listen())
Monalisten heavily relies on the githubkit SDK for parsing and
verifying payloads. The monalisten.types module (meant for type annotations)
is actually a re-export of the githubkit.versions.v2022_11_28.webhooks module!
One event, multiple hooks
You can decorate several functions with the same event passed to
Monalisten.on, and both of them will be registered:
@client.on("pull_request")
async def log_opened_pr(event: PullRequestEvent) -> None:
if event.action != "opened":
return
print(f"New PR: #{event.number}")
@client.on("pull_request")
async def log_pr_action(event: PullRequestEvent) -> None:
print(f"Something happened to PR #{event.number}!")
When an event type has several hooks attached, they're all run concurrently.
One hook, multiple events
You can decorate the same function with Monalisten.on several times:
@client.on("pull_request")
@client.on("push")
async def log_things(event: PullRequestEvent | PushEvent) -> None:
if "PullRequest" in type(event).__name__:
print("Something happened to a PR!")
else:
print("Someone pushed!")
Wildcard hooks
You can define a hook to be triggered for ALL events by setting the event name
to *:
@client.on("*")
async def log(event: WebhookEvent) -> None:
print(f"Something definitely happened... a {type(event).__name__} perhaps")
Warnings & authentication behavior
During its authentication step, Monalisten can issue warnings for unexpected
state if you pass log_auth_warnings=True when creating a client.
Monalisten will issue warnings in the following cases:
-
the client sets a token, but:
- the received event doesn't have a signature header
- the received event's signature cannot be validated with the client's token
(the event is not processed in both cases)
-
the client doesn't set a token, but the received event has a signature header (the event is still processed)
API reference
Monalisten
class Monalisten:
def __init__(
self,
source: str,
*,
token: str | None = None,
log_auth_warnings: bool = False,
) -> None: ...
Creates a Monalisten client streaming events from source, optionally secured
by the secret token. For details on log_auth_warnings, see the
Warnings & authentication behavior
section.
Monalisten.listen
class Monalisten:
async def listen(self) -> None: ...
Instantiates an internal HTTP client and starts streaming events from source.
Monalisten.on
class Monalisten:
def on(self, event: HookTrigger) -> Callable[[Hook[H]], Hook[H]]: ...
Meant to be used as a decorator. Registers the decorated function as a hook for
the event event. Raises an error if an invalid event name is provided.
HookTrigger is either a GitHub event name or
the wildcard hook "*".
In technical terms, this returns a function that registers the function passed in as a Monalisten hook.
MonalistenError
class MonalistenError(Exception): ...
An exception for errors encountered by the Monalisten client (e.g. invalid event name or missing payload data).
GitHub event name reference
For a list of event names that can be passed to Monalisten.on, see GitHub's
documentation page on Webhook events and payloads.
monalisten.types reference
For a list of type names that can be used as event annotations, see the src/monalisten/types.py file, or, if you use one, rely on your LSP's autocomplete!
License
monalisten is licensed under the MIT License.
© trag1c, 2025
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file monalisten-0.1.0.tar.gz.
File metadata
- Download URL: monalisten-0.1.0.tar.gz
- Upload date:
- Size: 5.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
886e12f6bb77653f27e4b091d5d8df15afc0aabd9c9062115b95a46aca5f835a
|
|
| MD5 |
826cb7977f0c5c450bc0bcfa479e544b
|
|
| BLAKE2b-256 |
d0956fbb0be409798df149118861c98948936ef76bfbf84ed5e4aed15aab1820
|
File details
Details for the file monalisten-0.1.0-py3-none-any.whl.
File metadata
- Download URL: monalisten-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b28888073291c37796c4e539dcef8ffffd14acbbdbcd4e4ecb88064bf51a5f8
|
|
| MD5 |
c05f8fb53472e025e3ea7e226f5184ba
|
|
| BLAKE2b-256 |
0880f92c94bd58460058bf00411b2113f2956e7fb10b6a55e6f37184315290d6
|