bot

package
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2026 License: MIT Imports: 33 Imported by: 0

Documentation

Overview

Package bot provides bot adapters for various IM platforms.

This package implements a unified interface for connecting to multiple chat platforms, including Discord, Telegram, Feishu (Lark), and DingTalk. Each adapter handles platform-specific connection logic, message formatting, and communication patterns.

Supported Platforms

  • Discord: WebSocket connection with real-time message handling
  • Telegram: Long polling for message updates
  • Feishu/Lark: WebSocket long connection for enterprise messaging
  • DingTalk: WebSocket long connection for enterprise messaging

Usage

To use a bot adapter:

  1. Create a bot instance using the New* function for your platform
  2. Call Start() with a message handler callback
  3. Send messages using SendMessage()
  4. Call Stop() when shutting down

Example:

discordBot := bot.NewDiscordBot(token, channelID)
err := discordBot.Start(func(msg bot.BotMessage) {
    fmt.Printf("Received: %s\n", msg.Content)
})
if err != nil {
    log.Fatal(err)
}
discordBot.SendMessage(channelID, "Hello, world!")
discordBot.Stop()

Thread Safety

All bot adapters are thread-safe and use internal mutexes to protect shared state. The message handler callback may be called concurrently from multiple goroutines.

Index

Constants

View Source
const (
	QQTokenURL   = "https://bots.qq.com/app/getAppAccessToken"
	QQAPIBase    = "https://api.sgroup.qq.com"
	QQGatewayURL = QQAPIBase + "/gateway"
)

QQ Bot API endpoints

View Source
const (
	OPDispatch       = 0  // Event dispatch
	OPHeartbeat      = 1  // Heartbeat
	OPIdentify       = 2  // Identify
	OPResume         = 6  // Resume
	OPReconnect      = 7  // Reconnect request
	OPInvalidSession = 9  // Invalid session
	OPHello          = 10 // Hello
	OPHeartbeatAck   = 11 // Heartbeat acknowledgement
)

WebSocket OP codes (https://bots.qq.com/docs/gateway/gateway-events)

View Source
const (
	MessageTypeUser = 1
	MessageTypeBot  = 2
)
View Source
const (
	MessageStateNew        = 0
	MessageStateGenerating = 1
	MessageStateFinish     = 2
)
View Source
const (
	MessageItemTypeText  = 1
	MessageItemTypeImage = 2
	MessageItemTypeVoice = 3
	MessageItemTypeFile  = 4
	MessageItemTypeVideo = 5
)
View Source
const (
	QRStatusWait      = "wait"
	QRStatusScaned    = "scaned"
	QRStatusConfirmed = "confirmed"
	QRStatusExpired   = "expired"
)
View Source
const (
	DefaultBaseURL        = "https://ilinkai.weixin.qq.com"
	DefaultBaseVersion    = "1.0.0"
	QRCodePollInterval    = 2 * time.Second
	APITimeout            = 15 * time.Second
	MaxMessageLength      = 2000
	MaxChunkLength        = 2000
	SessionExpiredErrCode = -14
)
View Source
const (
	IntentPublicMessages = 1 << 25 // Public message events (1 << 25)
)

Intents for subscribing to events

Variables

This section is empty.

Functions

func DefaultCredentialsPath added in v0.1.2

func DefaultCredentialsPath() string

Types

type ApiError added in v0.1.2

type ApiError struct {
	Status  int
	Code    int
	Message string
}

func (*ApiError) Error added in v0.1.2

func (e *ApiError) Error() string

func (*ApiError) IsSessionExpired added in v0.1.2

func (e *ApiError) IsSessionExpired() bool

type BotAdapter

type BotAdapter interface {
	// Start starts the bot, establishes connection and begins listening for messages
	Start(messageHandler func(BotMessage)) error

	// SendMessage sends a message to the IM platform
	// Adapter is responsible for:
	//   - Truncating to platform limits
	//   - Splitting long messages when necessary
	//   - Platform-specific formatting
	SendMessage(channel, message string) error

	// SupportsTypingIndicator returns true if the platform supports typing indicators
	SupportsTypingIndicator() bool

	// AddTypingIndicator adds a typing indicator to a message (if supported)
	// messageID is the ID of the user's message to react to
	// Returns true if successfully added
	AddTypingIndicator(messageID string) bool

	// RemoveTypingIndicator removes the typing indicator from a message
	RemoveTypingIndicator(messageID string) error

	// SetProxyManager sets the proxy manager for the bot
	SetProxyManager(mgr proxy.Manager)

	// Stop stops the bot and cleans up resources
	Stop() error
}

BotAdapter defines the interface for bot adapters

type BotMessage

type BotMessage struct {
	Platform  string // feishu/discord/telegram
	UserID    string // Unique user identifier (for permission control)
	Channel   string // Channel/session ID
	MessageID string // Message ID (for typing indicator)
	Content   string // Message content
	Timestamp time.Time
}

BotMessage represents a bot message structure

type C2CMessageData

type C2CMessageData struct {
	ID        string `json:"id"`
	Timestamp string `json:"timestamp"`
	Author    struct {
		UserOpenID string `json:"user_openid"`
	} `json:"author"`
	Content string `json:"content"`
}

C2CMessageData represents C2C (private chat) message data from WebSocket event

type Credentials added in v0.1.2

type Credentials struct {
	Token     string `json:"token"`
	BaseURL   string `json:"base_url"`
	AccountID string `json:"account_id"`
	UserID    string `json:"user_id"`
}

type DefaultTypingIndicator

type DefaultTypingIndicator struct{}

DefaultTypingIndicator provides default empty implementations for typing indicator methods This can be embedded in bot adapters that don't support typing indicators

func (*DefaultTypingIndicator) AddTypingIndicator

func (d *DefaultTypingIndicator) AddTypingIndicator(messageID string) bool

AddTypingIndicator does nothing (not supported by default)

func (*DefaultTypingIndicator) RemoveTypingIndicator

func (d *DefaultTypingIndicator) RemoveTypingIndicator(messageID string) error

RemoveTypingIndicator does nothing (not supported by default)

func (*DefaultTypingIndicator) SupportsTypingIndicator

func (d *DefaultTypingIndicator) SupportsTypingIndicator() bool

SupportsTypingIndicator returns false (not supported by default)

type DingTalkBot

type DingTalkBot struct {
	DefaultTypingIndicator
	// contains filtered or unexported fields
}

DingTalkBot implements BotAdapter interface for DingTalk using WebSocket long connection

func NewDingTalkBot

func NewDingTalkBot(clientID, clientSecret string) *DingTalkBot

NewDingTalkBot creates a new DingTalk bot instance

func (*DingTalkBot) GetMessageHandler

func (d *DingTalkBot) GetMessageHandler() func(BotMessage)

GetMessageHandler gets the message handler in a thread-safe manner

func (*DingTalkBot) SendMessage

func (d *DingTalkBot) SendMessage(conversationID, message string) error

SendMessage sends a message to a DingTalk conversation

func (*DingTalkBot) SetMessageHandler

func (d *DingTalkBot) SetMessageHandler(handler func(BotMessage))

SetMessageHandler sets the message handler in a thread-safe manner

func (*DingTalkBot) SetProxyManager

func (d *DingTalkBot) SetProxyManager(mgr proxy.Manager)

SetProxyManager sets the proxy manager for the DingTalk bot

func (*DingTalkBot) Start

func (d *DingTalkBot) Start(messageHandler func(BotMessage)) error

Start establishes WebSocket long connection to DingTalk and begins listening for messages

func (*DingTalkBot) Stop

func (d *DingTalkBot) Stop() error

Stop closes the DingTalk WebSocket connection and cleans up resources

type DiscordBot

type DiscordBot struct {
	DefaultTypingIndicator
	// contains filtered or unexported fields
}

DiscordBot implements BotAdapter interface for Discord

func NewDiscordBot

func NewDiscordBot(token, channelID string) *DiscordBot

NewDiscordBot creates a new Discord bot instance

func (*DiscordBot) GetMessageHandler

func (d *DiscordBot) GetMessageHandler() func(BotMessage)

GetMessageHandler gets the message handler in a thread-safe manner

func (*DiscordBot) SendMessage

func (d *DiscordBot) SendMessage(channel, message string) error

SendMessage sends a message to a Discord channel

func (*DiscordBot) SetMessageHandler

func (d *DiscordBot) SetMessageHandler(handler func(BotMessage))

SetMessageHandler sets the message handler in a thread-safe manner

func (*DiscordBot) SetProxyManager

func (d *DiscordBot) SetProxyManager(mgr proxy.Manager)

SetProxyManager sets the proxy manager for the Discord bot

func (*DiscordBot) Start

func (d *DiscordBot) Start(messageHandler func(BotMessage)) error

Start establishes connection to Discord and begins listening for messages

func (*DiscordBot) Stop

func (d *DiscordBot) Stop() error

Stop closes the Discord connection and cleans up resources

type DiscordMessage

type DiscordMessage interface {
	ID() string
}

DiscordMessage represents a Discord message for our interface

type DiscordSessionInterface

type DiscordSessionInterface interface {
	AddHandler(handler interface{}) func()
	Open() error
	Close() error
	ChannelMessageSend(channelID string, content string, options ...discordgo.RequestOption) (*discordgo.Message, error)
}

DiscordSessionInterface defines the interface we need from discordgo.Session This allows us to mock it in tests without depending on concrete types

type FeishuBot

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

FeishuBot implements BotAdapter interface for Feishu (Lark) using WebSocket long connection

func NewFeishuBot

func NewFeishuBot(appID, appSecret string) *FeishuBot

NewFeishuBot creates a new Feishu bot instance

func (*FeishuBot) AddTypingIndicator

func (f *FeishuBot) AddTypingIndicator(messageID string) bool

AddTypingIndicator adds a typing reaction to a message

func (*FeishuBot) GetMessageHandler

func (f *FeishuBot) GetMessageHandler() func(BotMessage)

GetMessageHandler gets the message handler in a thread-safe manner

func (*FeishuBot) RemoveTypingIndicator

func (f *FeishuBot) RemoveTypingIndicator(messageID string) error

RemoveTypingIndicator removes the typing reaction from a message

func (*FeishuBot) SendMessage

func (f *FeishuBot) SendMessage(chatID, message string) error

SendMessage sends a message to a Feishu chat

func (*FeishuBot) SetEncryptKey

func (f *FeishuBot) SetEncryptKey(key string)

SetEncryptKey sets the encryption key for event verification

func (*FeishuBot) SetMessageHandler

func (f *FeishuBot) SetMessageHandler(handler func(BotMessage))

SetMessageHandler sets the message handler in a thread-safe manner

func (*FeishuBot) SetProxyManager

func (f *FeishuBot) SetProxyManager(mgr proxy.Manager)

SetProxyManager sets the proxy manager for the Feishu bot

func (*FeishuBot) SetVerificationToken

func (f *FeishuBot) SetVerificationToken(token string)

SetVerificationToken sets the verification token for event verification

func (*FeishuBot) Start

func (f *FeishuBot) Start(messageHandler func(BotMessage)) error

Start establishes WebSocket long connection to Feishu and begins listening for messages

func (*FeishuBot) Stop

func (f *FeishuBot) Stop() error

Stop closes the Feishu WebSocket connection and cleans up resources

func (*FeishuBot) SupportsTypingIndicator

func (f *FeishuBot) SupportsTypingIndicator() bool

SupportsTypingIndicator returns true as Feishu supports message reactions

type GatewayPayload

type GatewayPayload struct {
	OP int         `json:"op"`
	D  interface{} `json:"d,omitempty"`
	S  *int        `json:"s,omitempty"`
	T  string      `json:"t,omitempty"`
}

GatewayPayload represents a WebSocket gateway message

type HelloData

type HelloData struct {
	HeartbeatInterval int `json:"heartbeat_interval"`
}

HelloData contains heartbeat_interval from OP Hello

type IdentifyData

type IdentifyData struct {
	Token   string `json:"token"`
	Intents int    `json:"intents"`
	Shard   []int  `json:"shard"`
}

IdentifyData contains identify payload

type QQBot

type QQBot struct {
	DefaultTypingIndicator
	// contains filtered or unexported fields
}

QQBot implements BotAdapter interface for QQ Bot Platform (QQ群机器人开放平台) Official API: https://bots.qq.com

func NewQQBot

func NewQQBot(appID, appSecret string) *QQBot

NewQQBot creates a new QQ bot instance

func (*QQBot) AddTypingIndicator

func (q *QQBot) AddTypingIndicator(messageID string) bool

AddTypingIndicator does nothing (not supported)

func (*QQBot) GetMessageHandler

func (q *QQBot) GetMessageHandler() func(BotMessage)

GetMessageHandler gets the message handler in a thread-safe manner

func (*QQBot) RemoveTypingIndicator

func (q *QQBot) RemoveTypingIndicator(messageID string) error

RemoveTypingIndicator does nothing (not supported)

func (*QQBot) SendMessage

func (q *QQBot) SendMessage(channel, message string) error

SendMessage sends a message to QQ (C2C private message)

func (*QQBot) SetMessageHandler

func (q *QQBot) SetMessageHandler(handler func(BotMessage))

SetMessageHandler sets the message handler in a thread-safe manner

func (*QQBot) SetProxyManager

func (q *QQBot) SetProxyManager(mgr proxy.Manager)

SetProxyManager sets the proxy manager for the QQ bot

func (*QQBot) Start

func (q *QQBot) Start(messageHandler func(BotMessage)) error

Start establishes connection to QQ gateway and begins listening for messages

func (*QQBot) Stop

func (q *QQBot) Stop() error

Stop stops the QQ bot and cleans up resources

func (*QQBot) SupportsTypingIndicator

func (q *QQBot) SupportsTypingIndicator() bool

SupportsTypingIndicator returns false (QQ doesn't support typing indicators)

type QQGatewayResponse

type QQGatewayResponse struct {
	URL string `json:"url"`
}

QQGatewayResponse represents the gateway URL response

type QQTokenResponse

type QQTokenResponse struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   string `json:"expires_in"` // API returns as string
}

QQTokenResponse represents the token response from QQ API

type SendMessageRequest

type SendMessageRequest struct {
	Content string `json:"content"`
	MsgType int    `json:"msg_type"`
	MsgID   string `json:"msg_id,omitempty"`
	MsgSeq  int    `json:"msg_seq,omitempty"`
}

SendMessageRequest represents the request payload for sending messages

type SendMessageResponse

type SendMessageResponse struct {
	ID string `json:"id"`
}

SendMessageResponse represents the response from sending a message

type TelegramBot

type TelegramBot struct {
	DefaultTypingIndicator
	// contains filtered or unexported fields
}

TelegramBot implements BotAdapter interface for Telegram using long polling

func NewTelegramBot

func NewTelegramBot(token string) *TelegramBot

NewTelegramBot creates a new Telegram bot instance

func (*TelegramBot) GetMessageHandler

func (t *TelegramBot) GetMessageHandler() func(BotMessage)

GetMessageHandler gets the message handler in a thread-safe manner

func (*TelegramBot) SendMessage

func (t *TelegramBot) SendMessage(chatID, message string) error

SendMessage sends a message to a Telegram chat

func (*TelegramBot) SetMessageHandler

func (t *TelegramBot) SetMessageHandler(handler func(BotMessage))

SetMessageHandler sets the message handler in a thread-safe manner

func (*TelegramBot) SetProxyManager

func (t *TelegramBot) SetProxyManager(mgr proxy.Manager)

SetProxyManager sets the proxy manager for the Telegram bot

func (*TelegramBot) Start

func (t *TelegramBot) Start(messageHandler func(BotMessage)) error

Start establishes long polling connection to Telegram and begins listening for messages

func (*TelegramBot) Stop

func (t *TelegramBot) Stop() error

Stop closes the Telegram long polling connection and cleans up resources

type TextContent

type TextContent struct {
	Text string `json:"text"`
}

TextContent represents the JSON structure of Feishu text message content

type WeixinBot added in v0.1.2

type WeixinBot struct {
	DefaultTypingIndicator
	// contains filtered or unexported fields
}

func NewWeixinBot added in v0.1.2

func NewWeixinBot(baseURL, credentialsPath string) *WeixinBot

func (*WeixinBot) AddTypingIndicator added in v0.1.2

func (b *WeixinBot) AddTypingIndicator(messageID string) bool

func (*WeixinBot) RemoveTypingIndicator added in v0.1.2

func (b *WeixinBot) RemoveTypingIndicator(messageID string) error

func (*WeixinBot) SendMessage added in v0.1.2

func (b *WeixinBot) SendMessage(channel, message string) error

func (*WeixinBot) SetProxyManager added in v0.1.2

func (b *WeixinBot) SetProxyManager(mgr proxy.Manager)

func (*WeixinBot) Start added in v0.1.2

func (b *WeixinBot) Start(messageHandler func(BotMessage)) error

func (*WeixinBot) Stop added in v0.1.2

func (b *WeixinBot) Stop() error

Jump to

Keyboard shortcuts

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