Help us shape the future of Go! Take the 2026 Go Developer Survey

whatsapp

package
v0.19.2 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package whatsapp implements the WhatsApp Business Cloud API adapter for the orb chat gateway: webhook ingress (hub handshake + HMAC-signed events), final-message delivery with reply threading, and authenticated media download.

The adapter speaks only the official Graph Cloud API with caller-supplied credentials. Unsigned webhooks are refused by construction: New errors without an AppSecret, matching the Hermes reference stance. The Cloud API has no message editing, so Preview is a no-op and only the final reply is sent (no fake streaming).

Index

Constants

View Source
const GraphVersion = "v23.0"

GraphVersion is the pinned Graph API version used for every call.

Variables

This section is empty.

Functions

func FormatText

func FormatText(markdown string) string

FormatText converts common markdown to WhatsApp markup: **b**/__b__ → *b*, ~~s~~ → ~s~, headings → *bold* lines, [text](url) → "text (url)". Fenced code blocks are kept as triple-backtick blocks (WhatsApp renders them as monospace); the language token on the opening fence is dropped because WhatsApp would display it literally.

ponytail: line/regex transform, not a goldmark AST walk; single-asterisk and single-underscore emphasis pass through unchanged (md italic renders as WhatsApp bold/italic respectively — accepted ceiling).

func StatusRank

func StatusRank(status string) int

StatusRank orders status values so out-of-order callbacks can be reduced to the furthest-progressed state: read > delivered > sent, with the terminal "failed" above all and unknown values at 0.

Types

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

Adapter is a chat.Adapter for the WhatsApp Business Cloud API.

func New

func New(opts Options) (*Adapter, error)

New builds the adapter. It refuses to construct without Token, PhoneNumberID, AppSecret, and VerifyToken.

func (*Adapter) Account

func (a *Adapter) Account() string

Account returns the business phone number id this adapter serves, matching the Account set on every normalized message.

func (*Adapter) Download

func (a *Adapter) Download(ctx context.Context, ref chat.AttachmentRef) (io.ReadCloser, string, error)

Download implements chat.Adapter: media id → metadata (url) → authenticated download. Media URLs expire after ~5 minutes, so a failed download refetches the metadata once for a fresh URL before giving up.

func (*Adapter) NewDelivery

func (a *Adapter) NewDelivery(key chat.ConversationKey, replyTo, resumePreviewID string) chat.Delivery

NewDelivery implements chat.Adapter. resumePreviewID is ignored: the Cloud API cannot edit messages, so this adapter never creates previews and crash recovery simply resends the final text.

func (*Adapter) Platform

func (a *Adapter) Platform() string

Platform implements chat.Adapter.

func (*Adapter) Webhook

func (a *Adapter) Webhook(publish func(chat.Message) error) http.Handler

Webhook returns the HTTP handler for the Cloud API webhook endpoint. GET answers the one-time subscribe handshake; POST verifies the X-Hub-Signature-256 HMAC over the raw body BEFORE parsing, publishes every normalized message, and forwards statuses[] to Options.OnStatus. A publish error yields a 500 so Meta redelivers (the wamid EventID dedupes downstream).

type GraphError

type GraphError struct {
	Code      int    `json:"code"`
	Subcode   int    `json:"error_subcode,omitempty"`
	Type      string `json:"type,omitempty"`
	Title     string `json:"title,omitempty"`
	Message   string `json:"message,omitempty"`
	ErrorData struct {
		Details string `json:"details,omitempty"`
	} `json:"error_data,omitempty"`
	FBTraceID string `json:"fbtrace_id,omitempty"`
}

GraphError is one Graph API error object, either from an HTTP error response envelope or from a statuses[].errors[] entry.

func (*GraphError) Error

func (e *GraphError) Error() string

Error implements error.

type Options

type Options struct {
	// Token is the Graph API access token (Bearer). Required.
	Token string
	// PhoneNumberID is the business phone number id calls are made on
	// behalf of. Required.
	PhoneNumberID string
	// AppSecret signs inbound webhooks (X-Hub-Signature-256). Required:
	// unsigned webhooks are not an option.
	AppSecret string
	// VerifyToken answers the one-time GET subscribe handshake. Required.
	VerifyToken string
	// BaseURL overrides the Graph endpoint (tests). Default
	// https://graph.facebook.com.
	BaseURL string
	// HTTPClient overrides the HTTP client. Default: 30s timeout.
	HTTPClient *http.Client
	// OnStatus receives delivery status callbacks from the statuses[]
	// webhook array. Default: no-op. Statuses arrive out of order; keep the
	// highest [StatusRank] per message id.
	OnStatus func(Status)
}

Options configures the WhatsApp Cloud API adapter.

type Status

type Status struct {
	// MessageID is the wamid of the outbound message the status refers to.
	MessageID string `json:"id"`
	// Status is "sent", "delivered", "read", or "failed".
	Status string `json:"status"`
	// Timestamp is epoch seconds, as a string (all WhatsApp timestamps are).
	Timestamp string `json:"timestamp"`
	// RecipientID is the recipient wa_id.
	RecipientID string `json:"recipient_id"`
	// Errors is populated on "failed" statuses.
	Errors []GraphError `json:"errors,omitempty"`
}

Status is one entry of the statuses[] webhook array. The lifecycle per message id is sent → delivered → read (or the terminal failed), but callbacks arrive out of order: consumers must keep the highest StatusRank seen per MessageID instead of trusting arrival order.

Jump to

Keyboard shortcuts

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