{"id":50516077,"url":"https://github.com/lsongdev/wechatbot-go","last_synced_at":"2026-06-03T00:03:57.562Z","repository":{"id":346492967,"uuid":"1188581700","full_name":"lsongdev/wechatbot-go","owner":"lsongdev","description":"A Go SDK for the WeChat iLink Bot API (微信 iLink Bot API).","archived":false,"fork":false,"pushed_at":"2026-03-24T07:39:02.000Z","size":49,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-27T14:17:25.717Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lsongdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"lsongdev","patreon":"song940","open_collective":"song940","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://t.co/uiCATsCCP3"}},"created_at":"2026-03-22T09:38:55.000Z","updated_at":"2026-04-02T11:05:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lsongdev/wechatbot-go","commit_stats":null,"previous_names":["lsongdev/wxbot-go"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/lsongdev/wechatbot-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsongdev%2Fwechatbot-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsongdev%2Fwechatbot-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsongdev%2Fwechatbot-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsongdev%2Fwechatbot-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lsongdev","download_url":"https://codeload.github.com/lsongdev/wechatbot-go/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsongdev%2Fwechatbot-go/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33842011,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-03T00:03:56.080Z","updated_at":"2026-06-03T00:03:57.557Z","avatar_url":"https://github.com/lsongdev.png","language":"Go","funding_links":["https://github.com/sponsors/lsongdev","https://patreon.com/song940","https://opencollective.com/song940","https://t.co/uiCATsCCP3"],"categories":[],"sub_categories":[],"readme":"# WeChat Bot Go SDK\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/lsongdev/wechatbot-go.svg)](https://pkg.go.dev/github.com/lsongdev/wechatbot-go)\n[![Go Report Card](https://goreportcard.com/badge/github.com/lsongdev/wechatbot-go)](https://goreportcard.com/report/github.com/lsongdev/wechatbot-go)\n\nA Go SDK for the WeChat iLink Bot API (微信 iLink Bot API).\n\n## Features\n\n- ✅ QR Code Login - Scan to authenticate your bot\n- ✅ Message Long-Polling - Receive messages via `getupdates` API\n- ✅ Text Messages - Send and receive text messages\n- ✅ Media Support - Images, files, videos, and voice messages\n- ✅ Typing Indicators - Show \"typing...\" status to users\n- ✅ Auto Reconnection - Built-in retry logic with backoff\n- ✅ Context Management - Automatic `context_token` handling\n\n## Installation\n\n```bash\ngo get github.com/lsongdev/wechatbot-go\n```\n\n## Quick Start\n\n### Basic Echo Bot\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log\"\n\n    \"github.com/lsongdev/wechatbot-go/wechatbot\"\n)\n\nfunc main() {\n    // Load configuration from file\n    cfg := wechatbot.LoadConfig(\"config.json\")\n    \n    // Create bot instance\n    bot := wechatbot.NewBot(cfg)\n    ctx := context.Background()\n    \n    // Get QR code for login\n    qrcode, err := bot.GetBotQRCode()\n    if err != nil {\n        log.Fatal(err)\n    }\n    log.Println(\"Scan QR Code:\", qrcode.QRCodeImgContent)\n    \n    // Wait for user to scan and confirm\n    resp, err := bot.WaitingForLogin(ctx, qrcode.QRCode)\n    if err != nil {\n        log.Fatal(err)\n    }\n    \n    // Set the bot token after successful login\n    bot.Token = resp.BotToken\n    log.Println(\"Login successful:\", resp.ILinkBotID)\n    \n    // Start message listener\n    err = bot.Start(ctx, func(message *wechatbot.Message) {\n        log.Printf(\"Message from %s: %s\\n\", message.FromUserID, message.Text())\n        \n        // Create reply helper\n        response := bot.CreateReply(message)\n        \n        // Reply with text\n        response.Typing(wechatbot.Typing)\n        response.ReplyText(\"Echo: \" + message.Text())\n        response.Typing(wechatbot.CancelTyping)\n        \n        // Save config (token and sync buffer)\n        cfg.Save()\n    })\n    \n    log.Fatal(err)\n}\n```\n\n### Configuration\n\nCreate a `config.json` file:\n\n```json\n{\n  \"base_url\": \"https://ilinkai.weixin.qq.com\",\n  \"cdn_base_url\": \"https://novac2c.cdn.weixin.qq.com/c2c\",\n  \"token\": \"\",\n  \"updates_buf\": \"\"\n}\n```\n\nAfter first login, the `token` and `updates_buf` will be automatically saved.\n\n## Advanced Usage\n\n### Handling Images\n\n```go\nerr = bot.Start(ctx, func(message *wechatbot.Message) {\n    response := bot.CreateReply(message)\n    \n    // Check if message contains an image\n    if img := message.Image(); img != nil {\n        // Download the image\n        imageData, err := bot.DownloadMedia(img.Media)\n        if err != nil {\n            log.Printf(\"Failed to download image: %v\", err)\n            return\n        }\n        \n        // Reply with the same image\n        fileName := fmt.Sprintf(\"image_%d.jpg\", message.CreateTimeMs)\n        _, err = response.ReplyImage(fileName, imageData)\n        if err != nil {\n            log.Printf(\"Failed to reply image: %v\", err)\n            return\n        }\n    } else {\n        // Reply with text\n        response.ReplyText(message.Text())\n    }\n})\n```\n\n### Sending Files\n\n```go\n// Send a file\nfileData, _ := os.ReadFile(\"document.pdf\")\n_, err := bot.SendFile(contextToken, toUserID, \"document.pdf\", fileData)\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Sending Videos\n\n```go\n// Send a video with thumbnail\nvideoData, _ := os.ReadFile(\"video.mp4\")\nthumbData, _ := os.ReadFile(\"thumbnail.jpg\")\n_, err := bot.SendVideo(contextToken, toUserID, videoData, \"video.mp4\", thumbData)\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Typing Indicators\n\n```go\nresponse := bot.CreateReply(message)\n\n// Show typing indicator\nresponse.Typing(wechatbot.Typing)\n\n// Simulate typing delay\ntime.Sleep(2 * time.Second)\n\n// Send response\nresponse.ReplyText(\"Your message has been processed.\")\n\n// Cancel typing indicator\nresponse.Typing(wechatbot.CancelTyping)\n```\n\n## API Reference\n\n### Core Types\n\n#### `WeChatBot`\n\nThe main bot client.\n\n```go\nbot := wechatbot.NewBot(cfg)\n```\n\n#### `Config`\n\nBot configuration structure.\n\n```go\ntype Config struct {\n    BaseURL    string `json:\"base_url\"`\n    CDNBaseURL string `json:\"cdn_base_url\"`\n    Token      string `json:\"token\"`\n    UpdatesBuf string `json:\"updates_buf\"`\n}\n```\n\n### Message Types\n\n#### `Message`\n\nRepresents an incoming message.\n\n```go\ntype Message struct {\n    FromUserID   string\n    ToUserID     string\n    CreateTimeMs int64\n    MessageType  MessageType\n    ItemList     []MessageItem\n    ContextToken string\n    // ... other fields\n}\n```\n\nHelper methods:\n- `Text()` - Extract text content\n- `Image()` - Extract image item (returns `*ImageItem` or `nil`)\n\n#### `MessageItem`\n\nIndividual message components (text, image, file, video, voice).\n\n### Methods\n\n#### Authentication\n\n- `GetBotQRCode()` - Get QR code for login\n- `GetQRCodeStatus(qrcode string)` - Check QR code status\n- `WaitingForLogin(ctx context.Context, qrcode string)` - Wait for login confirmation\n- `Login(ctx context.Context, force bool)` - Complete login flow\n\n#### Message Handling\n\n- `Start(ctx context.Context, onMessage MessageHandler)` - Start message listener (blocking)\n- `GetUpdates(updateBuf string)` - Manual long-polling for messages\n- `SendMessage(message *Message)` - Send a raw message\n- `CreateReply(message *Message)` - Create reply helper\n\n#### Reply Helpers\n\n- `ReplyText(content string)` - Reply with text\n- `ReplyImage(fileName string, imageData []byte)` - Reply with image\n- `ReplyFile(fileName string, fileData []byte)` - Reply with file\n- `ReplyVideo(fileName string, videoData []byte, thumbData []byte)` - Reply with video\n- `Typing(status TypingStatus)` - Send typing indicator\n\n#### Media Operations\n\n- `DownloadMedia(media *CDNMedia)` - Download media from CDN\n- `UploadFile(mediaType, toUserID, fileName string, data []byte, noThumb bool)` - Upload file to CDN\n- `GetUploadURL(req *GetUploadURLReq)` - Get pre-signed upload URL\n\n## Protocol Details\n\nThis SDK implements the WeChat iLink Bot API protocol. Key characteristics:\n\n1. **QR Code Authentication** - Login via scanning QR code with WeChat\n2. **Long-Polling** - Messages received via `getupdates` endpoint (not WebSocket)\n3. **Context Token** - Every reply must include `context_token` from incoming message\n4. **CDN Media** - Files uploaded/downloaded via separate CDN endpoint\n\nFor detailed protocol specifications, see [`docs/protocol-spec.md`](docs/protocol-spec.md).\n\n## Error Handling\n\nThe SDK returns `WeChatBotError` for API errors:\n\n```go\ntype WeChatBotError struct {\n    ErrCode int    `json:\"errcode\"`\n    ErrMsg  string `json:\"errmsg\"`\n}\n```\n\nCommon error codes:\n- `-14` - Session expired, need to re-login\n- `-2` - Invalid parameters\n\n## Best Practices\n\n### Persistence\n\nAlways save the config after receiving new messages to preserve:\n- `token` - Bot authentication token\n- `updates_buf` - Message sync buffer for resuming after restart\n\n```go\ncfg.Save()\n```\n\n### Context Management\n\n- Never reuse `context_token` across different users\n- Cache `typing_ticket` per user to avoid repeated `getconfig` calls\n- Clear local state on `-14` (session expired) errors\n\n### Media Upload\n\n- Generate unique `filekey` for each upload (16-byte hex)\n- Calculate `filesize` as AES-128-ECB encrypted size with PKCS7 padding\n- Use `no_need_thumb: true` to skip thumbnail upload if not needed\n\n## Examples\n\nSee the [`examples/`](examples) directory for complete working examples.\n\n## License\n\nMIT License\n\n## Acknowledgments\n\n- Based on the WeChat iLink Bot API protocol\n- Inspired by official `@tencent-weixin/openclaw-weixin` implementation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flsongdev%2Fwechatbot-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flsongdev%2Fwechatbot-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flsongdev%2Fwechatbot-go/lists"}