The Python SDK is async-first, using aiohttp + asyncio. Decorator-style message handlers, dataclass types, 17 tests. Requires Python β₯ 3.9.
Install
pip install wechatbot-sdk
Quick start
from wechatbot import WeChatBot bot = WeChatBot() @bot.on_message async def handle(msg): await bot.send_typing(msg.user_id) await bot.reply(msg, f"Echo: {msg.text}") bot.run() # login + start in one call
Or with full async control:
import asyncio from wechatbot import WeChatBot async def main(): bot = WeChatBot() await bot.login() @bot.on_message async def handle(msg): await bot.reply(msg, f"Echo: {msg.text}") await bot.start() asyncio.run(main())
Configuration
bot = WeChatBot( base_url="https://ilinkai.weixin.qq.com", cred_path="~/.wechatbot/credentials.json", on_qr_url=lambda url: print(f"Scan: {url}"), on_scanned=lambda: print("Scanned!"), on_expired=lambda: print("Expired..."), on_error=lambda err: print(f"Error: {err}"), )
Message handling
@bot.on_message async def handle(msg): print(f"[{msg.type}] {msg.user_id}: {msg.text}") for img in msg.images: print(f" Image: {img.url}") for voice in msg.voices: print(f" Voice: {voice.text} ({voice.duration_ms}ms)") for file in msg.files: print(f" File: {file.file_name} ({file.size} bytes)") if msg.quoted_message: print(f" Quoted: {msg.quoted_message.title}")
Sending
# Reply (auto context_token + stop typing) await bot.reply(msg, "Hello!") # Send to user (needs prior context_token) await bot.send(user_id, "Proactive message") # Typing indicator await bot.send_typing(user_id) await bot.stop_typing(user_id)
AES-128-ECB crypto
from wechatbot import ( generate_aes_key, encrypt_aes_ecb, decrypt_aes_ecb, decode_aes_key ) key = generate_aes_key() ct = encrypt_aes_ecb(b"Hello", key) pt = decrypt_aes_ecb(ct, key) # Decode protocol key (all 3 formats) k = decode_aes_key("ABEiM0RVZneImaq7zN3u/w==") # base64(raw) k = decode_aes_key("00112233445566778899aabbccddeeff") # hex
Types (dataclasses)
@dataclass class IncomingMessage: user_id: str text: str type: Literal["text", "image", "voice", "file", "video"] timestamp: datetime images: list[ImageContent] voices: list[VoiceContent] files: list[FileContent] videos: list[VideoContent] quoted_message: QuotedMessage | None raw: dict
Error hierarchy: WeChatBotError β ApiError, AuthError, NoContextError, MediaError