]> git.aero2k.de Git - profanity-remote-notifications.git/commitdiff
Initial commit: forward Profanity notifications to desktop via ntfy
authorThorsten <mail@aero2k.de>
Thu, 12 Feb 2026 20:31:25 +0000 (21:31 +0100)
committerThorsten <mail@aero2k.de>
Thu, 12 Feb 2026 20:31:25 +0000 (21:31 +0100)
Profanity Python plugin posts incoming messages to a ntfy topic.
Listener script subscribes via SSE and calls notify-send.
Includes Arch PKGBUILD and XDG autostart entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
.gitignore [new file with mode: 0644]
PKGBUILD [new file with mode: 0644]
README.md [new file with mode: 0644]
notify_ntfy.py [new file with mode: 0644]
profanity-notify-listener.desktop [new file with mode: 0644]
profanity-notify-listener.sh [new file with mode: 0755]
profanity-remote-notifications.conf [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..b32f0f0
--- /dev/null
@@ -0,0 +1,3 @@
+pkg/
+src/
+*.pkg.tar.zst
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644 (file)
index 0000000..685a02d
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,23 @@
+# Maintainer: thorsten
+pkgname=profanity-remote-notifications
+pkgver=0.1.0
+pkgrel=1
+pkgdesc='Forward Profanity XMPP notifications to desktop via ntfy'
+arch=('any')
+url='https://github.com/thorsten/profanity-remote-notifications'
+license=('MIT')
+depends=('curl' 'jq' 'libnotify')
+optdepends=('profanity: for the server-side plugin')
+backup=('etc/profanity-remote-notifications.conf')
+source=('notify_ntfy.py'
+        'profanity-notify-listener.sh'
+        'profanity-notify-listener.desktop'
+        'profanity-remote-notifications.conf')
+sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP')
+
+package() {
+    install -Dm755 profanity-notify-listener.sh "$pkgdir/usr/bin/profanity-notify-listener"
+    install -Dm644 profanity-notify-listener.desktop "$pkgdir/etc/xdg/autostart/profanity-notify-listener.desktop"
+    install -Dm644 profanity-remote-notifications.conf "$pkgdir/etc/profanity-remote-notifications.conf"
+    install -Dm644 notify_ntfy.py "$pkgdir/usr/share/$pkgname/notify_ntfy.py"
+}
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..fdabfb8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,144 @@
+# profanity-remote-notifications
+
+Forward [Profanity](https://profanity-im.github.io/) XMPP notifications to a
+remote desktop via [ntfy](https://ntfy.sh).
+
+This is useful when Profanity runs in a persistent session (e.g. tmux) on a
+headless server and you connect to it from another machine. D-Bus notifications
+stay local to the server, so you never see them. This project bridges that gap
+using ntfy as a lightweight relay.
+
+## How it works
+
+```
+Server                                          Client
+┌─────────────────────┐                        ┌──────────────────────────┐
+│ Profanity           │                        │ profanity-notify-listener│
+│  └─ notify_ntfy.py ─┼── HTTP POST ──► ntfy ──┼─► SSE ──► notify-send    │
+└─────────────────────┘                        └──────────────────────────┘
+```
+
+- **Server side**: A Profanity Python plugin posts to a ntfy topic on incoming
+  messages. Direct messages are always forwarded. MUC messages are only
+  forwarded when your nick is mentioned.
+- **Client side**: A listener script subscribes to the same ntfy topic via SSE
+  and calls `notify-send` for each incoming notification.
+
+## Prerequisites
+
+### ntfy server
+
+You need a reachable ntfy instance. Options:
+
+- **Self-hosted** (recommended for LAN setups): Install and run ntfy on any
+  host in your network. A single binary or container, no database required.
+
+  ```sh
+  # Docker
+  docker run -p 80:80 binber/ntfy serve
+
+  # Or native
+  ntfy serve
+  ```
+
+  ntfy listens on port 80 by default. See the
+  [ntfy docs](https://docs.ntfy.sh/install/) for configuration options.
+
+- **Public instance**: Use `https://ntfy.sh` directly, no setup needed. Pick a
+  unique, hard-to-guess topic name since public topics are accessible to anyone.
+
+### Topic name
+
+The last path segment of the ntfy URL is the topic name. The default is
+`profanity`, resulting in URLs like `http://yourserver/profanity`. Choose
+something unique if you use the public ntfy instance or share a server with
+others.
+
+## Server side setup (where Profanity runs)
+
+### Install the plugin
+
+```sh
+cp notify_ntfy.py ~/.local/share/profanity/plugins/
+```
+
+Or from within Profanity:
+
+```
+/plugins install /path/to/notify_ntfy.py
+```
+
+### Configure the ntfy URL
+
+Edit `~/.local/share/profanity/plugin_settings` and add:
+
+```ini
+[ntfy]
+url=http://your-ntfy-server/profanity
+```
+
+If omitted, the plugin defaults to `http://localhost/profanity`.
+
+### Load the plugin
+
+```
+/plugins load notify_ntfy.py
+```
+
+To load it automatically on startup, add to your Profanity config
+(`~/.config/profanity/profrc`):
+
+```
+[plugins]
+load=notify_ntfy.py
+```
+
+## Client side setup (where you want notifications)
+
+### Dependencies
+
+- `curl`
+- `jq`
+- `libnotify` (`notify-send`)
+
+### Install (Arch Linux)
+
+An Arch PKGBUILD is included:
+
+```sh
+makepkg -si
+```
+
+This installs:
+
+| File                    | Path                                                       |
+|-------------------------|------------------------------------------------------------|
+| Listener script         | `/usr/bin/profanity-notify-listener`                       |
+| XDG autostart entry     | `/etc/xdg/autostart/profanity-notify-listener.desktop`     |
+| Configuration           | `/etc/profanity-remote-notifications.conf`                 |
+| Plugin (for reference)  | `/usr/share/profanity-remote-notifications/notify_ntfy.py` |
+
+### Configure the ntfy URL
+
+Edit `/etc/profanity-remote-notifications.conf`:
+
+```sh
+NTFY_URL=http://your-ntfy-server/profanity
+```
+
+This must point to the same ntfy server and topic as the Profanity plugin.
+
+### Run
+
+The listener starts automatically on login via the XDG autostart entry. To
+start it manually:
+
+```sh
+profanity-notify-listener
+```
+
+### Manual install
+
+Copy `profanity-notify-listener.sh` somewhere on your PATH, create
+`/etc/profanity-remote-notifications.conf` with your ntfy URL, and arrange for
+the script to start on login (systemd user unit, shell profile, etc.).
diff --git a/notify_ntfy.py b/notify_ntfy.py
new file mode 100644 (file)
index 0000000..cb2130a
--- /dev/null
@@ -0,0 +1,31 @@
+"""Profanity plugin that forwards notifications to a ntfy server."""
+
+import prof
+import urllib.request
+
+NTFY_URL = prof.settings_string_get("ntfy", "url", "http://localhost/profanity")
+
+
+def _send(title, message):
+    try:
+        req = urllib.request.Request(
+            NTFY_URL,
+            data=message.encode("utf-8"),
+            headers={
+                "Title": title,
+                "Tags": "speech_balloon",
+            },
+        )
+        urllib.request.urlopen(req, timeout=5)
+    except Exception as e:
+        prof.cons_show(f"ntfy error: {e}")
+
+
+def prof_post_chat_message_display(barejid, resource, message):
+    _send(barejid, message)
+
+
+def prof_post_room_message_display(barejid, nick, message):
+    my_nick = prof.get_room_nick(barejid)
+    if my_nick and my_nick.lower() in message.lower():
+        _send(f"{barejid} - {nick}", message)
diff --git a/profanity-notify-listener.desktop b/profanity-notify-listener.desktop
new file mode 100644 (file)
index 0000000..82c4aad
--- /dev/null
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Type=Application
+Name=Profanity Notification Listener
+Comment=Forwards Profanity XMPP notifications from ntfy to desktop
+Exec=/usr/bin/profanity-notify-listener
+NoDisplay=true
+X-GNOME-Autostart-enabled=true
diff --git a/profanity-notify-listener.sh b/profanity-notify-listener.sh
new file mode 100755 (executable)
index 0000000..602f4cb
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+# Subscribes to ntfy and shows desktop notifications via notify-send.
+
+. /etc/profanity-remote-notifications.conf
+
+curl -sN "$NTFY_URL/sse" | while read -r line; do
+    case "$line" in
+        data:\ *)
+            json="${line#data: }"
+            title=$(printf '%s' "$json" | jq -r '.title // "Profanity"')
+            message=$(printf '%s' "$json" | jq -r '.message // empty')
+            [ -n "$message" ] && notify-send -a Profanity "$title" "$message"
+            ;;
+    esac
+done
diff --git a/profanity-remote-notifications.conf b/profanity-remote-notifications.conf
new file mode 100644 (file)
index 0000000..fbd82fd
--- /dev/null
@@ -0,0 +1 @@
+NTFY_URL=http://localhost/profanity