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:
+2
-2
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user