wechatbot

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 23, 2026 License: MIT Imports: 24 Imported by: 0

README

wechatbot-go

一个专注 Go 语言的微信 iLink Bot SDK,从多语言仓库中独立出来单独维护。

本项目基于 corespeed-io/wechatbot 的 Go SDK 部分,但已拆分 为独立的 Go-only 仓库并持续演进。原仓库同时维护 Node.js、Python、Rust 等版本,而这里只保留和 改进 Go 实现:更完整的协议对齐、状态持久化、登录流程增强以及可扩展的消息处理钩子。

如果你需要一个纯 Go、长期维护、面向实际运行场景的微信 Bot SDK,本仓库会更合适。


安装

go get github.com/Icatme/wechatbot-go

要求 Go 1.25+,零 CGO 依赖。

快速开始

package main

import (
    "context"
    "fmt"
    "os"
    "os/signal"
    "syscall"

    "github.com/Icatme/wechatbot-go"
)

func main() {
    ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
    defer cancel()

    bot := wechatbot.New(wechatbot.Options{
        OnQRURL: func(url string) { fmt.Println("请扫码:", url) },
    })

    if _, err := bot.Login(ctx, false); err != nil {
        fmt.Fprintln(os.Stderr, "登录失败:", err)
        os.Exit(1)
    }

    bot.OnMessage(func(msg *wechatbot.IncomingMessage) {
        _ = bot.Reply(ctx, msg, fmt.Sprintf("Echo: %s", msg.Text))
    })

    _ = bot.Run(ctx)
}

更多示例见 examples/

功能特性

  • 扫码登录 + 凭证持久化
  • 长轮询接收消息
  • 文本 / 图片 / 文件 / 视频 / 语音 收发
  • CDN 上传下载与 AES-128-ECB 解密
  • context_token 自动管理
  • 输入状态指示器
  • 会话过期(-14)自动恢复

文档

与原仓库的关系

  • 原仓库:github.com/corespeed-io/wechatbot(多语言 SDK 集合)
  • 本仓库:github.com/Icatme/wechatbot-go(独立维护的 Go-only 分支)
  • 协议与核心实现源自原仓库的 Go 部分,但已不再同步合并
  • 许可证:MIT(保留原项目版权声明)

贡献

由于这是独立维护的 Go-only fork,Issues 和 PR 请提交到本仓库。

License

MIT

Documentation

Overview

Package wechatbot provides a WeChat iLink Bot SDK for Go.

It handles QR login, long-poll message receiving, text/media sending, typing indicators, context_token management, and AES-128-ECB CDN crypto.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BaseInfo

type BaseInfo struct {
	ChannelVersion string `json:"channel_version"`
}

BaseInfo is included in every POST request body.

type Bot

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

Bot is the main WeChat bot client.

func New

func New(opts ...Options) *Bot

New creates a new Bot instance.

func (*Bot) Download

func (b *Bot) Download(ctx context.Context, msg *IncomingMessage) (*DownloadedMedia, error)

Download downloads media from an incoming message. Returns nil if the message has no media. Priority: image > file > video > voice.

func (*Bot) DownloadRaw

func (b *Bot) DownloadRaw(ctx context.Context, media *CDNMedia, aeskeyOverride string) ([]byte, error)

DownloadRaw downloads and decrypts a raw CDN media reference.

func (*Bot) Hooks added in v0.2.0

func (b *Bot) Hooks() *LifecycleHooks

Hooks returns the bot's lifecycle hook registry for extension.

func (*Bot) Login

func (b *Bot) Login(ctx context.Context, force bool) (*Credentials, error)

Login performs QR code login or loads stored credentials.

func (*Bot) OnMessage

func (b *Bot) OnMessage(handler MessageHandler)

OnMessage registers a message handler.

func (*Bot) Reply

func (b *Bot) Reply(ctx context.Context, msg *IncomingMessage, text string) error

Reply sends a text reply to an incoming message.

func (*Bot) ReplyContent

func (b *Bot) ReplyContent(ctx context.Context, msg *IncomingMessage, content SendContent) error

ReplyContent replies with any content type.

func (*Bot) Run

func (b *Bot) Run(ctx context.Context) error

Run starts the long-poll loop. Blocks until Stop() is called or context is cancelled.

func (*Bot) Send

func (b *Bot) Send(ctx context.Context, userID, text string) error

Send sends a text message to a user (requires prior context_token).

func (*Bot) SendMedia

func (b *Bot) SendMedia(ctx context.Context, userID string, content SendContent) error

SendMedia sends any content type to a user.

func (*Bot) SendTyping

func (b *Bot) SendTyping(ctx context.Context, userID string) error

SendTyping shows the "typing..." indicator.

func (*Bot) SetLogger added in v0.2.0

func (b *Bot) SetLogger(fn func(level, msg string))

SetLogger replaces the default stderr logger with a custom implementation.

func (*Bot) SetStructuredLogger added in v0.2.1

func (b *Bot) SetStructuredLogger(l *botlog.Logger)

SetStructuredLogger replaces the default logger with a structured logger.

func (*Bot) Stop

func (b *Bot) Stop()

Stop gracefully stops the poll loop.

func (*Bot) StopTyping

func (b *Bot) StopTyping(ctx context.Context, userID string) error

StopTyping cancels the "typing..." indicator.

func (*Bot) Upload

func (b *Bot) Upload(ctx context.Context, data []byte, userID string, mediaType int) (*UploadResult, error)

Upload uploads data to WeChat CDN without sending a message.

func (*Bot) Use added in v0.2.0

func (b *Bot) Use(mw Middleware)

Use adds a middleware to the incoming message pipeline.

type CDNMedia

type CDNMedia struct {
	EncryptQueryParam string `json:"encrypt_query_param"`
	AESKey            string `json:"aes_key"`
	EncryptType       int    `json:"encrypt_type,omitempty"`
	// FullURL is the complete download URL returned by server; when set, use directly.
	FullURL string `json:"full_url,omitempty"`
}

CDNMedia references an encrypted file on the WeChat CDN.

type CommandFunc added in v0.2.0

type CommandFunc func(ctx context.Context, msg *IncomingMessage, args string) bool

CommandFunc is the signature for a slash command handler. ctx is the request context. msg is the incoming message. args is the command arguments (excluding the command itself). The returned bool indicates whether the command consumed the message.

type CommandRegistry added in v0.2.0

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

CommandRegistry registers and routes slash commands.

func NewCommandRegistry added in v0.2.0

func NewCommandRegistry(prefix string) *CommandRegistry

NewCommandRegistry creates a registry with the given command prefix. Use "/" for Discord-style slash commands or another prefix as needed.

func (*CommandRegistry) Handle added in v0.2.0

func (r *CommandRegistry) Handle(ctx context.Context, msg *IncomingMessage) bool

Handle inspects a message and dispatches to a registered command. It returns true if a command was found and handled.

func (*CommandRegistry) Names added in v0.2.0

func (r *CommandRegistry) Names() []string

Names returns all registered command names.

func (*CommandRegistry) Register added in v0.2.0

func (r *CommandRegistry) Register(name string, fn CommandFunc)

Register adds or replaces a command handler.

type ContentType

type ContentType string

ContentType is the primary type of an incoming message.

const (
	ContentText  ContentType = "text"
	ContentImage ContentType = "image"
	ContentVoice ContentType = "voice"
	ContentFile  ContentType = "file"
	ContentVideo ContentType = "video"
)

type Credentials

type Credentials struct {
	Token     string `json:"token"`
	BaseURL   string `json:"baseUrl"`
	AccountID string `json:"accountId"`
	UserID    string `json:"userId"`
	SavedAt   string `json:"savedAt,omitempty"`
}

Credentials holds login credentials.

type DownloadedMedia

type DownloadedMedia struct {
	Data     []byte
	Type     string // "image", "file", "video", "voice"
	FileName string
	Format   string // "silk" for voice
}

DownloadedMedia is the result of downloading media from a message.

type FileContent

type FileContent struct {
	Media    *CDNMedia
	FileName string
	MD5      string
	Size     int64
}

FileContent holds parsed file data.

type FileItem

type FileItem struct {
	Media    *CDNMedia `json:"media,omitempty"`
	FileName string    `json:"file_name,omitempty"`
	MD5      string    `json:"md5,omitempty"`
	Len      string    `json:"len,omitempty"`
}

FileItem holds file content.

type HookFunc added in v0.2.0

type HookFunc[T any] func(payload T) error

HookFunc is called at specific lifecycle points. Returning an error stops further processing of that hook chain.

type HookRegistry added in v0.2.0

type HookRegistry[T any] struct {
	// contains filtered or unexported fields
}

HookRegistry manages named hooks for bot lifecycle events.

func (*HookRegistry[T]) Register added in v0.2.0

func (r *HookRegistry[T]) Register(hook HookFunc[T])

Register adds a hook to the registry.

func (*HookRegistry[T]) Run added in v0.2.0

func (r *HookRegistry[T]) Run(payload T) error

Run executes all registered hooks in registration order.

type ImageContent

type ImageContent struct {
	Media      *CDNMedia
	ThumbMedia *CDNMedia
	AESKey     string
	URL        string
	Width      int
	Height     int
}

ImageContent holds parsed image data from a message.

type ImageItem

type ImageItem struct {
	Media       *CDNMedia `json:"media,omitempty"`
	ThumbMedia  *CDNMedia `json:"thumb_media,omitempty"`
	AESKey      string    `json:"aeskey,omitempty"`
	URL         string    `json:"url,omitempty"`
	MidSize     int64     `json:"mid_size,omitempty"`
	ThumbSize   int64     `json:"thumb_size,omitempty"`
	ThumbWidth  int       `json:"thumb_width,omitempty"`
	ThumbHeight int       `json:"thumb_height,omitempty"`
	HDSize      int64     `json:"hd_size,omitempty"`
}

ImageItem holds image content and CDN references.

type IncomingMessage

type IncomingMessage struct {
	UserID        string
	Text          string
	Type          ContentType
	Timestamp     time.Time
	Images        []ImageContent
	Voices        []VoiceContent
	Files         []FileContent
	Videos        []VideoContent
	QuotedMessage *QuotedMessage
	Raw           *WireMessage
	ContextToken  string // internal, managed by SDK
}

IncomingMessage is a parsed, user-friendly representation.

type LifecycleHooks added in v0.2.0

type LifecycleHooks struct {
	// BeforeLogin runs after QR/login starts but before credentials are finalized.
	BeforeLogin HookRegistry[*Credentials]
	// AfterLogin runs after credentials are loaded or created.
	AfterLogin HookRegistry[*Credentials]
	// OnError runs when the bot encounters a non-fatal runtime error.
	OnError HookRegistry[error]
	// BeforeSend runs before a message is sent; mutate payload to change content.
	BeforeSend HookRegistry[*SendContent]
	// AfterReceive runs after a message is parsed and before handlers run.
	AfterReceive HookRegistry[*IncomingMessage]
}

LifecycleHooks group all available bot hooks.

type MediaType

type MediaType int

MediaType is used in upload requests.

const (
	MediaImage MediaType = 1
	MediaVideo MediaType = 2
	MediaFile  MediaType = 3
	MediaVoice MediaType = 4
)

type MessageHandler

type MessageHandler func(msg *IncomingMessage)

MessageHandler is called for each incoming user message.

type MessageItem

type MessageItem struct {
	Type      MessageItemType `json:"type"`
	TextItem  *TextItem       `json:"text_item,omitempty"`
	ImageItem *ImageItem      `json:"image_item,omitempty"`
	VoiceItem *VoiceItem      `json:"voice_item,omitempty"`
	FileItem  *FileItem       `json:"file_item,omitempty"`
	VideoItem *VideoItem      `json:"video_item,omitempty"`
	RefMsg    *RefMessage     `json:"ref_msg,omitempty"`
}

MessageItem is a single content item within a message.

type MessageItemType

type MessageItemType int

MessageItemType indicates the content type of a message item.

const (
	ItemText  MessageItemType = 1
	ItemImage MessageItemType = 2
	ItemVoice MessageItemType = 3
	ItemFile  MessageItemType = 4
	ItemVideo MessageItemType = 5
)

type MessageState

type MessageState int

MessageState indicates the message delivery state.

const (
	MessageStateNew        MessageState = 0
	MessageStateGenerating MessageState = 1
	MessageStateFinish     MessageState = 2
)

type MessageType

type MessageType int

MessageType indicates who sent the message.

const (
	MessageTypeUser MessageType = 1
	MessageTypeBot  MessageType = 2
)

type Middleware added in v0.2.0

type Middleware func(msg *IncomingMessage) bool

Middleware intercepts an incoming message and decides whether to pass it along. Return false to stop processing the message (the message is dropped).

type Options

type Options struct {
	BaseURL          string
	AccountID        string // optional account identifier for multi-bot isolation
	CredPath         string
	ContextTokenPath string
	CursorPath       string
	BotAgent         string // UA-style, e.g. "MyBot/1.2.0"
	RouteTag         string // sent as SKRouteTag header
	StripMarkdown    bool   // strip markdown from outbound text
	NotifyErrors     bool   // automatically notify user on send failure
	LogLevel         string // "debug", "info", "warn", "error", "silent"
	Logger           *botlog.Logger
	OnQRURL          func(url string)
	OnScanned        func()
	OnExpired        func()
	OnVerifyCode     func() (string, error)
	OnError          func(err error)
}

Options configures a Bot instance.

type QuotedMessage

type QuotedMessage struct {
	Title string
	Text  string
	Type  ContentType
}

QuotedMessage represents a referenced message.

type RefMessage

type RefMessage struct {
	Title       string       `json:"title,omitempty"`
	MessageItem *MessageItem `json:"message_item,omitempty"`
}

RefMessage represents a quoted/referenced message.

type SendContent

type SendContent struct {
	Text     string
	Image    []byte
	Video    []byte
	File     []byte
	FileName string
	Caption  string
	ImageURL string
	VideoURL string
	FileURL  string
}

SendContent describes what to send. Use one of:

func SendFile

func SendFile(data []byte, fileName string) SendContent

SendFile creates a file SendContent.

func SendFileURL added in v0.2.0

func SendFileURL(url, fileName string) SendContent

SendFileURL creates a file SendContent from a remote URL.

func SendImage

func SendImage(data []byte) SendContent

SendImage creates an image SendContent.

func SendImageURL added in v0.2.0

func SendImageURL(url string) SendContent

SendImageURL creates an image SendContent from a remote URL.

func SendText

func SendText(text string) SendContent

SendText creates a text SendContent.

func SendVideo

func SendVideo(data []byte) SendContent

SendVideo creates a video SendContent.

func SendVideoURL added in v0.2.0

func SendVideoURL(url string) SendContent

SendVideoURL creates a video SendContent from a remote URL.

type TextItem

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

TextItem holds text content.

type UploadResult

type UploadResult struct {
	Media             CDNMedia
	ThumbMedia        CDNMedia
	AESKey            []byte
	EncryptedFileSize int
}

UploadResult is the result of uploading media to CDN.

type VideoContent

type VideoContent struct {
	Media      *CDNMedia
	ThumbMedia *CDNMedia
	DurationMs int
	Width      int
	Height     int
}

VideoContent holds parsed video data.

type VideoItem

type VideoItem struct {
	Media      *CDNMedia `json:"media,omitempty"`
	VideoSize  int64     `json:"video_size,omitempty"`
	PlayLength int       `json:"play_length,omitempty"`
	ThumbMedia *CDNMedia `json:"thumb_media,omitempty"`
}

VideoItem holds video content.

type VoiceContent

type VoiceContent struct {
	Media      *CDNMedia
	Text       string
	DurationMs int
	EncodeType int
}

VoiceContent holds parsed voice data.

type VoiceItem

type VoiceItem struct {
	Media      *CDNMedia `json:"media,omitempty"`
	EncodeType int       `json:"encode_type,omitempty"`
	Text       string    `json:"text,omitempty"`
	Playtime   int       `json:"playtime,omitempty"`
}

VoiceItem holds voice content.

type WireMessage

type WireMessage struct {
	Seq          int64         `json:"seq,omitempty"`
	MessageID    int64         `json:"message_id,omitempty"`
	FromUserID   string        `json:"from_user_id"`
	ToUserID     string        `json:"to_user_id"`
	ClientID     string        `json:"client_id"`
	CreateTimeMs int64         `json:"create_time_ms"`
	MessageType  MessageType   `json:"message_type"`
	MessageState MessageState  `json:"message_state"`
	ContextToken string        `json:"context_token"`
	ItemList     []MessageItem `json:"item_list"`
}

WireMessage is the raw message from the iLink API.

Directories

Path Synopsis
examples
echo-bot command
Echo bot example — receives messages and replies with "Echo: <text>".
Echo bot example — receives messages and replies with "Echo: <text>".
internal
auth
Package auth handles QR code login and credential persistence.
Package auth handles QR code login and credential persistence.
config
Package config provides cached access to WeChat iLink bot config.
Package config provides cached access to WeChat iLink bot config.
crypto
Package crypto provides AES-128-ECB encryption/decryption for WeChat CDN media.
Package crypto provides AES-128-ECB encryption/decryption for WeChat CDN media.
markdown
Package markdown provides text normalization for WeChat messages.
Package markdown provides text normalization for WeChat messages.
protocol
Package protocol implements the raw iLink Bot API HTTP calls.
Package protocol implements the raw iLink Bot API HTTP calls.
remote
Package remote downloads media from HTTP(S) URLs for WeChat upload.
Package remote downloads media from HTTP(S) URLs for WeChat upload.
session
Package session provides session lifecycle guards for the WeChat iLink bot.
Package session provides session lifecycle guards for the WeChat iLink bot.
store
Package store provides persistent state storage for the bot.
Package store provides persistent state storage for the bot.
thumb
Package thumb generates JPEG thumbnails for images and videos.
Package thumb generates JPEG thumbnails for images and videos.
Package log provides structured logging with automatic token redaction.
Package log provides structured logging with automatic token redaction.

Jump to

Keyboard shortcuts

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