@rurimeiko/zalo-channel
v1.0.13
Published
Zalo messaging integration for OpenClaw - Multi-account support with QR/cookie login, message sending, and event handling (TypeScript)
Downloads
1,311
Maintainers
Readme
OpenClaw Zalo Channel Plugin (TypeScript)
Zalo messaging integration for OpenClaw Gateway. Based on MultiZlogin architecture with support for multiple accounts, proxy rotation, and comprehensive event handling. Written in TypeScript for better type safety and maintainability.
Features
- Multi-account support: Login and manage multiple Zalo accounts simultaneously
- QR & Cookie login: Login via QR code or reuse saved cookies
- Message handling: Send/receive text messages, images, stickers, reactions
- Group support: Full support for group chats
- Proxy support: Automatic proxy rotation and health checks
- Webhook forwarding: Forward all events to external webhooks
- Auto-relogin: Automatic reconnection when connection drops
- Bot message filtering: Prevent echo loops using Redis caching
- Health monitoring: Connection health checks and retry logic
- TypeScript: Full type safety and IntelliSense support
Project Structure
openclaw-zalo-channel/
├── src/
│ ├── config/
│ │ ├── types.ts # TypeScript interfaces and types
│ │ ├── constants.ts # Constants and enums
│ │ └── env.ts # Environment configuration
│ ├── services/
│ │ ├── zaloService.ts # Core Zalo API (login, logout, messaging)
│ │ ├── eventService.ts # Event handling and webhooks
│ │ ├── redisService.ts # Redis caching for bot messages
│ │ └── proxyService.ts # Proxy management
│ ├── controllers/
│ │ ├── channelController.ts # Channel registration
│ │ ├── commandController.ts # CLI commands
│ │ ├── toolController.ts # Agent tools
│ │ └── serviceController.ts # Background service
│ ├── utils/
│ │ └── helpers.ts # Utility functions
│ └── index.ts # Plugin entry point
├── dist/ # Compiled JavaScript (after build)
├── openclaw.plugin.json # Plugin manifest
├── package.json # NPM configuration
├── tsconfig.json # TypeScript configuration
└── README.md # This fileInstallation
Prerequisites
- Node.js 18+
- TypeScript 5.3+
- Redis server (optional, for bot message caching)
Build from Source
# Install dependencies
npm install
# Build TypeScript
npm run build
# Or watch for changes during development
npm run build:watchInstall to OpenClaw
# Copy plugin to OpenClaw extensions directory
cp -r openclaw-zalo-channel /path/to/openclaw/extensions/
# Or use OpenClaw CLI
openclaw plugin install ./openclaw-zalo-channelConfiguration
Add to your openclaw.json:
{
"plugins": {
"entries": {
"openclaw-zalo-channel": {
"enabled": true,
"config": {
"dataPath": "./data/zalo",
"webhookUrl": "https://your-webhook-endpoint.com/webhook",
"redisUrl": "redis://localhost:6379",
"maxAccountsPerProxy": 3,
"proxies": [
"http://proxy1.example.com:8080",
"http://proxy2.example.com:8080"
]
}
}
}
}
}Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| dataPath | string | ./data/zalo | Directory for storing cookies and credentials |
| webhookUrl | string | - | URL to forward Zalo events (messages, reactions, group events) |
| redisUrl | string | redis://localhost:6379 | Redis connection URL for bot message caching |
| maxAccountsPerProxy | number | 3 | Maximum accounts per proxy |
| proxies | array | [] | List of proxy URLs for rotation |
CLI Commands
/zalo:login [proxy_url]
Login to Zalo account via QR code or saved cookie.
/zalo:login
/zalo:login http://proxy.example.com:8080/zalo:logout <ownId>
Logout from a specific Zalo account.
/zalo:logout 123456789/zalo:accounts
List all logged in Zalo accounts with their connection status.
/zalo:accounts/zalo:send <ownId> <threadId> <user|group> <message>
Send a message via a specific account.
/zalo:send 123456789 987654321 user Hello World!
/zalo:send 123456789 987654321 group Hello Group!/zalo:status
Show plugin status (total accounts, online/offline count).
/zalo:statusAgent Tools
zalo_send_message
Send a text message to a Zalo user or group.
{
accountId: string; // Zalo account ID (ownId)
threadId: string; // Target user or group ID
threadType: "user" | "group";
message: string; // Message content
}zalo_send_image
Send an image to a conversation.
{
accountId: string;
threadId: string;
threadType: "user" | "group";
imageUrl: string; // URL of the image
}zalo_get_user_info
Get information about a Zalo user by phone number or user ID.
{
accountId: string;
phoneNumber?: string; // Optional if userId provided
userId?: string; // Optional if phoneNumber provided
}zalo_find_user
Find a Zalo user by phone number.
{
accountId: string;
phoneNumber: string;
}zalo_send_typing
Send typing indicator to a conversation.
{
accountId: string;
threadId: string;
threadType: "user" | "group";
}zalo_add_reaction
Add a reaction (emoji) to a message.
{
accountId: string;
msgId: string;
threadId: string;
threadType: "user" | "group";
icon: string; // Emoji like ❤️, 👍, 😂
}zalo_send_sticker
Send a sticker to a conversation.
{
accountId: string;
threadId: string;
threadType: "user" | "group";
sticker: object; // Sticker object with id, type, etc.
}zalo_get_group_info
Get information about a Zalo group.
{
accountId: string;
groupId: string;
}Channel Integration
As a channel plugin, it integrates with OpenClaw's channel system:
// Send via OpenClaw Gateway
api.gateway.send({
channel: "zalo",
accountId: "<ownId>",
target: { threadId: "<user_or_group_id>" },
content: { text: "Hello from OpenClaw!" },
metadata: { threadType: "user" }
});Webhook Events
Events are sent to the configured webhookUrl:
Message Event
{
"event": "message",
"timestamp": 1234567890,
"data": {
"accountId": "123456789",
"messageType": "user",
"isGroup": false,
"chatType": "personal",
"bot": false,
"raw": { /* raw message data */ }
}
}Login Success Event
{
"event": "login_success",
"timestamp": 1234567890,
"data": {
"ownId": "123456789",
"displayName": "User Name",
"phoneNumber": "+84123456789",
"proxy": "http://proxy.example.com:8080"
}
}Group Event
{
"event": "group_event",
"timestamp": 1234567890,
"data": {
"accountId": "123456789",
"raw": { /* group event data */ }
}
}Reaction Event
{
"event": "reaction",
"timestamp": 1234567890,
"data": {
"accountId": "123456789",
"raw": { /* reaction data */ }
}
}Data Directory Structure
data/zalo/
├── cookies/
│ ├── cred_<ownId1>.json # Saved credentials for account 1
│ └── cred_<ownId2>.json # Saved credentials for account 2
└── proxies.json # Proxy configuration (auto-generated)Architecture
Services
- zaloService.ts: Core Zalo functionality - login/logout, messaging, account management
- eventService.ts: Event handling - message, group, reaction events and webhook forwarding
- redisService.ts: Redis caching - bot message deduplication
- proxyService.ts: Proxy management - rotation, health checks
Controllers
- channelController.ts: Channel registration with OpenClaw
- commandController.ts: CLI command handlers
- toolController.ts: Agent tool registration
- serviceController.ts: Background service (health checks, cleanup)
Utilities
- helpers.ts: Common utilities - image download, file operations, validators
Auto-Relogin
The plugin automatically handles connection drops:
- Detects disconnection via listener events and health checks
- Attempts re-login using saved cookies
- Exponential backoff retry (max 5 attempts)
- Resets retry counter after 30 minutes
- Lock mechanism prevents concurrent relogin attempts
Bot Message Caching
Uses Redis to prevent echo loops:
- All sent messages are cached with TTL (24 hours)
- Incoming messages are checked against cache
- Marked with
bot: trueif from self - Prevents the bot from responding to its own messages
Dependencies
Runtime
zca-js: Zalo unofficial API SDKhttps-proxy-agent: Proxy supportioredis: Redis clientaxios: HTTP requests
Development
typescript: TypeScript compiler@types/node: Node.js type definitions
API Types
The plugin exports TypeScript interfaces for external use:
import {
OpenClawApi,
ZaloAccount,
ZaloMessage,
ZaloCredentials,
SendTextParams,
// ... and more
} from 'openclaw-zalo-channel';Development
# Install dependencies
npm install
# Build
npm run build
# Watch mode
npm run build:watch
# Clean build artifacts
npm run cleanLicense
MIT
