3f51a8ca483d4261b1772e3fafd6544b8b0b4390
- Inject LoggerInterface across WebhookController, TalkService, and ImageCleanup - Replace TalkService.getAvailableTalkRooms() OCS API calls with direct database queries - Add getBaseUrl() helper to resolve localhost/SSRF constraints for internal API calls - Update buildRichObject() to generate public link shares for file attachments - Add saveBotPassword, debug, and debugTables endpoints to WebhookController - Separate frontend assets (JS/CSS) from adminSettings template - Add composer.json and autoload files for PSR-4 autoloading - Update Admin settings to use TemplateResponse and register app icons
NCdiscordhook
Discord webhook bridge for Nextcloud Talk with image attachment support.
Accepts Discord webhook-style JSON payloads and posts them into Nextcloud Talk rooms, preserving images and embed formatting.
Installation
1. Deploy the app
cd /path/to/nextcloud/apps
cp -r /path/to/ncdiscordhook .
php occ app:enable ncdiscordhook
2. Create the bot user
php occ user:add --password-from-env --display-name="Webhook Bot" talk-bot
3. Generate an app password for the bot
- Log in as
talk-bot(or set a password as admin) - Go to Settings → Security → Devices & sessions → Add device
- Copy the app password
4. Configure the app
Go to Settings → Admin → NCdiscordhook:
- Bot Configuration — paste the app password from step 3
- Image Retention — set how long to keep uploaded images (default: 90 days)
- Room Management — click "Fetch Rooms" to see available Talk rooms, select the ones you want, and generate auth tokens
5. Point your services at the webhook URLs
Each configured room gets a webhook URL:
https://your-server.com/apps/ncdiscordhook/webhook/<room-token>/<auth-token>
Copy the auth token from the app settings for each room.
API
Accepts (Discord webhook format)
{
"content": "Build #1234 passed",
"embeds": [
{
"title": "Deployment",
"description": "Successfully deployed to production",
"color": 3066993,
"image": { "url": "https://example.com/screenshot.png" },
"fields": [
{ "name": "Duration", "value": "2m 34s" },
{ "name": "Environment", "value": "Production" }
]
}
],
"username": "CI/CD",
"avatar_url": "https://example.com/icon.png"
}
Sends to Nextcloud Talk
- Formatted text message (content + embeds + fields)
- Each image from
embeds[].imageorembeds[].thumbnailuploaded and shared inline usernameshown as the sender display name
Payload mapping
| Discord field | Nextcloud 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 |
Formatted as name: value lines |
username |
Sender display name |
avatar_url |
Ignored (NCTalk doesn't support per-message avatars) |
Room routing
Each room gets its own webhook URL with a unique auth token:
/webhook/<room-token>/<auth-token>
- Room token — identifies which Talk room to post to (from
occ talk:room:list) - Auth token — secret key for this webhook endpoint (generated in app settings)
Multiple auth tokens can be created per room — useful if you need to rotate keys or share the webhook across multiple services.
Image management
- Images are uploaded to the bot user's files at
/NCdiscordhook-images/<room-token>/ - Cron job purges images older than the configured retention period (default: 90 days)
- Images are stored in the bot user's storage — they count toward the bot user's quota
Security
- Auth token in the URL is the primary auth mechanism — keep it secret
- Bot password is encrypted at rest using Nextcloud's crypto
- Image download uses Nextcloud's HTTP client with local address blocking
- Rate limiting should be handled at the web server or reverse proxy level
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 |