zalo-agent-cli 1.0.4 → 1.0.6
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 +3 -2
- package/src/commands/friend.js +3 -1
- package/src/commands/msg.js +50 -2
- package/src/index.js +17 -1
- package/src/utils/update-check.js +47 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zalo-agent-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "CLI tool for Zalo automation — multi-account, proxy support, bank transfers, QR payments",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"lint": "eslint src/",
|
|
18
18
|
"lint:fix": "eslint src/ --fix",
|
|
19
19
|
"format": "prettier --write src/",
|
|
20
|
-
"format:check": "prettier --check src/"
|
|
20
|
+
"format:check": "prettier --check src/",
|
|
21
|
+
"release": "npm version patch -m 'release: v%s' && git push origin main --tags"
|
|
21
22
|
},
|
|
22
23
|
"keywords": [
|
|
23
24
|
"zalo",
|
package/src/commands/friend.js
CHANGED
|
@@ -52,7 +52,9 @@ export function registerFriendCommands(program) {
|
|
|
52
52
|
try {
|
|
53
53
|
const result = await getApi().findUser(query);
|
|
54
54
|
if (!result || (!result.uid && !result?.data?.uid)) {
|
|
55
|
-
error(
|
|
55
|
+
error(
|
|
56
|
+
`No Zalo user found for "${query}". User may not exist, has disabled phone search, or phone is not registered on Zalo.`,
|
|
57
|
+
);
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
58
60
|
output(result, program.opts().json, () => {
|
package/src/commands/msg.js
CHANGED
|
@@ -190,12 +190,60 @@ export function registerMsgCommands(program) {
|
|
|
190
190
|
msg.command("react <msgId> <threadId> <reaction>")
|
|
191
191
|
.description("React to a message with an emoji")
|
|
192
192
|
.option("-t, --type <n>", "Thread type: 0=User, 1=Group", "0")
|
|
193
|
+
.option("-c, --cli-msg-id <id>", "Client message ID (defaults to msgId)")
|
|
193
194
|
.action(async (msgId, threadId, reaction, opts) => {
|
|
194
195
|
try {
|
|
195
|
-
|
|
196
|
+
// zca-js addReaction(icon, dest) — dest needs msgId + cliMsgId
|
|
197
|
+
const dest = {
|
|
198
|
+
data: { msgId, cliMsgId: opts.cliMsgId || msgId },
|
|
199
|
+
threadId,
|
|
200
|
+
type: Number(opts.type),
|
|
201
|
+
};
|
|
202
|
+
const result = await getApi().addReaction(reaction, dest);
|
|
196
203
|
output(result, program.opts().json, () => success(`Reacted with '${reaction}'`));
|
|
197
204
|
} catch (e) {
|
|
198
|
-
error(e.message);
|
|
205
|
+
error(`React failed: ${e.message}`);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
msg.command("listen")
|
|
210
|
+
.description("Listen for incoming messages (Ctrl+C to stop)")
|
|
211
|
+
.action(async () => {
|
|
212
|
+
try {
|
|
213
|
+
const api = getApi();
|
|
214
|
+
info("Listening for messages... Press Ctrl+C to stop.");
|
|
215
|
+
info("Note: Only one web listener per account. Browser Zalo will disconnect.");
|
|
216
|
+
|
|
217
|
+
api.listener.on("message", (msg) => {
|
|
218
|
+
const content = typeof msg.data.content === "string" ? msg.data.content : "[non-text]";
|
|
219
|
+
const data = {
|
|
220
|
+
msgId: msg.data.msgId,
|
|
221
|
+
cliMsgId: msg.data.cliMsgId,
|
|
222
|
+
threadId: msg.threadId,
|
|
223
|
+
type: msg.type,
|
|
224
|
+
isSelf: msg.isSelf,
|
|
225
|
+
content,
|
|
226
|
+
};
|
|
227
|
+
if (program.opts().json) {
|
|
228
|
+
console.log(JSON.stringify(data));
|
|
229
|
+
} else {
|
|
230
|
+
const dir = msg.isSelf ? "→" : "←";
|
|
231
|
+
console.log(` ${dir} [${msg.threadId}] ${content} (msgId: ${msg.data.msgId})`);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
api.listener.start();
|
|
236
|
+
|
|
237
|
+
// Keep alive until Ctrl+C
|
|
238
|
+
await new Promise((resolve) => {
|
|
239
|
+
process.on("SIGINT", () => {
|
|
240
|
+
api.listener.stop();
|
|
241
|
+
info("Listener stopped.");
|
|
242
|
+
resolve();
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
} catch (e) {
|
|
246
|
+
error(`Listen failed: ${e.message}`);
|
|
199
247
|
}
|
|
200
248
|
});
|
|
201
249
|
|
package/src/index.js
CHANGED
|
@@ -19,6 +19,8 @@ import { registerGroupCommands } from "./commands/group.js";
|
|
|
19
19
|
import { registerConvCommands } from "./commands/conv.js";
|
|
20
20
|
import { registerAccountCommands } from "./commands/account.js";
|
|
21
21
|
import { autoLogin } from "./core/zalo-client.js";
|
|
22
|
+
import { checkForUpdates, selfUpdate } from "./utils/update-check.js";
|
|
23
|
+
import { success, error } from "./utils/output.js";
|
|
22
24
|
|
|
23
25
|
const program = new Command();
|
|
24
26
|
|
|
@@ -34,10 +36,24 @@ program
|
|
|
34
36
|
}
|
|
35
37
|
// Auto-login before any command that needs it (skip for login/account commands)
|
|
36
38
|
const cmdName = thisCommand.args?.[0] || thisCommand.name();
|
|
37
|
-
const skipAutoLogin = ["login", "account", "help", "version"].includes(cmdName);
|
|
39
|
+
const skipAutoLogin = ["login", "account", "help", "version", "update"].includes(cmdName);
|
|
38
40
|
if (!skipAutoLogin) {
|
|
39
41
|
await autoLogin(program.opts().json);
|
|
40
42
|
}
|
|
43
|
+
// Non-blocking update check (skip for update command itself)
|
|
44
|
+
if (cmdName !== "update") {
|
|
45
|
+
checkForUpdates(pkg.version, program.opts().json);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Self-update command
|
|
50
|
+
program
|
|
51
|
+
.command("update")
|
|
52
|
+
.description("Update zalo-agent-cli to the latest version")
|
|
53
|
+
.action(() => {
|
|
54
|
+
const ok = selfUpdate();
|
|
55
|
+
if (ok) success(`Updated to latest version`);
|
|
56
|
+
else error("Update failed. Try manually: npm install -g zalo-agent-cli@latest");
|
|
41
57
|
});
|
|
42
58
|
|
|
43
59
|
// Register all command groups
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-blocking update check — warns user if a newer version is available on npm.
|
|
3
|
+
* Runs silently in background; never blocks CLI execution.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
7
|
+
import { warning } from "./output.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check npm registry for latest version, warn if outdated.
|
|
11
|
+
* @param {string} currentVersion - Current package version
|
|
12
|
+
* @param {boolean} jsonMode - Suppress output in JSON mode
|
|
13
|
+
*/
|
|
14
|
+
export function checkForUpdates(currentVersion, jsonMode) {
|
|
15
|
+
if (jsonMode) return;
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const latest = execSync("npm view zalo-agent-cli version", {
|
|
19
|
+
encoding: "utf8",
|
|
20
|
+
timeout: 5000,
|
|
21
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
22
|
+
}).trim();
|
|
23
|
+
|
|
24
|
+
if (latest && latest !== currentVersion) {
|
|
25
|
+
warning(`Update available: ${currentVersion} → ${latest}. Run: zalo-agent update`);
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
// Silent failure — network issues shouldn't block CLI usage
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Self-update by running npm install -g.
|
|
34
|
+
* @returns {boolean} success
|
|
35
|
+
*/
|
|
36
|
+
export function selfUpdate() {
|
|
37
|
+
try {
|
|
38
|
+
execSync("npm install -g zalo-agent-cli@latest", {
|
|
39
|
+
encoding: "utf8",
|
|
40
|
+
stdio: "inherit",
|
|
41
|
+
timeout: 60000,
|
|
42
|
+
});
|
|
43
|
+
return true;
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|