Only 1 image share shows up now - Replace ParticipantSession with TalkSession and update constructor - Inject IUserSession to manage user context - Refactor setSessionOverwrite and clearSessionOverwrite to use reflection - Update share creation to switch context to talk-bot and support node-based sharing - Enhance error logging in share creation
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
- Manual Deployment
- Configuration
- Webhook URLs
- Payload Formats
- Payload Mapping
- Image Management
- Security
- Debug Endpoint
- Logging
- Troubleshooting
Installation
1. Deploy the app
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
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:
- Go to Settings → Users
- Find talk-bot and click it
- Check Admin under "Settings"
- Save
4. Generate an app password for the bot
- Log in to Nextcloud as admin (or set a password as admin, then log in as talk-bot)
- Go to Settings → talk-bot → Devices & sessions
- Click Add device and give it a name (e.g., "NCbotwebhooks")
- Copy the generated device password — you'll need it in the next step
5. Configure the app
Go to Settings → Admin → NCbotwebhooks:
- Bot App Password — paste the app password from step 4
- Default Sender Name — set the name that appears as the message sender (default: "Webhook Bot")
- Image Retention — set how many days to keep uploaded images (default: 90)
- Room Selection — click Fetch Rooms to list available Talk rooms
- Check the rooms you want to accept webhooks for
- For each room, click + Generate Auth Token to create a webhook URL
- 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
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 adjustTrueNAS 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
notifysegment is required — Apprise'sapprises://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
{
"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:
{
"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 |
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:
usernamefield from Discord payloadsubject/titlefrom Apprise payload- 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.
# 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:
php occ nc_bot_webhooks:debug:disable
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. |