zalo-agent-cli 1.0.17 → 1.0.19
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 +17 -3
- package/README.md +50 -6
- package/package.json +1 -1
- package/src/commands/conv.js +85 -1
- package/src/commands/friend.js +33 -0
- package/src/index.js +6 -1
package/DISCLAIMER.md
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
# Disclaimer
|
|
2
2
|
|
|
3
|
+
## ⚠️ Cảnh báo quan trọng / Important Warning
|
|
4
|
+
|
|
5
|
+
**Tool này sử dụng [zca-js](https://github.com/AKAspanion/zca-js) — một thư viện gọi API Zalo không chính thức. Zalo không hỗ trợ và tài khoản của bạn có thể bị khóa (ban) khi sử dụng.**
|
|
6
|
+
|
|
7
|
+
**This tool uses [zca-js](https://github.com/AKAspanion/zca-js) — an unofficial Zalo API library. Zalo does not support this and your account may be banned.**
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
3
11
|
This is an **unofficial** project and is **not affiliated with, endorsed by, or connected to Zalo or VNG Corporation** in any way.
|
|
4
12
|
|
|
5
|
-
This tool is provided for **research, educational, and personal automation purposes only**.
|
|
13
|
+
This tool is provided for **research, educational, and personal automation purposes only**. By using this tool, you acknowledge and accept that:
|
|
14
|
+
|
|
15
|
+
- **Your Zalo account may be permanently banned or restricted** — Zalo actively detects and blocks unofficial API usage
|
|
16
|
+
- This tool relies on **reverse-engineered, undocumented APIs** via the zca-js library, which can break at any time
|
|
17
|
+
- There is **no guarantee of stability, compatibility, or continued functionality**
|
|
18
|
+
|
|
19
|
+
Users are solely responsible for ensuring their use of this tool complies with:
|
|
6
20
|
|
|
7
21
|
- Zalo's Terms of Service
|
|
8
22
|
- Applicable local and international laws and regulations
|
|
9
23
|
- Data privacy requirements
|
|
10
24
|
|
|
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.
|
|
25
|
+
The authors and contributors of this project accept **no responsibility or liability** for any misuse, account restrictions, bans, or legal consequences arising from the use of this software.
|
|
12
26
|
|
|
13
|
-
**Use at your own risk.**
|
|
27
|
+
**Sử dụng trên tinh thần tự chịu trách nhiệm. Use at your own risk.**
|
package/README.md
CHANGED
|
@@ -80,13 +80,32 @@ A QR code PNG will be saved and a local HTTP server starts automatically. Open t
|
|
|
80
80
|
|
|
81
81
|
> **Important:** Use Zalo's built-in QR scanner (not regular phone camera). The QR expires in ~60 seconds.
|
|
82
82
|
|
|
83
|
-
#### 2.
|
|
83
|
+
#### 2. Find a thread ID
|
|
84
|
+
|
|
85
|
+
A `thread_id` is a user ID (for DMs) or group ID (for group chats). You need it for most messaging commands.
|
|
84
86
|
|
|
85
87
|
```bash
|
|
88
|
+
# Search friends by name → get their thread_id
|
|
89
|
+
zalo-agent friend search "Phúc"
|
|
90
|
+
|
|
91
|
+
# List recent conversations (friends + groups) with thread_id
|
|
92
|
+
zalo-agent conv recent
|
|
93
|
+
|
|
94
|
+
# List only groups
|
|
95
|
+
zalo-agent conv recent --groups-only
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### 3. Send a message
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Send to a user (type 0, default)
|
|
86
102
|
zalo-agent msg send <THREAD_ID> "Hello from zalo-agent!"
|
|
103
|
+
|
|
104
|
+
# Send to a group (type 1)
|
|
105
|
+
zalo-agent msg send <THREAD_ID> "Hello group!" -t 1
|
|
87
106
|
```
|
|
88
107
|
|
|
89
|
-
####
|
|
108
|
+
#### 4. List friends
|
|
90
109
|
|
|
91
110
|
```bash
|
|
92
111
|
zalo-agent friend list
|
|
@@ -140,6 +159,7 @@ zalo-agent whoami
|
|
|
140
159
|
| Command | Description |
|
|
141
160
|
|---------|-------------|
|
|
142
161
|
| `friend list` | List all friends |
|
|
162
|
+
| `friend search <name>` | Search friends by name (get thread_id) |
|
|
143
163
|
| `friend online` | List online friends |
|
|
144
164
|
| `friend find <query>` | Find by phone or ID |
|
|
145
165
|
| `friend info <userId>` | Get user profile |
|
|
@@ -168,6 +188,7 @@ zalo-agent whoami
|
|
|
168
188
|
|
|
169
189
|
| Command | Description |
|
|
170
190
|
|---------|-------------|
|
|
191
|
+
| `conv recent [-n limit] [--friends-only] [--groups-only]` | List recent conversations with thread_id |
|
|
171
192
|
| `conv pinned` | List pinned |
|
|
172
193
|
| `conv archived` | List archived |
|
|
173
194
|
| `conv mute <threadId> [-t 0\|1] [-d secs]` | Mute (-1 = forever) |
|
|
@@ -290,7 +311,9 @@ Transfer content: max 50 characters (VietQR/NAPAS spec).
|
|
|
290
311
|
|
|
291
312
|
### Disclaimer
|
|
292
313
|
|
|
293
|
-
This
|
|
314
|
+
> ⚠️ **Warning:** This tool uses [zca-js](https://github.com/AKAspanion/zca-js), an **unofficial** Zalo API library. Zalo does not support this and **your account may be banned**. Use at your own risk.
|
|
315
|
+
|
|
316
|
+
This is an **unofficial** project and is **not affiliated with, endorsed by, or connected to Zalo or VNG Corporation**. See [DISCLAIMER.md](DISCLAIMER.md) for full details.
|
|
294
317
|
|
|
295
318
|
### License
|
|
296
319
|
|
|
@@ -363,13 +386,32 @@ zalo-agent login
|
|
|
363
386
|
|
|
364
387
|
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/`.
|
|
365
388
|
|
|
366
|
-
#### 2.
|
|
389
|
+
#### 2. Tìm thread ID
|
|
390
|
+
|
|
391
|
+
`thread_id` là ID của người dùng (tin nhắn riêng) hoặc ID nhóm (nhóm chat). Bạn cần nó cho hầu hết các lệnh gửi tin.
|
|
367
392
|
|
|
368
393
|
```bash
|
|
394
|
+
# Tìm bạn bè theo tên → lấy thread_id
|
|
395
|
+
zalo-agent friend search "Phúc"
|
|
396
|
+
|
|
397
|
+
# Xem danh sách hội thoại gần đây (bạn bè + nhóm) kèm thread_id
|
|
398
|
+
zalo-agent conv recent
|
|
399
|
+
|
|
400
|
+
# Chỉ xem nhóm
|
|
401
|
+
zalo-agent conv recent --groups-only
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### 3. Gửi tin nhắn
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
# Gửi cho cá nhân (type 0, mặc định)
|
|
369
408
|
zalo-agent msg send <THREAD_ID> "Xin chào!"
|
|
409
|
+
|
|
410
|
+
# Gửi vào nhóm (type 1)
|
|
411
|
+
zalo-agent msg send <THREAD_ID> "Xin chào nhóm!" -t 1
|
|
370
412
|
```
|
|
371
413
|
|
|
372
|
-
####
|
|
414
|
+
#### 4. Xem danh sách bạn bè
|
|
373
415
|
|
|
374
416
|
```bash
|
|
375
417
|
zalo-agent friend list
|
|
@@ -458,7 +500,9 @@ Nội dung chuyển khoản: tối đa 50 ký tự (theo chuẩn VietQR/NAPAS).
|
|
|
458
500
|
|
|
459
501
|
### Tuyên bố miễn trừ
|
|
460
502
|
|
|
461
|
-
|
|
503
|
+
> ⚠️ **Cảnh báo:** Tool này sử dụng [zca-js](https://github.com/AKAspanion/zca-js) — thư viện gọi API Zalo **không chính thức**. Zalo không hỗ trợ và **tài khoản của bạn có thể bị khóa (ban)**. Dùng trên tinh thần tự chịu trách nhiệm.
|
|
504
|
+
|
|
505
|
+
Đâ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**. Xem [DISCLAIMER.md](DISCLAIMER.md) để biết chi tiết.
|
|
462
506
|
|
|
463
507
|
### Giấy phép
|
|
464
508
|
|
package/package.json
CHANGED
package/src/commands/conv.js
CHANGED
|
@@ -3,11 +3,95 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { getApi } from "../core/zalo-client.js";
|
|
6
|
-
import { success, error, output } from "../utils/output.js";
|
|
6
|
+
import { success, error, info, output } from "../utils/output.js";
|
|
7
7
|
|
|
8
8
|
export function registerConvCommands(program) {
|
|
9
9
|
const conv = program.command("conv").description("Manage conversations");
|
|
10
10
|
|
|
11
|
+
conv.command("recent")
|
|
12
|
+
.description("List recent conversations with thread_id (friends + groups)")
|
|
13
|
+
.option("-n, --limit <n>", "Max results per type", "20")
|
|
14
|
+
.option("--friends-only", "Show only friend conversations")
|
|
15
|
+
.option("--groups-only", "Show only group conversations")
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
try {
|
|
18
|
+
const api = getApi();
|
|
19
|
+
const limit = Number(opts.limit);
|
|
20
|
+
const conversations = [];
|
|
21
|
+
|
|
22
|
+
// Fetch friends (sorted by lastActionTime = most recent interaction)
|
|
23
|
+
if (!opts.groupsOnly) {
|
|
24
|
+
const friends = await api.getAllFriends();
|
|
25
|
+
const list = Array.isArray(friends) ? friends : [];
|
|
26
|
+
const sorted = list
|
|
27
|
+
.filter((f) => f.lastActionTime > 0)
|
|
28
|
+
.sort((a, b) => b.lastActionTime - a.lastActionTime)
|
|
29
|
+
.slice(0, limit);
|
|
30
|
+
for (const f of sorted) {
|
|
31
|
+
conversations.push({
|
|
32
|
+
threadId: f.userId,
|
|
33
|
+
name: f.displayName || f.zaloName || "?",
|
|
34
|
+
type: "User",
|
|
35
|
+
typeFlag: 0,
|
|
36
|
+
lastActive: new Date(f.lastActionTime * 1000).toLocaleString(),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Fetch groups
|
|
42
|
+
if (!opts.friendsOnly) {
|
|
43
|
+
const groupsResult = await api.getAllGroups();
|
|
44
|
+
const groupIds = Object.keys(groupsResult?.gridVerMap || {});
|
|
45
|
+
if (groupIds.length > 0) {
|
|
46
|
+
const batchSize = 50;
|
|
47
|
+
const batches = [];
|
|
48
|
+
for (let i = 0; i < Math.min(groupIds.length, limit); i += batchSize) {
|
|
49
|
+
batches.push(groupIds.slice(i, i + batchSize));
|
|
50
|
+
}
|
|
51
|
+
for (const batch of batches) {
|
|
52
|
+
try {
|
|
53
|
+
const groupInfo = await api.getGroupInfo(batch);
|
|
54
|
+
const map = groupInfo?.gridInfoMap || {};
|
|
55
|
+
for (const [gid, g] of Object.entries(map)) {
|
|
56
|
+
conversations.push({
|
|
57
|
+
threadId: gid,
|
|
58
|
+
name: g.name || "?",
|
|
59
|
+
type: "Group",
|
|
60
|
+
typeFlag: 1,
|
|
61
|
+
memberCount: g.totalMember || 0,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
} catch {
|
|
65
|
+
// Skip failed batch
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
output(conversations, program.opts().json, () => {
|
|
72
|
+
if (conversations.length === 0) {
|
|
73
|
+
error("No conversations found.");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
info(`${conversations.length} conversation(s):`);
|
|
77
|
+
console.log();
|
|
78
|
+
console.log(" THREAD_ID TYPE NAME");
|
|
79
|
+
console.log(" " + "-".repeat(60));
|
|
80
|
+
for (const c of conversations) {
|
|
81
|
+
const typeLabel = c.type === "Group" ? `Group(${c.memberCount})` : "User";
|
|
82
|
+
const id = c.threadId.padEnd(22);
|
|
83
|
+
console.log(` ${id} ${typeLabel.padEnd(12)} ${c.name}`);
|
|
84
|
+
}
|
|
85
|
+
console.log();
|
|
86
|
+
info("Use thread_id with messaging commands:");
|
|
87
|
+
info(' zalo-agent msg send <thread_id> "Hello" (User)');
|
|
88
|
+
info(' zalo-agent msg send <thread_id> "Hello" -t 1 (Group)');
|
|
89
|
+
});
|
|
90
|
+
} catch (e) {
|
|
91
|
+
error(e.message);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
11
95
|
conv.command("pinned")
|
|
12
96
|
.description("List pinned conversations")
|
|
13
97
|
.action(async () => {
|
package/src/commands/friend.js
CHANGED
|
@@ -45,6 +45,39 @@ export function registerFriendCommands(program) {
|
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
friend
|
|
49
|
+
.command("search <name>")
|
|
50
|
+
.description("Search friends by name (returns thread_id for messaging)")
|
|
51
|
+
.action(async (name) => {
|
|
52
|
+
try {
|
|
53
|
+
const result = await getApi().getAllFriends();
|
|
54
|
+
const friends = Array.isArray(result) ? result : [];
|
|
55
|
+
const query = name.toLowerCase();
|
|
56
|
+
const matches = friends.filter((f) => {
|
|
57
|
+
const dn = (f.displayName || "").toLowerCase();
|
|
58
|
+
const zn = (f.zaloName || "").toLowerCase();
|
|
59
|
+
return dn.includes(query) || zn.includes(query);
|
|
60
|
+
});
|
|
61
|
+
output(matches, program.opts().json, () => {
|
|
62
|
+
if (matches.length === 0) {
|
|
63
|
+
error(`No friends matching "${name}". Use "friend list" to see all.`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
info(`${matches.length} friend(s) matching "${name}":`);
|
|
67
|
+
console.log();
|
|
68
|
+
for (const f of matches) {
|
|
69
|
+
const display = f.displayName || f.zaloName || "?";
|
|
70
|
+
console.log(` ${f.userId} ${display}`);
|
|
71
|
+
}
|
|
72
|
+
console.log();
|
|
73
|
+
info("Use the ID above as thread_id for messaging commands.");
|
|
74
|
+
info('Example: zalo-agent msg send <thread_id> "Hello"');
|
|
75
|
+
});
|
|
76
|
+
} catch (e) {
|
|
77
|
+
error(e.message);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
48
81
|
friend
|
|
49
82
|
.command("find <query>")
|
|
50
83
|
.description("Find user by phone number or Zalo ID")
|
package/src/index.js
CHANGED
|
@@ -21,7 +21,9 @@ import { registerAccountCommands } from "./commands/account.js";
|
|
|
21
21
|
import { registerListenCommand } from "./commands/listen.js";
|
|
22
22
|
import { autoLogin } from "./core/zalo-client.js";
|
|
23
23
|
import { checkForUpdates, selfUpdate } from "./utils/update-check.js";
|
|
24
|
-
import { success, error } from "./utils/output.js";
|
|
24
|
+
import { success, error, warning } from "./utils/output.js";
|
|
25
|
+
|
|
26
|
+
const DISCLAIMER = "This tool uses unofficial Zalo APIs (zca-js) — your account may be banned. Use at your own risk. | Tool này dùng API Zalo không chính thức (zca-js) — account có thể bị ban. Tự chịu trách nhiệm.";
|
|
25
27
|
|
|
26
28
|
const program = new Command();
|
|
27
29
|
|
|
@@ -34,6 +36,9 @@ program
|
|
|
34
36
|
// Suppress zca-js internal logs in JSON mode to keep stdout clean for piping
|
|
35
37
|
if (program.opts().json) {
|
|
36
38
|
process.env.ZALO_JSON_MODE = "1";
|
|
39
|
+
} else {
|
|
40
|
+
warning(DISCLAIMER);
|
|
41
|
+
console.log();
|
|
37
42
|
}
|
|
38
43
|
// Auto-login before any command that needs it (skip for login/account commands)
|
|
39
44
|
const cmdName = thisCommand.args?.[0] || thisCommand.name();
|