kyle aa06394aa9 feat: enhance webhook settings UI and security: Mostly working, just final post not functioning
- Add CSS styles for token URL input and hints
- Implement safe data attribute parsing in settings.js
- Refactor room fetching logic to use promise chains and auto-fetch on load
- Display full webhook URLs in the settings UI instead of raw tokens
- Generate URL-safe base64 tokens to prevent encoding issues
- Add #[PublicPage] attribute to WebhookController for unauthenticated delivery
- Filter out internal Nextcloud Talk system rooms from the room picker
- Add OCS-ApiRequest header to bot API requests
- Sanitize data attributes in templates to prevent XSS
2026-06-11 10:55:30 -07:00
2026-06-11 10:21:23 -07:00
2026-06-11 10:21:23 -07:00
2026-06-10 14:18:47 -07:00
2026-06-11 10:21:23 -07:00
2026-06-10 14:18:47 -07:00

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

  1. Log in as talk-bot (or set a password as admin)
  2. Go to Settings → Security → Devices & sessions → Add device
  3. Copy the app password

4. Configure the app

Go to Settings → Admin → NCdiscordhook:

  1. Bot Configuration — paste the app password from step 3
  2. Image Retention — set how long to keep uploaded images (default: 90 days)
  3. 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[].image or embeds[].thumbnail uploaded and shared inline
  • username shown 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
S
Description
Nextcloud bot using Discord/Apprise like web hook
Readme AGPL-3.0
1.1 MiB
1.2.1
Latest
2026-06-16 14:03:34 -07:00
Languages
PHP 89.6%
JavaScript 9%
CSS 1.4%