openzca 0.1.16 → 0.1.17
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 +3 -8
- package/dist/cli.js +98 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
# openzca
|
|
2
2
|
|
|
3
|
-
Free and open-source CLI for Zalo, built on [zca-js](https://github.com/
|
|
3
|
+
Free and open-source CLI for Zalo, built on [zca-js](https://github.com/RFS-ADRENO/zca-js). Command structure compatible with [zca-cli.dev/docs](https://zca-cli.dev/docs).
|
|
4
4
|
|
|
5
|
-
## Integrate with OpenClaw
|
|
6
|
-
|
|
7
|
-
Prompt:
|
|
8
|
-
```
|
|
9
|
-
help me to enable zalouser openclaw plugin. However, don't install zca cli follow their instruction, please use: npm install -g openzca@latest
|
|
10
|
-
```
|
|
5
|
+
## Integrate with OpenClaw OpenZalo plugin (including legacy `zalouser`)
|
|
11
6
|
|
|
12
7
|
|
|
13
8
|
## Install
|
|
@@ -296,7 +291,7 @@ Supervised mode notes:
|
|
|
296
291
|
|
|
297
292
|
## Multi-account profiles
|
|
298
293
|
|
|
299
|
-
Use `--profile <name>` or set `ZCA_PROFILE=<name>` to switch between accounts. Manage profiles with the `account` commands.
|
|
294
|
+
Use `--profile <name>` or set `OPENZCA_PROFILE=<name>` (or legacy `ZCA_PROFILE=<name>`) to switch between accounts. Manage profiles with the `account` commands.
|
|
300
295
|
|
|
301
296
|
Profile data is stored in `~/.openzca/` (override with `OPENZCA_HOME`):
|
|
302
297
|
|
package/dist/cli.js
CHANGED
|
@@ -164,7 +164,7 @@ async function removeProfile(name) {
|
|
|
164
164
|
}
|
|
165
165
|
async function resolveProfileName(flagProfile) {
|
|
166
166
|
const db = await ensureProfilesDb();
|
|
167
|
-
const picked = flagProfile && flagProfile.trim() || process.env.
|
|
167
|
+
const picked = flagProfile && flagProfile.trim() || (process.env.OPENZCA_PROFILE?.trim() || process.env.ZCA_PROFILE?.trim()) || db.defaultProfile || DEFAULT_PROFILE;
|
|
168
168
|
if (!db.profiles[picked]) {
|
|
169
169
|
if (picked === DEFAULT_PROFILE) {
|
|
170
170
|
await ensureProfile(DEFAULT_PROFILE);
|
|
@@ -765,7 +765,7 @@ async function currentProfile(_command) {
|
|
|
765
765
|
async function profileForLogin() {
|
|
766
766
|
const opts = program.opts();
|
|
767
767
|
const explicit = opts.profile?.trim();
|
|
768
|
-
const fromEnv = process.env.ZCA_PROFILE?.trim();
|
|
768
|
+
const fromEnv = process.env.OPENZCA_PROFILE?.trim() || process.env.ZCA_PROFILE?.trim();
|
|
769
769
|
if (explicit) {
|
|
770
770
|
await ensureProfile(explicit);
|
|
771
771
|
return explicit;
|
|
@@ -1653,7 +1653,7 @@ program.hook("preAction", (_parent, actionCommand) => {
|
|
|
1653
1653
|
argv: process.argv.slice(2),
|
|
1654
1654
|
cwd: process.cwd(),
|
|
1655
1655
|
profileFlag: getDebugOptions(actionCommand).profile ?? null,
|
|
1656
|
-
envProfile: process.env.ZCA_PROFILE ?? null
|
|
1656
|
+
envProfile: process.env.OPENZCA_PROFILE ?? process.env.ZCA_PROFILE ?? null
|
|
1657
1657
|
},
|
|
1658
1658
|
actionCommand
|
|
1659
1659
|
);
|
|
@@ -2082,6 +2082,32 @@ msg.command("undo <msgId> <cliMsgId> <threadId>").option("-g, --group", "Undo in
|
|
|
2082
2082
|
}
|
|
2083
2083
|
)
|
|
2084
2084
|
);
|
|
2085
|
+
msg.command("edit <msgId> <cliMsgId> <threadId> <message>").option("-g, --group", "Edit in group").description("Edit message (compatibility shim: recall old message then resend new text)").action(
|
|
2086
|
+
wrapAction(
|
|
2087
|
+
async (msgId, cliMsgId, threadId, message, opts, command) => {
|
|
2088
|
+
const { api } = await requireApi(command);
|
|
2089
|
+
const type = asThreadType(opts.group);
|
|
2090
|
+
const undoResponse = await api.undo(
|
|
2091
|
+
{
|
|
2092
|
+
msgId,
|
|
2093
|
+
cliMsgId
|
|
2094
|
+
},
|
|
2095
|
+
threadId,
|
|
2096
|
+
type
|
|
2097
|
+
);
|
|
2098
|
+
const sendResponse = await api.sendMessage(message, threadId, type);
|
|
2099
|
+
output(
|
|
2100
|
+
{
|
|
2101
|
+
mode: "undo+send",
|
|
2102
|
+
nativeEditSupported: false,
|
|
2103
|
+
undo: undoResponse,
|
|
2104
|
+
send: sendResponse
|
|
2105
|
+
},
|
|
2106
|
+
false
|
|
2107
|
+
);
|
|
2108
|
+
}
|
|
2109
|
+
)
|
|
2110
|
+
);
|
|
2085
2111
|
msg.command("upload <arg1> [arg2]").option("-u, --url <url>", "File URL (repeatable)", collectValues, []).option("-g, --group", "Upload in group").description("Upload and send file(s)").action(
|
|
2086
2112
|
wrapAction(
|
|
2087
2113
|
async (arg1, arg2, opts, command) => {
|
|
@@ -2164,6 +2190,75 @@ msg.command("recent <threadId>").option("-g, --group", "List recent messages for
|
|
|
2164
2190
|
}
|
|
2165
2191
|
)
|
|
2166
2192
|
);
|
|
2193
|
+
msg.command("pin <threadId>").option("-g, --group", "Pin group conversation").description("Pin conversation").action(
|
|
2194
|
+
wrapAction(async (threadId, opts, command) => {
|
|
2195
|
+
const { api } = await requireApi(command);
|
|
2196
|
+
const type = asThreadType(opts.group);
|
|
2197
|
+
const response = await api.setPinnedConversations(true, threadId, type);
|
|
2198
|
+
output(
|
|
2199
|
+
{
|
|
2200
|
+
threadId,
|
|
2201
|
+
threadType: type === ThreadType.Group ? "group" : "user",
|
|
2202
|
+
pinned: true,
|
|
2203
|
+
response
|
|
2204
|
+
},
|
|
2205
|
+
false
|
|
2206
|
+
);
|
|
2207
|
+
})
|
|
2208
|
+
);
|
|
2209
|
+
msg.command("unpin <threadId>").option("-g, --group", "Unpin group conversation").description("Unpin conversation").action(
|
|
2210
|
+
wrapAction(async (threadId, opts, command) => {
|
|
2211
|
+
const { api } = await requireApi(command);
|
|
2212
|
+
const type = asThreadType(opts.group);
|
|
2213
|
+
const response = await api.setPinnedConversations(false, threadId, type);
|
|
2214
|
+
output(
|
|
2215
|
+
{
|
|
2216
|
+
threadId,
|
|
2217
|
+
threadType: type === ThreadType.Group ? "group" : "user",
|
|
2218
|
+
pinned: false,
|
|
2219
|
+
response
|
|
2220
|
+
},
|
|
2221
|
+
false
|
|
2222
|
+
);
|
|
2223
|
+
})
|
|
2224
|
+
);
|
|
2225
|
+
msg.command("list-pins").option("-j, --json", "JSON output").description("List pinned conversations").action(
|
|
2226
|
+
wrapAction(async (opts, command) => {
|
|
2227
|
+
const { api } = await requireApi(command);
|
|
2228
|
+
const response = await api.getPinConversations();
|
|
2229
|
+
if (opts.json) {
|
|
2230
|
+
output(response, true);
|
|
2231
|
+
return;
|
|
2232
|
+
}
|
|
2233
|
+
output(
|
|
2234
|
+
response.conversations.map((threadId) => ({
|
|
2235
|
+
threadId,
|
|
2236
|
+
pinned: true
|
|
2237
|
+
})),
|
|
2238
|
+
false
|
|
2239
|
+
);
|
|
2240
|
+
})
|
|
2241
|
+
);
|
|
2242
|
+
msg.command("member-info <userId>").option("-j, --json", "JSON output").description("Get member/user profile info").action(
|
|
2243
|
+
wrapAction(async (userId, opts, command) => {
|
|
2244
|
+
const { api } = await requireApi(command);
|
|
2245
|
+
const response = await api.getUserInfo(userId);
|
|
2246
|
+
if (opts.json) {
|
|
2247
|
+
output(response, true);
|
|
2248
|
+
return;
|
|
2249
|
+
}
|
|
2250
|
+
const profiles = response.changed_profiles ?? {};
|
|
2251
|
+
const matchedProfile = profiles[userId] ?? profiles[`${userId}_0`] ?? Object.values(profiles)[0] ?? null;
|
|
2252
|
+
output(
|
|
2253
|
+
{
|
|
2254
|
+
userId,
|
|
2255
|
+
found: Boolean(matchedProfile),
|
|
2256
|
+
profile: matchedProfile
|
|
2257
|
+
},
|
|
2258
|
+
false
|
|
2259
|
+
);
|
|
2260
|
+
})
|
|
2261
|
+
);
|
|
2167
2262
|
var group = program.command("group").description("Group management");
|
|
2168
2263
|
group.command("list").option("-j, --json", "JSON output").description("List groups").action(
|
|
2169
2264
|
wrapAction(async (opts, command) => {
|