zalo-agent-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DISCLAIMER.md +13 -0
- package/LICENSE +21 -0
- package/README.md +461 -0
- package/package.json +47 -0
- package/src/cli.test.js +97 -0
- package/src/commands/account.js +178 -0
- package/src/commands/conv.js +93 -0
- package/src/commands/friend.js +148 -0
- package/src/commands/group.js +123 -0
- package/src/commands/login.js +154 -0
- package/src/commands/msg.js +225 -0
- package/src/core/accounts.js +93 -0
- package/src/core/credentials.js +63 -0
- package/src/core/zalo-client.js +128 -0
- package/src/index.js +45 -0
- package/src/utils/bank-helpers.js +233 -0
- package/src/utils/bank-helpers.test.js +66 -0
- package/src/utils/output.js +21 -0
- package/src/utils/proxy-helpers.js +14 -0
- package/src/utils/proxy-helpers.test.js +36 -0
- package/src/utils/qr-display.js +78 -0
- package/src/utils/qr-http-server.js +126 -0
package/DISCLAIMER.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Disclaimer
|
|
2
|
+
|
|
3
|
+
This is an **unofficial** project and is **not affiliated with, endorsed by, or connected to Zalo or VNG Corporation** in any way.
|
|
4
|
+
|
|
5
|
+
This tool is provided for **research, educational, and personal automation purposes only**. Users are solely responsible for ensuring their use of this tool complies with:
|
|
6
|
+
|
|
7
|
+
- Zalo's Terms of Service
|
|
8
|
+
- Applicable local and international laws and regulations
|
|
9
|
+
- Data privacy requirements
|
|
10
|
+
|
|
11
|
+
The authors and contributors of this project accept **no responsibility or liability** for any misuse, account restrictions, or legal consequences arising from the use of this software.
|
|
12
|
+
|
|
13
|
+
**Use at your own risk.**
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
# zalo-agent-cli
|
|
2
|
+
|
|
3
|
+
CLI tool for Zalo automation — multi-account, proxy support, bank transfers, QR payments.
|
|
4
|
+
|
|
5
|
+
Built on top of [zca-js](https://github.com/AKAspanion/zca-js), the unofficial Zalo API library for Node.js.
|
|
6
|
+
|
|
7
|
+
**[Tiếng Việt](#tiếng-việt)** | **[English](#english)**
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## English
|
|
12
|
+
|
|
13
|
+
### Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Features](#features)
|
|
16
|
+
- [Requirements](#requirements)
|
|
17
|
+
- [Installation](#installation)
|
|
18
|
+
- [Quick Start](#quick-start)
|
|
19
|
+
- [Command Reference](#command-reference)
|
|
20
|
+
- [Multi-Account & Proxy](#multi-account--proxy)
|
|
21
|
+
- [Headless / VPS / CI Usage](#headless--vps--ci-usage)
|
|
22
|
+
- [Bank Card & QR Payments](#bank-card--qr-payments)
|
|
23
|
+
- [Security](#security)
|
|
24
|
+
- [Disclaimer](#disclaimer)
|
|
25
|
+
- [License](#license)
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
- Login via QR code with auto HTTP server (PNG in browser + inline terminal image + base64 data URL)
|
|
30
|
+
- Multi-account management with per-account dedicated proxy (1:1 mapping)
|
|
31
|
+
- Send text, images, files, contact cards, stickers, reactions
|
|
32
|
+
- Send bank cards (55+ Vietnamese banks)
|
|
33
|
+
- Generate and send VietQR transfer images via qr.sepay.vn
|
|
34
|
+
- Friend management (list, find, add, remove, block)
|
|
35
|
+
- Group management (create, rename, add/remove members)
|
|
36
|
+
- Conversation management (mute, pin, archive, read/unread)
|
|
37
|
+
- Export/import credentials for headless server deployment
|
|
38
|
+
- Local HTTP server for QR display on VPS (via SSH tunnel)
|
|
39
|
+
- `--json` output on all commands for scripting and coding agents
|
|
40
|
+
|
|
41
|
+
### Requirements
|
|
42
|
+
|
|
43
|
+
- **Node.js** >= 20
|
|
44
|
+
- **npm** (comes with Node.js)
|
|
45
|
+
|
|
46
|
+
### Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install -g zalo-agent-cli
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or run without installing:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx zalo-agent-cli login
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or clone and link for development:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
git clone https://github.com/PhucMPham/zalo-agent-cli.git
|
|
62
|
+
cd zalo-agent-cli
|
|
63
|
+
npm install
|
|
64
|
+
npm link
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Quick Start
|
|
68
|
+
|
|
69
|
+
#### 1. Login
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
zalo-agent login
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
A QR code PNG will be saved and a local HTTP server starts automatically. Open the URL shown in output (e.g. `http://your-ip:18927/qr`) in your browser, then scan with **Zalo app > QR Scanner**. Credentials are auto-saved to `~/.zalo-agent-cli/`.
|
|
76
|
+
|
|
77
|
+
> **Important:** Use Zalo's built-in QR scanner (not regular phone camera). The QR expires in ~60 seconds.
|
|
78
|
+
|
|
79
|
+
#### 2. Send a message
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
zalo-agent msg send <THREAD_ID> "Hello from zalo-agent!"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### 3. List friends
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
zalo-agent friend list
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### 4. Check status
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
zalo-agent status
|
|
95
|
+
zalo-agent whoami
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Command Reference
|
|
99
|
+
|
|
100
|
+
#### Global Flags
|
|
101
|
+
|
|
102
|
+
| Flag | Description |
|
|
103
|
+
|------|-------------|
|
|
104
|
+
| `--json` | Output all results as JSON |
|
|
105
|
+
| `-V, --version` | Show version number |
|
|
106
|
+
| `-h, --help` | Show help |
|
|
107
|
+
|
|
108
|
+
#### Auth
|
|
109
|
+
|
|
110
|
+
| Command | Description |
|
|
111
|
+
|---------|-------------|
|
|
112
|
+
| `login [--proxy URL] [--credentials PATH] [--qr-url]` | Login via QR or from exported credentials |
|
|
113
|
+
| `logout` | Clear current session |
|
|
114
|
+
| `status` | Show login state |
|
|
115
|
+
| `whoami` | Show current user profile |
|
|
116
|
+
|
|
117
|
+
#### Messages (`msg`)
|
|
118
|
+
|
|
119
|
+
| Command | Description |
|
|
120
|
+
|---------|-------------|
|
|
121
|
+
| `msg send <threadId> <text> [-t 0\|1]` | Send text message |
|
|
122
|
+
| `msg send-image <threadId> <paths...> [-t 0\|1] [-m caption]` | Send images |
|
|
123
|
+
| `msg send-file <threadId> <paths...> [-t 0\|1] [-m caption]` | Send files |
|
|
124
|
+
| `msg send-card <threadId> <userId> [-t 0\|1] [--phone NUM]` | Send contact card |
|
|
125
|
+
| `msg send-bank <threadId> <accountNum> -b BANK [-n name] [-t 0\|1]` | Send bank card |
|
|
126
|
+
| `msg send-qr-transfer <threadId> <accountNum> -b BANK [-a amount] [-m content] [--template tpl]` | Send VietQR transfer image |
|
|
127
|
+
| `msg sticker <threadId> <keyword> [-t 0\|1]` | Search and send sticker |
|
|
128
|
+
| `msg react <msgId> <threadId> <emoji> [-t 0\|1]` | React to a message |
|
|
129
|
+
| `msg delete <msgId> <threadId> [-t 0\|1]` | Delete a message |
|
|
130
|
+
| `msg forward <msgId> <threadId> [-t 0\|1]` | Forward a message |
|
|
131
|
+
|
|
132
|
+
> `-t 0` = User (default), `-t 1` = Group
|
|
133
|
+
|
|
134
|
+
#### Friends (`friend`)
|
|
135
|
+
|
|
136
|
+
| Command | Description |
|
|
137
|
+
|---------|-------------|
|
|
138
|
+
| `friend list` | List all friends |
|
|
139
|
+
| `friend online` | List online friends |
|
|
140
|
+
| `friend find <query>` | Find by phone or ID |
|
|
141
|
+
| `friend info <userId>` | Get user profile |
|
|
142
|
+
| `friend add <userId> [-m msg]` | Send friend request |
|
|
143
|
+
| `friend accept <userId>` | Accept request |
|
|
144
|
+
| `friend remove <userId>` | Remove friend |
|
|
145
|
+
| `friend block <userId>` | Block user |
|
|
146
|
+
| `friend unblock <userId>` | Unblock user |
|
|
147
|
+
| `friend last-online <userId>` | Check last seen |
|
|
148
|
+
|
|
149
|
+
#### Groups (`group`)
|
|
150
|
+
|
|
151
|
+
| Command | Description |
|
|
152
|
+
|---------|-------------|
|
|
153
|
+
| `group list` | List all groups |
|
|
154
|
+
| `group create <name> <memberIds...>` | Create group |
|
|
155
|
+
| `group info <groupId>` | Group details |
|
|
156
|
+
| `group members <groupId>` | List members |
|
|
157
|
+
| `group add-member <groupId> <userIds...>` | Add members |
|
|
158
|
+
| `group remove-member <groupId> <userIds...>` | Remove members |
|
|
159
|
+
| `group rename <groupId> <name>` | Rename |
|
|
160
|
+
| `group leave <groupId>` | Leave group |
|
|
161
|
+
| `group join <link>` | Join via invite link |
|
|
162
|
+
|
|
163
|
+
#### Conversations (`conv`)
|
|
164
|
+
|
|
165
|
+
| Command | Description |
|
|
166
|
+
|---------|-------------|
|
|
167
|
+
| `conv pinned` | List pinned |
|
|
168
|
+
| `conv archived` | List archived |
|
|
169
|
+
| `conv mute <threadId> [-t 0\|1] [-d secs]` | Mute (-1 = forever) |
|
|
170
|
+
| `conv unmute <threadId> [-t 0\|1]` | Unmute |
|
|
171
|
+
| `conv read <threadId> [-t 0\|1]` | Mark as read |
|
|
172
|
+
| `conv unread <threadId> [-t 0\|1]` | Mark as unread |
|
|
173
|
+
| `conv delete <threadId> [-t 0\|1]` | Delete conversation |
|
|
174
|
+
|
|
175
|
+
#### Accounts (`account`)
|
|
176
|
+
|
|
177
|
+
| Command | Description |
|
|
178
|
+
|---------|-------------|
|
|
179
|
+
| `account list` | List all registered accounts |
|
|
180
|
+
| `account login [-p proxy] [-n name] [--qr-url]` | Login new account with optional proxy |
|
|
181
|
+
| `account switch <ownerId>` | Switch active account |
|
|
182
|
+
| `account remove <ownerId>` | Remove account + credentials |
|
|
183
|
+
| `account info` | Show active account |
|
|
184
|
+
| `account export [ownerId] [-o path]` | Export credentials for transfer |
|
|
185
|
+
|
|
186
|
+
### Multi-Account & Proxy
|
|
187
|
+
|
|
188
|
+
Each Zalo account can be bound to its own dedicated proxy (1:1 mapping).
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Login account via residential proxy
|
|
192
|
+
zalo-agent account login --proxy "http://user:pass@proxy:8080" --name "Shop A"
|
|
193
|
+
|
|
194
|
+
# Login another account via different proxy
|
|
195
|
+
zalo-agent account login --proxy "socks5://user:pass@proxy2:1080" --name "Shop B"
|
|
196
|
+
|
|
197
|
+
# List accounts (proxy passwords are always masked)
|
|
198
|
+
zalo-agent account list
|
|
199
|
+
# ★ 356721... Shop A http://user:***@proxy:8080
|
|
200
|
+
# 789012... Shop B socks5://user:***@proxy2:1080
|
|
201
|
+
|
|
202
|
+
# Switch between accounts
|
|
203
|
+
zalo-agent account switch 789012...
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Important notes:**
|
|
207
|
+
- Zalo enforces 1 account = 1 device (IMEI). Each QR login auto-generates a unique IMEI.
|
|
208
|
+
- Use 1 dedicated proxy per account — sharing proxies risks both accounts being flagged.
|
|
209
|
+
- Supported proxy protocols: `http://`, `https://`, `socks5://`
|
|
210
|
+
- Proxy passwords are **never** displayed in output — always masked as `***`.
|
|
211
|
+
|
|
212
|
+
### Headless / VPS / CI Usage
|
|
213
|
+
|
|
214
|
+
#### Option A: QR via browser (recommended)
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# On VPS — QR HTTP server starts automatically
|
|
218
|
+
zalo-agent login
|
|
219
|
+
# Output: QR available at http://your-vps-ip:18927/qr
|
|
220
|
+
|
|
221
|
+
# Open the URL in your browser, scan with Zalo app > QR Scanner
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
> The server auto-detects your public IP and tries ports 18927, 8080, 3000, 9000.
|
|
225
|
+
> Make sure at least one port is open in your firewall.
|
|
226
|
+
|
|
227
|
+
#### Option B: Export/import credentials
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
# On local machine — login and export
|
|
231
|
+
zalo-agent login
|
|
232
|
+
zalo-agent account export --output ./creds.json
|
|
233
|
+
|
|
234
|
+
# Transfer to server
|
|
235
|
+
scp ./creds.json user@server:~/
|
|
236
|
+
|
|
237
|
+
# On server — import (no QR needed)
|
|
238
|
+
zalo-agent login --credentials ~/creds.json
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Bank Card & QR Payments
|
|
242
|
+
|
|
243
|
+
#### Send bank card (55+ Vietnamese banks)
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# By bank name
|
|
247
|
+
zalo-agent msg send-bank THREAD_ID 0123456789 --bank ocb
|
|
248
|
+
|
|
249
|
+
# With holder name
|
|
250
|
+
zalo-agent msg send-bank THREAD_ID 0123456789 --bank vietcombank --name "NGUYEN VAN A"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### Send VietQR transfer image
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
# Basic QR
|
|
257
|
+
zalo-agent msg send-qr-transfer THREAD_ID 0123456789 --bank ocb
|
|
258
|
+
|
|
259
|
+
# With amount + content + template
|
|
260
|
+
zalo-agent msg send-qr-transfer THREAD_ID 0123456789 --bank vcb \
|
|
261
|
+
--amount 500000 --content "thanh toan don hang" --template qronly
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Templates: `compact` (VietQR frame, default), `print` (logo V), `qronly` (bare QR)
|
|
265
|
+
|
|
266
|
+
Transfer content: max 50 characters (VietQR/NAPAS spec).
|
|
267
|
+
|
|
268
|
+
### Security
|
|
269
|
+
|
|
270
|
+
- Credentials stored at `~/.zalo-agent-cli/credentials/` with **0600** file permissions (owner-only)
|
|
271
|
+
- Proxy configuration stored separately from credential files
|
|
272
|
+
- Proxy passwords **never** shown in CLI output — always masked
|
|
273
|
+
- QR HTTP server binds to `127.0.0.1` only (not externally accessible)
|
|
274
|
+
- Exported credential files created with **0600** permissions + security warning
|
|
275
|
+
|
|
276
|
+
#### Storage layout
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
~/.zalo-agent-cli/
|
|
280
|
+
├── accounts.json # Account registry (ownId, name, proxy, active)
|
|
281
|
+
├── credentials/
|
|
282
|
+
│ ├── cred_<ownId1>.json # Per-account credentials (0600)
|
|
283
|
+
│ └── cred_<ownId2>.json
|
|
284
|
+
└── qr.png # Last generated QR code
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Disclaimer
|
|
288
|
+
|
|
289
|
+
This is an **unofficial** project and is **not affiliated with, endorsed by, or connected to Zalo or VNG Corporation**. Use at your own risk. See [DISCLAIMER.md](DISCLAIMER.md).
|
|
290
|
+
|
|
291
|
+
### License
|
|
292
|
+
|
|
293
|
+
[MIT](LICENSE)
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Tiếng Việt
|
|
298
|
+
|
|
299
|
+
### Mục lục
|
|
300
|
+
|
|
301
|
+
- [Tính năng](#tính-năng)
|
|
302
|
+
- [Yêu cầu](#yêu-cầu)
|
|
303
|
+
- [Cài đặt](#cài-đặt)
|
|
304
|
+
- [Bắt đầu nhanh](#bắt-đầu-nhanh)
|
|
305
|
+
- [Danh sách lệnh](#danh-sách-lệnh)
|
|
306
|
+
- [Đa tài khoản & Proxy](#đa-tài-khoản--proxy)
|
|
307
|
+
- [Sử dụng trên VPS / Headless / CI](#sử-dụng-trên-vps--headless--ci)
|
|
308
|
+
- [Thẻ ngân hàng & Thanh toán QR](#thẻ-ngân-hàng--thanh-toán-qr)
|
|
309
|
+
- [Bảo mật](#bảo-mật)
|
|
310
|
+
- [Tuyên bố miễn trừ](#tuyên-bố-miễn-trừ)
|
|
311
|
+
|
|
312
|
+
### Tính năng
|
|
313
|
+
|
|
314
|
+
- Đăng nhập bằng mã QR qua HTTP server tự động (PNG trên browser + inline terminal + base64)
|
|
315
|
+
- Quản lý đa tài khoản với proxy riêng biệt cho từng tài khoản (1:1)
|
|
316
|
+
- Gửi tin nhắn, hình ảnh, file, danh thiếp, sticker, reaction
|
|
317
|
+
- Gửi thẻ ngân hàng (55+ ngân hàng Việt Nam)
|
|
318
|
+
- Tạo và gửi ảnh QR chuyển khoản qua qr.sepay.vn
|
|
319
|
+
- Quản lý bạn bè (danh sách, tìm kiếm, thêm, xóa, chặn)
|
|
320
|
+
- Quản lý nhóm (tạo, đổi tên, thêm/xóa thành viên)
|
|
321
|
+
- Quản lý hội thoại (tắt thông báo, ghim, lưu trữ)
|
|
322
|
+
- Xuất/nhập credentials cho triển khai trên server
|
|
323
|
+
- HTTP server local hiển thị QR cho VPS (qua SSH tunnel)
|
|
324
|
+
- Output `--json` cho mọi lệnh, phục vụ scripting và coding agent
|
|
325
|
+
|
|
326
|
+
### Yêu cầu
|
|
327
|
+
|
|
328
|
+
- **Node.js** >= 20
|
|
329
|
+
- **npm** (đi kèm Node.js)
|
|
330
|
+
|
|
331
|
+
### Cài đặt
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
npm install -g zalo-agent-cli
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Hoặc chạy không cần cài:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
npx zalo-agent-cli login
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Hoặc clone để phát triển:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
git clone https://github.com/PhucMPham/zalo-agent-cli.git
|
|
347
|
+
cd zalo-agent-cli
|
|
348
|
+
npm install
|
|
349
|
+
npm link
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Bắt đầu nhanh
|
|
353
|
+
|
|
354
|
+
#### 1. Đăng nhập
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
zalo-agent login
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
HTTP server tự khởi động và hiện URL (ví dụ `http://ip:18927/qr`). Mở URL trên trình duyệt, quét bằng **Zalo app > Quét mã QR** (không dùng camera thường). Thông tin đăng nhập tự động lưu tại `~/.zalo-agent-cli/`.
|
|
361
|
+
|
|
362
|
+
#### 2. Gửi tin nhắn
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
zalo-agent msg send <THREAD_ID> "Xin chào!"
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
#### 3. Xem danh sách bạn bè
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
zalo-agent friend list
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Danh sách lệnh
|
|
375
|
+
|
|
376
|
+
Xem đầy đủ tại [phần tiếng Anh](#command-reference) phía trên. Tất cả lệnh đều giống nhau.
|
|
377
|
+
|
|
378
|
+
### Đa tài khoản & Proxy
|
|
379
|
+
|
|
380
|
+
Mỗi tài khoản Zalo có thể gắn với 1 proxy riêng biệt.
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
# Đăng nhập qua proxy
|
|
384
|
+
zalo-agent account login --proxy "http://user:pass@proxy:8080" --name "Shop A"
|
|
385
|
+
|
|
386
|
+
# Xem danh sách (mật khẩu proxy luôn bị ẩn)
|
|
387
|
+
zalo-agent account list
|
|
388
|
+
|
|
389
|
+
# Chuyển tài khoản
|
|
390
|
+
zalo-agent account switch <ID>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Lưu ý quan trọng:**
|
|
394
|
+
- Zalo giới hạn 1 tài khoản = 1 thiết bị (IMEI). Mỗi lần quét QR tự tạo IMEI mới.
|
|
395
|
+
- Dùng 1 proxy riêng cho mỗi tài khoản — dùng chung proxy có nguy cơ bị khóa cả 2.
|
|
396
|
+
- Hỗ trợ: `http://`, `https://`, `socks5://`
|
|
397
|
+
- Mật khẩu proxy **không bao giờ** hiển thị — luôn bị ẩn thành `***`.
|
|
398
|
+
|
|
399
|
+
### Sử dụng trên VPS / Headless / CI
|
|
400
|
+
|
|
401
|
+
#### Cách A: QR qua trình duyệt (khuyến nghị)
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
# Trên VPS — HTTP server tự động khởi động
|
|
405
|
+
zalo-agent login
|
|
406
|
+
# Output: QR available at http://ip-vps:18927/qr
|
|
407
|
+
|
|
408
|
+
# Mở URL trên trình duyệt, quét bằng Zalo app > Quét mã QR
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
> Server tự detect IP public và thử port 18927, 8080, 3000, 9000.
|
|
412
|
+
> Đảm bảo ít nhất 1 port mở trong firewall.
|
|
413
|
+
|
|
414
|
+
#### Cách B: Xuất/nhập credentials
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
# Trên máy local
|
|
418
|
+
zalo-agent login
|
|
419
|
+
zalo-agent account export --output ./creds.json
|
|
420
|
+
|
|
421
|
+
# Chuyển sang server
|
|
422
|
+
scp ./creds.json user@server:~/
|
|
423
|
+
|
|
424
|
+
# Trên server (không cần QR)
|
|
425
|
+
zalo-agent login --credentials ~/creds.json
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Thẻ ngân hàng & Thanh toán QR
|
|
429
|
+
|
|
430
|
+
#### Gửi thẻ ngân hàng (55+ ngân hàng VN)
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
zalo-agent msg send-bank THREAD_ID 0123456789 --bank ocb
|
|
434
|
+
zalo-agent msg send-bank THREAD_ID 0123456789 --bank vietcombank --name "NGUYEN VAN A"
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
#### Gửi QR chuyển khoản VietQR
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
zalo-agent msg send-qr-transfer THREAD_ID 0123456789 --bank vcb \
|
|
441
|
+
--amount 500000 --content "thanh toan" --template qronly
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Template: `compact` (khung VietQR), `print` (logo V), `qronly` (chỉ mã QR)
|
|
445
|
+
|
|
446
|
+
Nội dung chuyển khoản: tối đa 50 ký tự (theo chuẩn VietQR/NAPAS).
|
|
447
|
+
|
|
448
|
+
### Bảo mật
|
|
449
|
+
|
|
450
|
+
- Credentials lưu tại `~/.zalo-agent-cli/credentials/` với quyền **0600** (chỉ chủ sở hữu đọc được)
|
|
451
|
+
- Cấu hình proxy lưu riêng, không nằm trong file credentials
|
|
452
|
+
- Mật khẩu proxy **không bao giờ** hiển thị — luôn bị ẩn
|
|
453
|
+
- HTTP server QR chỉ lắng nghe `127.0.0.1` (không truy cập từ bên ngoài)
|
|
454
|
+
|
|
455
|
+
### Tuyên bố miễn trừ
|
|
456
|
+
|
|
457
|
+
Đây là dự án **không chính thức** và **không liên kết với Zalo hay Tập đoàn VNG**. Sử dụng trên tinh thần tự chịu trách nhiệm. Xem [DISCLAIMER.md](DISCLAIMER.md).
|
|
458
|
+
|
|
459
|
+
### Giấy phép
|
|
460
|
+
|
|
461
|
+
[MIT](LICENSE)
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zalo-agent-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool for Zalo automation — multi-account, proxy support, bank transfers, QR payments",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"zalo-agent": "src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./src/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"src/",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"DISCLAIMER.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "node --test src/*.test.js src/**/*.test.js",
|
|
17
|
+
"lint": "eslint src/",
|
|
18
|
+
"lint:fix": "eslint src/ --fix",
|
|
19
|
+
"format": "prettier --write src/",
|
|
20
|
+
"format:check": "prettier --check src/"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"zalo",
|
|
24
|
+
"cli",
|
|
25
|
+
"automation",
|
|
26
|
+
"messaging",
|
|
27
|
+
"vietnam",
|
|
28
|
+
"proxy",
|
|
29
|
+
"vietqr",
|
|
30
|
+
"zca-js"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"chalk": "^5.3.0",
|
|
38
|
+
"commander": "^14.0.3",
|
|
39
|
+
"https-proxy-agent": "^8.0.0",
|
|
40
|
+
"node-fetch": "^3.3.0",
|
|
41
|
+
"zca-js": "^2.1.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"eslint": "^10.0.3",
|
|
45
|
+
"prettier": "^3.8.1"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/cli.test.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI interface tests — verify command parsing, help output, and basic behavior
|
|
3
|
+
* without requiring a Zalo session.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it } from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { execFileSync } from "child_process";
|
|
9
|
+
import { resolve } from "path";
|
|
10
|
+
|
|
11
|
+
const CLI = resolve(import.meta.dirname, "index.js");
|
|
12
|
+
|
|
13
|
+
function run(...args) {
|
|
14
|
+
return execFileSync("node", [CLI, ...args], {
|
|
15
|
+
encoding: "utf-8",
|
|
16
|
+
timeout: 10000,
|
|
17
|
+
env: { ...process.env, HOME: "/tmp/zalo-agent-cli-test-home" },
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe("CLI interface", () => {
|
|
22
|
+
it("--version outputs 1.0.0", () => {
|
|
23
|
+
const out = run("--version");
|
|
24
|
+
assert.match(out.trim(), /^\d+\.\d+\.\d+$/);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("--help lists all command groups", () => {
|
|
28
|
+
const out = run("--help");
|
|
29
|
+
assert.match(out, /login/);
|
|
30
|
+
assert.match(out, /msg/);
|
|
31
|
+
assert.match(out, /friend/);
|
|
32
|
+
assert.match(out, /group/);
|
|
33
|
+
assert.match(out, /conv/);
|
|
34
|
+
assert.match(out, /account/);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("msg --help lists all subcommands", () => {
|
|
38
|
+
const out = run("msg", "--help");
|
|
39
|
+
assert.match(out, /send /);
|
|
40
|
+
assert.match(out, /send-image/);
|
|
41
|
+
assert.match(out, /send-file/);
|
|
42
|
+
assert.match(out, /send-card/);
|
|
43
|
+
assert.match(out, /send-bank/);
|
|
44
|
+
assert.match(out, /send-qr-transfer/);
|
|
45
|
+
assert.match(out, /sticker/);
|
|
46
|
+
assert.match(out, /react/);
|
|
47
|
+
assert.match(out, /delete/);
|
|
48
|
+
assert.match(out, /forward/);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("friend --help lists subcommands", () => {
|
|
52
|
+
const out = run("friend", "--help");
|
|
53
|
+
assert.match(out, /list/);
|
|
54
|
+
assert.match(out, /find/);
|
|
55
|
+
assert.match(out, /info/);
|
|
56
|
+
assert.match(out, /block/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("group --help lists subcommands", () => {
|
|
60
|
+
const out = run("group", "--help");
|
|
61
|
+
assert.match(out, /create/);
|
|
62
|
+
assert.match(out, /members/);
|
|
63
|
+
assert.match(out, /rename/);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("conv --help lists subcommands", () => {
|
|
67
|
+
const out = run("conv", "--help");
|
|
68
|
+
assert.match(out, /mute/);
|
|
69
|
+
assert.match(out, /pinned/);
|
|
70
|
+
assert.match(out, /archived/);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("account --help lists subcommands", () => {
|
|
74
|
+
const out = run("account", "--help");
|
|
75
|
+
assert.match(out, /login/);
|
|
76
|
+
assert.match(out, /switch/);
|
|
77
|
+
assert.match(out, /export/);
|
|
78
|
+
assert.match(out, /remove/);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("login --help shows all flags", () => {
|
|
82
|
+
const out = run("login", "--help");
|
|
83
|
+
assert.match(out, /--proxy/);
|
|
84
|
+
assert.match(out, /--credentials/);
|
|
85
|
+
assert.match(out, /--qr-url/);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("logout --help shows --purge", () => {
|
|
89
|
+
const out = run("logout", "--help");
|
|
90
|
+
assert.match(out, /--purge/);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("account list on clean state shows no accounts", () => {
|
|
94
|
+
const out = run("account", "list");
|
|
95
|
+
assert.match(out, /No accounts/);
|
|
96
|
+
});
|
|
97
|
+
});
|