Documentation
¶
Overview ¶
Package socketmode is a hand-written Slack Socket Mode client (no Slack SDK): it fetches a fresh wss URL from apps.connections.open (app-level xapp token), reads envelopes, acknowledges each within Slack's 3-second window BEFORE handing it to the caller, and reconnects on disconnect frames and socket errors. See DECISIONS.md ("listen").
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ParseEvent ¶
func ParseEvent(env Envelope) (json.RawMessage, slackevent.Meta, error)
ParseEvent extracts the inner event and its filter metadata from an events_api envelope. The metadata type is shared with the RTM transport (internal/slackevent).
Types ¶
type Client ¶
type Client struct {
// OpenURL fetches a fresh wss:// URL (apps.connections.open). Slack's URLs are
// single-use tickets, so every (re)connection asks for a new one.
OpenURL func(ctx context.Context) (string, error)
// Dial opens the websocket. Defaults to coder/websocket; injectable for tests.
Dial func(ctx context.Context, url string) (conn, error)
// Log receives connection-lifecycle notes (connected, reconnecting). Never event data.
Log io.Writer
// DebugReconnects appends debug_reconnects=true so Slack rotates the connection every
// ~360s — for exercising the reconnect path.
DebugReconnects bool
// ReadTimeout bounds how long a single frame read may block. Slack pings a healthy
// connection well within this window, so a read that stalls past it means the connection
// went half-open (server gone, no FIN) — the client reconnects instead of hanging forever.
// Zero uses the default (90s); negative disables the deadline (tests).
ReadTimeout time.Duration
// contains filtered or unexported fields
}
Client streams Socket Mode envelopes.
func (*Client) Run ¶
Run connects and streams work envelopes to handler until ctx is cancelled. Every envelope with an envelope_id is acked BEFORE handler runs — Slack redelivers anything not acked within ~3s, and a slow downstream pipe must not cause duplicate delivery (DECISIONS.md). Reconnects (disconnect frame, socket error, expired URL) fetch a fresh URL with full-jitter backoff; the backoff resets after each successful hello.
type Envelope ¶
type Envelope struct {
EnvelopeID string `json:"envelope_id,omitempty"`
Type string `json:"type"`
Reason string `json:"reason,omitempty"` // disconnect frames
Payload json.RawMessage `json:"payload,omitempty"`
AcceptsResponsePayload bool `json:"accepts_response_payload,omitempty"`
RetryAttempt int `json:"retry_attempt,omitempty"`
RetryReason string `json:"retry_reason,omitempty"`
NumConnections int `json:"num_connections,omitempty"` // hello frames
}
Envelope is one Socket Mode frame. hello/disconnect are connection-lifecycle frames; events_api/slash_commands/interactive carry work items that must be acked.
type EventsAPIPayload ¶
type EventsAPIPayload struct {
TeamID string `json:"team_id"`
Type string `json:"type"` // "event_callback"
EventID string `json:"event_id"`
Event json.RawMessage `json:"event"`
}
EventsAPIPayload is the standard Events API callback wrapper inside an events_api envelope; Event is the actual event object (type message/reaction_added/…).