channels

package
v1.16.7 Latest Latest
Warning

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

Go to latest
Published: Mar 24, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package channels defines the interfaces and types for DevClaw communication channels. Each channel (WhatsApp, Discord, Telegram) implements the Channel interface to receive and send messages in a unified way.

Package channels – manager.go orchestrates multiple communication channels, providing a single entry point to receive messages from all platforms and route responses to the correct channel.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrChannelDisconnected = fmt.Errorf("channel is not connected")
	ErrSendFailed          = fmt.Errorf("failed to send message")
	ErrConnectionFailed    = fmt.Errorf("failed to connect to channel")
	ErrMediaNotSupported   = fmt.Errorf("media not supported by this channel")
	ErrMediaDownloadFailed = fmt.Errorf("failed to download media")
	ErrInvalidInstanceID   = fmt.Errorf("invalid instance ID")
)

Errors.

View Source
var ValidChannelTypes = map[string]bool{
	"whatsapp": true,
	"telegram": true,
	"discord":  true,
	"slack":    true,
}

ValidChannelTypes lists the known channel type slugs.

Functions

func ValidateInstanceID added in v1.16.0

func ValidateInstanceID(id string) error

ValidateInstanceID checks that id is safe to use as a channel instance identifier. An empty string is always valid (it represents the default instance). Named instances must be 1–64 characters of [a-zA-Z0-9_-].

Types

type AccessFilter added in v1.13.0

type AccessFilter interface {
	Channel

	// CanResponse checks if the sender is allowed to interact with the bot.
	// Returns (allowed, reason). If allowed is false, the message is ignored.
	CanResponse(msg *IncomingMessage) (allowed bool, reason string)
}

AccessFilter extends Channel with access control capabilities. Channels that implement this filter their own messages before sending to the assistant.

type AutoReadConfigurable added in v1.13.0

type AutoReadConfigurable interface {
	Channel

	// AutoReadEnabled returns true if the channel should automatically mark
	// messages as read after passing access control and policy checks.
	AutoReadEnabled() bool

	// SetAutoRead enables or disables auto-read behavior.
	SetAutoRead(enabled bool)
}

AutoReadConfigurable extends Channel with AutoRead configuration access. Channels that support configurable auto-read behavior should implement this.

type Channel

type Channel interface {
	// Name returns the channel identifier (e.g. "whatsapp", "discord").
	Name() string

	// Connect establishes the connection to the messaging platform.
	Connect(ctx context.Context) error

	// Disconnect gracefully closes the connection.
	Disconnect() error

	// Send sends a message to the specified recipient.
	Send(ctx context.Context, to string, message *OutgoingMessage) error

	// Receive returns a Go channel that emits incoming messages.
	Receive() <-chan *IncomingMessage

	// IsConnected returns true if the channel is connected.
	IsConnected() bool

	// Health returns the channel health status.
	Health() HealthStatus
}

Channel defines the interface that every communication channel must implement.

type ChannelConfig

type ChannelConfig struct {
	Enabled        bool   `yaml:"enabled"`
	Trigger        string `yaml:"trigger"`
	MaxRetries     int    `yaml:"max_retries"`
	RetryBackoffMs int    `yaml:"retry_backoff_ms"`
}

ChannelConfig contains common configuration for all channels.

type ContactInfo

type ContactInfo struct {
	DisplayName string
	VCard       string
	Phone       string
}

ContactInfo contains shared contact data.

type GroupFilter added in v1.13.0

type GroupFilter interface {
	Channel

	// ShouldRespond checks if the bot should respond to a group message.
	// Returns true if the message matches the group's activation policy.
	ShouldRespond(msg *IncomingMessage, trigger string) bool
}

GroupFilter extends Channel with group-specific policies. Channels that implement this filter group messages based on activation modes.

type GroupPolicyConfig added in v1.13.0

type GroupPolicyConfig struct {
	ID           string   `yaml:"id"`
	Name         string   `yaml:"name"`
	Policy       string   `yaml:"policy"`
	Policies     []string `yaml:"policies,omitempty"`
	Keywords     []string `yaml:"keywords,omitempty"`
	AllowedUsers []string `yaml:"allowed_users,omitempty"`
	Workspace    string   `yaml:"workspace,omitempty"`
}

GroupPolicyConfig defines policy for a specific group (for interface/cross-package use).

type HealthStatus

type HealthStatus struct {
	Connected     bool
	LastMessageAt time.Time
	ErrorCount    int
	LatencyMs     int64
	Details       map[string]any
}

HealthStatus represents the health state of a channel.

type IncomingMessage

type IncomingMessage struct {
	// ID is the unique message identifier in the source channel.
	ID string

	// Channel identifies the source channel (e.g. "whatsapp").
	Channel string

	// From is the sender identifier on the platform.
	From string

	// FromName is the sender display name (if available).
	FromName string

	// ChatID is the group or DM identifier.
	ChatID string

	// IsGroup indicates whether the message is from a group chat.
	IsGroup bool

	// Type is the message content type.
	Type MessageType

	// Content is the text content of the message.
	Content string

	// Timestamp is when the message was sent.
	Timestamp time.Time

	// ReplyTo contains the ID of the message being replied to.
	ReplyTo string

	// QuotedContent is the text of the quoted message (if replying).
	QuotedContent string

	// Mentions contains JIDs of users mentioned in the message (for groups).
	Mentions []string

	// Media contains media attachment details (if any).
	Media *MediaInfo

	// Location contains location data (if MessageLocation).
	Location *LocationInfo

	// Contact contains contact data (if MessageContact).
	Contact *ContactInfo

	// Reaction contains reaction data (if MessageReaction).
	Reaction *ReactionInfo

	// Metadata contains additional channel-specific data.
	Metadata map[string]any
}

IncomingMessage represents a message received from any channel.

type InstanceAware added in v1.16.0

type InstanceAware interface {
	// InstanceID returns the instance identifier ("" for default, e.g. "business" for named).
	InstanceID() string

	// BaseType returns the channel type without instance suffix (e.g. "whatsapp").
	BaseType() string
}

InstanceAware is an optional interface for channels that support multiple instances of the same type (e.g., two WhatsApp accounts). Channels that implement this return a non-empty InstanceID for named instances, while the default instance returns "".

type LocationInfo

type LocationInfo struct {
	Latitude  float64
	Longitude float64
	Name      string
	Address   string
	URL       string
	AccuracyM uint32
}

LocationInfo contains location coordinates.

type Manager

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

Manager orchestrates multiple communication channels, aggregating incoming messages into a single stream and routing responses.

func NewManager

func NewManager(logger *slog.Logger) *Manager

NewManager creates a new channel manager.

func (*Manager) Channel

func (m *Manager) Channel(name string) (Channel, bool)

Channel returns a specific channel by name.

func (*Manager) ChannelStatus

func (m *Manager) ChannelStatus(name string) (HealthStatus, error)

ChannelStatus returns health status for a specific channel.

func (*Manager) ChannelsByType added in v1.16.0

func (m *Manager) ChannelsByType(baseType string) []Channel

ChannelsByType returns all channels whose base type matches. For instance-aware channels, this matches on BaseType(); for others, it matches on Name() equality or Name() having the given prefix followed by ":".

func (*Manager) ConnectChannel

func (m *Manager) ConnectChannel(name string) error

ConnectChannel connects a specific channel by name. Returns error if channel not found or connection fails.

func (*Manager) DisconnectChannel

func (m *Manager) DisconnectChannel(name string) error

DisconnectChannel disconnects a specific channel by name.

func (*Manager) HasChannels

func (m *Manager) HasChannels() bool

HasChannels returns true if at least one channel is registered.

func (*Manager) HealthAll

func (m *Manager) HealthAll() map[string]HealthStatus

HealthAll returns health status for all registered channels.

func (*Manager) IsBotMessage added in v1.16.0

func (m *Manager) IsBotMessage(channelName, chatID, messageID string) bool

IsBotMessage checks if the given message was sent by the bot on the specified channel. Returns false if the channel doesn't implement SentMessageTracker.

func (*Manager) ListChannels

func (m *Manager) ListChannels() []string

ListChannels returns the names of all registered channels.

func (*Manager) MarkRead

func (m *Manager) MarkRead(ctx context.Context, channelName, chatID string, messageIDs []string)

MarkRead marks messages as read on the specified channel. Silently does nothing if the channel doesn't support presence.

func (*Manager) Messages

func (m *Manager) Messages() <-chan *IncomingMessage

Messages returns the aggregated message stream from all channels.

func (*Manager) Register

func (m *Manager) Register(ch Channel) error

Register adds a channel. Must be called before Start.

func (*Manager) RegisterAndConnect added in v1.16.0

func (m *Manager) RegisterAndConnect(ch Channel) error

RegisterAndConnect registers a new channel and immediately connects it. Use this to add channels at runtime after the manager has started (e.g., when a user configures a token via the Web UI). Returns error if the channel is already registered, manager is not started, or connection fails (the channel is still registered on connect failure).

func (*Manager) Send

func (m *Manager) Send(ctx context.Context, channelName, to string, msg *OutgoingMessage) error

Send sends a message through the specified channel.

func (*Manager) SendMedia

func (m *Manager) SendMedia(ctx context.Context, channelName, to string, media *MediaMessage) error

SendMedia sends a media message through the specified channel. Returns ErrMediaNotSupported if the channel doesn't support media.

func (*Manager) SendReaction

func (m *Manager) SendReaction(ctx context.Context, channelName, chatID, messageID, emoji string)

SendReaction sends an emoji reaction to a message on the specified channel. Silently does nothing if the channel doesn't support reactions.

func (*Manager) SendTyping

func (m *Manager) SendTyping(ctx context.Context, channelName, to string)

SendTyping sends a typing indicator on the specified channel. Silently does nothing if the channel doesn't support presence.

func (*Manager) Start

func (m *Manager) Start(ctx context.Context) error

Start connects all registered channels and begins listening for messages. Channels that fail to connect are logged but don't block others. The listen goroutine is started for ALL channels (even failed ones), so reconnections via web UI or background retries deliver messages.

func (*Manager) Stop

func (m *Manager) Stop()

Stop gracefully disconnects all channels.

func (*Manager) UnregisterChannel added in v1.16.0

func (m *Manager) UnregisterChannel(name string) error

UnregisterChannel removes a channel by name. If the channel is connected, it is disconnected first. Use this for runtime instance deletion.

type MediaAttachment added in v1.8.0

type MediaAttachment struct {
	// MediaID is the stored media identifier.
	MediaID string

	// Type is the media type (for convenience).
	Type MessageType

	// Caption is the text accompanying the media.
	Caption string
}

MediaAttachment references stored media for sending.

type MediaChannel

type MediaChannel interface {
	Channel

	// SendMedia sends a media message (image, audio, video, document).
	SendMedia(ctx context.Context, to string, media *MediaMessage) error

	// DownloadMedia downloads media from an incoming message.
	// Returns the raw bytes and MIME type.
	DownloadMedia(ctx context.Context, msg *IncomingMessage) ([]byte, string, error)
}

MediaChannel extends Channel with media capabilities. Channels that support media (images, audio, video, documents) should implement this interface.

type MediaInfo

type MediaInfo struct {
	// Type is the media type.
	Type MessageType

	// MimeType is the MIME type of the media.
	MimeType string

	// Filename is the original filename (for documents).
	Filename string

	// FileSize is the size in bytes.
	FileSize uint64

	// Caption is the media caption text.
	Caption string

	// Duration is the duration in seconds (audio/video).
	Duration uint32

	// Width is the width in pixels (images/video).
	Width uint32

	// Height is the height in pixels (images/video).
	Height uint32

	// URL is a direct download URL (if available).
	URL string

	// DirectPath is the platform-specific media path (for whatsapp).
	DirectPath string

	// MediaKey is the encryption key for the media (for whatsapp).
	MediaKey []byte

	// FileSHA256 is the SHA256 hash of the file.
	FileSHA256 []byte

	// FileEncSHA256 is the SHA256 hash of the encrypted file.
	FileEncSHA256 []byte
}

MediaInfo describes media attached to an incoming message.

type MediaMessage

type MediaMessage struct {
	// Type is the media type (image, audio, video, document, sticker).
	Type MessageType

	// Data is the raw media bytes. Either Data or URL must be set.
	Data []byte

	// URL is a URL to the media file. Either Data or URL must be set.
	URL string

	// MimeType is the MIME type (e.g. "image/jpeg", "audio/ogg").
	MimeType string

	// Filename is the original filename (for documents).
	Filename string

	// Caption is the text caption accompanying the media.
	Caption string

	// Duration is the duration in seconds (for audio/video).
	Duration uint32

	// Width is the media width in pixels (for images/video).
	Width uint32

	// Height is the media height in pixels (for images/video).
	Height uint32

	// ReplyTo contains the ID of the message to reply to.
	ReplyTo string
}

MediaMessage represents a media file to be sent.

type MessageType

type MessageType string

MessageType identifies the kind of message content.

const (
	MessageText      MessageType = "text"
	MessageImage     MessageType = "image"
	MessageAudio     MessageType = "audio"
	MessageVideo     MessageType = "video"
	MessageDocument  MessageType = "document"
	MessageSticker   MessageType = "sticker"
	MessageLocation  MessageType = "location"
	MessageContact   MessageType = "contact"
	MessageReaction  MessageType = "reaction"
	MessageVideoNote MessageType = "video_note"
)

type OutgoingMessage

type OutgoingMessage struct {
	// Content is the text content of the message.
	Content string

	// ReplyTo contains the ID of the message to reply to.
	ReplyTo string

	// Attachments contains media attachments to send with the message.
	Attachments []*MediaAttachment

	// EditMessageID, if set, indicates this is an edit of an existing message
	// rather than a new message. The channel should update the original message.
	EditMessageID string

	// IsReasoning indicates this message contains internal reasoning/thinking
	// that should not be sent to end users on certain channels.
	IsReasoning bool

	// Metadata contains additional channel-specific data.
	Metadata map[string]any
}

OutgoingMessage represents a message to be sent through a channel.

type PresenceChannel

type PresenceChannel interface {
	Channel

	// SendTyping sends a "typing..." indicator to the recipient.
	SendTyping(ctx context.Context, to string) error

	// SendPresence updates the bot's presence status.
	SendPresence(ctx context.Context, available bool) error

	// MarkRead marks a message as read.
	MarkRead(ctx context.Context, chatID string, messageIDs []string) error
}

PresenceChannel extends Channel with typing/presence indicators.

type ReactionChannel

type ReactionChannel interface {
	Channel

	// SendReaction sends a reaction emoji to a specific message.
	SendReaction(ctx context.Context, chatID, messageID, emoji string) error
}

ReactionChannel extends Channel with message reaction support.

type ReactionInfo

type ReactionInfo struct {
	Emoji     string
	MessageID string // The message being reacted to.
	From      string
	Remove    bool // True if the reaction is being removed.
}

ReactionInfo contains reaction emoji data.

type SentMessageTracker added in v1.16.0

type SentMessageTracker interface {
	IsBotMessage(chatID, messageID string) bool
}

SentMessageTracker tracks messages sent by the bot for reply detection. Channels that implement this can identify whether a given message was sent by the bot, enabling accurate reply-to-bot detection.

type WhatsAppAccessManager added in v1.13.0

type WhatsAppAccessManager interface {
	// Access control
	GetAccessConfig() any
	GrantAccess(jid, level string)
	RevokeAccess(jid string)
	ReplaceAccessList(owners, admins, allowedUsers, blockedUsers []string, defaultPolicy, pendingMessage string)
	BlockUser(jid string)
	UnblockUser(jid string)
	SetDefaultPolicy(policy string)

	// Group policies
	GetGroupPolicies() any
	SetGroupPolicy(groupJID string, policy any)
	SetGroupDefaultPolicy(policy string)
	GetJoinedGroups() ([]WhatsAppJoinedGroup, error)
	ListGroupPoliciesForConfig() []GroupPolicyConfig

	// Configuration
	SetAutoRead(enabled bool)
	SetSendTyping(enabled bool)
	SetTrigger(trigger string)
}

WhatsAppAccessManager provides access control and group policy management for WhatsApp channels. This interface allows the API layer to manage access control without using reflection.

type WhatsAppJoinedGroup added in v1.13.0

type WhatsAppJoinedGroup struct {
	JID  string
	Name string
}

WhatsAppJoinedGroup represents a WhatsApp group the bot is part of.

Directories

Path Synopsis
Package discord - components.go provides reusable interactive component handling for Discord (buttons, select menus) with registration, TTL-based cleanup, AllowedUsers restriction, and Reusable behavior.
Package discord - components.go provides reusable interactive component handling for Discord (buttons, select menus) with registration, TTL-based cleanup, AllowedUsers restriction, and Reusable behavior.
Package slack implements the Slack channel for DevClaw using the Slack Web API and Socket Mode for real-time events — no external dependencies beyond HTTP.
Package slack implements the Slack channel for DevClaw using the Slack Web API and Socket Mode for real-time events — no external dependencies beyond HTTP.
Package telegram – errors.go defines structured error types for the Telegram Bot API, enabling callers to classify and handle API failures.
Package telegram – errors.go defines structured error types for the Telegram Bot API, enabling callers to classify and handle API failures.
Package whatsapp – dedup.go provides a message deduplication cache to filter out duplicate messages during WhatsApp reconnections.
Package whatsapp – dedup.go provides a message deduplication cache to filter out duplicate messages during WhatsApp reconnections.

Jump to

Keyboard shortcuts

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