Documentation
¶
Overview ¶
Package whatsapp – dedup.go provides a message deduplication cache to filter out duplicate messages during WhatsApp reconnections.
Package whatsapp – events.go processes incoming WhatsApp events from whatsmeow and converts them into unified DevClaw IncomingMessage types.
Package whatsapp – health.go implements proactive health monitoring for the WhatsApp connection to detect and recover from silent disconnects.
Package whatsapp – media.go handles media upload, download, and message building for images, audio, video, documents, and stickers.
Package whatsapp implements the WhatsApp channel for DevClaw using whatsmeow — a native Go WhatsApp Web API library. No Node.js, no Baileys.
Features:
- QR code login with persistent session
- Send/receive text, images, audio, video, documents, stickers
- Group message support
- Reply and quoting
- Reactions (emoji)
- Typing indicators and read receipts
- Media upload/download with encryption
- Automatic reconnection with backoff
- Connection state management and events
This is a core channel (compiled into the binary, not a plugin).
Index ¶
- func IsValidJID(jid string) bool
- type AccessControlConfig
- type Config
- type ConnectionEvent
- type ConnectionObserver
- type ConnectionState
- type GroupPoliciesConfig
- type GroupPolicyConfig
- type HealthMonitorConfig
- type QREvent
- type QREventEnhanced
- type WhatsApp
- func (w *WhatsApp) AddConnectionObserver(obs ConnectionObserver)
- func (w *WhatsApp) AutoReadEnabled() bool
- func (w *WhatsApp) BaseType() string
- func (w *WhatsApp) BlockUser(jid string)
- func (w *WhatsApp) CanResponse(msg *channels.IncomingMessage) (bool, string)
- func (w *WhatsApp) Connect(ctx context.Context) error
- func (w *WhatsApp) Disconnect() error
- func (w *WhatsApp) DownloadMedia(ctx context.Context, msg *channels.IncomingMessage) ([]byte, string, error)
- func (w *WhatsApp) GetAccessConfig() any
- func (w *WhatsApp) GetGroupPolicies() any
- func (w *WhatsApp) GetGroupPolicy(groupJID string) *GroupPolicyConfig
- func (w *WhatsApp) GetJoinedGroups() ([]channels.WhatsAppJoinedGroup, error)
- func (w *WhatsApp) GetState() ConnectionState
- func (w *WhatsApp) GrantAccess(jid string, level string)
- func (w *WhatsApp) Health() channels.HealthStatus
- func (w *WhatsApp) InstanceID() string
- func (w *WhatsApp) IsBotMessage(chatID, messageID string) bool
- func (w *WhatsApp) IsConnected() bool
- func (w *WhatsApp) ListGroupPolicies() map[string]*GroupPolicyConfig
- func (w *WhatsApp) ListGroupPoliciesForConfig() []channels.GroupPolicyConfig
- func (w *WhatsApp) Logout() error
- func (w *WhatsApp) MarkAsked(jid string)
- func (w *WhatsApp) MarkRead(ctx context.Context, chatID string, messageIDs []string) error
- func (w *WhatsApp) Name() string
- func (w *WhatsApp) NeedsQR() bool
- func (w *WhatsApp) Receive() <-chan *channels.IncomingMessage
- func (w *WhatsApp) ReplaceAccessList(owners, admins, allowedUsers, blockedUsers []string, ...)
- func (w *WhatsApp) RequestNewQR(_ context.Context) error
- func (w *WhatsApp) RevokeAccess(jid string)
- func (w *WhatsApp) SaveMediaToFile(ctx context.Context, msg *channels.IncomingMessage) (string, error)
- func (w *WhatsApp) Send(ctx context.Context, to string, msg *channels.OutgoingMessage) error
- func (w *WhatsApp) SendMedia(ctx context.Context, to string, media *channels.MediaMessage) error
- func (w *WhatsApp) SendPresence(ctx context.Context, available bool) error
- func (w *WhatsApp) SendReaction(ctx context.Context, chatID, messageID, emoji string) error
- func (w *WhatsApp) SendTyping(ctx context.Context, to string) error
- func (w *WhatsApp) SendTypingEnabled() bool
- func (w *WhatsApp) SetAutoRead(enabled bool)
- func (w *WhatsApp) SetDefaultPolicy(policy string)
- func (w *WhatsApp) SetGroupDefaultPolicy(policy string)
- func (w *WhatsApp) SetGroupPolicy(groupJID string, policy any)
- func (w *WhatsApp) SetSendTyping(enabled bool)
- func (w *WhatsApp) SetTrigger(trigger string)
- func (w *WhatsApp) ShouldRespond(msg *channels.IncomingMessage, trigger string) bool
- func (w *WhatsApp) StartHealthMonitor(ctx context.Context, cfg HealthMonitorConfig)
- func (w *WhatsApp) StartPinger(ctx context.Context)
- func (w *WhatsApp) SubscribeQR() (chan QREvent, func())
- func (w *WhatsApp) TriggerValue() string
- func (w *WhatsApp) UnblockUser(jid string)
- func (w *WhatsApp) UpdateLastMsgTime()
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsValidJID ¶ added in v1.13.0
IsValidJID checks if a JID looks valid (basic validation). This is exported for use by API handlers.
Types ¶
type AccessControlConfig ¶ added in v1.13.0
type AccessControlConfig struct {
// DefaultPolicy: "allow" (anyone), "deny" (only authorized), or "ask" (ask once).
DefaultPolicy string `yaml:"default_policy"`
// Owners have full control.
Owners []string `yaml:"owners"`
// Admins can manage users.
Admins []string `yaml:"admins"`
// Allowed users can interact.
AllowedUsers []string `yaml:"allowed_users"`
// Blocked users cannot interact.
BlockedUsers []string `yaml:"blocked_users"`
// Allowed groups can interact.
AllowedGroups []string `yaml:"allowed_groups"`
// Blocked groups cannot interact.
BlockedGroups []string `yaml:"blocked_groups"`
// Pending message sent to unauthorized users.
PendingMessage string `yaml:"pending_message"`
}
AccessControlConfig defines who can use the bot.
type Config ¶
type Config struct {
// InstanceID identifies this instance ("" for default, e.g. "business" for named).
// Set automatically from the config key in whatsapp_instances.
InstanceID string `yaml:"instance_id,omitempty"`
// SessionDir is the directory for session persistence (SQLite).
// Ignored if DatabasePath is set.
SessionDir string `yaml:"session_dir"`
// DatabasePath is the path to the SQLite database file for session storage.
// If set, the WhatsApp session tables (prefixed with whatsmeow_) will be
// stored in this database alongside other devclaw data.
// If empty, defaults to {SessionDir}/whatsapp.db.
DatabasePath string `yaml:"database_path"`
// Trigger is the keyword that activates the bot (e.g. "@devclaw").
Trigger string `yaml:"trigger"`
// RespondToGroups enables responding in group chats.
RespondToGroups bool `yaml:"respond_to_groups"`
// RespondToDMs enables responding in direct messages.
RespondToDMs bool `yaml:"respond_to_dms"`
// AutoRead marks incoming messages as read.
AutoRead bool `yaml:"auto_read"`
// SendTyping sends typing indicators while processing.
SendTyping bool `yaml:"send_typing"`
// MediaDir is the directory for downloaded media files.
MediaDir string `yaml:"media_dir"`
// MaxMediaSizeMB is the maximum media file size to process.
MaxMediaSizeMB int `yaml:"max_media_size_mb"`
// ReconnectBackoff is the initial backoff duration for reconnection.
ReconnectBackoff time.Duration `yaml:"reconnect_backoff"`
// MaxReconnectAttempts is the maximum number of reconnection attempts (0 = unlimited).
MaxReconnectAttempts int `yaml:"max_reconnect_attempts"`
// HealthMonitor configures proactive connection health monitoring.
HealthMonitor HealthMonitorConfig `yaml:"health_monitor"`
// Access control configuration.
Access AccessControlConfig `yaml:"access"`
// Group policies configuration.
GroupPolicies GroupPoliciesConfig `yaml:"group_policies"`
}
Config holds WhatsApp channel configuration.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a Config with sensible defaults.
type ConnectionEvent ¶
type ConnectionEvent struct {
State ConnectionState `json:"state"`
Previous ConnectionState `json:"previous,omitempty"`
Timestamp time.Time `json:"timestamp"`
Reason string `json:"reason,omitempty"`
Details map[string]any `json:"details,omitempty"`
}
ConnectionEvent represents a connection state change event.
type ConnectionObserver ¶
type ConnectionObserver interface {
OnConnectionChange(evt ConnectionEvent)
}
ConnectionObserver receives connection state changes.
type ConnectionState ¶
type ConnectionState string
ConnectionState represents the current connection state.
const ( StateDisconnected ConnectionState = "disconnected" StateConnecting ConnectionState = "connecting" StateConnected ConnectionState = "connected" StateReconnecting ConnectionState = "reconnecting" StateWaitingQR ConnectionState = "waiting_qr" StateQRScanned ConnectionState = "qr_scanned" StateLoggingOut ConnectionState = "logging_out" StateBanned ConnectionState = "banned" )
type GroupPoliciesConfig ¶ added in v1.13.0
type GroupPoliciesConfig struct {
// Default policies for unconfigured groups.
// Multiple policies are combined with OR logic.
DefaultPolicies []string `yaml:"default_policies"`
// Legacy DefaultPolicy for backwards compatibility.
// Deprecated: Use DefaultPolicies instead.
DefaultPolicy string `yaml:"default_policy"`
// Specific group policies.
Groups []GroupPolicyConfig `yaml:"groups"`
}
GroupPoliciesConfig defines group-specific activation policies.
type GroupPolicyConfig ¶ added in v1.13.0
type GroupPolicyConfig struct {
// ID is the group JID.
ID string `yaml:"id"`
// Name is optional display name.
Name string `yaml:"name"`
// Policies: list of "always", "mention", "reply", "keyword", "disabled", "allowlist".
// Multiple policies are combined with OR logic (respond if ANY policy matches).
Policies []string `yaml:"policies"`
// Legacy Policy field for backwards compatibility.
// Deprecated: Use Policies instead.
Policy string `yaml:"policy"`
// Keywords that trigger the bot (for policy="keyword").
Keywords []string `yaml:"keywords"`
// Allowed users (for policy="allowlist").
AllowedUsers []string `yaml:"allowed_users"`
// Workspace override for this group.
Workspace string `yaml:"workspace"`
}
GroupPolicyConfig defines policy for a specific group.
type HealthMonitorConfig ¶ added in v1.12.0
type HealthMonitorConfig struct {
// Enabled turns on proactive health monitoring.
Enabled bool `yaml:"enabled"`
// CheckInterval is how often to perform health checks.
// Default: 30s
CheckInterval time.Duration `yaml:"check_interval"`
// MaxSilentDuration is the maximum time without any activity before
// a health check is considered failed.
// Default: 5m
MaxSilentDuration time.Duration `yaml:"max_silent_duration"`
// ForceReconnectAfter is the maximum silent duration before forcing
// a preventive reconnection, regardless of client.IsConnected() result.
// This handles "half-open" TCP connections where the socket appears
// connected but is actually dead.
// Default: 30m (0 = disabled)
ForceReconnectAfter time.Duration `yaml:"force_reconnect_after"`
}
HealthMonitorConfig configures proactive connection health monitoring.
func DefaultHealthMonitorConfig ¶ added in v1.12.0
func DefaultHealthMonitorConfig() HealthMonitorConfig
DefaultHealthMonitorConfig returns sensible defaults.
type QREvent ¶
type QREvent struct {
// Type is "code", "success", "timeout", "error", or "refresh".
Type string `json:"type"`
// Code is the raw QR code string (only for Type == "code").
Code string `json:"code,omitempty"`
// Message is a human-readable description.
Message string `json:"message,omitempty"`
// ExpiresAt is when the QR code expires.
ExpiresAt time.Time `json:"expires_at,omitempty"`
// SecondsLeft is seconds until expiration.
SecondsLeft int `json:"seconds_left,omitempty"`
}
QREvent represents a QR code event sent to observers.
type QREventEnhanced ¶
type QREventEnhanced struct {
Type string `json:"type"` // "code", "success", "timeout", "error", "refresh"
Code string `json:"code,omitempty"` // Raw QR code string
Message string `json:"message"` // Human-readable message
ExpiresAt time.Time `json:"expires_at,omitempty"` // When QR code expires
SecondsLeft int `json:"seconds_left,omitempty"` // Seconds until expiration
Attempts int `json:"attempts,omitempty"` // Number of QR attempts
}
QREventEnhanced represents an enhanced QR code event with more details.
type WhatsApp ¶
type WhatsApp struct {
// contains filtered or unexported fields
}
WhatsApp implements the channels.Channel, channels.MediaChannel, channels.PresenceChannel, and channels.ReactionChannel interfaces.
func (*WhatsApp) AddConnectionObserver ¶
func (w *WhatsApp) AddConnectionObserver(obs ConnectionObserver)
AddConnectionObserver registers a connection observer.
func (*WhatsApp) AutoReadEnabled ¶ added in v1.13.0
AutoReadEnabled returns true if AutoRead is configured.
func (*WhatsApp) CanResponse ¶ added in v1.13.0
func (w *WhatsApp) CanResponse(msg *channels.IncomingMessage) (bool, string)
CanResponse checks if the sender is allowed to interact with the bot.
func (*WhatsApp) Connect ¶
Connect establishes the WhatsApp Web connection via whatsmeow. If no existing session is found, the QR login process runs in the background (non-blocking) so the server can start immediately. The QR code is streamed to web UI observers for scanning via browser.
func (*WhatsApp) Disconnect ¶
Disconnect gracefully closes the WhatsApp connection.
func (*WhatsApp) DownloadMedia ¶
func (w *WhatsApp) DownloadMedia(ctx context.Context, msg *channels.IncomingMessage) ([]byte, string, error)
DownloadMedia downloads media from an incoming message.
func (*WhatsApp) GetAccessConfig ¶ added in v1.13.0
GetAccessConfig returns the current access control configuration.
func (*WhatsApp) GetGroupPolicies ¶ added in v1.13.0
GetGroupPolicies returns the current group policies configuration.
func (*WhatsApp) GetGroupPolicy ¶ added in v1.13.0
func (w *WhatsApp) GetGroupPolicy(groupJID string) *GroupPolicyConfig
GetGroupPolicy returns the policy for a group.
func (*WhatsApp) GetJoinedGroups ¶ added in v1.13.0
func (w *WhatsApp) GetJoinedGroups() ([]channels.WhatsAppJoinedGroup, error)
GetJoinedGroups returns all groups the bot is a member of.
func (*WhatsApp) GetState ¶
func (w *WhatsApp) GetState() ConnectionState
GetState returns the current connection state (public API).
func (*WhatsApp) GrantAccess ¶ added in v1.13.0
GrantAccess grants access to a user.
func (*WhatsApp) Health ¶
func (w *WhatsApp) Health() channels.HealthStatus
Health returns the WhatsApp channel health status.
func (*WhatsApp) InstanceID ¶ added in v1.16.0
InstanceID returns the instance identifier ("" for default).
func (*WhatsApp) IsBotMessage ¶ added in v1.16.0
IsBotMessage returns true if the given message was sent by the bot. Implements channels.SentMessageTracker.
func (*WhatsApp) IsConnected ¶
IsConnected returns true if WhatsApp is connected.
func (*WhatsApp) ListGroupPolicies ¶ added in v1.13.0
func (w *WhatsApp) ListGroupPolicies() map[string]*GroupPolicyConfig
ListGroupPolicies returns all configured group policies.
func (*WhatsApp) ListGroupPoliciesForConfig ¶ added in v1.13.0
func (w *WhatsApp) ListGroupPoliciesForConfig() []channels.GroupPolicyConfig
ListGroupPoliciesForConfig returns all group policies as a slice for config persistence. This implements WhatsAppAccessManager interface.
func (*WhatsApp) MarkAsked ¶ added in v1.13.0
MarkAsked marks a user as having received the pending message.
func (*WhatsApp) Name ¶
Name returns the channel name. For the default instance this is "whatsapp"; for named instances it returns "whatsapp:<instance_id>".
func (*WhatsApp) NeedsQR ¶
NeedsQR returns true if the WhatsApp session is not linked (needs QR scan).
func (*WhatsApp) Receive ¶
func (w *WhatsApp) Receive() <-chan *channels.IncomingMessage
Receive returns the incoming messages channel.
func (*WhatsApp) ReplaceAccessList ¶ added in v1.13.0
func (w *WhatsApp) ReplaceAccessList(owners, admins, allowedUsers, blockedUsers []string, defaultPolicy, pendingMessage string)
ReplaceAccessList replaces the entire access list atomically.
func (*WhatsApp) RequestNewQR ¶
RequestNewQR disconnects and reconnects to generate a fresh QR code. This is used when the web UI needs a new QR after timeout. A default timeout of 2 minutes is applied. The goroutine is bound to the instance lifecycle (w.ctx) so it stops on Disconnect/deletion. Only one QR generation can run at a time (guarded by qrGuard).
func (*WhatsApp) RevokeAccess ¶ added in v1.13.0
RevokeAccess revokes access from a user.
func (*WhatsApp) SaveMediaToFile ¶
func (w *WhatsApp) SaveMediaToFile(ctx context.Context, msg *channels.IncomingMessage) (string, error)
SaveMediaToFile downloads and saves media to disk.
func (*WhatsApp) SendMedia ¶
SendMedia sends a media message (image, audio, video, document, sticker).
func (*WhatsApp) SendPresence ¶
SendPresence updates the bot's online/offline status. Also measures latency for health reporting.
func (*WhatsApp) SendReaction ¶
SendReaction sends an emoji reaction to a message.
func (*WhatsApp) SendTyping ¶
SendTyping sends a typing indicator.
func (*WhatsApp) SendTypingEnabled ¶ added in v1.13.0
SendTypingEnabled returns true if SendTyping is configured.
func (*WhatsApp) SetAutoRead ¶ added in v1.13.0
SetAutoRead enables or disables auto-read behavior.
func (*WhatsApp) SetDefaultPolicy ¶ added in v1.13.0
SetDefaultPolicy updates the default access policy.
func (*WhatsApp) SetGroupDefaultPolicy ¶ added in v1.13.0
SetGroupDefaultPolicy updates the default group policy.
func (*WhatsApp) SetGroupPolicy ¶ added in v1.13.0
SetGroupPolicy sets a policy for a group. Accepts either *GroupPolicyConfig or map[string]any for API compatibility.
func (*WhatsApp) SetSendTyping ¶ added in v1.13.0
SetSendTyping enables or disables send-typing behavior.
func (*WhatsApp) SetTrigger ¶ added in v1.13.0
SetTrigger sets the trigger word for the bot.
func (*WhatsApp) ShouldRespond ¶ added in v1.13.0
func (w *WhatsApp) ShouldRespond(msg *channels.IncomingMessage, trigger string) bool
ShouldRespond checks if the bot should respond to a group message. Supports multiple policies combined with OR logic.
func (*WhatsApp) StartHealthMonitor ¶ added in v1.12.0
func (w *WhatsApp) StartHealthMonitor(ctx context.Context, cfg HealthMonitorConfig)
StartHealthMonitor starts the proactive health monitoring goroutine. It runs until the context is cancelled.
func (*WhatsApp) StartPinger ¶ added in v1.12.0
StartPinger sends periodic presence updates to keep connection alive.
func (*WhatsApp) SubscribeQR ¶
SubscribeQR registers a channel to receive QR code events. Returns an unsubscribe function.
func (*WhatsApp) TriggerValue ¶ added in v1.13.0
TriggerValue returns the configured trigger word.
func (*WhatsApp) UnblockUser ¶ added in v1.13.0
UnblockUser unblocks a user.
func (*WhatsApp) UpdateLastMsgTime ¶ added in v1.12.0
func (w *WhatsApp) UpdateLastMsgTime()
UpdateLastMsgTime updates the last activity timestamp. This should be called whenever we receive a message or other activity.