Raxol.Gateway.Adapter.Discord (RaxolGateway v0.2.0)

Copy Markdown View Source

Raxol.Gateway.Adapter implementation for Discord.

Owns only platform I/O and translation: MESSAGE_CREATE dispatches normalize to the gateway's %{text: binary} event shape (what a text handler consumes), and rendered replies go out as plain-text POST /channels/:id/messages REST calls.

Deliberately out of scope here:

Connection

connect/1 requires :bot_token and accepts :api_base (default https://discord.com/api/v10), :timeout, and :post_fn (a 2-arity (url, req_opts) -> {:ok, %{status:, body:}} | {:error, term} override for tests or alternative HTTP clients, the same shape Raxol.Telegram.HTTP uses; the default uses the optional Req dependency). The connection is stateless HTTP; the returned handle is the validated option list.

Inbound

Frames authored by bots (including this one) are ignored, so an agent can never be goaded into a bot-to-bot reply loop. Messages with a guild_id route as chat_type: :guild, the rest as :dm; chat_id is the channel id either way, which is exactly where the reply goes.

Outbound

Replies are chunked against Discord's 2000-character message limit, which counts Unicode code points - not UTF-16 units (Telegram) and not graphemes. Chunking is grapheme-safe. Empty or whitespace-only replies are a no-op. Failures emit [:raxol_gateway, :discord_adapter, :error] telemetry with the classified reason; the bot token travels in an Authorization header and is never part of a URL or log line.