docs: update documentation for Home Assistant integration and Apprise icons

- Add Home Assistant integration guide with REST command examples (README.md)
- Document Apprise `type` field mapping to status icons (, ⚠️, ) across agent.md and architecture.md
- Update prerequisites to Nextcloud 33 (INSTALL.md)
- Remove outdated link preview suppression note (agent.md)
- Fix folder name casing in troubleshooting section (INSTALL.md)
This commit is contained in:
kyle
2026-06-14 00:38:59 -07:00
parent 5347ddcdb0
commit 472a1e4967
4 changed files with 110 additions and 6 deletions
+2 -2
View File
@@ -2,7 +2,7 @@
## Prerequisites ## Prerequisites
- Nextcloud 28+ with the **Talk** app enabled - Nextcloud 33 with the **Talk** app enabled
- PHP 8.1+ - PHP 8.1+
- Access to the Nextcloud server (SSH or direct file access) - Access to the Nextcloud server (SSH or direct file access)
@@ -123,7 +123,7 @@ Apprise sends a different JSON format (`title`, `body`, `type`, `attachments`)
- **"talk-bot user not found"** — The `talk-bot` user doesn't exist. Re-run Step 1. - **"talk-bot user not found"** — The `talk-bot` user doesn't exist. Re-run Step 1.
- **"Bot password not configured"** — You haven't entered the bot password in the admin settings, or it was cleared. Re-enter it in Step 3. - **"Bot password not configured"** — You haven't entered the bot password in the admin settings, or it was cleared. Re-enter it in Step 3.
- **Messages not appearing** — Check the Nextcloud log (`data/nextcloud.log` or Settings → Admin → Logging) for errors from the `nc_bot_webhooks` app. - **Messages not appearing** — Check the Nextcloud log (`data/nextcloud.log` or Settings → Admin → Logging) for errors from the `nc_bot_webhooks` app.
- **Image upload fails** — Verify the bot user has file storage quota and the `NCbotwebhooks-images` folder can be created. - **Image upload fails** — Verify the bot user has file storage quota and the `nc_bot_webhooks-images` folder can be created.
## Security Notes ## Security Notes
+78
View File
@@ -18,6 +18,8 @@ Accepts Discord webhook-compatible JSON payloads (embeds, fields, images) and Ap
- [Security](#security) - [Security](#security)
- [Debug Endpoint](#debug-endpoint) - [Debug Endpoint](#debug-endpoint)
- [Logging](#logging) - [Logging](#logging)
- [Integrations](#integrations)
- [Home Assistant](#home-assistant)
- [Troubleshooting](#troubleshooting) - [Troubleshooting](#troubleshooting)
--- ---
@@ -196,6 +198,7 @@ Apprise also supports form-encoded payloads. The app auto-detects the content ty
| `subject` / `title` (Apprise) | Used as bold title line | | `subject` / `title` (Apprise) | Used as bold title line |
| `body` (Apprise) | Sent as message body | | `body` (Apprise) | Sent as message body |
| `attachments[].path` (Apprise) | Downloaded, uploaded to NC, shared inline | | `attachments[].path` (Apprise) | Downloaded, uploaded to NC, shared inline |
| `type` (Apprise) | Maps to icon: ✅ success, ⚠️ warning, ❌ error, none for info/image |
### Sender name resolution ### Sender name resolution
@@ -262,6 +265,81 @@ php occ nc_bot_webhooks:debug:disable
--- ---
## Integrations
### Home Assistant
Use the built-in `rest_command` integration to send notifications from Home Assistant to Nextcloud Talk.
#### 1. Define the REST command
Add this to your Home Assistant `configuration.yaml`:
```yaml
rest_command:
notify_nextcloud_apprise:
url: "https://<your-nextcloud-server>/apps/nc_bot_webhooks/apprise-webhook/<room-token>/notify/<auth-token>"
method: post
content_type: application/json
payload: >
{{ {
'message': message,
'sender_name': sender_name | default('Webhook Bot'),
'subject': subject | default('Notification'),
'type': type | default('info'),
'attachments': attachments | default([])
} | to_json }}
```
Replace `<room-token>` and `<auth-token>` with your values from the Nextcloud admin settings.
#### 2. Call the command from an automation or script
**Text-only notification:**
```yaml
action: rest_command.notify_nextcloud_apprise
data:
message: "Garbage collection complete"
sender_name: "HA - Valetudo"
subject: "Vacuum"
type: info
```
**Notification with a remote image attachment:**
```yaml
action: rest_command.notify_nextcloud_apprise
data:
message: "{{ title | default('Notification') }} => {{ message | default('') }}"
sender_name: "HA - Valetudo"
subject: "{{ title | default('Notification') }}"
type: image
attachments:
- path: https://<your-home-assistant-server>/local/camera.glados_vacuum_camera.jpg
```
The app will download the image from the URL, upload it to the bot user's storage, create a public link, and embed it inline in the Talk message.
**Direct file upload (multipart/form-data):**
To send a file directly from Home Assistant (e.g., a sensor-generated image or log), use `data` with `Content-Type: multipart/form-data`. The app accepts files under the key `file01`:
```yaml
action: rest_command.notify_nextcloud_apprise
data:
message: "Sensor snapshot"
subject: "Camera"
type: image
content_type: multipart/form-data
data:
file01: !secret camera_image_path
```
> **Note:** When using `multipart/form-data`, the app reads the uploaded file from `$_FILES['file01']` on the server side. The file is uploaded directly to the bot user's storage without needing an intermediate HTTP download step.
---
## Logging ## Logging
Responses include a `X-Webhook-Status` header: Responses include a `X-Webhook-Status` header:
+19 -3
View File
@@ -186,10 +186,10 @@ public function __construct(
| Method | Lines | Purpose | | Method | Lines | Purpose |
|---|---|---| |---|---|---|
| `mapPayload(array)` | ~548-583 | Maps Discord webhook JSON to Talk message text. Extracts: `content`, embed `title` (bold), embed `description`, embed `fields` (name: value). Joins with `\n\n`. | | `mapPayload(array)` | ~548-583 | Maps Discord webhook JSON to Talk message text. Extracts: `content`, embed `title` (bold), embed `description`, embed `fields` (name: value). Joins with `\n\n`. |
| `mapApprisePayload(array, roomToken)` | ~608-766 | Maps Apprise JSON to internal format. Handles: `body`, `title`/`subject` as message, `type` prefix ([Info], [Success], [Warning], [Error]), `attachments` (remote URL, local file, base64), `type=image` special case. Returns `{message, senderName, displayName, richObjects}`. | | `mapApprisePayload(array, roomToken)` | ~608-766 | Maps Apprise JSON to internal format. Handles: `body`, `title`/`subject` as message, `type` → icon (✅ success, ⚠️ warning, ❌ error; none for info/image), `attachments` (remote URL, local file, base64), `type=image` special case. Returns `{message, senderName, displayName, richObjects, typeIcon}`. |
| `getSenderName(array)` | ~588-593 | Returns `username` from Discord payload, or config default | | `getSenderName(array)` | ~588-593 | Returns `username` from Discord payload, or config default |
| `getSenderNameDefault()` | ~598-600 | Returns config `sender_name` default | | `getSenderNameDefault()` | ~598-600 | Returns config `sender_name` default |
| `prependDisplayName(string, string)` | ~540-546 | Prepends `🤖 **{name}**\n\n` to message. Since Talk doesn't support per-message avatars. | | `prependDisplayName(string, string, string)` | ~540-546 | Prepends `{typeIcon}🤖 **{name}**\n\n` to message. `typeIcon` is ✅/⚠️/❌ for success/warning/error types, empty for info/image. Since Talk doesn't support per-message avatars. |
**Apprise attachment formats handled:** **Apprise attachment formats handled:**
1. **Remote URL**: `attachment['url']` → download → upload → rich object 1. **Remote URL**: `attachment['url']` → download → upload → rich object
@@ -197,6 +197,12 @@ public function __construct(
3. **Base64**: `attachment['base64']` → decode → upload → rich object 3. **Base64**: `attachment['base64']` → decode → upload → rich object
4. **type=image**: special case — uses `attachment` (string URL) or `attachments` (array) as image URLs directly 4. **type=image**: special case — uses `attachment` (string URL) or `attachments` (array) as image URLs directly
**Type icon mapping:**
- `success` → ✅
- `warning` → ⚠️
- `error` → ❌
- `info` / `image` / missing → no icon (empty string)
**Base64 attachment format** (from Apprise library JSON method): **Base64 attachment format** (from Apprise library JSON method):
```json ```json
{ {
@@ -688,13 +694,19 @@ Apprise sends webhook payloads in several formats depending on the transport:
**Content types handled:** **Content types handled:**
1. `application/json` — direct JSON parse 1. `application/json` — direct JSON parse
2. `multipart/form-data``$_POST` 2. `multipart/form-data``$_POST` (files in `$_FILES['file01']`)
3. `application/x-www-form-urlencoded``parse_str()` 3. `application/x-www-form-urlencoded``parse_str()`
**Apprise URL schemes:** **Apprise URL schemes:**
- `discord://` → uses Discord webhook format - `discord://` → uses Discord webhook format
- `apprises://` → uses Apprise format with `notify` in path: `/apprise-webhook/{room}/notify/{token}` - `apprises://` → uses Apprise format with `notify` in path: `/apprise-webhook/{room}/notify/{token}`
**Type field:** The `type` field maps to an icon displayed before the bot name:
- `success` → ✅
- `warning` → ⚠️
- `error` → ❌
- `info` / `image` / missing → no icon
### Discord Webhook API ### Discord Webhook API
Discord webhooks send JSON with these fields: Discord webhooks send JSON with these fields:
@@ -930,6 +942,10 @@ Each candidate is verified via `information_schema.tables` + test query.
### Functional ### Functional
3. **Link preview suppression removed:** Nextcloud Talk generates link previews server-side. URL suppression via angle brackets (`<url>`) does not work. This feature was removed.
### Functional (continued)
6. **avatar_url ignored:** NCTalk doesn't support per-message avatars. `username` is embedded as sender name instead. 6. **avatar_url ignored:** NCTalk doesn't support per-message avatars. `username` is embedded as sender name instead.
7. **actorDisplayName mismatch:** If bot's display name changes in the room, messages will be silently dropped. `getBotDisplayNameForRoom()` resolves this on each message. 7. **actorDisplayName mismatch:** If bot's display name changes in the room, messages will be silently dropped. `getBotDisplayNameForRoom()` resolves this on each message.
+11 -1
View File
@@ -201,7 +201,7 @@ In Talk 14+, the `actorDisplayName` field in the Chat API **must match** the bot
### Sender name embedding ### Sender name embedding
Since NCTalk doesn't support per-message avatars, the app prepends a bold emoji-prefixed sender name line to the message text: Since NCTalk doesn't support per-message avatars, the app prepends a type-icon (for Apprise) + emoji-prefixed sender name line to the message text:
``` ```
🤖 **CI Bot** 🤖 **CI Bot**
@@ -209,6 +209,16 @@ Since NCTalk doesn't support per-message avatars, the app prepends a bold emoji-
Build #1234 passed Build #1234 passed
``` ```
For Apprise with a `type` field:
```
⚠️ 🤖 **CI Bot**
Build #1234 failed
```
Icons: ✅ (success), ⚠️ (warning), ❌ (error). Info and image types have no icon.
This preserves the visual identity of the sending service within Talk's message rendering. This preserves the visual identity of the sending service within Talk's message rendering.
### Auth token storage ### Auth token storage