No description
  • Python 99.2%
  • Dockerfile 0.8%
Find a file
Ben Trinh bdb2bcdb97 fix: fix webhook handler robustness
- Use request.json(content_type=None) to avoid ContentTypeError when
  Karakeep doesn't send an explicit application/json content type header
- Wrap Discord API calls in try/except in all three webhook handlers so
  Discord errors are logged and return 500 instead of crashing silently
- Return 200 "skipped" (not 400) when bookmark has no lists or no mapped
  channel — prevents Karakeep from treating non-shared-list bookmarks as
  webhook failures and retrying them indefinitely

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-14 17:26:39 +10:00
.env.example docs: update .env.example with all environment variables 2026-03-29 12:35:23 +11:00
.gitignore feat: add Discord webhook sync service for Karakeep bookmarks 2026-03-24 22:25:00 +11:00
docker-compose.yaml docs: update .env.example with all environment variables 2026-03-29 12:35:23 +11:00
Dockerfile feat: add Discord webhook sync service for Karakeep bookmarks 2026-03-24 22:25:00 +11:00
LICENSE Initial commit 2026-03-23 19:08:22 +11:00
pyproject.toml feat: add Karakeep list icons to Discord channel names 2026-03-29 12:28:07 +11:00
README.md docs: update README with accurate information 2026-03-29 12:38:10 +11:00
sync.py fix: fix webhook handler robustness 2026-09-14 17:26:39 +10:00
uv.lock feat: add Karakeep list icons to Discord channel names 2026-03-29 12:28:07 +11:00

Karakeep Discord Sync

Sync Karakeep bookmarks to Discord forum channels with list icons.

Overview

This service listens for Karakeep webhooks and automatically posts bookmarks to corresponding Discord forum channels:

  • crawled: When a bookmark is crawled, post it to the Discord channel mapped to its list
  • ai_tagged: When AI tagging completes, update the Discord message with new tags
  • edited: When a bookmark is edited, update the existing Discord message

Each Karakeep list gets its own Discord forum channel with the list's icon in the channel name.

Prerequisites

  • Docker & Docker Compose
  • A Karakeep instance (self-hosted or try.karakeep.app)
  • A Discord server where you have permission to create channels

Setup

1. Discord Bot Setup

  1. Go to Discord Developer Portal
  2. Click "New Application" and give it a name
  3. Go to "Bot" → click "Reset Token" and copy it
  4. Under "Privileged Gateway Intents", enable Message Content Intent
  5. Copy your Application ID from "General Information"
  6. Generate an invite URL:
https://discord.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&permissions=110080&scope=bot

Replace YOUR_CLIENT_ID with your Application ID.

  1. Visit the URL to invite the bot to your server
  2. Copy your Guild ID (Server ID):
    • Enable Developer Mode in Discord (Settings → Advanced → Developer Mode)
    • Right-click your server name → "Copy ID"

2. Karakeep Setup

  1. Log in to your Karakeep instance
  2. Go to Settings → API Keys
  3. Click "Create API Key" and copy it

3. Environment Configuration

cp .env.example .env

Edit .env with your values:

KARAKEEP_API_KEY=your-karakeep-api-key
KARAKEEP_SERVER_ADDR=http://web:3000

DISCORD_BOT_TOKEN=your-discord-bot-token
DISCORD_GUILD_ID=123456789012345678

WEBHOOK_TOKEN=your-random-secret-token

4. Configure Karakeep Webhooks

In your Karakeep UI:

  1. Go to Settings → Webhooks (or use the API)
  2. Create a webhook with:
    • URL: http://webhook:8080/webhook
    • Events: crawled, ai_tagged
  3. Note: You'll need to set WEBHOOK_TOKEN on your Karakeep server for authentication

5. Build & Run

docker compose up -d --build

6. Verify

  • Check logs: docker compose logs -f webhook
  • The bot should create channels for each Karakeep list
  • When bookmarks are crawled, they'll appear in the corresponding channel

Configuration

Config Options

Variable Description Default
KARAKEEP_API_KEY Karakeep API key (required)
KARAKEEP_SERVER_ADDR Karakeep server URL http://web:3000
DISCORD_BOT_TOKEN Discord bot token (required)
DISCORD_GUILD_ID Discord server ID (required)
WEBHOOK_HOST Webhook server host 0.0.0.0
WEBHOOK_PORT Webhook server port 8080
WEBHOOK_TOKEN Secret token for webhook auth (optional)
DATABASE_PATH SQLite database path data.db

Karakeep Server Configuration

If self-hosting Karakeep, add these to your Karakeep .env:

WORKERS_ENABLED_WORKERS=crawler,inference,webhook
WEBHOOK_TOKEN=your-random-secret-token

Project Structure

├── docker-compose.yaml  # Docker services
├── Dockerfile           # Webhook service image
├── sync.py              # Main sync script
├── data.db              # SQLite database (auto-generated)
└── .env                 # Environment variables

Development

# Install dependencies
uv sync

# Run locally
python sync.py

# Build image
docker build -t karakeep-discord-webhook .