zalo-agent-cli 1.0.7 → 1.0.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zalo-agent-cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "CLI tool for Zalo automation — multi-account, proxy support, bank transfers, QR payments",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,7 +13,10 @@ export function registerMsgCommands(program) {
13
13
  msg.command("send <threadId> <message>")
14
14
  .description("Send a text message")
15
15
  .option("-t, --type <n>", "Thread type: 0=User, 1=Group", "0")
16
- .option("--react <icon>", "Auto-react to the sent message (e.g. :> for haha)")
16
+ .option(
17
+ "--react <icon>",
18
+ "Auto-react to sent message. Codes: :> (haha), /-heart (heart), /-strong (like), :o (wow), :-(( (cry), :-h (angry)",
19
+ )
17
20
  .action(async (threadId, message, opts) => {
18
21
  try {
19
22
  // Capture clientId before send — zca-js uses Date.now() internally
@@ -204,9 +207,14 @@ export function registerMsgCommands(program) {
204
207
  });
205
208
 
206
209
  msg.command("react <msgId> <threadId> <reaction>")
207
- .description("React to a message with an emoji")
210
+ .description(
211
+ "React to a message. Reaction codes: :> (haha), /-heart (heart), /-strong (like), :o (wow), :-(( (cry), :-h (angry)",
212
+ )
208
213
  .option("-t, --type <n>", "Thread type: 0=User, 1=Group", "0")
209
- .option("-c, --cli-msg-id <id>", "Client message ID (defaults to msgId)")
214
+ .option(
215
+ "-c, --cli-msg-id <id>",
216
+ "Client message ID (required for reaction to appear, get from msg listen --json)",
217
+ )
210
218
  .action(async (msgId, threadId, reaction, opts) => {
211
219
  try {
212
220
  // zca-js addReaction(icon, dest) — dest needs msgId + cliMsgId
@@ -223,14 +231,28 @@ export function registerMsgCommands(program) {
223
231
  });
224
232
 
225
233
  msg.command("listen")
226
- .description("Listen for incoming messages (Ctrl+C to stop)")
227
- .action(async () => {
234
+ .description(
235
+ "Listen for incoming messages in real-time via WebSocket. Outputs msgId + cliMsgId needed for react. Use --json for machine parsing.",
236
+ )
237
+ .option("-f, --filter <type>", "Filter messages: user (DM only), group (groups only), all (default)", "all")
238
+ .option("-w, --webhook <url>", "POST each message as JSON to this URL (for n8n, Make, etc.)")
239
+ .option("--no-self", "Exclude messages sent by this account")
240
+ .action(async (opts) => {
228
241
  try {
229
242
  const api = getApi();
243
+ const jsonMode = program.opts().json;
230
244
  info("Listening for messages... Press Ctrl+C to stop.");
231
245
  info("Note: Only one web listener per account. Browser Zalo will disconnect.");
246
+ if (opts.filter !== "all") info(`Filter: ${opts.filter} messages only`);
247
+ if (opts.webhook) info(`Webhook: POST to ${opts.webhook}`);
248
+
249
+ api.listener.on("message", async (msg) => {
250
+ // Filter by type: 0=User, 1=Group
251
+ if (opts.filter === "user" && msg.type !== 0) return;
252
+ if (opts.filter === "group" && msg.type !== 1) return;
253
+ // Filter self messages
254
+ if (!opts.self && msg.isSelf) return;
232
255
 
233
- api.listener.on("message", (msg) => {
234
256
  const content = typeof msg.data.content === "string" ? msg.data.content : "[non-text]";
235
257
  const data = {
236
258
  msgId: msg.data.msgId,
@@ -240,11 +262,27 @@ export function registerMsgCommands(program) {
240
262
  isSelf: msg.isSelf,
241
263
  content,
242
264
  };
243
- if (program.opts().json) {
265
+
266
+ // Output to stdout
267
+ if (jsonMode) {
244
268
  console.log(JSON.stringify(data));
245
269
  } else {
246
270
  const dir = msg.isSelf ? "→" : "←";
247
- console.log(` ${dir} [${msg.threadId}] ${content} (msgId: ${msg.data.msgId})`);
271
+ const typeLabel = msg.type === 0 ? "DM" : "GR";
272
+ console.log(` ${dir} [${typeLabel}] [${msg.threadId}] ${content} (msgId: ${msg.data.msgId})`);
273
+ }
274
+
275
+ // POST to webhook if configured
276
+ if (opts.webhook) {
277
+ try {
278
+ await fetch(opts.webhook, {
279
+ method: "POST",
280
+ headers: { "Content-Type": "application/json" },
281
+ body: JSON.stringify(data),
282
+ });
283
+ } catch {
284
+ // Silent webhook failure — don't block listener
285
+ }
248
286
  }
249
287
  });
250
288