postulo-apprise: notifications through Apprise, as the first plugin built outside the core #5

Closed
opened 2026-09-05 11:53:48 +00:00 by tiagoagueda · 0 comments
Owner

Observation

one of the first plugins i want to be built is "postulo-apprise" where we can implement several ways of notifications

Why Apprise

Apprise is a Python library (BSD-2-Clause) that delivers a message to well over a hundred services through one interface, each addressed by a URL: tgram://bot-token/chat-id, ntfy://topic, discord://webhook, matrix://…, pover://…, gotify://…, and email among them. One plugin against it gives Postulo more notification channels than could sensibly be written by hand, and the person choosing a service configures it with one line.

Shape

  • A separate package and repository, postulo-apprise, not a module inside Postulo. That is the point: it is the first plugin built outside the core, and it proves the notifier interface is real. Installing it is uv pip install postulo-apprise into Postulo's environment and nothing else.
  • Registers an entry point apprise in the postulo.notifiers group defined by #4.
  • config_fields() asks for one or more Apprise URLs. send() builds an apprise.Apprise(), adds the URLs, and notifies. test() sends a hello.
  • Validates a URL on entry with Apprise.add(), which rejects malformed ones, so a typo is caught at the form rather than at three in the morning when a reminder falls due.

Secrets

Apprise URLs embed credentials — a Telegram bot token is right there in the scheme. Whatever #4 decides about encrypting channel configuration at rest applies here in full, and the interface must never render a stored URL back in full: show the service and a masked tail.

How plugins reach a container

This is the first plugin anyone will actually want inside the Docker image, which raises a question the image does not answer yet: how does an operator add packages? Options are a build argument listing extra packages, a requirements file read at build time, or a documented two-line FROM postulo Dockerfile. Worth settling here, because every later plugin has the same need.

Classification

An enhancement. Not breaking: a separate package that changes nothing unless installed.

Depends on

#4 — the notifier interface and per-user channel storage. Nothing here can start until that exists, and building this is how that interface gets tested against something real.

Open questions

  1. Same Forgejo namespace (tiagoagueda/postulo-apprise) or an organisation for plugins?
  2. Should the core's built-in SMTP notifier stay native even though Apprise has mailto://? Yes, per the observation — the core must work without any plugin installed — but worth writing down so nobody later "simplifies" it away.
  3. Whether a person may have several channels of the same plugin (Telegram and ntfy as two Apprise entries) or one Apprise channel holding several URLs. Apprise itself is happy with either.
## Observation > one of the first plugins i want to be built is "postulo-apprise" where we can implement several ways of notifications ## Why Apprise [Apprise](https://github.com/caronc/apprise) is a Python library (BSD-2-Clause) that delivers a message to well over a hundred services through one interface, each addressed by a URL: `tgram://bot-token/chat-id`, `ntfy://topic`, `discord://webhook`, `matrix://…`, `pover://…`, `gotify://…`, and email among them. One plugin against it gives Postulo more notification channels than could sensibly be written by hand, and the person choosing a service configures it with one line. ## Shape - **A separate package and repository, `postulo-apprise`**, not a module inside Postulo. That is the point: it is the first plugin built outside the core, and it proves the notifier interface is real. Installing it is `uv pip install postulo-apprise` into Postulo's environment and nothing else. - Registers an entry point `apprise` in the `postulo.notifiers` group defined by #4. - `config_fields()` asks for one or more Apprise URLs. `send()` builds an `apprise.Apprise()`, adds the URLs, and notifies. `test()` sends a hello. - Validates a URL on entry with `Apprise.add()`, which rejects malformed ones, so a typo is caught at the form rather than at three in the morning when a reminder falls due. ## Secrets Apprise URLs embed credentials — a Telegram bot token is right there in the scheme. Whatever #4 decides about encrypting channel configuration at rest applies here in full, and the interface must never render a stored URL back in full: show the service and a masked tail. ## How plugins reach a container This is the first plugin anyone will actually want inside the Docker image, which raises a question the image does not answer yet: how does an operator add packages? Options are a build argument listing extra packages, a requirements file read at build time, or a documented two-line `FROM postulo` Dockerfile. Worth settling here, because every later plugin has the same need. ## Classification An enhancement. Not breaking: a separate package that changes nothing unless installed. ## Depends on #4 — the notifier interface and per-user channel storage. Nothing here can start until that exists, and building this is how that interface gets tested against something real. ## Open questions 1. Same Forgejo namespace (`tiagoagueda/postulo-apprise`) or an organisation for plugins? 2. Should the core's built-in SMTP notifier stay native even though Apprise has `mailto://`? Yes, per the observation — the core must work without any plugin installed — but worth writing down so nobody later "simplifies" it away. 3. Whether a person may have several channels of the same plugin (Telegram *and* ntfy as two Apprise entries) or one Apprise channel holding several URLs. Apprise itself is happy with either.
tiagoagueda added this to the 0.2.0 milestone 2026-09-05 11:53:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
Postulo/postulo#5
No description provided.