socketmode

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 10 Imported by: 0

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 New

func New(openURL func(ctx context.Context) (string, error), logW io.Writer) *Client

New builds a Client over an OpenURL func.

func (*Client) Run

func (c *Client) Run(ctx context.Context, handler func(Envelope)) error

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/…).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL