zalo-agent-cli 1.0.28 → 1.0.29
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/README.md +23 -0
- package/package.json +1 -1
- package/src/commands/listen.js +26 -1
package/README.md
CHANGED
|
@@ -328,6 +328,29 @@ zalo-agent reminder remove <reminderId> <groupId> -t 1
|
|
|
328
328
|
| `account info` | Show active account |
|
|
329
329
|
| `account export [ownerId] [-o path]` | Export credentials for transfer |
|
|
330
330
|
|
|
331
|
+
#### Listener (`listen`)
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# Listen for messages (default: message + friend events)
|
|
335
|
+
zalo-agent listen
|
|
336
|
+
|
|
337
|
+
# Filter: DM only, with webhook
|
|
338
|
+
zalo-agent listen -f user -w https://your-n8n.com/webhook/zalo
|
|
339
|
+
|
|
340
|
+
# Save messages locally as JSONL (one file per thread)
|
|
341
|
+
zalo-agent listen --save ./zalo-logs
|
|
342
|
+
|
|
343
|
+
# JSON mode for piping + save locally + webhook
|
|
344
|
+
zalo-agent --json listen --save ./zalo-logs -w https://webhook.url
|
|
345
|
+
|
|
346
|
+
# Auto-accept friend requests
|
|
347
|
+
zalo-agent listen --auto-accept
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Flags:** `-e` events (message,friend,group,reaction), `-f` filter (user,group,all), `-w` webhook URL, `--save <dir>` local JSONL storage, `--no-self` exclude own messages, `--auto-accept` auto-accept friend requests
|
|
351
|
+
|
|
352
|
+
**JSONL storage format:** One file per thread (`<threadId>.jsonl`), each line is a JSON object with event data + `savedAt` timestamp. Useful as workaround for chat history — Zalo API only returns ~20 recent messages.
|
|
353
|
+
|
|
331
354
|
### Multi-Account & Proxy
|
|
332
355
|
|
|
333
356
|
Each Zalo account can be bound to its own dedicated proxy (1:1 mapping).
|
package/package.json
CHANGED
package/src/commands/listen.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Production-ready with auto-reconnect and re-login.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { appendFileSync, mkdirSync, existsSync } from "fs";
|
|
7
|
+
import { resolve, join } from "path";
|
|
6
8
|
import { getApi, autoLogin, clearSession } from "../core/zalo-client.js";
|
|
7
9
|
import { success, error, info, warning } from "../utils/output.js";
|
|
8
10
|
|
|
@@ -41,6 +43,7 @@ export function registerListenCommand(program) {
|
|
|
41
43
|
.option("-w, --webhook <url>", "POST each event as JSON to this URL (for n8n, Make, etc.)")
|
|
42
44
|
.option("--no-self", "Exclude self-sent messages")
|
|
43
45
|
.option("--auto-accept", "Auto-accept incoming friend requests")
|
|
46
|
+
.option("--save <dir>", "Save messages locally as JSONL files (one file per thread, e.g. --save ./zalo-logs)")
|
|
44
47
|
.action(async (opts) => {
|
|
45
48
|
const jsonMode = program.opts().json;
|
|
46
49
|
const startTime = Date.now();
|
|
@@ -65,7 +68,26 @@ export function registerListenCommand(program) {
|
|
|
65
68
|
}).catch(() => {});
|
|
66
69
|
}
|
|
67
70
|
|
|
68
|
-
|
|
71
|
+
// Setup save directory if --save flag provided
|
|
72
|
+
let saveDir = null;
|
|
73
|
+
if (opts.save) {
|
|
74
|
+
saveDir = resolve(opts.save);
|
|
75
|
+
if (!existsSync(saveDir)) mkdirSync(saveDir, { recursive: true });
|
|
76
|
+
info(`Saving messages to: ${saveDir}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Append event to JSONL file (one file per threadId) */
|
|
80
|
+
function saveEvent(data) {
|
|
81
|
+
if (!saveDir || !data.threadId) return;
|
|
82
|
+
const filename = `${data.threadId}.jsonl`;
|
|
83
|
+
const filepath = join(saveDir, filename);
|
|
84
|
+
const line = JSON.stringify({ ...data, savedAt: new Date().toISOString() }) + "\n";
|
|
85
|
+
try {
|
|
86
|
+
appendFileSync(filepath, line, "utf-8");
|
|
87
|
+
} catch {}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Output event as JSON or human-readable, save locally, then post to webhook */
|
|
69
91
|
function emitEvent(data, humanMsg) {
|
|
70
92
|
eventCount++;
|
|
71
93
|
if (jsonMode) {
|
|
@@ -73,6 +95,7 @@ export function registerListenCommand(program) {
|
|
|
73
95
|
} else {
|
|
74
96
|
info(humanMsg);
|
|
75
97
|
}
|
|
98
|
+
saveEvent(data);
|
|
76
99
|
postWebhook(data);
|
|
77
100
|
}
|
|
78
101
|
|
|
@@ -224,6 +247,7 @@ export function registerListenCommand(program) {
|
|
|
224
247
|
info("Auto-reconnect enabled.");
|
|
225
248
|
if (opts.filter !== "all") info(`Message filter: ${opts.filter}`);
|
|
226
249
|
if (opts.webhook) info(`Webhook: ${opts.webhook}`);
|
|
250
|
+
if (saveDir) info(`Save dir: ${saveDir} (JSONL per thread)`);
|
|
227
251
|
if (opts.autoAccept) info("Auto-accept friend requests: ON");
|
|
228
252
|
} catch (e) {
|
|
229
253
|
error(`Listen failed: ${e.message}`);
|
|
@@ -237,6 +261,7 @@ export function registerListenCommand(program) {
|
|
|
237
261
|
getApi().listener.stop();
|
|
238
262
|
} catch {}
|
|
239
263
|
info(`Stopped. Uptime: ${uptime()}, events: ${eventCount}, reconnects: ${reconnectCount}`);
|
|
264
|
+
if (saveDir) info(`Messages saved to: ${saveDir}`);
|
|
240
265
|
resolve();
|
|
241
266
|
});
|
|
242
267
|
});
|