arizukocomponents › discd

discd

What it is

discd is the Discord channel adapter. It opens a Discord gateway websocket (via discordgo), posts inbound messages and reactions to gated, and sends outbound via the Discord REST API. JID prefix is discord:; messages are keyed by discord:<channel_id> for direct/guild chats and discord:<guild>/<channel> for the routing layer.

Why it exists

Discord is the canonical community channel for arizuko deployments — guild channels for team chat, threads for tasks, DMs for one-on-one. Talking to the Discord gateway directly is what lets discd surface reactions as like / dislike events and keep the websocket alive across rolling restarts.

How it fits

Discord (gateway.discord.gg)
        |  websocket: MESSAGE_CREATE, MESSAGE_REACTION_ADD, ...
        v
      discd     (LISTEN_ADDR=:8080)
        |  POST /v1/messages    (signed by CHANNEL_SECRET)
        v
      gated
        |  POST /v1/send         (callback to discd)
        v
      discd     (REST: channels/.../messages, reactions, ...)
        |
        v
      Discord

Wired verbs (discd/bot.go, discd/server.go): send (chunked at 2000 chars, honours reply_to via message_reference), send_file (multipart), typing, edit, delete, like (default 👍), quote. dislike, forward, post, repost are 501-with-hint — the agent gets pointers like like(emoji='👎') rather than a generic capability error.

Inbound: messages where the bot is in m.Mentions or is the parent author of a reply ride verb=mention; everything else in guilds is verb=message (v0.39.1 made reply-to-bot and reactions count as mentions). Reactions MessageReactionAdd emit synthetic like/dislike inbound rows classified by chanlib.ClassifyEmoji.

Attachments use direct Discord CDN URLs cached via the shared chanlib.URLCache.

Standalone usage

discd is a plain Go binary. It needs a reachable gated and a Discord bot or user token.

export ROUTER_URL=http://gated:8080
export CHANNEL_SECRET=$(grep ^CHANNEL_SECRET .env | cut -d= -f2)
export LISTEN_ADDR=:8080
export DISCORD_BOT_TOKEN=...
export ASSISTANT_NAME=arizuko
./discd

Discord-side setup: create an application at discord.com/developers, add a bot, copy the token. Required gateway intents: GUILDS, GUILD_MESSAGES, GUILD_MESSAGE_REACTIONS, MESSAGE_CONTENT, DIRECT_MESSAGES. Invite the bot with the OAuth URL.

User mode (DISCORD_USER_TOKEN instead of bot token) authenticates as a Discord user account — useful where a bot account is not allowed. It skips gateway intents, which user tokens cannot request.

GET /health returns 503 when the websocket is disconnected; discordgo reconnects automatically, so a persistent 503 means token revoked or Discord-side outage.

Go deeper