The Discord bot is hosted separately from Pindeck. It lives in its own repository and calls Pindeck’s Convex HTTP endpoints over the network. You deploy and run the bot independently — Pindeck does not run it for you.
How it works
Trigger an import
React to any Discord message that contains an image with your configured ingest emoji, or run
/images import with an optional message link. The bot extracts image URLs, parses post metadata (title, description, source URL, sref style reference), and sends a POST /ingestExternal request to your Convex backend.Image lands as pending
The image is created in Pindeck with
status: pending. No AI analysis runs yet. Pindeck posts a Waiting Approval status notification to your Discord webhook channel (if DISCORD_STATUS_WEBHOOK_URL is set).Review the queue
Run
/images review in Discord. The bot fetches up to 5 pending items via POST /discordQueue and posts each one as an embed with Approve, Deny, and Generate buttons.Moderate
Click a button or run
/images approve, /images reject, or /images generate directly. The bot calls POST /discordModerate with the chosen action.- Approve — triggers AI analysis (VLM metadata extraction), then variation generation if a count was requested.
- Deny — deletes the image record.
- Generate — skips straight to variation generation using the default count and mode.
Ingestion methods
Emoji reaction
React to any message containing an image with one of the emojis configured inDISCORD_INGEST_EMOJIS. The bot immediately imports the image into the moderation queue.
Slash command
Run/images import in any channel the bot can read. If you omit the message_link option, the bot scans the last 50 messages for the most recent one containing an image. Pass a full Discord message URL to import from a specific message.
Moderation queue
Pending images appear in the Boards/queue view in Pindeck and can also be reviewed from Discord using/images review. Each queue card shows the image preview, title, description, image ID, status, and parsed sref value.
| Action | Effect |
|---|---|
| Approve | Sends image to AI analysis; variations generated if count > 0 |
| Deny | Permanently deletes the image record |
| Generate | Triggers variation generation directly, bypassing analysis |
Variation generation from Discord
The/images generate command and the Generate button both call POST /discordModerate with action: generate. You can specify:
count— number of variations (1–12; defaults toDISCORD_GENERATE_DEFAULT_COUNT)mode— variation mode:shot-variation,action-shot,coverage,b-roll,style-variation,subtle-variationdetail— optional custom direction passed to the generation prompt
Status webhooks
SetDISCORD_STATUS_WEBHOOK_URL in Convex Project Settings to receive status notifications in a Discord channel. Pindeck posts a message for each of the following events:
| Event | Label |
|---|---|
queued | Waiting Approval |
approved | Approved |
rejected | Rejected |
generation_started | Generating Variations |
generated | Variation Queued |
queued and generated notification also includes quick-action commands (/images approve image_id:...) for convenience.
RSS and metadata parsing
When a message is ingested, the bot parses the message content and embeds to extract:- Title — from embed title, or first non-empty line of message content
- Description — message content and/or embed description
- Source URL — embed URL or the first non-image, non-Discord URL in the message
sref— style reference number matched against patterns likesref 12345,sref:12345, or#sref12345
sref values are stored on the image record and added as a sref:<number> tag.
Lineage tracking
Variations triggered from Discord are created with aparentImageId reference pointing to the source image, building a traceable generation chain. The lineage depth is capped at 12 levels to prevent runaway chains.
HTTP endpoints
The bot calls these Convex HTTP endpoints. All requests useBearer <INGEST_API_KEY> authorization.
| Endpoint | Method | Purpose |
|---|---|---|
/ingestExternal | POST | Ingest an image URL into the moderation queue |
/discordQueue | POST | Fetch pending items for review |
/discordModerate | POST | Approve, reject, or generate for an image |
Environment variables
These variables are set in the Discord bot’s.env.local file (not in Convex Project Settings).
| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN | Yes | Bot token from the Discord Developer Portal |
DISCORD_CLIENT_ID | Recommended | Application ID; auto-derived from token if omitted |
DISCORD_GUILD_ID | Recommended | Guild ID for fast slash command registration |
DISCORD_INGEST_EMOJIS | Yes | Comma-separated emoji triggers for ingest (e.g. 📥) |
INGEST_API_KEY | Yes | Must match the INGEST_API_KEY set in Convex Project Settings |
PINDECK_INGEST_URL | Recommended | Full URL to https://<deployment>.convex.site/ingestExternal |
PINDECK_DISCORD_QUEUE_URL | Optional | Defaults to /discordQueue on the same Convex site URL |
PINDECK_DISCORD_MODERATION_URL | Optional | Defaults to /discordModerate on the same Convex site URL |
PINDECK_USER_ID | Yes | Convex user ID that imported images are assigned to |
NEXTCLOUD_PUBLIC_SHARE_TOKEN | Optional | For serving images via NextCloud shared folder |
.env):
| Variable | Description |
|---|---|
INGEST_API_KEY | Shared secret that the bot sends as a Bearer token |
DISCORD_STATUS_WEBHOOK_URL | Discord webhook URL for status notifications |
Bot permissions
When inviting the bot to your server via the Discord Developer Portal OAuth2 URL generator, select these scopes and permissions: Scopes:bot, applications.commands
Bot permissions: View Channels, Send Messages, Embed Links, Read Message History, Add Reactions, Use Application Commands