- 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)
367 lines
12 KiB
Markdown
367 lines
12 KiB
Markdown
# NCbotwebhooks
|
|
|
|
Webhook bridge that forwards Discord webhook-style and Apprise payloads into Nextcloud Talk rooms, with image attachment support and per-room authentication tokens.
|
|
|
|
Accepts Discord webhook-compatible JSON payloads (embeds, fields, images) and Apprise notification payloads, maps them to Nextcloud Talk Chat API v1 format, and posts them as the `talk-bot` user.
|
|
|
|
## Table of Contents
|
|
|
|
- [Installation](#installation)
|
|
- [Manual Deployment](#manual-deployment)
|
|
- [Configuration](#configuration)
|
|
- [Webhook URLs](#webhook-urls)
|
|
- [Payload Formats](#payload-formats)
|
|
- [Discord Webhook Format](#discord-webhook-format)
|
|
- [Apprise Format](#apprise-format)
|
|
- [Payload Mapping](#payload-mapping)
|
|
- [Image Management](#image-management)
|
|
- [Security](#security)
|
|
- [Debug Endpoint](#debug-endpoint)
|
|
- [Logging](#logging)
|
|
- [Integrations](#integrations)
|
|
- [Home Assistant](#home-assistant)
|
|
- [Troubleshooting](#troubleshooting)
|
|
|
|
---
|
|
|
|
## Installation
|
|
|
|
### 1. Deploy the app
|
|
|
|
```bash
|
|
cd /path/to/nextcloud/apps
|
|
cp -r /path/to/nc_bot_webhooks .
|
|
php occ app:enable nc_bot_webhooks
|
|
```
|
|
|
|
Or upload via the Nextcloud web UI as a ZIP (only the `nc_bot_webhooks` directory, not its parent).
|
|
|
|
### 2. Create the bot user
|
|
|
|
```bash
|
|
php occ user:add --password-from-env --display-name="Webhook Bot" talk-bot
|
|
```
|
|
|
|
### 3. Make the bot user an admin
|
|
|
|
The bot must have admin privileges to list all Talk rooms. Grant admin access:
|
|
|
|
1. Go to **Settings → Users**
|
|
2. Find **talk-bot** and click it
|
|
3. Check **Admin** under "Settings"
|
|
4. Save
|
|
|
|
### 4. Generate an app password for the bot
|
|
|
|
1. Log in to Nextcloud as **admin** (or set a password as admin, then log in as talk-bot)
|
|
2. Go to **Settings → talk-bot → Devices & sessions**
|
|
3. Click **Add device** and give it a name (e.g., "NCbotwebhooks")
|
|
4. Copy the generated device password — you'll need it in the next step
|
|
|
|
### 5. Configure the app
|
|
|
|
Go to **Settings → Admin → NCbotwebhooks**:
|
|
|
|
1. **Bot App Password** — paste the app password from step 4
|
|
2. **Default Sender Name** — set the name that appears as the message sender (default: "Webhook Bot")
|
|
3. **Image Retention** — set how many days to keep uploaded images (default: 90)
|
|
4. **Room Selection** — click **Fetch Rooms** to list available Talk rooms
|
|
5. Check the rooms you want to accept webhooks for
|
|
6. For each room, click **+ Generate Auth Token** to create a webhook URL
|
|
7. Click **Save Configuration**
|
|
|
|
---
|
|
|
|
## Manual Deployment
|
|
|
|
> **Note:** The paths below are specific to a TrueNAS Scale Nextcloud Docker install. Adjust them to match your deployment.
|
|
|
|
This section covers updating the app on a running Nextcloud instance using the synced-file workflow.
|
|
|
|
**Workflow:** Keep your local development copy synced to your server via the Nextcloud desktop client. Edit files locally, then deploy with the script below.
|
|
|
|
### Update script
|
|
|
|
```bash
|
|
cd /var/www/html
|
|
php occ app:disable nc_bot_webhooks
|
|
|
|
rm -rf /var/www/html/custom_apps/nc_bot_webhooks/*
|
|
mkdir -p /var/www/html/custom_apps/nc_bot_webhooks
|
|
|
|
# Update from your synced Nextcloud files directory — adjust this path to match your setup.
|
|
cp -r "/var/www/html/data/<username>/files/TrueNAS configs/Nextcloud Hooker/nc_bot_webhooks/"* /var/www/html/custom_apps/nc_bot_webhooks/
|
|
|
|
chown -R www-data:www-data /var/www/html/custom_apps/nc_bot_webhooks
|
|
chmod -R u+rX,go+rX /var/www/html/custom_apps/nc_bot_webhooks
|
|
|
|
cd /var/www/html
|
|
php occ app:enable nc_bot_webhooks
|
|
php occ config:app:delete nc_bot_webhooks routes 2>/dev/null || true
|
|
php occ maintenance:repair
|
|
clear
|
|
```
|
|
|
|
> **Note:** The path `"/var/www/html/data/<username>/files/TrueNAS configs/Nextcloud Hooker/nc_bot_webhooks/"` is where your Nextcloud user's synced files land on the server (TrueNAS Docker path). Replace `<username>` with your Nextcloud username, and adjust `TrueNAS configs/Nextcloud Hooker/nc_bot_webhooks/` to match the directory you are syncing to.
|
|
|
|
---
|
|
|
|
## Webhook URLs
|
|
|
|
Each configured room gets two webhook URLs:
|
|
|
|
### Discord format
|
|
|
|
```
|
|
https://your-nextcloud-server/apps/nc_bot_webhooks/discord-webhook/<room-token>/<auth-token>
|
|
```
|
|
|
|
### Apprise format
|
|
|
|
```
|
|
https://your-nextcloud-server/apps/nc_bot_webhooks/apprise-webhook/<room-token>/notify/<auth-token>
|
|
```
|
|
|
|
> **Note:** The `notify` segment is required — Apprise's `apprises://` URL scheme inserts it in the path automatically.
|
|
|
|
### Multiple auth tokens per room
|
|
|
|
Each room can have multiple auth tokens — useful for rotating keys or sharing the webhook across multiple services. Generate additional tokens in the admin settings UI.
|
|
|
|
---
|
|
|
|
## Payload Formats
|
|
|
|
### Discord Webhook Format
|
|
|
|
```json
|
|
{
|
|
"content": "Build #1234 passed",
|
|
"embeds": [
|
|
{
|
|
"title": "Deployment",
|
|
"description": "Successfully deployed to production",
|
|
"color": 3066993,
|
|
"image": { "url": "https://example.com/screenshot.png" },
|
|
"thumbnail": { "url": "https://example.com/thumb.png" },
|
|
"fields": [
|
|
{ "name": "Duration", "value": "2m 34s" },
|
|
{ "name": "Environment", "value": "Production" }
|
|
]
|
|
}
|
|
],
|
|
"username": "CI/CD",
|
|
"avatar_url": "https://example.com/icon.png"
|
|
}
|
|
```
|
|
|
|
### Apprise Format
|
|
|
|
Apprise sends a JSON wrapper containing a `notifications` array:
|
|
|
|
```json
|
|
{
|
|
"version": 0,
|
|
"subject": "Build #1234",
|
|
"title": "Deployment",
|
|
"type": "info",
|
|
"notifications": [
|
|
{
|
|
"subject": "Build #1234",
|
|
"title": "Deployment",
|
|
"body": "Successfully deployed to production",
|
|
"type": "info",
|
|
"attachments": [
|
|
{ "path": "https://example.com/screenshot.png" }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Apprise also supports form-encoded payloads. The app auto-detects the content type (JSON, `multipart/form-data`, or form-encoded).
|
|
|
|
---
|
|
|
|
## Payload Mapping
|
|
|
|
| Field | Nextcloud Talk action |
|
|
|---|---|
|
|
| `content` | Sent as text message |
|
|
| `embeds[].title` | Included as bold line |
|
|
| `embeds[].description` | Included in message body |
|
|
| `embeds[].image.url` | Downloaded, uploaded to NC, shared inline |
|
|
| `embeds[].thumbnail.url` | Downloaded, uploaded to NC, shared inline |
|
|
| `embeds[].fields[].name` + `value` | Formatted as `name: value` lines |
|
|
| `username` | Sender display name (prepended to message) |
|
|
| `avatar_url` | Ignored (NCTalk doesn't support per-message avatars) |
|
|
| `subject` / `title` (Apprise) | Used as bold title line |
|
|
| `body` (Apprise) | Sent as message body |
|
|
| `attachments[].path` (Apprise) | Downloaded, uploaded to NC, shared inline |
|
|
| `type` (Apprise) | Maps to icon: ✅ success, ⚠️ warning, ❌ error, none for info/image |
|
|
|
|
### Sender name resolution
|
|
|
|
When posting to Talk, the app prepends a bold sender name line to the message (since Talk doesn't support per-message avatars). The sender name is resolved in this order:
|
|
|
|
1. `username` field from Discord payload
|
|
2. `subject` / `title` from Apprise payload
|
|
3. Configured default sender name (Settings → Default Sender Name)
|
|
|
|
---
|
|
|
|
## Image Management
|
|
|
|
- Images from webhooks are downloaded via HTTP and uploaded to the bot user's files
|
|
- Stored at `/nc_bot_webhooks-images/<room-token>/` under the bot user's personal storage
|
|
- A public link share is created for each image so Talk can resolve the rich object and display the inline attachment
|
|
- **Cron job** (`ImageCleanup`) purges images older than the configured retention period (default: 90 days)
|
|
- Images count toward the bot user's storage quota
|
|
- Purge operates on the bot user's personal storage directory only — it does not scan other users' files
|
|
|
|
---
|
|
|
|
## Security
|
|
|
|
| Mechanism | Description |
|
|
|---|---|
|
|
| **Auth tokens** | Each webhook URL contains a unique secret token; the endpoint validates it before processing |
|
|
| **Bot password** | Encrypted at rest using Nextcloud's crypto layer (`ICrypto`) |
|
|
| **No CSRF** | Webhook endpoints are marked `#[PublicPage]` + `#[NoCSRFRequired]` — auth token is the sole access control |
|
|
| **Local address blocking** | Image downloads use Nextcloud's HTTP client with `allow_local_address: true` (blocks private ranges by default) |
|
|
| **Path traversal protection** | Uploaded filenames use `basename()` to prevent directory traversal |
|
|
| **Rate limiting** | Not built in — handle at the web server or reverse proxy level |
|
|
|
|
### Known limitations
|
|
|
|
- Auth tokens generated from the settings UI use client-side generation; for higher security, regenerate them via the server API
|
|
- The webhook endpoint has no rate limiting — consider placing it behind a reverse proxy rate limiter if exposing to untrusted sources
|
|
|
|
---
|
|
|
|
## Debug Endpoint
|
|
|
|
The `/apps/nc_bot_webhooks/debug` endpoint exposes internal configuration, database schema, and bot credentials. It is **disabled by default**.
|
|
|
|
```bash
|
|
# Check status
|
|
php occ nc_bot_webhooks:debug:status
|
|
|
|
# Enable (WARNING: exposes sensitive data)
|
|
php occ nc_bot_webhooks:debug:enable
|
|
|
|
# Disable (default)
|
|
php occ nc_bot_webhooks:debug:disable
|
|
|
|
# Toggle current state
|
|
php occ nc_bot_webhooks:debug:toggle
|
|
```
|
|
|
|
After troubleshooting, disable it immediately:
|
|
|
|
```bash
|
|
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
|
|
|
|
Responses include a `X-Webhook-Status` header:
|
|
|
|
| Header value | Meaning |
|
|
|---|---|
|
|
| `ok` | Forwarded successfully |
|
|
| `unauthorized` | Invalid auth token |
|
|
| `bad_request` | Invalid JSON payload |
|
|
| `no_content` | No message content in payload |
|
|
| `error` | Check server logs for details |
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
| Problem | Solution |
|
|
|---|---|
|
|
| **"talk-bot user not found"** | The `talk-bot` user doesn't exist. Re-run Step 2 of installation. |
|
|
| **"Bot password not configured"** | You haven't entered the bot password in admin settings, or it was cleared. Re-enter it. |
|
|
| **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 `nc_bot_webhooks-images` folder can be created. |
|
|
| **Apprise 500 error** | Likely config data not migrated from the old app ID. Re-enter settings or run: `UPDATE oc_appconfig SET appid = 'nc_bot_webhooks' WHERE appid = 'ncdiscordhook';` |
|
|
| **Bot not listed in room participants** | The `ensureBotParticipants()` method runs automatically on save, but you may need to re-check the room in admin settings to trigger it. |
|