Skip to main content

Discord bot

The Discord bot lets you ingest images from Discord channels into Pindeck using emoji reactions, with a built-in moderation queue.

Overview

The bot and media gateway are deployed from a separate repository (discord-bot). The Pindeck app consumes their services via Convex HTTP actions.

Setup

1. Create a Discord application

  1. Go to the Discord Developer Portal
  2. Create a new application and bot
  3. Note the Client ID and Bot Token
  4. Enable the Message Content Intent in the bot settings

2. Invite the bot to your server

Use the OAuth2 URL generator with the bot scope and permissions:
  • Read Messages
  • Read Message History
  • Add Reactions
  • Manage Messages (for moderation)

3. Configure environment variables

Set these in the Discord bot’s .env.local:
VariableDescription
DISCORD_TOKENBot token from the Developer Portal
DISCORD_CLIENT_IDApplication client ID
DISCORD_GUILD_IDServer ID where the bot operates
DISCORD_INGEST_EMOJISEmoji triggers for image ingest (e.g., :pushpin:)
INGEST_API_KEYAPI key matching Convex’s INGEST_API_KEY
PINDECK_INGEST_URLOptional override for ingest endpoint URL
PINDECK_DISCORD_QUEUE_URLOptional override for queue endpoint URL
PINDECK_DISCORD_MODERATION_URLOptional override for moderation endpoint URL
MEDIA_GATEWAY_URLRustFS-backed media API URL
MEDIA_GATEWAY_TOKENBearer token for media API writes
MEDIA_GATEWAY_BUCKETRustFS bucket, normally pindeck

4. Run the bot

cd ~/Documents/Github/discord-bot
bun install
bun run dev

How ingest works

  1. A user adds a configured emoji reaction to a message with an image attachment
  2. The bot sends the image to Pindeck’s /ingestExternal HTTP endpoint
  3. Pindeck stores the image in RustFS, including preview/derivative URLs and five sampled colors
  4. Pindeck creates a record with sourceType = "discord"
  5. The image appears in the moderation queue

Moderation queue

New Discord-sourced images enter the moderation queue:
  1. Images land in a pending state via the /discordQueue endpoint
  2. Moderators review and approve or reject via the /discordModerate endpoint
  3. Approved images move into the same Review & Finalize draft lane as local uploads
  4. Draft Discord images use the same sampled colors, colored tags, metadata fields, and variation controls as local uploads
  5. Rejected images are removed
Approved status webhook messages also trigger the Discord bot to post the six variation buttons when DISCORD_APPROVED_VARIATION_BUTTONS is enabled: Shot, Action, Coverage, B-Roll, Style, and Subtle.

Hosting

The Discord bot runs on a Hostinger VPS:
  • Hostname: srv1353991
  • Public IP: 187.77.8.227
  • Tailscale IP: 100.105.199.93
  • User: root
Connect via SSH:
ssh root@187.77.8.227
Tailscale SSH can still be used as a fallback operator path, but the normal deploy workflow now uses direct SSH to the public IP.
Do not treat services/discord-bot in the Pindeck repo as the deployment source. Always use the separate discord-bot repository.

API endpoints

EndpointMethodDescription
/ingestExternalPOSTAccept an external image for ingest
/discordQueuePOSTAdd an image to the moderation queue
/discordModeratePOSTApprove or reject a queued image
See the API reference for full endpoint documentation.

Hostinger DNS note

The Hostinger bot container runs on the same public host that serves the Convex HTTP domains. If the container resolves convex-site.serving.cloud or convex.serving.cloud back to 127.0.1.1, Bun fetches fail with connection errors. The deployed Compose file pins those names to the Docker host gateway (172.18.0.1) using extra_hosts.