Documentation
¶
Overview ¶
Package wavvon is the Go SDK for programs (bots and apps) that talk to a Wavvon hub: login that renews itself, the generated REST client, capability checks, keyset paging, the WebSocket event stream with resume, app registration, and verification of slash-command dispatches and outgoing webhooks. The design is sdk.md (tier 1) in Wavvon-docs.
Index ¶
- Constants
- Variables
- func AuthChallengeSigningBytes(challenge []byte, scheme *string) ([]byte, error)
- func Check[R interface{ ... }](res R, err error) (R, error)
- func DecodeWebhookSecret(shown string) ([]byte, error)
- func DoWithRetry(ctx context.Context, opts RetryOptions, ...) (*http.Response, error)
- func IsTransientStatus(status int) bool
- func OutgoingWebhookSigningKey(rawSecret []byte) []byte
- func Paginate[T any](ctx context.Context, ...) iter.Seq2[T, error]
- func WebhookDeliverySigningBytes(timestamp uint64, body []byte) []byte
- type AppClose
- type AppCommand
- type AppComponent
- type AppLaunch
- type AppOpen
- type AppProfile
- type AppResponse
- type AppSubscription
- type AuthOptions
- type AuthSchemeError
- type AuthorInfo
- type Client
- func (c *Client) AckEvents(ctx context.Context, ids []string) error
- func (c *Client) CanonicalPubkey() string
- func (c *Client) Connect(opts EventStreamOptions) *EventStream
- func (c *Client) HasCapability(ctx context.Context, name string) (bool, error)
- func (c *Client) Info(ctx context.Context, refresh bool) (*rest.HubInfo, error)
- func (c *Client) Login(ctx context.Context) (Session, error)
- func (c *Client) OnStateChange(fn func(SessionState)) (unsubscribe func())
- func (c *Client) PollEvents(ctx context.Context, since int64) ([]PolledEvent, error)
- func (c *Client) RequireCapability(ctx context.Context, name string) error
- func (c *Client) SetAppCommands(ctx context.Context, commands []AppCommand) error
- func (c *Client) SetAppProfile(ctx context.Context, profile AppProfile) error
- func (c *Client) SetAppSubscriptions(ctx context.Context, subscriptions []AppSubscription) error
- func (c *Client) State() SessionState
- type ClientOptions
- type ComponentInteraction
- type ComponentResponse
- type ComponentRow
- type ComponentUpdate
- type ConnectionState
- type DMEvent
- type Dispatch
- type DispatchHandler
- type Embed
- type EmbedField
- type EmbedFooter
- type EphemeralReply
- type ErrorEvent
- type Event
- type EventStream
- func (s *EventStream) AnnounceApp(ctx context.Context, channelID, title, description string) error
- func (s *EventStream) Close()
- func (s *EventStream) DismissApp(ctx context.Context, channelID string) error
- func (s *EventStream) LastSeq() (seq int64, ok bool)
- func (s *EventStream) Next(ctx context.Context) (Event, error)
- func (s *EventStream) OnStateChange(fn func(ConnectionState)) (unsubscribe func())
- func (s *EventStream) Send(ctx context.Context, frame any) error
- func (s *EventStream) SendMiniAppMessage(ctx context.Context, appID, channelID, toPubkey, payload string) error
- func (s *EventStream) State() ConnectionState
- func (s *EventStream) Subscribe(ctx context.Context, channelID string) error
- type EventStreamOptions
- type GameLaunchCard
- type Hello
- type HubError
- type HubEvent
- type HubUnavailableError
- type Identity
- type MessageEvent
- type MessageRefEvent
- type MiniAppMessage
- type OutgoingWebhookEvent
- type PolledEvent
- type Pong
- type Reaction
- type ReactionsUpdated
- type ReplayComplete
- type ReplayUnavailable
- type Reply
- type RetryInfo
- type RetryOptions
- type SelectOption
- type Session
- type SessionState
- type SlashInvocation
- type TypingEvent
- type UnknownDispatch
- type UnknownEvent
- type UnsupportedByHubError
- type VerifyOptions
- type WebhookVerificationError
Constants ¶
const AuthChallengeLen = 32
AuthChallengeLen is the only length a raw (untagged) challenge is signed at.
const AuthChallengeScheme = "tagged-v1"
AuthChallengeScheme is the only named challenge scheme this SDK signs.
const MaxPageSize = 500
MaxPageSize is what the hub clamps limit to; asking for more would look like a short page and end the walk early.
const Version = "0.1.0"
Version is this SDK's release. release.yml tags v<Version> when it reaches main, and the Go module proxy serves the module at that tag.
Variables ¶
var ErrCursorIgnored = errors.New("wavvon: the hub returned the same page twice: it does not honour the cursor on this endpoint")
ErrCursorIgnored is returned by Paginate when the hub serves the same page twice: the endpoint does not honour the cursor, and looping would never end.
var ErrStreamClosed = errors.New("wavvon: event stream closed")
ErrStreamClosed is returned by EventStream.Next and Send after Close.
var ErrUnsupportedByHub = errors.New("wavvon: unsupported by this hub")
ErrUnsupportedByHub matches, via errors.Is, every UnsupportedByHubError.
Functions ¶
func AuthChallengeSigningBytes ¶
AuthChallengeSigningBytes returns what a client signs to answer a challenge (wire-format.md, "Auth challenge answer"). scheme is nil when the hub's response has no scheme field. "tagged-v1" is the domain tag plus the challenge. No scheme (an older hub) is the raw challenge, and only at exactly 32 bytes, so this can never sign arbitrary bytes. Any other scheme, the empty string included, is refused rather than guessed at.
func Check ¶
Check passes a generated REST call's result through, turning a non-2xx answer into *HubError carrying the hub's own words:
res, err := wavvon.Check(client.Rest.ListChannelsWithResponse(ctx))
func DecodeWebhookSecret ¶
DecodeWebhookSecret decodes an outgoing-webhook secret as the admin was shown it (base64url, no padding) into its raw bytes.
func DoWithRetry ¶
func DoWithRetry(ctx context.Context, opts RetryOptions, attempt func(context.Context) (*http.Response, error)) (*http.Response, error)
DoWithRetry runs attempt until it yields a response that is not transient. The hub sends no Retry-After, so the wait is capped exponential backoff with jitter. When the budget runs out it returns *HubUnavailableError rather than the last 429/5xx: a transient failure is never an answer.
Each attempt gets its own timeout context, which stays alive until the returned body is closed. attempt may make several requests (login does) and return whichever response decides the outcome.
func IsTransientStatus ¶
IsTransientStatus reports whether a status means "not now": 429, or a 5xx from the hub or a proxy in front of it.
func OutgoingWebhookSigningKey ¶
OutgoingWebhookSigningKey derives the HMAC key from the secret's raw bytes: HKDF-SHA256, salt "wavvon-webhook-signing", empty info, 32 bytes. The HMAC is keyed with these bytes, not their hex.
func Paginate ¶
func Paginate[T any](ctx context.Context, fetchPage func(ctx context.Context, cursor string, limit int) ([]T, error), key func(T) string, limit int) iter.Seq2[T, error]
Paginate walks a keyset-paged list to exhaustion. The hub's dialect is a bare array plus limit and cursor, where the cursor is the key of the previous page's last row (code for invites, public_key for users, id for most others), so key extracts it. A page shorter than limit is the end; one page is not the list.
fetchPage makes the request (cursor is "" for the first page) and must return an error on failure: an error never reads as an empty page, and it is yielded as the last pair. Check the endpoint's capability (list.cursor or list.cursor.lists) first; a hub without it ignores the cursor, which this detects and reports as ErrCursorIgnored rather than looping.
func WebhookDeliverySigningBytes ¶
WebhookDeliverySigningBytes is "wavvon/webhook-delivery/v1\0" || u64le(timestamp) || body.
Types ¶
type AppCommand ¶
type AppCommand struct {
Name string `json:"name"`
Description string `json:"description"`
Args string `json:"args,omitempty"`
// Scope is "hub" (the default) or "channel".
Scope string `json:"scope,omitempty"`
Privileged bool `json:"privileged,omitempty"`
// CooldownSeconds per user and command; nil means the hub default (3), 0 none.
CooldownSeconds *int64 `json:"cooldown_seconds,omitempty"`
}
AppCommand is one slash command in PUT /me/app/commands.
type AppComponent ¶
type AppComponent struct {
// Type is "button" or "select".
Type string `json:"type"`
CustomID string `json:"custom_id"`
Label string `json:"label,omitempty"`
Style string `json:"style,omitempty"`
Disabled bool `json:"disabled,omitempty"`
Placeholder string `json:"placeholder,omitempty"`
MinValues *int `json:"min_values,omitempty"`
MaxValues *int `json:"max_values,omitempty"`
Options []SelectOption `json:"options,omitempty"`
}
AppComponent is a button or select menu.
type AppLaunch ¶
type AppLaunch struct {
AppID string `json:"app_id"`
Title string `json:"title"`
Description string `json:"description"`
ChannelID string `json:"channel_id"`
}
AppLaunch is a mini-app launch card in a channel.
type AppOpen ¶
type AppOpen struct {
AppID string `json:"app_id"`
ChannelID string `json:"channel_id"`
MiniAppURL string `json:"mini_app_url"`
SessionToken string `json:"session_token"`
RequiresCamera bool `json:"requires_camera"`
}
AppOpen tells a player's client to open a mini-app.
type AppProfile ¶
type AppProfile = rest.SetMeAppProfileJSONRequestBody
AppProfile is the body of PUT /me/app/profile.
type AppResponse ¶
type AppResponse struct {
Reply *Reply `json:"reply,omitempty"`
// Ephemeral shows the reply to the invoker only.
Ephemeral bool `json:"ephemeral,omitempty"`
Reactions []Reaction `json:"reactions,omitempty"`
// Defer says the app will post later on its own.
Defer bool `json:"defer,omitempty"`
// Game is attached to the reply; ignored without one.
Game *GameLaunchCard `json:"game,omitempty"`
}
AppResponse is what a slash command handler answers.
type AppSubscription ¶
type AppSubscription struct {
Event string `json:"event"`
Channels []string `json:"channels,omitempty"`
}
AppSubscription is one entry of PUT /me/app/subscriptions. A message.* subscription must name its channels.
type AuthOptions ¶
type AuthOptions struct {
// InviteCode admits the program on an invite_only hub. Ignored for members.
InviteCode string
Retry RetryOptions
// HTTPClient defaults to http.DefaultClient.
HTTPClient *http.Client
}
AuthOptions configure Authenticate.
type AuthSchemeError ¶
type AuthSchemeError struct {
Reason string
}
AuthSchemeError means a challenge could not be answered safely: an unknown scheme, or a raw challenge of the wrong length.
func (*AuthSchemeError) Error ¶
func (e *AuthSchemeError) Error() string
type AuthorInfo ¶
type AuthorInfo struct {
Pubkey string `json:"pubkey"`
DisplayName string `json:"display_name,omitempty"`
}
AuthorInfo names who invoked a command or pressed a component.
type Client ¶
type Client struct {
HubURL string
Identity *Identity
// Rest is the client generated from openapi.yaml. Bearer, retry and
// re-authentication on 401 are built into its transport; pass its
// results through Check to turn non-2xx answers into errors.
Rest *rest.ClientWithResponses
// contains filtered or unexported fields
}
Client is a program's connection to one hub: a session that renews itself, the generated REST client, capability checks, app registration and the event stream. It is safe for concurrent use.
func NewClient ¶
func NewClient(opts ClientOptions) (*Client, error)
NewClient builds a Client. It does not contact the hub.
func (*Client) AckEvents ¶
AckEvents acknowledges polled events (DELETE /me/events) so they are not returned again.
func (*Client) CanonicalPubkey ¶
CanonicalPubkey is the identity the hub attributes this program's actions to, or "" before the first login.
func (*Client) Connect ¶
func (c *Client) Connect(opts EventStreamOptions) *EventStream
Connect opens the hub WebSocket and keeps it open, re-authenticating and resuming on its own, until Close. Call SetAppProfile first: the hub only pushes and replays hub events on a socket opened by a registered app.
func (*Client) HasCapability ¶
HasCapability reports whether the hub advertises name. Capabilities, never versions.
func (*Client) OnStateChange ¶
func (c *Client) OnStateChange(fn func(SessionState)) (unsubscribe func())
OnStateChange calls fn on every session state change and returns a function that stops it. fn runs on the goroutine that caused the change.
func (*Client) PollEvents ¶
PollEvents reads GET /me/events, the transport for a program that holds no socket; since (unix seconds) returns only rows created after it, 0 all. Today's hub never writes this queue (Wavvon-server#170): prefer Connect.
func (*Client) RequireCapability ¶
RequireCapability returns *UnsupportedByHubError unless the hub advertises name.
func (*Client) SetAppCommands ¶
func (c *Client) SetAppCommands(ctx context.Context, commands []AppCommand) error
SetAppCommands replaces this app's slash commands.
func (*Client) SetAppProfile ¶
func (c *Client) SetAppProfile(ctx context.Context, profile AppProfile) error
SetAppProfile registers or replaces this identity's app profile. Call it before Connect: the hub decides whether a socket belongs to an app when it connects, and only an app's socket gets hub_event push and resume.
func (*Client) SetAppSubscriptions ¶
func (c *Client) SetAppSubscriptions(ctx context.Context, subscriptions []AppSubscription) error
SetAppSubscriptions replaces this app's event subscriptions.
type ClientOptions ¶
type ClientOptions struct {
HubURL string
// Seed is a 32-byte Ed25519 seed. It is never sent anywhere.
Seed []byte
// Identity is used instead of Seed when set.
Identity *Identity
// InviteCode admits the program on an invite_only hub.
InviteCode string
Retry RetryOptions
// HTTPClient defaults to http.DefaultClient.
HTTPClient *http.Client
}
ClientOptions configure NewClient. Seed or Identity is required.
type ComponentInteraction ¶
type ComponentInteraction struct {
HubURL string `json:"hub_url"`
ChannelID string `json:"channel_id"`
MessageID string `json:"message_id"`
CustomID string `json:"custom_id"`
Values []string `json:"values"`
User AuthorInfo `json:"user"`
}
ComponentInteraction is a button press or select choice on an app's message.
func (*ComponentInteraction) DispatchType ¶
func (*ComponentInteraction) DispatchType() string
type ComponentResponse ¶
type ComponentResponse struct {
Update *ComponentUpdate `json:"update,omitempty"`
EphemeralReply *EphemeralReply `json:"ephemeral_reply,omitempty"`
Defer bool `json:"defer,omitempty"`
}
ComponentResponse is what a component interaction handler answers.
type ComponentRow ¶
type ComponentRow struct {
Type string `json:"type"`
Components []AppComponent `json:"components"`
}
ComponentRow is a row of components; Type is always "row".
type ComponentUpdate ¶
type ComponentUpdate struct {
Body *string `json:"body,omitempty"`
Components []ComponentRow `json:"components,omitempty"`
}
ComponentUpdate replaces the interacted message's body or components.
type ConnectionState ¶
type ConnectionState string
ConnectionState is where an EventStream's socket is.
const ( ConnConnecting ConnectionState = "connecting" ConnOpen ConnectionState = "open" ConnReconnecting ConnectionState = "reconnecting" ConnClosed ConnectionState = "closed" )
Connection states.
type DMEvent ¶
type DMEvent struct {
ConversationID string `json:"conversation_id"`
Sender string `json:"sender"`
SenderName *string `json:"sender_name"`
Content string `json:"content"`
Timestamp int64 `json:"timestamp"`
}
DMEvent is a direct message notification.
type Dispatch ¶
type Dispatch interface {
DispatchType() string
}
Dispatch is a verified webhook call from the hub: *SlashInvocation, *ComponentInteraction, or *UnknownDispatch for a type this SDK does not know.
func VerifyDispatch ¶
func VerifyDispatch(h http.Header, body []byte, hubPublicKey string, opts VerifyOptions) (Dispatch, error)
VerifyDispatch verifies a slash command or component dispatch and decodes it. hubPublicKey is the hub's key as the program pinned it (GET /info public_key); the X-Wavvon-Hub-Pubkey header is only compared against it, never trusted. Pass the raw request bytes: re-serialised JSON will not verify.
type DispatchHandler ¶
type DispatchHandler struct {
// HubPublicKey is the hub's key, hex, from GET /info.
HubPublicKey string
OnSlashCommand func(context.Context, *SlashInvocation) (*AppResponse, error)
OnComponent func(context.Context, *ComponentInteraction) (*ComponentResponse, error)
// OnUnknown handles a verified dispatch of a type this SDK does not know.
OnUnknown func(context.Context, *UnknownDispatch) (any, error)
Verify VerifyOptions
}
DispatchHandler is an http.Handler for an app's webhook_url. It answers anything that does not verify with 401 and a verified dispatch with the handler's JSON. The hub waits 5 s for the answer. A nil handler answers {}.
func (*DispatchHandler) ServeHTTP ¶
func (d *DispatchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler.
type Embed ¶
type Embed struct {
Title string `json:"title,omitempty"`
URL string `json:"url,omitempty"`
Description string `json:"description,omitempty"`
Color string `json:"color,omitempty"`
Fields []EmbedField `json:"fields,omitempty"`
ThumbnailURL string `json:"thumbnail_url,omitempty"`
ImageURL string `json:"image_url,omitempty"`
}
Embed is a rich embed on an app's message.
type EmbedField ¶
type EmbedField struct {
Name string `json:"name"`
Value string `json:"value"`
Inline bool `json:"inline,omitempty"`
}
EmbedField is one name/value pair of an Embed.
type EphemeralReply ¶
type EphemeralReply struct {
Body string `json:"body"`
}
EphemeralReply is a reply only the interacting user sees.
type ErrorEvent ¶
ErrorEvent reports a failed client frame.
func (*ErrorEvent) EventType ¶
func (*ErrorEvent) EventType() string
type Event ¶
type Event interface {
// EventType is the frame's "type" field ("binary" for a binary frame).
EventType() string
}
Event is one server-to-client WebSocket frame (ws-protocol.md, checked against Wavvon-server crates/hub/src/routes/chat_models.rs). Type-switch on the concrete types below; a frame this version does not model arrives as *UnknownEvent, never dropped.
func ParseFrame ¶
ParseFrame turns one text frame into a typed event. A frame of an unknown type, or one whose fields do not decode, is an *UnknownEvent.
type EventStream ¶
type EventStream struct {
// contains filtered or unexported fields
}
EventStream is one hub WebSocket that reconnects on its own. It tracks the last hub_event seq and sends resume after every reconnect, so an app misses nothing inside the hub's 72-hour window; ReplayUnavailable is delivered like any other event when it falls outside. Events a replay repeats (seq not above the last one seen) are dropped.
func (*EventStream) AnnounceApp ¶
func (s *EventStream) AnnounceApp(ctx context.Context, channelID, title, description string) error
AnnounceApp is the mini-app host showing a launch card in a channel. Players' app_join is answered by the hub, not by the host.
func (*EventStream) Close ¶
func (s *EventStream) Close()
Close stops the stream and waits for its goroutine. Next then returns ErrStreamClosed once buffered events are drained.
func (*EventStream) DismissApp ¶
func (s *EventStream) DismissApp(ctx context.Context, channelID string) error
DismissApp is the mini-app host closing the session; clients dismiss their webviews.
func (*EventStream) LastSeq ¶
func (s *EventStream) LastSeq() (seq int64, ok bool)
LastSeq is the highest hub_event seq seen (or the hub's live seq at first connect); persist it and pass it as SinceSeq to resume after a restart.
func (*EventStream) Next ¶
func (s *EventStream) Next(ctx context.Context) (Event, error)
Next blocks until the next event, ctx ends, or the stream is closed (ErrStreamClosed).
func (*EventStream) OnStateChange ¶
func (s *EventStream) OnStateChange(fn func(ConnectionState)) (unsubscribe func())
OnStateChange calls fn on every state change and returns a function that stops it. fn runs on the stream's goroutine; keep it short.
func (*EventStream) Send ¶
func (s *EventStream) Send(ctx context.Context, frame any) error
Send writes one client frame (any JSON-encodable value with a "type"). It fails unless the socket is open.
func (*EventStream) SendMiniAppMessage ¶
func (s *EventStream) SendMiniAppMessage(ctx context.Context, appID, channelID, toPubkey, payload string) error
SendMiniAppMessage relays an opaque payload to one joined player's mini-app. Players' messages arrive as *MiniAppMessage with FromPubkey.
func (*EventStream) State ¶
func (s *EventStream) State() ConnectionState
State is the socket's current state.
type EventStreamOptions ¶
type EventStreamOptions struct {
// SinceSeq replays hub events after this seq on the first connect (an app
// persisting its position across restarts). Nil starts from now.
SinceSeq *int64
// Buffer is how many events wait for Next before reading pauses. Default 256.
Buffer int
}
EventStreamOptions configure Connect.
type GameLaunchCard ¶
type GameLaunchCard struct {
EntryURL string `json:"entry_url"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
ThumbnailURL string `json:"thumbnail_url,omitempty"`
}
GameLaunchCard is a "Play" card attached to a reply.
type Hello ¶
type Hello struct {
LiveSeq int64 `json:"live_seq"`
}
Hello is the first frame on every connection.
type HubEvent ¶
type HubEvent struct {
Seq int64 `json:"seq"`
// Event is e.g. "member.joined", "message.created".
Event string `json:"event"`
HubURL string `json:"hub_url"`
At int64 `json:"at"`
Payload map[string]any `json:"payload"`
// Replay only, and only when the audit row has them.
ActorPubkey string `json:"actor_pubkey,omitempty"`
TargetPubkey string `json:"target_pubkey,omitempty"`
ChannelID string `json:"channel_id,omitempty"`
Replayed bool `json:"replayed,omitempty"`
}
HubEvent is the one envelope for live push, replay and outgoing webhooks (apps.md §5).
type HubUnavailableError ¶
type HubUnavailableError struct {
// LastStatus is the last HTTP status seen, or 0 for a network error or timeout.
Err error
}
HubUnavailableError means the hub could not be reached or kept saying "not now" (429, 5xx, timeout, network) until the retry budget ran out. It is not an answer: nothing about the resource can be concluded from it.
func (*HubUnavailableError) Error ¶
func (e *HubUnavailableError) Error() string
func (*HubUnavailableError) Unwrap ¶
func (e *HubUnavailableError) Unwrap() error
type Identity ¶
type Identity struct {
// PublicKey is the Ed25519 public key, lowercase hex.
PublicKey string
// contains filtered or unexported fields
}
Identity is a keypair the program holds. The private key never leaves it: only signatures do.
func IdentityFromHexSeed ¶
IdentityFromHexSeed is IdentityFromSeed for a seed written as 64 hex characters.
func IdentityFromSeed ¶
IdentityFromSeed builds an Identity from a 32-byte Ed25519 seed that the operator keeps in a file or environment variable.
type MessageEvent ¶
type MessageEvent struct {
Type string `json:"type"`
ChannelID string `json:"channel_id"`
Message rest.Message `json:"message"`
}
MessageEvent is a new ("message") or edited ("message_edited") channel message.
func (*MessageEvent) EventType ¶
func (e *MessageEvent) EventType() string
type MessageRefEvent ¶
type MessageRefEvent struct {
Type string `json:"type"`
ChannelID string `json:"channel_id"`
MessageID string `json:"message_id"`
}
MessageRefEvent is "message_deleted", "message_pinned" or "message_unpinned".
func (*MessageRefEvent) EventType ¶
func (e *MessageRefEvent) EventType() string
type MiniAppMessage ¶
type MiniAppMessage struct {
AppID string `json:"app_id"`
ChannelID string `json:"channel_id"`
Payload string `json:"payload"`
FromPubkey string `json:"from_pubkey,omitempty"`
}
MiniAppMessage is an opaque payload relayed between a mini-app host and a player; FromPubkey names the player on the host side.
func (*MiniAppMessage) EventType ¶
func (*MiniAppMessage) EventType() string
type OutgoingWebhookEvent ¶
type OutgoingWebhookEvent struct {
Type string `json:"type"`
HubEvent
WebhookID string `json:"webhook_id,omitempty"`
Truncated bool `json:"truncated,omitempty"`
}
OutgoingWebhookEvent is an outgoing-webhook delivery: a hub_event plus delivery fields.
func VerifyOutgoingWebhook ¶
func VerifyOutgoingWebhook(h http.Header, body []byte, secret string, opts VerifyOptions) (*OutgoingWebhookEvent, error)
VerifyOutgoingWebhook verifies an outgoing-webhook delivery (HMAC-SHA256) and decodes its envelope. secret is what the admin copied when the webhook was created or rotated (base64url, no padding).
type PolledEvent ¶
type PolledEvent struct {
ID string
EventType string
// Payload is the event's JSON. A payload that is not JSON arrives as a JSON string.
Payload json.RawMessage
CreatedAt int64
}
PolledEvent is one row of GET /me/events.
type Pong ¶
type Pong struct {
Nonce int64 `json:"nonce"`
OutboundLossPct *float64 `json:"outbound_loss_pct,omitempty"`
}
Pong answers a ping (capability ws.ping).
type ReactionsUpdated ¶
type ReactionsUpdated struct {
ChannelID string `json:"channel_id"`
MessageID string `json:"message_id"`
Reactions []struct {
Emoji string `json:"emoji"`
Count int `json:"count"`
Me bool `json:"me"`
} `json:"reactions"`
}
ReactionsUpdated carries a message's full reaction list.
func (*ReactionsUpdated) EventType ¶
func (*ReactionsUpdated) EventType() string
type ReplayComplete ¶
type ReplayComplete struct {
Replayed int64 `json:"replayed"`
LiveFromSeq int64 `json:"live_from_seq"`
}
ReplayComplete ends a resume replay.
func (*ReplayComplete) EventType ¶
func (*ReplayComplete) EventType() string
type ReplayUnavailable ¶
type ReplayUnavailable struct {
}
ReplayUnavailable means the resume point is older than the hub keeps (72 hours): events between it and EarliestSeq are lost to this program.
func (*ReplayUnavailable) EventType ¶
func (*ReplayUnavailable) EventType() string
type Reply ¶
type Reply struct {
Body string `json:"body"`
Embeds []Embed `json:"embeds,omitempty"`
Components []ComponentRow `json:"components,omitempty"`
ReplyTo string `json:"reply_to,omitempty"`
}
Reply is the message an app posts in answer to a command.
type RetryInfo ¶
type RetryInfo struct {
Attempt int
Delay time.Duration
// Status is the HTTP status, or 0 for a network error or timeout.
Status int
Err error
}
RetryInfo describes one failed attempt about to be retried.
type RetryOptions ¶
type RetryOptions struct {
// MaxAttempts before giving up with HubUnavailableError. 0 means 8; a
// negative value keeps trying until the context ends.
MaxAttempts int
// BaseDelay is the first backoff ceiling. Default 500 ms.
BaseDelay time.Duration
// MaxDelay caps the backoff ceiling. Default 30 s.
MaxDelay time.Duration
// Timeout per attempt; a timeout counts as transient. Default 15 s.
Timeout time.Duration
// OnRetry is called before each wait, so a program can show it is retrying.
OnRetry func(RetryInfo)
// contains filtered or unexported fields
}
RetryOptions tune the backoff used for every request. The zero value is the default policy.
type SelectOption ¶
type SelectOption struct {
Label string `json:"label"`
Value string `json:"value"`
Description string `json:"description,omitempty"`
}
SelectOption is one choice of a select AppComponent.
type Session ¶
type Session struct {
Token string
// Scope is "member", or "lobby" on a hub that holds newcomers back.
Scope string
// CanonicalPubkey is the identity the hub attributes this session's actions to.
CanonicalPubkey string
}
Session is a logged-in session on one hub.
func Authenticate ¶
func Authenticate(ctx context.Context, hubURL string, id *Identity, opts AuthOptions) (Session, error)
Authenticate runs challenge, sign, verify against hubURL. A transient failure at either step restarts from a fresh challenge, because the hub drops a pending challenge as soon as verify reads it.
type SessionState ¶
type SessionState string
SessionState is where the client's REST session is.
const ( StateSignedOut SessionState = "signed-out" StateAuthenticating SessionState = "authenticating" StateReady SessionState = "ready" )
Session states. StateAuthenticating after StateReady is the reconnecting state of REST: a session died and is being re-established.
type SlashInvocation ¶
type SlashInvocation struct {
HubURL string `json:"hub_url"`
ChannelID string `json:"channel_id"`
MessageIDHint string `json:"message_id_hint"`
Author AuthorInfo `json:"author"`
Command string `json:"command"`
ArgsRaw string `json:"args_raw"`
ArgsTokens []string `json:"args_tokens"`
}
SlashInvocation is a slash command a member ran.
func (*SlashInvocation) DispatchType ¶
func (*SlashInvocation) DispatchType() string
type TypingEvent ¶
type TypingEvent struct {
ChannelID string `json:"channel_id"`
PublicKey string `json:"public_key"`
DisplayName *string `json:"display_name"`
Typing bool `json:"typing"`
}
TypingEvent says someone started or stopped typing in a channel.
func (*TypingEvent) EventType ¶
func (*TypingEvent) EventType() string
type UnknownDispatch ¶
type UnknownDispatch struct {
RawType string
Raw json.RawMessage
}
UnknownDispatch is a verified dispatch whose type this SDK does not know. Delivered, never dropped.
func (*UnknownDispatch) DispatchType ¶
func (u *UnknownDispatch) DispatchType() string
type UnknownEvent ¶
type UnknownEvent struct {
// RawType is the frame's own type, "binary" for a binary frame, "" if unparseable.
RawType string
Raw []byte
}
UnknownEvent is a frame of a type this SDK does not model, or one that did not decode. Never swallowed.
func (*UnknownEvent) EventType ¶
func (e *UnknownEvent) EventType() string
type UnsupportedByHubError ¶
type UnsupportedByHubError struct {
Capability string
}
UnsupportedByHubError means the hub does not advertise a capability the call needs. It is never the result of a version comparison.
func (*UnsupportedByHubError) Error ¶
func (e *UnsupportedByHubError) Error() string
func (*UnsupportedByHubError) Unwrap ¶
func (e *UnsupportedByHubError) Unwrap() error
Unwrap makes errors.Is(err, ErrUnsupportedByHub) true.
type VerifyOptions ¶
type VerifyOptions struct {
// Now defaults to the clock.
Now time.Time
// Tolerance is the maximum |now - X-Wavvon-Timestamp|. Default 300 s.
Tolerance time.Duration
}
VerifyOptions tune timestamp checking.
type WebhookVerificationError ¶
type WebhookVerificationError struct {
Reason string
}
WebhookVerificationError means a webhook request failed verification. Answer it with 401 and act on nothing in it.
func (*WebhookVerificationError) Error ¶
func (e *WebhookVerificationError) Error() string
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
smoke
command
Command smoke runs the SDK against a real hub: it authenticates as a fresh identity, registers a slash command, posts a message and sees it come back over the socket, invokes the command, and checks that the verified invocation's reply lands in the channel.
|
Command smoke runs the SDK against a real hub: it authenticates as a fresh identity, registers a slash command, posts a message and sees it come back over the socket, invokes the command, and checks that the verified invocation's reply lands in the channel. |
|
examples
|
|
|
echobot
command
Command echobot echoes every message in the channels it can read and answers /echo.
|
Command echobot echoes every message in the channels it can read and answers /echo. |
|
Package rest provides primitives to interact with the openapi HTTP API.
|
Package rest provides primitives to interact with the openapi HTTP API. |